Merge "Import translations. DO NOT MERGE ANYWHERE" into tm-dev
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 0e391ce..36c9d13 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -526,7 +526,7 @@
             endListener = composeViewContentAnimator(launcherAnimator, alphas, scales);
         } else {
             List<View> viewsToAnimate = new ArrayList<>();
-            Workspace workspace = mLauncher.getWorkspace();
+            Workspace<?> workspace = mLauncher.getWorkspace();
             workspace.forEachVisiblePage(
                     view -> viewsToAnimate.add(((CellLayout) view).getShortcutsAndWidgets()));
 
diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduController.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
index 680012c..d63bc18 100644
--- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
@@ -131,7 +131,7 @@
     private int placeFoldersInWorkspace(ArrayDeque<FolderInfo> folders) {
         if (folders.isEmpty()) return 0;
 
-        Workspace workspace = mLauncher.getWorkspace();
+        Workspace<?> workspace = mLauncher.getWorkspace();
         InvariantDeviceProfile idp = mLauncher.getDeviceProfile().inv;
 
         GridOccupancy[] occupancyList = new GridOccupancy[workspace.getChildCount()];
@@ -176,7 +176,7 @@
      * @return pageId where items are migrated
      */
     private int migrateHotseatWhole() {
-        Workspace workspace = mLauncher.getWorkspace();
+        Workspace<?> workspace = mLauncher.getWorkspace();
 
         int pageId = -1;
         int toRow = 0;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 296000b..a22398d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -29,6 +29,7 @@
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
 import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
 import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_EXTRA_NAVIGATION_BAR;
+import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_SIZE;
 
 import android.animation.AnimatorSet;
 import android.app.ActivityOptions;
@@ -214,8 +215,12 @@
         );
         // Adjust the frame by the rounded corners (ie. leaving just the bar as the inset) when
         // the IME is showing
-        mWindowLayoutParams.providedInternalImeInsets = Insets.of(0,
+        mWindowLayoutParams.providedInternalImeInsets = new Insets[ITYPE_SIZE];
+        final Insets reducingSize = Insets.of(0,
                 getDefaultTaskbarWindowHeight() - mTaskbarHeightForIme, 0, 0);
+        mWindowLayoutParams.providedInternalImeInsets[ITYPE_EXTRA_NAVIGATION_BAR] = reducingSize;
+        mWindowLayoutParams.providedInternalImeInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT] =
+                reducingSize;
 
         mWindowLayoutParams.insetsRoundedCornerFrame = true;
 
@@ -563,8 +568,14 @@
             }
         }
         mWindowLayoutParams.height = height;
-        mWindowLayoutParams.providedInternalImeInsets =
+        final Insets reducingSize =
                 Insets.of(0, height - mTaskbarHeightForIme, 0, 0);
+        if (mWindowLayoutParams.providedInternalImeInsets == null) {
+            mWindowLayoutParams.providedInternalImeInsets = new Insets[ITYPE_SIZE];
+        }
+        mWindowLayoutParams.providedInternalImeInsets[ITYPE_EXTRA_NAVIGATION_BAR] = reducingSize;
+        mWindowLayoutParams.providedInternalImeInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT] =
+                reducingSize;
         mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 8e31a74..e02a9d7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -19,6 +19,7 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
 
+import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
 import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
 
 import android.content.ComponentCallbacks;
@@ -41,7 +42,6 @@
 import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.launcher3.taskbar.unfold.NonDestroyableScopedUnfoldTransitionProgressProvider;
 import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.DisplayController.Info;
 import com.android.launcher3.util.SettingsCache;
 import com.android.launcher3.util.SimpleBroadcastReceiver;
 import com.android.quickstep.RecentsActivity;
@@ -55,7 +55,7 @@
 /**
  * Class to manage taskbar lifecycle
  */
