Merge "Don't update everything when only refreshrate changes"
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 5e8db69..d2ac7c1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -113,6 +113,11 @@
         return !mTaskbarLauncherStateController.isAnimatingToLauncher();
     }
 
+    public void setShouldDelayLauncherStateAnim(boolean shouldDelayLauncherStateAnim) {
+        mTaskbarLauncherStateController.setShouldDelayLauncherStateAnim(
+                shouldDelayLauncherStateAnim);
+    }
+
     /**
      * Should be called from onResume() and onPause(), and animates the Taskbar accordingly.
      */
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 7e4fa08..224c05e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -48,6 +48,7 @@
 import android.graphics.Region.Op;
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.PaintDrawable;
+import android.inputmethodservice.InputMethodService;
 import android.util.Property;
 import android.view.Gravity;
 import android.view.MotionEvent;
@@ -591,6 +592,11 @@
             return;
         }
 
+        if (InputMethodService.canImeRenderGesturalNavButtons() && mContext.isGestureNav()) {
+            // IME is rendering the nav buttons, so we don't need to create a new layer for them.
+            return;
+        }
+
         mSeparateWindowParent.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
             @Override
             public void onViewAttachedToWindow(View view) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index ec685b6..e37bd21 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -256,6 +256,10 @@
         return mNavMode == Mode.THREE_BUTTONS;
     }
 
+    public boolean isGestureNav() {
+        return mNavMode == Mode.NO_BUTTON;
+    }
+
     public int getLeftCornerRadius() {
         return mLeftCorner == null ? 0 : mLeftCorner.getRadius();
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 30f2073..ebe6a04 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -74,6 +74,8 @@
     private boolean mIsAnimatingToLauncherViaGesture;
     private boolean mIsAnimatingToLauncherViaResume;
 
+    private boolean mShouldDelayLauncherStateAnim;
+
     private final StateManager.StateListener<LauncherState> mStateListener =
             new StateManager.StateListener<LauncherState>() {
 
@@ -86,7 +88,9 @@
                         mLauncherState = toState;
                     }
                     updateStateForFlag(FLAG_TRANSITION_STATE_RUNNING, true);
-                    applyState();
+                    if (!mShouldDelayLauncherStateAnim) {
+                        applyState();
+                    }
                 }
 
                 @Override
@@ -159,6 +163,15 @@
         return mIsAnimatingToLauncherViaResume || mIsAnimatingToLauncherViaGesture;
     }
 
