[automerger skipped] DO NOT MERGE - Merge Android 13 am: db30759106 -s ours am: 5bbe26bf0e -s ours am: a53ff51208 -s ours

am skip reason: Merged-In I67328c973d97974bcea340943f7ce02c55550d8e with SHA-1 e628400809 is already in history

Original change: https://android-review.googlesource.com/c/platform/frameworks/libs/systemui/+/2186816

Change-Id: Id493852e9196f5251a9d322d7ec772f41fe8022d
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
index c0be55d..f671171 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
@@ -1,5 +1,6 @@
 package com.android.launcher3.icons;
 
+import static android.graphics.Paint.ANTI_ALIAS_FLAG;
 import static android.graphics.Paint.DITHER_FLAG;
 import static android.graphics.Paint.FILTER_BITMAP_FLAG;
 import static android.graphics.drawable.AdaptiveIconDrawable.getExtraInsetFraction;
@@ -44,6 +45,10 @@
 
     private static final int DEFAULT_WRAPPER_BACKGROUND = Color.WHITE;
 
+    protected static final int BITMAP_GENERATION_MODE_DEFAULT = 0;
+    protected static final int BITMAP_GENERATION_MODE_ALPHA = 1;
+    protected static final int BITMAP_GENERATION_MODE_WITH_SHADOW = 2;
+
     private static final float ICON_BADGE_SCALE = 0.444f;
 
     private final Rect mOldBounds = new Rect();
@@ -69,8 +74,6 @@
     private Drawable mWrapperIcon;
     private int mWrapperBackgroundColor = DEFAULT_WRAPPER_BACKGROUND;
 
-    private final Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
-    private static final float PLACEHOLDER_TEXT_SIZE = 20f;
     private static int PLACEHOLDER_BACKGROUND_COLOR = Color.rgb(245, 245, 245);
 
     protected BaseIconFactory(Context context, int fillResIconDpi, int iconBitmapSize,
@@ -85,10 +88,6 @@
 
         mCanvas = new Canvas();
         mCanvas.setDrawFilter(new PaintFlagsDrawFilter(DITHER_FLAG, FILTER_BITMAP_FLAG));
-        mTextPaint.setTextAlign(Paint.Align.CENTER);
-        mTextPaint.setColor(PLACEHOLDER_BACKGROUND_COLOR);
-        mTextPaint.setTextSize(context.getResources().getDisplayMetrics().density *
-                PLACEHOLDER_TEXT_SIZE);
         clear();
     }
 
@@ -138,16 +137,11 @@
      * @return
      */
     public BitmapInfo createIconBitmap(String placeholder, int color) {
-        Bitmap placeholderBitmap = Bitmap.createBitmap(mIconBitmapSize, mIconBitmapSize,
-                Bitmap.Config.ARGB_8888);
-        mTextPaint.setColor(color);
-        Canvas canvas = new Canvas(placeholderBitmap);
-        canvas.drawText(placeholder, mIconBitmapSize / 2, mIconBitmapSize * 5 / 8, mTextPaint);
         AdaptiveIconDrawable drawable = new AdaptiveIconDrawable(
                 new ColorDrawable(PLACEHOLDER_BACKGROUND_COLOR),
-                new BitmapDrawable(mContext.getResources(), placeholderBitmap));
+                new CenterTextDrawable(placeholder, color));
         Bitmap icon = createIconBitmap(drawable, IconNormalizer.ICON_VISIBLE_AREA_FACTOR);
-        return BitmapInfo.of(icon, extractColor(icon));
+        return BitmapInfo.of(icon, color);
     }
 
     public BitmapInfo createIconBitmap(Bitmap icon) {
@@ -187,12 +181,7 @@
         boolean shrinkNonAdaptiveIcons = options == null || options.mShrinkNonAdaptiveIcons;
         float[] scale = new float[1];
         icon = normalizeAndWrapToAdaptiveIcon(icon, shrinkNonAdaptiveIcons, null, scale);
-        Bitmap bitmap = createIconBitmap(icon, scale[0]);
-        if (icon instanceof AdaptiveIconDrawable) {
-            mCanvas.setBitmap(bitmap);
-            getShadowGenerator().recreateIcon(Bitmap.createBitmap(bitmap), mCanvas);
-            mCanvas.setBitmap(null);
-        }
+        Bitmap bitmap = createIconBitmap(icon, scale[0], BITMAP_GENERATION_MODE_WITH_SHADOW);
 
         int color = extractColor(bitmap);
         BitmapInfo info = BitmapInfo.of(bitmap, color);
@@ -206,8 +195,7 @@
                 // Convert mono drawable to bitmap
                 Drawable paddedMono = new ClippedMonoDrawable(mono);
                 info.setMonoIcon(
-                        createIconBitmap(paddedMono, scale[0], mIconBitmapSize, Config.ALPHA_8),
-                        this);
+                        createIconBitmap(paddedMono, scale[0], BITMAP_GENERATION_MODE_ALPHA), this);
             }
         }
         info = info.withFlags(getBitmapFlagOp(options));
