Merge "Remove dead taskbar code" into sc-dev
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index 4fd2e40..4e72260 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -116,8 +116,7 @@
             android:theme="@style/AppItemActivityTheme"
             android:excludeFromRecents="true"
             android:autoRemoveFromRecents="true"
-            android:exported="true"
-            android:label="@string/action_add_to_workspace" >
+            android:exported="true">
             <intent-filter>
                 <action android:name="android.content.pm.action.CONFIRM_PIN_SHORTCUT" />
                 <action android:name="android.content.pm.action.CONFIRM_PIN_APPWIDGET" />
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 750f673..e1456b1 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -25,6 +25,7 @@
 import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
 import static com.android.quickstep.views.RecentsView.TASK_MODALNESS;
 import static com.android.quickstep.views.SplitPlaceholderView.ALPHA_FLOAT;
+import static com.android.quickstep.views.TaskView.FLAG_UPDATE_ALL;
 
 import android.annotation.TargetApi;
 import android.os.Build;
@@ -73,7 +74,7 @@
 
         if (toState.overviewUi) {
             // While animating into recents, update the visible task data as needed
-            builder.addOnFrameCallback(mRecentsView::loadVisibleTaskData);
+            builder.addOnFrameCallback(() -> mRecentsView.loadVisibleTaskData(FLAG_UPDATE_ALL));
             mRecentsView.updateEmptyMessage();
         } else {
             builder.addListener(
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
index fb58bf6..aa770d2 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
@@ -82,20 +82,6 @@
     }
 
     @Override
-    public ScaleAndTranslation getHotseatScaleAndTranslation(Launcher launcher) {
-        if ((getVisibleElements(launcher) & HOTSEAT_ICONS) != 0) {
-            // Translate hotseat offscreen if we show it in overview.
-            RecentsView recentsView = launcher.getOverviewPanel();
-            ScaleAndTranslation scaleAndTranslation = super.getHotseatScaleAndTranslation(launcher);
-            scaleAndTranslation.translationY += LayoutUtils.getShelfTrackingDistance(launcher,
-                    launcher.getDeviceProfile(),
-                    recentsView.getPagedOrientationHandler());
-            return scaleAndTranslation;
-        }
-        return super.getHotseatScaleAndTranslation(launcher);
-    }
-
-    @Override
     protected float getDepthUnchecked(Context context) {
         return 1f;
     }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index 5a28cfd..d8a5f9b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -78,40 +78,11 @@
     }
 
     @Override
-    public ScaleAndTranslation getHotseatScaleAndTranslation(Launcher launcher) {
-        if ((getVisibleElements(launcher) & HOTSEAT_ICONS) != 0) {
-            DeviceProfile dp = launcher.getDeviceProfile();
-            if (dp.allAppsIconSizePx >= dp.iconSizePx) {
-                return new ScaleAndTranslation(1, 0, 0);
-            } else {
-                float scale = ((float) dp.allAppsIconSizePx) / dp.iconSizePx;
-                // Distance between the screen center (which is the pivotY for hotseat) and the
-                // bottom of the hotseat (which we want to preserve)
-                float distanceFromBottom = dp.heightPx / 2 - dp.hotseatBarBottomPaddingPx;
-                // On scaling, the bottom edge is moved closer to the pivotY. We move the
-                // hotseat back down so that the bottom edge's position is preserved.
-                float translationY = distanceFromBottom * (1 - scale);
-                return new ScaleAndTranslation(scale, 0, translationY);
-            }
-        }
-        return getWorkspaceScaleAndTranslation(launcher);
-    }
-
-    @Override
     public float[] getOverviewScaleAndOffset(Launcher launcher) {
         return new float[] {NO_SCALE, NO_OFFSET};
     }
 
     @Override
-    public ScaleAndTranslation getQsbScaleAndTranslation(Launcher launcher) {
-        if (this == OVERVIEW) {
-            // Treat the QSB as part of the hotseat so they move together.
-            return getHotseatScaleAndTranslation(launcher);
-        }
-        return super.getQsbScaleAndTranslation(launcher);
-    }
-
-    @Override
     public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
         return new PageAlphaProvider(DEACCEL_2) {
             @Override
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
index 54f6ce6..82bfa9b 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
@@ -29,6 +29,7 @@
 import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
 import static com.android.quickstep.views.RecentsView.TASK_MODALNESS;
 import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
+import static com.android.quickstep.views.TaskView.FLAG_UPDATE_ALL;
 
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.anim.PropertySetter;
@@ -70,7 +71,7 @@
             return;
         }
         // While animating into recents, update the visible task data as needed
-        setter.addOnFrameCallback(mRecentsView::loadVisibleTaskData);
+        setter.addOnFrameCallback(() -> mRecentsView.loadVisibleTaskData(FLAG_UPDATE_ALL));
         mRecentsView.updateEmptyMessage();
 
         setProperties(toState, config, setter);
diff --git a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index 23f9c10..d4ca31f 100644
--- a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -82,34 +82,25 @@
 
         DeviceProfile grid = launcher.getDeviceProfile();
         Workspace workspace = launcher.getWorkspace();
-        CellLayout cellLayout = (CellLayout) workspace.getChildAt(workspace.getCurrentPage());
-        ShortcutAndWidgetContainer currentPage = cellLayout.getShortcutsAndWidgets();
         Hotseat hotseat = launcher.getHotseat();
 
+        // Hotseat and QSB takes up two additional rows.
+        int totalRows = grid.inv.numRows + (grid.isVerticalBarLayout() ? 0 : 2);
+
+        // Add animation for all the visible workspace pages
+        workspace.getVisiblePages()
+                .forEach(page -> addAnimationForPage((CellLayout) page, totalRows));
+
         boolean workspaceClipChildren = workspace.getClipChildren();
         boolean workspaceClipToPadding = workspace.getClipToPadding();
-        boolean cellLayoutClipChildren = cellLayout.getClipChildren();
-        boolean cellLayoutClipToPadding = cellLayout.getClipToPadding();
         boolean hotseatClipChildren = hotseat.getClipChildren();
         boolean hotseatClipToPadding = hotseat.getClipToPadding();
 
         workspace.setClipChildren(false);
         workspace.setClipToPadding(false);
-        cellLayout.setClipChildren(false);
-        cellLayout.setClipToPadding(false);
         hotseat.setClipChildren(false);
         hotseat.setClipToPadding(false);
 
-        // Hotseat and QSB takes up two additional rows.
-        int totalRows = grid.inv.numRows + (grid.isVerticalBarLayout() ? 0 : 2);
-
-        // Set up springs on workspace items.
-        for (int i = currentPage.getChildCount() - 1; i >= 0; i--) {
-            View child = currentPage.getChildAt(i);
-            CellLayout.LayoutParams lp = ((CellLayout.LayoutParams) child.getLayoutParams());
-            addStaggeredAnimationForView(child, lp.cellY + lp.cellVSpan, totalRows);
-        }
-
         // Set up springs for the hotseat and qsb.
         ViewGroup hotseatIcons = hotseat.getShortcutsAndWidgets();
         if (grid.isVerticalBarLayout()) {
@@ -154,14 +145,37 @@
             public void onAnimationEnd(Animator animation) {
                 workspace.setClipChildren(workspaceClipChildren);
                 workspace.setClipToPadding(workspaceClipToPadding);
-                cellLayout.setClipChildren(cellLayoutClipChildren);
-                cellLayout.setClipToPadding(cellLayoutClipToPadding);
                 hotseat.setClipChildren(hotseatClipChildren);
                 hotseat.setClipToPadding(hotseatClipToPadding);
             }
         });
     }
 
+    private void addAnimationForPage(CellLayout page, int totalRows) {
+        ShortcutAndWidgetContainer itemsContainer = page.getShortcutsAndWidgets();
+
+        boolean pageClipChildren = page.getClipChildren();
+        boolean pageClipToPadding = page.getClipToPadding();
+
+        page.setClipChildren(false);
+        page.setClipToPadding(false);
+
+        // Set up springs on workspace items.
+        for (int i = itemsContainer.getChildCount() - 1; i >= 0; i--) {
+            View child = itemsContainer.getChildAt(i);
+            CellLayout.LayoutParams lp = ((CellLayout.LayoutParams) child.getLayoutParams());
+            addStaggeredAnimationForView(child, lp.cellY + lp.cellVSpan, totalRows);
+        }
+
+        mAnimators.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                page.setClipChildren(pageClipChildren);
+                page.setClipToPadding(pageClipToPadding);
+            }
+        });
+    }
+
     /**
      * Setup workspace with 0 duration to prepare for our staggered animation.
      */
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index f216985..4d8176c 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -315,6 +315,10 @@
     private final ClearAllButton mClearAllButton;
     private final Rect mClearAllButtonDeadZoneRect = new Rect();
     private final Rect mTaskViewDeadZoneRect = new Rect();