+    public void setShouldDelayLauncherStateAnim(boolean shouldDelayLauncherStateAnim) {
+        if (!shouldDelayLauncherStateAnim && mShouldDelayLauncherStateAnim) {
+            // Animate the animation we have delayed immediately. This is usually triggered when
+            // the user has released their finger.
+            applyState();
+        }
+        mShouldDelayLauncherStateAnim = shouldDelayLauncherStateAnim;
+    }
+
     /**
      * Updates the proper flag to change the state of the task bar.
      *
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
index ef6f53e..7ec1243 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
@@ -18,6 +18,7 @@
 
 import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
 import static com.android.launcher3.LauncherAnimUtils.newCancelListener;
+import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.HINT_STATE;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.OVERVIEW;
@@ -33,11 +34,13 @@
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
 
+import com.android.launcher3.BaseQuickstepLauncher;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.states.StateAnimationConfig;
+import com.android.launcher3.taskbar.LauncherTaskbarUIController;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.util.AnimatorControllerWithResistance;
 import com.android.quickstep.util.MotionPauseDetector;
@@ -109,6 +112,14 @@
 
     @Override
     public void onDragStart(boolean start, float startDisplacement) {
+        if (mLauncher.isInState(ALL_APPS)) {
+            LauncherTaskbarUIController controller =
+                    ((BaseQuickstepLauncher) mLauncher).getTaskbarUIController();
+            if (controller != null) {
+                controller.setShouldDelayLauncherStateAnim(true);
+            }
+        }
+
         super.onDragStart(start, startDisplacement);
 
         mMotionPauseDetector.clear();
@@ -139,6 +150,12 @@
 
     @Override
     public void onDragEnd(float velocity) {
+        LauncherTaskbarUIController controller =
+                ((BaseQuickstepLauncher) mLauncher).getTaskbarUIController();
+        if (controller != null) {
+            controller.setShouldDelayLauncherStateAnim(false);
+        }
+
         if (mStartedOverview) {
             goToOverviewOrHomeOnDragEnd(velocity);
         } else {
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index bb03b91..d348602 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -238,27 +238,35 @@
 
         isScalableGrid = inv.isScalable && !isVerticalBarLayout() && !isMultiWindowMode;
 
-        // Determine sizes.
-        widthPx = windowBounds.bounds.width();
-        heightPx = windowBounds.bounds.height();
-        availableWidthPx = windowBounds.availableSize.x;
-        availableHeightPx = windowBounds.availableSize.y;
-
+        // Determine device posture.
         mInfo = info;
         isTablet = info.isTablet(windowBounds);
         isPhone = !isTablet;
         isTwoPanels = isTablet && useTwoPanels;
+        isTaskbarPresent = isTablet && ApiWrapper.TASKBAR_DRAWN_IN_PROCESS
+                && FeatureFlags.ENABLE_TASKBAR.get();
 
-
-        aspectRatio = ((float) Math.max(widthPx, heightPx)) / Math.min(widthPx, heightPx);
-        boolean isTallDevice = Float.compare(aspectRatio, TALL_DEVICE_ASPECT_RATIO_THRESHOLD) >= 0;
-        mQsbCenterFactor = context.getResources().getFloat(R.dimen.qsb_center_factor);
-        // Some more constants
+        // Some more constants.
         context = getContext(context, info, isVerticalBarLayout()
                 ? Configuration.ORIENTATION_LANDSCAPE
                 : Configuration.ORIENTATION_PORTRAIT);
-        mMetrics = context.getResources().getDisplayMetrics();
         final Resources res = context.getResources();
+        mMetrics = res.getDisplayMetrics();
+
+        // Determine sizes.
+        widthPx = windowBounds.bounds.width();
+        heightPx = windowBounds.bounds.height();
+        availableWidthPx = windowBounds.availableSize.x;
+        int taskbarInset = isTaskbarPresent
+                ? ResourceUtils.getNavbarSize(
+                        isLandscape ? "navigation_bar_height_landscape" : "navigation_bar_height",
+                        res)
+                : 0;
+        availableHeightPx =  windowBounds.availableSize.y - taskbarInset;
+
+        aspectRatio = ((float) Math.max(widthPx, heightPx)) / Math.min(widthPx, heightPx);
+        boolean isTallDevice = Float.compare(aspectRatio, TALL_DEVICE_ASPECT_RATIO_THRESHOLD) >= 0;
+        mQsbCenterFactor = res.getFloat(R.dimen.qsb_center_factor);
 
         if (isTwoPanels) {
             if (isLandscape) {
@@ -274,8 +282,6 @@
             }
         }
 
-        isTaskbarPresent = isTablet && ApiWrapper.TASKBAR_DRAWN_IN_PROCESS
-                && FeatureFlags.ENABLE_TASKBAR.get();
         if (isTaskbarPresent) {
             taskbarSize = res.getDimensionPixelSize(R.dimen.taskbar_size);
         }
diff --git a/src/com/android/launcher3/allapps/AppInfoComparator.java b/src/com/android/launcher3/allapps/AppInfoComparator.java
index 823f98e..311a40e 100644
--- a/src/com/android/launcher3/allapps/AppInfoComparator.java
+++ b/src/com/android/launcher3/allapps/AppInfoComparator.java
@@ -43,7 +43,9 @@
     @Override
     public int compare(AppInfo a, AppInfo b) {
         // Order by the title in the current locale
-        int result = mLabelComparator.compare(a.title.toString(), b.title.toString());
+        int result = mLabelComparator.compare(
+                a.title == null ? "" : a.title.toString(),
+                b.title == null ? "" : b.title.toString());
         if (result != 0) {
             return result;
         }
diff --git a/src/com/android/launcher3/compat/AlphabeticIndexCompat.java b/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
index 46c9006..4f8d53e 100644
--- a/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
+++ b/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
@@ -4,12 +4,12 @@
 import android.icu.text.AlphabeticIndex;
 import android.os.LocaleList;
 
+import androidx.annotation.NonNull;
+
 import com.android.launcher3.Utilities;
 
 import java.util.Locale;
 
-import androidx.annotation.NonNull;
-
 public class AlphabeticIndexCompat {
 
     private static final String MID_DOT = "\u2219";
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index a0ab56b..cd168a2 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -135,12 +135,12 @@
 
     public static final BooleanFlag ENABLE_BULK_WORKSPACE_ICON_LOADING = getDebugFlag(
             "ENABLE_BULK_WORKSPACE_ICON_LOADING",
-            false,
+            true,
             "Enable loading workspace icons in bulk.");
 
     public static final BooleanFlag ENABLE_BULK_ALL_APPS_ICON_LOADING = getDebugFlag(
             "ENABLE_BULK_ALL_APPS_ICON_LOADING",
-            false,
+            true,
             "Enable loading all apps icons in bulk.");
 
     // Keep as DeviceFlag for remote disable in emergency.
diff --git a/src/com/android/launcher3/folder/FolderNameProvider.java b/src/com/android/launcher3/folder/FolderNameProvider.java
index 9c1b24d..3d3a96d 100644
--- a/src/com/android/launcher3/folder/FolderNameProvider.java
+++ b/src/com/android/launcher3/folder/FolderNameProvider.java
@@ -121,7 +121,8 @@
         if (packageNames.size() == 1) {
             Optional<AppInfo> info = getAppInfoByPackageName(packageNames.iterator().next());
             // Place it as first viable suggestion and shift everything else
-            info.ifPresent(i -> setAsFirstSuggestion(nameInfos, i.title.toString()));
+            info.ifPresent(i -> setAsFirstSuggestion(
+                    nameInfos, i.title == null ? "" : i.title.toString()));
         }
         if (DEBUG) {
             Log.d(TAG, "getSuggestedFolderName:" + nameInfos.toString());
diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java
index dbed9a9..b8c9762 100644
--- a/src/com/android/launcher3/model/AllAppsList.java
+++ b/src/com/android/launcher3/model/AllAppsList.java
@@ -143,6 +143,8 @@
         if (loadIcon) {
             mIconCache.getTitleAndIcon(info, activityInfo, false /* useLowResIcon */);
             info.sectionName = mIndex.computeSectionName(info.title);
