Snap for 7298338 from 999780e7761747b3874040665aea45a947223778 to sc-v2-release

Change-Id: I483fcb00acf9ae6969bba215d2ddc250045b3500
diff --git a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
index 4e1f25b..4af6a00 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
@@ -27,6 +27,8 @@
 
 import androidx.annotation.NonNull;
 
+import com.android.launcher3.icons.BitmapInfo.Extender;
+
 /**
  * This class will be moved to androidx library. There shouldn't be any dependency outside
  * this package.
@@ -342,7 +344,11 @@
             int offset = Math.max((int) Math.ceil(BLUR_FACTOR * size),
                     Math.round(size * (1 - scale) / 2 ));
             icon.setBounds(offset, offset, size - offset, size - offset);
-            icon.draw(mCanvas);
+            if (icon instanceof BitmapInfo.Extender) {
+                ((Extender) icon).drawForPersistence(mCanvas);
+            } else {
+                icon.draw(mCanvas);
+            }
         } else {
             if (icon instanceof BitmapDrawable) {
                 BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
diff --git a/iconloaderlib/src/com/android/launcher3/icons/BitmapInfo.java b/iconloaderlib/src/com/android/launcher3/icons/BitmapInfo.java
index 694343b..2e20e8b 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/BitmapInfo.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/BitmapInfo.java
@@ -18,8 +18,12 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.os.Build;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 public class BitmapInfo {
 
@@ -46,6 +50,14 @@
     }
 
     /**
+     * Returns a serialized version of BitmapInfo
+     */
+    @Nullable
+    public byte[] toByteArray() {
+        return isNullOrLowRes() ? null : GraphicsUtils.flattenBitmap(icon);
+    }
+
+    /**
      * Creates a drawable for the provided BitmapInfo
      */
     public FastBitmapDrawable newIcon(Context context) {
@@ -56,6 +68,23 @@
         return drawable;
     }
 
+    /**
+     * Returns a BitmapInfo previously serialized using {@link #toByteArray()};
+     */
+    @NonNull
+    public static BitmapInfo fromByteArray(byte[] data, int color) {
+        BitmapFactory.Options decodeOptions;
+        if (BitmapRenderer.USE_HARDWARE_BITMAP && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            decodeOptions = new BitmapFactory.Options();
+            decodeOptions.inPreferredConfig = Bitmap.Config.HARDWARE;
+        } else {
+            decodeOptions = null;
+        }
+        return BitmapInfo.of(
+                BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions),
+                color);
+    }
+
     public static BitmapInfo fromBitmap(@NonNull Bitmap bitmap) {
         return of(bitmap, 0);
     }
@@ -77,8 +106,8 @@
         }
 
         /**
-         * Notifies the drawable that it will be drawn directly in the UI, without any preprocessing
+         * Called to draw the UI independent of any runtime configurations like time or theme
          */
-        default void prepareToDrawOnUi() { }
+        default void drawForPersistence(Canvas canvas) { }
     }
 }
diff --git a/iconloaderlib/src/com/android/launcher3/icons/ClockDrawableWrapper.java b/iconloaderlib/src/com/android/launcher3/icons/ClockDrawableWrapper.java
index ed9d89c..8581aa6 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/ClockDrawableWrapper.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/ClockDrawableWrapper.java
@@ -129,6 +129,7 @@
                 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);
@@ -149,10 +150,21 @@
     }
 
     @Override
