Merge "Moving some common functionality to IconLoaderLib" into sc-dev

This commit is contained in:
Sunny Goyal
2021-03-26 16:42:04 +00:00
committed by Android (Google) Code Review
28 changed files with 44 additions and 1148 deletions
+1
View File
@@ -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);
-2
View File
@@ -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">
-2
View File
@@ -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;
}
}
+1
View File
@@ -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;
+1
View File
@@ -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();
}
+2 -21
View File
@@ -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) {