Have consistent All Apps UI between grid size changes.

We build an IDP with no grid size override values. This
allows us to reference the profile measurements so that we can have a
consistent UI for areas that the grid size change should not affect.

Bug: 124967099
Change-Id: I6235862c95800d8f31dbf2de1d12b1fcf4dbd850
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 310a9e9..d66ba73 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -58,6 +58,7 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
 
 public class InvariantDeviceProfile {
 
@@ -191,54 +192,11 @@
         Point smallestSize = new Point(displayInfo.smallestSize);
         Point largestSize = new Point(displayInfo.largestSize);
 
-        ArrayList<DisplayOption> allOptions = getPredefinedDeviceProfiles(context, gridName);
         // This guarantees that width < height
         float minWidthDps = Utilities.dpiFromPx(Math.min(smallestSize.x, smallestSize.y),
                 displayInfo.metrics);
         float minHeightDps = Utilities.dpiFromPx(Math.min(largestSize.x, largestSize.y),
                 displayInfo.metrics);
-        // Sort the profiles based on the closeness to the device size
-        Collections.sort(allOptions, (a, b) ->
-                Float.compare(dist(minWidthDps, minHeightDps, a.minWidthDps, a.minHeightDps),
-                        dist(minWidthDps, minHeightDps, b.minWidthDps, b.minHeightDps)));
-        DisplayOption interpolatedDisplayOption =
-                invDistWeightedInterpolate(minWidthDps,  minHeightDps, allOptions);
-
-        GridOption closestProfile = allOptions.get(0).grid;
-        numRows = closestProfile.numRows;
-        numColumns = closestProfile.numColumns;
-        numHotseatIcons = closestProfile.numHotseatIcons;
-        defaultLayoutId = closestProfile.defaultLayoutId;
-        demoModeLayoutId = closestProfile.demoModeLayoutId;
-        numFolderRows = closestProfile.numFolderRows;
-        numFolderColumns = closestProfile.numFolderColumns;
-        numAllAppsColumns = closestProfile.numAllAppsColumns;
-
-        mExtraAttrs = closestProfile.extraAttrs;
-
-        if (!closestProfile.name.equals(gridName)) {
-            Utilities.getPrefs(context).edit()
-                    .putString(KEY_IDP_GRID_NAME, closestProfile.name).apply();
-        }
-
-        iconSize = interpolatedDisplayOption.iconSize;
-        iconShapePath = getIconShapePath(context);
-        landscapeIconSize = interpolatedDisplayOption.landscapeIconSize;
-        iconBitmapSize = ResourceUtils.pxFromDp(iconSize, displayInfo.metrics);
-        iconTextSize = interpolatedDisplayOption.iconTextSize;
-        fillResIconDpi = getLauncherIconDensity(iconBitmapSize);
-
-        if (Utilities.getPrefs(context).getBoolean(GRID_OPTIONS_PREFERENCE_KEY, false)) {
-            allAppsIconSize = interpolatedDisplayOption.allAppsIconSize;
-            allAppsIconTextSize = interpolatedDisplayOption.allAppsIconTextSize;
-        } else {
-            allAppsIconSize = iconSize;
-            allAppsIconTextSize = iconTextSize;
-        }
-
-        // If the partner customization apk contains any grid overrides, apply them
-        // Supported overrides: numRows, numColumns, iconSize
-        applyPartnerDeviceProfileOverrides(context, displayInfo.metrics);
 
         Point realSize = new Point(displayInfo.realSize);
         // The real size never changes. smallSide and largeSide will remain the
@@ -246,10 +204,64 @@
         int smallSide = Math.min(realSize.x, realSize.y);
         int largeSide = Math.max(realSize.x, realSize.y);
 
-        landscapeProfile = new DeviceProfile(context, this, smallestSize, largestSize,
-                largeSide, smallSide, true /* isLandscape */, false /* isMultiWindowMode */);
-        portraitProfile = new DeviceProfile(context, this, smallestSize, largestSize,
-                smallSide, largeSide, false /* isLandscape */, false /* isMultiWindowMode */);
+        // We want a list of all options as well as the list of filtered options. This allows us
+        // to have a consistent UI for areas that the grid size change should not affect
+        // ie. All Apps should be consistent between grid sizes.
+        ArrayList<DisplayOption> allOptions = new ArrayList<>();
+        ArrayList<DisplayOption> filteredOptions = new ArrayList<>();
+        getPredefinedDeviceProfiles(context, gridName, filteredOptions, allOptions);
+
+        if (allOptions.isEmpty() && filteredOptions.isEmpty()) {
+            throw new RuntimeException("No display option with canBeDefault=true");
+        }
+
+        // Sort the profiles based on the closeness to the device size
+        Comparator<DisplayOption> comparator = (a, b) -> Float.compare(dist(minWidthDps,
+                minHeightDps, a.minWidthDps, a.minHeightDps),
+                dist(minWidthDps, minHeightDps, b.minWidthDps, b.minHeightDps));
+
+        // Calculate the device profiles as if there is no grid override.
+        Collections.sort(allOptions, comparator);
+        DisplayOption interpolatedDisplayOption =
+                invDistWeightedInterpolate(minWidthDps,  minHeightDps, allOptions);
+        initGridOption(context, allOptions, interpolatedDisplayOption, displayInfo.metrics);
+
+        // Create IDP with no grid override values.
+        InvariantDeviceProfile originalIDP = new InvariantDeviceProfile(this);
+        originalIDP.landscapeProfile = new DeviceProfile(context, this, null, smallestSize,
+                largestSize, largeSide, smallSide, true /* isLandscape */,
+                false /* isMultiWindowMode */);
+        originalIDP.portraitProfile = new DeviceProfile(context, this, null, smallestSize,
+                largestSize, smallSide, largeSide, false /* isLandscape */,
+                false /* isMultiWindowMode */);
+
+        if (filteredOptions.isEmpty()) {
+            filteredOptions = allOptions;
+
+            landscapeProfile = originalIDP.landscapeProfile;
+            portraitProfile = originalIDP.portraitProfile;
+        } else {
+            Collections.sort(filteredOptions, comparator);
+            interpolatedDisplayOption =
+                    invDistWeightedInterpolate(minWidthDps, minHeightDps, filteredOptions);
+
+            initGridOption(context, filteredOptions, interpolatedDisplayOption,
+                    displayInfo.metrics);
+            numAllAppsColumns = originalIDP.numAllAppsColumns;
+
+            landscapeProfile = new DeviceProfile(context, this, originalIDP, smallestSize,
+                    largestSize, largeSide, smallSide, true /* isLandscape */,
+                    false /* isMultiWindowMode */);
+            portraitProfile = new DeviceProfile(context, this, originalIDP, smallestSize,
+                    largestSize, smallSide, largeSide, false /* isLandscape */,
+                    false /* isMultiWindowMode */);
+        }
+
+        GridOption closestProfile = filteredOptions.get(0).grid;
+        if (!closestProfile.name.equals(gridName)) {
+            Utilities.getPrefs(context).edit()
+                    .putString(KEY_IDP_GRID_NAME, closestProfile.name).apply();
+        }
 
         // We need to ensure that there is enough extra space in the wallpaper
         // for the intended parallax effects
@@ -267,6 +279,33 @@
         return closestProfile.name;
     }
 