+    /**
+     * Reflects if Recents is currently in the middle of a gesture
+     */
+    private boolean mGestureActive;
 
     private final ScrollState mScrollState = new ScrollState();
     // Keeps track of the previously known visible tasks for purposes of loading/unloading task data
@@ -624,8 +628,8 @@
             return;
         }
         mModel.getIconCache().clear();
-        unloadVisibleTaskData();
-        loadVisibleTaskData();
+        unloadVisibleTaskData(TaskView.FLAG_UPDATE_ICON);
+        loadVisibleTaskData(TaskView.FLAG_UPDATE_ICON);
     }
 
     public void init(OverviewActionsView actionsView, SplitPlaceholderView splitPlaceholderView) {
@@ -908,7 +912,7 @@
         }
 
         // Unload existing visible task data
-        unloadVisibleTaskData();
+        unloadVisibleTaskData(TaskView.FLAG_UPDATE_ALL);
 
         TaskView ignoreResetTaskView =
                 mIgnoreResetTaskId == -1 ? null : getTaskView(mIgnoreResetTaskId);
@@ -1031,7 +1035,7 @@
 
         updateCurveProperties();
         // Update the set of visible task's data
-        loadVisibleTaskData();
+        loadVisibleTaskData(TaskView.FLAG_UPDATE_ALL);
         setTaskModalness(0);
     }
 
@@ -1147,7 +1151,7 @@
             }
 
             // After scrolling, update the visible task's data
-            loadVisibleTaskData();
+            loadVisibleTaskData(TaskView.FLAG_UPDATE_ALL);
         }
 
         // Update the high res thumbnail loader state
@@ -1210,7 +1214,7 @@
      * Iterates through all the tasks, and loads the associated task data for newly visible tasks,
      * and unloads the associated task data for tasks that are no longer visible.
      */
-    public void loadVisibleTaskData() {
+    public void loadVisibleTaskData(@TaskView.TaskDataChanges int dataChanges) {
         if (!mOverviewStateEnabled || mTaskListChangeId == -1) {
             // Skip loading visible task data if we've already left the overview state, or if the
             // task list hasn't been loaded yet (the task views will not reflect the task list)
@@ -1252,12 +1256,18 @@
                     continue;
                 }
                 if (!mHasVisibleTaskData.get(task.key.id)) {
-                    taskView.onTaskListVisibilityChanged(true /* visible */);
+                    // Ignore thumbnail update if it's current running task during the gesture
+                    // We snapshot at end of gesture, it will update then
+                    int changes = dataChanges;
+                    if (taskView == getRunningTaskView() && mGestureActive) {
+                        changes &= ~TaskView.FLAG_UPDATE_THUMBNAIL;
+                    }
+                    taskView.onTaskListVisibilityChanged(true /* visible */, changes);
                 }
                 mHasVisibleTaskData.put(task.key.id, visible);
             } else {
                 if (mHasVisibleTaskData.get(task.key.id)) {
-                    taskView.onTaskListVisibilityChanged(false /* visible */);
+                    taskView.onTaskListVisibilityChanged(false /* visible */, dataChanges);
                 }
                 mHasVisibleTaskData.delete(task.key.id);
             }
@@ -1267,12 +1277,12 @@
     /**
      * Unloads any associated data from the currently visible tasks
      */
-    private void unloadVisibleTaskData() {
+    private void unloadVisibleTaskData(@TaskView.TaskDataChanges int dataChanges) {
         for (int i = 0; i < mHasVisibleTaskData.size(); i++) {
             if (mHasVisibleTaskData.valueAt(i)) {
                 TaskView taskView = getTaskView(mHasVisibleTaskData.keyAt(i));
                 if (taskView != null) {
-                    taskView.onTaskListVisibilityChanged(false /* visible */);
+                    taskView.onTaskListVisibilityChanged(false /* visible */, dataChanges);
                 }
             }
         }
@@ -1310,7 +1320,7 @@
         mRecentsAnimationController = null;
         mLiveTileParams.setTargetSet(null);
 
-        unloadVisibleTaskData();
+        unloadVisibleTaskData(TaskView.FLAG_UPDATE_ALL);
         setCurrentPage(0);
         mDwbToastShown = false;
         mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW, 0);
@@ -1358,6 +1368,7 @@
      * Called when a gesture from an app is starting.
      */
     public void onGestureAnimationStart(RunningTaskInfo runningTaskInfo) {
+        mGestureActive = true;
         // This needs to be called before the other states are set since it can create the task view
         if (mOrientationState.setGestureActive(true)) {
             updateOrientationHandler();
@@ -1428,6 +1439,7 @@
      * Called when a gesture from an app has finished, and the animation to the target has ended.
      */
     public void onGestureAnimationEnd() {
+        mGestureActive = false;
         if (mOrientationState.setGestureActive(false)) {
             updateOrientationHandler();
         }
@@ -2733,7 +2745,7 @@
     @Override
     protected void notifyPageSwitchListener(int prevPage) {
         super.notifyPageSwitchListener(prevPage);
-        loadVisibleTaskData();
+        loadVisibleTaskData(TaskView.FLAG_UPDATE_ALL);
         updateEnabledOverlays();
     }
 
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 2b7e6fd..a2acab8 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -42,6 +42,8 @@
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
 
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
@@ -67,6 +69,7 @@
 import android.widget.FrameLayout;
 import android.widget.Toast;
 
+import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 
 import com.android.launcher3.DeviceProfile;
@@ -106,6 +109,7 @@
 import com.android.systemui.shared.system.ActivityOptionsCompat;
 import com.android.systemui.shared.system.QuickStepContract;
 
+import java.lang.annotation.Retention;
 import java.util.Collections;
 import java.util.List;
 import java.util.function.Consumer;
@@ -117,6 +121,19 @@
 
     private static final String TAG = TaskView.class.getSimpleName();
 
+    public static final int FLAG_UPDATE_ICON = 1;
+    public static final int FLAG_UPDATE_THUMBNAIL = FLAG_UPDATE_ICON << 1;
+
+    public static final int FLAG_UPDATE_ALL = FLAG_UPDATE_ICON | FLAG_UPDATE_THUMBNAIL;
+
+    /**
+     * Used in conjunction with {@link #onTaskListVisibilityChanged(boolean, int)}, providing more
+     * granularity on which components of this task require an update
+     */
+    @Retention(SOURCE)
+    @IntDef({FLAG_UPDATE_ALL, FLAG_UPDATE_ICON, FLAG_UPDATE_THUMBNAIL})
+    public @interface TaskDataChanges {}
+
     /**
      * The alpha of a black scrim on a page in the carousel as it leaves the screen.
      * In the resting position of the carousel, the adjacent pages have about half this scrim.
@@ -557,7 +574,19 @@
         }
     }
 
+    /**
+     * See {@link TaskDataChanges}
+     * @param visible If this task view will be visible to the user in overview or hidden
+     */
     public void onTaskListVisibilityChanged(boolean visible) {
+        onTaskListVisibilityChanged(visible, FLAG_UPDATE_ALL);
+    }
+
+    /**
+     * See {@link TaskDataChanges}
+     * @param visible If this task view will be visible to the user in overview or hidden
+     */
+    public void onTaskListVisibilityChanged(boolean visible, @TaskDataChanges int changes) {
         if (mTask == null) {
             return;
         }
@@ -568,22 +597,37 @@
             RecentsModel model = RecentsModel.INSTANCE.get(getContext());
             TaskThumbnailCache thumbnailCache = model.getThumbnailCache();
             TaskIconCache iconCache = model.getIconCache();
-            mThumbnailLoadRequest = thumbnailCache.updateThumbnailInBackground(
-                    mTask, thumbnail -> mSnapshotView.setThumbnail(mTask, thumbnail));
-            mIconLoadRequest = iconCache.updateIconInBackground(mTask,
-                    (task) -> {
-                        setIcon(task.icon);
-                        mDigitalWellBeingToast.initialize(mTask);
-                    });
+
+            if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
+                mThumbnailLoadRequest = thumbnailCache.updateThumbnailInBackground(
+                        mTask, thumbnail -> {
+                            mSnapshotView.setThumbnail(mTask, thumbnail);
+                        });
+            }
+            if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
+                mIconLoadRequest = iconCache.updateIconInBackground(mTask,
+                        (task) -> {
+                            setIcon(task.icon);
+                            mDigitalWellBeingToast.initialize(mTask);
+                        });
+            }
         } else {
-            mSnapshotView.setThumbnail(null, null);
-            setIcon(null);
-            // Reset the task thumbnail reference as well (it will be fetched from the cache or
-            // reloaded next time we need it)
-            mTask.thumbnail = null;
+            if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
+                mSnapshotView.setThumbnail(null, null);
+                // Reset the task thumbnail reference as well (it will be fetched from the cache or
+                // reloaded next time we need it)
+                mTask.thumbnail = null;
+            }
+            if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
+                setIcon(null);
+            }
         }
     }
 