-public class TaskbarManager implements DisplayController.DisplayInfoChangeListener {
+public class TaskbarManager {
 
     private static final Uri USER_SETUP_COMPLETE_URI = Settings.Secure.getUriFor(
             Settings.Secure.USER_SETUP_COMPLETE);
@@ -91,8 +91,15 @@
      * navigation mode, that callback gets called too soon, before it's internal navigation mode
      * reflects the current one.
      * DisplayController's callback is delayed enough to get the correct nav mode value
+     *
+     * We also use density change here because DeviceProfile has had a chance to update it's state
+     * whereas density for component callbacks registered in this class don't update DeviceProfile.
+     * Confused? Me too. Make it less confusing (TODO: b/227669780)
+     *
+     * Flags used with {@link #mDispInfoChangeListener}
      */
-    private static final int CHANGE_FLAGS = CHANGE_NAVIGATION_MODE;
+    private static final int CHANGE_FLAGS = CHANGE_NAVIGATION_MODE | CHANGE_DENSITY;
+    private final DisplayController.DisplayInfoChangeListener mDispInfoChangeListener;
 
     private boolean mUserUnlocked = false;
 
@@ -105,6 +112,7 @@
                 SystemUiProxy.INSTANCE.get(mContext), new Handler());
         mUserSetupCompleteListener = isUserSetupComplete -> recreateTaskbar();
         mNavBarKidsModeListener = isNavBarKidsMode -> recreateTaskbar();
+        // TODO(b/227669780): Consolidate this w/ DisplayController callbacks
         mComponentCallbacks = new ComponentCallbacks() {
             private Configuration mOldConfig = mContext.getResources().getConfiguration();
 
@@ -116,7 +124,7 @@
                 int configDiff = mOldConfig.diff(newConfig);
                 int configsRequiringRecreate = ActivityInfo.CONFIG_ASSETS_PATHS
                         | ActivityInfo.CONFIG_LAYOUT_DIRECTION | ActivityInfo.CONFIG_UI_MODE
-                        | ActivityInfo.CONFIG_DENSITY | ActivityInfo.CONFIG_SCREEN_SIZE;
+                        | ActivityInfo.CONFIG_SCREEN_SIZE;
                 boolean requiresRecreate = (configDiff & configsRequiringRecreate) != 0;
                 if ((configDiff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0
                         && mTaskbarActivityContext != null && dp != null) {
@@ -151,8 +159,12 @@
             public void onLowMemory() { }
         };
         mShutdownReceiver = new SimpleBroadcastReceiver(i -> destroyExistingTaskbar());
-
-        mDisplayController.addChangeListener(this);
+        mDispInfoChangeListener = (context, info, flags) -> {
+            if ((flags & CHANGE_FLAGS) != 0) {
+                recreateTaskbar();
+            }
+        };
+        mDisplayController.addChangeListener(mDispInfoChangeListener);
         SettingsCache.INSTANCE.get(mContext).register(USER_SETUP_COMPLETE_URI,
                 mUserSetupCompleteListener);
         SettingsCache.INSTANCE.get(mContext).register(NAV_BAR_KIDS_MODE,
@@ -163,13 +175,6 @@
         recreateTaskbar();
     }
 
-    @Override
-    public void onDisplayInfoChanged(Context context, Info info, int flags) {
-        if ((flags & CHANGE_FLAGS) != 0) {
-            recreateTaskbar();
-        }
-    }
-
     private void destroyExistingTaskbar() {
         if (mTaskbarActivityContext != null) {
             mTaskbarActivityContext.onDestroy();
@@ -310,7 +315,7 @@
      */
     public void destroy() {
         destroyExistingTaskbar();
-        mDisplayController.removeChangeListener(this);
+        mDisplayController.removeChangeListener(mDispInfoChangeListener);
         SettingsCache.INSTANCE.get(mContext).unregister(USER_SETUP_COMPLETE_URI,
                 mUserSetupCompleteListener);
         SettingsCache.INSTANCE.get(mContext).unregister(NAV_BAR_KIDS_MODE,
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 829accc..f32b315 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -263,7 +263,7 @@
 
         switch (state.ordinal) {
             case HINT_STATE_ORDINAL: {
-                Workspace workspace = getWorkspace();
+                Workspace<?> workspace = getWorkspace();
                 getStateManager().goToState(NORMAL);
                 if (workspace.getNextPage() != Workspace.DEFAULT_PAGE) {
                     workspace.post(workspace::moveToDefaultScreen);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index 4d05349..b1d83e7 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -118,7 +118,7 @@
             config.duration = Math.max(config.duration, scrollDuration);
             overview.snapToPage(DEFAULT_PAGE, Math.toIntExact(config.duration));
 
-            Workspace workspace = mActivity.getWorkspace();
+            Workspace<?> workspace = mActivity.getWorkspace();
             // Start from a higher workspace scale, but only if we're invisible so we don't jump.
             boolean isWorkspaceVisible = workspace.getVisibility() == VISIBLE;
             if (isWorkspaceVisible) {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index 86c42ca..4d3b057 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -21,7 +21,7 @@
 import static com.android.launcher3.LauncherAnimUtils.newCancelListener;
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
+import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PULL_BACK_PROGRESS;
 import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
 import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_EDU;
@@ -147,7 +147,7 @@
             AbstractFloatingView.closeOpenContainer(mLauncher, AbstractFloatingView.TYPE_TASK_MENU);
         } else if (mStartState == ALL_APPS) {
             AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
-            builder.setFloat(allAppsController, ALL_APPS_PROGRESS,
+            builder.setFloat(allAppsController, ALL_APPS_PULL_BACK_PROGRESS,
                     -mPullbackDistance / allAppsController.getShiftRange(), PULLBACK_INTERPOLATOR);
 
             // Slightly fade out all apps content to further distinguish from scrolling.
diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
index 6f171f9..97be437 100644
--- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
+++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
@@ -45,7 +45,7 @@
     // Percentage of the width of the quick search bar that will be reduced
     // from the both sides of the bar when progress is 0
     private static final float MAX_WIDTH_INSET_FRACTION = 0.15f;
-    private static final FloatProperty<Workspace> WORKSPACE_SCALE_PROPERTY =
+    private static final FloatProperty<Workspace<?>> WORKSPACE_SCALE_PROPERTY =
             WORKSPACE_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_UNFOLD_ANIMATION);
     private static final FloatProperty<Hotseat> HOTSEAT_SCALE_PROPERTY =
             HOTSEAT_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_UNFOLD_ANIMATION);
diff --git a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index 44396fa..b1e2eac 100644
--- a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -92,7 +92,7 @@
 
         if (staggerWorkspace) {
             DeviceProfile grid = launcher.getDeviceProfile();
-            Workspace workspace = launcher.getWorkspace();
+            Workspace<?> workspace = launcher.getWorkspace();
             Hotseat hotseat = launcher.getHotseat();
 
             // Hotseat and QSB takes up two additional rows.
diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
index 70fde1d..b222f51 100644
--- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
@@ -56,6 +56,7 @@
     private final int mTaskId;
     private final ComponentName mComponentName;
     private final SurfaceControl mLeash;
+    private final Rect mSourceRectHint = new Rect();
     private final Rect mAppBounds = new Rect();
     private final Matrix mHomeToWindowPositionMap = new Matrix();
     private final Rect mStartBounds = new Rect();
@@ -140,6 +141,7 @@
         }
 
         if (sourceRectHint == null) {
+            mSourceRectHint.setEmpty();
             mSourceHintRectInsets = null;
 
             // Create a new overlay layer
@@ -169,6 +171,7 @@
                 t.apply();
             });
         } else {
+            mSourceRectHint.set(sourceRectHint);
             mSourceHintRectInsets = new Rect(sourceRectHint.left - appBounds.left,
                     sourceRectHint.top - appBounds.top,
                     appBounds.right - sourceRectHint.right,
@@ -249,7 +252,8 @@
             return mSurfaceTransactionHelper.scaleAndRotate(tx, mLeash, mAppBounds, bounds, insets,
                     rotatedPosition.degree, rotatedPosition.positionX, rotatedPosition.positionY);
         } else {
-            return mSurfaceTransactionHelper.scaleAndCrop(tx, mLeash, mAppBounds, bounds, insets);
+            return mSurfaceTransactionHelper.scaleAndCrop(tx, mLeash, mSourceRectHint, mAppBounds,
+                    bounds, insets);
         }
     }
 
diff --git a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
index 3d72398..354d157 100644
--- a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
@@ -37,7 +37,7 @@
 
     @Override
     protected void onPrepareViewsForAnimation() {
-        Workspace workspace = mLauncher.getWorkspace();
+        Workspace<?> workspace = mLauncher.getWorkspace();
 
         // App icons and widgets
         workspace
diff --git a/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java b/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java
index 5326d2b..5eb543e 100644
--- a/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java
+++ b/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java
@@ -53,7 +53,7 @@
 
     // Should be used for animations running alongside this WorkspaceRevealAnim.
     public static final int DURATION_MS = 350;
-    private static final FloatProperty<Workspace> WORKSPACE_SCALE_PROPERTY =
+    private static final FloatProperty<Workspace<?>> WORKSPACE_SCALE_PROPERTY =
             WORKSPACE_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_REVEAL_ANIM);
 
     private static final FloatProperty<Hotseat> HOTSEAT_SCALE_PROPERTY =
@@ -68,7 +68,7 @@
         ResourceProvider rp = DynamicResource.provider(launcher);
         mScaleStart = rp.getFloat(R.dimen.swipe_up_scale_start);
 
-        Workspace workspace = launcher.getWorkspace();
+        Workspace<?> workspace = launcher.getWorkspace();
         workspace.setPivotToScaleWithSelf(launcher.getHotseat());
 
         // Add reveal animations.
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index 6b15807..99a2d6f 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -155,7 +155,7 @@
     public void setInsets(Rect insets) {
         mInsets.set(insets);
         updateVerticalMargin(DisplayController.getNavigationMode(getContext()));
-        updatePaddingAndTranslations();
+        updatePadding();
     }
 
     public void updateHiddenFlags(@ActionsHiddenFlags int visibilityFlags, boolean enable) {
@@ -199,10 +199,9 @@
     }
 
     /**
-     * Aligns OverviewActionsView vertically with and offsets horizontal position based on
-     * 3 button nav container in taskbar.
+     * Offsets OverviewActionsView horizontal position based on 3 button nav container in taskbar.
      */
-    private void updatePaddingAndTranslations() {
+    private void updatePadding() {
         boolean alignFor3ButtonTaskbar = mDp.isTaskbarPresent &&
                 DisplayController.getNavigationMode(getContext()) == THREE_BUTTONS;
         if (alignFor3ButtonTaskbar) {
@@ -213,20 +212,8 @@
             } else {
                 setPadding(mInsets.left, 0, mInsets.right + additionalPadding, 0);
             }
-
-            // Align vertically, using taskbar height + mDp.taskbarOffsetY() to estimate where
-            // the button nav top is.
-            int marginBottom = getOverviewActionsBottomMarginPx(
-                    DisplayController.getNavigationMode(getContext()), mDp);
-            int actionsTop =
-                    (mDp.heightPx - marginBottom - mInsets.bottom) - mDp.overviewActionsHeight;
-            int navTop = mDp.heightPx - (mDp.taskbarSize + mDp.getTaskbarOffsetY());
-            int transY = navTop - actionsTop + ((mDp.taskbarSize - mDp.overviewActionsHeight) / 2);
-            setTranslationY(transY);
         } else {
             setPadding(mInsets.left, 0, mInsets.right, 0);
-            setTranslationX(0);
-            setTranslationY(0);
         }
     }
 
@@ -287,19 +274,28 @@
 
     /** Get the bottom margin associated with the action buttons in Overview. */
     public static int getOverviewActionsBottomMarginPx(NavigationMode mode, DeviceProfile dp) {
-        int inset = dp.getInsets().bottom;
+        int bottomInset = dp.getInsets().bottom;
 
         if (dp.isVerticalBarLayout()) {
-            return inset;
+            return bottomInset;
         }
 
-        // Actions button will be aligned with nav buttons in updatePaddingAndTranslations().
         if (mode == NavigationMode.THREE_BUTTONS) {
-            return dp.overviewActionsMarginThreeButtonPx + inset;
+            int bottomMargin = dp.overviewActionsMarginThreeButtonPx + bottomInset;
+            if (dp.isTaskbarPresent) {
+                // Align vertically, using taskbar height + mDp.taskbarOffsetY() to estimate where
+                // the button nav top is.
+                int actionsTop = (dp.heightPx - bottomMargin - bottomInset)
+                        - dp.overviewActionsHeight;
+                int navTop = dp.heightPx - (dp.taskbarSize + dp.getTaskbarOffsetY());
+                bottomMargin -=
+                        navTop - actionsTop + ((dp.taskbarSize - dp.overviewActionsHeight) / 2);
+            }
+            return bottomMargin;
         }
 
         // There is no bottom inset when taskbar is present, use stashed taskbar as padding instead.
         return dp.overviewActionsBottomMarginGesturePx
-                + (dp.isTaskbarPresent ? dp.stashedTaskbarSize : inset);
+                + (dp.isTaskbarPresent ? dp.stashedTaskbarSize : bottomInset);
     }
 }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 3fa0169..c6d26a1 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -383,7 +383,7 @@
     private static final float ANIMATION_DISMISS_PROGRESS_MIDPOINT = 0.5f;
     private static final float END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET = 0.75f;
 
-    private static final float SIGNIFICANT_MOVE_THRESHOLD_TABLET = 0.15f;
+    private static final float SIGNIFICANT_MOVE_SCREEN_WIDTH_PERCENTAGE = 0.15f;
 
     protected final RecentsOrientedState mOrientationState;
     protected final BaseActivityInterface<STATE_TYPE, ACTIVITY_TYPE> mSizeStrategy;
@@ -1195,9 +1195,14 @@
     }
 
     @Override
-    protected float getSignificantMoveThreshold() {
-        return mActivity.getDeviceProfile().isTablet ? SIGNIFICANT_MOVE_THRESHOLD_TABLET
-                : super.getSignificantMoveThreshold();
+    protected boolean isSignificantMove(float absoluteDelta, int pageOrientedSize) {
+        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+        if (!deviceProfile.isTablet) {
+            return super.isSignificantMove(absoluteDelta, pageOrientedSize);
+        }
+
+        return absoluteDelta
+                > deviceProfile.availableWidthPx * SIGNIFICANT_MOVE_SCREEN_WIDTH_PERCENTAGE;
     }
 
     @Override
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index 602dd6d..eb347f2 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -38,10 +38,10 @@
 
 <!-- Hotseat -->
     <dimen name="dynamic_grid_hotseat_side_padding">0dp</dimen>
-    <dimen name="spring_loaded_hotseat_top_margin">97dp</dimen>
+    <dimen name="spring_loaded_hotseat_top_margin">65dp</dimen>
 
 <!-- Dragging -->
-    <dimen name="drop_target_top_margin">34dp</dimen>
+    <dimen name="drop_target_top_margin">64dp</dimen>
     <dimen name="drop_target_bottom_margin">16dp</dimen>
     <dimen name="drop_target_button_drawable_horizontal_padding">16dp</dimen>
     <dimen name="drop_target_button_drawable_vertical_padding">16dp</dimen>
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
index 3ec211a..fad8c95 100644
--- a/res/values-sw720dp/dimens.xml
+++ b/res/values-sw720dp/dimens.xml
@@ -28,11 +28,11 @@
     <dimen name="drop_target_button_drawable_horizontal_padding">24dp</dimen>
     <dimen name="drop_target_button_drawable_vertical_padding">20dp</dimen>
     <dimen name="drop_target_button_gap">32dp</dimen>
-    <dimen name="drop_target_top_margin">32dp</dimen>
-    <dimen name="drop_target_bottom_margin">32dp</dimen>
+    <dimen name="drop_target_top_margin">110dp</dimen>
+    <dimen name="drop_target_bottom_margin">48dp</dimen>
 
 <!-- Hotseat -->
-    <dimen name="spring_loaded_hotseat_top_margin">164dp</dimen>
+    <dimen name="spring_loaded_hotseat_top_margin">108dp</dimen>
 
 <!-- Widget picker-->
     <dimen name="widget_list_horizontal_margin">30dp</dimen>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index ae4c310..97d02d0 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -52,7 +52,7 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"İş"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Görüşmeler"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Faydalı bilgiler parmaklarınızın ucunda"</string>
-    <string name="widget_education_content" msgid="1731667670753497052">"Uygulamaları açmadan bilgi almak için ana ekranınıza widget\'lar ekleyebilirsiniz"</string>
+    <string name="widget_education_content" msgid="1731667670753497052">"Uygulama açmadan bilgi almak için ana ekranınıza widget ekleyebilirsiniz"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Widget ayarlarını değiştirmek için dokunun"</string>
     <string name="widget_education_close_button" msgid="8676165703104836580">"Anladım"</string>
     <string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Widget ayarlarını değiştir"</string>
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index 300f22b..4b4a017 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -383,7 +383,7 @@
 
         // Handle invalid resize across CellLayouts in the two panel UI.
         if (mCellLayout.getParent() instanceof Workspace) {
-            Workspace workspace = (Workspace) mCellLayout.getParent();
+            Workspace<?> workspace = (Workspace<?>) mCellLayout.getParent();
             CellLayout pairedCellLayout = workspace.getScreenPair(mCellLayout);
             if (pairedCellLayout != null) {
                 Rect focusedCellLayoutBound = sTmpRect;
@@ -570,7 +570,7 @@
         final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
         final CellLayout pairedCellLayout;
         if (mCellLayout.getParent() instanceof Workspace) {
-            Workspace workspace = (Workspace) mCellLayout.getParent();
+            Workspace<?> workspace = (Workspace<?>) mCellLayout.getParent();
             pairedCellLayout = workspace.getScreenPair(mCellLayout);
         } else {
             pairedCellLayout = null;
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index f7133c4..87bbac6 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -1203,7 +1203,7 @@
             return getContext().getString(R.string.move_to_hotseat_position,
                     Math.max(cellX, cellY) + 1);
         } else {
-            Workspace workspace = getWorkspace();
+            Workspace<?> workspace = getWorkspace();
             int row = cellY + 1;
             int col = workspace.mIsRtl ? mCountX - cellX : cellX + 1;
             int panelCount = workspace.getPanelCount();
@@ -1217,7 +1217,7 @@
         }
     }
 
-    private Workspace getWorkspace() {
+    private Workspace<?> getWorkspace() {
         return Launcher.cast(mActivity).getWorkspace();
     }
 
diff --git a/src/com/android/launcher3/DropTargetBar.java b/src/com/android/launcher3/DropTargetBar.java
index 54f769b..ec3629d 100644
--- a/src/com/android/launcher3/DropTargetBar.java
+++ b/src/com/android/launcher3/DropTargetBar.java
@@ -179,7 +179,7 @@
         }
 
         Launcher launcher = Launcher.getLauncher(getContext());
-        Workspace workspace = launcher.getWorkspace();
+        Workspace<?> workspace = launcher.getWorkspace();
         DeviceProfile dp = launcher.getDeviceProfile();
         int buttonHorizontalPadding = dp.dropTargetHorizontalPaddingPx;
         int buttonVerticalPadding = dp.dropTargetVerticalPaddingPx;
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 9c749aa..d1d6c18 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -41,7 +41,7 @@
 
     @ViewDebug.ExportedProperty(category = "launcher")
     private boolean mHasVerticalHotseat;
-    private Workspace mWorkspace;
+    private Workspace<?> mWorkspace;
     private boolean mSendTouchToWorkspace;
     @Nullable
     private Consumer<Boolean> mOnVisibilityAggregatedCallback;
@@ -122,7 +122,7 @@
         InsettableFrameLayout.dispatchInsets(this, insets);
     }
 
-    public void setWorkspace(Workspace w) {
+    public void setWorkspace(Workspace<?> w) {
         mWorkspace = w;
     }
 
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 3cc8a81..923e614 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -2360,7 +2360,7 @@
         // Get the list of added items and intersect them with the set of items here
         final Collection<Animator> bounceAnims = new ArrayList<>();
         boolean canAnimatePageChange = canAnimatePageChange();
-        Workspace workspace = mWorkspace;
+        Workspace<?> workspace = mWorkspace;
         int newItemsScreenId = -1;
         int end = items.size();
         View newView = null;
diff --git a/src/com/android/launcher3/LauncherAnimUtils.java b/src/com/android/launcher3/LauncherAnimUtils.java
index 4f3ae59..808bf96 100644
--- a/src/com/android/launcher3/LauncherAnimUtils.java
+++ b/src/com/android/launcher3/LauncherAnimUtils.java
@@ -72,8 +72,8 @@
      * of all the ones set, to have a smooth experience even in the case of overlapping scaling
      * animation.
      */
-    public static final MultiScalePropertyFactory<Workspace> WORKSPACE_SCALE_PROPERTY_FACTORY =
-            new MultiScalePropertyFactory<Workspace>("workspace_scale_property");
+    public static final MultiScalePropertyFactory<Workspace<?>> WORKSPACE_SCALE_PROPERTY_FACTORY =
+            new MultiScalePropertyFactory<Workspace<?>>("workspace_scale_property");
 
     /** Property to set the scale of hotseat. */
     public static final MultiScalePropertyFactory<Hotseat> HOTSEAT_SCALE_PROPERTY_FACTORY =
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 1eb493b..f5ac359 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -1195,8 +1195,8 @@
         mAllowOverScroll = enable;
     }
 
-    protected float getSignificantMoveThreshold() {
-        return SIGNIFICANT_MOVE_THRESHOLD;
+    protected boolean isSignificantMove(float absoluteDelta, int pageOrientedSize) {
+        return absoluteDelta > pageOrientedSize * SIGNIFICANT_MOVE_THRESHOLD;
     }
 
     @Override
@@ -1322,13 +1322,12 @@
                 velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
 
                 int velocity = (int) mOrientationHandler.getPrimaryVelocity(velocityTracker,
-                    mActivePointerId);
+                        mActivePointerId);
                 float delta = primaryDirection - mDownMotionPrimary;
-                delta /= mOrientationHandler.getPrimaryScale(this);
-                int pageOrientedSize = mOrientationHandler.getMeasuredSize(getPageAt(mCurrentPage));
-
-                boolean isSignificantMove = Math.abs(delta)
-                        > pageOrientedSize * getSignificantMoveThreshold();
+                int pageOrientedSize = (int) (mOrientationHandler.getMeasuredSize(
+                        getPageAt(mCurrentPage))
+                        * mOrientationHandler.getPrimaryScale(this));
+                boolean isSignificantMove = isSignificantMove(Math.abs(delta), pageOrientedSize);
 
                 mTotalMotion += Math.abs(mLastMotion + mLastMotionRemainder - primaryDirection);
                 boolean passedSlop = mAllowEasyFling || mTotalMotion > mPageSlop;
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 61090e7..86e88b7 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -149,6 +149,8 @@
      * {@link #isFinishedSwitchingState()} ()} to return true. */
     private static final float FINISHED_SWITCHING_STATE_TRANSITION_PROGRESS = 0.5f;
 
+    private static final float SIGNIFICANT_MOVE_SCREEN_WIDTH_PERCENTAGE = 0.15f;
+
     private static final boolean ENFORCE_DRAG_EVENT_ORDER = false;
 
     private static final int ADJACENT_SCREEN_DROP_DURATION = 300;
@@ -3410,6 +3412,17 @@
         return getContext().getString(R.string.workspace_scroll_format, currentPage, totalPages);
     }
 
+    @Override
+    protected boolean isSignificantMove(float absoluteDelta, int pageOrientedSize) {
+        DeviceProfile deviceProfile = mLauncher.getDeviceProfile();
+        if (!deviceProfile.isTablet) {
+            return super.isSignificantMove(absoluteDelta, pageOrientedSize);
+        }
+
+        return absoluteDelta
+                > deviceProfile.availableWidthPx * SIGNIFICANT_MOVE_SCREEN_WIDTH_PERCENTAGE;
+    }
+
     /**
      * Used as a workaround to ensure that the AppWidgetService receives the
      * PACKAGE_ADDED broadcast before updating widgets.
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index 1e09b2d..84b95ec 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -67,18 +67,18 @@
  */
 public class WorkspaceStateTransitionAnimation {
 
-    private static final FloatProperty<Workspace> WORKSPACE_SCALE_PROPERTY =
+    private static final FloatProperty<Workspace<?>> WORKSPACE_SCALE_PROPERTY =
             WORKSPACE_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_WORKSPACE_STATE);
 
     private static final FloatProperty<Hotseat> HOTSEAT_SCALE_PROPERTY =
             HOTSEAT_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_WORKSPACE_STATE);
 
     private final Launcher mLauncher;
-    private final Workspace mWorkspace;
+    private final Workspace<?> mWorkspace;
 
     private float mNewScale;
 
-    public WorkspaceStateTransitionAnimation(Launcher launcher, Workspace workspace) {
+    public WorkspaceStateTransitionAnimation(Launcher launcher, Workspace<?> workspace) {
         mLauncher = launcher;
         mWorkspace = workspace;
     }
@@ -224,7 +224,7 @@
      * Returns a spring based animator for the scale property of {@param workspace}.
      */
     public static ValueAnimator getWorkspaceSpringScaleAnimator(Launcher launcher,
-            Workspace workspace, float scale) {
+            Workspace<?> workspace, float scale) {
         return getSpringScaleAnimator(launcher, workspace, scale, WORKSPACE_SCALE_PROPERTY);
     }
 
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index 18c05eb..462daf5 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -19,7 +19,7 @@
 import com.android.launcher3.ButtonDropTarget;
 import com.android.launcher3.CellLayout;
 import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.PendingAddItemInfo;
 import com.android.launcher3.R;
 import com.android.launcher3.Workspace;
@@ -153,61 +153,9 @@
         } else if (action == MOVE) {
             return beginAccessibleDrag(host, item, fromKeyboard);
         } else if (action == ADD_TO_WORKSPACE) {
-            final int[] coordinates = new int[2];
-            final int screenId = findSpaceOnWorkspace(item, coordinates);
-            if (screenId == -1) {
-                return false;
-            }
-            mContext.getStateManager().goToState(NORMAL, true, forSuccessCallback(() -> {
-                if (item instanceof AppInfo) {
-                    WorkspaceItemInfo info = ((AppInfo) item).makeWorkspaceItem();
-                    mContext.getModelWriter().addItemToDatabase(info,
-                            Favorites.CONTAINER_DESKTOP,
-                            screenId, coordinates[0], coordinates[1]);
-
-                    mContext.bindItems(
-                            Collections.singletonList(info),
-                            /* forceAnimateIcons= */ true,
-                            /* focusFirstItemForAccessibility= */ true);
-                    announceConfirmation(R.string.item_added_to_workspace);
-                } else if (item instanceof PendingAddItemInfo) {
-                    PendingAddItemInfo info = (PendingAddItemInfo) item;
-                    Workspace workspace = mContext.getWorkspace();
-                    workspace.snapToPage(workspace.getPageIndexForScreenId(screenId));
-                    mContext.addPendingItem(info, Favorites.CONTAINER_DESKTOP,
-                            screenId, coordinates, info.spanX, info.spanY);
-                }
-                else if (item instanceof WorkspaceItemInfo) {
-                    WorkspaceItemInfo info = ((WorkspaceItemInfo) item).clone();
-                    mContext.getModelWriter().addItemToDatabase(info,
-                            Favorites.CONTAINER_DESKTOP,
-                            screenId, coordinates[0], coordinates[1]);
-                    mContext.bindItems(Collections.singletonList(info), true, true);
-                }
-            }));
-            return true;
+            return addToWorkspace(item, true);
         } else if (action == MOVE_TO_WORKSPACE) {
-            Folder folder = Folder.getOpen(mContext);
-            folder.close(true);
-            WorkspaceItemInfo info = (WorkspaceItemInfo) item;
-            folder.getInfo().remove(info, false);
-
-            final int[] coordinates = new int[2];
-            final int screenId = findSpaceOnWorkspace(item, coordinates);
-            if (screenId == -1) {
-                return false;
-            }
-            mContext.getModelWriter().moveItemInDatabase(info,
-                    Favorites.CONTAINER_DESKTOP,
-                    screenId, coordinates[0], coordinates[1]);
-
-            // Bind the item in next frame so that if a new workspace page was created,
-            // it will get laid out.
-            new Handler().post(() -> {
-                mContext.bindItems(Collections.singletonList(item), true);
-                announceConfirmation(R.string.item_moved);
-            });
-            return true;
+            return moveToWorkspace(item);
         } else if (action == RESIZE) {
             final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) item;
             List<OptionItem> actions = getSupportedResizeActions(host, info);
@@ -403,4 +351,76 @@
         }
         return screenId;
     }
+
+    /**
+     * Functionality to add the item {@link ItemInfo} to the workspace
+     * @param item item to be added
+     * @param accessibility true if the first item to be added to the workspace
+     *     should be focused for accessibility.
+     *
+     * @return true if the item could be successfully added
+     */
+    public boolean addToWorkspace(ItemInfo item, boolean accessibility) {
+        final int[] coordinates = new int[2];
+        final int screenId = findSpaceOnWorkspace(item, coordinates);
+        if (screenId == -1) {
+            return false;
+        }
+        mContext.getStateManager().goToState(NORMAL, true, forSuccessCallback(() -> {
+            if (item instanceof AppInfo) {
+                WorkspaceItemInfo info = ((AppInfo) item).makeWorkspaceItem();
+                mContext.getModelWriter().addItemToDatabase(info,
+                        LauncherSettings.Favorites.CONTAINER_DESKTOP,
+                        screenId, coordinates[0], coordinates[1]);
+
+                mContext.bindItems(
+                        Collections.singletonList(info),
+                        /* forceAnimateIcons= */ true,
+                        /* focusFirstItemForAccessibility= */ accessibility);
+                announceConfirmation(R.string.item_added_to_workspace);
+            } else if (item instanceof PendingAddItemInfo) {
+                PendingAddItemInfo info = (PendingAddItemInfo) item;
+                Workspace<?> workspace = mContext.getWorkspace();
+                workspace.snapToPage(workspace.getPageIndexForScreenId(screenId));
+                mContext.addPendingItem(info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
+                        screenId, coordinates, info.spanX, info.spanY);
+            } else if (item instanceof WorkspaceItemInfo) {
+                WorkspaceItemInfo info = ((WorkspaceItemInfo) item).clone();
+                mContext.getModelWriter().addItemToDatabase(info,
+                        LauncherSettings.Favorites.CONTAINER_DESKTOP,
+                        screenId, coordinates[0], coordinates[1]);
+                mContext.bindItems(Collections.singletonList(info), true, accessibility);
+            }
+        }));
+        return true;
+    }
+    /**
+     * Functionality to move the item {@link ItemInfo} to the workspace
+     * @param item item to be moved
+     *
+     * @return true if the item could be successfully added
+     */
+    public boolean moveToWorkspace(ItemInfo item) {
+        Folder folder = Folder.getOpen(mContext);
+        folder.close(true);
+        WorkspaceItemInfo info = (WorkspaceItemInfo) item;
+        folder.getInfo().remove(info, false);
+
+        final int[] coordinates = new int[2];
+        final int screenId = findSpaceOnWorkspace(item, coordinates);
+        if (screenId == -1) {
+            return false;
+        }
+        mContext.getModelWriter().moveItemInDatabase(info,
+                LauncherSettings.Favorites.CONTAINER_DESKTOP,
+                screenId, coordinates[0], coordinates[1]);
+
+        // Bind the item in next frame so that if a new workspace page was created,
+        // it will get laid out.
+        new Handler().post(() -> {
+            mContext.bindItems(Collections.singletonList(item), true);
+            announceConfirmation(R.string.item_moved);
+        });
+        return true;
+    }
 }
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index cdc313f..8662d00 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -44,6 +44,7 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.statemanager.StateManager.StateHandler;
 import com.android.launcher3.states.StateAnimationConfig;
+import com.android.launcher3.util.UiThreadHelper;
 import com.android.launcher3.views.ScrimView;
 
 /**
@@ -75,6 +76,21 @@
                 }
             };
 
+    public static final FloatProperty<AllAppsTransitionController> ALL_APPS_PULL_BACK_PROGRESS =
+            new FloatProperty<AllAppsTransitionController>("allAppsPullBackProgress") {
+
+                @Override
+                public Float get(AllAppsTransitionController controller) {
+                    return controller.mPullBackProgress;
+                }
+
+                @Override
+                public void setValue(AllAppsTransitionController controller, float progress) {
+                    controller.setPullBackProgress(progress);
+                }
+            };
+
+
     private ActivityAllAppsContainerView<Launcher> mAppsView;
 
     private final Launcher mLauncher;
@@ -88,15 +104,17 @@
     // When {@link mProgress} is 1, all apps container is pulled down.
     private float mShiftRange;      // changes depending on the orientation
     private float mProgress;        // [0, 1], mShiftRange * mProgress = shiftCurrent
+    private float mPullBackProgress;  // [0, 1], mShiftRange * mPullBackProgress = shiftCurrent
 
     private ScrimView mScrimView;
+    private View mPullBackView;
 
     public AllAppsTransitionController(Launcher l) {
         mLauncher = l;
         DeviceProfile dp = mLauncher.getDeviceProfile();
         setShiftRange(dp.allAppsShiftRange);
         mProgress = 1f;
-
+        mPullBackProgress = 1f;
         mIsVerticalLayout = dp.isVerticalBarLayout();
         mLauncher.addOnDeviceProfileChangeListener(this);
     }
@@ -114,6 +132,8 @@
             mLauncher.getHotseat().setTranslationY(0);
             mLauncher.getWorkspace().getPageIndicator().setTranslationY(0);
         }
+
+        mPullBackView = dp.isTablet ? mAppsView.getRecyclerViewContainer() : mAppsView;
     }
 
     /**
@@ -133,12 +153,19 @@
         return mProgress;
     }
 
+    private void setPullBackProgress(float progress) {
+        mPullBackProgress = progress;
+        mPullBackView.setTranslationY(mPullBackProgress * mShiftRange);
+    }
+
     /**
      * Sets the vertical transition progress to {@param state} and updates all the dependent UI
      * accordingly.
      */
     @Override
     public void setState(LauncherState state) {
+        // Always reset pull back progress when switching states.
+        setPullBackProgress(0f);
         setProgress(state.getVerticalProgress(mLauncher));
         setAlphas(state, new StateAnimationConfig(), NO_ANIM_PROPERTY_SETTER);
         onProgressAnimationEnd();
@@ -151,6 +178,12 @@
     @Override
     public void setStateWithAnimation(LauncherState toState,
             StateAnimationConfig config, PendingAnimation builder) {
+        if (NORMAL.equals(toState) && mLauncher.isInState(ALL_APPS)) {
+            UiThreadHelper.hideKeyboardAsync(mLauncher, mLauncher.getAppsView().getWindowToken());
+        }
+
+        // Always reset pull back progress when switching states.
+        setPullBackProgress(0f);
         float targetProgress = toState.getVerticalProgress(mLauncher);
         if (Float.compare(mProgress, targetProgress) == 0) {
             setAlphas(toState, config, builder);
@@ -212,6 +245,8 @@
                             | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
         }
         mAppsView.setScrimView(scrimView);
+        mPullBackView = mLauncher.getDeviceProfile().isTablet
+                ? mAppsView.getRecyclerViewContainer() : mAppsView;
     }
 
     /**
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index 5ee4203..14e10918 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -104,7 +104,10 @@
         mFocusIndicatorHelper = new ViewGroupFocusHelper(this);
     }
 
-    public void setup(DragController dragController, Workspace workspace) {
+    /**
+     * Set up the drag layer with the parameters.
+     */
+    public void setup(DragController dragController, Workspace<?> workspace) {
         mDragController = dragController;
         recreateControllers();
         mWorkspaceDragScrim = new Scrim(this);
diff --git a/src/com/android/launcher3/dragndrop/SpringLoadedDragController.java b/src/com/android/launcher3/dragndrop/SpringLoadedDragController.java
index 6325877..fb8a1bc 100644
--- a/src/com/android/launcher3/dragndrop/SpringLoadedDragController.java
+++ b/src/com/android/launcher3/dragndrop/SpringLoadedDragController.java
@@ -55,7 +55,7 @@
     public void onAlarm(Alarm alarm) {
         if (mScreen != null) {
             // Snap to the screen that we are hovering over now
-            Workspace w = mLauncher.getWorkspace();
+            Workspace<?> w = mLauncher.getWorkspace();
             if (!w.isVisible(mScreen)) {
                 w.snapToPage(w.indexOfChild(mScreen));
             }
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 7c665c6..5fe2435 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -342,7 +342,7 @@
             Rect to = finalRect;
             if (to == null) {
                 to = new Rect();
-                Workspace workspace = launcher.getWorkspace();
+                Workspace<?> workspace = launcher.getWorkspace();
                 // Set cellLayout and this to it's final state to compute final animation locations
                 workspace.setFinalTransitionTransform();
                 float scaleX = getScaleX();
diff --git a/src/com/android/launcher3/pageindicators/PageIndicator.java b/src/com/android/launcher3/pageindicators/PageIndicator.java
index 5967be7..ec69193 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicator.java
@@ -28,21 +28,22 @@
 
     /**
      * Sets the flag if the Page Indicator should autohide.
-     * @param shouldAutoHide
      */
     default void setShouldAutoHide(boolean shouldAutoHide) {
-        //No-op by default
+        // No-op by default
     }
+
     /**
      * Pauses all currently running animations.
      */
     default void pauseAnimations() {
-        //No-op by default
+        // No-op by default
     }
+
     /**
      * Force-ends all currently running or paused animations.
      */
     default void skipAnimationsToEnd() {
-        //No-op by default
+        // No-op by default
     }
 }
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index f06e5ce..df8a3e2 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -351,7 +351,7 @@
         if (mColorExtractors == null) {
             return;
         }
-        Workspace workspace = launcher.getWorkspace();
+        Workspace<?> workspace = launcher.getWorkspace();
         if (workspace == null) {
             return;
         }
diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java
index 9be3cc5..52356ce 100644
--- a/src/com/android/launcher3/states/SpringLoadedState.java
+++ b/src/com/android/launcher3/states/SpringLoadedState.java
@@ -46,7 +46,7 @@
     @Override
     public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
         DeviceProfile grid = launcher.getDeviceProfile();
-        Workspace ws = launcher.getWorkspace();
+        Workspace<?> ws = launcher.getWorkspace();
         if (ws.getChildCount() == 0) {
             return super.getWorkspaceScaleAndTranslation(launcher);
         }
diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java
index 2eae99a..a6b481a 100644
--- a/src/com/android/launcher3/testing/TestInformationHandler.java
+++ b/src/com/android/launcher3/testing/TestInformationHandler.java
@@ -178,7 +178,7 @@
 
             case TestProtocol.REQUEST_WORKSPACE_CELL_LAYOUT_SIZE:
                 return getLauncherUIProperty(Bundle::putIntArray, launcher -> {
-                    final Workspace workspace = launcher.getWorkspace();
+                    final Workspace<?> workspace = launcher.getWorkspace();
                     final int screenId = workspace.getScreenIdForPageIndex(
                             workspace.getCurrentPage());
                     final CellLayout cellLayout = workspace.getScreenWithId(screenId);
@@ -189,7 +189,7 @@
                 final WorkspaceCellCenterRequest request = extra.getParcelable(
                         TestProtocol.TEST_INFO_REQUEST_FIELD);
                 return getLauncherUIProperty(Bundle::putParcelable, launcher -> {
-                    final Workspace workspace = launcher.getWorkspace();
+                    final Workspace<?> workspace = launcher.getWorkspace();
                     // TODO(b/216387249): allow caller selecting different pages.
                     CellLayout cellLayout = (CellLayout) workspace.getPageAt(
                             workspace.getCurrentPage());
diff --git a/src/com/android/launcher3/touch/WorkspaceTouchListener.java b/src/com/android/launcher3/touch/WorkspaceTouchListener.java
index fe0bf6d..17bbdf1 100644
--- a/src/com/android/launcher3/touch/WorkspaceTouchListener.java
+++ b/src/com/android/launcher3/touch/WorkspaceTouchListener.java
@@ -64,7 +64,7 @@
 
     private final Rect mTempRect = new Rect();
     private final Launcher mLauncher;
-    private final Workspace mWorkspace;
+    private final Workspace<?> mWorkspace;
     private final PointF mTouchDownPoint = new PointF();
     private final float mTouchSlop;
 
@@ -72,7 +72,7 @@
 
     private final GestureDetector mGestureDetector;
 
-    public WorkspaceTouchListener(Launcher launcher, Workspace workspace) {
+    public WorkspaceTouchListener(Launcher launcher, Workspace<?> workspace) {
         mLauncher = launcher;
         mWorkspace = workspace;
         // Use twice the touch slop as we are looking for long press which is more
diff --git a/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java b/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java
index f1276dd..43e9820 100644
--- a/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java
+++ b/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java
@@ -32,7 +32,7 @@
     // Don't use all the wallpaper for parallax until you have at least this many pages
     private static final int MIN_PARALLAX_PAGE_SPAN = 4;
 
-    private final Workspace mWorkspace;
+    private final Workspace<?> mWorkspace;
     private final boolean mIsRtl;
     private final Handler mHandler;
 
@@ -43,7 +43,7 @@
     private boolean mLockedToDefaultPage;
     private int mNumScreens;
 
-    public WallpaperOffsetInterpolator(Workspace workspace) {
+    public WallpaperOffsetInterpolator(Workspace<?> workspace) {
         mWorkspace = workspace;
         mIsRtl = Utilities.isRtl(workspace.getResources());
         mHandler = new OffsetHandler(workspace.getContext());