+    private void initGridOption(Context context, ArrayList<DisplayOption> options,
+            DisplayOption displayOption, DisplayMetrics metrics) {
+        GridOption closestProfile = options.get(0).grid;
+        numRows = closestProfile.numRows;
+        numColumns = closestProfile.numColumns;
+        numHotseatIcons = closestProfile.numHotseatIcons;
+        defaultLayoutId = closestProfile.defaultLayoutId;
+        demoModeLayoutId = closestProfile.demoModeLayoutId;
+        numFolderRows = closestProfile.numFolderRows;
+        numFolderColumns = closestProfile.numFolderColumns;
+        numAllAppsColumns = numColumns;
+
+        mExtraAttrs = closestProfile.extraAttrs;
+
+        iconSize = displayOption.iconSize;
+        iconShapePath = getIconShapePath(context);
+        landscapeIconSize = displayOption.landscapeIconSize;
+        iconBitmapSize = ResourceUtils.pxFromDp(iconSize, metrics);
+        iconTextSize = displayOption.iconTextSize;
+        fillResIconDpi = getLauncherIconDensity(iconBitmapSize);
+
+        // If the partner customization apk contains any grid overrides, apply them
+        // Supported overrides: numRows, numColumns, iconSize
+        applyPartnerDeviceProfileOverrides(context, metrics);
+    }
+
+
     @Nullable
     public TypedValue getAttrValue(int attr) {
         return mExtraAttrs == null ? null : mExtraAttrs.get(attr);
@@ -344,7 +383,13 @@
         }
     }
 
