Merge "Log stackstrace if updateIconAlphaForHome is called after Taskbar is destroyed" into tm-qpr-dev
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index d5e8351..bd71a9f 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -289,6 +289,7 @@
 
     <!-- Transient taskbar -->
     <dimen name="transient_taskbar_size">72dp</dimen>
+    <dimen name="transient_taskbar_min_width">150dp</dimen>
     <dimen name="transient_taskbar_icon_size">48dp</dimen>
     <dimen name="transient_taskbar_margin">24dp</dimen>
     <dimen name="transient_taskbar_shadow_blur">40dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
index 5e670d294..e46e11b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
@@ -199,13 +199,6 @@
         hotseatItemInfos = mControllers.taskbarRecentAppsController
                 .updateHotseatItemInfos(hotseatItemInfos);
         mContainer.updateHotseatItems(hotseatItemInfos);
-
-        final boolean finalIsHotseatEmpty = isHotseatEmpty;
-        mControllers.runAfterInit(() -> {
-            mControllers.taskbarStashController.updateStateForFlag(
-                    TaskbarStashController.FLAG_STASHED_IN_APP_EMPTY, finalIsHotseatEmpty);
-            mControllers.taskbarStashController.applyState();
-        });
     }
 
     @Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index c95535b..2f69b07 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -72,21 +72,20 @@
     public static final int FLAG_IN_APP = 1 << 0;
     public static final int FLAG_STASHED_IN_APP_MANUAL = 1 << 1; // long press, persisted
     public static final int FLAG_STASHED_IN_SYSUI_STATE = 1 << 2; // app pinning, keyguard, etc.
-    public static final int FLAG_STASHED_IN_APP_EMPTY = 1 << 3; // no hotseat icons
-    public static final int FLAG_STASHED_IN_APP_SETUP = 1 << 4; // setup wizard and AllSetActivity
-    public static final int FLAG_STASHED_IN_APP_IME = 1 << 5; // IME is visible
-    public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 6;
-    public static final int FLAG_STASHED_IN_TASKBAR_ALL_APPS = 1 << 7; // All apps is visible.
-    public static final int FLAG_IN_SETUP = 1 << 8; // In the Setup Wizard
-    public static final int FLAG_STASHED_SMALL_SCREEN = 1 << 9; // phone screen gesture nav, stashed
-    public static final int FLAG_STASHED_IN_APP_AUTO = 1 << 10; // Autohide (transient taskbar).
+    public static final int FLAG_STASHED_IN_APP_SETUP = 1 << 3; // setup wizard and AllSetActivity
+    public static final int FLAG_STASHED_IN_APP_IME = 1 << 4; // IME is visible
+    public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 5;
+    public static final int FLAG_STASHED_IN_TASKBAR_ALL_APPS = 1 << 6; // All apps is visible.
+    public static final int FLAG_IN_SETUP = 1 << 7; // In the Setup Wizard
+    public static final int FLAG_STASHED_SMALL_SCREEN = 1 << 8; // phone screen gesture nav, stashed
+    public static final int FLAG_STASHED_IN_APP_AUTO = 1 << 9; // Autohide (transient taskbar).
 
     // If any of these flags are enabled, isInApp should return true.
     private static final int FLAGS_IN_APP = FLAG_IN_APP | FLAG_IN_SETUP;
 
     // If we're in an app and any of these flags are enabled, taskbar should be stashed.
     private static final int FLAGS_STASHED_IN_APP = FLAG_STASHED_IN_APP_MANUAL
-            | FLAG_STASHED_IN_SYSUI_STATE | FLAG_STASHED_IN_APP_EMPTY | FLAG_STASHED_IN_APP_SETUP
+            | FLAG_STASHED_IN_SYSUI_STATE | FLAG_STASHED_IN_APP_SETUP
             | FLAG_STASHED_IN_APP_IME | FLAG_STASHED_IN_TASKBAR_ALL_APPS
             | FLAG_STASHED_SMALL_SCREEN | FLAG_STASHED_IN_APP_AUTO;
 
@@ -932,7 +931,6 @@
         appendFlag(sj, flags, FLAGS_IN_APP, "FLAG_IN_APP");
         appendFlag(sj, flags, FLAG_STASHED_IN_APP_MANUAL, "FLAG_STASHED_IN_APP_MANUAL");
         appendFlag(sj, flags, FLAG_STASHED_IN_SYSUI_STATE, "FLAG_STASHED_IN_SYSUI_STATE");
-        appendFlag(sj, flags, FLAG_STASHED_IN_APP_EMPTY, "FLAG_STASHED_IN_APP_EMPTY");
         appendFlag(sj, flags, FLAG_STASHED_IN_APP_SETUP, "FLAG_STASHED_IN_APP_SETUP");
         appendFlag(sj, flags, FLAG_STASHED_IN_APP_IME, "FLAG_STASHED_IN_APP_IME");
         appendFlag(sj, flags, FLAG_IN_STASHED_LAUNCHER_STATE, "FLAG_IN_STASHED_LAUNCHER_STATE");
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
index 80f030f..a6b2a8a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
@@ -113,7 +113,8 @@
                 return;
             }
             reset();
-            if (mControllers.taskbarStashController.isTaskbarVisibleAndNotStashing()) {
+            if (mControllers.taskbarStashController.isInApp()
+                    && mControllers.taskbarStashController.isTaskbarVisibleAndNotStashing()) {
                 mControllers.taskbarEduTooltipController.maybeShowFeaturesEdu();
             }
         }));
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 38351a9..eddc278 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -88,6 +88,8 @@
 
     private View mQsb;
 
+    private float mTransientTaskbarMinWidth;
+
     public TaskbarView(@NonNull Context context) {
         this(context, null);
     }
@@ -108,6 +110,8 @@
         mIconLayoutBounds = mActivityContext.getTransientTaskbarBounds();
         Resources resources = getResources();
         mIsRtl = Utilities.isRtl(resources);
+        mTransientTaskbarMinWidth = mContext.getResources().getDimension(
+                R.dimen.transient_taskbar_min_width);
 
         int actualMargin = resources.getDimensionPixelSize(R.dimen.taskbar_icon_spacing);
         int actualIconSize = mActivityContext.getDeviceProfile().iconSizePx;
@@ -124,11 +128,9 @@
 
         mThemeIconsBackground = calculateThemeIconsBackground();
 