+        } else {
+            info.title = "";
         }
 
         data.add(info);
@@ -167,6 +169,8 @@
         if (loadIcon) {
             mIconCache.getTitleAndIcon(promiseAppInfo, promiseAppInfo.usingLowResIcon());
             promiseAppInfo.sectionName = mIndex.computeSectionName(promiseAppInfo.title);
+        } else {
+            promiseAppInfo.title = "";
         }
 
         data.add(promiseAppInfo);
diff --git a/src/com/android/launcher3/model/data/IconRequestInfo.java b/src/com/android/launcher3/model/data/IconRequestInfo.java
index 5dc6a3b..fbf01e5 100644
--- a/src/com/android/launcher3/model/data/IconRequestInfo.java
+++ b/src/com/android/launcher3/model/data/IconRequestInfo.java
@@ -75,7 +75,10 @@
         this.useLowResIcon = useLowResIcon;
     }
 
-    /** Loads  */
+    /**
+     * Loads this request's item info's title. This method should only be used on IconRequestInfos
+     * for WorkspaceItemInfos.
+     */
     public boolean loadWorkspaceIcon(Context context) {
         if (!(itemInfo instanceof WorkspaceItemInfo)) {
             throw new IllegalStateException(
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 3e98983..5afbee2 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -134,8 +134,6 @@
 
         String result;
         if (sDumpWasGenerated) {
-            Log.d("b/195319692", "dump has already been generated by another test",
-                    new Exception());
             result = "dump has already been generated by another test";
         } else {
             try {
@@ -150,7 +148,6 @@
                             "am dumpheap " + device.getLauncherPackageName() + " " + fileName);
                 }
                 sDumpWasGenerated = true;
-                Log.d("b/195319692", "sDumpWasGenerated := true", new Exception());
                 result = "saved memory dump as an artifact";
             } catch (Throwable e) {
                 Log.e(TAG, "dumpHprofData failed", e);