-    public void prepareToDrawOnUi() {
+    public void drawForPersistence(Canvas canvas) {
+        LayerDrawable foreground = (LayerDrawable) getForeground();
+        resetLevel(foreground, mAnimationInfo.hourLayerIndex);
+        resetLevel(foreground, mAnimationInfo.minuteLayerIndex);
+        resetLevel(foreground, mAnimationInfo.secondLayerIndex);
+        draw(canvas);
         mAnimationInfo.applyTime(Calendar.getInstance(), (LayerDrawable) getForeground());
     }
 
+    private void resetLevel(LayerDrawable drawable, int index) {
+        if (index != INVALID_VALUE) {
+            drawable.getDrawable(index).setLevel(0);
+        }
+    }
+
     private static class AnimationInfo {
 
         public ConstantState baseDrawableState;
diff --git a/iconloaderlib/src/com/android/launcher3/icons/IconProvider.java b/iconloaderlib/src/com/android/launcher3/icons/IconProvider.java
index c0e1549..dd6e63d 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/IconProvider.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/IconProvider.java
@@ -24,6 +24,7 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.LauncherActivityInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -34,13 +35,12 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.launcher3.icons.BitmapInfo.Extender;
 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;
+import java.util.function.Supplier;
 
 /**
  * Class to handle icon loading from different packages
@@ -57,13 +57,6 @@
     // 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;
@@ -87,58 +80,68 @@
     }
 
     /**
-     * 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 ActivityInfo such that it can be drawn directly
      * on the UI
+     * @deprecated Use {@link #getIcon}
      */
     public Drawable getIconForUI(ActivityInfo info, UserHandle user) {
-        Drawable icon = getIcon(info);
-        if (icon instanceof BitmapInfo.Extender) {
-            ((Extender) icon).prepareToDrawOnUi();
-        }
-        return icon;
+        return getIcon(info);
     }
 
     /**
      * 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);
+        return getIconWithOverrides(info.getApplicationInfo().packageName, info.getUser(), iconDpi,
+                () -> info.getIcon(iconDpi));
     }
 
     /**
      * Loads the icon for the provided activity info
      */
     public Drawable getIcon(ActivityInfo info) {
-        return getIcon(info.applicationInfo.packageName,
-                UserHandle.getUserHandleForUid(info.applicationInfo.uid),
-                info, mContext.getPackageManager(),
-                AI_LOADER);
+        return getIcon(info, mContext.getResources().getConfiguration().densityDpi);
     }
 
-    private <T, P> Drawable getIcon(String packageName, UserHandle user, T obj, P param,
-            BiFunction<T, P, Drawable> loader) {
+    /**
+     * Loads the icon for the provided activity info
+     */
+    public Drawable getIcon(ActivityInfo info, int iconDpi) {
+        return getIconWithOverrides(info.applicationInfo.packageName,
+                UserHandle.getUserHandleForUid(info.applicationInfo.uid),
+                iconDpi, () -> loadActivityInfoIcon(info, iconDpi));
+    }
+
+    private Drawable getIconWithOverrides(String packageName, UserHandle user, int iconDpi,
+            Supplier<Drawable> fallback) {
         Drawable icon = null;
         if (mCalendar != null && mCalendar.getPackageName().equals(packageName)) {
-            icon = loadCalendarDrawable(0);
+            icon = loadCalendarDrawable(iconDpi);
         } else if (mClock != null
                 && mClock.getPackageName().equals(packageName)
                 && Process.myUserHandle().equals(user)) {
-            icon = loadClockDrawable(0);
+            icon = loadClockDrawable(iconDpi);
         }
-        return icon == null ? loader.apply(obj, param) : icon;
+        return icon == null ? fallback.get() : icon;
+    }
+
+
+    private Drawable loadActivityInfoIcon(ActivityInfo ai, int density) {
+        final int iconRes = ai.getIconResource();
+        Drawable icon = null;
+        // Get the preferred density icon from the app's resources
+        if (density != 0 && iconRes != 0) {
+            try {
+                final Resources resources = mContext.getPackageManager()
+                        .getResourcesForApplication(ai.applicationInfo);
+                icon = resources.getDrawableForDensity(iconRes, density);
+            } catch (NameNotFoundException | Resources.NotFoundException exc) { }
+        }
+        // Get the default density icon
+        if (icon == null) {
+            icon = ai.loadIcon(mContext.getPackageManager());
+        }
+        return icon;
     }
 
     private Drawable loadCalendarDrawable(int iconDpi) {
@@ -203,7 +206,6 @@
         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
diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java b/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java
index 5587a64..59ee136 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java
@@ -32,7 +32,6 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteException;
 import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.Handler;
@@ -49,8 +48,6 @@
 
 import com.android.launcher3.icons.BaseIconFactory;
 import com.android.launcher3.icons.BitmapInfo;
-import com.android.launcher3.icons.BitmapRenderer;
-import com.android.launcher3.icons.GraphicsUtils;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.SQLiteCacheHelper;
 
@@ -94,7 +91,6 @@
     protected String mSystemState = "";
 
     private final String mDbFileName;
-    private final BitmapFactory.Options mDecodeOptions;
     private final Looper mBgLooper;
 
     public BaseIconCache(Context context, String dbFileName, Looper bgLooper,
@@ -122,13 +118,6 @@
             };
         }
 
-        if (BitmapRenderer.USE_HARDWARE_BITMAP && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-            mDecodeOptions = new BitmapFactory.Options();
-            mDecodeOptions.inPreferredConfig = Bitmap.Config.HARDWARE;
-        } else {
-            mDecodeOptions = null;
-        }
-
         updateSystemState();
         mIconDpi = iconDpi;
         mIconDb = new IconDB(context, dbFileName, iconPixelSize);
@@ -492,10 +481,10 @@
                 if (!lowRes) {
                     byte[] data = c.getBlob(2);
                     try {
-                        entry.bitmap = BitmapInfo.of(
-                                BitmapFactory.decodeByteArray(data, 0, data.length, mDecodeOptions),
-                                entry.bitmap.color);
-                    } catch (Exception e) { }
+                        entry.bitmap = BitmapInfo.fromByteArray(data, entry.bitmap.color);
+                    } catch (Exception e) {
+                        return false;
+                    }
                 }
                 return true;
             }
@@ -564,8 +553,7 @@
     private ContentValues newContentValues(BitmapInfo bitmapInfo, String label,
             String packageName, @Nullable String keywords) {
         ContentValues values = new ContentValues();
-        values.put(IconDB.COLUMN_ICON,
-                bitmapInfo.isLowRes() ? null : GraphicsUtils.flattenBitmap(bitmapInfo.icon));
+        values.put(IconDB.COLUMN_ICON, bitmapInfo.toByteArray());
         values.put(IconDB.COLUMN_ICON_COLOR, bitmapInfo.color);
 
         values.put(IconDB.COLUMN_LABEL, label);