+    private boolean needsUpdate(@TaskDataChanges int dataChange, @TaskDataChanges int flag) {
+        return (dataChange & flag) == flag;
+    }
+
     private void cancelPendingLoadTasks() {
         if (mThumbnailLoadRequest != null) {
             mThumbnailLoadRequest.cancel();
diff --git a/res/drawable/add_item_dialog_background.xml b/res/drawable/add_item_dialog_background.xml
new file mode 100644
index 0000000..04bde8f
--- /dev/null
+++ b/res/drawable/add_item_dialog_background.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle" >
+    <solid android:color="?android:attr/colorBackground" />
+    <corners
+        android:topLeftRadius="?android:attr/dialogCornerRadius"
+        android:topRightRadius="?android:attr/dialogCornerRadius" />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/add_item_dialog_button_background.xml b/res/drawable/add_item_dialog_button_background.xml
new file mode 100644
index 0000000..1b4591f
--- /dev/null
+++ b/res/drawable/add_item_dialog_button_background.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<inset
+    android:insetLeft="@dimen/pin_widget_button_inset_horizontal"
+    android:insetRight="@dimen/pin_widget_button_inset_horizontal"
+    android:insetTop="@dimen/pin_widget_button_inset_vertical"
+    android:insetBottom="@dimen/pin_widget_button_inset_vertical"
+    xmlns:android="http://schemas.android.com/apk/res/android">
+    <ripple
+        android:color="?android:attr/colorControlHighlight">
+        <item>
+            <shape android:tint="?android:attr/colorAccent" android:shape="rectangle">
+                <corners android:radius="18dp" />
+                <solid android:color="#FFFFFF"  />
+                <padding
+                    android:left="@dimen/pin_widget_button_padding_horizontal"
+                    android:top="@dimen/pin_widget_button_padding_vertical"
+                    android:right="@dimen/pin_widget_button_padding_horizontal"
+                    android:bottom="@dimen/pin_widget_button_padding_vertical" />
+            </shape>
+        </item>
+    </ripple>
+</inset>
\ No newline at end of file
diff --git a/res/layout/add_item_confirmation_activity.xml b/res/layout/add_item_confirmation_activity.xml
index b1a1efe..d5e7333 100644
--- a/res/layout/add_item_confirmation_activity.xml
+++ b/res/layout/add_item_confirmation_activity.xml
@@ -17,70 +17,51 @@
 */
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/add_item_confirmation"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:padding="24dp"
     android:orientation="vertical">
-    <ScrollView
+
+    <TextView
+        style="@style/TextHeadline"
+        android:id="@+id/widget_appName"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center_horizontal"
+        android:textColor="?android:attr/textColorPrimary"
+        android:textSize="24sp"
+        android:ellipsize="end"
+        android:fadingEdge="horizontal"
+        android:singleLine="true"
+        android:maxLines="1" />
+
+    <include layout="@layout/widget_cell"
+        android:id="@+id/widget_cell"
         android:layout_width="match_parent"
         android:layout_height="0dp"
         android:layout_weight="1"
-        android:clipToPadding="false">
-
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical">
-
-            <TextView
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingBottom="20dp"
-                android:paddingLeft="24dp"
-                android:paddingRight="24dp"
-                android:paddingTop="4dp"
-                android:text="@string/add_item_request_drag_hint" />
-
-            <FrameLayout
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:background="?android:attr/colorPrimaryDark"
-                android:theme="?attr/widgetsTheme">
-
-                <com.android.launcher3.widget.WidgetCell
-                    android:id="@+id/widget_cell"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center_horizontal"
-                    android:layout_weight="1"
-                    android:background="?android:attr/colorPrimaryDark"
-                    android:focusable="true"
-                    android:gravity="center_horizontal"
-                    android:orientation="vertical" >
-
-                    <include layout="@layout/widget_cell_content"  />
-
-                </com.android.launcher3.widget.WidgetCell>
-            </FrameLayout>
-        </LinearLayout>
-    </ScrollView>
+        android:layout_marginVertical="16dp" />
 
     <LinearLayout
-        style="?android:attr/buttonBarStyle"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:gravity="end"
-        android:paddingBottom="4dp"
-        android:paddingEnd="12dp"
-        android:paddingStart="12dp"
-        android:paddingTop="4dp" >
+        android:padding="8dp"
+        android:orientation="horizontal">
         <Button
-            style="?android:attr/buttonBarButtonStyle"
+            style="@style/Widget.DeviceDefault.Button.Rounded.Colored"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:onClick="onCancelClick"
             android:text="@android:string/cancel" />
+
+        <Space
+            android:layout_width="4dp"
+            android:layout_height="wrap_content" />
+
         <Button
-            style="?android:attr/buttonBarButtonStyle"
+            style="@style/Widget.DeviceDefault.Button.Rounded.Colored"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:onClick="onPlaceAutomaticallyClick"
diff --git a/res/layout/app_widget_resize_frame.xml b/res/layout/app_widget_resize_frame.xml
index 2e476df..671dbc6 100644
--- a/res/layout/app_widget_resize_frame.xml
+++ b/res/layout/app_widget_resize_frame.xml
@@ -26,6 +26,7 @@
 
         <!-- Frame -->
         <ImageView
+            android:id="@+id/widget_resize_frame"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_gravity="center"
diff --git a/res/layout/deep_shortcut.xml b/res/layout/deep_shortcut.xml
index d6b4a37..0d11b50 100644
--- a/res/layout/deep_shortcut.xml
+++ b/res/layout/deep_shortcut.xml
@@ -32,6 +32,8 @@
         android:paddingEnd="@dimen/popup_padding_end"
         android:drawableEnd="@drawable/ic_drag_handle"
         android:drawablePadding="@dimen/deep_shortcut_drawable_padding"
+        android:singleLine="true"
+        android:ellipsize="end"
         android:textSize="14sp"
         android:textColor="?android:attr/textColorPrimary"
         launcher:layoutHorizontal="true"
diff --git a/res/layout/system_shortcut.xml b/res/layout/system_shortcut.xml
index 68251e4..9f45f30 100644
--- a/res/layout/system_shortcut.xml
+++ b/res/layout/system_shortcut.xml
@@ -31,7 +31,8 @@
         android:paddingStart="@dimen/deep_shortcuts_text_padding_start"
         android:paddingEnd="@dimen/popup_padding_end"
         android:textSize="14sp"
-        android:maxLines="1"
+        android:singleLine="true"
+        android:ellipsize="end"
         android:textColor="?android:attr/textColorPrimary"
         launcher:iconDisplay="shortcut_popup"
         launcher:layoutHorizontal="true"
diff --git a/res/layout/widget_cell_content.xml b/res/layout/widget_cell_content.xml
index a3d0070..30bd8b1 100644
--- a/res/layout/widget_cell_content.xml
+++ b/res/layout/widget_cell_content.xml
@@ -18,8 +18,8 @@
     android:layout_height="wrap_content">
 
     <!-- The image of the widget. This view does not support padding. Any placement adjustment
-         should be done using margins.
-          width & height are set at runtime after scaling the preview image. -->
+         should be done using margins. Width & height are set at runtime after scaling the preview
+         image. -->
     <com.android.launcher3.widget.WidgetImageView
         android:id="@+id/widget_preview"
         android:layout_width="0dp"
@@ -41,16 +41,15 @@
         android:textColor="?android:attr/textColorPrimary"
         android:textSize="@dimen/widget_cell_font_size" />
 
-    <!-- The original dimensions of the widget (can't be the same text as above due to different
-         style. -->
+    <!-- The original dimensions of the widget -->
     <TextView
         android:id="@+id/widget_dims"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:gravity="center_horizontal"
-        android:textColor="?android:attr/textColorTertiary"
+        android:textColor="?android:attr/textColorSecondary"
         android:textSize="@dimen/widget_cell_font_size"
-        android:alpha="0.8" />
+        android:alpha="0.7" />
 
     <TextView
         android:id="@+id/widget_description"
@@ -58,9 +57,10 @@
         android:layout_height="wrap_content"
         android:gravity="center_horizontal"
         android:textSize="@dimen/widget_cell_font_size"
-        android:textColor="?android:attr/textColorTertiary"
+        android:textColor="?android:attr/textColorSecondary"
         android:maxLines="2"
         android:ellipsize="end"
-        android:fadingEdge="horizontal" />
+        android:fadingEdge="horizontal"
+        android:alpha="0.7" />
 
 </merge>
\ No newline at end of file
diff --git a/res/layout/widgets_list_row_header.xml b/res/layout/widgets_list_row_header.xml
index ed3a042..598041c 100644
--- a/res/layout/widgets_list_row_header.xml
+++ b/res/layout/widgets_list_row_header.xml
@@ -56,7 +56,8 @@
             android:layout_height="wrap_content"
             android:ellipsize="end"
             android:maxLines="1"
-            android:textColor="?android:attr/textColorTertiary"
+            android:textColor="?android:attr/textColorSecondary"
+            android:alpha="0.7"
             tools:text="m widgets, n shortcuts" />
 
     </LinearLayout>
diff --git a/res/layout/widgets_search_bar.xml b/res/layout/widgets_search_bar.xml
index 1db7462..e3836df 100644
--- a/res/layout/widgets_search_bar.xml
+++ b/res/layout/widgets_search_bar.xml
@@ -32,5 +32,6 @@
         android:src="@drawable/ic_gm_close_24"
         android:background="?android:selectableItemBackground"
         android:layout_gravity="center"
+        android:contentDescription="@string/widgets_full_sheet_cancel_button_description"
         android:visibility="gone"/>
 </com.android.launcher3.widget.picker.search.LauncherWidgetsSearchBar>
\ No newline at end of file
diff --git a/res/values-night/styles.xml b/res/values-night/styles.xml
index 510e1f4..07a5096 100644
--- a/res/values-night/styles.xml
+++ b/res/values-night/styles.xml
@@ -21,6 +21,8 @@
 
     <style name="AppItemActivityTheme" parent="@android:style/Theme.DeviceDefault.Dialog.Alert">
         <item name="widgetsTheme">@style/WidgetContainerTheme.Dark</item>
+        <item name="android:windowBackground">@drawable/add_item_dialog_background</item>
+        <item name="android:windowNoTitle">true</item>
     </style>
 
 </resources>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 9d6c936..cf830c7 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -138,6 +138,12 @@
     <dimen name="shortcut_preview_padding_right">0dp</dimen>
     <dimen name="shortcut_preview_padding_top">0dp</dimen>
 
+<!-- Pin widget dialog -->
+    <dimen name="pin_widget_button_padding_horizontal">8dp</dimen>
+    <dimen name="pin_widget_button_padding_vertical">4dp</dimen>
+    <dimen name="pin_widget_button_inset_horizontal">4dp</dimen>
+    <dimen name="pin_widget_button_inset_vertical">6dp</dimen>
+
 <!-- Dragging -->
     <!-- Drag padding to add to the bottom of drop targets -->
     <dimen name="drop_target_drag_padding">14dp</dimen>
@@ -185,7 +191,7 @@
 
 <!-- Deep shortcuts -->
     <dimen name="deep_shortcuts_elevation">0dp</dimen>
-    <dimen name="bg_popup_item_width">234dp</dimen>
+    <dimen name="bg_popup_item_width">216dp</dimen>
     <dimen name="bg_popup_item_height">56dp</dimen>
     <dimen name="pre_drag_view_scale">6dp</dimen>
     <!-- an icon with shortcuts must be dragged this far before the container is removed. -->
@@ -277,4 +283,7 @@
 <!-- Taskbar related (placeholders to compile in Launcher3 without Quickstep) -->
     <dimen name="taskbar_size">0dp</dimen>
 
+    <!-- Size of the maximum radius for the enforced rounded rectangles. -->
+    <dimen name="enforced_rounded_corner_max_radius">16dp</dimen>
+
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7c372830..e5e5db3 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -81,6 +81,9 @@
     <!-- Search bar text shown in the popup view showing all available widgets installed on the
          device. [CHAR_LIMIT=50] -->
     <string name="widgets_full_sheet_search_bar_hint">Search</string>
+    <!-- Spoken text for screen readers. This text lets a user know that the button is used to clear
+         the text that the user entered in the search box. [CHAR_LIMIT=none] -->
+    <string name="widgets_full_sheet_cancel_button_description">Clear text from search box</string>
     <!-- Text shown when there is no widgets shown in the popup view showing all available widgets
          installed on the device. [CHAR_LIMIT=none] -->
     <string name="no_widgets_available">No widgets available</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index adc2238..a27cdac 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -145,6 +145,8 @@
 
     <style name="AppItemActivityTheme" parent="@android:style/Theme.DeviceDefault.Light.Dialog.Alert">
         <item name="widgetsTheme">@style/WidgetContainerTheme</item>
+        <item name="android:windowBackground">@drawable/add_item_dialog_background</item>
+        <item name="android:windowNoTitle">true</item>
     </style>
 
     <style name="HomeSettingsTheme" parent="@android:style/Theme.DeviceDefault.Settings">
@@ -281,4 +283,8 @@
         <item name="android:colorControlHighlight">#DFE1E5</item>
         <item name="android:colorForeground">@color/all_apps_bg_hand_fill_dark</item>
     </style>
+
+    <style name="Widget.DeviceDefault.Button.Rounded.Colored" parent="@android:style/Widget.DeviceDefault.Button.Colored">
+        <item name="android:background">@drawable/add_item_dialog_button_background</item>
+    </style>
 </resources>
diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java
index e1214ff..6b5678c 100644
--- a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java
+++ b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java
@@ -82,7 +82,7 @@
         mTestProfile.numColumns = 5;
         mUserHandle = Process.myUserHandle();
         mAdapter = new WidgetsListAdapter(mContext, mMockLayoutInflater, mMockWidgetCache,
-                mIconCache, null, null);
+                mIconCache, null, null, null);
         mAdapter.registerAdapterDataObserver(mListener);
 
         doAnswer(invocation -> ((ComponentWithLabel) invocation.getArgument(0))
diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
index 84a03d5..12a092d 100644
--- a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
+++ b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
@@ -105,7 +105,8 @@
                 mWidgetPreviewLoader,
                 mIconCache,
                 /* iconClickListener= */ view -> {},
-                /* iconLongClickListener= */ view -> false);
+                /* iconLongClickListener= */ view -> false,
+                /* searchBarUIHelper= */ null);
         mViewHolderBinder = new WidgetsListHeaderViewHolderBinder(
                 LayoutInflater.from(mTestActivity), mOnHeaderClickListener, widgetsListAdapter);
     }
diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinderTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinderTest.java
index 075c58d..e090341 100644
--- a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinderTest.java
+++ b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinderTest.java
@@ -105,7 +105,8 @@
                 mWidgetPreviewLoader,
                 mIconCache,
                 /* iconClickListener= */ view -> {},
-                /* iconLongClickListener= */ view -> false);
+                /* iconLongClickListener= */ view -> false,
+                /* searchBarUIHelper= */ null);
         mViewHolderBinder = new WidgetsListSearchHeaderViewHolderBinder(
                 LayoutInflater.from(mTestActivity), mOnHeaderClickListener, widgetsListAdapter);
     }
diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
index 0c6e717..0935d1c 100644
--- a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
+++ b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
@@ -111,7 +111,8 @@
                 mWidgetPreviewLoader,
                 mIconCache,
                 /* iconClickListener= */ view -> {},
-                /* iconLongClickListener= */ view -> false);
+                /* iconLongClickListener= */ view -> false,
+                /* searchBarUIHelper= */ null);
         mViewHolderBinder = new WidgetsListTableViewHolderBinder(
                 mContext,
                 LayoutInflater.from(mTestActivity),
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index d02efb0..ab91785 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -14,12 +14,15 @@
 import android.content.Context;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
 import android.os.Bundle;
 import android.util.AttributeSet;
 import android.util.SizeF;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
+import android.widget.ImageView;
 
 import androidx.annotation.Nullable;
 
@@ -166,6 +169,15 @@
         DragLayer dl = launcher.getDragLayer();
         AppWidgetResizeFrame frame = (AppWidgetResizeFrame) launcher.getLayoutInflater()
                 .inflate(R.layout.app_widget_resize_frame, dl, false);
+        if (widget.hasEnforcedCornerRadius()) {
+            float enforcedCornerRadius = widget.getEnforcedCornerRadius();
+            ImageView imageView = frame.findViewById(R.id.widget_resize_frame);
+            Drawable d = imageView.getDrawable();
+            if (d instanceof GradientDrawable) {
+                GradientDrawable gd = (GradientDrawable) d.mutate();
+                gd.setCornerRadius(enforcedCornerRadius);
+            }
+        }
         frame.setupForWidget(widget, cellLayout, dl);
         ((DragLayer.LayoutParams) frame.getLayoutParams()).customPosition = true;
 
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 0f8c6b9..06bc438 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -176,10 +176,6 @@
         return launcher.getNormalOverviewScaleAndOffset();
     }
 
