diff options
| author | android-build-team Robot <android-build-team-robot@google.com> | 2021-05-27 01:07:43 +0000 |
|---|---|---|
| committer | android-build-team Robot <android-build-team-robot@google.com> | 2021-05-27 01:07:43 +0000 |
| commit | 74c9de459bd83e1b2832258a4f905f016e96d673 (patch) | |
| tree | 3f16a8de74161f581449edfe12af8266839da0b6 | |
| parent | 7c7ae2a854993bfbd1605fad8528adb9f4cf4bcb (diff) | |
| parent | 625c8a5bd17148101445f9ba141164de689eb9dc (diff) | |
Snap for 7401515 from 625c8a5bd17148101445f9ba141164de689eb9dc to sc-v2-release
Change-Id: Ibf5595b9503e2afbc4e19c4419f84f63cd607eac
5 files changed, 221 insertions, 71 deletions
diff --git a/iconloaderlib/src/com/android/launcher3/icons/BitmapInfo.java b/iconloaderlib/src/com/android/launcher3/icons/BitmapInfo.java index 845a8ec..06b39b8 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/BitmapInfo.java +++ b/iconloaderlib/src/com/android/launcher3/icons/BitmapInfo.java @@ -22,6 +22,7 @@ import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.Canvas; +import android.graphics.drawable.Drawable; import android.os.Build; import android.os.UserHandle; import android.util.Log; @@ -146,14 +147,17 @@ public class BitmapInfo { /** * Called for creating a custom BitmapInfo */ - default BitmapInfo getExtendedInfo(Bitmap bitmap, int color, - BaseIconFactory iconFactory, float normalizationScale, UserHandle user) { - return BitmapInfo.of(bitmap, color); - } + BitmapInfo getExtendedInfo(Bitmap bitmap, int color, + BaseIconFactory iconFactory, float normalizationScale, UserHandle user); /** * Called to draw the UI independent of any runtime configurations like time or theme */ - default void drawForPersistence(Canvas canvas) { } + void drawForPersistence(Canvas canvas); + + /** + * Returns a new icon with theme applied + */ + Drawable getThemedDrawable(Context context); } } diff --git a/iconloaderlib/src/com/android/launcher3/icons/ClockDrawableWrapper.java b/iconloaderlib/src/com/android/launcher3/icons/ClockDrawableWrapper.java index fe00428..a7894c9 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/ClockDrawableWrapper.java +++ b/iconloaderlib/src/com/android/launcher3/icons/ClockDrawableWrapper.java @@ -15,14 +15,25 @@ */ package com.android.launcher3.icons; +import static com.android.launcher3.icons.ThemedIconDrawable.getColors; + import android.annotation.TargetApi; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuff.Mode; +import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.drawable.AdaptiveIconDrawable; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.os.Build; @@ -31,11 +42,15 @@ import android.os.Process; import android.os.SystemClock; import android.os.UserHandle; import android.util.Log; +import android.util.TypedValue; import androidx.annotation.Nullable; +import com.android.launcher3.icons.ThemedIconDrawable.ThemeData; + import java.util.Calendar; import java.util.concurrent.TimeUnit; +import java.util.function.IntFunction; /** * Wrapper over {@link AdaptiveIconDrawable} to intercept icon flattening logic for dynamic @@ -74,6 +89,7 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap private final AnimationInfo mAnimationInfo = new AnimationInfo(); private int mTargetSdkVersion; + protected ThemeData mThemeData; public ClockDrawableWrapper(AdaptiveIconDrawable base) { super(base.getBackground(), base.getForeground()); @@ -88,60 +104,94 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap 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; + Resources res = pm.getResourcesForApplication(appInfo); + return forExtras(appInfo, appInfo.metaData, + resId -> res.getDrawableForDensity(resId, iconDpi)); + } catch (Exception e) { + Log.d(TAG, "Unable to load clock drawable info", e); + } + return null; + } + + private static ClockDrawableWrapper fromThemeData(Context context, ThemeData themeData) { + try { + TypedArray ta = themeData.mResources.obtainTypedArray(themeData.mResID); + int count = ta.length(); + Bundle extras = new Bundle(); + for (int i = 0; i < count; i += 2) { + TypedValue v = ta.peekValue(i + 1); + extras.putInt(ta.getString(i), v.type >= TypedValue.TYPE_FIRST_INT + && v.type <= TypedValue.TYPE_LAST_INT + ? v.data : v.resourceId); } - int drawableId = metadata.getInt(ROUND_ICON_METADATA_KEY, 0); - if (drawableId == 0) { - return null; + ta.recycle(); + ClockDrawableWrapper drawable = ClockDrawableWrapper.forExtras( + context.getApplicationInfo(), extras, resId -> { + int[] colors = getColors(context); + Drawable bg = new ColorDrawable(colors[0]); + Drawable fg = themeData.mResources.getDrawable(resId).mutate(); + fg.setTint(colors[1]); + return new AdaptiveIconDrawable(bg, fg); + }); + if (drawable != null) { + return drawable; } + } catch (Exception e) { + Log.e(TAG, "Error loading themed clock", e); + } + return null; + } - Drawable drawable = pm.getResourcesForApplication(appInfo).getDrawableForDensity( - drawableId, iconDpi).mutate(); - if (!(drawable instanceof AdaptiveIconDrawable)) { - return null; - } + private static ClockDrawableWrapper forExtras(ApplicationInfo appInfo, Bundle metadata, + IntFunction<Drawable> drawableProvider) { + if (metadata == null) { + return null; + } + int drawableId = metadata.getInt(ROUND_ICON_METADATA_KEY, 0); + if (drawableId == 0) { + return null; + } - ClockDrawableWrapper wrapper = - new ClockDrawableWrapper((AdaptiveIconDrawable) drawable); - wrapper.mTargetSdkVersion = appInfo.targetSdkVersion; - AnimationInfo info = wrapper.mAnimationInfo; + Drawable drawable = drawableProvider.apply(drawableId).mutate(); + if (!(drawable instanceof AdaptiveIconDrawable)) { + return null; + } - info.baseDrawableState = drawable.getConstantState(); + ClockDrawableWrapper wrapper = + new ClockDrawableWrapper((AdaptiveIconDrawable) drawable); + wrapper.mTargetSdkVersion = appInfo.targetSdkVersion; + AnimationInfo info = wrapper.mAnimationInfo; - 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.baseDrawableState = drawable.getConstantState(); - 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); + 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); - 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; - } - info.applyTime(Calendar.getInstance(), foreground); - return wrapper; - } catch (Exception e) { - Log.d(TAG, "Unable to load clock drawable info", e); + 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; } - return null; + 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; + } + info.applyTime(Calendar.getInstance(), foreground); + return wrapper; } @Override - public BitmapInfo getExtendedInfo(Bitmap bitmap, int color, + public ClockBitmapInfo getExtendedInfo(Bitmap bitmap, int color, BaseIconFactory iconFactory, float normalizationScale, UserHandle user) { iconFactory.disableColorExtraction(); AdaptiveIconDrawable background = new AdaptiveIconDrawable( @@ -150,7 +200,7 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap Process.myUserHandle(), mTargetSdkVersion, false); return new ClockBitmapInfo(bitmap, color, normalizationScale, - mAnimationInfo, bitmapInfo.icon); + mAnimationInfo, bitmapInfo.icon, mThemeData); } @Override @@ -163,6 +213,15 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap mAnimationInfo.applyTime(Calendar.getInstance(), (LayerDrawable) getForeground()); } + @Override + public Drawable getThemedDrawable(Context context) { + if (mThemeData != null) { + ClockDrawableWrapper drawable = fromThemeData(context, mThemeData); + return drawable == null ? this : drawable; + } + return this; + } + private void resetLevel(LayerDrawable drawable, int index) { if (index != INVALID_VALUE) { drawable.getDrawable(index).setLevel(0); @@ -214,20 +273,45 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap } } - private static class ClockBitmapInfo extends BitmapInfo { + static class ClockBitmapInfo extends BitmapInfo { public final float scale; public final int offset; public final AnimationInfo animInfo; public final Bitmap mFlattenedBackground; + public final ThemeData themeData; + public final ColorFilter bgFilter; + + ClockBitmapInfo(Bitmap icon, int color, float scale, AnimationInfo animInfo, + Bitmap background, ThemeData themeData) { + this(icon, color, scale, animInfo, background, themeData, null); + } + ClockBitmapInfo(Bitmap icon, int color, float scale, AnimationInfo animInfo, - Bitmap background) { + Bitmap background, ThemeData themeData, ColorFilter bgFilter) { super(icon, color); this.scale = scale; this.animInfo = animInfo; this.offset = (int) Math.ceil(ShadowGenerator.BLUR_FACTOR * icon.getWidth()); this.mFlattenedBackground = background; + this.themeData = themeData; + this.bgFilter = bgFilter; + } + + @Override + public FastBitmapDrawable newThemedIcon(Context context) { + if (themeData != null) { + ClockDrawableWrapper wrapper = fromThemeData(context, themeData); + if (wrapper != null) { + int[] colors = getColors(context); + ColorFilter bgFilter = new PorterDuffColorFilter(colors[0], Mode.SRC_ATOP); + return new ClockBitmapInfo(icon, colors[1], scale, + wrapper.mAnimationInfo, mFlattenedBackground, themeData, bgFilter) + .newIcon(context); + } + } + return super.newThemedIcon(context); } @Override @@ -242,6 +326,16 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap public byte[] toByteArray() { return null; } + + void drawBackground(Canvas canvas, Rect bounds, Paint paint) { + // draw the background that is already flattened to a bitmap + ColorFilter oldFilter = paint.getColorFilter(); + if (bgFilter != null) { + paint.setColorFilter(bgFilter); + } + canvas.drawBitmap(mFlattenedBackground, null, bounds, paint); + paint.setColorFilter(oldFilter); + } } private static class ClockIconDrawable extends FastBitmapDrawable implements Runnable { @@ -274,8 +368,7 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap super.drawInternal(canvas, bounds); return; } - // draw the background that is already flattened to a bitmap - canvas.drawBitmap(mInfo.mFlattenedBackground, null, bounds, mPaint); + mInfo.drawBackground(canvas, bounds, mPaint); // prepare and draw the foreground mInfo.animInfo.applyTime(mTime, mForeground); @@ -289,6 +382,11 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap } @Override + public boolean isThemed() { + return mInfo.bgFilter != null; + } + + @Override protected void updateFilter() { super.updateFilter(); mFullDrawable.setColorFilter(mPaint.getColorFilter()); diff --git a/iconloaderlib/src/com/android/launcher3/icons/FastBitmapDrawable.java b/iconloaderlib/src/com/android/launcher3/icons/FastBitmapDrawable.java index cf510a1..96ee291 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/FastBitmapDrawable.java +++ b/iconloaderlib/src/com/android/launcher3/icons/FastBitmapDrawable.java @@ -113,6 +113,20 @@ public class FastBitmapDrawable extends Drawable { canvas.drawBitmap(mBitmap, null, bounds, mPaint); } + /** + * Returns the primary icon color + */ + public int getIconColor() { + return mIconColor; + } + + /** + * Returns if this represents a themed icon + */ + public boolean isThemed() { + return false; + } + @Override public void setColorFilter(ColorFilter cf) { mColorFilter = cf; diff --git a/iconloaderlib/src/com/android/launcher3/icons/IconProvider.java b/iconloaderlib/src/com/android/launcher3/icons/IconProvider.java index 6c96967..449c0da 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/IconProvider.java +++ b/iconloaderlib/src/com/android/launcher3/icons/IconProvider.java @@ -82,6 +82,10 @@ public class IconProvider { private final ComponentName mCalendar; private final ComponentName mClock; + static final int ICON_TYPE_DEFAULT = 0; + static final int ICON_TYPE_CALENDAR = 1; + static final int ICON_TYPE_CLOCK = 2; + public IconProvider(Context context) { this(context, false); } @@ -143,17 +147,23 @@ public class IconProvider { Supplier<Drawable> fallback) { Drawable icon = null; + int iconType = ICON_TYPE_DEFAULT; if (mCalendar != null && mCalendar.getPackageName().equals(packageName)) { icon = loadCalendarDrawable(iconDpi); + iconType = ICON_TYPE_CALENDAR; } else if (mClock != null && mClock.getPackageName().equals(packageName) && Process.myUserHandle().equals(user)) { icon = loadClockDrawable(iconDpi); + iconType = ICON_TYPE_CLOCK; + } + if (icon == null) { + icon = fallback.get(); + iconType = ICON_TYPE_DEFAULT; } - icon = icon == null ? fallback.get() : icon; ThemeData td = getThemedIconMap().get(packageName); - return td != null ? td.wrapDrawable(icon) : icon; + return td != null ? td.wrapDrawable(icon, iconType) : icon; } private Drawable loadActivityInfoIcon(ActivityInfo ai, int density) { @@ -265,7 +275,7 @@ public class IconProvider { /** * @return Today's day of the month, zero-indexed. */ - private int getDay() { + static int getDay() { return Calendar.getInstance().get(Calendar.DAY_OF_MONTH) - 1; } diff --git a/iconloaderlib/src/com/android/launcher3/icons/ThemedIconDrawable.java b/iconloaderlib/src/com/android/launcher3/icons/ThemedIconDrawable.java index 7425c68..797a439 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/ThemedIconDrawable.java +++ b/iconloaderlib/src/com/android/launcher3/icons/ThemedIconDrawable.java @@ -20,9 +20,12 @@ import static android.content.res.Configuration.UI_MODE_NIGHT_YES; import static android.content.res.Resources.ID_NULL; import static com.android.launcher3.icons.GraphicsUtils.getExpectedBitmapSize; +import static com.android.launcher3.icons.IconProvider.ICON_TYPE_CALENDAR; +import static com.android.launcher3.icons.IconProvider.ICON_TYPE_CLOCK; import android.content.Context; import android.content.res.Resources; +import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; @@ -38,6 +41,7 @@ import android.util.Log; import androidx.annotation.Nullable; import com.android.launcher3.icons.BitmapInfo.Extender; +import com.android.launcher3.icons.ClockDrawableWrapper.ClockBitmapInfo; import com.android.launcher3.icons.cache.BaseIconCache; import java.io.ByteArrayInputStream; @@ -63,7 +67,7 @@ public class ThemedIconDrawable extends FastBitmapDrawable { private final Rect mBadgeBounds; protected ThemedIconDrawable(ThemedConstantState constantState) { - super(constantState.mBitmap, constantState.mIconColor, constantState.mIsDisabled); + super(constantState.mBitmap, constantState.colorFg, constantState.mIsDisabled); bitmapInfo = constantState.bitmapInfo; colorBg = constantState.colorBg; colorFg = constantState.colorFg; @@ -72,6 +76,7 @@ public class ThemedIconDrawable extends FastBitmapDrawable { mBgWrapper = new AdaptiveIconDrawable(new ColorDrawable(colorBg), null); mBadgeBounds = bitmapInfo.mUserBadge == null ? null : new Rect(0, 0, bitmapInfo.mUserBadge.getWidth(), bitmapInfo.mUserBadge.getHeight()); + } @Override @@ -96,6 +101,11 @@ public class ThemedIconDrawable extends FastBitmapDrawable { } @Override + public boolean isThemed() { + return true; + } + + @Override public ConstantState getConstantState() { return new ThemedConstantState(bitmapInfo, colorBg, colorFg, mIsDisabled); } @@ -147,7 +157,7 @@ public class ThemedIconDrawable extends FastBitmapDrawable { if (isNullOrLowRes()) { return null; } - String resName = mThemeData.mResources.getResourceName(mThemeData.mIconID); + String resName = mThemeData.mResources.getResourceName(mThemeData.mResID); ByteArrayOutputStream out = new ByteArrayOutputStream( getExpectedBitmapSize(icon) + 3 + resName.length()); try { @@ -200,30 +210,46 @@ public class ThemedIconDrawable extends FastBitmapDrawable { public static class ThemeData { final Resources mResources; - final int mIconID; + final int mResID; - public ThemeData(Resources resources, int iconID) { + public ThemeData(Resources resources, int resID) { mResources = resources; - mIconID = iconID; + mResID = resID; } Drawable loadMonochromeDrawable(int accentColor) { - Drawable d = mResources.getDrawable(mIconID).mutate(); + Drawable d = mResources.getDrawable(mResID).mutate(); d.setTint(accentColor); - d = new InsetDrawable(d, .15f); + d = new InsetDrawable(d, .2f); return d; } - public Drawable wrapDrawable(Drawable original) { - return (original instanceof AdaptiveIconDrawable) - ? new ThemedAdaptiveIcon((AdaptiveIconDrawable) original, this) - : original; + public Drawable wrapDrawable(Drawable original, int iconType) { + if (!(original instanceof AdaptiveIconDrawable)) { + return original; + } + AdaptiveIconDrawable aid = (AdaptiveIconDrawable) original; + String resourceType = mResources.getResourceTypeName(mResID); + if (iconType == ICON_TYPE_CALENDAR && "array".equals(resourceType)) { + TypedArray ta = mResources.obtainTypedArray(mResID); + int id = ta.getResourceId(IconProvider.getDay(), ID_NULL); + ta.recycle(); + return id == ID_NULL ? original + : new ThemedAdaptiveIcon(aid, new ThemeData(mResources, id)); + } else if (iconType == ICON_TYPE_CLOCK && "array".equals(resourceType)) { + ((ClockDrawableWrapper) original).mThemeData = this; + return original; + } else if ("drawable".equals(resourceType)) { + return new ThemedAdaptiveIcon(aid, this); + } else { + return original; + } } } - public static class ThemedAdaptiveIcon extends AdaptiveIconDrawable implements Extender { + static class ThemedAdaptiveIcon extends AdaptiveIconDrawable implements Extender { - private final ThemeData mThemeData; + protected final ThemeData mThemeData; public ThemedAdaptiveIcon(AdaptiveIconDrawable parent, ThemeData themeData) { super(parent.getBackground(), parent.getForeground()); @@ -243,9 +269,7 @@ public class ThemedIconDrawable extends FastBitmapDrawable { draw(canvas); } - /** - * Returns a new icon with theme applied - */ + @Override public Drawable getThemedDrawable(Context context) { int[] colors = getColors(context); Drawable bg = new ColorDrawable(colors[0]); |