-    static ArrayList<DisplayOption> getPredefinedDeviceProfiles(Context context, String gridName) {
+    /**
+     * @param gridName The current grid name.
+     * @param filteredOptionsOut List filled with all the filtered options based on gridName.
+     * @param allOptionsOut List filled with all the options that can be the default option.
+     */
+    static void getPredefinedDeviceProfiles(Context context, String gridName,
+            ArrayList<DisplayOption> filteredOptionsOut, ArrayList<DisplayOption> allOptionsOut) {
         ArrayList<DisplayOption> profiles = new ArrayList<>();
         try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) {
             final int depth = parser.getDepth();
@@ -371,26 +416,19 @@
             throw new RuntimeException(e);
         }
 
-        ArrayList<DisplayOption> filteredProfiles = new ArrayList<>();
         if (!TextUtils.isEmpty(gridName)) {
             for (DisplayOption option : profiles) {
                 if (gridName.equals(option.grid.name)) {
-                    filteredProfiles.add(option);
+                    filteredOptionsOut.add(option);
                 }
             }
         }
-        if (filteredProfiles.isEmpty()) {
-            // No grid found, use the default options
-            for (DisplayOption option : profiles) {
-                if (option.canBeDefault) {
-                    filteredProfiles.add(option);
-                }
+
+        for (DisplayOption option : profiles) {
+            if (option.canBeDefault) {
+                allOptionsOut.add(option);
             }
         }
-        if (filteredProfiles.isEmpty()) {
-            throw new RuntimeException("No display option with canBeDefault=true");
-        }
-        return filteredProfiles;
     }
 
     private int getLauncherIconDensity(int requiredSize) {
@@ -514,8 +552,6 @@
 
         private final int numHotseatIcons;
 
-        private final int numAllAppsColumns;
-
         private final int defaultLayoutId;
         private final int demoModeLayoutId;
 
@@ -538,8 +574,6 @@
                     R.styleable.GridDisplayOption_numFolderRows, numRows);
             numFolderColumns = a.getInt(
                     R.styleable.GridDisplayOption_numFolderColumns, numColumns);
-            numAllAppsColumns = a.getInt(
-                    R.styleable.GridDisplayOption_numAllAppsColumns, numColumns);
 
             a.recycle();
 
@@ -559,8 +593,6 @@
         private float iconSize;
         private float iconTextSize;
         private float landscapeIconSize;
-        private float allAppsIconSize;
-        private float allAppsIconTextSize;
 
         DisplayOption(GridOption grid, Context context, AttributeSet attrs) {
             this.grid = grid;
@@ -579,10 +611,6 @@
                     iconSize);
             iconTextSize = a.getFloat(R.styleable.ProfileDisplayOption_iconTextSize, 0);
 
-            allAppsIconSize = a.getFloat(R.styleable.ProfileDisplayOption_allAppsIconSize,
-                    iconSize);
-            allAppsIconTextSize = a.getFloat(R.styleable.ProfileDisplayOption_allAppsIconTextSize,
-                    iconTextSize);
             a.recycle();
         }
 
@@ -597,18 +625,14 @@
         private DisplayOption multiply(float w) {
             iconSize *= w;
             landscapeIconSize *= w;
-            allAppsIconSize *= w;
             iconTextSize *= w;
-            allAppsIconTextSize *= w;
             return this;
         }
 
         private DisplayOption add(DisplayOption p) {
             iconSize += p.iconSize;
             landscapeIconSize += p.landscapeIconSize;
-            allAppsIconSize += p.allAppsIconSize;
             iconTextSize += p.iconTextSize;
-            allAppsIconTextSize += p.allAppsIconTextSize;
             return this;
         }
     }