-    public ScaleAndTranslation getQsbScaleAndTranslation(Launcher launcher) {
-        return new ScaleAndTranslation(NO_SCALE, NO_OFFSET, NO_OFFSET);
-    }
-
     public float getOverviewFullscreenProgress() {
         return 0;
     }
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 72eff62..65fde86 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -307,7 +307,7 @@
     /**
      * Returns the currently visible pages.
      */
-    protected Iterable<View> getVisiblePages() {
+    public Iterable<View> getVisiblePages() {
         int panelCount = getPanelCount();
         List<View> visiblePages = new ArrayList<>(panelCount);
         for (int i = mCurrentPage; i < mCurrentPage + panelCount; i++) {
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index 29a0c75..16e022c 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -94,7 +94,6 @@
         ScaleAndTranslation scaleAndTranslation = state.getWorkspaceScaleAndTranslation(mLauncher);
         ScaleAndTranslation hotseatScaleAndTranslation = state.getHotseatScaleAndTranslation(
                 mLauncher);
-        ScaleAndTranslation qsbScaleAndTranslation = state.getQsbScaleAndTranslation(mLauncher);
         mNewScale = scaleAndTranslation.scale;
         PageAlphaProvider pageAlphaProvider = state.getWorkspacePageAlphaProvider(mLauncher);
         final int childCount = mWorkspace.getChildCount();
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 96251f0..7f76d27 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -215,6 +215,9 @@
     public static final BooleanFlag ENABLE_SPLIT_SELECT = getDebugFlag(
             "ENABLE_SPLIT_SELECT", false, "Uses new split screen selection overview UI");
 
+    public static final BooleanFlag ENABLE_ENFORCED_ROUNDED_CORNERS = new DeviceFlag(
+            "ENABLE_ENFORCED_ROUNDED_CORNERS", true, "Enforce rounded corners on all App Widgets");
+
     public static void initialize(Context context) {
         synchronized (sDebugFlags) {
             for (DebugFlag flag : sDebugFlags) {
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index 7bc9865..b7a7366 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -37,11 +37,14 @@
 import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Bundle;
+import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.DragShadowBuilder;
 import android.view.View.OnLongClickListener;
 import android.view.View.OnTouchListener;
+import android.view.WindowManager;
+import android.widget.TextView;
 
 import com.android.launcher3.BaseActivity;
 import com.android.launcher3.InvariantDeviceProfile;
@@ -127,6 +130,9 @@
         if (savedInstanceState == null) {
             logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_START);
         }
+
+        TextView widgetAppName = findViewById(R.id.widget_appName);
+        widgetAppName.setText(getApplicationInfo().labelRes);
     }
 
     @Override
@@ -326,4 +332,15 @@
                 .withItemInfo((ItemInfo) mWidgetCell.getWidgetView().getTag())
                 .log(command);
     }
+
+    @Override
+    public void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        View view = getWindow().getDecorView();
+        WindowManager.LayoutParams layoutParams =
+                (WindowManager.LayoutParams) view.getLayoutParams();
+        layoutParams.gravity = Gravity.BOTTOM;
+        layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
+        getWindowManager().updateViewLayout(view, layoutParams);
+    }
 }
diff --git a/src/com/android/launcher3/dragndrop/AppWidgetHostViewDrawable.java b/src/com/android/launcher3/dragndrop/AppWidgetHostViewDrawable.java
index 92ae670..5cd95dc 100644
--- a/src/com/android/launcher3/dragndrop/AppWidgetHostViewDrawable.java
+++ b/src/com/android/launcher3/dragndrop/AppWidgetHostViewDrawable.java
@@ -17,8 +17,12 @@
 
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
+import android.graphics.Outline;
 import android.graphics.Paint;
+import android.graphics.Path;
 import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
 
 import com.android.launcher3.widget.LauncherAppWidgetHostView;
@@ -28,14 +32,30 @@
 
     private final LauncherAppWidgetHostView mAppWidgetHostView;
     private Paint mPaint = new Paint();
+    private final Path mClipPath;
 
     public AppWidgetHostViewDrawable(LauncherAppWidgetHostView appWidgetHostView) {
         mAppWidgetHostView = appWidgetHostView;
+        Path clipPath = null;
+        if (appWidgetHostView.getClipToOutline()) {
+            Outline outline = new Outline();
+            mAppWidgetHostView.getOutlineProvider().getOutline(mAppWidgetHostView, outline);
+            Rect rect = new Rect();
+            if (outline.getRect(rect)) {
+                float radius = outline.getRadius();
+                clipPath = new Path();
+                clipPath.addRoundRect(new RectF(rect), radius, radius, Path.Direction.CCW);
+            }
+        }
+        mClipPath = clipPath;
     }
 
     @Override
     public void draw(Canvas canvas) {
         int saveCount = canvas.saveLayer(0, 0, getIntrinsicWidth(), getIntrinsicHeight(), mPaint);
+        if (mClipPath != null) {
+            canvas.clipPath(mClipPath);
+        }
         mAppWidgetHostView.draw(canvas);
         canvas.restoreToCount(saveCount);
     }
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index 7a6b4f9..419c3f1 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -110,6 +110,8 @@
         mDragController = dragController;
         recreateControllers();
 
+        mOverviewScrim.setup();
+
         mWorkspaceDragScrim = new WorkspaceDragScrim((this));
         mWorkspaceDragScrim.setWorkspace(workspace);
 
@@ -118,8 +120,6 @@
         mRootView = (LauncherRootView) getParent();
         mSysUiScrim = new SysUiScrim(mRootView);
         mRootView.setSysUiScrim(mSysUiScrim);
-
-
     }
 
     @Override
