Merge "Moving some common functionality to IconLoaderLib" into sc-dev
This commit is contained in:
@@ -44,6 +44,7 @@ android_library {
|
||||
"src/com/android/launcher3/ResourceUtils.java",
|
||||
"src/com/android/launcher3/testing/TestProtocol.java",
|
||||
],
|
||||
resource_dirs: [ ],
|
||||
manifest: "tests/tapl/AndroidManifest.xml",
|
||||
platform_apis: true,
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ import androidx.annotation.Nullable;
|
||||
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.shortcuts.DeepShortcutView;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.launcher3.util.ActivityOptionsWrapper;
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.FastBitmapDrawable.newIcon;
|
||||
import static com.android.launcher3.uioverrides.QuickstepLauncher.GO_LOW_RAM_RECENTS_ENABLED;
|
||||
|
||||
import android.app.ActivityManager.TaskDescription;
|
||||
@@ -34,7 +33,6 @@ import android.view.accessibility.AccessibilityManager;
|
||||
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
@@ -137,11 +135,12 @@ public class TaskIconCache {
|
||||
// TODO: Load icon resource (b/143363444)
|
||||
Bitmap icon = TaskDescriptionCompat.getIcon(desc, key.userId);
|
||||
if (icon != null) {
|
||||
entry.icon = new FastBitmapDrawable(getBitmapInfo(
|
||||
/* isInstantApp */
|
||||
entry.icon = getBitmapInfo(
|
||||
new BitmapDrawable(mContext.getResources(), icon),
|
||||
key.userId,
|
||||
desc.getPrimaryColor(),
|
||||
false /* isInstantApp */));
|
||||
false /* isInstantApp */).newIcon(mContext);
|
||||
} else {
|
||||
activityInfo = PackageManagerWrapper.getInstance().getActivityInfo(
|
||||
key.getComponent(), key.userId);
|
||||
@@ -151,7 +150,7 @@ public class TaskIconCache {
|
||||
key.userId,
|
||||
desc.getPrimaryColor(),
|
||||
activityInfo.applicationInfo.isInstantApp());
|
||||
entry.icon = newIcon(mContext, bitmapInfo);
|
||||
entry.icon = bitmapInfo.newIcon(mContext);
|
||||
} else {
|
||||
entry.icon = getDefaultIcon(key.userId);
|
||||
}
|
||||
@@ -199,7 +198,7 @@ public class TaskIconCache {
|
||||
}
|
||||
mDefaultIcons.put(userId, info);
|
||||
}
|
||||
return new FastBitmapDrawable(info);
|
||||
return info.newIcon(mContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,26 +21,14 @@ import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A view which draws a drawable stretched to fit its size. Unlike ImageView, it avoids relayout
|
||||
* when the drawable changes.
|
||||
*/
|
||||
public class IconView extends View {
|
||||
|
||||
public interface OnScaleUpdateListener {
|
||||
public void onScaleUpdate(float scale);
|
||||
}
|
||||
|
||||
private Drawable mDrawable;
|
||||
|
||||
private ArrayList<OnScaleUpdateListener> mScaleListeners;
|
||||
|
||||
public IconView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
@@ -93,16 +81,6 @@ public class IconView extends View {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateDrawable(@NonNull Drawable drawable) {
|
||||
super.invalidateDrawable(drawable);
|
||||
if (drawable instanceof FastBitmapDrawable && mScaleListeners != null) {
|
||||
for (OnScaleUpdateListener listener : mScaleListeners) {
|
||||
listener.onScaleUpdate(((FastBitmapDrawable) drawable).getScale());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (mDrawable != null) {
|
||||
@@ -115,22 +93,6 @@ public class IconView extends View {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addUpdateScaleListener(OnScaleUpdateListener listener) {
|
||||
if (mScaleListeners == null) {
|
||||
mScaleListeners = new ArrayList<>();
|
||||
}
|
||||
mScaleListeners.add(listener);
|
||||
if (mDrawable instanceof FastBitmapDrawable) {
|
||||
listener.onScaleUpdate(((FastBitmapDrawable) mDrawable).getScale());
|
||||
}
|
||||
}
|
||||
|
||||
public void removeUpdateScaleListener(OnScaleUpdateListener listener) {
|
||||
if (mScaleListeners != null) {
|
||||
mScaleListeners.remove(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(float alpha) {
|
||||
super.setAlpha(alpha);
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
<attr name="workspaceKeyShadowColor" format="color" />
|
||||
<attr name="workspaceStatusBarScrim" format="reference" />
|
||||
<attr name="widgetsTheme" format="reference" />
|
||||
<attr name="loadingIconColor" format="color" />
|
||||
<attr name="iconOnlyShortcutColor" format="color" />
|
||||
<attr name="eduHalfSheetBGColor" format="color" />
|
||||
|
||||
@@ -44,7 +43,6 @@
|
||||
<attr name="folderTextColor" format="color" />
|
||||
<attr name="folderHintColor" format="color" />
|
||||
<attr name="workProfileOverlayTextColor" format="color" />
|
||||
<attr name="disabledIconAlpha" format="float" />
|
||||
|
||||
<!-- BubbleTextView specific attributes. -->
|
||||
<declare-styleable name="BubbleTextView">
|
||||
|
||||
@@ -87,8 +87,6 @@
|
||||
|
||||
<!-- Default packages -->
|
||||
<string name="wallpaper_picker_package" translatable="false"></string>
|
||||
<string name="calendar_component_name" translatable="false"></string>
|
||||
<string name="clock_component_name" translatable="false"></string>
|
||||
<string name="local_colors_extraction_class" translatable="false"></string>
|
||||
|
||||
<!-- Accessibility actions -->
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.FastBitmapDrawable.newIcon;
|
||||
import static com.android.launcher3.graphics.IconShape.getShape;
|
||||
import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
|
||||
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
|
||||
@@ -57,11 +56,12 @@ import com.android.launcher3.dragndrop.DraggableView;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.graphics.IconPalette;
|
||||
import com.android.launcher3.graphics.IconShape;
|
||||
import com.android.launcher3.graphics.PlaceHolderIconDrawable;
|
||||
import com.android.launcher3.graphics.PreloadIconDrawable;
|
||||
import com.android.launcher3.icons.DotRenderer;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
import com.android.launcher3.icons.PlaceHolderIconDrawable;
|
||||
import com.android.launcher3.icons.cache.HandlerRunnable;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
@@ -92,12 +92,9 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
private static final int[] STATE_PRESSED = new int[]{android.R.attr.state_pressed};
|
||||
private static final float HIGHLIGHT_SCALE = 1.16f;
|
||||
|
||||
|
||||
private final PointF mTranslationForReorderBounce = new PointF(0, 0);
|
||||
private final PointF mTranslationForReorderPreview = new PointF(0, 0);
|
||||
|
||||
private static final int ICON_UPDATE_ANIMATION_DURATION = 375;
|
||||
|
||||
private float mScaleForReorderBounce = 1f;
|
||||
|
||||
protected final Paint mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
@@ -335,7 +332,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
|
||||
@UiThread
|
||||
protected void applyIconAndLabel(ItemInfoWithIcon info) {
|
||||
FastBitmapDrawable iconDrawable = newIcon(getContext(), info);
|
||||
FastBitmapDrawable iconDrawable = info.newIcon(getContext());
|
||||
mDotParams.color = IconPalette.getMutedColor(info.bitmap.color, 0.54f);
|
||||
|
||||
setIcon(iconDrawable);
|
||||
@@ -933,7 +930,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
|
||||
private void resetIconScale() {
|
||||
if (mIcon instanceof FastBitmapDrawable) {
|
||||
((FastBitmapDrawable) mIcon).setScale(1f);
|
||||
((FastBitmapDrawable) mIcon).resetScale();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,357 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.ColorMatrix;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.Property;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.graphics.PlaceHolderIconDrawable;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
||||
|
||||
public class FastBitmapDrawable extends Drawable {
|
||||
|
||||
private static final float PRESSED_SCALE = 1.1f;
|
||||
|
||||
private static final float DISABLED_DESATURATION = 1f;
|
||||
private static final float DISABLED_BRIGHTNESS = 0.5f;
|
||||
|
||||
public static final int CLICK_FEEDBACK_DURATION = 200;
|
||||
|
||||
private static ColorFilter sDisabledFColorFilter;
|
||||
|
||||
protected final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG);
|
||||
protected Bitmap mBitmap;
|
||||
protected final int mIconColor;
|
||||
|
||||
@Nullable private ColorFilter mColorFilter;
|
||||
|
||||
private boolean mIsPressed;
|
||||
private boolean mIsDisabled;
|
||||
private float mDisabledAlpha = 1f;
|
||||
private float mRoundedCornersRadius = 0f;
|
||||
private final Path mClipPath = new Path();
|
||||
|
||||
// Animator and properties for the fast bitmap drawable's scale
|
||||
private static final Property<FastBitmapDrawable, Float> SCALE
|
||||
= new Property<FastBitmapDrawable, Float>(Float.TYPE, "scale") {
|
||||
@Override
|
||||
public Float get(FastBitmapDrawable fastBitmapDrawable) {
|
||||
return fastBitmapDrawable.mScale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(FastBitmapDrawable fastBitmapDrawable, Float value) {
|
||||
fastBitmapDrawable.mScale = value;
|
||||
fastBitmapDrawable.invalidateSelf();
|
||||
}
|
||||
};
|
||||
private ObjectAnimator mScaleAnimation;
|
||||
private float mScale = 1;
|
||||
|
||||
private int mAlpha = 255;
|
||||
|
||||
public FastBitmapDrawable(Bitmap b) {
|
||||
this(b, Color.TRANSPARENT);
|
||||
}
|
||||
|
||||
public FastBitmapDrawable(BitmapInfo info) {
|
||||
this(info.icon, info.color);
|
||||
}
|
||||
|
||||
protected FastBitmapDrawable(Bitmap b, int iconColor) {
|
||||
this(b, iconColor, false);
|
||||
}
|
||||
|
||||
protected FastBitmapDrawable(Bitmap b, int iconColor, boolean isDisabled) {
|
||||
mBitmap = b;
|
||||
mIconColor = iconColor;
|
||||
setFilterBitmap(true);
|
||||
setIsDisabled(isDisabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void draw(Canvas canvas) {
|
||||
if (mRoundedCornersRadius > 0) {
|
||||
float radius = mRoundedCornersRadius * mScale;
|
||||
mClipPath.reset();
|
||||
mClipPath.addRoundRect(0, 0, getIntrinsicWidth(), getIntrinsicHeight(),
|
||||
radius, radius, Path.Direction.CCW);
|
||||
canvas.clipPath(mClipPath);
|
||||
}
|
||||
if (mScale != 1f) {
|
||||
int count = canvas.save();
|
||||
Rect bounds = getBounds();
|
||||
canvas.scale(mScale, mScale, bounds.exactCenterX(), bounds.exactCenterY());
|
||||
drawInternal(canvas, bounds);
|
||||
canvas.restoreToCount(count);
|
||||
} else {
|
||||
drawInternal(canvas, getBounds());
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawInternal(Canvas canvas, Rect bounds) {
|
||||
canvas.drawBitmap(mBitmap, null, bounds, mPaint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter cf) {
|
||||
mColorFilter = cf;
|
||||
updateFilter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.TRANSLUCENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
if (mAlpha != alpha) {
|
||||
mAlpha = alpha;
|
||||
mPaint.setAlpha(alpha);
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFilterBitmap(boolean filterBitmap) {
|
||||
mPaint.setFilterBitmap(filterBitmap);
|
||||
mPaint.setAntiAlias(filterBitmap);
|
||||
}
|
||||
|
||||
public int getAlpha() {
|
||||
return mAlpha;
|
||||
}
|
||||
|
||||
public void setScale(float scale) {
|
||||
if (mScaleAnimation != null) {
|
||||
mScaleAnimation.cancel();
|
||||
mScaleAnimation = null;
|
||||
}
|
||||
mScale = scale;
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
public float getAnimatedScale() {
|
||||
return mScaleAnimation == null ? 1 : mScale;
|
||||
}
|
||||
|
||||
public float getScale() {
|
||||
return mScale;
|
||||
}
|
||||
|
||||
public void setRoundedCornersRadius(float radius) {
|
||||
mRoundedCornersRadius = radius;
|
||||
}
|
||||
|
||||
public float getRoundedCornersRadius() {
|
||||
return mRoundedCornersRadius;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return mBitmap.getWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return mBitmap.getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimumWidth() {
|
||||
return getBounds().width();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimumHeight() {
|
||||
return getBounds().height();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStateful() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorFilter getColorFilter() {
|
||||
return mPaint.getColorFilter();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onStateChange(int[] state) {
|
||||
boolean isPressed = false;
|
||||
for (int s : state) {
|
||||
if (s == android.R.attr.state_pressed) {
|
||||
isPressed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mIsPressed != isPressed) {
|
||||
mIsPressed = isPressed;
|
||||
|
||||
if (mScaleAnimation != null) {
|
||||
mScaleAnimation.cancel();
|
||||
mScaleAnimation = null;
|
||||
}
|
||||
|
||||
if (mIsPressed) {
|
||||
// Animate when going to pressed state
|
||||
mScaleAnimation = ObjectAnimator.ofFloat(this, SCALE, PRESSED_SCALE);
|
||||
mScaleAnimation.setDuration(CLICK_FEEDBACK_DURATION);
|
||||
mScaleAnimation.setInterpolator(ACCEL);
|
||||
mScaleAnimation.start();
|
||||
} else {
|
||||
if (isVisible()) {
|
||||
mScaleAnimation = ObjectAnimator.ofFloat(this, SCALE, 1f);
|
||||
mScaleAnimation.setDuration(CLICK_FEEDBACK_DURATION);
|
||||
mScaleAnimation.setInterpolator(DEACCEL);
|
||||
mScaleAnimation.start();
|
||||
} else {
|
||||
mScale = 1f;
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setIsDisabled(boolean isDisabled) {
|
||||
if (mIsDisabled != isDisabled) {
|
||||
mIsDisabled = isDisabled;
|
||||
updateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isDisabled() {
|
||||
return mIsDisabled;
|
||||
}
|
||||
|
||||
private ColorFilter getDisabledColorFilter() {
|
||||
if (sDisabledFColorFilter == null) {
|
||||
ColorMatrix tempBrightnessMatrix = new ColorMatrix();
|
||||
ColorMatrix tempFilterMatrix = new ColorMatrix();
|
||||
|
||||
tempFilterMatrix.setSaturation(1f - DISABLED_DESATURATION);
|
||||
float scale = 1 - DISABLED_BRIGHTNESS;
|
||||
int brightnessI = (int) (255 * DISABLED_BRIGHTNESS);
|
||||
float[] mat = tempBrightnessMatrix.getArray();
|
||||
mat[0] = scale;
|
||||
mat[6] = scale;
|
||||
mat[12] = scale;
|
||||
mat[4] = brightnessI;
|
||||
mat[9] = brightnessI;
|
||||
mat[14] = brightnessI;
|
||||
mat[18] = mDisabledAlpha;
|
||||
tempFilterMatrix.preConcat(tempBrightnessMatrix);
|
||||
sDisabledFColorFilter = new ColorMatrixColorFilter(tempFilterMatrix);
|
||||
}
|
||||
return sDisabledFColorFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the paint to reflect the current brightness and saturation.
|
||||
*/
|
||||
protected void updateFilter() {
|
||||
mPaint.setColorFilter(mIsDisabled ? getDisabledColorFilter() : mColorFilter);
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstantState getConstantState() {
|
||||
return new FastBitmapConstantState(mBitmap, mIconColor, mIsDisabled);
|
||||
}
|
||||
|
||||
protected static class FastBitmapConstantState extends ConstantState {
|
||||
protected final Bitmap mBitmap;
|
||||
protected final int mIconColor;
|
||||
protected final boolean mIsDisabled;
|
||||
|
||||
public FastBitmapConstantState(Bitmap bitmap, int color, boolean isDisabled) {
|
||||
mBitmap = bitmap;
|
||||
mIconColor = color;
|
||||
mIsDisabled = isDisabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FastBitmapDrawable newDrawable() {
|
||||
return new FastBitmapDrawable(mBitmap, mIconColor, mIsDisabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChangingConfigurations() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface to be implemented by custom {@link BitmapInfo} to handle drawable construction
|
||||
*/
|
||||
public interface Factory {
|
||||
|
||||
/**
|
||||
* Called to create a new drawable
|
||||
*/
|
||||
FastBitmapDrawable newDrawable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a FastBitmapDrawable with the icon.
|
||||
*/
|
||||
public static FastBitmapDrawable newIcon(Context context, ItemInfoWithIcon info) {
|
||||
FastBitmapDrawable drawable = newIcon(context, info.bitmap);
|
||||
drawable.setIsDisabled(info.isDisabled());
|
||||
return drawable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a drawable for the provided BitmapInfo
|
||||
*/
|
||||
public static FastBitmapDrawable newIcon(Context context, BitmapInfo info) {
|
||||
final FastBitmapDrawable drawable;
|
||||
if (info instanceof Factory) {
|
||||
drawable = ((Factory) info).newDrawable();
|
||||
} else if (info.isLowRes()) {
|
||||
drawable = new PlaceHolderIconDrawable(info, context);
|
||||
} else {
|
||||
drawable = new FastBitmapDrawable(info);
|
||||
}
|
||||
drawable.mDisabledAlpha = Themes.getFloat(context, R.attr.disabledIconAlpha, 1f);
|
||||
return drawable;
|
||||
}
|
||||
}
|
||||
@@ -69,6 +69,7 @@ import androidx.core.os.BuildCompat;
|
||||
import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
|
||||
import com.android.launcher3.graphics.GridCustomizationsProvider;
|
||||
import com.android.launcher3.graphics.TintedDrawableSpan;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.icons.IconProvider;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
import com.android.launcher3.icons.ShortcutCachingLogic;
|
||||
|
||||
@@ -37,6 +37,7 @@ import android.util.Pair;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.icons.GraphicsUtils;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
|
||||
@@ -83,6 +83,7 @@ import com.android.launcher3.graphics.DragPreviewProvider;
|
||||
import com.android.launcher3.graphics.PreloadIconDrawable;
|
||||
import com.android.launcher3.graphics.WorkspaceDragScrim;
|
||||
import com.android.launcher3.icons.BitmapRenderer;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.logger.LauncherAtom;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
|
||||
|
||||
@@ -44,7 +44,6 @@ import androidx.dynamicanimation.animation.FloatPropertyCompat;
|
||||
import androidx.dynamicanimation.animation.SpringAnimation;
|
||||
import androidx.dynamicanimation.animation.SpringForce;
|
||||
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
import com.android.launcher3.FirstFrameAnimatorHelper;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
@@ -52,6 +51,7 @@ import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
|
||||
@@ -28,7 +28,6 @@ import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Process;
|
||||
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAnimUtils;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
@@ -78,7 +77,7 @@ class PinShortcutRequestActivityInfo extends ShortcutConfigActivityInfo {
|
||||
Drawable d = mContext.getSystemService(LauncherApps.class)
|
||||
.getShortcutIconDrawable(mInfo, LauncherAppState.getIDP(mContext).fillResIconDpi);
|
||||
if (d == null) {
|
||||
d = new FastBitmapDrawable(cache.getDefaultIcon(Process.myUserHandle()));
|
||||
d = cache.getDefaultIcon(Process.myUserHandle()).newIcon(mContext);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
@@ -483,7 +483,7 @@ public class FolderPagedView extends PagedView<PageIndicatorDots> {
|
||||
icon.verifyHighRes();
|
||||
// Set the callback back to the actual icon, in case
|
||||
// it was captured by the FolderIcon
|
||||
Drawable d = icon.getCompoundDrawables()[1];
|
||||
Drawable d = icon.getIcon();
|
||||
if (d != null) {
|
||||
d.setCallback(icon);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.launcher3.folder;
|
||||
|
||||
import static com.android.launcher3.FastBitmapDrawable.newIcon;
|
||||
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.ENTER_INDEX;
|
||||
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.EXIT_INDEX;
|
||||
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
|
||||
@@ -33,10 +32,10 @@ import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.FloatProperty;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.graphics.PreloadIconDrawable;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
@@ -113,7 +112,7 @@ public class PreviewItemManager {
|
||||
}
|
||||
|
||||
Drawable prepareCreateAnimation(final View destView) {
|
||||
Drawable animateDrawable = ((TextView) destView).getCompoundDrawables()[1];
|
||||
Drawable animateDrawable = ((BubbleTextView) destView).getIcon();
|
||||
computePreviewDrawingParams(animateDrawable.getIntrinsicWidth(),
|
||||
destView.getMeasuredWidth());
|
||||
mReferenceDrawable = animateDrawable;
|
||||
@@ -401,7 +400,7 @@ public class PreviewItemManager {
|
||||
drawable.setLevel(item.getProgressLevel());
|
||||
p.drawable = drawable;
|
||||
} else {
|
||||
p.drawable = newIcon(mContext, item);
|
||||
p.drawable = item.newIcon(mContext);
|
||||
}
|
||||
p.drawable.setBounds(0, 0, mIconSize, mIconSize);
|
||||
p.item = item;
|
||||
|
||||
@@ -30,13 +30,13 @@ import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.dragndrop.AppWidgetHostViewDrawable;
|
||||
import com.android.launcher3.dragndrop.DraggableView;
|
||||
import com.android.launcher3.icons.BitmapRenderer;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.util.SafeCloseable;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetHostView;
|
||||
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.graphics;
|
||||
|
||||
import static androidx.core.graphics.ColorUtils.compositeColors;
|
||||
|
||||
import static com.android.launcher3.graphics.IconShape.getShapePath;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
||||
/**
|
||||
* Subclass which draws a placeholder icon when the actual icon is not yet loaded
|
||||
*/
|
||||
public class PlaceHolderIconDrawable extends FastBitmapDrawable {
|
||||
|
||||
// Path in [0, 100] bounds.
|
||||
private final Path mProgressPath;
|
||||
|
||||
public PlaceHolderIconDrawable(BitmapInfo info, Context context) {
|
||||
super(info);
|
||||
|
||||
mProgressPath = getShapePath();
|
||||
mPaint.setColor(compositeColors(
|
||||
Themes.getAttrColor(context, R.attr.loadingIconColor), info.color));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawInternal(Canvas canvas, Rect bounds) {
|
||||
int saveCount = canvas.save();
|
||||
canvas.translate(bounds.left, bounds.top);
|
||||
canvas.scale(bounds.width() / 100f, bounds.height() / 100f);
|
||||
canvas.drawPath(mProgressPath, mPaint);
|
||||
canvas.restoreToCount(saveCount);
|
||||
}
|
||||
|
||||
/** Updates this placeholder to {@code newIcon} with animation. */
|
||||
public void animateIconUpdate(Drawable newIcon) {
|
||||
int placeholderColor = mPaint.getColor();
|
||||
int originalAlpha = Color.alpha(placeholderColor);
|
||||
|
||||
ValueAnimator iconUpdateAnimation = ValueAnimator.ofInt(originalAlpha, 0);
|
||||
iconUpdateAnimation.setDuration(375);
|
||||
iconUpdateAnimation.addUpdateListener(valueAnimator -> {
|
||||
int newAlpha = (int) valueAnimator.getAnimatedValue();
|
||||
int newColor = ColorUtils.setAlphaComponent(placeholderColor, newAlpha);
|
||||
|
||||
newIcon.setColorFilter(new PorterDuffColorFilter(newColor, PorterDuff.Mode.SRC_ATOP));
|
||||
});
|
||||
iconUpdateAnimation.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
newIcon.setColorFilter(null);
|
||||
}
|
||||
});
|
||||
iconUpdateAnimation.start();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -37,8 +37,8 @@ import android.util.Property;
|
||||
import android.util.SparseArray;
|
||||
import android.view.ContextThemeWrapper;
|
||||
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
||||
|
||||
@@ -1,328 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.icons;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.AdaptiveIconDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Process;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Wrapper over {@link AdaptiveIconDrawable} to intercept icon flattening logic for dynamic
|
||||
* clock icons
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class ClockDrawableWrapper extends AdaptiveIconDrawable implements BitmapInfo.Extender {
|
||||
|
||||
private static final String TAG = "ClockDrawableWrapper";
|
||||
|
||||
private static final boolean DISABLE_SECONDS = true;
|
||||
|
||||
// Time after which the clock icon should check for an update. The actual invalidate
|
||||
// will only happen in case of any change.
|
||||
public static final long TICK_MS = DISABLE_SECONDS ? TimeUnit.MINUTES.toMillis(1) : 200L;
|
||||
|
||||
private static final String LAUNCHER_PACKAGE = "com.android.launcher3";
|
||||
private static final String ROUND_ICON_METADATA_KEY = LAUNCHER_PACKAGE
|
||||
+ ".LEVEL_PER_TICK_ICON_ROUND";
|
||||
private static final String HOUR_INDEX_METADATA_KEY = LAUNCHER_PACKAGE + ".HOUR_LAYER_INDEX";
|
||||
private static final String MINUTE_INDEX_METADATA_KEY = LAUNCHER_PACKAGE
|
||||
+ ".MINUTE_LAYER_INDEX";
|
||||
private static final String SECOND_INDEX_METADATA_KEY = LAUNCHER_PACKAGE
|
||||
+ ".SECOND_LAYER_INDEX";
|
||||
private static final String DEFAULT_HOUR_METADATA_KEY = LAUNCHER_PACKAGE
|
||||
+ ".DEFAULT_HOUR";
|
||||
private static final String DEFAULT_MINUTE_METADATA_KEY = LAUNCHER_PACKAGE
|
||||
+ ".DEFAULT_MINUTE";
|
||||
private static final String DEFAULT_SECOND_METADATA_KEY = LAUNCHER_PACKAGE
|
||||
+ ".DEFAULT_SECOND";
|
||||
|
||||
/* Number of levels to jump per second for the second hand */
|
||||
private static final int LEVELS_PER_SECOND = 10;
|
||||
|
||||
public static final int INVALID_VALUE = -1;
|
||||
|
||||
private final AnimationInfo mAnimationInfo = new AnimationInfo();
|
||||
private int mTargetSdkVersion;
|
||||
|
||||
public ClockDrawableWrapper(AdaptiveIconDrawable base) {
|
||||
super(base.getBackground(), base.getForeground());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and returns the wrapper from the provided package, or returns null
|
||||
* if it is unable to load.
|
||||
*/
|
||||
public static ClockDrawableWrapper forPackage(Context context, String pkg, int iconDpi) {
|
||||
try {
|
||||
PackageManager pm = context.getPackageManager();
|
||||
ApplicationInfo appInfo = pm.getApplicationInfo(pkg,
|
||||
PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.GET_META_DATA);
|
||||
final Bundle metadata = appInfo.metaData;
|
||||
if (metadata == null) {
|
||||
return null;
|
||||
}
|
||||
int drawableId = metadata.getInt(ROUND_ICON_METADATA_KEY, 0);
|
||||
if (drawableId == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Drawable drawable = pm.getResourcesForApplication(appInfo).getDrawableForDensity(
|
||||
drawableId, iconDpi).mutate();
|
||||
if (!(drawable instanceof AdaptiveIconDrawable)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ClockDrawableWrapper wrapper =
|
||||
new ClockDrawableWrapper((AdaptiveIconDrawable) drawable);
|
||||
wrapper.mTargetSdkVersion = appInfo.targetSdkVersion;
|
||||
AnimationInfo info = wrapper.mAnimationInfo;
|
||||
|
||||
info.baseDrawableState = drawable.getConstantState();
|
||||
|
||||
info.hourLayerIndex = metadata.getInt(HOUR_INDEX_METADATA_KEY, INVALID_VALUE);
|
||||
info.minuteLayerIndex = metadata.getInt(MINUTE_INDEX_METADATA_KEY, INVALID_VALUE);
|
||||
info.secondLayerIndex = metadata.getInt(SECOND_INDEX_METADATA_KEY, INVALID_VALUE);
|
||||
|
||||
info.defaultHour = metadata.getInt(DEFAULT_HOUR_METADATA_KEY, 0);
|
||||
info.defaultMinute = metadata.getInt(DEFAULT_MINUTE_METADATA_KEY, 0);
|
||||
info.defaultSecond = metadata.getInt(DEFAULT_SECOND_METADATA_KEY, 0);
|
||||
|
||||
LayerDrawable foreground = (LayerDrawable) wrapper.getForeground();
|
||||
int layerCount = foreground.getNumberOfLayers();
|
||||
if (info.hourLayerIndex < 0 || info.hourLayerIndex >= layerCount) {
|
||||
info.hourLayerIndex = INVALID_VALUE;
|
||||
}
|
||||
if (info.minuteLayerIndex < 0 || info.minuteLayerIndex >= layerCount) {
|
||||
info.minuteLayerIndex = INVALID_VALUE;
|
||||
}
|
||||
if (info.secondLayerIndex < 0 || info.secondLayerIndex >= layerCount) {
|
||||
info.secondLayerIndex = INVALID_VALUE;
|
||||
} else if (DISABLE_SECONDS) {
|
||||
foreground.setDrawable(info.secondLayerIndex, null);
|
||||
info.secondLayerIndex = INVALID_VALUE;
|
||||
}
|
||||
return wrapper;
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "Unable to load clock drawable info", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BitmapInfo getExtendedInfo(Bitmap bitmap, int color, BaseIconFactory iconFactory) {
|
||||
iconFactory.disableColorExtraction();
|
||||
float [] scale = new float[1];
|
||||
AdaptiveIconDrawable background = new AdaptiveIconDrawable(
|
||||
getBackground().getConstantState().newDrawable(), null);
|
||||
BitmapInfo bitmapInfo = iconFactory.createBadgedIconBitmap(background,
|
||||
Process.myUserHandle(), mTargetSdkVersion, false, scale);
|
||||
|
||||
return new ClockBitmapInfo(bitmap, color, scale[0], mAnimationInfo, bitmapInfo.icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareToDrawOnUi() {
|
||||
mAnimationInfo.applyTime(Calendar.getInstance(), (LayerDrawable) getForeground());
|
||||
}
|
||||
|
||||
private static class AnimationInfo {
|
||||
|
||||
public ConstantState baseDrawableState;
|
||||
|
||||
public int hourLayerIndex;
|
||||
public int minuteLayerIndex;
|
||||
public int secondLayerIndex;
|
||||
public int defaultHour;
|
||||
public int defaultMinute;
|
||||
public int defaultSecond;
|
||||
|
||||
boolean applyTime(Calendar time, LayerDrawable foregroundDrawable) {
|
||||
time.setTimeInMillis(System.currentTimeMillis());
|
||||
|
||||
// We need to rotate by the difference from the default time if one is specified.
|
||||
int convertedHour = (time.get(Calendar.HOUR) + (12 - defaultHour)) % 12;
|
||||
int convertedMinute = (time.get(Calendar.MINUTE) + (60 - defaultMinute)) % 60;
|
||||
int convertedSecond = (time.get(Calendar.SECOND) + (60 - defaultSecond)) % 60;
|
||||
|
||||
boolean invalidate = false;
|
||||
if (hourLayerIndex != INVALID_VALUE) {
|
||||
final Drawable hour = foregroundDrawable.getDrawable(hourLayerIndex);
|
||||
if (hour.setLevel(convertedHour * 60 + time.get(Calendar.MINUTE))) {
|
||||
invalidate = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (minuteLayerIndex != INVALID_VALUE) {
|
||||
final Drawable minute = foregroundDrawable.getDrawable(minuteLayerIndex);
|
||||
if (minute.setLevel(time.get(Calendar.HOUR) * 60 + convertedMinute)) {
|
||||
invalidate = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (secondLayerIndex != INVALID_VALUE) {
|
||||
final Drawable second = foregroundDrawable.getDrawable(secondLayerIndex);
|
||||
if (second.setLevel(convertedSecond * LEVELS_PER_SECOND)) {
|
||||
invalidate = true;
|
||||
}
|
||||
}
|
||||
|
||||
return invalidate;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ClockBitmapInfo extends BitmapInfo implements FastBitmapDrawable.Factory {
|
||||
|
||||
public final float scale;
|
||||
public final int offset;
|
||||
public final AnimationInfo animInfo;
|
||||
public final Bitmap mFlattenedBackground;
|
||||
|
||||
ClockBitmapInfo(Bitmap icon, int color, float scale, AnimationInfo animInfo,
|
||||
Bitmap background) {
|
||||
super(icon, color);
|
||||
this.scale = scale;
|
||||
this.animInfo = animInfo;
|
||||
this.offset = (int) Math.ceil(ShadowGenerator.BLUR_FACTOR * icon.getWidth());
|
||||
this.mFlattenedBackground = background;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FastBitmapDrawable newDrawable() {
|
||||
return new ClockIconDrawable(this);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ClockIconDrawable extends FastBitmapDrawable implements Runnable {
|
||||
|
||||
private final Calendar mTime = Calendar.getInstance();
|
||||
|
||||
private final ClockBitmapInfo mInfo;
|
||||
|
||||
private final AdaptiveIconDrawable mFullDrawable;
|
||||
private final LayerDrawable mForeground;
|
||||
|
||||
ClockIconDrawable(ClockBitmapInfo clockInfo) {
|
||||
super(clockInfo);
|
||||
|
||||
mInfo = clockInfo;
|
||||
|
||||
mFullDrawable = (AdaptiveIconDrawable) mInfo.animInfo.baseDrawableState.newDrawable();
|
||||
mForeground = (LayerDrawable) mFullDrawable.getForeground();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBoundsChange(Rect bounds) {
|
||||
super.onBoundsChange(bounds);
|
||||
mFullDrawable.setBounds(bounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawInternal(Canvas canvas, Rect bounds) {
|
||||
if (mInfo == null) {
|
||||
super.drawInternal(canvas, bounds);
|
||||
return;
|
||||
}
|
||||
// draw the background that is already flattened to a bitmap
|
||||
canvas.drawBitmap(mInfo.mFlattenedBackground, null, bounds, mPaint);
|
||||
|
||||
// prepare and draw the foreground
|
||||
mInfo.animInfo.applyTime(mTime, mForeground);
|
||||
|
||||
canvas.scale(mInfo.scale, mInfo.scale,
|
||||
bounds.exactCenterX() + mInfo.offset, bounds.exactCenterY() + mInfo.offset);
|
||||
canvas.clipPath(mFullDrawable.getIconMask());
|
||||
mForeground.draw(canvas);
|
||||
|
||||
reschedule();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateFilter() {
|
||||
super.updateFilter();
|
||||
mFullDrawable.setColorFilter(mPaint.getColorFilter());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (mInfo.animInfo.applyTime(mTime, mForeground)) {
|
||||
invalidateSelf();
|
||||
} else {
|
||||
reschedule();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setVisible(boolean visible, boolean restart) {
|
||||
boolean result = super.setVisible(visible, restart);
|
||||
if (visible) {
|
||||
reschedule();
|
||||
} else {
|
||||
unscheduleSelf(this);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void reschedule() {
|
||||
if (!isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
unscheduleSelf(this);
|
||||
final long upTime = SystemClock.uptimeMillis();
|
||||
final long step = TICK_MS; /* tick every 200 ms */
|
||||
scheduleSelf(this, upTime - ((upTime % step)) + step);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstantState getConstantState() {
|
||||
return new ClockConstantState(mInfo, isDisabled());
|
||||
}
|
||||
|
||||
private static class ClockConstantState extends FastBitmapConstantState {
|
||||
|
||||
private final ClockBitmapInfo mInfo;
|
||||
|
||||
ClockConstantState(ClockBitmapInfo info, boolean isDisabled) {
|
||||
super(info.icon, info.color, isDisabled);
|
||||
mInfo = info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FastBitmapDrawable newDrawable() {
|
||||
ClockIconDrawable drawable = new ClockIconDrawable(mInfo);
|
||||
drawable.setIsDisabled(mIsDisabled);
|
||||
return drawable;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,251 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher3.icons;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.LauncherActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.icons.BitmapInfo.Extender;
|
||||
import com.android.launcher3.pm.UserCache;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.launcher3.util.SafeCloseable;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* Class to handle icon loading from different packages
|
||||
*/
|
||||
public class IconProvider {
|
||||
|
||||
private static final String TAG = "IconProvider";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final String ICON_METADATA_KEY_PREFIX = ".dynamic_icons";
|
||||
|
||||
private static final String SYSTEM_STATE_SEPARATOR = " ";
|
||||
|
||||
// Default value returned if there are problems getting resources.
|
||||
private static final int NO_ID = 0;
|
||||
|
||||
private static final BiFunction<LauncherActivityInfo, Integer, Drawable> LAI_LOADER =
|
||||
LauncherActivityInfo::getIcon;
|
||||
|
||||
private static final BiFunction<ActivityInfo, PackageManager, Drawable> AI_LOADER =
|
||||
ActivityInfo::loadUnbadgedIcon;
|
||||
|
||||
|
||||
private final Context mContext;
|
||||
private final ComponentName mCalendar;
|
||||
private final ComponentName mClock;
|
||||
|
||||
public IconProvider(Context context) {
|
||||
mContext = context;
|
||||
mCalendar = parseComponentOrNull(context, R.string.calendar_component_name);
|
||||
mClock = parseComponentOrNull(context, R.string.clock_component_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds any modification to the provided systemState for dynamic icons. This system state
|
||||
* is used by caches to check for icon invalidation.
|
||||
*/
|
||||
public String getSystemStateForPackage(String systemState, String packageName) {
|
||||
if (mCalendar != null && mCalendar.getPackageName().equals(packageName)) {
|
||||
return systemState + SYSTEM_STATE_SEPARATOR + getDay();
|
||||
} else {
|
||||
return systemState;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the icon for the provided LauncherActivityInfo such that it can be drawn directly
|
||||
* on the UI
|
||||
*/
|
||||
public Drawable getIconForUI(LauncherActivityInfo info, int iconDpi) {
|
||||
Drawable icon = getIcon(info, iconDpi);
|
||||
if (icon instanceof BitmapInfo.Extender) {
|
||||
((Extender) icon).prepareToDrawOnUi();
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the icon for the provided LauncherActivityInfo
|
||||
*/
|
||||
public Drawable getIcon(LauncherActivityInfo info, int iconDpi) {
|
||||
return getIcon(info.getApplicationInfo().packageName, info.getUser(),
|
||||
info, iconDpi, LAI_LOADER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the icon for the provided activity info
|
||||
*/
|
||||
public Drawable getIcon(ActivityInfo info, UserHandle user) {
|
||||
return getIcon(info.applicationInfo.packageName, user, info, mContext.getPackageManager(),
|
||||
AI_LOADER);
|
||||
}
|
||||
|
||||
private <T, P> Drawable getIcon(String packageName, UserHandle user, T obj, P param,
|
||||
BiFunction<T, P, Drawable> loader) {
|
||||
Drawable icon = null;
|
||||
if (mCalendar != null && mCalendar.getPackageName().equals(packageName)) {
|
||||
icon = loadCalendarDrawable(0);
|
||||
} else if (mClock != null
|
||||
&& mClock.getPackageName().equals(packageName)
|
||||
&& Process.myUserHandle().equals(user)) {
|
||||
icon = loadClockDrawable(0);
|
||||
}
|
||||
return icon == null ? loader.apply(obj, param) : icon;
|
||||
}
|
||||
|
||||
private Drawable loadCalendarDrawable(int iconDpi) {
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
try {
|
||||
final Bundle metadata = pm.getActivityInfo(
|
||||
mCalendar,
|
||||
PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_META_DATA)
|
||||
.metaData;
|
||||
final Resources resources = pm.getResourcesForApplication(mCalendar.getPackageName());
|
||||
final int id = getDynamicIconId(metadata, resources);
|
||||
if (id != NO_ID) {
|
||||
if (DEBUG) Log.d(TAG, "Got icon #" + id);
|
||||
return resources.getDrawableForDensity(id, iconDpi, null /* theme */);
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Could not get activityinfo or resources for package: "
|
||||
+ mCalendar.getPackageName());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Drawable loadClockDrawable(int iconDpi) {
|
||||
return ClockDrawableWrapper.forPackage(mContext, mClock.getPackageName(), iconDpi);
|
||||
}
|
||||
|
||||
protected boolean isClockIcon(ComponentKey key) {
|
||||
return mClock != null && mClock.equals(key.componentName)
|
||||
&& Process.myUserHandle().equals(key.user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param metadata metadata of the default activity of Calendar
|
||||
* @param resources from the Calendar package
|
||||
* @return the resource id for today's Calendar icon; 0 if resources cannot be found.
|
||||
*/
|
||||
private int getDynamicIconId(Bundle metadata, Resources resources) {
|
||||
if (metadata == null) {
|
||||
return NO_ID;
|
||||
}
|
||||
String key = mCalendar.getPackageName() + ICON_METADATA_KEY_PREFIX;
|
||||
final int arrayId = metadata.getInt(key, NO_ID);
|
||||
if (arrayId == NO_ID) {
|
||||
return NO_ID;
|
||||
}
|
||||
try {
|
||||
return resources.obtainTypedArray(arrayId).getResourceId(getDay(), NO_ID);
|
||||
} catch (Resources.NotFoundException e) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "package defines '" + key + "' but corresponding array not found");
|
||||
}
|
||||
return NO_ID;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Today's day of the month, zero-indexed.
|
||||
*/
|
||||
private int getDay() {
|
||||
return Calendar.getInstance().get(Calendar.DAY_OF_MONTH) - 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers a callback to listen for calendar icon changes.
|
||||
* The callback receives the packageName for the calendar icon
|
||||
*/
|
||||
public static SafeCloseable registerIconChangeListener(Context context,
|
||||
BiConsumer<String, UserHandle> callback, Handler handler) {
|
||||
ComponentName calendar = parseComponentOrNull(context, R.string.calendar_component_name);
|
||||
ComponentName clock = parseComponentOrNull(context, R.string.clock_component_name);
|
||||
|
||||
if (calendar == null && clock == null) {
|
||||
return () -> { };
|
||||
}
|
||||
|
||||
BroadcastReceiver receiver = new DateTimeChangeReceiver(callback);
|
||||
final IntentFilter filter = new IntentFilter(Intent.ACTION_TIMEZONE_CHANGED);
|
||||
if (calendar != null) {
|
||||
filter.addAction(Intent.ACTION_TIME_CHANGED);
|
||||
filter.addAction(Intent.ACTION_DATE_CHANGED);
|
||||
}
|
||||
context.registerReceiver(receiver, filter, null, handler);
|
||||
|
||||
return () -> context.unregisterReceiver(receiver);
|
||||
}
|
||||
|
||||
private static class DateTimeChangeReceiver extends BroadcastReceiver {
|
||||
|
||||
private final BiConsumer<String, UserHandle> mCallback;
|
||||
|
||||
DateTimeChangeReceiver(BiConsumer<String, UserHandle> callback) {
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
|
||||
ComponentName clock = parseComponentOrNull(context, R.string.clock_component_name);
|
||||
if (clock != null) {
|
||||
mCallback.accept(clock.getPackageName(), Process.myUserHandle());
|
||||
}
|
||||
}
|
||||
|
||||
ComponentName calendar =
|
||||
parseComponentOrNull(context, R.string.calendar_component_name);
|
||||
if (calendar != null) {
|
||||
for (UserHandle user : UserCache.INSTANCE.get(context).getUserProfiles()) {
|
||||
mCallback.accept(calendar.getPackageName(), user);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static ComponentName parseComponentOrNull(Context context, int resId) {
|
||||
String cn = context.getString(resId);
|
||||
return TextUtils.isEmpty(cn) ? null : ComponentName.unflattenFromString(cn);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import android.content.Intent;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.pm.PackageInstallInfo;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
|
||||
@@ -216,4 +217,14 @@ public abstract class ItemInfoWithIcon extends ItemInfo {
|
||||
* @return a copy of this
|
||||
*/
|
||||
public abstract ItemInfoWithIcon clone();
|
||||
|
||||
|
||||
/**
|
||||
* Returns a FastBitmapDrawable with the icon.
|
||||
*/
|
||||
public FastBitmapDrawable newIcon(Context context) {
|
||||
FastBitmapDrawable drawable = bitmap.newIcon(context);
|
||||
drawable.setIsDisabled(isDisabled());
|
||||
return drawable;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,12 +23,12 @@ import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.graphics.DragPreviewProvider;
|
||||
import com.android.launcher3.icons.BitmapRenderer;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
|
||||
/**
|
||||
* Extension of {@link DragPreviewProvider} which generates bitmaps scaled to the default icon size.
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher3.util;
|
||||
|
||||
/**
|
||||
* Extension of closeable which does not throw an exception
|
||||
*/
|
||||
public interface SafeCloseable extends AutoCloseable {
|
||||
|
||||
@Override
|
||||
void close();
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import android.util.TypedValue;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.icons.GraphicsUtils;
|
||||
import com.android.launcher3.uioverrides.WallpaperColorInfo;
|
||||
|
||||
/**
|
||||
@@ -92,10 +93,7 @@ public class Themes {
|
||||
}
|
||||
|
||||
public static int getAttrColor(Context context, int attr) {
|
||||
TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
|
||||
int colorAccent = ta.getColor(0, 0);
|
||||
ta.recycle();
|
||||
return colorAccent;
|
||||
return GraphicsUtils.getAttrColor(context, attr);
|
||||
}
|
||||
|
||||
public static boolean getAttrBoolean(Context context, int attr) {
|
||||
@@ -119,23 +117,6 @@ public class Themes {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the alpha corresponding to the theme attribute {@param attr}, in the range [0, 255].
|
||||
*/
|
||||
public static int getAlpha(Context context, int attr) {
|
||||
return (int) (255 * getFloat(context, attr, 0) + 0.5f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the alpha corresponding to the theme attribute {@param attr}
|
||||
*/
|
||||
public static float getFloat(Context context, int attr, float defValue) {
|
||||
TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
|
||||
float value = ta.getFloat(0, defValue);
|
||||
ta.recycle();
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales a color matrix such that, when applied to color R G B A, it produces R' G' B' A' where
|
||||
* R' = r * R
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.launcher3.widget;
|
||||
|
||||
import static com.android.launcher3.FastBitmapDrawable.newIcon;
|
||||
import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
|
||||
|
||||
import android.content.Context;
|
||||
@@ -37,8 +36,8 @@ import android.view.View.OnClickListener;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
@@ -152,12 +151,12 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView
|
||||
// 2) Preload icon in the center
|
||||
// 3) Setup icon in the center and app icon in the top right corner.
|
||||
if (mDisabledForSafeMode) {
|
||||
FastBitmapDrawable disabledIcon = newIcon(getContext(), info);
|
||||
FastBitmapDrawable disabledIcon = info.newIcon(getContext());
|
||||
disabledIcon.setIsDisabled(true);
|
||||
mCenterDrawable = disabledIcon;
|
||||
mSettingIconDrawable = null;
|
||||
} else if (isReadyForClickSetup()) {
|
||||
mCenterDrawable = newIcon(getContext(), info);
|
||||
mCenterDrawable = info.newIcon(getContext());
|
||||
mSettingIconDrawable = getResources().getDrawable(R.drawable.ic_setting).mutate();
|
||||
updateSettingColor(info.bitmap.color);
|
||||
} else {
|
||||
|
||||
@@ -29,7 +29,6 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.DragSource;
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.PendingAddItemInfo;
|
||||
@@ -38,6 +37,7 @@ import com.android.launcher3.dragndrop.AppWidgetHostViewDrawable;
|
||||
import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.dragndrop.DraggableView;
|
||||
import com.android.launcher3.graphics.DragPreviewProvider;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
import com.android.launcher3.widget.dragndrop.AppWidgetHostViewDragListener;
|
||||
|
||||
|
||||
@@ -40,12 +40,12 @@ import androidx.annotation.Nullable;
|
||||
import com.android.launcher3.BaseActivity;
|
||||
import com.android.launcher3.CheckLongPressHelper;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.WidgetPreviewLoader;
|
||||
import com.android.launcher3.dragndrop.AppWidgetHostViewDrawable;
|
||||
import com.android.launcher3.icons.BaseIconFactory;
|
||||
import com.android.launcher3.icons.BitmapRenderer;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.model.WidgetItem;
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package com.android.launcher3.widget.picker;
|
||||
|
||||
import static com.android.launcher3.FastBitmapDrawable.newIcon;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
@@ -32,11 +30,11 @@ import androidx.annotation.UiThread;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.graphics.PlaceHolderIconDrawable;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
|
||||
import com.android.launcher3.icons.PlaceHolderIconDrawable;
|
||||
import com.android.launcher3.icons.cache.HandlerRunnable;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.model.data.PackageItemInfo;
|
||||
@@ -145,7 +143,7 @@ public final class WidgetsListHeader extends LinearLayout implements ItemInfoUpd
|
||||
}
|
||||
|
||||
private void setIcon(PackageItemInfo info) {
|
||||
FastBitmapDrawable icon = newIcon(getContext(), info);
|
||||
FastBitmapDrawable icon = info.newIcon(getContext());
|
||||
applyDrawables(icon);
|
||||
mIconDrawable = icon;
|
||||
if (mIconDrawable != null) {
|
||||
|
||||
Reference in New Issue
Block a user