@@ -252,10 +240,8 @@
     public Bitmap createScaledBitmapWithShadow(Drawable d) {
         float scale = getNormalizer().getScale(d, null, null, null);
         Bitmap bitmap = createIconBitmap(d, scale);
-        mCanvas.setBitmap(bitmap);
-        getShadowGenerator().recreateIcon(Bitmap.createBitmap(bitmap), mCanvas);
-        mCanvas.setBitmap(null);
-        return bitmap;
+        return BitmapRenderer.createHardwareBitmap(bitmap.getWidth(), bitmap.getHeight(),
+                canvas -> getShadowGenerator().recreateIcon(bitmap, canvas));
     }
 
     public Bitmap createScaledBitmapWithoutShadow(Drawable icon) {
@@ -280,7 +266,7 @@
         mDisableColorExtractor = true;
     }
 
-    private Drawable normalizeAndWrapToAdaptiveIcon(@NonNull Drawable icon,
+    protected Drawable normalizeAndWrapToAdaptiveIcon(@NonNull Drawable icon,
             boolean shrinkNonAdaptiveIcons, RectF outIconBounds, float[] outScale) {
         if (icon == null) {
             return null;
@@ -312,21 +298,24 @@
         return icon;
     }
 
-    private Bitmap createIconBitmap(Drawable icon, float scale) {
-        return createIconBitmap(icon, scale, mIconBitmapSize);
+    protected Bitmap createIconBitmap(Drawable icon, float scale) {
+        return createIconBitmap(icon, scale, BITMAP_GENERATION_MODE_DEFAULT);
     }
 
-    /**
-     * @param icon drawable that should be flattened to a bitmap
-     * @param scale the scale to apply before drawing {@param icon} on the canvas
-     */
-    public Bitmap createIconBitmap(@NonNull Drawable icon, float scale, int size) {
-        return createIconBitmap(icon, scale, size, Bitmap.Config.ARGB_8888);
-    }
+    protected Bitmap createIconBitmap(@NonNull Drawable icon, float scale,
+            int bitmapGenerationMode) {
+        final int size = mIconBitmapSize;
 
-    private Bitmap createIconBitmap(@NonNull Drawable icon, float scale, int size,
-            Bitmap.Config config) {
-        Bitmap bitmap = Bitmap.createBitmap(size, size, config);
+        final Bitmap bitmap;
+        switch (bitmapGenerationMode) {
+            case BITMAP_GENERATION_MODE_ALPHA:
+                bitmap = Bitmap.createBitmap(size, size, Config.ALPHA_8);
+                break;
+            case BITMAP_GENERATION_MODE_WITH_SHADOW:
+            default:
+                bitmap = Bitmap.createBitmap(size, size, Config.ARGB_8888);
+                break;
+        }
         if (icon == null) {
             return bitmap;
         }
@@ -335,11 +324,15 @@
 
         if (icon instanceof AdaptiveIconDrawable) {
             int offset = Math.max((int) Math.ceil(BLUR_FACTOR * size),
-                    Math.round(size * (1 - scale) / 2 ));
+                    Math.round(size * (1 - scale) / 2));
             // b/211896569: AdaptiveIconDrawable do not work properly for non top-left bounds
             icon.setBounds(0, 0, size - offset - offset, size - offset - offset);
             int count = mCanvas.save();
             mCanvas.translate(offset, offset);
+            if (bitmapGenerationMode == BITMAP_GENERATION_MODE_WITH_SHADOW) {
+                getShadowGenerator().addPathShadow(
+                        ((AdaptiveIconDrawable) icon).getIconMask(), mCanvas);
+            }
 
             if (icon instanceof BitmapInfo.Extender) {
                 ((Extender) icon).drawForPersistence(mCanvas);
@@ -351,7 +344,7 @@
             if (icon instanceof BitmapDrawable) {
                 BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
                 Bitmap b = bitmapDrawable.getBitmap();
-                if (bitmap != null && b.getDensity() == Bitmap.DENSITY_NONE) {
+                if (b != null && b.getDensity() == Bitmap.DENSITY_NONE) {
                     bitmapDrawable.setTargetDensity(mContext.getResources().getDisplayMetrics());
                 }
             }
@@ -491,4 +484,27 @@
             canvas.restoreToCount(saveCount);
         }
     }
+
+    private static class CenterTextDrawable extends ColorDrawable {
+
+        private final Rect mTextBounds = new Rect();
+        private final Paint mTextPaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG);
+        private final String mText;
+
+        CenterTextDrawable(String text, int color) {
+            mText = text;
+            mTextPaint.setColor(color);
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            Rect bounds = getBounds();
+            mTextPaint.setTextSize(bounds.height() / 3f);
+            mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBounds);
+            canvas.drawText(mText,
+                    bounds.exactCenterX() - mTextBounds.exactCenterX(),
+                    bounds.exactCenterY() - mTextBounds.exactCenterY(),
+                    mTextPaint);
+        }
+    }
 }
diff --git a/iconloaderlib/src/com/android/launcher3/icons/ClockDrawableWrapper.java b/iconloaderlib/src/com/android/launcher3/icons/ClockDrawableWrapper.java
index d624805..167fca4 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/ClockDrawableWrapper.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/ClockDrawableWrapper.java
@@ -387,7 +387,8 @@
             mBgPaint.setColorFilter(cs.mBgFilter);
             mThemedFgColor = cs.mThemedFgColor;
 
-            mFullDrawable = (AdaptiveIconDrawable) mAnimInfo.baseDrawableState.newDrawable();
+            mFullDrawable =
+                    (AdaptiveIconDrawable) mAnimInfo.baseDrawableState.newDrawable().mutate();
             mFG = (LayerDrawable) mFullDrawable.getForeground();
 
             // Time needs to be applied here since drawInternal is NOT guaranteed to be called
@@ -397,6 +398,13 @@
         }
 
         @Override
+        public void setAlpha(int alpha) {
+            super.setAlpha(alpha);
+            mBgPaint.setAlpha(alpha);
+            mFG.setAlpha(alpha);
+        }
+
+        @Override
         protected void onBoundsChange(Rect bounds) {
             super.onBoundsChange(bounds);
 
@@ -434,8 +442,7 @@
         protected void updateFilter() {
             super.updateFilter();
             int alpha = mIsDisabled ? (int) (mDisabledAlpha * FULLY_OPAQUE) : FULLY_OPAQUE;
-            mBgPaint.setAlpha(alpha);
-            mFG.setAlpha(alpha);
+            setAlpha(alpha);
             mBgPaint.setColorFilter(mIsDisabled ? getDisabledColorFilter() : mBgFilter);
             mFG.setColorFilter(mIsDisabled ? getDisabledColorFilter() : null);
         }
diff --git a/iconloaderlib/src/com/android/launcher3/icons/ShadowGenerator.java b/iconloaderlib/src/com/android/launcher3/icons/ShadowGenerator.java
index 96dee3b..be49ffd 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/ShadowGenerator.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/ShadowGenerator.java
@@ -24,6 +24,7 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
+import android.graphics.Path;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.RectF;
@@ -58,22 +59,17 @@
     }
 
     public synchronized void recreateIcon(Bitmap icon, Canvas out) {
-        recreateIcon(icon, mDefaultBlurMaskFilter, AMBIENT_SHADOW_ALPHA, KEY_SHADOW_ALPHA, out);
-    }
-
-    public synchronized void recreateIcon(Bitmap icon, BlurMaskFilter blurMaskFilter,
-            int ambientAlpha, int keyAlpha, Canvas out) {
         if (ENABLE_SHADOWS) {
             int[] offset = new int[2];
-            mBlurPaint.setMaskFilter(blurMaskFilter);
+            mBlurPaint.setMaskFilter(mDefaultBlurMaskFilter);
             Bitmap shadow = icon.extractAlpha(mBlurPaint, offset);
 
             // Draw ambient shadow
-            mDrawPaint.setAlpha(ambientAlpha);
+            mDrawPaint.setAlpha(AMBIENT_SHADOW_ALPHA);
             out.drawBitmap(shadow, offset[0], offset[1], mDrawPaint);
 
             // Draw key shadow
-            mDrawPaint.setAlpha(keyAlpha);
+            mDrawPaint.setAlpha(KEY_SHADOW_ALPHA);
             out.drawBitmap(shadow, offset[0], offset[1] + KEY_SHADOW_DISTANCE * mIconSize,
                     mDrawPaint);
         }
@@ -83,6 +79,26 @@
         out.drawBitmap(icon, 0, 0, mDrawPaint);
     }
 
+    /** package private **/
+    void addPathShadow(Path path, Canvas out) {
+        if (ENABLE_SHADOWS) {
+            mDrawPaint.setMaskFilter(mDefaultBlurMaskFilter);
+
+            // Draw ambient shadow
+            mDrawPaint.setAlpha(AMBIENT_SHADOW_ALPHA);
+            out.drawPath(path, mDrawPaint);
+
+            // Draw key shadow
+            int save = out.save();
+            mDrawPaint.setAlpha(KEY_SHADOW_ALPHA);
+            out.translate(0, KEY_SHADOW_DISTANCE * mIconSize);
+            out.drawPath(path, mDrawPaint);
+            out.restoreToCount(save);
+
+            mDrawPaint.setMaskFilter(null);
+        }
+    }
+
     /**
      * Returns the minimum amount by which an icon with {@param bounds} should be scaled
      * so that the shadows do not get clipped.
diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java b/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java
index 9e1ad7b..aec1cdd 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java
@@ -180,7 +180,8 @@
                 long updateTime = c.getLong(indexLastUpdate);
                 int version = c.getInt(indexVersion);
                 T app = componentMap.remove(component);
-                if (version == info.versionCode && updateTime == info.lastUpdateTime
+                if (version == info.versionCode
+                        && updateTime == cachingLogic.getLastUpdatedTime(app, info)
                         && TextUtils.equals(c.getString(systemStateIndex),
                                 mIconCache.getIconSystemState(info.packageName))) {