@@ -555,7 +555,6 @@
     public void setInsets(Rect insets) {
         super.setInsets(insets);
         mSysUiScrim.onInsetsChanged(insets, mAllowSysuiScrims);
-        mOverviewScrim.onInsetsChanged(insets);
     }
 
     public WorkspaceDragScrim getWorkspaceDragScrim() {
diff --git a/src/com/android/launcher3/graphics/OverviewScrim.java b/src/com/android/launcher3/graphics/OverviewScrim.java
index c0c3e5e..53303db 100644
--- a/src/com/android/launcher3/graphics/OverviewScrim.java
+++ b/src/com/android/launcher3/graphics/OverviewScrim.java
@@ -18,10 +18,6 @@
 
 import static android.view.View.VISIBLE;
 
-import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
-import static com.android.launcher3.LauncherState.OVERVIEW;
-
-import android.graphics.Rect;
 import android.util.FloatProperty;
 import android.view.View;
 import android.view.ViewGroup;
@@ -55,15 +51,15 @@
 
     public OverviewScrim(View view) {
         super(view);
-        mStableScrimmedView = mCurrentScrimmedView = mLauncher.getOverviewPanel();
 
         onExtractedColorsChanged(mWallpaperColorInfo);
     }
 
-    public void onInsetsChanged(Rect insets) {
-        mStableScrimmedView = (OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0
-                ? mLauncher.getHotseat()
-                : mLauncher.getOverviewPanel();
+    /**
+     * Initializes once view hierarchy is established.
+     */
+    public void setup() {
+        mStableScrimmedView = mCurrentScrimmedView = mLauncher.getOverviewPanel();
     }
 
     public void updateCurrentScrimmedView(ViewGroup root) {
diff --git a/src/com/android/launcher3/states/HintState.java b/src/com/android/launcher3/states/HintState.java
index fd1d965..eb2c551 100644
--- a/src/com/android/launcher3/states/HintState.java
+++ b/src/com/android/launcher3/states/HintState.java
@@ -53,10 +53,4 @@
     public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
         return new ScaleAndTranslation(0.92f, 0, 0);
     }
-
-    @Override
-    public ScaleAndTranslation getQsbScaleAndTranslation(Launcher launcher) {
-        // Treat the QSB as part of the hotseat so they move together.
-        return getHotseatScaleAndTranslation(launcher);
-    }
 }
diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java
index fce8fff..d593013 100644
--- a/src/com/android/launcher3/states/SpringLoadedState.java
+++ b/src/com/android/launcher3/states/SpringLoadedState.java
@@ -59,10 +59,11 @@
 
         float scale = grid.workspaceSpringLoadShrinkFactor;
         Rect insets = launcher.getDragLayer().getInsets();
+        int insetsBottom = grid.isTaskbarPresent ? grid.taskbarSize : insets.bottom;
 
         float scaledHeight = scale * ws.getNormalChildHeight();
         float shrunkTop = insets.top + grid.dropTargetBarSizePx;
-        float shrunkBottom = ws.getMeasuredHeight() - insets.bottom
+        float shrunkBottom = ws.getMeasuredHeight() - insetsBottom
                 - grid.workspacePadding.bottom
                 - grid.workspaceSpringLoadedBottomSpace;
         float totalShrunkSpace = shrunkBottom - shrunkTop;
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
index 5c18faf..2e542ed 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Canvas;
+import android.graphics.Outline;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.os.Handler;
@@ -32,12 +33,14 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.ViewOutlineProvider;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.AdapterView;
 import android.widget.Advanceable;
 import android.widget.RemoteViews;
 
 import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
 
 import com.android.launcher3.CheckLongPressHelper;
 import com.android.launcher3.Launcher;
@@ -95,6 +98,18 @@
     private final Rect mWidgetSizeAtDrag = new Rect();
     private final RectF mTempRectF = new RectF();
     private final boolean mIsRtl;
+    private final Rect mEnforcedRectangle = new Rect();
+    private final float mEnforcedCornerRadius;
+    private final ViewOutlineProvider mCornerRadiusEnforcementOutline = new ViewOutlineProvider() {
+        @Override
+        public void getOutline(View view, Outline outline) {
+            if (mEnforcedRectangle.isEmpty() || mEnforcedCornerRadius <= 0) {
+                outline.setEmpty();
+            } else {
+                outline.setRoundRect(mEnforcedRectangle, mEnforcedCornerRadius);
+            }
+        }
+    };
 
     public LauncherAppWidgetHostView(Context context) {
         super(context);
@@ -112,6 +127,8 @@
         mIsRtl = Utilities.isRtl(context.getResources());
         mColorExtractor = LocalColorExtractor.newInstance(getContext());
         mColorExtractor.setListener(this);
+
+        mEnforcedCornerRadius = RoundedCornerEnforcement.computeEnforcedRadius(getContext());
     }
 
     @Override
@@ -169,7 +186,7 @@
         if (viewGroup instanceof AdapterView) {
             return true;
         } else {
-            for (int i=0; i < viewGroup.getChildCount(); i++) {
+            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                 View child = viewGroup.getChildAt(i);
                 if (child instanceof ViewGroup) {
                     if (checkScrollableRecursively((ViewGroup) child)) {
@@ -272,6 +289,8 @@
             int pageId = mWorkspace.getPageIndexForScreenId(info.screenId);
             updateColorExtraction(mCurrentWidgetSize, pageId);
         }
+
+        enforceRoundedCorners();
     }
 
     /** Starts the drag mode. */
@@ -469,4 +488,39 @@
         }
         return false;
     }
+
+    @UiThread
+    private void resetRoundedCorners() {
+        setOutlineProvider(ViewOutlineProvider.BACKGROUND);
+        setClipToOutline(false);
+    }
+
+    @UiThread
+    private void enforceRoundedCorners() {
+        if (mEnforcedCornerRadius <= 0 || !RoundedCornerEnforcement.isRoundedCornerEnabled(this)) {
+            resetRoundedCorners();
+            return;
+        }
+        View background = RoundedCornerEnforcement.findBackground(this);
+        if (RoundedCornerEnforcement.hasAppWidgetOptedOut(this, background)) {
+            resetRoundedCorners();
+            return;
+        }
+        RoundedCornerEnforcement.computeRoundedRectangle(this,
+                background,
+                mEnforcedRectangle);
+        setOutlineProvider(mCornerRadiusEnforcementOutline);
+        setClipToOutline(true);
+    }
+
+    /** Returns the corner radius currently enforced, in pixels. */
+    public float getEnforcedCornerRadius() {
+        return mEnforcedCornerRadius;
+    }
+
+    /** Returns true if the corner radius are enforced for this App Widget. */
+    public boolean hasEnforcedCornerRadius() {
+        return getClipToOutline();
+    }
+
 }
diff --git a/src/com/android/launcher3/widget/RoundedCornerEnforcement.java b/src/com/android/launcher3/widget/RoundedCornerEnforcement.java
new file mode 100644
index 0000000..99eccd1
--- /dev/null
+++ b/src/com/android/launcher3/widget/RoundedCornerEnforcement.java
@@ -0,0 +1,170 @@
+/*
+ * 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;
+
+import android.appwidget.AppWidgetHostView;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.IdRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.config.FeatureFlags;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utilities to compute the enforced the use of rounded corners on App Widgets.
+ */
+public class RoundedCornerEnforcement {
+    // This class is only a namespace and not meant to be instantiated.
+    private RoundedCornerEnforcement() {
+    }
+
+    /**
+     * Find the background view for a widget.
+     *
+     * @param appWidget the view containing the App Widget (typically the instance of
+     * {@link AppWidgetHostView}).
+     */
+    @Nullable
+    public static View findBackground(@NonNull View appWidget) {
+        List<View> backgrounds = findViewsWithId(appWidget, android.R.id.background);
+        if (backgrounds.size() == 1) {
+            return backgrounds.get(0);
+        }
+        // Really, the argument should contain the widget, so it cannot be the background.
+        if (appWidget instanceof ViewGroup) {
+            ViewGroup vg = (ViewGroup) appWidget;
+            if (vg.getChildCount() > 0) {
+                return findUndefinedBackground(vg.getChildAt(0));
+            }
+        }
+        return appWidget;
+    }
+
+    /**
+     * Check whether the app widget has opted out of the enforcement.
+     */
+    public static boolean hasAppWidgetOptedOut(@NonNull View appWidget, @NonNull View background) {
+        return background.getId() == android.R.id.background && background.getClipToOutline();
+    }
+
+    /** Check if the app widget is in the deny list. */
+    public static boolean isRoundedCornerEnabled(@NonNull View view) {
+        if (!Utilities.ATLEAST_S || !FeatureFlags.ENABLE_ENFORCED_ROUNDED_CORNERS.get()) {
+            return false;
+        }
+        // Here we need to test if the view's component is in the (to be created) deny list.
+        return true;
+    }
+
+    /**
+     * Computes the rounded rectangle needed for this app widget.
+     *
+     * @param appWidget View onto which the rounded rectangle will be applied.
+     * @param background Background view. This must be either {@code appWidget} or a descendant
+     *                  of {@code appWidget}.
+     * @param outRect Rectangle set to the rounded rectangle coordinates, in the reference frame
+     *                of {@code appWidget}.
+     */
+    public static void computeRoundedRectangle(@NonNull View appWidget, @NonNull View background,
+            @NonNull Rect outRect) {
+        outRect.left = 0;
+        outRect.right = background.getWidth();
+        outRect.top = 0;
+        outRect.bottom = background.getHeight();
+        while (background != appWidget) {
+            outRect.offset(background.getLeft(), background.getTop());
+            background = (View) background.getParent();
+        }
+    }
+
+    /**
+     * Computes the radius of the rounded rectangle that should be applied to a widget expanded
+     * in the given context.
+     */
+    public static float computeEnforcedRadius(@NonNull Context context) {
+        if (!Utilities.ATLEAST_S) {
+            return 0;
+        }
+        Resources res = context.getResources();
+        float systemRadius = res.getDimension(android.R.dimen.system_app_widget_background_radius);
+        float defaultRadius = res.getDimension(R.dimen.enforced_rounded_corner_max_radius);
+        return Math.min(defaultRadius, systemRadius);
+    }
+
+    private static List<View> findViewsWithId(View view, @IdRes int viewId) {
+        List<View> output = new ArrayList<>();
+        accumulateViewsWithId(view, viewId, output);
+        return output;
+    }
+
+    // Traverse views. If the predicate returns true, continue on the children, otherwise, don't.
+    private static void accumulateViewsWithId(View view, @IdRes int viewId, List<View> output) {
+        if (view.getId() == viewId) {
+            output.add(view);
+            return;
+        }
+        if (view instanceof ViewGroup) {
+            ViewGroup vg = (ViewGroup) view;
+            for (int i = 0; i < vg.getChildCount(); i++) {
+                accumulateViewsWithId(vg.getChildAt(i), viewId, output);
+            }
+        }
+    }
+
+    private static boolean isViewVisible(View view) {
+        if (view.getVisibility() != View.VISIBLE) {
+            return false;
+        }
+        return !view.willNotDraw() || view.getForeground() != null || view.getBackground() != null;
+    }
+
+    @Nullable
+    private static View findUndefinedBackground(View current) {
+        if (current.getVisibility() != View.VISIBLE) {
+            return null;
+        }
+        if (isViewVisible(current)) {
+            return current;
+        }
+        View lastVisibleView = null;
+        // Find the first view that is either not a ViewGroup, or a ViewGroup which will draw
+        // something, or a ViewGroup that contains more than one view.
+        if (current instanceof ViewGroup) {
+            ViewGroup vg = (ViewGroup) current;
+            for (int i = 0; i < vg.getChildCount(); i++) {
+                View visibleView = findUndefinedBackground(vg.getChildAt(i));
+                if (visibleView != null) {
+                    if (lastVisibleView != null) {
+                        return current; // At least two visible children
+                    }
+                    lastVisibleView = visibleView;
+                }
+            }
+        }
+        return lastVisibleView;
+    }
+}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index f43f712..29c00b2 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -34,6 +34,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.WindowInsets;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 import android.widget.TextView;
@@ -57,6 +58,7 @@
 import com.android.launcher3.widget.model.WidgetsListBaseEntry;
 import com.android.launcher3.widget.picker.search.SearchModeListener;
 import com.android.launcher3.widget.picker.search.WidgetsSearchBar;
+import com.android.launcher3.widget.picker.search.WidgetsSearchBarUIHelper;
 import com.android.launcher3.widget.util.WidgetsTableUtils;
 import com.android.launcher3.workprofile.PersonalWorkPagedView;
 import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.OnActivePageChangedListener;
@@ -70,7 +72,8 @@
  */
 public class WidgetsFullSheet extends BaseWidgetSheet
         implements Insettable, ProviderChangedListener, OnActivePageChangedListener,
-        WidgetsRecyclerView.HeaderViewDimensionsProvider, SearchModeListener {
+        WidgetsRecyclerView.HeaderViewDimensionsProvider, SearchModeListener,
+        WidgetsSearchBarUIHelper {
     private static final String TAG = WidgetsFullSheet.class.getSimpleName();
 
     private static final long DEFAULT_OPEN_DURATION = 267;
@@ -554,6 +557,17 @@
         return super.onBackPressed();
     }
 
+    @Override
+    public void onDragStart(boolean start, float startDisplacement) {
+        super.onDragStart(start, startDisplacement);
+        getWindowInsetsController().hide(WindowInsets.Type.ime());
+    }
+
+    @Override
+    public void clearSearchBarFocus() {
+        mSearchAndRecommendationViewHolder.mSearchBar.clearSearchBarFocus();
+    }
+
     /** A holder class for holding adapters & their corresponding recycler view. */
     private final class AdapterHolder {
         static final int PRIMARY = 0;
@@ -576,7 +590,9 @@
                     apps.getWidgetCache(),
                     apps.getIconCache(),
                     /* iconClickListener= */ WidgetsFullSheet.this,
-                    /* iconLongClickListener= */ WidgetsFullSheet.this);
+                    /* iconLongClickListener= */ WidgetsFullSheet.this,
+                    /* WidgetsSearchBarUIHelper= */
+                    mAdapterType == SEARCH ? WidgetsFullSheet.this : null);
             mWidgetsListAdapter.setHasStableIds(true);
             switch (mAdapterType) {
                 case PRIMARY:
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
index d841c64..d9c9d4d 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
@@ -41,6 +41,7 @@
 import com.android.launcher3.widget.model.WidgetsListContentEntry;
 import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
 import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry;
+import com.android.launcher3.widget.picker.search.WidgetsSearchBarUIHelper;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -69,6 +70,7 @@
     private static final int VIEW_TYPE_WIDGETS_HEADER = R.id.view_type_widgets_header;
     private static final int VIEW_TYPE_WIDGETS_SEARCH_HEADER = R.id.view_type_widgets_search_header;
 
+    @Nullable private final WidgetsSearchBarUIHelper mSearchBarUIHelper;
     private final WidgetsDiffReporter mDiffReporter;
     private final SparseArray<ViewHolderBinder> mViewHolderBinders = new SparseArray<>();
     private final WidgetsListTableViewHolderBinder mWidgetsListTableViewHolderBinder;
@@ -88,7 +90,9 @@
 
     public WidgetsListAdapter(Context context, LayoutInflater layoutInflater,
             WidgetPreviewLoader widgetPreviewLoader, IconCache iconCache,
-            OnClickListener iconClickListener, OnLongClickListener iconLongClickListener) {
+            OnClickListener iconClickListener, OnLongClickListener iconLongClickListener,
+            @Nullable WidgetsSearchBarUIHelper searchBarUIHelper) {
+        mSearchBarUIHelper = searchBarUIHelper;
         mDiffReporter = new WidgetsDiffReporter(iconCache, this);
         mWidgetsListTableViewHolderBinder = new WidgetsListTableViewHolderBinder(context,
                 layoutInflater, iconClickListener, iconLongClickListener,
@@ -237,6 +241,9 @@
 
     @Override
     public void onHeaderClicked(boolean showWidgets, PackageUserKey packageUserKey) {
+        if (mSearchBarUIHelper != null) {
+            mSearchBarUIHelper.clearSearchBarFocus();
+        }
         if (showWidgets) {
             mWidgetsContentVisiblePackageUserKey = packageUserKey;
             updateVisibleEntries();
diff --git a/src/com/android/launcher3/widget/picker/search/LauncherWidgetsSearchBar.java b/src/com/android/launcher3/widget/picker/search/LauncherWidgetsSearchBar.java
index cc33619..56a08b1 100644
--- a/src/com/android/launcher3/widget/picker/search/LauncherWidgetsSearchBar.java
+++ b/src/com/android/launcher3/widget/picker/search/LauncherWidgetsSearchBar.java
@@ -79,4 +79,9 @@
         super.onDetachedFromWindow();
         mController.onDestroy();
     }
+
+    @Override
+    public void clearSearchBarFocus() {
+        mController.clearFocus();
+    }
 }
diff --git a/src/com/android/launcher3/widget/picker/search/WidgetsSearchBar.java b/src/com/android/launcher3/widget/picker/search/WidgetsSearchBar.java
index ef7bf23..3ac82c0 100644
--- a/src/com/android/launcher3/widget/picker/search/WidgetsSearchBar.java
+++ b/src/com/android/launcher3/widget/picker/search/WidgetsSearchBar.java
@@ -35,6 +35,11 @@
     void reset();
 
     /**
+     * Clears focus from search bar.
+     */
+    void clearSearchBarFocus();
+
+    /**
      * Sets the vertical location, in pixels, of this search bar relative to its top position.
      */
     void setTranslationY(float translationY);
diff --git a/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarController.java b/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarController.java
index 6011097..d35a75b 100644
--- a/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarController.java
+++ b/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarController.java
@@ -103,8 +103,7 @@
     public void clearSearchResult() {
         mSearchAlgorithm.cancel(/* interruptActiveRequests= */ true);
         mInput.getText().clear();
-        mInput.clearFocus();
-        mInput.hideKeyboard();
+        clearFocus();
         mSearchModeListener.exitSearchMode();
     }
 
@@ -117,18 +116,24 @@
 
     @Override
     public boolean onBackKey() {
-        mInput.clearFocus();
-        mInput.hideKeyboard();
+        clearFocus();
         return true;
     }
 
     @Override
     public boolean onKey(View view, int keyCode, KeyEvent event) {
         if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) {
-            mInput.clearFocus();
-            mInput.hideKeyboard();
+            clearFocus();
             return true;
         }
         return false;
     }
+
+    /**
+     * Clears focus from edit text.
+     */
+    public void clearFocus() {
+        mInput.clearFocus();
+        mInput.hideKeyboard();
+    }
 }
diff --git a/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarUIHelper.java b/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarUIHelper.java
new file mode 100644
index 0000000..edfdc65
--- /dev/null
+++ b/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarUIHelper.java
@@ -0,0 +1,27 @@
+/*
+ * 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.search;
+
+/**
+ * UI helper for {@link WidgetsSearchBar}.
+ */
+public interface WidgetsSearchBarUIHelper {
+    /**
+     * Clears focus from the search bar.
+     */
+    void clearSearchBarFocus();
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/Widgets.java b/tests/tapl/com/android/launcher3/tapl/Widgets.java
index fe4c712..f084913 100644
--- a/tests/tapl/com/android/launcher3/tapl/Widgets.java
+++ b/tests/tapl/com/android/launcher3/tapl/Widgets.java
@@ -18,7 +18,6 @@
 
 import static com.android.launcher3.tapl.LauncherInstrumentation.WAIT_TIME_MS;
 
-import android.graphics.Point;
 import android.graphics.Rect;
 
 import androidx.test.uiautomator.By;
@@ -30,6 +29,7 @@
 import com.android.launcher3.testing.TestProtocol;
 
 import java.util.Collection;
+import java.util.List;
 
 /**
  * All widgets container.
@@ -100,17 +100,18 @@
         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
              LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
                      "getting widget " + labelText + " in widgets list")) {
+            final UiObject2 searchBar = findSearchBar();
             final UiObject2 fullWidgetsPicker = verifyActiveContainer();
             mLauncher.assertTrue("Widgets container didn't become scrollable",
                     fullWidgetsPicker.wait(Until.scrollable(true), WAIT_TIME_MS));
-            final Point displaySize = mLauncher.getRealDisplaySize();
 
-            Rect headerRect = new Rect();
-            final UiObject2 widgetsContainer = findTestAppWidgetsTableContainer(headerRect);
+            final UiObject2 widgetsContainer = findTestAppWidgetsTableContainer(searchBar);
             mLauncher.assertTrue("Can't locate widgets list for the test app: "
                             + mLauncher.getLauncherPackageName(),
                     widgetsContainer != null);
             final BySelector labelSelector = By.clazz("android.widget.TextView").text(labelText);
+            final BySelector previewSelector = By.res(mLauncher.getLauncherPackageName(),
+                    "widget_preview");
             int i = 0;
             for (; ; ) {
                 final Collection<UiObject2> tableRows = widgetsContainer.getChildren();
@@ -125,19 +126,28 @@
                                 "View is not WidgetCell",
                                 "com.android.launcher3.widget.WidgetCell",
                                 widget.getClassName());
-
-                        return new Widget(mLauncher, widget);
+                        UiObject2 preview = widget.findObject(previewSelector);
+                        mLauncher.assertTrue("Can't find widget preview", preview != null);
+                        Rect previewRect = new Rect(preview.getVisibleBounds());
+                        boolean intersected = searchBar.getVisibleBounds().intersect(previewRect);
+                        if (intersected) {
+                            Rect scrollUp = new Rect(/* left= */ 0, /* top= */0, /* right*/ 0,
+                                    /* bottom= */ searchBar.getVisibleBounds().height());
+                            mLauncher.scroll(
+                                    fullWidgetsPicker,
+                                    Direction.UP,
+                                    scrollUp,
+                                    /* steps= */ 2,
+                                    /* slowDown= */ true);
+                        }
+                        preview = widget.findObject(previewSelector);
+                        return new Widget(mLauncher, preview);
                     }
                 }
 
                 mLauncher.assertTrue("Too many attempts", ++i <= 40);
                 final int scroll = getWidgetsScroll();
