Loading iconloaderlib/res/drawable/ic_work_app_badge.xml 0 → 100644 +39 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2021 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. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="@dimen/profile_badge_size" android:height="@dimen/profile_badge_size" android:viewportWidth="24" android:viewportHeight="24"> <path android:fillColor="#11000000" android:pathData="M.5,12.25 A11.5,11.5 0 1,1 23.5,12.25 A11.5,11.5 0 1,1 .5,12.25" /> <path android:fillColor="@android:color/white" android:pathData="M1,12 A11,11 0 1,1 23,12 A11,11 0 1,1 1,12" /> <group android:scaleX=".6" android:scaleY=".6" android:pivotX="12" android:pivotY="12"> <path android:fillColor="#1A73E8" android:pathData="M20,6h-4L16,4c0,-1.11 -0.89,-2 -2,-2h-4c-1.11,0 -2,0.89 -2,2v2L4,6c-1.11,0 -1.99,0.89 -1.99,2L2,19c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2L22,8c0,-1.11 -0.89,-2 -2,-2zM14,6h-4L10,4h4v2z" /> </group> </vector> iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java +61 −134 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ package com.android.launcher3.icons; import static android.graphics.Paint.DITHER_FLAG; import static android.graphics.Paint.FILTER_BITMAP_FLAG; import static com.android.launcher3.icons.BitmapInfo.FLAG_INSTANT; import static com.android.launcher3.icons.ShadowGenerator.BLUR_FACTOR; import android.content.Context; Loading @@ -22,10 +23,10 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.InsetDrawable; import android.os.Build; import android.os.Process; import android.os.UserHandle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.launcher3.icons.BitmapInfo.Extender; Loading @@ -35,10 +36,7 @@ import com.android.launcher3.icons.BitmapInfo.Extender; */ public class BaseIconFactory implements AutoCloseable { private static final String TAG = "BaseIconFactory"; private static final int DEFAULT_WRAPPER_BACKGROUND = Color.WHITE; static final boolean ATLEAST_OREO = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; static final boolean ATLEAST_P = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P; private static final float ICON_BADGE_SCALE = 0.444f; Loading @@ -48,7 +46,6 @@ public class BaseIconFactory implements AutoCloseable { private final PackageManager mPm; private final ColorExtractor mColorExtractor; private boolean mDisableColorExtractor; private boolean mBadgeOnLeft = false; protected final int mFillResIconDpi; protected final int mIconBitmapSize; Loading @@ -59,7 +56,6 @@ public class BaseIconFactory implements AutoCloseable { private Drawable mWrapperIcon; private int mWrapperBackgroundColor = DEFAULT_WRAPPER_BACKGROUND; private Bitmap mUserBadgeBitmap; private final Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); private static final float PLACEHOLDER_TEXT_SIZE = 20f; Loading Loading @@ -91,7 +87,6 @@ public class BaseIconFactory implements AutoCloseable { protected void clear() { mWrapperBackgroundColor = DEFAULT_WRAPPER_BACKGROUND; mDisableColorExtractor = false; mBadgeOnLeft = false; } public ShadowGenerator getShadowGenerator() { Loading @@ -115,10 +110,7 @@ public class BaseIconFactory implements AutoCloseable { if (resources != null) { final int id = resources.getIdentifier(iconRes.resourceName, null, null); // do not stamp old legacy shortcuts as the app may have already forgotten about it return createBadgedIconBitmap( resources.getDrawableForDensity(id, mFillResIconDpi), Process.myUserHandle() /* only available on primary user */, false /* do not apply legacy treatment */); return createBadgedIconBitmap(resources.getDrawableForDensity(id, mFillResIconDpi)); } } catch (Exception e) { // Icon not found. Loading @@ -134,8 +126,6 @@ public class BaseIconFactory implements AutoCloseable { * @return */ public BitmapInfo createIconBitmap(String placeholder, int color) { if (!ATLEAST_OREO) return null; Bitmap placeholderBitmap = Bitmap.createBitmap(mIconBitmapSize, mIconBitmapSize, Bitmap.Config.ARGB_8888); mTextPaint.setColor(color); Loading @@ -159,43 +149,17 @@ public class BaseIconFactory implements AutoCloseable { /** * Creates an icon from the bitmap cropped to the current device icon shape */ public BitmapInfo createShapedIconBitmap(Bitmap icon, UserHandle user) { public BitmapInfo createShapedIconBitmap(Bitmap icon, IconOptions options) { Drawable d = new FixedSizeBitmapDrawable(icon); if (ATLEAST_OREO) { float inset = AdaptiveIconDrawable.getExtraInsetFraction(); inset = inset / (1 + 2 * inset); d = new AdaptiveIconDrawable(new ColorDrawable(Color.BLACK), new InsetDrawable(d, inset, inset, inset, inset)); } return createBadgedIconBitmap(d, user, true); } public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user, boolean shrinkNonAdaptiveIcons) { return createBadgedIconBitmap(icon, user, shrinkNonAdaptiveIcons, false, null); } public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user, int iconAppTargetSdk) { return createBadgedIconBitmap(icon, user, iconAppTargetSdk, false); } public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user, int iconAppTargetSdk, boolean isInstantApp) { return createBadgedIconBitmap(icon, user, iconAppTargetSdk, isInstantApp, null); } public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user, int iconAppTargetSdk, boolean isInstantApp, float[] scale) { boolean shrinkNonAdaptiveIcons = ATLEAST_P || (ATLEAST_OREO && iconAppTargetSdk >= Build.VERSION_CODES.O); return createBadgedIconBitmap(icon, user, shrinkNonAdaptiveIcons, isInstantApp, scale); return createBadgedIconBitmap(d, options); } public Bitmap createScaledBitmapWithoutShadow(Drawable icon, int iconAppTargetSdk) { boolean shrinkNonAdaptiveIcons = ATLEAST_P || (ATLEAST_OREO && iconAppTargetSdk >= Build.VERSION_CODES.O); return createScaledBitmapWithoutShadow(icon, shrinkNonAdaptiveIcons); public BitmapInfo createBadgedIconBitmap(@NonNull Drawable icon) { return createBadgedIconBitmap(icon, null); } /** Loading @@ -203,75 +167,41 @@ public class BaseIconFactory implements AutoCloseable { * The bitmap is visually normalized with other icons and has enough spacing to add shadow. * * @param icon source of the icon * @param user info can be used for a badge * @param shrinkNonAdaptiveIcons {@code true} if non adaptive icons should be treated * @param isInstantApp info can be used for a badge * @param scale returns the scale result from normalization * @return a bitmap suitable for disaplaying as an icon at various system UIs. */ public BitmapInfo createBadgedIconBitmap(@NonNull Drawable icon, UserHandle user, boolean shrinkNonAdaptiveIcons, boolean isInstantApp, float[] scale) { if (scale == null) { scale = new float[1]; } public BitmapInfo createBadgedIconBitmap(@NonNull Drawable icon, @Nullable IconOptions options) { boolean shrinkNonAdaptiveIcons = options == null || options.mShrinkNonAdaptiveIcons; float[] scale = new float[1]; icon = normalizeAndWrapToAdaptiveIcon(icon, shrinkNonAdaptiveIcons, null, scale); Bitmap bitmap = createIconBitmap(icon, scale[0]); if (ATLEAST_OREO && icon instanceof AdaptiveIconDrawable) { if (icon instanceof AdaptiveIconDrawable) { mCanvas.setBitmap(bitmap); getShadowGenerator().recreateIcon(Bitmap.createBitmap(bitmap), mCanvas); mCanvas.setBitmap(null); } if (isInstantApp) { badgeWithDrawable(bitmap, mContext.getDrawable(R.drawable.ic_instant_app_badge)); } if (user != null) { BitmapDrawable drawable = new FixedSizeBitmapDrawable(bitmap); Drawable badged = mPm.getUserBadgedIcon(drawable, user); if (badged instanceof BitmapDrawable) { bitmap = ((BitmapDrawable) badged).getBitmap(); } else { bitmap = createIconBitmap(badged, 1f); } } int color = extractColor(bitmap); return icon instanceof BitmapInfo.Extender ? ((BitmapInfo.Extender) icon).getExtendedInfo(bitmap, color, this, scale[0], user) BitmapInfo info = icon instanceof BitmapInfo.Extender ? ((BitmapInfo.Extender) icon).getExtendedInfo(bitmap, color, this, scale[0]) : BitmapInfo.of(bitmap, color); if (options != null) { if (options.mIsInstantApp) { info.flags |= FLAG_INSTANT; } public Bitmap getUserBadgeBitmap(UserHandle user) { if (mUserBadgeBitmap == null) { Bitmap bitmap = Bitmap.createBitmap( mIconBitmapSize, mIconBitmapSize, Bitmap.Config.ARGB_8888); Drawable badgedDrawable = mPm.getUserBadgedIcon( new FixedSizeBitmapDrawable(bitmap), user); if (badgedDrawable instanceof BitmapDrawable) { mUserBadgeBitmap = ((BitmapDrawable) badgedDrawable).getBitmap(); } else { badgedDrawable.setBounds(0, 0, mIconBitmapSize, mIconBitmapSize); mUserBadgeBitmap = BitmapRenderer.createSoftwareBitmap( mIconBitmapSize, mIconBitmapSize, badgedDrawable::draw); info.withUser(options.mUserHandle); } } return mUserBadgeBitmap; return info; } public Bitmap createScaledBitmapWithoutShadow(Drawable icon, boolean shrinkNonAdaptiveIcons) { public Bitmap createScaledBitmapWithoutShadow(Drawable icon) { RectF iconBounds = new RectF(); float[] scale = new float[1]; icon = normalizeAndWrapToAdaptiveIcon(icon, shrinkNonAdaptiveIcons, iconBounds, scale); icon = normalizeAndWrapToAdaptiveIcon(icon, true, iconBounds, scale); return createIconBitmap(icon, Math.min(scale[0], ShadowGenerator.getScaleForBounds(iconBounds))); } /** * Switches badging to left/right */ public void setBadgeOnLeft(boolean badgeOnLeft) { mBadgeOnLeft = badgeOnLeft; } /** * Sets the background color used for wrapped adaptive icon */ Loading @@ -293,7 +223,7 @@ public class BaseIconFactory implements AutoCloseable { } float scale = 1f; if (shrinkNonAdaptiveIcons && ATLEAST_OREO) { if (shrinkNonAdaptiveIcons) { if (mWrapperIcon == null) { mWrapperIcon = mContext.getDrawable(R.drawable.adaptive_icon_drawable_wrapper) .mutate(); Loading @@ -319,29 +249,6 @@ public class BaseIconFactory implements AutoCloseable { return icon; } /** * Adds the {@param badge} on top of {@param target} using the badge dimensions. */ public void badgeWithDrawable(Bitmap target, Drawable badge) { mCanvas.setBitmap(target); badgeWithDrawable(mCanvas, badge); mCanvas.setBitmap(null); } /** * Adds the {@param badge} on top of {@param target} using the badge dimensions. */ public void badgeWithDrawable(Canvas target, Drawable badge) { int badgeSize = getBadgeSizeForIconSize(mIconBitmapSize); if (mBadgeOnLeft) { badge.setBounds(0, mIconBitmapSize - badgeSize, badgeSize, mIconBitmapSize); } else { badge.setBounds(mIconBitmapSize - badgeSize, mIconBitmapSize - badgeSize, mIconBitmapSize, mIconBitmapSize); } badge.draw(target); } private Bitmap createIconBitmap(Drawable icon, float scale) { return createIconBitmap(icon, scale, mIconBitmapSize); } Loading @@ -358,7 +265,7 @@ public class BaseIconFactory implements AutoCloseable { mCanvas.setBitmap(bitmap); mOldBounds.set(icon.getBounds()); if (ATLEAST_OREO && icon instanceof AdaptiveIconDrawable) { if (icon instanceof AdaptiveIconDrawable) { int offset = Math.max((int) Math.ceil(BLUR_FACTOR * size), Math.round(size * (1 - scale) / 2 )); icon.setBounds(offset, offset, size - offset, size - offset); Loading Loading @@ -408,9 +315,8 @@ public class BaseIconFactory implements AutoCloseable { clear(); } public BitmapInfo makeDefaultIcon(UserHandle user) { return createBadgedIconBitmap(getFullResDefaultActivityIcon(mFillResIconDpi), user, Build.VERSION.SDK_INT); public BitmapInfo makeDefaultIcon() { return createBadgedIconBitmap(getFullResDefaultActivityIcon(mFillResIconDpi)); } public static Drawable getFullResDefaultActivityIcon(int iconDpi) { Loading @@ -420,17 +326,6 @@ public class BaseIconFactory implements AutoCloseable { iconDpi); } /** * Badges the provided source with the badge info */ public BitmapInfo badgeBitmap(Bitmap source, BitmapInfo badgeInfo) { Bitmap icon = BitmapRenderer.createHardwareBitmap(mIconBitmapSize, mIconBitmapSize, (c) -> { getShadowGenerator().recreateIcon(source, c); badgeWithDrawable(c, new FixedSizeBitmapDrawable(badgeInfo.icon)); }); return BitmapInfo.of(icon, badgeInfo.color); } private int extractColor(Bitmap bitmap) { return mDisableColorExtractor ? 0 : mColorExtractor.findDominantColorByHue(bitmap); } Loading @@ -442,6 +337,38 @@ public class BaseIconFactory implements AutoCloseable { return (int) (ICON_BADGE_SCALE * iconSize); } public static class IconOptions { boolean mShrinkNonAdaptiveIcons = true; boolean mIsInstantApp; UserHandle mUserHandle; /** * Set to false if non-adaptive icons should not be treated */ public IconOptions setShrinkNonAdaptiveIcons(boolean shrink) { mShrinkNonAdaptiveIcons = shrink; return this; } /** * User for this icon, in case of badging */ public IconOptions setUser(UserHandle user) { mUserHandle = user; return this; } /** * If this icon represents an instant app */ public IconOptions setInstantApp(boolean instantApp) { mIsInstantApp = instantApp; return this; } } /** * An extension of {@link BitmapDrawable} which returns the bitmap pixel size as intrinsic size. * This allows the badging to be done based on the action bitmap size rather than Loading iconloaderlib/src/com/android/launcher3/icons/BitmapInfo.java +71 −12 Original line number Diff line number Diff line Loading @@ -24,20 +24,37 @@ import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Process; import android.os.UserHandle; import android.util.Log; import androidx.annotation.IntDef; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.launcher3.icons.ThemedIconDrawable.ThemedBitmapInfo; import com.android.launcher3.icons.cache.BaseIconCache; import java.io.ByteArrayOutputStream; import java.io.IOException; public class BitmapInfo { static final int FLAG_WORK = 1 << 0; static final int FLAG_INSTANT = 1 << 1; @IntDef(flag = true, value = { FLAG_WORK, FLAG_INSTANT, }) @interface BitmapInfoFlags {} public static final int FLAG_THEMED = 1 << 0; public static final int FLAG_NO_BADGE = 1 << 1; @IntDef(flag = true, value = { FLAG_THEMED, FLAG_NO_BADGE, }) public @interface DrawableCreationFlags {} public static final Bitmap LOW_RES_ICON = Bitmap.createBitmap(1, 1, Config.ALPHA_8); public static final BitmapInfo LOW_RES_INFO = fromBitmap(LOW_RES_ICON); Loading @@ -49,11 +66,40 @@ public class BitmapInfo { public final Bitmap icon; public final int color; public @BitmapInfoFlags int flags; private BitmapInfo badgeInfo; public BitmapInfo(Bitmap icon, int color) { this.icon = icon; this.color = color; } public BitmapInfo withBadgeInfo(BitmapInfo badgeInfo) { BitmapInfo result = new BitmapInfo(icon, color); result.flags = flags; result.badgeInfo = badgeInfo; return result; } @Override public BitmapInfo clone() { BitmapInfo result = new BitmapInfo(icon, color); result.flags = flags; return result; } /** * Ensures that the BitmapInfo represents the provided user */ public BitmapInfo withUser(UserHandle userHandle) { if (userHandle == null || Process.myUserHandle().equals(userHandle)) { flags &= ~FLAG_WORK; } else { flags |= FLAG_WORK; } return this; } /** * Ideally icon should not be null, except in cases when generating hardware bitmap failed */ Loading Loading @@ -87,31 +133,44 @@ public class BitmapInfo { } /** * Returns a new icon based on the theme of the context * Creates a drawable for the provided BitmapInfo */ public FastBitmapDrawable newThemedIcon(Context context) { return newIcon(context); public FastBitmapDrawable newIcon(Context context) { return newIcon(context, 0); } /** * Creates a drawable for the provided BitmapInfo */ public FastBitmapDrawable newIcon(Context context) { public FastBitmapDrawable newIcon(Context context, @DrawableCreationFlags int creationFlags) { FastBitmapDrawable drawable = isLowRes() ? new PlaceHolderIconDrawable(this, context) : new FastBitmapDrawable(this); drawable.mDisabledAlpha = GraphicsUtils.getFloat(context, R.attr.disabledIconAlpha, 1f); applyFlags(context, drawable, creationFlags); return drawable; } protected void applyFlags(Context context, FastBitmapDrawable drawable, @DrawableCreationFlags int creationFlags) { drawable.mDisabledAlpha = GraphicsUtils.getFloat(context, R.attr.disabledIconAlpha, 1f); if ((creationFlags & FLAG_NO_BADGE) == 0) { if (badgeInfo != null) { drawable.setBadge(badgeInfo.newIcon(context, creationFlags)); } else if ((flags & FLAG_INSTANT) != 0) { drawable.setBadge(context.getDrawable(R.drawable.ic_instant_app_badge)); } else if ((flags & FLAG_WORK) != 0) { drawable.setBadge(context.getDrawable(R.drawable.ic_work_app_badge)); } } } /** * Returns a BitmapInfo previously serialized using {@link #toByteArray()}; */ @NonNull public static BitmapInfo fromByteArray(byte[] data, int color, UserHandle user, BaseIconCache iconCache, Context context) { public static BitmapInfo fromByteArray(byte[] data, int color, Context context) { if (data == null) { return null; throw new NullPointerException(); } BitmapFactory.Options decodeOptions; if (BitmapRenderer.USE_HARDWARE_BITMAP && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { Loading @@ -125,9 +184,9 @@ public class BitmapInfo { BitmapFactory.decodeByteArray(data, 1, data.length - 1, decodeOptions), color); } else if (data[0] == TYPE_THEMED) { return ThemedBitmapInfo.decode(data, color, decodeOptions, user, iconCache, context); return ThemedBitmapInfo.decode(data, color, decodeOptions, context); } else { return null; throw new IllegalArgumentException("Unknown type " + data[0]); } } Loading @@ -148,7 +207,7 @@ public class BitmapInfo { * Called for creating a custom BitmapInfo */ BitmapInfo getExtendedInfo(Bitmap bitmap, int color, BaseIconFactory iconFactory, float normalizationScale, UserHandle user); BaseIconFactory iconFactory, float normalizationScale); /** * Called to draw the UI independent of any runtime configurations like time or theme Loading iconloaderlib/src/com/android/launcher3/icons/ClockDrawableWrapper.java +21 −27 Original line number Diff line number Diff line Loading @@ -86,7 +86,6 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap public static final int INVALID_VALUE = -1; private final AnimationInfo mAnimationInfo = new AnimationInfo(); private int mTargetSdkVersion; protected ThemeData mThemeData; public ClockDrawableWrapper(AdaptiveIconDrawable base) { Loading @@ -103,7 +102,7 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap ApplicationInfo appInfo = pm.getApplicationInfo(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.GET_META_DATA); Resources res = pm.getResourcesForApplication(appInfo); return forExtras(appInfo, appInfo.metaData, return forExtras(appInfo.metaData, resId -> res.getDrawableForDensity(resId, iconDpi)); } catch (Exception e) { Log.d(TAG, "Unable to load clock drawable info", e); Loading @@ -123,8 +122,7 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap ? v.data : v.resourceId); } ta.recycle(); ClockDrawableWrapper drawable = ClockDrawableWrapper.forExtras( context.getApplicationInfo(), extras, resId -> { ClockDrawableWrapper drawable = ClockDrawableWrapper.forExtras(extras, resId -> { int[] colors = getColors(context); Drawable bg = new ColorDrawable(colors[0]); Drawable fg = themeData.mResources.getDrawable(resId).mutate(); Loading @@ -140,8 +138,8 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap return null; } private static ClockDrawableWrapper forExtras(ApplicationInfo appInfo, Bundle metadata, IntFunction<Drawable> drawableProvider) { private static ClockDrawableWrapper forExtras( Bundle metadata, IntFunction<Drawable> drawableProvider) { if (metadata == null) { return null; } Loading @@ -157,7 +155,6 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap ClockDrawableWrapper wrapper = new ClockDrawableWrapper((AdaptiveIconDrawable) drawable); wrapper.mTargetSdkVersion = appInfo.targetSdkVersion; AnimationInfo info = wrapper.mAnimationInfo; info.baseDrawableState = drawable.getConstantState(); Loading Loading @@ -190,13 +187,11 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap @Override public ClockBitmapInfo getExtendedInfo(Bitmap bitmap, int color, BaseIconFactory iconFactory, float normalizationScale, UserHandle user) { BaseIconFactory iconFactory, float normalizationScale) { iconFactory.disableColorExtraction(); AdaptiveIconDrawable background = new AdaptiveIconDrawable( getBackground().getConstantState().newDrawable(), null); BitmapInfo bitmapInfo = iconFactory.createBadgedIconBitmap(background, Process.myUserHandle(), mTargetSdkVersion, false); BitmapInfo bitmapInfo = iconFactory.createBadgedIconBitmap(background); return new ClockBitmapInfo(bitmap, color, normalizationScale, mAnimationInfo, bitmapInfo.icon, mThemeData); } Loading Loading @@ -298,24 +293,23 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap } @Override public FastBitmapDrawable newThemedIcon(Context context) { if (themeData != null) { public FastBitmapDrawable newIcon(Context context, @DrawableCreationFlags int creationFlags) { FastBitmapDrawable d = null; if ((creationFlags & FLAG_THEMED) != 0 && 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, d = new ClockBitmapInfo(icon, colors[1], scale, wrapper.mAnimationInfo, mFlattenedBackground, themeData, bgFilter) .newIcon(context); } } return super.newThemedIcon(context); if (d == null) { d = new ClockIconDrawable(this); } @Override public FastBitmapDrawable newIcon(Context context) { ClockIconDrawable d = new ClockIconDrawable(this); d.mDisabledAlpha = GraphicsUtils.getFloat(context, R.attr.disabledIconAlpha, 1f); applyFlags(context, d, creationFlags); return d; } Loading iconloaderlib/src/com/android/launcher3/icons/FastBitmapDrawable.java +71 −15 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
iconloaderlib/res/drawable/ic_work_app_badge.xml 0 → 100644 +39 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2021 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. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="@dimen/profile_badge_size" android:height="@dimen/profile_badge_size" android:viewportWidth="24" android:viewportHeight="24"> <path android:fillColor="#11000000" android:pathData="M.5,12.25 A11.5,11.5 0 1,1 23.5,12.25 A11.5,11.5 0 1,1 .5,12.25" /> <path android:fillColor="@android:color/white" android:pathData="M1,12 A11,11 0 1,1 23,12 A11,11 0 1,1 1,12" /> <group android:scaleX=".6" android:scaleY=".6" android:pivotX="12" android:pivotY="12"> <path android:fillColor="#1A73E8" android:pathData="M20,6h-4L16,4c0,-1.11 -0.89,-2 -2,-2h-4c-1.11,0 -2,0.89 -2,2v2L4,6c-1.11,0 -1.99,0.89 -1.99,2L2,19c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2L22,8c0,-1.11 -0.89,-2 -2,-2zM14,6h-4L10,4h4v2z" /> </group> </vector>
iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java +61 −134 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ package com.android.launcher3.icons; import static android.graphics.Paint.DITHER_FLAG; import static android.graphics.Paint.FILTER_BITMAP_FLAG; import static com.android.launcher3.icons.BitmapInfo.FLAG_INSTANT; import static com.android.launcher3.icons.ShadowGenerator.BLUR_FACTOR; import android.content.Context; Loading @@ -22,10 +23,10 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.InsetDrawable; import android.os.Build; import android.os.Process; import android.os.UserHandle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.launcher3.icons.BitmapInfo.Extender; Loading @@ -35,10 +36,7 @@ import com.android.launcher3.icons.BitmapInfo.Extender; */ public class BaseIconFactory implements AutoCloseable { private static final String TAG = "BaseIconFactory"; private static final int DEFAULT_WRAPPER_BACKGROUND = Color.WHITE; static final boolean ATLEAST_OREO = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; static final boolean ATLEAST_P = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P; private static final float ICON_BADGE_SCALE = 0.444f; Loading @@ -48,7 +46,6 @@ public class BaseIconFactory implements AutoCloseable { private final PackageManager mPm; private final ColorExtractor mColorExtractor; private boolean mDisableColorExtractor; private boolean mBadgeOnLeft = false; protected final int mFillResIconDpi; protected final int mIconBitmapSize; Loading @@ -59,7 +56,6 @@ public class BaseIconFactory implements AutoCloseable { private Drawable mWrapperIcon; private int mWrapperBackgroundColor = DEFAULT_WRAPPER_BACKGROUND; private Bitmap mUserBadgeBitmap; private final Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); private static final float PLACEHOLDER_TEXT_SIZE = 20f; Loading Loading @@ -91,7 +87,6 @@ public class BaseIconFactory implements AutoCloseable { protected void clear() { mWrapperBackgroundColor = DEFAULT_WRAPPER_BACKGROUND; mDisableColorExtractor = false; mBadgeOnLeft = false; } public ShadowGenerator getShadowGenerator() { Loading @@ -115,10 +110,7 @@ public class BaseIconFactory implements AutoCloseable { if (resources != null) { final int id = resources.getIdentifier(iconRes.resourceName, null, null); // do not stamp old legacy shortcuts as the app may have already forgotten about it return createBadgedIconBitmap( resources.getDrawableForDensity(id, mFillResIconDpi), Process.myUserHandle() /* only available on primary user */, false /* do not apply legacy treatment */); return createBadgedIconBitmap(resources.getDrawableForDensity(id, mFillResIconDpi)); } } catch (Exception e) { // Icon not found. Loading @@ -134,8 +126,6 @@ public class BaseIconFactory implements AutoCloseable { * @return */ public BitmapInfo createIconBitmap(String placeholder, int color) { if (!ATLEAST_OREO) return null; Bitmap placeholderBitmap = Bitmap.createBitmap(mIconBitmapSize, mIconBitmapSize, Bitmap.Config.ARGB_8888); mTextPaint.setColor(color); Loading @@ -159,43 +149,17 @@ public class BaseIconFactory implements AutoCloseable { /** * Creates an icon from the bitmap cropped to the current device icon shape */ public BitmapInfo createShapedIconBitmap(Bitmap icon, UserHandle user) { public BitmapInfo createShapedIconBitmap(Bitmap icon, IconOptions options) { Drawable d = new FixedSizeBitmapDrawable(icon); if (ATLEAST_OREO) { float inset = AdaptiveIconDrawable.getExtraInsetFraction(); inset = inset / (1 + 2 * inset); d = new AdaptiveIconDrawable(new ColorDrawable(Color.BLACK), new InsetDrawable(d, inset, inset, inset, inset)); } return createBadgedIconBitmap(d, user, true); } public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user, boolean shrinkNonAdaptiveIcons) { return createBadgedIconBitmap(icon, user, shrinkNonAdaptiveIcons, false, null); } public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user, int iconAppTargetSdk) { return createBadgedIconBitmap(icon, user, iconAppTargetSdk, false); } public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user, int iconAppTargetSdk, boolean isInstantApp) { return createBadgedIconBitmap(icon, user, iconAppTargetSdk, isInstantApp, null); } public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user, int iconAppTargetSdk, boolean isInstantApp, float[] scale) { boolean shrinkNonAdaptiveIcons = ATLEAST_P || (ATLEAST_OREO && iconAppTargetSdk >= Build.VERSION_CODES.O); return createBadgedIconBitmap(icon, user, shrinkNonAdaptiveIcons, isInstantApp, scale); return createBadgedIconBitmap(d, options); } public Bitmap createScaledBitmapWithoutShadow(Drawable icon, int iconAppTargetSdk) { boolean shrinkNonAdaptiveIcons = ATLEAST_P || (ATLEAST_OREO && iconAppTargetSdk >= Build.VERSION_CODES.O); return createScaledBitmapWithoutShadow(icon, shrinkNonAdaptiveIcons); public BitmapInfo createBadgedIconBitmap(@NonNull Drawable icon) { return createBadgedIconBitmap(icon, null); } /** Loading @@ -203,75 +167,41 @@ public class BaseIconFactory implements AutoCloseable { * The bitmap is visually normalized with other icons and has enough spacing to add shadow. * * @param icon source of the icon * @param user info can be used for a badge * @param shrinkNonAdaptiveIcons {@code true} if non adaptive icons should be treated * @param isInstantApp info can be used for a badge * @param scale returns the scale result from normalization * @return a bitmap suitable for disaplaying as an icon at various system UIs. */ public BitmapInfo createBadgedIconBitmap(@NonNull Drawable icon, UserHandle user, boolean shrinkNonAdaptiveIcons, boolean isInstantApp, float[] scale) { if (scale == null) { scale = new float[1]; } public BitmapInfo createBadgedIconBitmap(@NonNull Drawable icon, @Nullable IconOptions options) { boolean shrinkNonAdaptiveIcons = options == null || options.mShrinkNonAdaptiveIcons; float[] scale = new float[1]; icon = normalizeAndWrapToAdaptiveIcon(icon, shrinkNonAdaptiveIcons, null, scale); Bitmap bitmap = createIconBitmap(icon, scale[0]); if (ATLEAST_OREO && icon instanceof AdaptiveIconDrawable) { if (icon instanceof AdaptiveIconDrawable) { mCanvas.setBitmap(bitmap); getShadowGenerator().recreateIcon(Bitmap.createBitmap(bitmap), mCanvas); mCanvas.setBitmap(null); } if (isInstantApp) { badgeWithDrawable(bitmap, mContext.getDrawable(R.drawable.ic_instant_app_badge)); } if (user != null) { BitmapDrawable drawable = new FixedSizeBitmapDrawable(bitmap); Drawable badged = mPm.getUserBadgedIcon(drawable, user); if (badged instanceof BitmapDrawable) { bitmap = ((BitmapDrawable) badged).getBitmap(); } else { bitmap = createIconBitmap(badged, 1f); } } int color = extractColor(bitmap); return icon instanceof BitmapInfo.Extender ? ((BitmapInfo.Extender) icon).getExtendedInfo(bitmap, color, this, scale[0], user) BitmapInfo info = icon instanceof BitmapInfo.Extender ? ((BitmapInfo.Extender) icon).getExtendedInfo(bitmap, color, this, scale[0]) : BitmapInfo.of(bitmap, color); if (options != null) { if (options.mIsInstantApp) { info.flags |= FLAG_INSTANT; } public Bitmap getUserBadgeBitmap(UserHandle user) { if (mUserBadgeBitmap == null) { Bitmap bitmap = Bitmap.createBitmap( mIconBitmapSize, mIconBitmapSize, Bitmap.Config.ARGB_8888); Drawable badgedDrawable = mPm.getUserBadgedIcon( new FixedSizeBitmapDrawable(bitmap), user); if (badgedDrawable instanceof BitmapDrawable) { mUserBadgeBitmap = ((BitmapDrawable) badgedDrawable).getBitmap(); } else { badgedDrawable.setBounds(0, 0, mIconBitmapSize, mIconBitmapSize); mUserBadgeBitmap = BitmapRenderer.createSoftwareBitmap( mIconBitmapSize, mIconBitmapSize, badgedDrawable::draw); info.withUser(options.mUserHandle); } } return mUserBadgeBitmap; return info; } public Bitmap createScaledBitmapWithoutShadow(Drawable icon, boolean shrinkNonAdaptiveIcons) { public Bitmap createScaledBitmapWithoutShadow(Drawable icon) { RectF iconBounds = new RectF(); float[] scale = new float[1]; icon = normalizeAndWrapToAdaptiveIcon(icon, shrinkNonAdaptiveIcons, iconBounds, scale); icon = normalizeAndWrapToAdaptiveIcon(icon, true, iconBounds, scale); return createIconBitmap(icon, Math.min(scale[0], ShadowGenerator.getScaleForBounds(iconBounds))); } /** * Switches badging to left/right */ public void setBadgeOnLeft(boolean badgeOnLeft) { mBadgeOnLeft = badgeOnLeft; } /** * Sets the background color used for wrapped adaptive icon */ Loading @@ -293,7 +223,7 @@ public class BaseIconFactory implements AutoCloseable { } float scale = 1f; if (shrinkNonAdaptiveIcons && ATLEAST_OREO) { if (shrinkNonAdaptiveIcons) { if (mWrapperIcon == null) { mWrapperIcon = mContext.getDrawable(R.drawable.adaptive_icon_drawable_wrapper) .mutate(); Loading @@ -319,29 +249,6 @@ public class BaseIconFactory implements AutoCloseable { return icon; } /** * Adds the {@param badge} on top of {@param target} using the badge dimensions. */ public void badgeWithDrawable(Bitmap target, Drawable badge) { mCanvas.setBitmap(target); badgeWithDrawable(mCanvas, badge); mCanvas.setBitmap(null); } /** * Adds the {@param badge} on top of {@param target} using the badge dimensions. */ public void badgeWithDrawable(Canvas target, Drawable badge) { int badgeSize = getBadgeSizeForIconSize(mIconBitmapSize); if (mBadgeOnLeft) { badge.setBounds(0, mIconBitmapSize - badgeSize, badgeSize, mIconBitmapSize); } else { badge.setBounds(mIconBitmapSize - badgeSize, mIconBitmapSize - badgeSize, mIconBitmapSize, mIconBitmapSize); } badge.draw(target); } private Bitmap createIconBitmap(Drawable icon, float scale) { return createIconBitmap(icon, scale, mIconBitmapSize); } Loading @@ -358,7 +265,7 @@ public class BaseIconFactory implements AutoCloseable { mCanvas.setBitmap(bitmap); mOldBounds.set(icon.getBounds()); if (ATLEAST_OREO && icon instanceof AdaptiveIconDrawable) { if (icon instanceof AdaptiveIconDrawable) { int offset = Math.max((int) Math.ceil(BLUR_FACTOR * size), Math.round(size * (1 - scale) / 2 )); icon.setBounds(offset, offset, size - offset, size - offset); Loading Loading @@ -408,9 +315,8 @@ public class BaseIconFactory implements AutoCloseable { clear(); } public BitmapInfo makeDefaultIcon(UserHandle user) { return createBadgedIconBitmap(getFullResDefaultActivityIcon(mFillResIconDpi), user, Build.VERSION.SDK_INT); public BitmapInfo makeDefaultIcon() { return createBadgedIconBitmap(getFullResDefaultActivityIcon(mFillResIconDpi)); } public static Drawable getFullResDefaultActivityIcon(int iconDpi) { Loading @@ -420,17 +326,6 @@ public class BaseIconFactory implements AutoCloseable { iconDpi); } /** * Badges the provided source with the badge info */ public BitmapInfo badgeBitmap(Bitmap source, BitmapInfo badgeInfo) { Bitmap icon = BitmapRenderer.createHardwareBitmap(mIconBitmapSize, mIconBitmapSize, (c) -> { getShadowGenerator().recreateIcon(source, c); badgeWithDrawable(c, new FixedSizeBitmapDrawable(badgeInfo.icon)); }); return BitmapInfo.of(icon, badgeInfo.color); } private int extractColor(Bitmap bitmap) { return mDisableColorExtractor ? 0 : mColorExtractor.findDominantColorByHue(bitmap); } Loading @@ -442,6 +337,38 @@ public class BaseIconFactory implements AutoCloseable { return (int) (ICON_BADGE_SCALE * iconSize); } public static class IconOptions { boolean mShrinkNonAdaptiveIcons = true; boolean mIsInstantApp; UserHandle mUserHandle; /** * Set to false if non-adaptive icons should not be treated */ public IconOptions setShrinkNonAdaptiveIcons(boolean shrink) { mShrinkNonAdaptiveIcons = shrink; return this; } /** * User for this icon, in case of badging */ public IconOptions setUser(UserHandle user) { mUserHandle = user; return this; } /** * If this icon represents an instant app */ public IconOptions setInstantApp(boolean instantApp) { mIsInstantApp = instantApp; return this; } } /** * An extension of {@link BitmapDrawable} which returns the bitmap pixel size as intrinsic size. * This allows the badging to be done based on the action bitmap size rather than Loading
iconloaderlib/src/com/android/launcher3/icons/BitmapInfo.java +71 −12 Original line number Diff line number Diff line Loading @@ -24,20 +24,37 @@ import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Process; import android.os.UserHandle; import android.util.Log; import androidx.annotation.IntDef; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.launcher3.icons.ThemedIconDrawable.ThemedBitmapInfo; import com.android.launcher3.icons.cache.BaseIconCache; import java.io.ByteArrayOutputStream; import java.io.IOException; public class BitmapInfo { static final int FLAG_WORK = 1 << 0; static final int FLAG_INSTANT = 1 << 1; @IntDef(flag = true, value = { FLAG_WORK, FLAG_INSTANT, }) @interface BitmapInfoFlags {} public static final int FLAG_THEMED = 1 << 0; public static final int FLAG_NO_BADGE = 1 << 1; @IntDef(flag = true, value = { FLAG_THEMED, FLAG_NO_BADGE, }) public @interface DrawableCreationFlags {} public static final Bitmap LOW_RES_ICON = Bitmap.createBitmap(1, 1, Config.ALPHA_8); public static final BitmapInfo LOW_RES_INFO = fromBitmap(LOW_RES_ICON); Loading @@ -49,11 +66,40 @@ public class BitmapInfo { public final Bitmap icon; public final int color; public @BitmapInfoFlags int flags; private BitmapInfo badgeInfo; public BitmapInfo(Bitmap icon, int color) { this.icon = icon; this.color = color; } public BitmapInfo withBadgeInfo(BitmapInfo badgeInfo) { BitmapInfo result = new BitmapInfo(icon, color); result.flags = flags; result.badgeInfo = badgeInfo; return result; } @Override public BitmapInfo clone() { BitmapInfo result = new BitmapInfo(icon, color); result.flags = flags; return result; } /** * Ensures that the BitmapInfo represents the provided user */ public BitmapInfo withUser(UserHandle userHandle) { if (userHandle == null || Process.myUserHandle().equals(userHandle)) { flags &= ~FLAG_WORK; } else { flags |= FLAG_WORK; } return this; } /** * Ideally icon should not be null, except in cases when generating hardware bitmap failed */ Loading Loading @@ -87,31 +133,44 @@ public class BitmapInfo { } /** * Returns a new icon based on the theme of the context * Creates a drawable for the provided BitmapInfo */ public FastBitmapDrawable newThemedIcon(Context context) { return newIcon(context); public FastBitmapDrawable newIcon(Context context) { return newIcon(context, 0); } /** * Creates a drawable for the provided BitmapInfo */ public FastBitmapDrawable newIcon(Context context) { public FastBitmapDrawable newIcon(Context context, @DrawableCreationFlags int creationFlags) { FastBitmapDrawable drawable = isLowRes() ? new PlaceHolderIconDrawable(this, context) : new FastBitmapDrawable(this); drawable.mDisabledAlpha = GraphicsUtils.getFloat(context, R.attr.disabledIconAlpha, 1f); applyFlags(context, drawable, creationFlags); return drawable; } protected void applyFlags(Context context, FastBitmapDrawable drawable, @DrawableCreationFlags int creationFlags) { drawable.mDisabledAlpha = GraphicsUtils.getFloat(context, R.attr.disabledIconAlpha, 1f); if ((creationFlags & FLAG_NO_BADGE) == 0) { if (badgeInfo != null) { drawable.setBadge(badgeInfo.newIcon(context, creationFlags)); } else if ((flags & FLAG_INSTANT) != 0) { drawable.setBadge(context.getDrawable(R.drawable.ic_instant_app_badge)); } else if ((flags & FLAG_WORK) != 0) { drawable.setBadge(context.getDrawable(R.drawable.ic_work_app_badge)); } } } /** * Returns a BitmapInfo previously serialized using {@link #toByteArray()}; */ @NonNull public static BitmapInfo fromByteArray(byte[] data, int color, UserHandle user, BaseIconCache iconCache, Context context) { public static BitmapInfo fromByteArray(byte[] data, int color, Context context) { if (data == null) { return null; throw new NullPointerException(); } BitmapFactory.Options decodeOptions; if (BitmapRenderer.USE_HARDWARE_BITMAP && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { Loading @@ -125,9 +184,9 @@ public class BitmapInfo { BitmapFactory.decodeByteArray(data, 1, data.length - 1, decodeOptions), color); } else if (data[0] == TYPE_THEMED) { return ThemedBitmapInfo.decode(data, color, decodeOptions, user, iconCache, context); return ThemedBitmapInfo.decode(data, color, decodeOptions, context); } else { return null; throw new IllegalArgumentException("Unknown type " + data[0]); } } Loading @@ -148,7 +207,7 @@ public class BitmapInfo { * Called for creating a custom BitmapInfo */ BitmapInfo getExtendedInfo(Bitmap bitmap, int color, BaseIconFactory iconFactory, float normalizationScale, UserHandle user); BaseIconFactory iconFactory, float normalizationScale); /** * Called to draw the UI independent of any runtime configurations like time or theme Loading
iconloaderlib/src/com/android/launcher3/icons/ClockDrawableWrapper.java +21 −27 Original line number Diff line number Diff line Loading @@ -86,7 +86,6 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap public static final int INVALID_VALUE = -1; private final AnimationInfo mAnimationInfo = new AnimationInfo(); private int mTargetSdkVersion; protected ThemeData mThemeData; public ClockDrawableWrapper(AdaptiveIconDrawable base) { Loading @@ -103,7 +102,7 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap ApplicationInfo appInfo = pm.getApplicationInfo(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.GET_META_DATA); Resources res = pm.getResourcesForApplication(appInfo); return forExtras(appInfo, appInfo.metaData, return forExtras(appInfo.metaData, resId -> res.getDrawableForDensity(resId, iconDpi)); } catch (Exception e) { Log.d(TAG, "Unable to load clock drawable info", e); Loading @@ -123,8 +122,7 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap ? v.data : v.resourceId); } ta.recycle(); ClockDrawableWrapper drawable = ClockDrawableWrapper.forExtras( context.getApplicationInfo(), extras, resId -> { ClockDrawableWrapper drawable = ClockDrawableWrapper.forExtras(extras, resId -> { int[] colors = getColors(context); Drawable bg = new ColorDrawable(colors[0]); Drawable fg = themeData.mResources.getDrawable(resId).mutate(); Loading @@ -140,8 +138,8 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap return null; } private static ClockDrawableWrapper forExtras(ApplicationInfo appInfo, Bundle metadata, IntFunction<Drawable> drawableProvider) { private static ClockDrawableWrapper forExtras( Bundle metadata, IntFunction<Drawable> drawableProvider) { if (metadata == null) { return null; } Loading @@ -157,7 +155,6 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap ClockDrawableWrapper wrapper = new ClockDrawableWrapper((AdaptiveIconDrawable) drawable); wrapper.mTargetSdkVersion = appInfo.targetSdkVersion; AnimationInfo info = wrapper.mAnimationInfo; info.baseDrawableState = drawable.getConstantState(); Loading Loading @@ -190,13 +187,11 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap @Override public ClockBitmapInfo getExtendedInfo(Bitmap bitmap, int color, BaseIconFactory iconFactory, float normalizationScale, UserHandle user) { BaseIconFactory iconFactory, float normalizationScale) { iconFactory.disableColorExtraction(); AdaptiveIconDrawable background = new AdaptiveIconDrawable( getBackground().getConstantState().newDrawable(), null); BitmapInfo bitmapInfo = iconFactory.createBadgedIconBitmap(background, Process.myUserHandle(), mTargetSdkVersion, false); BitmapInfo bitmapInfo = iconFactory.createBadgedIconBitmap(background); return new ClockBitmapInfo(bitmap, color, normalizationScale, mAnimationInfo, bitmapInfo.icon, mThemeData); } Loading Loading @@ -298,24 +293,23 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap } @Override public FastBitmapDrawable newThemedIcon(Context context) { if (themeData != null) { public FastBitmapDrawable newIcon(Context context, @DrawableCreationFlags int creationFlags) { FastBitmapDrawable d = null; if ((creationFlags & FLAG_THEMED) != 0 && 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, d = new ClockBitmapInfo(icon, colors[1], scale, wrapper.mAnimationInfo, mFlattenedBackground, themeData, bgFilter) .newIcon(context); } } return super.newThemedIcon(context); if (d == null) { d = new ClockIconDrawable(this); } @Override public FastBitmapDrawable newIcon(Context context) { ClockIconDrawable d = new ClockIconDrawable(this); d.mDisabledAlpha = GraphicsUtils.getFloat(context, R.attr.disabledIconAlpha, 1f); applyFlags(context, d, creationFlags); return d; } Loading
iconloaderlib/src/com/android/launcher3/icons/FastBitmapDrawable.java +71 −15 File changed.Preview size limit exceeded, changes collapsed. Show changes