-        if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()
-                && !mActivityContext.getPackageManager().hasSystemFeature(FEATURE_PC)) {
+        if (!mActivityContext.getPackageManager().hasSystemFeature(FEATURE_PC)) {
             mAllAppsButton = (IconButtonView) LayoutInflater.from(context)
                     .inflate(R.layout.taskbar_all_apps_button, this, false);
-            mAllAppsButton.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
             mAllAppsButton.setScaleX(mIsRtl ? -1 : 1);
             mAllAppsButton.setForegroundTint(mActivityContext.getColor(
                     DisplayController.isTransientTaskbar(mActivityContext)
@@ -277,7 +279,8 @@
         if (mAllAppsButton != null) {
             addView(mAllAppsButton, mIsRtl ? getChildCount() : 0);
 
-            if (mTaskbarDivider != null) {
+            // if only all apps button present, don't include divider view.
+            if (mTaskbarDivider != null && getChildCount() > 1) {
                 addView(mTaskbarDivider, mIsRtl ? (getChildCount() - 1) : 1);
             }
         }
@@ -319,6 +322,11 @@
         int count = getChildCount();
         DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
         int spaceNeeded = getIconLayoutWidth();
+        // We are removing the margin from taskbar divider item in taskbar,
+        // so remove it from spacing also.
+        if (FeatureFlags.ENABLE_TASKBAR_PINNING.get() && count > 1) {
+            spaceNeeded -= mIconTouchSize;
+        }
         int navSpaceNeeded = deviceProfile.hotseatBarEndOffset;
         boolean layoutRtl = isLayoutRtl();
         int iconEnd = right - (right - left - spaceNeeded) / 2;
@@ -362,7 +370,15 @@
                 iconEnd = iconStart - mItemMarginLeftRight;
             }
         }
+
         mIconLayoutBounds.left = iconEnd;
+
+        if (mIconLayoutBounds.right - mIconLayoutBounds.left < mTransientTaskbarMinWidth) {
+            int center = mIconLayoutBounds.centerX();
+            int distanceFromCenter = (int) mTransientTaskbarMinWidth / 2;
+            mIconLayoutBounds.right = center + distanceFromCenter;
+            mIconLayoutBounds.left = center - distanceFromCenter;
+        }
     }
 
     @Override
@@ -519,6 +535,7 @@
 
     /**
      * Finds the first icon to match one of the given matchers, from highest to lowest priority.
+     *
      * @return The first match, or All Apps button if no match was found.
      */
     public View getFirstMatch(Predicate<ItemInfo>... matchers) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 9824fe0..6252e60 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -380,8 +380,7 @@
         for (int i = 0; i < mTaskbarView.getChildCount(); i++) {
             View child = mTaskbarView.getChildAt(i);
             int positionInHotseat;
-            boolean isAllAppsButton = FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()
-                    && child == mTaskbarView.getAllAppsButtonView();
+            boolean isAllAppsButton = child == mTaskbarView.getAllAppsButtonView();
             if (!mIsHotseatIconOnTopWhenAligned) {
                 // When going to home, the EMPHASIZED interpolator in TaskbarLauncherStateController
                 // plays iconAlignment to 1 really fast, therefore moving the fading towards the end
@@ -630,7 +629,7 @@
     }
 
     public static final FloatProperty<View> ICON_TRANSLATE_X =
-            new FloatProperty<View>("taskbarAligmentTranslateX") {
+            new FloatProperty<View>("taskbarAlignmentTranslateX") {
 
                 @Override
                 public void setValue(View view, float v) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
index 7a34869..4a95a8f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
@@ -20,7 +20,6 @@
 
 import com.android.launcher3.R;
 import com.android.launcher3.appprediction.PredictionRowView;
-import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.taskbar.TaskbarControllers;
@@ -54,9 +53,6 @@
 
     /** Initialize the controller. */
     public void init(TaskbarControllers controllers, boolean allAppsVisible) {
-        if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
-            return;
-        }
         mControllers = controllers;
 
         /*
@@ -70,10 +66,6 @@
 
     /** Updates the current {@link AppInfo} instances. */
     public void setApps(AppInfo[] apps, int flags) {
-        if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
-            return;
-        }
-
         mApps = apps;
         mAppsModelFlags = flags;
         if (mAppsView != null) {
@@ -91,10 +83,6 @@
 
     /** Updates the current predictions. */
     public void setPredictedApps(List<ItemInfo> predictedApps) {
-        if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
-            return;
-        }
-
         mPredictedApps = predictedApps;
         if (mAppsView != null) {
             mAppsView.getFloatingHeaderView()
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 5b40849..5ecc05a 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -1624,10 +1624,13 @@
 
         // If we are entering Overview as a result of initiating a split from somewhere else
         // (e.g. split from Home), we need to make sure the staged app is not drawn as a thumbnail.
-        int stagedTaskIdToBeRemovedFromGrid = mSplitSelectSource != null
-                ? mSplitSelectSource.alreadyRunningTaskId
-                : INVALID_TASK_ID;
-
+        int stagedTaskIdToBeRemovedFromGrid;
+        if (mSplitSelectSource != null) {
+            stagedTaskIdToBeRemovedFromGrid = mSplitSelectSource.alreadyRunningTaskId;
+            updateCurrentTaskActionsVisibility();
+        } else {
+            stagedTaskIdToBeRemovedFromGrid = INVALID_TASK_ID;
+        }
         // update the map of instance counts
         mFilterState.updateInstanceCountMap(taskGroups);
 
diff --git a/res/drawable/ic_all_apps_button.xml b/res/drawable/ic_all_apps_button.xml
index 4f0b6a8..47f2a5d 100644
--- a/res/drawable/ic_all_apps_button.xml
+++ b/res/drawable/ic_all_apps_button.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2022 The Android Open Source Project
+<!-- Copyright (C) 2023 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,43 +13,36 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="29dp"
-    android:height="28dp"
-    android:viewportWidth="29"
-    android:viewportHeight="28">
-  <group
-      android:pivotY="14.5"
-      android:pivotX="22"
-      android:scaleX=".50"
-      android:scaleY=".50">
-    <path
-        android:pathData="M4 7C3.0375 7 2.215 6.65 1.5325 5.9675C0.85 5.285 0.5 4.4625 0.5 3.5C0.5 2.5375 0.85 1.715 1.5325 1.0325C2.215 0.35 3.0375 0 4 0C4.9625 0 5.785 0.35 6.4675 1.0325C7.15 1.715 7.5 2.5375 7.5 3.5C7.5 4.4625 7.15 5.285 6.4675 5.9675C5.785 6.65 4.9625 7 4 7Z"
-        android:fillColor="@color/all_apps_button_color"/>
-    <path
-        android:pathData="M14.5 7C13.5375 7 12.715 6.65 12.0325 5.9675C11.35 5.285 11 4.4625 11 3.5C11 2.5375 11.35 1.715 12.0325 1.0325C12.715 0.35 13.5375 0 14.5 0C15.4625 0 16.285 0.35 16.9675 1.0325C17.65 1.715 18 2.5375 18 3.5C18 4.4625 17.65 5.285 16.9675 5.9675C16.285 6.65 15.4625 7 14.5 7Z"
-        android:fillColor="@color/all_apps_button_color"/>
-    <path
-        android:pathData="M25 7C24.0375 7 23.215 6.65 22.5325 5.9675C21.85 5.285 21.5 4.4625 21.5 3.5C21.5 2.5375 21.85 1.715 22.5325 1.0325C23.215 0.35 24.0375 0 25 0C25.9625 0 26.785 0.35 27.4675 1.0325C28.15 1.715 28.5 2.5375 28.5 3.5C28.5 4.4625 28.15 5.285 27.4675 5.9675C26.785 6.65 25.9625 7 25 7Z"
-        android:fillColor="@color/all_apps_button_color"/>
-    <path
-        android:pathData="M4 17.5C3.0375 17.5 2.215 17.15 1.5325 16.4675C0.85 15.785 0.5 14.9625 0.5 14C0.5 13.0375 0.85 12.215 1.5325 11.5325C2.215 10.85 3.0375 10.5 4 10.5C4.9625 10.5 5.785 10.85 6.4675 11.5325C7.15 12.215 7.5 13.0375 7.5 14C7.5 14.9625 7.15 15.785 6.4675 16.4675C5.785 17.15 4.9625 17.5 4 17.5Z"
-        android:fillColor="@color/all_apps_button_color"/>
-    <path
-        android:pathData="M14.5 17.5C13.5375 17.5 12.715 17.15 12.0325 16.4675C11.35 15.785 11 14.9625 11 14C11 13.0375 11.35 12.215 12.0325 11.5325C12.715 10.85 13.5375 10.5 14.5 10.5C15.4625 10.5 16.285 10.85 16.9675 11.5325C17.65 12.215 18 13.0375 18 14C18 14.9625 17.65 15.785 16.9675 16.4675C16.285 17.15 15.4625 17.5 14.5 17.5Z"
-        android:fillColor="@color/all_apps_button_color"/>
-    <path
-        android:pathData="M25 17.5C24.0375 17.5 23.215 17.15 22.5325 16.4675C21.85 15.785 21.5 14.9625 21.5 14C21.5 13.0375 21.85 12.215 22.5325 11.5325C23.215 10.85 24.0375 10.5 25 10.5C25.9625 10.5 26.785 10.85 27.4675 11.5325C28.15 12.215 28.5 13.0375 28.5 14C28.5 14.9625 28.15 15.785 27.4675 16.4675C26.785 17.15 25.9625 17.5 25 17.5Z"
-        android:fillColor="@color/all_apps_button_color"/>
-    <path
-        android:pathData="M4 28C3.0375 28 2.215 27.65 1.5325 26.9675C0.85 26.285 0.5 25.4625 0.5 24.5C0.5 23.5375 0.85 22.715 1.5325 22.0325C2.215 21.35 3.0375 21 4 21C4.9625 21 5.785 21.35 6.4675 22.0325C7.15 22.715 7.5 23.5375 7.5 24.5C7.5 25.4625 7.15 26.285 6.4675 26.9675C5.785 27.65 4.9625 28 4 28Z"
-        android:fillColor="@color/all_apps_button_color"/>
-    <path
-        android:pathData="M14.5 28C13.5375 28 12.715 27.65 12.0325 26.9675C11.35 26.285 11 25.4625 11 24.5C11 23.5375 11.35 22.715 12.0325 22.0325C12.715 21.35 13.5375 21 14.5 21C15.4625 21 16.285 21.35 16.9675 22.0325C17.65 22.715 18 23.5375 18 24.5C18 25.4625 17.65 26.285 16.9675 26.9675C16.285 27.65 15.4625 28 14.5 28Z"
-        android:fillColor="@color/all_apps_button_color"/>
-    <path
-        android:pathData="M25 28C24.0375 28 23.215 27.65 22.5325 26.9675C21.85 26.285 21.5 25.4625 21.5 24.5C21.5 23.5375 21.85 22.715 22.5325 22.0325C23.215 21.35 24.0375 21 25 21C25.9625 21 26.785 21.35 27.4675 22.0325C28.15 22.715 28.5 23.5375 28.5 24.5C28.5 25.4625 28.15 26.285 27.4675 26.9675C26.785 27.65 25.9625 28 25 28Z"
-        android:fillColor="@color/all_apps_button_color"/>
-  </group>
+    android:width="52dp"
+    android:height="52dp"
+    android:viewportWidth="52"
+    android:viewportHeight="52">
+  <path
+      android:pathData="M15.5,19C14.538,19 13.715,18.65 13.033,17.968C12.35,17.285 12,16.462 12,15.5C12,14.538 12.35,13.715 13.033,13.033C13.715,12.35 14.538,12 15.5,12C16.462,12 17.285,12.35 17.968,13.033C18.65,13.715 19,14.538 19,15.5C19,16.462 18.65,17.285 17.968,17.968C17.285,18.65 16.462,19 15.5,19Z"
+      android:fillColor="#40484B"/>
+  <path
+      android:pathData="M26,19C25.038,19 24.215,18.65 23.532,17.968C22.85,17.285 22.5,16.462 22.5,15.5C22.5,14.538 22.85,13.715 23.532,13.033C24.215,12.35 25.038,12 26,12C26.962,12 27.785,12.35 28.468,13.033C29.15,13.715 29.5,14.538 29.5,15.5C29.5,16.462 29.15,17.285 28.468,17.968C27.785,18.65 26.962,19 26,19Z"
+      android:fillColor="#40484B"/>
+  <path
+      android:pathData="M36.5,19C35.537,19 34.715,18.65 34.033,17.968C33.35,17.285 33,16.462 33,15.5C33,14.538 33.35,13.715 34.033,13.033C34.715,12.35 35.537,12 36.5,12C37.463,12 38.285,12.35 38.967,13.033C39.65,13.715 40,14.538 40,15.5C40,16.462 39.65,17.285 38.967,17.968C38.285,18.65 37.463,19 36.5,19Z"
+      android:fillColor="#40484B"/>
+  <path
+      android:pathData="M15.5,29.5C14.538,29.5 13.715,29.15 13.033,28.468C12.35,27.785 12,26.962 12,26C12,25.038 12.35,24.215 13.033,23.532C13.715,22.85 14.538,22.5 15.5,22.5C16.462,22.5 17.285,22.85 17.968,23.532C18.65,24.215 19,25.038 19,26C19,26.962 18.65,27.785 17.968,28.468C17.285,29.15 16.462,29.5 15.5,29.5Z"
+      android:fillColor="#40484B"/>
+  <path
+      android:pathData="M26,29.5C25.038,29.5 24.215,29.15 23.532,28.468C22.85,27.785 22.5,26.962 22.5,26C22.5,25.038 22.85,24.215 23.532,23.532C24.215,22.85 25.038,22.5 26,22.5C26.962,22.5 27.785,22.85 28.468,23.532C29.15,24.215 29.5,25.038 29.5,26C29.5,26.962 29.15,27.785 28.468,28.468C27.785,29.15 26.962,29.5 26,29.5Z"
+      android:fillColor="#40484B"/>
+  <path
+      android:pathData="M36.5,29.5C35.537,29.5 34.715,29.15 34.033,28.468C33.35,27.785 33,26.962 33,26C33,25.038 33.35,24.215 34.033,23.532C34.715,22.85 35.537,22.5 36.5,22.5C37.463,22.5 38.285,22.85 38.967,23.532C39.65,24.215 40,25.038 40,26C40,26.962 39.65,27.785 38.967,28.468C38.285,29.15 37.463,29.5 36.5,29.5Z"
+      android:fillColor="#40484B"/>
+  <path
+      android:pathData="M15.5,40C14.538,40 13.715,39.65 13.033,38.967C12.35,38.285 12,37.463 12,36.5C12,35.537 12.35,34.715 13.033,34.033C13.715,33.35 14.538,33 15.5,33C16.462,33 17.285,33.35 17.968,34.033C18.65,34.715 19,35.537 19,36.5C19,37.463 18.65,38.285 17.968,38.967C17.285,39.65 16.462,40 15.5,40Z"
+      android:fillColor="#40484B"/>
+  <path
+      android:pathData="M26,40C25.038,40 24.215,39.65 23.532,38.967C22.85,38.285 22.5,37.463 22.5,36.5C22.5,35.537 22.85,34.715 23.532,34.033C24.215,33.35 25.038,33 26,33C26.962,33 27.785,33.35 28.468,34.033C29.15,34.715 29.5,35.537 29.5,36.5C29.5,37.463 29.15,38.285 28.468,38.967C27.785,39.65 26.962,40 26,40Z"
+      android:fillColor="#40484B"/>
+  <path
+      android:pathData="M36.5,40C35.537,40 34.715,39.65 34.033,38.967C33.35,38.285 33,37.463 33,36.5C33,35.537 33.35,34.715 34.033,34.033C34.715,33.35 35.537,33 36.5,33C37.463,33 38.285,33.35 38.967,34.033C39.65,34.715 40,35.537 40,36.5C40,37.463 39.65,38.285 38.967,38.967C38.285,39.65 37.463,40 36.5,40Z"
+      android:fillColor="#40484B"/>
 </vector>
diff --git a/res/layout/widgets_bottom_sheet_content.xml b/res/layout/widgets_bottom_sheet_content.xml
index a5f72ef..b76eef7 100644
--- a/res/layout/widgets_bottom_sheet_content.xml
+++ b/res/layout/widgets_bottom_sheet_content.xml
@@ -18,7 +18,6 @@
         android:id="@+id/widgets_bottom_sheet"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:background="@drawable/bg_rounded_corner_bottom_sheet"
         android:paddingTop="@dimen/bottom_sheet_handle_margin"
         android:orientation="vertical">
         <View
diff --git a/res/layout/widgets_full_sheet.xml b/res/layout/widgets_full_sheet.xml
index e3f1fca..e31bf7a 100644
--- a/res/layout/widgets_full_sheet.xml
+++ b/res/layout/widgets_full_sheet.xml
@@ -25,7 +25,6 @@
         android:id="@+id/container"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:background="@drawable/bg_widgets_full_sheet"
         android:focusable="true"
         android:importantForAccessibility="no">
 
diff --git a/res/layout/widgets_full_sheet_large_screen.xml b/res/layout/widgets_full_sheet_large_screen.xml
index 3dbe6f5..1c0037d 100644
--- a/res/layout/widgets_full_sheet_large_screen.xml
+++ b/res/layout/widgets_full_sheet_large_screen.xml
@@ -24,7 +24,6 @@
         android:id="@+id/container"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:background="@drawable/bg_widgets_full_sheet"
         android:focusable="true"
         android:importantForAccessibility="no">
 
diff --git a/res/layout/widgets_full_sheet_paged_view.xml b/res/layout/widgets_full_sheet_paged_view.xml
index 2819b99..b02e3e3 100644
--- a/res/layout/widgets_full_sheet_paged_view.xml
+++ b/res/layout/widgets_full_sheet_paged_view.xml
@@ -47,6 +47,7 @@
         android:layout_height="wrap_content"
         android:layout_below="@id/collapse_handle"
         android:paddingBottom="0dp"
+        android:clipToOutline="true"
         android:orientation="vertical">
 
         <TextView
diff --git a/res/layout/widgets_full_sheet_paged_view_large_screen.xml b/res/layout/widgets_full_sheet_paged_view_large_screen.xml
index 6634345..edee352 100644
--- a/res/layout/widgets_full_sheet_paged_view_large_screen.xml
+++ b/res/layout/widgets_full_sheet_paged_view_large_screen.xml
@@ -53,6 +53,7 @@
             android:id="@+id/search_and_recommendations_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:clipToOutline="true"
             android:orientation="vertical">
 
             <FrameLayout
diff --git a/res/layout/widgets_full_sheet_recyclerview.xml b/res/layout/widgets_full_sheet_recyclerview.xml
index 2291943..366d2d2 100644
--- a/res/layout/widgets_full_sheet_recyclerview.xml
+++ b/res/layout/widgets_full_sheet_recyclerview.xml
@@ -31,6 +31,7 @@
         android:layout_below="@id/collapse_handle"
         android:paddingBottom="16dp"
         android:paddingHorizontal="@dimen/widget_list_horizontal_margin"
+        android:clipToOutline="true"
         android:orientation="vertical">
 
         <TextView
diff --git a/res/layout/widgets_full_sheet_recyclerview_large_screen.xml b/res/layout/widgets_full_sheet_recyclerview_large_screen.xml
index 212cd55..c6a4f62 100644
--- a/res/layout/widgets_full_sheet_recyclerview_large_screen.xml
+++ b/res/layout/widgets_full_sheet_recyclerview_large_screen.xml
@@ -38,6 +38,7 @@
             android:id="@+id/search_and_recommendations_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:clipToOutline="true"
             android:orientation="vertical">
 
             <FrameLayout
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 2c34b3f..e63b054 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -1315,23 +1315,29 @@
                     hotseatBarSizePx - hotseatBarBottomPadding - hotseatCellHeightPx;
 
             int hotseatWidth = getHotseatRequiredWidth();
-            int leftSpacing = (availableWidthPx - hotseatWidth) / 2;
-            int rightSpacing = leftSpacing;
+            int startSpacing;
+            int endSpacing;
             // Hotseat aligns to the left with nav buttons
             if (hotseatBarEndOffset > 0) {
-                leftSpacing = inlineNavButtonsEndSpacing;
-                rightSpacing = availableWidthPx - hotseatWidth - leftSpacing + hotseatBorderSpace;
+                startSpacing = inlineNavButtonsEndSpacing;
+                endSpacing = availableWidthPx - hotseatWidth - startSpacing + hotseatBorderSpace;
+            } else {
+                startSpacing = (availableWidthPx - hotseatWidth) / 2;
+                endSpacing = startSpacing;
             }
+            startSpacing += getAdditionalQsbSpace();
 
-            hotseatBarPadding.set(leftSpacing, hotseatBarTopPadding, rightSpacing,
-                    hotseatBarBottomPadding);
-
+            hotseatBarPadding.top = hotseatBarTopPadding;
+            hotseatBarPadding.bottom = hotseatBarBottomPadding;
             boolean isRtl = Utilities.isRtl(context.getResources());
             if (isRtl) {
-                hotseatBarPadding.right += getAdditionalQsbSpace();
+                hotseatBarPadding.left = endSpacing;
+                hotseatBarPadding.right = startSpacing;
             } else {
-                hotseatBarPadding.left += getAdditionalQsbSpace();
+                hotseatBarPadding.left = startSpacing;
+                hotseatBarPadding.right = endSpacing;
             }
+
         } else if (isScalableGrid) {
             int sideSpacing = (availableWidthPx - hotseatQsbWidth) / 2;
             hotseatBarPadding.set(sideSpacing,
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index 7641728..14e3fa6 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -16,10 +16,10 @@
 package com.android.launcher3.allapps;
 
 import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.SEARCH;
-import static com.android.launcher3.allapps.AllAppsTransitionController.SWIPE_ALL_APPS_TO_HOME_MIN_SCALE;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_COUNT;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB;
+import static com.android.launcher3.util.ScrollableLayoutManager.PREDICTIVE_BACK_MIN_SCALE;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -526,7 +526,7 @@
                 public void getOutline(View view, Outline outline) {
                     @Px final int bottomOffsetPx =
                             (int) (ActivityAllAppsContainerView.this.getMeasuredHeight()
-                                    * SWIPE_ALL_APPS_TO_HOME_MIN_SCALE);
+                                    * PREDICTIVE_BACK_MIN_SCALE);
                     outline.setRect(
                             0,
                             0,
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index 866932a..df383bf 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -21,7 +21,6 @@
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 
-import androidx.annotation.Px;
 import androidx.core.view.accessibility.AccessibilityEventCompat;
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
 import androidx.core.view.accessibility.AccessibilityRecordCompat;
@@ -146,19 +145,6 @@
         }
 
         /**
-         * We need to extend all apps' RecyclerView's bottom by 5% of view height to ensure extra
-         * roll(s) of app icons is rendered at the bottom, so that they can fill the bottom gap
-         * created during predictive back's scale animation from all apps to home.
-         */
-        @Override
-        protected void calculateExtraLayoutSpace(RecyclerView.State state, int[] extraLayoutSpace) {
-            super.calculateExtraLayoutSpace(state, extraLayoutSpace);
-            @Px int extraSpacePx = (int) (getHeight()
-                    * (1 - AllAppsTransitionController.SWIPE_ALL_APPS_TO_HOME_MIN_SCALE) / 2);
-            extraLayoutSpace[1] = Math.max(extraLayoutSpace[1], extraSpacePx);
-        }
-
-        /**
          * Returns the number of rows before {@param adapterPosition}, including this position
          * which should not be counted towards the collection info.
          */
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index b618724..92c017c 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -61,6 +61,7 @@
 import com.android.launcher3.util.MultiPropertyFactory;
 import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
 import com.android.launcher3.util.MultiValueAlpha;
+import com.android.launcher3.util.ScrollableLayoutManager;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.util.VibratorWrapper;
 import com.android.launcher3.views.ScrimView;
@@ -79,8 +80,7 @@
         implements StateHandler<LauncherState>, OnDeviceProfileChangeListener {
     // This constant should match the second derivative of the animator interpolator.
     public static final float INTERP_COEFF = 1.7f;
-    public static final float SWIPE_ALL_APPS_TO_HOME_MIN_SCALE = 0.9f;
-    private static final int REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS = 200;
+    public static final int REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS = 200;
 
     private static final float NAV_BAR_COLOR_FORCE_UPDATE_THRESHOLD = 0.1f;
     private static final float SWIPE_DRAG_COMMIT_THRESHOLD =
@@ -280,8 +280,9 @@
 
         float deceleratedProgress =
                 Interpolators.PREDICTIVE_BACK_DECELERATED_EASE.getInterpolation(backProgress);
-        float scaleProgress = SWIPE_ALL_APPS_TO_HOME_MIN_SCALE
-                + (1 - SWIPE_ALL_APPS_TO_HOME_MIN_SCALE) * (1 - deceleratedProgress);
+        float scaleProgress = ScrollableLayoutManager.PREDICTIVE_BACK_MIN_SCALE
+                + (1 - ScrollableLayoutManager.PREDICTIVE_BACK_MIN_SCALE)
+                * (1 - deceleratedProgress);
 
         mAllAppScale.updateValue(scaleProgress);
     }
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 7b0033d..c89a461 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -230,10 +230,6 @@
             "ENABLE_ICON_LABEL_AUTO_SCALING", true,
             "Enables scaling/spacing for icon labels to make more characters visible");
 
-    public static final BooleanFlag ENABLE_ALL_APPS_IN_TASKBAR = getDebugFlag(
-            "ENABLE_ALL_APPS_IN_TASKBAR", true,
-            "Enables accessing All Apps from the system Taskbar.");
-
     public static final BooleanFlag ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT = getDebugFlag(
             "ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT", false,
             "Enables displaying the all apps button in the hotseat.");
diff --git a/src/com/android/launcher3/util/ScrollableLayoutManager.java b/src/com/android/launcher3/util/ScrollableLayoutManager.java
index 9bc4ddc..cb6ecaa 100644
--- a/src/com/android/launcher3/util/ScrollableLayoutManager.java
+++ b/src/com/android/launcher3/util/ScrollableLayoutManager.java
@@ -20,6 +20,7 @@
 import android.view.View;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Px;
 import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 import androidx.recyclerview.widget.RecyclerView.Adapter;
@@ -31,6 +32,10 @@
  */
 public class ScrollableLayoutManager extends GridLayoutManager {
 
+    public static final float PREDICTIVE_BACK_MIN_SCALE = 0.9f;
+    private static final float EXTRA_BOTTOM_SPACE_BY_HEIGHT_PERCENT =
+            (1 - PREDICTIVE_BACK_MIN_SCALE) / 2;
+
     // keyed on item type
     protected final SparseIntArray mCachedSizes = new SparseIntArray();
 
@@ -111,6 +116,13 @@
         return adapter == null ? 0 : getItemsHeight(adapter, adapter.getItemCount());
     }
 
+    @Override
+    protected void calculateExtraLayoutSpace(RecyclerView.State state, int[] extraLayoutSpace) {
+        super.calculateExtraLayoutSpace(state, extraLayoutSpace);
+        @Px int extraSpacePx = (int) (getHeight() * EXTRA_BOTTOM_SPACE_BY_HEIGHT_PERCENT);
+        extraLayoutSpace[1] = Math.max(extraLayoutSpace[1], extraSpacePx);
+    }
+
     /**
      * Returns the sum of the height, in pixels, of this list adapter's items from index
      * 0 (inclusive) until {@code untilIndex} (exclusive). If untilIndex is same as the itemCount,
diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java
index f73347a..e2f1c04 100644
--- a/src/com/android/launcher3/views/AbstractSlideInView.java
+++ b/src/com/android/launcher3/views/AbstractSlideInView.java
@@ -17,15 +17,20 @@
 
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
 import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
 import static com.android.launcher3.LauncherAnimUtils.TABLET_BOTTOM_SHEET_SUCCESS_TRANSITION_PROGRESS;
+import static com.android.launcher3.allapps.AllAppsTransitionController.REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS;
 import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
+import static com.android.launcher3.util.ScrollableLayoutManager.PREDICTIVE_BACK_MIN_SCALE;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.Property;
 import android.view.MotionEvent;
@@ -33,10 +38,13 @@
 import android.view.ViewGroup;
 import android.view.animation.Interpolator;
 
+import androidx.annotation.FloatRange;
 import androidx.annotation.Nullable;
+import androidx.annotation.Px;
 
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.touch.BaseSwipeDetector;
 import com.android.launcher3.touch.SingleAxisSwipeDetector;
@@ -85,6 +93,10 @@
     protected @Nullable OnCloseListener mOnCloseBeginListener;
     protected List<OnCloseListener> mOnCloseListeners = new ArrayList<>();
 
+    private final AnimatedFloat mSlidInViewScale = new AnimatedFloat(this::onScaleProgressChanged);
+    private boolean mIsBackProgressing;
+    @Nullable private Drawable mContentBackground;
+
     public AbstractSlideInView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
         mActivityContext = ActivityContext.lookupContext(context);
@@ -105,6 +117,10 @@
         mColorScrim = scrimColor != -1 ? createColorScrim(context, scrimColor) : null;
     }
 
+    protected void setContentBackground(Drawable drawable) {
+        mContentBackground = drawable;
+    }
+
     protected void attachToContainer() {
         if (mColorScrim != null) {
             getPopupContainer().addView(mColorScrim);
@@ -132,6 +148,7 @@
         if (mColorScrim != null) {
             mColorScrim.setAlpha(1 - mTranslationShift);
         }
+        invalidate();
     }
 
     @Override
@@ -161,6 +178,68 @@
         return true;
     }
 
+    @Override
+    public void onBackProgressed(@FloatRange(from = 0.0, to = 1.0) float progress) {
+        super.onBackProgressed(progress);
+        float deceleratedProgress =
+                Interpolators.PREDICTIVE_BACK_DECELERATED_EASE.getInterpolation(progress);
+        mIsBackProgressing = progress > 0f;
+        mSlidInViewScale.updateValue(PREDICTIVE_BACK_MIN_SCALE
+                + (1 - PREDICTIVE_BACK_MIN_SCALE) * (1 - deceleratedProgress));
+    }
+
+    private void onScaleProgressChanged() {
+        float scaleProgress = mSlidInViewScale.value;
+        SCALE_PROPERTY.set(this, scaleProgress);
+        setClipChildren(!mIsBackProgressing);
+        mContent.setClipChildren(!mIsBackProgressing);
+        invalidate();
+    }
+
+    @Override
+    public void onBackInvoked() {
+        super.onBackInvoked();
+        animateSlideInViewToNoScale();
+    }
+
+    @Override
+    public void onBackCancelled() {
+        super.onBackCancelled();
+        animateSlideInViewToNoScale();
+    }
+
+    protected void animateSlideInViewToNoScale() {
+        mSlidInViewScale.animateToValue(1f)
+                .setDuration(REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS)
+                .start();
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        drawScaledBackground(canvas);
+        super.dispatchDraw(canvas);
+    }
+
+    /** Draw scaled background during predictive back animation. */
+    protected void drawScaledBackground(Canvas canvas) {
+        if (mContentBackground == null) {
+            return;
+        }
+        mContentBackground.setBounds(
+                mContent.getLeft(),
+                mContent.getTop() + (int) mContent.getTranslationY(),
+                mContent.getRight(),
+                mContent.getBottom() + (mIsBackProgressing ? getBottomOffsetPx() : 0));
+        mContentBackground.draw(canvas);
+    }
+
+    /** Return extra space revealed during predictive back animation. */
+    @Px
+    protected int getBottomOffsetPx() {
+        return (int) (getMeasuredHeight()
+                * (1 - PREDICTIVE_BACK_MIN_SCALE) / 2);
+    }
+
     /**
      * Returns {@code true} if the touch event is over the visible area of the bottom sheet.
      *
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index bf521cc..4099302 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -113,6 +113,7 @@
         }
         mWidgetCellHorizontalPadding = getResources().getDimensionPixelSize(
                 R.dimen.widget_cell_horizontal_padding);
+        setContentBackground(getContext().getDrawable(R.drawable.bg_rounded_corner_bottom_sheet));
     }
 
     @Override
diff --git a/src/com/android/launcher3/widget/model/WidgetListSpaceEntry.java b/src/com/android/launcher3/widget/model/WidgetListSpaceEntry.java
index 7f24905..5b1da5b 100644
--- a/src/com/android/launcher3/widget/model/WidgetListSpaceEntry.java
+++ b/src/com/android/launcher3/widget/model/WidgetListSpaceEntry.java
@@ -33,9 +33,4 @@
                 Collections.EMPTY_LIST);
         mPkgItem.title = "";
     }
-
-    @Override
-    public int getRank() {
-        return RANK_WIDGETS_TOP_SPACE;
-    }
 }
diff --git a/src/com/android/launcher3/widget/model/WidgetsListBaseEntry.java b/src/com/android/launcher3/widget/model/WidgetsListBaseEntry.java
index f09f4c6..0003b76 100644
--- a/src/com/android/launcher3/widget/model/WidgetsListBaseEntry.java
+++ b/src/com/android/launcher3/widget/model/WidgetsListBaseEntry.java
@@ -16,16 +16,11 @@
 
 package com.android.launcher3.widget.model;
 
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import androidx.annotation.IntDef;
-
 import com.android.launcher3.model.WidgetItem;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.PackageItemInfo;
 import com.android.launcher3.widget.WidgetItemComparator;
 
-import java.lang.annotation.Retention;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -48,23 +43,4 @@
         this.mWidgets =
                 items.stream().sorted(new WidgetItemComparator()).collect(Collectors.toList());
     }
-
-    /**
-     * Returns the ranking of this entry in the
-     * {@link com.android.launcher3.widget.picker.WidgetsListAdapter}.
-     *
-     * <p>Entries with smaller value should be shown first. See
-     * {@link com.android.launcher3.widget.picker.WidgetsDiffReporter} for more details.
-     */
-    @Rank
-    public abstract int getRank();
-
-    @Retention(SOURCE)
-    @IntDef({RANK_WIDGETS_TOP_SPACE, RANK_WIDGETS_LIST_HEADER, RANK_WIDGETS_LIST_CONTENT})
-    public @interface Rank {
-    }
-
-    public static final int RANK_WIDGETS_TOP_SPACE = 1;
-    public static final int RANK_WIDGETS_LIST_HEADER = 2;
-    public static final int RANK_WIDGETS_LIST_CONTENT = 3;
 }
diff --git a/src/com/android/launcher3/widget/model/WidgetsListContentEntry.java b/src/com/android/launcher3/widget/model/WidgetsListContentEntry.java
index 73b17f1..626e0b9 100644
--- a/src/com/android/launcher3/widget/model/WidgetsListContentEntry.java
+++ b/src/com/android/launcher3/widget/model/WidgetsListContentEntry.java
@@ -61,12 +61,6 @@
                 + mMaxSpanSizeInCells;
     }
 
-    @Override
-    @Rank
-    public int getRank() {
-        return RANK_WIDGETS_LIST_CONTENT;
-    }
-
     /**
      * Returns a copy of this {@link WidgetsListContentEntry} with updated
      * {@param maxSpanSizeInCells}.
diff --git a/src/com/android/launcher3/widget/model/WidgetsListHeaderEntry.java b/src/com/android/launcher3/widget/model/WidgetsListHeaderEntry.java
index bb0cf92..68f18ae 100644
--- a/src/com/android/launcher3/widget/model/WidgetsListHeaderEntry.java
+++ b/src/com/android/launcher3/widget/model/WidgetsListHeaderEntry.java
@@ -85,12 +85,6 @@
         return "Header:" + mPkgItem.packageName + ":" + mWidgets.size();
     }
 
-    @Override
-    @Rank
-    public int getRank() {
-        return RANK_WIDGETS_LIST_HEADER;
-    }
-
     public boolean isSearchEntry() {
         return mIsSearchEntry;
     }
diff --git a/src/com/android/launcher3/widget/picker/WidgetsDiffCallback.java b/src/com/android/launcher3/widget/picker/WidgetsDiffCallback.java
new file mode 100644
index 0000000..e610ea9
--- /dev/null
+++ b/src/com/android/launcher3/widget/picker/WidgetsDiffCallback.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.widget.picker;
+
+import androidx.recyclerview.widget.DiffUtil.Callback;
+
+import com.android.launcher3.widget.model.WidgetsListBaseEntry;
+
+import java.util.List;
+
+/**
+ * DiffUtil callback to compare widgets
+ */
+public class WidgetsDiffCallback extends Callback {
+
+    private final List<WidgetsListBaseEntry> mOldEntries;
+    private final List<WidgetsListBaseEntry> mNewEntries;
+
+    public WidgetsDiffCallback(
+            List<WidgetsListBaseEntry> oldEntries,
+            List<WidgetsListBaseEntry> newEntries) {
+        mOldEntries = oldEntries;
+        mNewEntries = newEntries;
+    }
+
+    @Override
+    public int getOldListSize() {
+        return mOldEntries.size();
+    }
+
+    @Override
+    public int getNewListSize() {
+        return mNewEntries.size();
+    }
+
+    @Override
+    public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
+        // Items are same if they point to the same package entry
+        WidgetsListBaseEntry oldItem = mOldEntries.get(oldItemPosition);
+        WidgetsListBaseEntry newItem = mNewEntries.get(newItemPosition);
+        return oldItem.getClass().equals(newItem.getClass())
+                && oldItem.mPkgItem.equals(newItem.mPkgItem);
+    }
+
+    @Override
+    public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
+        // Always update all entries since the icon may have changed
+        return false;
+    }
+}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsDiffReporter.java b/src/com/android/launcher3/widget/picker/WidgetsDiffReporter.java
deleted file mode 100644
index d09fe84..0000000
--- a/src/com/android/launcher3/widget/picker/WidgetsDiffReporter.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.widget.picker;
-
-import android.util.Log;
-
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.launcher3.icons.IconCache;
-import com.android.launcher3.model.data.PackageItemInfo;
-import com.android.launcher3.widget.model.WidgetsListBaseEntry;
-import com.android.launcher3.widget.model.WidgetsListContentEntry;
-import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
-import com.android.launcher3.widget.picker.WidgetsListAdapter.WidgetListBaseRowEntryComparator;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Do diff on widget's tray list items and call the {@link RecyclerView.Adapter}
- * methods accordingly.
- */
-public class WidgetsDiffReporter {
-    private static final boolean DEBUG = false;
-    private static final String TAG = "WidgetsDiffReporter";
-
-    private final IconCache mIconCache;
-    private final RecyclerView.Adapter mListener;
-
-    public WidgetsDiffReporter(IconCache iconCache, RecyclerView.Adapter listener) {
-        mIconCache = iconCache;
-        mListener = listener;
-    }
-
-    /**
-     * Notifies the difference between {@code currentEntries} & {@code newEntries} by calling the
-     * relevant {@link androidx.recyclerview.widget.RecyclerView.RecyclerViewDataObserver} methods.
-     */
-    public void process(ArrayList<WidgetsListBaseEntry> currentEntries,
-            List<WidgetsListBaseEntry> newEntries,
-            WidgetListBaseRowEntryComparator comparator) {
-        if (DEBUG) {
-            Log.d(TAG, "process oldEntries#=" + currentEntries.size()
-                    + " newEntries#=" + newEntries.size());
-        }
-        // Early exit if either of the list is empty
-        if (currentEntries.isEmpty() || newEntries.isEmpty()) {
-            // Skip if both list are empty.
-            // On rotation, we open the widget tray with empty. Then try to fetch the list again
-            // when the animation completes (which still gives empty). And we get the final result
-            // when the bind actually completes.
-            if (currentEntries.size() != newEntries.size()) {
-                currentEntries.clear();
-                currentEntries.addAll(newEntries);
-                mListener.notifyDataSetChanged();
-            }
-            return;
-        }
-        ArrayList<WidgetsListBaseEntry> orgEntries =
-                (ArrayList<WidgetsListBaseEntry>) currentEntries.clone();
-        Iterator<WidgetsListBaseEntry> orgIter = orgEntries.iterator();
-        Iterator<WidgetsListBaseEntry> newIter = newEntries.iterator();
-
-        WidgetsListBaseEntry orgRowEntry = orgIter.next();
-        WidgetsListBaseEntry newRowEntry = newIter.next();
-
-        do {
-            int diff = compareAppNameAndType(orgRowEntry, newRowEntry, comparator);
-            if (DEBUG) {
-                Log.d(TAG, String.format("diff=%d orgRowEntry (%s) newRowEntry (%s)",
-                        diff, orgRowEntry != null ? orgRowEntry.toString() : null,
-                        newRowEntry != null ? newRowEntry.toString() : null));
-            }
-            int index = -1;
-            if (diff < 0) {
-                index = currentEntries.indexOf(orgRowEntry);
-                mListener.notifyItemRemoved(index);
-                if (DEBUG) {
-                    Log.d(TAG, String.format("notifyItemRemoved called (%d)%s", index,
-                            orgRowEntry.mTitleSectionName));
-                }
-                currentEntries.remove(index);
-                orgRowEntry = orgIter.hasNext() ? orgIter.next() : null;
-            } else if (diff > 0) {
-                index = orgRowEntry != null ? currentEntries.indexOf(orgRowEntry)
-                        : currentEntries.size();
-                currentEntries.add(index, newRowEntry);
-                if (DEBUG) {
-                    Log.d(TAG, String.format("notifyItemInserted called (%d)%s", index,
-                            newRowEntry.mTitleSectionName));
-                }
-                newRowEntry = newIter.hasNext() ? newIter.next() : null;
-                mListener.notifyItemInserted(index);
-
-            } else {
-                // same app name & type but,
-                // did the icon, title, etc, change?
-                // or did the header view changed due to user interactions?
-                // or did the widget size and desc, span, etc change?
-                if (!isSamePackageItemInfo(orgRowEntry.mPkgItem, newRowEntry.mPkgItem)
-                        || hasHeaderUpdated(orgRowEntry, newRowEntry)
-                        || hasWidgetsListContentChanged(orgRowEntry, newRowEntry)) {
-                    index = currentEntries.indexOf(orgRowEntry);
-                    currentEntries.set(index, newRowEntry);
-                    mListener.notifyItemChanged(index);
-                    if (DEBUG) {
-                        Log.d(TAG, String.format("notifyItemChanged called (%d)%s", index,
-                                newRowEntry.mTitleSectionName));
-                    }
-                }
-                orgRowEntry = orgIter.hasNext() ? orgIter.next() : null;
-                newRowEntry = newIter.hasNext() ? newIter.next() : null;
-            }
-        } while(orgRowEntry != null || newRowEntry != null);
-    }
-
-    /**
-     * Compares the app name and then entry type for the given {@link WidgetsListBaseEntry}s.
-     *
-     * @Return 0 if both entries' order is the same. Negative integer if {@code newRowEntry} should
-     *         order before {@code orgRowEntry}. Positive integer if {@code orgRowEntry} should
-     *         order before {@code newRowEntry}.
-     */
-    private int compareAppNameAndType(WidgetsListBaseEntry curRow, WidgetsListBaseEntry newRow,
-            WidgetListBaseRowEntryComparator comparator) {
-        if (curRow == null && newRow == null) {
-            throw new IllegalStateException(
-                    "Cannot compare PackageItemInfo if both rows are null.");
-        }
-
-        if (curRow == null && newRow != null) {
-            return 1; // new row needs to be inserted
-        } else if (curRow != null && newRow == null) {
-            return -1; // old row needs to be deleted
-        }
-        int diff = comparator.compare(curRow, newRow);
-        if (diff == 0) {
-            return newRow.getRank() - curRow.getRank();
-        }
-        return diff;
-    }
-
-    /**
-     * Returns {@code true} if both {@code curRow} & {@code newRow} are
-     * {@link WidgetsListContentEntry}s with a different list or arrangement of widgets.
-     */
-    private boolean hasWidgetsListContentChanged(WidgetsListBaseEntry curRow,
-            WidgetsListBaseEntry newRow) {
-        if (!(curRow instanceof WidgetsListContentEntry)
-                || !(newRow instanceof WidgetsListContentEntry)) {
-            return false;
-        }
-        return !curRow.equals(newRow);
-    }
-
-    /**
-     * Returns {@code true} if {@code newRow} is {@link WidgetsListHeaderEntry} and its content has
-     * been changed due to user interactions.
-     */
-    private boolean hasHeaderUpdated(WidgetsListBaseEntry curRow, WidgetsListBaseEntry newRow) {
-        if (newRow instanceof WidgetsListHeaderEntry && curRow instanceof WidgetsListHeaderEntry) {
-            // Always refresh search header entries to reset rounded corners in their view holder.
-            return !curRow.equals(newRow) || ((WidgetsListHeaderEntry) curRow).isSearchEntry();
-        }
-        return false;
-    }
-
-    private boolean isSamePackageItemInfo(PackageItemInfo curInfo, PackageItemInfo newInfo) {
-        return curInfo.bitmap.icon.equals(newInfo.bitmap.icon)
-                && !mIconCache.isDefaultIcon(curInfo.bitmap, curInfo.user);
-    }
-}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 2ce400e..545e661 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -17,9 +17,7 @@
 
 import static android.view.View.MeasureSpec.makeMeasureSpec;
 
-import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
-import static com.android.launcher3.allapps.AllAppsTransitionController.SWIPE_ALL_APPS_TO_HOME_MIN_SCALE;
 import static com.android.launcher3.config.FeatureFlags.LARGE_SCREEN_WIDGET_PICKER;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGETSTRAY_SEARCHED;
 import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
@@ -31,6 +29,7 @@
 import android.content.pm.LauncherApps;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.Outline;
 import android.graphics.Rect;
 import android.os.Process;
 import android.os.UserHandle;
@@ -42,6 +41,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewOutlineProvider;
 import android.view.WindowInsets;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
@@ -59,10 +59,8 @@
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.compat.AccessibilityManagerCompat;
 import com.android.launcher3.model.UserManagerState;
@@ -170,6 +168,18 @@
                 }
             };
 
+    private final ViewOutlineProvider mViewOutlineProvider = new ViewOutlineProvider() {
+        @Override
+        public void getOutline(View view, Outline outline) {
+            outline.setRect(
+                    0,
+                    0,
+                    view.getMeasuredWidth(),
+                    view.getMeasuredHeight() + getBottomOffsetPx()
+            );
+        }
+    };
+
     private final int mTabsHeight;
     private final int mWidgetSheetContentHorizontalPadding;
 
@@ -195,6 +205,8 @@
     private int mOrientation;
     private @Nullable WidgetsRecyclerView mCurrentTouchEventRecyclerView;
 
+    private RecyclerViewFastScroller mFastScroller;
+
     public WidgetsFullSheet(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
         DeviceProfile dp = Launcher.getLauncher(context).getDeviceProfile();
@@ -213,6 +225,7 @@
 
         mUserManagerState.init(UserCache.INSTANCE.get(context),
                 context.getSystemService(UserManager.class));
+        setContentBackground(getContext().getDrawable(R.drawable.bg_widgets_full_sheet));
     }
 
     public WidgetsFullSheet(Context context, AttributeSet attrs) {
@@ -224,6 +237,9 @@
         super.onFinishInflate();
         mContent = findViewById(R.id.container);
 
+        mContent.setOutlineProvider(mViewOutlineProvider);
+        mContent.setClipToOutline(true);
+
         LayoutInflater layoutInflater = LayoutInflater.from(getContext());
         int contentLayoutRes = mHasWorkProfile ? R.layout.widgets_full_sheet_paged_view
                 : R.layout.widgets_full_sheet_recyclerview;
@@ -233,14 +249,17 @@
         }
         layoutInflater.inflate(contentLayoutRes, mContent, true);
 
-        RecyclerViewFastScroller fastScroller = findViewById(R.id.fast_scroller);
+        mFastScroller = findViewById(R.id.fast_scroller);
         if (mIsTwoPane) {
-            fastScroller.setVisibility(GONE);
+            mFastScroller.setVisibility(GONE);
         }
         mAdapters.get(AdapterHolder.PRIMARY).setup(findViewById(R.id.primary_widgets_list_view));
         mAdapters.get(AdapterHolder.SEARCH).setup(findViewById(R.id.search_widgets_list_view));
         if (mHasWorkProfile) {
             mViewPager = findViewById(R.id.widgets_view_pager);
+            mViewPager.setOutlineProvider(mViewOutlineProvider);
+            mViewPager.setClipToOutline(true);
+            mViewPager.setClipChildren(false);
             mViewPager.initParentViews(this);
             mViewPager.getPageIndicator().setOnActivePageChangedListener(this);
             mViewPager.getPageIndicator().setActiveMarker(AdapterHolder.PRIMARY);
@@ -349,11 +368,8 @@
 
     @Override
     public void onBackProgressed(@FloatRange(from = 0.0, to = 1.0) float progress) {
-        float deceleratedProgress =
-                Interpolators.PREDICTIVE_BACK_DECELERATED_EASE.getInterpolation(progress);
-        float scaleProgress = SWIPE_ALL_APPS_TO_HOME_MIN_SCALE
-                + (1 - SWIPE_ALL_APPS_TO_HOME_MIN_SCALE) * (1 - deceleratedProgress);
-        SCALE_PROPERTY.set(this, scaleProgress);
+        super.onBackProgressed(progress);
+        mFastScroller.setVisibility(progress > 0 ? View.INVISIBLE : View.VISIBLE);
     }
 
     private void attachScrollbarToRecyclerView(WidgetsRecyclerView recyclerView) {
@@ -859,6 +875,7 @@
     public void onBackInvoked() {
         if (mIsInSearchMode) {
             mSearchBar.reset();
+            animateSlideInViewToNoScale();
         } else {
             super.onBackInvoked();
         }
@@ -943,8 +960,6 @@
         AdapterHolder(int adapterType) {
             mAdapterType = adapterType;
             Context context = getContext();
-            LauncherAppState apps = LauncherAppState.getInstance(context);
-
             HeaderChangeListener headerChangeListener = new HeaderChangeListener() {
                 @Override
                 public void onHeaderChanged(@NonNull PackageUserKey selectedHeader) {
@@ -975,7 +990,6 @@
             mWidgetsListAdapter = new WidgetsListAdapter(
                     context,
                     LayoutInflater.from(context),
-                    apps.getIconCache(),
                     this::getEmptySpaceHeight,
                     /* iconClickListener= */ WidgetsFullSheet.this,
                     /* iconLongClickListener= */ WidgetsFullSheet.this,
@@ -1003,6 +1017,9 @@
 
         void setup(WidgetsRecyclerView recyclerView) {
             mWidgetsRecyclerView = recyclerView;
+            mWidgetsRecyclerView.setOutlineProvider(mViewOutlineProvider);
+            mWidgetsRecyclerView.setClipToOutline(true);
+            mWidgetsRecyclerView.setClipChildren(false);
             mWidgetsRecyclerView.setAdapter(mWidgetsListAdapter);
             mWidgetsRecyclerView.setItemAnimator(mWidgetsListItemAnimator);
             mWidgetsRecyclerView.setHeaderViewDimensionsProvider(WidgetsFullSheet.this);
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
index b5ff719..20b1d9b 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
@@ -32,13 +32,14 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.DiffUtil;
+import androidx.recyclerview.widget.DiffUtil.DiffResult;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 import androidx.recyclerview.widget.RecyclerView.Adapter;
 import androidx.recyclerview.widget.RecyclerView.ViewHolder;
 
 import com.android.launcher3.R;
-import com.android.launcher3.icons.IconCache;
 import com.android.launcher3.model.data.PackageItemInfo;
 import com.android.launcher3.recyclerview.ViewHolderBinder;
 import com.android.launcher3.util.LabelComparator;
@@ -82,7 +83,6 @@
     public static final int VIEW_TYPE_WIDGETS_HEADER = R.id.view_type_widgets_header;
 
     private final Context mContext;
-    private final WidgetsDiffReporter mDiffReporter;
     private final SparseArray<ViewHolderBinder> mViewHolderBinders = new SparseArray<>();
     private final WidgetListBaseRowEntryComparator mRowComparator =
             new WidgetListBaseRowEntryComparator();
@@ -102,12 +102,11 @@
     private int mMaxSpanSize = 4;
 
     public WidgetsListAdapter(Context context, LayoutInflater layoutInflater,
-            IconCache iconCache, IntSupplier emptySpaceHeightProvider,
-            OnClickListener iconClickListener, OnLongClickListener iconLongClickListener,
+            IntSupplier emptySpaceHeightProvider, OnClickListener iconClickListener,
+            OnLongClickListener iconLongClickListener,
             WidgetsFullSheet.HeaderChangeListener headerChangeListener) {
         mHeaderChangeListener = headerChangeListener;
         mContext = context;
-        mDiffReporter = new WidgetsDiffReporter(iconCache, this);
 
         mViewHolderBinders.put(
                 VIEW_TYPE_WIDGETS_LIST,
@@ -205,7 +204,11 @@
                 })
                 .collect(Collectors.toList());
 
-        mDiffReporter.process(mVisibleEntries, newVisibleEntries, mRowComparator);
+        DiffResult diffResult = DiffUtil.calculateDiff(
+                new WidgetsDiffCallback(mVisibleEntries, newVisibleEntries), false);
+        mVisibleEntries.clear();
+        mVisibleEntries.addAll(newVisibleEntries);
+        diffResult.dispatchUpdatesTo(this);
 
         if (mPendingClickHeader != null) {
             // Get the position for the clicked header after adjusting the visible entries. The
diff --git a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
index f490333..1b743e8 100644
--- a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
+++ b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
@@ -40,7 +40,6 @@
 import com.android.launcher3.widget.model.WidgetsListBaseEntry;
 import com.android.launcher3.widget.model.WidgetsListContentEntry;
 import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
-import com.android.launcher3.widget.picker.WidgetsDiffReporter;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -73,8 +72,7 @@
     /**
      * Returns a list of {@link WidgetsListBaseEntry}. All {@link WidgetItem} in a single row
      * are sorted (based on label and user), but the overall list of
-     * {@link WidgetsListBaseEntry}s is not sorted. This list is sorted at the UI when using
-     * {@link WidgetsDiffReporter}
+     * {@link WidgetsListBaseEntry}s is not sorted.
      *
      * @see com.android.launcher3.widget.picker.WidgetsListAdapter#setWidgets(List)
      */
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetsDiffReporterTest.java b/tests/src/com/android/launcher3/widget/picker/WidgetsDiffReporterTest.java
deleted file mode 100644
index 8c87957..0000000
--- a/tests/src/com/android/launcher3/widget/picker/WidgetsDiffReporterTest.java
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.widget.picker;
-
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-
-import static com.android.launcher3.util.WidgetUtils.createAppWidgetProviderInfo;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-
-import android.appwidget.AppWidgetProviderInfo;
-import android.content.ComponentName;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.os.UserHandle;
-
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.icons.BitmapInfo;
-import com.android.launcher3.icons.ComponentWithLabel;
-import com.android.launcher3.icons.IconCache;
-import com.android.launcher3.model.WidgetItem;
-import com.android.launcher3.model.data.PackageItemInfo;
-import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
-import com.android.launcher3.widget.model.WidgetsListBaseEntry;
-import com.android.launcher3.widget.model.WidgetsListContentEntry;
-import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
-import com.android.launcher3.widget.picker.WidgetsListAdapter.WidgetListBaseRowEntryComparator;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public final class WidgetsDiffReporterTest {
-    private static final String TEST_PACKAGE_PREFIX = "com.android.test";
-    private static final WidgetListBaseRowEntryComparator COMPARATOR =
-            new WidgetListBaseRowEntryComparator();
-
-    @Mock private IconCache mIconCache;
-    @Mock private RecyclerView.Adapter mAdapter;
-
-    private InvariantDeviceProfile mTestProfile;
-    private WidgetsDiffReporter mWidgetsDiffReporter;
-    private Context mContext;
-    private WidgetsListHeaderEntry mHeaderA;
-    private WidgetsListHeaderEntry mHeaderB;
-    private WidgetsListHeaderEntry mHeaderC;
-    private WidgetsListHeaderEntry mHeaderD;
-    private WidgetsListHeaderEntry mHeaderE;
-    private WidgetsListContentEntry mContentC;
-    private WidgetsListContentEntry mContentE;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mTestProfile = new InvariantDeviceProfile();
-        mTestProfile.numRows = 5;
-        mTestProfile.numColumns = 5;
-
-        doAnswer(invocation -> ((ComponentWithLabel) invocation.getArgument(0))
-                .getComponent().getPackageName())
-                .when(mIconCache).getTitleNoCache(any());
-
-        mContext = getApplicationContext();
-        mWidgetsDiffReporter = new WidgetsDiffReporter(mIconCache, mAdapter);
-        mHeaderA = createWidgetsHeaderEntry(TEST_PACKAGE_PREFIX + "A",
-                /* appName= */ "A", /* numOfWidgets= */ 3);
-        mHeaderB = createWidgetsHeaderEntry(TEST_PACKAGE_PREFIX + "B",
-                /* appName= */ "B", /* numOfWidgets= */ 3);
-        mHeaderC = createWidgetsHeaderEntry(TEST_PACKAGE_PREFIX + "C",
-                /* appName= */ "C", /* numOfWidgets= */ 3);
-        mContentC = createWidgetsContentEntry(TEST_PACKAGE_PREFIX + "C",
-                /* appName= */ "C", /* numOfWidgets= */ 3);
-        mHeaderD = createWidgetsHeaderEntry(TEST_PACKAGE_PREFIX + "D",
-                /* appName= */ "D", /* numOfWidgets= */ 3);
-        mHeaderE = createWidgetsHeaderEntry(TEST_PACKAGE_PREFIX + "E",
-                /* appName= */ "E", /* numOfWidgets= */ 3);
-        mContentE = createWidgetsContentEntry(TEST_PACKAGE_PREFIX + "E",
-                /* appName= */ "E", /* numOfWidgets= */ 3);
-    }
-
-    @Test
-    public void listNotChanged_shouldNotInvokeAnyCallbacks() {
-        // GIVEN the current list has app headers [A, B, C].
-        ArrayList<WidgetsListBaseEntry> currentList = new ArrayList<>(
-                List.of(mHeaderA, mHeaderB, mHeaderC));
-
-        // WHEN computing the list difference.
-        mWidgetsDiffReporter.process(currentList, currentList, COMPARATOR);
-
-        // THEN there is no adaptor callback.
-        verifyZeroInteractions(mAdapter);
-        // THEN the current list contains the same entries.
-        assertThat(currentList).containsExactly(mHeaderA, mHeaderB, mHeaderC);
-    }
-
-    @Test
-    public void headersOnly_emptyListToNonEmpty_shouldInvokeNotifyDataSetChanged() {
-        // GIVEN the current list has app headers [A, B, C].
-        ArrayList<WidgetsListBaseEntry> currentList = new ArrayList<>();
-
-        List<WidgetsListBaseEntry> newList = List.of(
-                createWidgetsHeaderEntry(TEST_PACKAGE_PREFIX + "A", "A", 3),
-                createWidgetsHeaderEntry(TEST_PACKAGE_PREFIX + "B", "B", 3),
-                createWidgetsHeaderEntry(TEST_PACKAGE_PREFIX + "C", "C", 3));
-
-        // WHEN computing the list difference.
-        mWidgetsDiffReporter.process(currentList, newList, COMPARATOR);
-
-        // THEN notifyDataSetChanged is called
-        verify(mAdapter).notifyDataSetChanged();
-        // THEN the current list contains all elements from the new list.
-        assertThat(currentList).containsExactlyElementsIn(newList);
-    }
-
-    @Test
-    public void headersOnly_nonEmptyToEmptyList_shouldInvokeNotifyDataSetChanged() {
-        // GIVEN the current list has app headers [A, B, C].
-        ArrayList<WidgetsListBaseEntry> currentList = new ArrayList<>(
-                List.of(mHeaderA, mHeaderB, mHeaderC));
-        // GIVEN the new list is empty.
-        List<WidgetsListBaseEntry> newList = List.of();
-
-        // WHEN computing the list difference.
-        mWidgetsDiffReporter.process(currentList, newList, COMPARATOR);
-
-        // THEN notifyDataSetChanged is called.
-        verify(mAdapter).notifyDataSetChanged();
-        // THEN the current list isEmpty.
-        assertThat(currentList).isEmpty();
-    }
-
-    @Test
-    public void headersOnly_itemAddedAndRemovedInTheNewList_shouldInvokeCorrectCallbacks() {
-        // GIVEN the current list has app headers [A, B, D].
-        ArrayList<WidgetsListBaseEntry> currentList = new ArrayList<>(
-                List.of(mHeaderA, mHeaderB, mHeaderD));
-        // GIVEN the new list has app headers [A, C, E].
-        List<WidgetsListBaseEntry> newList = List.of(mHeaderA, mHeaderC, mHeaderE);
-
-        // WHEN computing the list difference.
-        mWidgetsDiffReporter.process(currentList, newList, COMPARATOR);
-
-        // THEN "B" is removed from position 1.
-        verify(mAdapter).notifyItemRemoved(/* position= */ 1);
-        // THEN "D" is removed from position 2.
-        verify(mAdapter).notifyItemRemoved(/* position= */ 2);
-        // THEN "C" is inserted at position 1.
-        verify(mAdapter).notifyItemInserted(/* position= */ 1);
-        // THEN "E" is inserted at position 2.
-        verify(mAdapter).notifyItemInserted(/* position= */ 2);
-        // THEN the current list contains all elements from the new list.
-        assertThat(currentList).containsExactlyElementsIn(newList);
-    }
-
-    @Test
-    public void headersContentsMix_itemAddedAndRemovedInTheNewList_shouldInvokeCorrectCallbacks() {
-        // GIVEN the current list has app headers [A, B, E content].
-        ArrayList<WidgetsListBaseEntry> currentList = new ArrayList<>(
-                List.of(mHeaderA, mHeaderB, mContentE));
-        // GIVEN the new list has app headers [A, C content, D].
-        List<WidgetsListBaseEntry> newList = List.of(mHeaderA, mContentC, mHeaderD);
-
-        // WHEN computing the list difference.
-        mWidgetsDiffReporter.process(currentList, newList, COMPARATOR);
-
-        // THEN "B" is removed from position 1.
-        verify(mAdapter).notifyItemRemoved(/* position= */ 1);
-        // THEN "C content" is inserted at position 1.
-        verify(mAdapter).notifyItemInserted(/* position= */ 1);
-        // THEN "D" is inserted at position 2.
-        verify(mAdapter).notifyItemInserted(/* position= */ 2);
-        // THEN "E content" is removed from position 3.
-        verify(mAdapter).notifyItemRemoved(/* position= */ 3);
-        // THEN the current list contains all elements from the new list.
-        assertThat(currentList).containsExactlyElementsIn(newList);
-    }
-
-    @Test
-    public void headersContentsMix_userInteractWithHeader_shouldInvokeCorrectCallbacks() {
-        // GIVEN the current list has app headers [A, B, E content].
-        ArrayList<WidgetsListBaseEntry> currentList = new ArrayList<>(
-                List.of(mHeaderA, mHeaderB, mContentE));
-        // GIVEN the new list has app headers [A, B, E content] and the user has interacted with B.
-        List<WidgetsListBaseEntry> newList =
-                List.of(mHeaderA, mHeaderB.withWidgetListShown(), mContentE);
-
-        // WHEN computing the list difference.
-        mWidgetsDiffReporter.process(currentList, newList, COMPARATOR);
-
-        // THEN notify "B" has been changed.
-        verify(mAdapter).notifyItemChanged(/* position= */ 1);
-        // THEN the current list contains all elements from the new list.
-        assertThat(currentList).containsExactlyElementsIn(newList);
-    }
-
-    @Test
-    public void headersContentsMix_headerWidgetsModified_shouldInvokeCorrectCallbacks() {
-        // GIVEN the current list has app headers [A, B, E content].
-        ArrayList<WidgetsListBaseEntry> currentList = new ArrayList<>(
-                List.of(mHeaderA, mHeaderB, mContentE));
-        // GIVEN the new list has one of the headers widgets list modified.
-        List<WidgetsListBaseEntry> newList = List.of(
-                WidgetsListHeaderEntry.create(
-                        mHeaderA.mPkgItem, mHeaderA.mTitleSectionName,
-                        mHeaderA.mWidgets.subList(0, 1)),
-                mHeaderB, mContentE);
-
-        // WHEN computing the list difference.
-        mWidgetsDiffReporter.process(currentList, newList, COMPARATOR);
-
-        // THEN notify "A" has been changed.
-        verify(mAdapter).notifyItemChanged(/* position= */ 0);
-        // THEN the current list contains all elements from the new list.
-        assertThat(currentList).containsExactlyElementsIn(newList);
-    }
-
-    @Test
-    public void headersContentsMix_contentMaxSpanSizeModified_shouldInvokeCorrectCallbacks() {
-        // GIVEN the current list has app headers [A, B, E content].
-        ArrayList<WidgetsListBaseEntry> currentList = new ArrayList<>(
-                List.of(mHeaderA, mHeaderB, mContentE));
-        // GIVEN the new list has max span size in "E content" modified.
-        List<WidgetsListBaseEntry> newList = List.of(
-                mHeaderA,
-                mHeaderB,
-                new WidgetsListContentEntry(
-                        mContentE.mPkgItem,
-                        mContentE.mTitleSectionName,
-                        mContentE.mWidgets,
-                        mContentE.getMaxSpanSizeInCells() + 1));
-
-        // WHEN computing the list difference.
-        mWidgetsDiffReporter.process(currentList, newList, COMPARATOR);
-
-        // THEN notify "E content" has been changed.
-        verify(mAdapter).notifyItemChanged(/* position= */ 2);
-        // THEN the current list contains all elements from the new list.
-        assertThat(currentList).containsExactlyElementsIn(newList);
-    }
-
-
-    private WidgetsListHeaderEntry createWidgetsHeaderEntry(String packageName, String appName,
-            int numOfWidgets) {
-        List<WidgetItem> widgetItems = generateWidgetItems(packageName, numOfWidgets);
-        PackageItemInfo pInfo = createPackageItemInfo(packageName, appName,
-                widgetItems.get(0).user);
-
-        return WidgetsListHeaderEntry.create(pInfo, /* titleSectionName= */ "", widgetItems);
-    }
-
-    private WidgetsListContentEntry createWidgetsContentEntry(String packageName, String appName,
-            int numOfWidgets) {
-        List<WidgetItem> widgetItems = generateWidgetItems(packageName, numOfWidgets);
-        PackageItemInfo pInfo = createPackageItemInfo(packageName, appName,
-                widgetItems.get(0).user);
-
-        return new WidgetsListContentEntry(pInfo, /* titleSectionName= */ "", widgetItems);
-    }
-
-    private PackageItemInfo createPackageItemInfo(String packageName, String appName,
-            UserHandle userHandle) {
-        PackageItemInfo pInfo = new PackageItemInfo(packageName, userHandle);
-        pInfo.title = appName;
-        pInfo.bitmap = BitmapInfo.of(Bitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8), 0);
-        return pInfo;
-    }
-
-    private List<WidgetItem> generateWidgetItems(String packageName, int numOfWidgets) {
-        ArrayList<WidgetItem> widgetItems = new ArrayList<>();
-        for (int i = 0; i < numOfWidgets; i++) {
-            ComponentName cn = ComponentName.createRelative(packageName, ".SampleWidget" + i);
-            AppWidgetProviderInfo widgetInfo = createAppWidgetProviderInfo(cn);
-
-            WidgetItem widgetItem = new WidgetItem(
-                    LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, widgetInfo),
-                    mTestProfile, mIconCache);
-            widgetItems.add(widgetItem);
-        }
-        return widgetItems;
-    }
-}
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java b/tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java
deleted file mode 100644
index 0044d04..0000000
--- a/tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.widget.picker;
-
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isNull;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.verify;
-
-import android.appwidget.AppWidgetProviderInfo;
-import android.content.ComponentName;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.os.Process;
-import android.os.UserHandle;
-import android.view.LayoutInflater;
-
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.icons.BitmapInfo;
-import com.android.launcher3.icons.ComponentWithLabel;
-import com.android.launcher3.icons.IconCache;
-import com.android.launcher3.model.WidgetItem;
-import com.android.launcher3.model.data.PackageItemInfo;
-import com.android.launcher3.util.ActivityContextWrapper;
-import com.android.launcher3.util.PackageUserKey;
-import com.android.launcher3.util.WidgetUtils;
-import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
-import com.android.launcher3.widget.model.WidgetsListBaseEntry;
-import com.android.launcher3.widget.model.WidgetsListContentEntry;
-import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Unit tests for WidgetsListAdapter
- * Note that all indices matching are shifted by 1 to account for the empty space at the start.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public final class WidgetsListAdapterTest {
-    private static final String TEST_PACKAGE_PLACEHOLDER = "com.google.test";
-
-    @Mock private LayoutInflater mMockLayoutInflater;
-    @Mock private RecyclerView.AdapterDataObserver mListener;
-    @Mock private IconCache mIconCache;
-
-    private WidgetsListAdapter mAdapter;
-    private InvariantDeviceProfile mTestProfile;
-    private UserHandle mUserHandle;
-    private Context mContext;
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        mContext = new ActivityContextWrapper(getApplicationContext());
-        mTestProfile = new InvariantDeviceProfile();
-        mTestProfile.numRows = 5;
-        mTestProfile.numColumns = 5;
-        mUserHandle = Process.myUserHandle();
-        mAdapter = new WidgetsListAdapter(mContext, mMockLayoutInflater,
-                mIconCache, () -> 0, null, null, null);
-        mAdapter.registerAdapterDataObserver(mListener);
-
-        doAnswer(invocation -> ((ComponentWithLabel) invocation.getArgument(0))
-                        .getComponent().getPackageName())
-                .when(mIconCache).getTitleNoCache(any());
-    }
-
-    @Test
-    public void setWidgets_shouldNotifyDataSetChanged() {
-        mAdapter.setWidgets(generateSampleMap(1));
-
-        verify(mListener).onChanged();
-    }
-
-    @Test
-    public void setWidgets_withItemInserted_shouldNotifyItemInserted() {
-        mAdapter.setWidgets(generateSampleMap(1));
-        mAdapter.setWidgets(generateSampleMap(2));
-
-        verify(mListener).onItemRangeInserted(eq(2), eq(1));
-    }
-
-    @Test
-    public void setWidgets_withItemRemoved_shouldNotifyItemRemoved() {
-        mAdapter.setWidgets(generateSampleMap(2));
-        mAdapter.setWidgets(generateSampleMap(1));
-
-        verify(mListener).onItemRangeRemoved(eq(2), eq(1));
-    }
-
-    @Test
-    public void setWidgets_appIconChanged_shouldNotifyItemChanged() {
-        mAdapter.setWidgets(generateSampleMap(1));
-        mAdapter.setWidgets(generateSampleMap(1));
-
-        verify(mListener).onItemRangeChanged(eq(1), eq(1), isNull());
-    }
-
-    @Test
-    public void headerClick_expanded_shouldNotifyItemChange() {
-        // GIVEN a list of widgets entries:
-        // [com.google.test0, com.google.test0 content,
-        //  com.google.test1, com.google.test1 content,
-        //  com.google.test2, com.google.test2 content]
-        // The visible widgets entries: [com.google.test0, com.google.test1, com.google.test2].
-        mAdapter.setWidgets(generateSampleMap(3));
-
-        // WHEN com.google.test.1 header is expanded.
-        mAdapter.onHeaderClicked(/* showWidgets= */ true,
-                new PackageUserKey(TEST_PACKAGE_PLACEHOLDER + 1, mUserHandle));
-
-        // THEN the visible entries list becomes:
-        // [com.google.test0, com.google.test1, com.google.test1 content, com.google.test2]
-        // com.google.test.1 content is inserted into position 2.
-        verify(mListener).onItemRangeInserted(eq(3), eq(1));
-    }
-
-    @Test
-    public void setWidgets_expandedApp_moreWidgets_shouldNotifyItemChangedWithWidgetItemInfoDiff() {
-        // GIVEN the adapter was first populated with com.google.test0 & com.google.test1. Each app
-        // has one widget.
-        ArrayList<WidgetsListBaseEntry> allEntries = generateSampleMap(2);
-        mAdapter.setWidgets(allEntries);
-        // GIVEN test com.google.test1 is expanded.
-        // Visible entries in the adapter are:
-        // [com.google.test0, com.google.test1, com.google.test1 content]
-        mAdapter.onHeaderClicked(/* showWidgets= */ true,
-                new PackageUserKey(TEST_PACKAGE_PLACEHOLDER + 1, mUserHandle));
-        Mockito.reset(mListener);
-
-        // WHEN the adapter is updated with the same list of apps but com.google.test1 has 2 widgets
-        // now.
-        WidgetsListContentEntry testPackage1ContentEntry =
-                (WidgetsListContentEntry) allEntries.get(3);
-        WidgetItem widgetItem = testPackage1ContentEntry.mWidgets.get(0);
-        WidgetsListContentEntry newTestPackage1ContentEntry = new WidgetsListContentEntry(
-                testPackage1ContentEntry.mPkgItem,
-                testPackage1ContentEntry.mTitleSectionName, List.of(widgetItem, widgetItem));
-        allEntries.set(3, newTestPackage1ContentEntry);
-        mAdapter.setWidgets(allEntries);
-
-        // THEN the onItemRangeChanged is invoked for "com.google.test1 content" at index 2.
-        verify(mListener).onItemRangeChanged(eq(3), eq(1), isNull());
-    }
-
-    @Test
-    public void setWidgets_hodgepodge_shouldInvokeExpectedDataObserverCallbacks() {
-        // GIVEN a widgets entry list:
-        // Index:  0|   1      | 2|      3   | 4|     5    | 6|     7    | 8|     9    |
-        //        [A, A content, B, B content, C, C content, D, D content, E, E content]
-        List<WidgetsListBaseEntry> allAppsWithWidgets = generateSampleMap(5);
-        // GIVEN the current widgets list consist of [A, A content, B, B content, E, E content].
-        // GIVEN the visible widgets list consist of [A, B, E]
-        List<WidgetsListBaseEntry> currentList = List.of(
-                // A & A content
-                allAppsWithWidgets.get(0), allAppsWithWidgets.get(1),
-                // B & B content
-                allAppsWithWidgets.get(2), allAppsWithWidgets.get(3),
-                // E & E content
-                allAppsWithWidgets.get(8), allAppsWithWidgets.get(9));
-        mAdapter.setWidgets(currentList);
-
-        // WHEN the widgets list is updated to [A, A content, C, C content, D, D content].
-        // WHEN the visible widgets list is updated to [A, C, D].
-        List<WidgetsListBaseEntry> newList = List.of(
-                // A & A content
-                allAppsWithWidgets.get(0), allAppsWithWidgets.get(1),
-                // C & C content
-                allAppsWithWidgets.get(4), allAppsWithWidgets.get(5),
-                // D & D content
-                allAppsWithWidgets.get(6), allAppsWithWidgets.get(7));
-        mAdapter.setWidgets(newList);
-
-        // Account for 1st items as empty space
-        // Computation logic                           | [Intermediate list during computation]
-        // THEN B <> C < 0, removed B from index 1     | [A, E]
-        verify(mListener).onItemRangeRemoved(/* positionStart= */ 2, /* itemCount= */ 1);
-        // THEN E <> C > 0, C inserted to index 1      | [A, C, E]
-        verify(mListener).onItemRangeInserted(/* positionStart= */ 2, /* itemCount= */ 1);
-        // THEN E <> D > 0, D inserted to index 2      | [A, C, D, E]
-        verify(mListener).onItemRangeInserted(/* positionStart= */ 3, /* itemCount= */ 1);
-        // THEN E <> null = -1, E deleted from index 3 | [A, C, D]
-        verify(mListener).onItemRangeRemoved(/* positionStart= */ 4, /* itemCount= */ 1);
-    }
-
-    @Test
-    public void setWidgetsOnSearch_expandedApp_shouldResetExpandedApp() {
-        // GIVEN a list of widgets entries:
-        // [Empty item
-        //  com.google.test0,
-        //  com.google.test0 content,
-        //  com.google.test1,
-        //  com.google.test1 content,
-        //  com.google.test2,
-        //  com.google.test2 content]
-        // The visible widgets entries:
-        // [Empty item,
-        // com.google.test0,
-        // com.google.test1,
-        // com.google.test2].
-        ArrayList<WidgetsListBaseEntry> allEntries = generateSampleMap(3);
-        mAdapter.setWidgetsOnSearch(allEntries);
-        // GIVEN com.google.test.1 header is expanded. The visible entries list becomes:
-        // [Empty item, com.google.test0, com.google.test1, com.google.test1 content,
-        // com.google.test2]
-        mAdapter.onHeaderClicked(/* showWidgets= */ true,
-                new PackageUserKey(TEST_PACKAGE_PLACEHOLDER + 1, mUserHandle));
-        Mockito.reset(mListener);
-
-        // WHEN same widget entries are set again.
-        mAdapter.setWidgetsOnSearch(allEntries);
-
-        // THEN expanded app is reset and the visible entries list becomes:
-        // [Empty item, com.google.test0, com.google.test1, com.google.test2]
-        verify(mListener).onItemRangeChanged(eq(2), eq(1), isNull());
-        verify(mListener).onItemRangeRemoved(/* positionStart= */ 3, /* itemCount= */ 1);
-    }
-
-    /**
-     * Generates a list of sample widget entries.
-     *
-     * <p>Each sample app has 1 widget only. An app is represented by 2 entries,
-     * {@link WidgetsListHeaderEntry} & {@link WidgetsListContentEntry}. Only
-     * {@link WidgetsListHeaderEntry} is always visible in the {@link WidgetsListAdapter}.
-     * {@link WidgetsListContentEntry} is only shown upon clicking the corresponding app's
-     * {@link WidgetsListHeaderEntry}. Only at most one {@link WidgetsListContentEntry} is shown at
-     * a time.
-     *
-     * @param num the number of apps that have widgets.
-     */
-    private ArrayList<WidgetsListBaseEntry> generateSampleMap(int num) {
-        ArrayList<WidgetsListBaseEntry> result = new ArrayList<>();
-        if (num <= 0) return result;
-
-        for (int i = 0; i < num; i++) {
-            String packageName = TEST_PACKAGE_PLACEHOLDER + i;
-
-            List<WidgetItem> widgetItems = generateWidgetItems(packageName, /* numOfWidgets= */ 1);
-
-            PackageItemInfo pInfo = new PackageItemInfo(packageName, widgetItems.get(0).user);
-            pInfo.title = pInfo.packageName;
-            pInfo.bitmap = BitmapInfo.of(Bitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8), 0);
-
-            result.add(WidgetsListHeaderEntry.create(
-                    pInfo, /* titleSectionName= */ "", widgetItems));
-            result.add(new WidgetsListContentEntry(pInfo, /* titleSectionName= */ "", widgetItems));
-        }
-
-        return result;
-    }
-
-    private List<WidgetItem> generateWidgetItems(String packageName, int numOfWidgets) {
-        ArrayList<WidgetItem> widgetItems = new ArrayList<>();
-        for (int i = 0; i < numOfWidgets; i++) {
-            ComponentName cn = ComponentName.createRelative(packageName, ".SampleWidget" + i);
-            AppWidgetProviderInfo widgetInfo = WidgetUtils.createAppWidgetProviderInfo(cn);
-
-            widgetItems.add(new WidgetItem(
-                    LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, widgetInfo),
-                    mTestProfile, mIconCache));
-        }
-        return widgetItems;
-    }
-}