Adding utility method to get adaptive icon scale

Change-Id: I5ff190c3b794bb13309375782ccd420e85b59091
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 3e7f67b..819a551 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -42,7 +42,7 @@
 import android.view.Display;
 import android.view.WindowManager;
 
-import com.android.launcher3.folder.FolderShape;
+import com.android.launcher3.graphics.IconShape;
 import com.android.launcher3.util.ConfigMonitor;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.MainThreadInitializedObject;
@@ -304,7 +304,7 @@
             changeFlags |= CHANGE_FLAG_ICON_PARAMS;
         }
         if (!iconShapePath.equals(oldProfile.iconShapePath)) {
-            FolderShape.init(context);
+            IconShape.init(context);
         }
 
         apply(context, changeFlags);
diff --git a/src/com/android/launcher3/MainProcessInitializer.java b/src/com/android/launcher3/MainProcessInitializer.java
index 93df025..95ee687 100644
--- a/src/com/android/launcher3/MainProcessInitializer.java
+++ b/src/com/android/launcher3/MainProcessInitializer.java
@@ -19,7 +19,7 @@
 import android.content.Context;
 
 import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.folder.FolderShape;
+import com.android.launcher3.graphics.IconShape;
 import com.android.launcher3.logging.FileLog;
 import com.android.launcher3.util.ResourceBasedOverride;
 
@@ -38,6 +38,6 @@
         FileLog.setDir(context.getApplicationContext().getFilesDir());
         FeatureFlags.initialize(context);
         SessionCommitReceiver.applyDefaultUserPrefs(context);
-        FolderShape.init(context);
+        IconShape.init(context);
     }
 }
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index 2461e28..2450039 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -19,7 +19,7 @@
 import static com.android.launcher3.BubbleTextView.TEXT_ALPHA_PROPERTY;
 import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
 import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
-import static com.android.launcher3.folder.FolderShape.getShape;
+import static com.android.launcher3.graphics.IconShape.getShape;
 import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
 
 import android.animation.Animator;
diff --git a/src/com/android/launcher3/folder/PreviewBackground.java b/src/com/android/launcher3/folder/PreviewBackground.java
index 46df77a..09e8276 100644
--- a/src/com/android/launcher3/folder/PreviewBackground.java
+++ b/src/com/android/launcher3/folder/PreviewBackground.java
@@ -16,7 +16,7 @@
 
 package com.android.launcher3.folder;
 
-import static com.android.launcher3.folder.FolderShape.getShape;
+import static com.android.launcher3.graphics.IconShape.getShape;
 import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
 
 import android.animation.Animator;
@@ -311,7 +311,7 @@
 
     public Path getClipPath() {
         mPath.reset();
-        getShape().addShape(mPath, getOffsetX(), getOffsetY(), getScaledRadius());
+        getShape().addToPath(mPath, getOffsetX(), getOffsetY(), getScaledRadius());
         return mPath;
     }
 
diff --git a/src/com/android/launcher3/graphics/DrawableFactory.java b/src/com/android/launcher3/graphics/DrawableFactory.java
index ce83a17..c9566cb 100644
--- a/src/com/android/launcher3/graphics/DrawableFactory.java
+++ b/src/com/android/launcher3/graphics/DrawableFactory.java
@@ -16,15 +16,15 @@
 
 package com.android.launcher3.graphics;
 
+import static com.android.launcher3.graphics.IconShape.getShapePath;
+
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
-import android.graphics.Path;
 import android.graphics.Rect;
-import android.graphics.drawable.AdaptiveIconDrawable;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Process;
@@ -34,7 +34,6 @@
 import com.android.launcher3.FastBitmapDrawable;
 import com.android.launcher3.ItemInfoWithIcon;
 import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
 import com.android.launcher3.icons.BitmapInfo;
 import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.util.ResourceBasedOverride;