-                mLauncher.scroll(
-                        fullWidgetsPicker,
-                        Direction.DOWN,
-                        headerRect,
-                        10,
-                        true);
+                mLauncher.scrollToLastVisibleRow(fullWidgetsPicker, tableRows, 0);
                 final int newScroll = getWidgetsScroll();
                 mLauncher.assertTrue(
                         "Scrolled in a wrong direction in Widgets: from " + scroll + " to "
@@ -147,8 +157,21 @@
         }
     }
 
+    private UiObject2 findSearchBar() {
+        final BySelector searchBarContainerSelector = By.res(mLauncher.getLauncherPackageName(),
+                "search_and_recommendations_container");
+        final BySelector searchBarSelector = By.res(mLauncher.getLauncherPackageName(),
+                "widgets_search_bar");
+        final UiObject2 searchBarContainer = mLauncher.waitForLauncherObject(
+                searchBarContainerSelector);
+        mLauncher.assertTrue("Can't find a search bar container", searchBarContainer != null);
+        UiObject2 searchBar = searchBarContainer.findObject(searchBarSelector);
+        mLauncher.assertTrue("Can't find a search bar", searchBar != null);
+        return searchBar;
+    }
+
     /** Finds the widgets list of this test app from the collapsed full widgets picker. */
-    private UiObject2 findTestAppWidgetsTableContainer(Rect outHeaderRect) {
+    private UiObject2 findTestAppWidgetsTableContainer(final UiObject2 searchBar) {
         final BySelector headerSelector = By.res(mLauncher.getLauncherPackageName(),
                 "widgets_list_header");
         final BySelector targetAppSelector = By.clazz("android.widget.TextView").text(
@@ -161,12 +184,23 @@
             UiObject2 fullWidgetsPicker = verifyActiveContainer();
 
             UiObject2 header = fullWidgetsPicker.findObject(headerSelector);
-            outHeaderRect.set(0, 0, 0, header.getVisibleBounds().height());
             mLauncher.assertTrue("Can't find a widget header", header != null);
 
             // Look for a header that has the test app name.
             UiObject2 headerTitle = fullWidgetsPicker.findObject(targetAppSelector);
             if (headerTitle != null) {
+                Rect headerTitleRect = new Rect(headerTitle.getVisibleBounds());
+                boolean intersected = searchBar.getVisibleBounds().intersect(headerTitleRect);
+                if (intersected) {
+                    Rect scrollUp = new Rect(/* left= */ 0, /* top= */0, /* right*/ 0,
+                            /* bottom= */ searchBar.getVisibleBounds().height());
+                    mLauncher.scroll(
+                            fullWidgetsPicker,
+                            Direction.UP,
+                            scrollUp,
+                            /* steps= */ 2,
+                            /* slowDown= */ true);
+                }
                 // If we find the header and it has not been expanded, let's click it to see the
                 // widgets list.
                 if (!hasHeaderExpanded) {
@@ -185,14 +219,11 @@
                 if (widgetsContainer != null) {
                     return widgetsContainer;
                 }
-
+                mLauncher.scrollToLastVisibleRow(fullWidgetsPicker, List.of(headerTitle), 0);
+            } else {
+                mLauncher.scrollToLastVisibleRow(fullWidgetsPicker, fullWidgetsPicker.getChildren(),
+                        0);
             }
-            mLauncher.scroll(
-                    fullWidgetsPicker,
-                    Direction.DOWN,
-                    outHeaderRect,
-                    /* steps= */ 10,
-                    /* slowDown= */ true);
         }
 
         return null;