@@ -47,16 +46,8 @@
 public class DrawableFactory implements ResourceBasedOverride {
 
     public static final MainThreadInitializedObject<DrawableFactory> INSTANCE =
-            new MainThreadInitializedObject<>(c -> {
-                DrawableFactory factory = Overrides.getObject(DrawableFactory.class,
-                        c.getApplicationContext(), R.string.drawable_factory_class);
-                factory.mContext = c;
-                return factory;
-            });
-
-
-    private Context mContext;
-    private Path mPreloadProgressPath;
+            new MainThreadInitializedObject<>(c -> Overrides.getObject(DrawableFactory.class,
+                        c.getApplicationContext(), R.string.drawable_factory_class));
 
     protected final UserHandle mMyUser = Process.myUserHandle();
     protected final ArrayMap<UserHandle, Bitmap> mUserBadges = new ArrayMap<>();
@@ -66,7 +57,7 @@
      */
     public FastBitmapDrawable newIcon(Context context, ItemInfoWithIcon info) {
         FastBitmapDrawable drawable = info.usingLowResIcon()
-                ? new PlaceHolderIconDrawable(info, getPreloadProgressPath(), context)
+                ? new PlaceHolderIconDrawable(info, getShapePath(), context)
                 : new FastBitmapDrawable(info);
         drawable.setIsDisabled(info.isDisabled());
         return drawable;
@@ -74,7 +65,7 @@
 
     public FastBitmapDrawable newIcon(Context context, BitmapInfo info, ActivityInfo target) {
         return info.isLowRes()
-                ? new PlaceHolderIconDrawable(info, getPreloadProgressPath(), context)
+                ? new PlaceHolderIconDrawable(info, getShapePath(), context)
                 : new FastBitmapDrawable(info);
     }
 
@@ -82,29 +73,7 @@
      * Returns a FastBitmapDrawable with the icon.
      */
     public PreloadIconDrawable newPendingIcon(Context context, ItemInfoWithIcon info) {
-        return new PreloadIconDrawable(info, getPreloadProgressPath(), context);
-    }
-
-    protected Path getPreloadProgressPath() {
-        if (mPreloadProgressPath != null) {
-            return mPreloadProgressPath;
-        }
-        if (Utilities.ATLEAST_OREO) {
-            // Load the path from Mask Icon
-            AdaptiveIconDrawable icon = (AdaptiveIconDrawable)
-                    mContext.getDrawable(R.drawable.adaptive_icon_drawable_wrapper);
-            icon.setBounds(0, 0,
-                    PreloadIconDrawable.PATH_SIZE, PreloadIconDrawable.PATH_SIZE);
-            mPreloadProgressPath = icon.getIconMask();
-        } else {
-
-            // Create a circle static from top center and going clockwise.
-            Path p = new Path();
-            p.moveTo(PreloadIconDrawable.PATH_SIZE / 2, 0);
-            p.addArc(0, 0, PreloadIconDrawable.PATH_SIZE, PreloadIconDrawable.PATH_SIZE, -90, 360);
-            mPreloadProgressPath = p;
-        }
-        return mPreloadProgressPath;
+        return new PreloadIconDrawable(info, getShapePath(), context);
     }
 
     /**
diff --git a/src/com/android/launcher3/folder/FolderShape.java b/src/com/android/launcher3/graphics/IconShape.java
similarity index 86%
rename from src/com/android/launcher3/folder/FolderShape.java
rename to src/com/android/launcher3/graphics/IconShape.java
index ec6078e..88e4452 100644
--- a/src/com/android/launcher3/folder/FolderShape.java
+++ b/src/com/android/launcher3/graphics/IconShape.java
@@ -13,7 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.launcher3.folder;
+package com.android.launcher3.graphics;
+
+import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -31,7 +33,6 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.graphics.Region.Op;
-import android.graphics.RegionIterator;
 import android.graphics.drawable.AdaptiveIconDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.os.Build;
@@ -45,6 +46,8 @@
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
+import com.android.launcher3.icons.GraphicsUtils;
+import com.android.launcher3.icons.IconNormalizer;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.views.ClipPathView;
@@ -59,22 +62,39 @@
 import androidx.annotation.Nullable;
 
 /**
- * Abstract representation of the shape of a folder icon
+ * Abstract representation of the shape of an icon shape
  */
-public abstract class FolderShape {
+public abstract class IconShape {
 
-    private static FolderShape sInstance = new Circle();
+    private static IconShape sInstance = new Circle();
+    private static Path sShapePath;
+    private static float sNormalizationScale = ICON_VISIBLE_AREA_FACTOR;
 
-    public static FolderShape getShape() {
+    public static final int DEFAULT_PATH_SIZE = 100;
+
+    public static IconShape getShape() {
         return sInstance;
     }
 
+    public static Path getShapePath() {
+        if (sShapePath == null) {
+            Path p = new Path();
+            getShape().addToPath(p, 0, 0, DEFAULT_PATH_SIZE * 0.5f);
+            sShapePath = p;
+        }
+        return sShapePath;
+    }
+
+    public static float getNormalizationScale() {
+        return sNormalizationScale;
+    }
+
     private SparseArray<TypedValue> mAttrs;
 
     public abstract void drawShape(Canvas canvas, float offsetX, float offsetY, float radius,
             Paint paint);
 
-    public abstract void addShape(Path path, float offsetX, float offsetY, float radius);
+    public abstract void addToPath(Path path, float offsetX, float offsetY, float radius);
 
     public abstract <T extends View & ClipPathView> Animator createRevealAnimator(T target,
             Rect startRect, Rect endRect, float endRadius, boolean isReversed);
@@ -87,7 +107,7 @@
     /**
      * Abstract shape where the reveal animation is a derivative of a round rect animation
      */
-    private static abstract class SimpleRectShape extends FolderShape {
+    private static abstract class SimpleRectShape extends IconShape {
 
         @Override
         public final <T extends View & ClipPathView> Animator createRevealAnimator(T target,
@@ -107,7 +127,7 @@
     /**
      * Abstract shape which draws using {@link Path}
      */
-    private static abstract class PathShape extends FolderShape {
+    private static abstract class PathShape extends IconShape {
 
         private final Path mTmpPath = new Path();
 
@@ -115,7 +135,7 @@
         public final void drawShape(Canvas canvas, float offsetX, float offsetY, float radius,
                 Paint paint) {
             mTmpPath.reset();
-            addShape(mTmpPath, offsetX, offsetY, radius);
+            addToPath(mTmpPath, offsetX, offsetY, radius);
             canvas.drawPath(mTmpPath, paint);
         }
 
@@ -166,7 +186,7 @@
         }
 
         @Override
-        public void addShape(Path path, float offsetX, float offsetY, float radius) {
+        public void addToPath(Path path, float offsetX, float offsetY, float radius) {
             path.addCircle(radius + offsetX, radius + offsetY, radius, Path.Direction.CW);
         }
 
@@ -196,7 +216,7 @@
         }
 
         @Override
-        public void addShape(Path path, float offsetX, float offsetY, float radius) {
+        public void addToPath(Path path, float offsetX, float offsetY, float radius) {
             float cx = radius + offsetX;
             float cy = radius + offsetY;
             float cr = radius * mRadiusRatio;
@@ -223,7 +243,7 @@
         }
 
         @Override
-        public void addShape(Path p, float offsetX, float offsetY, float r1) {
+        public void addToPath(Path p, float offsetX, float offsetY, float r1) {
             float r2 = r1 * mRadiusRatio;
             float cx = r1 + offsetX;
             float cy = r1 + offsetY;
@@ -274,7 +294,7 @@
         }
 
         @Override
-        public void addShape(Path p, float offsetX, float offsetY, float r) {
+        public void addToPath(Path p, float offsetX, float offsetY, float r) {
             float cx = r + offsetX;
             float cy = r + offsetY;
             float control = r - r * mRadiusRatio;
@@ -358,7 +378,7 @@
         pickBestShape(context);
     }
 
-    private static FolderShape getShapeDefinition(String type, float radius) {
+    private static IconShape getShapeDefinition(String type, float radius) {
         switch (type) {
             case "Circle":
                 return new Circle();
@@ -373,8 +393,8 @@
         }
     }
 
-    private static List<FolderShape> getAllShapes(Context context) {
-        ArrayList<FolderShape> result = new ArrayList<>();
+    private static List<IconShape> getAllShapes(Context context) {
+        ArrayList<IconShape> result = new ArrayList<>();
         try (XmlResourceParser parser = context.getResources().getXml(R.xml.folder_shapes)) {
 
             // Find the root tag
@@ -393,7 +413,7 @@
                 if (type == XmlPullParser.START_TAG) {
                     AttributeSet attrs = Xml.asAttributeSet(parser);
                     TypedArray a = context.obtainStyledAttributes(attrs, radiusAttr);
-                    FolderShape shape = getShapeDefinition(parser.getName(), a.getFloat(0, 1));
+                    IconShape shape = getShapeDefinition(parser.getName(), a.getFloat(0, 1));
                     a.recycle();
 
                     shape.mAttrs = Themes.createValueMap(context, attrs, keysToIgnore);
@@ -409,7 +429,7 @@
     @TargetApi(Build.VERSION_CODES.O)
     protected static void pickBestShape(Context context) {
         // Pick any large size
-        int size = 200;
+        final int size = 200;
 
         Region full = new Region(0, 0, size, size);
         Region iconR = new Region();
@@ -420,23 +440,17 @@
 
         Path shapePath = new Path();
         Region shapeR = new Region();
-        Rect tempRect = new Rect();
 
         // Find the shape with minimum area of divergent region.
         int minArea = Integer.MAX_VALUE;
-        FolderShape closestShape = null;
-        for (FolderShape shape : getAllShapes(context)) {
+        IconShape closestShape = null;
+        for (IconShape shape : getAllShapes(context)) {
             shapePath.reset();
-            shape.addShape(shapePath, 0, 0, size / 2f);
+            shape.addToPath(shapePath, 0, 0, size / 2f);
             shapeR.setPath(shapePath, full);
             shapeR.op(iconR, Op.XOR);
 
-            RegionIterator itr = new RegionIterator(shapeR);
-            int area = 0;
-
-            while (itr.next(tempRect)) {
-                area += tempRect.width() * tempRect.height();
-            }
+            int area = GraphicsUtils.getArea(shapeR);
             if (area < minArea) {
                 minArea = area;
                 closestShape = shape;
@@ -446,5 +460,10 @@
         if (closestShape != null) {
             sInstance = closestShape;
         }
+
+        // Initialize shape properties
+        drawable.setBounds(0, 0, DEFAULT_PATH_SIZE, DEFAULT_PATH_SIZE);
+        sShapePath = new Path(drawable.getIconMask());
+        sNormalizationScale = IconNormalizer.normalizeAdaptiveIcon(drawable, size, null);
     }
 }
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index d3a7955..cc4c2ef 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -17,6 +17,8 @@
 
 package com.android.launcher3.graphics;
 
+import static com.android.launcher3.graphics.IconShape.DEFAULT_PATH_SIZE;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
@@ -55,8 +57,6 @@
                 }
             };
 
-    public static final int PATH_SIZE = 100;
-
     private static final float PROGRESS_WIDTH = 7;
     private static final float PROGRESS_GAP = 2;
     private static final int MAX_PAINT_ALPHA = 255;
@@ -123,14 +123,14 @@
     protected void onBoundsChange(Rect bounds) {
         super.onBoundsChange(bounds);
         mTmpMatrix.setScale(
-                (bounds.width() - 2 * PROGRESS_WIDTH - 2 * PROGRESS_GAP) / PATH_SIZE,
-                (bounds.height() - 2 * PROGRESS_WIDTH - 2 * PROGRESS_GAP) / PATH_SIZE);
+                (bounds.width() - 2 * PROGRESS_WIDTH - 2 * PROGRESS_GAP) / DEFAULT_PATH_SIZE,
+                (bounds.height() - 2 * PROGRESS_WIDTH - 2 * PROGRESS_GAP) / DEFAULT_PATH_SIZE);
         mTmpMatrix.postTranslate(
                 bounds.left + PROGRESS_WIDTH + PROGRESS_GAP,
                 bounds.top + PROGRESS_WIDTH + PROGRESS_GAP);
 
         mProgressPath.transform(mTmpMatrix, mScaledTrackPath);
-        float scale = bounds.width() / PATH_SIZE;
+        float scale = bounds.width() / DEFAULT_PATH_SIZE;
         mProgressPaint.setStrokeWidth(PROGRESS_WIDTH * scale);
 
         mShadowBitmap = getShadowBitmap(bounds.width(), bounds.height(),
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index 020e380..e2c8c14 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -54,7 +54,7 @@
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
 import com.android.launcher3.folder.FolderIcon;
-import com.android.launcher3.folder.FolderShape;
+import com.android.launcher3.graphics.IconShape;
 import com.android.launcher3.graphics.ShiftedBitmapDrawable;
 import com.android.launcher3.icons.LauncherIcons;
 import com.android.launcher3.popup.SystemShortcut;
@@ -144,7 +144,7 @@
         mTaskCornerRadius = cornerRadius;
         if (mIsAdaptiveIcon && shapeRevealProgress >= 0) {
             if (mRevealAnimator == null) {
-                mRevealAnimator = (ValueAnimator) FolderShape.getShape().createRevealAnimator(this,
+                mRevealAnimator = (ValueAnimator) IconShape.getShape().createRevealAnimator(this,
                         mStartRevealRect, mEndRevealRect, mTaskCornerRadius / scale, !isOpening);
                 mRevealAnimator.addListener(new AnimatorListenerAdapter() {
                     @Override