Merge "Hide app icon during predictive back to home" into main
diff --git a/quickstep/src/com/android/launcher3/HomeTransitionController.java b/quickstep/src/com/android/launcher3/HomeTransitionController.java
index b264115..2b50283 100644
--- a/quickstep/src/com/android/launcher3/HomeTransitionController.java
+++ b/quickstep/src/com/android/launcher3/HomeTransitionController.java
@@ -28,19 +28,16 @@
  */
 public class HomeTransitionController {
 
-    private final QuickstepLauncher mLauncher;
+    @Nullable private QuickstepLauncher mLauncher;
     @Nullable private IHomeTransitionListener mHomeTransitionListener;
 
-    public HomeTransitionController(QuickstepLauncher launcher) {
+    public void registerHomeTransitionListener(QuickstepLauncher launcher) {
         mLauncher = launcher;
-    }
-
-    public void registerHomeTransitionListener() {
         mHomeTransitionListener = new IHomeTransitionListener.Stub() {
             @Override
             public void onHomeVisibilityChanged(boolean isVisible) {
                 MAIN_EXECUTOR.execute(() -> {
-                    if (mLauncher.getTaskbarUIController() != null) {
+                    if (mLauncher != null && mLauncher.getTaskbarUIController() != null) {
                         mLauncher.getTaskbarUIController().onLauncherVisibilityChanged(isVisible);
                     }
                 });
@@ -53,5 +50,6 @@
     public void unregisterHomeTransitionListener() {
         SystemUiProxy.INSTANCE.get(mLauncher).setHomeTransitionListener(null);
         mHomeTransitionListener = null;
+        mLauncher = null;
     }
 }
diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
index 1440498..ea1d286 100644
--- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -23,6 +23,7 @@
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.LinearLayout;
 
 import androidx.annotation.NonNull;
@@ -31,6 +32,7 @@
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
+import com.android.launcher3.Flags;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.allapps.FloatingHeaderRow;
@@ -199,8 +201,12 @@
                 icon.setOnFocusChangeListener(mFocusHelper);
 
                 LayoutParams lp = (LayoutParams) icon.getLayoutParams();
-                // Ensure the all apps icon height matches the workspace icons in portrait mode.
-                lp.height = mActivityContext.getDeviceProfile().allAppsCellHeightPx;
+                if (Flags.enableFocusOutline()) {
+                    lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
+                } else {
+                    // Ensure the all apps icon height matches the workspace icons in portrait mode.
+                    lp.height = mActivityContext.getDeviceProfile().allAppsCellHeightPx;
+                }
                 lp.width = 0;
                 lp.weight = 1;
                 addView(icon);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
index 3f9b66a..dab9950 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
@@ -16,7 +16,6 @@
 package com.android.launcher3.taskbar
 
 import android.animation.Animator
-import android.animation.AnimatorListenerAdapter
 import android.animation.AnimatorSet
 import android.animation.ObjectAnimator
 import android.annotation.SuppressLint
@@ -197,32 +196,19 @@
             mActivityContext.deviceProfile.taskbarIconSize) / 2 + verticalOffsetForPopupView
     }
 
-    override fun animateClose() {
-        if (!mIsOpen) {
-            return
+    override fun onCreateCloseAnimation(anim: AnimatorSet?) {
+        // If taskbar pinning preference changed insert custom close animation for popup menu.
+        if (didPreferenceChange) {
+            mOpenCloseAnimator = getCloseAnimator()
         }
-        if (mOpenCloseAnimator != null) {
-            mOpenCloseAnimator.cancel()
-        }
-        mIsOpen = false
-
-        mOpenCloseAnimator = getCloseAnimator()
-
-        mOpenCloseAnimator.addListener(
-            object : AnimatorListenerAdapter() {
-                override fun onAnimationEnd(animation: Animator) {
-                    mOpenCloseAnimator = null
-                    if (mDeferContainerRemoval) {
-                        setVisibility(INVISIBLE)
-                    } else {
-                        closeComplete()
-                    }
-                }
-            }
-        )
         onCloseCallback(didPreferenceChange)
         onCloseCallback = {}
-        mOpenCloseAnimator.start()
+    }
+
+    /** Aligning the view pivot to center for animation. */
+    override fun setPivotForOpenCloseAnimation() {
+        pivotX = measuredWidth / 2f
+        pivotY = measuredHeight.toFloat()
     }
 
     private fun getCloseAnimator(): AnimatorSet {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 2f7f6f3..48c83da 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -21,9 +21,7 @@
 import static com.android.app.animation.Interpolators.FINAL_FRAME;
 import static com.android.app.animation.Interpolators.INSTANT;
 import static com.android.app.animation.Interpolators.LINEAR;
-import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION;
-import static com.android.launcher3.config.FeatureFlags.enableTaskbarPinning;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TRANSIENT_TASKBAR_HIDE;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TRANSIENT_TASKBAR_SHOW;
 import static com.android.launcher3.taskbar.TaskbarKeyguardController.MASK_ANY_SYSUI_LOCKED;
@@ -59,7 +57,6 @@
 import com.android.internal.jank.InteractionJankMonitor;
 import com.android.launcher3.Alarm;
 import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.R;
 import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.anim.AnimatorListeners;
@@ -949,8 +946,7 @@
             return false;
         }
         // Do not stash if pinned taskbar and hardware keyboard is attached.
-        if (mActivity.isHardwareKeyboard() && enableTaskbarPinning()
-                && LauncherPrefs.get(mActivity).get(TASKBAR_PINNING)) {
+        if (mActivity.isHardwareKeyboard() && DisplayController.isPinnedTaskbar(mActivity)) {
             return false;
         }
         return mIsImeShowing || mIsImeSwitcherShowing;
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
index b516d6f..23e3310 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
@@ -65,18 +65,19 @@
 
     fun getParamsToCenterView(): FrameLayout.LayoutParams {
         val params = FrameLayout.LayoutParams(
-                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
+                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
         params.gravity = Gravity.CENTER
         return params;
     }
 
-    open fun repositionContextualContainer(contextualContainer: ViewGroup, barAxisMargin: Int,
+    open fun repositionContextualContainer(contextualContainer: ViewGroup, buttonSize: Int,
+                                           barAxisMarginStart: Int, barAxisMarginEnd: Int,
                                            gravity: Int) {
         val contextualContainerParams = FrameLayout.LayoutParams(
-                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT)
+                buttonSize, ViewGroup.LayoutParams.MATCH_PARENT)
         contextualContainerParams.apply {
-            marginStart = barAxisMargin
-            marginEnd = barAxisMargin
+            marginStart = barAxisMarginStart
+            marginEnd = barAxisMarginEnd
             topMargin = 0
             bottomMargin = 0
         }
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt
index 65b77ac..f31af09 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt
@@ -21,6 +21,7 @@
 import android.graphics.drawable.PaintDrawable
 import android.view.Gravity
 import android.view.ViewGroup
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
 import android.widget.FrameLayout
 import android.widget.ImageView
 import android.widget.LinearLayout
@@ -103,8 +104,9 @@
 
         val contextualMargin = resources.getDimensionPixelSize(
                 R.dimen.taskbar_contextual_button_padding)
-        repositionContextualContainer(endContextualContainer, 0, Gravity.END)
-        repositionContextualContainer(startContextualContainer, contextualMargin, Gravity.START)
+        repositionContextualContainer(endContextualContainer, WRAP_CONTENT, 0, 0, Gravity.END)
+        repositionContextualContainer(startContextualContainer, WRAP_CONTENT, contextualMargin,
+                contextualMargin, Gravity.START)
 
         if (imeSwitcher != null) {
             startContextualContainer.addView(imeSwitcher)
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt
index a96ee1f..b1b50d6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt
@@ -106,7 +106,7 @@
             }
         }
 
-        repositionContextualButtons()
+        repositionContextualButtons(contextualButtonHeight.toInt())
     }
 
     open fun addThreeButtons() {
@@ -116,13 +116,15 @@
         navButtonContainer.addView(backButton)
     }
 
-    open fun repositionContextualButtons() {
+    open fun repositionContextualButtons(buttonSize: Int) {
         endContextualContainer.removeAllViews()
         startContextualContainer.removeAllViews()
 
-        val contextualMargin = resources.getDimensionPixelSize(
-                R.dimen.taskbar_contextual_button_padding)
-        repositionContextualContainer(startContextualContainer, contextualMargin, Gravity.TOP)
+        val roundedCornerContentMargin = resources.getDimensionPixelSize(
+                R.dimen.taskbar_phone_rounded_corner_content_margin)
+        val contentPadding = resources.getDimensionPixelSize(R.dimen.taskbar_phone_content_padding)
+        repositionContextualContainer(startContextualContainer, buttonSize,
+                roundedCornerContentMargin + contentPadding, 0, Gravity.TOP)
 
         if (imeSwitcher != null) {
             startContextualContainer.addView(imeSwitcher)
@@ -137,15 +139,16 @@
         }
     }
 
-    override fun repositionContextualContainer(contextualContainer: ViewGroup, barAxisMargin: Int,
+    override fun repositionContextualContainer(contextualContainer: ViewGroup, buttonSize: Int,
+                                               barAxisMarginTop: Int, barAxisMarginBottom: Int,
                                                gravity: Int) {
         val contextualContainerParams = FrameLayout.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
+                ViewGroup.LayoutParams.MATCH_PARENT, buttonSize)
         contextualContainerParams.apply {
             marginStart = 0
             marginEnd = 0
-            topMargin = barAxisMargin
-            bottomMargin = barAxisMargin
+            topMargin = barAxisMarginTop
+            bottomMargin = barAxisMarginBottom
         }
         contextualContainerParams.gravity = gravity or Gravity.CENTER_HORIZONTAL
         contextualContainer.layoutParams = contextualContainerParams
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt
index 22d9f82..05183b8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt
@@ -110,9 +110,8 @@
         endContextualContainer.removeAllViews()
         startContextualContainer.removeAllViews()
 
-        val contextualMargin = resources.getDimensionPixelSize(
-                R.dimen.taskbar_contextual_button_padding)
-        repositionContextualContainer(endContextualContainer, contextualMargin, Gravity.END)
+        repositionContextualContainer(endContextualContainer, contextualButtonWidth.toInt(), 0,
+                roundedCornerContentMargin + contentPadding, Gravity.END)
 
         if (imeSwitcher != null) {
             endContextualContainer.addView(imeSwitcher)
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneSeascapeNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneSeascapeNavLayoutter.kt
index 0368b1d..0f52552 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneSeascapeNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneSeascapeNavLayoutter.kt
@@ -50,13 +50,15 @@
         navButtonContainer.addView(recentsButton)
     }
 
-    override fun repositionContextualButtons() {
+    override fun repositionContextualButtons(buttonSize: Int) {
         endContextualContainer.removeAllViews()
         startContextualContainer.removeAllViews()
 
-        val contextualMargin = resources.getDimensionPixelSize(
-                R.dimen.taskbar_contextual_button_padding)
-        repositionContextualContainer(endContextualContainer, contextualMargin, Gravity.BOTTOM)
+        val roundedCornerContentMargin = resources.getDimensionPixelSize(
+                R.dimen.taskbar_phone_rounded_corner_content_margin)
+        val contentPadding = resources.getDimensionPixelSize(R.dimen.taskbar_phone_content_padding)
+        repositionContextualContainer(endContextualContainer, buttonSize, 0,
+                roundedCornerContentMargin + contentPadding,  Gravity.BOTTOM)
 
         if (imeSwitcher != null) {
             endContextualContainer.addView(imeSwitcher)
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt
index 1ac0060..5111bba 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt
@@ -19,6 +19,7 @@
 import android.content.res.Resources
 import android.view.Gravity
 import android.view.ViewGroup
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
 import android.widget.FrameLayout
 import android.widget.ImageView
 import android.widget.LinearLayout
@@ -61,8 +62,9 @@
 
         val contextualMargin = resources.getDimensionPixelSize(
                 R.dimen.taskbar_contextual_button_padding)
-        repositionContextualContainer(endContextualContainer, 0, Gravity.END)
-        repositionContextualContainer(startContextualContainer, contextualMargin, Gravity.START)
+        repositionContextualContainer(endContextualContainer, WRAP_CONTENT, 0, 0, Gravity.END)
+        repositionContextualContainer(startContextualContainer, WRAP_CONTENT, contextualMargin,
+                contextualMargin, Gravity.START)
 
         if (imeSwitcher != null) {
             startContextualContainer.addView(imeSwitcher)
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt
index 5465b6b..45dbebb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt
@@ -19,6 +19,7 @@
 import android.content.res.Resources
 import android.view.Gravity
 import android.view.ViewGroup
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
 import android.widget.FrameLayout
 import android.widget.ImageView
 import android.widget.LinearLayout
@@ -96,8 +97,9 @@
         if (!context.deviceProfile.isGestureMode) {
             val contextualMargin = resources.getDimensionPixelSize(
                     R.dimen.taskbar_contextual_button_padding)
-            repositionContextualContainer(endContextualContainer, 0, Gravity.END)
-            repositionContextualContainer(startContextualContainer, contextualMargin, Gravity.START)
+            repositionContextualContainer(endContextualContainer, WRAP_CONTENT, 0, 0, Gravity.END)
+            repositionContextualContainer(startContextualContainer, WRAP_CONTENT, contextualMargin,
+                    contextualMargin, Gravity.START)
 
             if (imeSwitcher != null) {
                 startContextualContainer.addView(imeSwitcher)
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index a065387..f45ddb6 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -266,8 +266,8 @@
         mAppTransitionManager.registerRemoteTransitions();
 
         if (FeatureFlags.enableHomeTransitionListener()) {
-            mHomeTransitionController = new HomeTransitionController(this);
-            mHomeTransitionController.registerHomeTransitionListener();
+            mHomeTransitionController = new HomeTransitionController();
+            mHomeTransitionController.registerHomeTransitionListener(this);
         }
 
         mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
index 1d55da3..856b519 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
@@ -62,12 +62,6 @@
     @Override
     public void onBackPressed(Launcher launcher) {
         launcher.getStateManager().goToState(LauncherState.OVERVIEW);
-        RecentsView recentsView = launcher.<RecentsView>getOverviewPanel();
-        if (recentsView != null) {
-            recentsView.resetModalVisuals();
-        } else {
-            super.onBackPressed(launcher);
-        }
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 86ba7ef..6f45caf 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -305,6 +305,10 @@
         @Override
         public void onNavigationBarSurface(SurfaceControl surface) {
             // TODO: implement
+            if (surface != null) {
+                surface.release();
+                surface = null;
+            }
         }
 
         @BinderThread
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 35fa539..1008da3 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -217,7 +217,6 @@
         } else {
             if (mActivity.isInState(RecentsState.MODAL_TASK)) {
                 mActivity.getStateManager().goToState(DEFAULT, animate);
-                resetModalVisuals();
             }
         }
     }
@@ -237,6 +236,8 @@
         setOverviewFullscreenEnabled(toState.isFullScreen());
         if (toState == MODAL_TASK) {
             setOverviewSelectEnabled(true);
+        } else {
+            resetModalVisuals();
         }
 
         // Set border after select mode changes to avoid showing border during state transition
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 5b5d0de..9bb9775a 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -16,6 +16,7 @@
 package com.android.quickstep.views;
 
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.CLEAR_ALL_BUTTON;
 import static com.android.launcher3.LauncherState.EDIT_MODE;
@@ -144,6 +145,8 @@
         setOverviewFullscreenEnabled(toState.getOverviewFullscreenProgress() == 1);
         if (toState == OVERVIEW_MODAL_TASK) {
             setOverviewSelectEnabled(true);
+        } else {
+            resetModalVisuals();
         }
 
         // Set border after select mode changes to avoid showing border during state transition
@@ -214,7 +217,6 @@
         } else {
             if (mActivity.isInState(LauncherState.OVERVIEW_MODAL_TASK)) {
                 mActivity.getStateManager().goToState(LauncherState.OVERVIEW, animate);
-                resetModalVisuals();
             }
         }
     }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index ebb6ba8..997624f 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -4382,11 +4382,14 @@
 
     private void updatePivots() {
         if (mOverviewSelectEnabled) {
-            getModalTaskSize(mTempRect);
-            Rect selectedTaskPosition = getSelectedTaskBounds();
-
-            Utilities.getPivotsForScalingRectToRect(mTempRect, selectedTaskPosition,
-                    mTempPointF);
+            if (enableGridOnlyOverview()) {
+                getModalTaskSize(mTempRect);
+                Rect selectedTaskPosition = getSelectedTaskBounds();
+                Utilities.getPivotsForScalingRectToRect(mTempRect, selectedTaskPosition,
+                        mTempPointF);
+            } else {
+                mTempPointF.set(mLastComputedTaskSize.centerX(), mLastComputedTaskSize.bottom);
+            }
         } else {
             mTempRect.set(mLastComputedTaskSize);
             // Only update pivot when it is tablet and not in grid yet, so the pivot is correct
@@ -5709,11 +5712,20 @@
     }
 
     private void updateEnabledOverlays() {
+        TaskView focusedTaskView = getFocusedTaskView();
         int taskCount = getTaskViewCount();
         for (int i = 0; i < taskCount; i++) {
             TaskView taskView = requireTaskViewAt(i);
+            if (taskView == focusedTaskView) {
+                continue;
+            }
             taskView.setOverlayEnabled(mOverlayEnabled && isTaskViewFullyVisible(taskView));
         }
+        // Focus task overlay should be enabled and refreshed at last
+        if (focusedTaskView != null) {
+            focusedTaskView.setOverlayEnabled(
+                    mOverlayEnabled && isTaskViewFullyVisible(focusedTaskView));
+        }
     }
 
     public void setOverlayEnabled(boolean overlayEnabled) {
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index edf95ea..0a325ac 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -32,6 +32,8 @@
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.rule.ShellCommandRule.disableHeadsUpNotification;
 import static com.android.launcher3.util.rule.ShellCommandRule.getLauncherCommand;
+import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -67,7 +69,6 @@
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.RuleChain;
@@ -185,9 +186,10 @@
         mLauncher.getLaunchedAppState().switchToOverview();
     }
 
-    // b/143488140
+    // Staging; will be promoted to presubmit if stable
+    @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT)
+
     //@NavigationModeSwitch
-    @Ignore
     @Test
     public void goToOverviewFromApp() {
         startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 25adb62..ebe3365 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -44,6 +44,7 @@
 import com.android.launcher3.tapl.Overview;
 import com.android.launcher3.tapl.OverviewActions;
 import com.android.launcher3.tapl.OverviewTask;
+import com.android.launcher3.tapl.SelectModeButtons;
 import com.android.launcher3.ui.AbstractLauncherUiTest;
 import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
 import com.android.launcher3.util.Wait;
@@ -194,6 +195,43 @@
         actionsView.clickAndDismissScreenshot();
     }
 
+    @Test
+    public void testDismissOverviewWithEscKey() throws Exception {
+        startTestAppsWithCheck();
+        final Overview overview = mLauncher.goHome().switchToOverview();
+        assertTrue("Launcher internal state is not Overview",
+                isInState(() -> LauncherState.OVERVIEW));
+
+        overview.dismissByEscKey();
+        assertTrue("Launcher internal state is not Home",
+                isInState(() -> LauncherState.NORMAL));
+    }
+
+    @Test
+    public void testDismissModalTaskAndOverviewWithEscKey() throws Exception {
+        startTestAppsWithCheck();
+        final Overview overview = mLauncher.goHome().switchToOverview();
+
+        final SelectModeButtons selectModeButtons;
+
+        if (mLauncher.isTablet() && mLauncher.isGridOnlyOverviewEnabled()) {
+            selectModeButtons = overview.getCurrentTask().tapMenu().tapSelectMenuItem();
+        } else {
+            selectModeButtons = overview.getOverviewActions().clickSelect();
+        }
+
+        assertTrue("Launcher internal state is not Overview Modal Task",
+                isInState(() -> LauncherState.OVERVIEW_MODAL_TASK));
+
+        selectModeButtons.dismissByEscKey();
+
+        assertTrue("Launcher internal state is not Overview",
+                isInState(() -> LauncherState.OVERVIEW));
+        overview.dismissByEscKey();
+        assertTrue("Launcher internal state is not Home",
+                isInState(() -> LauncherState.NORMAL));
+    }
+
     private int getCurrentOverviewPage(Launcher launcher) {
         return launcher.<RecentsView>getOverviewPanel().getCurrentPage();
     }
@@ -210,11 +248,12 @@
         return launcher.<RecentsView>getOverviewPanel().getBottomRowTaskCountForTablet();
     }
 
-    @Ignore
+    // Staging; will be promoted to presubmit if stable
+    @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT)
+
     @Test
     @NavigationModeSwitch
     @PortraitLandscape
-    @ScreenRecord // b/238461765
     public void testSwitchToOverview() throws Exception {
         startTestAppsWithCheck();
         assertNotNull("Workspace.switchToOverview() returned null",
@@ -236,7 +275,9 @@
         }
     }
 
-    @Ignore
+    // Staging; will be promoted to presubmit if stable
+    @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT)
+
     @Test
     @NavigationModeSwitch
     @PortraitLandscape
@@ -295,7 +336,9 @@
 
     @Test
     @TaskbarModeSwitch
-    @Ignore // b/314873201
+    @ScreenRecord // b/314873201
+    // Staging; will be promoted to presubmit if stable
+    @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT)
     public void testQuickSwitchToPreviousAppForTablet() throws Exception {
         assumeTrue(mLauncher.isTablet());
         startTestActivity(2);
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 53297f2..72d2213 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -78,7 +78,6 @@
 public class DeviceProfile {
 
     private static final int DEFAULT_DOT_SIZE = 100;
-    private static final float ALL_APPS_TABLET_MAX_ROWS = 5.5f;
     private static final float MIN_FOLDER_TEXT_SIZE_SP = 16f;
     private static final float MIN_WIDGET_PADDING_DP = 6f;
 
@@ -734,14 +733,9 @@
             hotseatBorderSpace = cellLayoutBorderSpacePx.y;
         }
 
-        // AllApps height calculation depends on updated cellSize
         if (isTablet) {
-            int collapseHandleHeight =
-                    res.getDimensionPixelOffset(R.dimen.bottom_sheet_handle_area_height);
-            int contentHeight = heightPx - collapseHandleHeight - hotseatQsbHeight;
-            int targetContentHeight = (int) (allAppsCellHeightPx * ALL_APPS_TABLET_MAX_ROWS);
-            allAppsPadding.top = Math.max(mInsets.top, contentHeight - targetContentHeight);
-            allAppsShiftRange = heightPx - allAppsPadding.top;
+            allAppsPadding.top = mInsets.top;
+            allAppsShiftRange = heightPx;
         } else {
             allAppsPadding.top = 0;
             allAppsShiftRange =
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 5721ed3..1cbc5b6 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -247,7 +247,7 @@
     public InvariantDeviceProfile(Context context, String gridName) {
         String newName = initGrid(context, gridName);
         if (newName == null || !newName.equals(gridName)) {
-            throw new IllegalArgumentException("Unknown grid name");
+            throw new IllegalArgumentException("Unknown grid name: " + gridName);
         }
     }
 
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index 7f1d216..4ad4c71 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -1150,14 +1150,15 @@
 
         applyAdapterSideAndBottomPaddings(grid);
 
-        MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
-        mlp.leftMargin = insets.left;
-        mlp.rightMargin = insets.right;
-        setLayoutParams(mlp);
+        // Ignore left/right insets on tablet because we are already centered in-screen.
+        if (grid.isPhone) {
+            MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
+            mlp.leftMargin = insets.left;
+            mlp.rightMargin = insets.right;
+            setLayoutParams(mlp);
+        }
 
-        if (grid.isVerticalBarLayout() && !FeatureFlags.enableResponsiveWorkspace()) {
-            setPadding(grid.workspacePadding.left, 0, grid.workspacePadding.right, 0);
-        } else {
+        if (!grid.isVerticalBarLayout() || FeatureFlags.enableResponsiveWorkspace()) {
             int topPadding = grid.allAppsPadding.top;
             if (isSearchBarFloating() && !grid.isTablet) {
                 topPadding += getResources().getDimensionPixelSize(
diff --git a/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt b/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt
index 2945979..b2497a3 100644
--- a/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt
+++ b/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt
@@ -21,9 +21,14 @@
 import android.graphics.Rect
 import android.graphics.drawable.Drawable
 import android.util.AttributeSet
+import android.util.Log
 import android.view.Gravity
 import android.widget.FrameLayout
 import com.android.launcher3.DeviceProfile
+import com.android.launcher3.icons.BitmapInfo
+import com.android.launcher3.icons.PlaceHolderIconDrawable
+import com.android.launcher3.model.data.WorkspaceItemInfo
+import com.android.launcher3.util.Themes
 
 /**
  * A FrameLayout marking the area on an [AppPairIcon] where the visual icon will be drawn. One of
@@ -31,6 +36,8 @@
  */
 class AppPairIconGraphic @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
     FrameLayout(context, attrs) {
+    private val TAG = "AppPairIconGraphic"
+
     companion object {
         // Design specs -- the below ratios are in relation to the size of a standard app icon.
         private const val OUTER_PADDING_SCALE = 1 / 30f
@@ -61,8 +68,8 @@
 
     private lateinit var parentIcon: AppPairIcon
     private lateinit var appPairBackground: Drawable
-    private lateinit var appIcon1: Drawable
-    private lateinit var appIcon2: Drawable
+    private var appIcon1: Drawable? = null
+    private var appIcon2: Drawable? = null
 
     fun init(grid: DeviceProfile, icon: AppPairIcon) {
         // Calculate device-specific measurements
@@ -79,12 +86,33 @@
 
         appPairBackground = AppPairIconBackground(context, this)
         appPairBackground.setBounds(0, 0, backgroundSize.toInt(), backgroundSize.toInt())
-        appIcon1 = parentIcon.info.contents[0].newIcon(context)
-        appIcon2 = parentIcon.info.contents[1].newIcon(context)
-        appIcon1.setBounds(0, 0, memberIconSize.toInt(), memberIconSize.toInt())
-        appIcon2.setBounds(0, 0, memberIconSize.toInt(), memberIconSize.toInt())
+        applyIcons(parentIcon.info.contents)
     }
 
+    /** Sets up app pair member icons for drawing. */
+    private fun applyIcons(contents: ArrayList<WorkspaceItemInfo>) {
+        // App pair should always contain 2 members; if not 2, return to avoid a crash loop
+        if (contents.size != 2) {
+            Log.w(TAG, "AppPair contents not 2, size: " + contents.size, Throwable())
+            return
+        }
+
+        // Generate new icons, using themed flag if needed
+        val flags = if (Themes.isThemedIconEnabled(context)) BitmapInfo.FLAG_THEMED else 0
+        val newIcon1 = parentIcon.info.contents[0].newIcon(context, flags)
+        val newIcon2 = parentIcon.info.contents[1].newIcon(context, flags)
+
+        // If app icons did not draw fully last time, animate to full icon
+        (appIcon1 as? PlaceHolderIconDrawable)?.animateIconUpdate(newIcon1)
+        (appIcon2 as? PlaceHolderIconDrawable)?.animateIconUpdate(newIcon2)
+
+        appIcon1 = newIcon1
+        appIcon2 = newIcon2
+        appIcon1?.setBounds(0, 0, memberIconSize.toInt(), memberIconSize.toInt())
+        appIcon2?.setBounds(0, 0, memberIconSize.toInt(), memberIconSize.toInt())
+    }
+
+
     /** Gets this icon graphic's bounds, with respect to the parent icon's coordinate system. */
     fun getIconBounds(outBounds: Rect) {
         outBounds.set(0, 0, backgroundSize.toInt(), backgroundSize.toInt())
@@ -110,6 +138,16 @@
         // Draw background
         appPairBackground.draw(canvas)
 
+        // Make sure icons are loaded
+        if (
+            appIcon1 == null ||
+                appIcon2 == null ||
+                appIcon1 is PlaceHolderIconDrawable ||
+                appIcon2 is PlaceHolderIconDrawable
+        ) {
+            applyIcons(parentIcon.info.contents)
+        }
+
         // Draw first icon
         canvas.save()
         // The app icons are placed differently depending on device orientation.
@@ -118,7 +156,7 @@
         } else {
             canvas.translate(width / 2f - memberIconSize / 2f, innerPadding)
         }
-        appIcon1.draw(canvas)
+        appIcon1?.draw(canvas)
         canvas.restore()
 
         // Draw second icon
@@ -135,7 +173,7 @@
                 height - (innerPadding + memberIconSize)
             )
         }
-        appIcon2.draw(canvas)
+        appIcon2?.draw(canvas)
         canvas.restore()
     }
 }
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index e3314d4..4d4a8f7 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -636,10 +636,10 @@
         return getResources().getDimensionPixelSize(R.dimen.popup_vertical_padding);
     }
 
-    protected AnimatorSet getOpenCloseAnimator(boolean isOpening, int scaleDuration,
-            int fadeStartDelay, int fadeDuration, int childFadeStartDelay, int childFadeDuration,
-            Interpolator interpolator) {
-
+    /**
+     * Sets X and Y pivots for the view animation considering arrow position.
+     */
+    protected void setPivotForOpenCloseAnimation() {
         int arrowCenter = mArrowOffsetHorizontal + mArrowWidth / 2;
         if (mIsArrowRotated) {
             setPivotX(mIsLeftAligned ? 0f : getMeasuredWidth());
@@ -648,6 +648,14 @@
             setPivotX(mIsLeftAligned ? arrowCenter : getMeasuredWidth() - arrowCenter);
             setPivotY(mIsAboveIcon ? getMeasuredHeight() : 0f);
         }
+    }
+
+
+    protected AnimatorSet getOpenCloseAnimator(boolean isOpening, int scaleDuration,
+            int fadeStartDelay, int fadeDuration, int childFadeStartDelay, int childFadeDuration,
+            Interpolator interpolator) {
+
+        setPivotForOpenCloseAnimation();
 
         float[] alphaValues = isOpening ? new float[] {0, 1} : new float[] {1, 0};
         float[] scaleValues = isOpening ? new float[] {0.5f, 1.02f} : new float[] {1f, 0.5f};
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 18f583d..1419dc4 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -175,6 +175,13 @@
         sTransientTaskbarStatusForTests = enable;
     }
 
+    /**
+     * Returns whether the taskbar is pinned in gesture navigation mode.
+     */
+    public static boolean isPinnedTaskbar(Context context) {
+        return INSTANCE.get(context).getInfo().isPinnedTaskbar();
+    }
+
     @Override
     public void close() {
         mDestroyed = true;
@@ -423,6 +430,12 @@
             }
             return true;
         }
+        /**
+         * Returns whether the taskbar is pinned in gesture navigation mode.
+         */
+        public boolean isPinnedTaskbar() {
+            return navigationMode == NavigationMode.NO_BUTTON && !isTransientTaskbar();
+        }
 
         /**
          * Returns {@code true} if the bounds represent a tablet.
diff --git a/src/com/android/launcher3/util/KeyboardShortcutsDelegate.java b/src/com/android/launcher3/util/KeyboardShortcutsDelegate.java
index c9db83d..e4e0bae 100644
--- a/src/com/android/launcher3/util/KeyboardShortcutsDelegate.java
+++ b/src/com/android/launcher3/util/KeyboardShortcutsDelegate.java
@@ -17,6 +17,7 @@
 
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.getSupportedActions;
 
 import android.util.Log;
@@ -27,6 +28,7 @@
 
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.accessibility.BaseAccessibilityDelegate;
@@ -118,17 +120,22 @@
                 return true;
             } else if (mLauncher.getAppsView().isInAllApps()) {
                 // Close all apps if there are no open floating views.
-                closeAllApps();
+                mLauncher.getStateManager().goToState(NORMAL, true);
+                return true;
+            } else if (mLauncher.isInState(LauncherState.OVERVIEW)
+                    || mLauncher.isInState(LauncherState.OVERVIEW_SPLIT_SELECT)) {
+                // Close Overview and return to home.
+                mLauncher.getStateManager().goToState(NORMAL, true);
+                return true;
+            } else if (mLauncher.isInState(LauncherState.OVERVIEW_MODAL_TASK)) {
+                // Return to the previous state (Overview) when the modal task is open.
+                mLauncher.getStateManager().goToState(OVERVIEW, true);
                 return true;
             }
         }
         return null;
     }
 
-    private void closeAllApps() {
-        mLauncher.getStateManager().goToState(NORMAL, true);
-    }
-
     /**
      * Handle key up event.
      * @param keyCode code of the key being pressed.
diff --git a/src/com/android/launcher3/views/ClipIconView.java b/src/com/android/launcher3/views/ClipIconView.java
index 87e496e..7737adb 100644
--- a/src/com/android/launcher3/views/ClipIconView.java
+++ b/src/com/android/launcher3/views/ClipIconView.java
@@ -112,7 +112,7 @@
         float scaleY = rect.height() / minSize;
         float scale = Math.max(1f, Math.min(scaleX, scaleY));
 
-        if (Float.isNaN(scale)) {
+        if (Float.isNaN(scale) || Float.isInfinite(scale)) {
             // Views are no longer laid out, do not update.
             return;
         }
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt
index 0f27893..92caf23 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt
@@ -55,7 +55,7 @@
 	bottomSheetCloseDuration: 500
 	bottomSheetWorkspaceScale: 0.97
 	bottomSheetDepth: 0.0
-	allAppsShiftRange: 1496.0px (748.0dp)
+	allAppsShiftRange: 1600.0px (800.0dp)
 	allAppsOpenDuration: 500
 	allAppsCloseDuration: 500
 	allAppsIconSizePx: 120.0px (60.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt
index 85f7ca1..3815fa9 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt
@@ -55,7 +55,7 @@
 	bottomSheetCloseDuration: 500
 	bottomSheetWorkspaceScale: 0.97
 	bottomSheetDepth: 0.0
-	allAppsShiftRange: 1496.0px (748.0dp)
+	allAppsShiftRange: 1600.0px (800.0dp)
 	allAppsOpenDuration: 500
 	allAppsCloseDuration: 500
 	allAppsIconSizePx: 120.0px (60.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt
index bd47777..7e0f316 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt
@@ -55,7 +55,7 @@
 	bottomSheetCloseDuration: 500
 	bottomSheetWorkspaceScale: 0.97
 	bottomSheetDepth: 0.0
-	allAppsShiftRange: 2019.0px (1009.5dp)
+	allAppsShiftRange: 2560.0px (1280.0dp)
 	allAppsOpenDuration: 500
 	allAppsCloseDuration: 500
 	allAppsIconSizePx: 120.0px (60.0dp)
@@ -66,7 +66,7 @@
 	allAppsBorderSpacePxX: 16.0px (8.0dp)
 	allAppsBorderSpacePxY: 32.0px (16.0dp)
 	numShownAllAppsColumns: 6
-	allAppsPadding.top: 541.0px (270.5dp)
+	allAppsPadding.top: 104.0px (52.0dp)
 	allAppsPadding.left: 32.0px (16.0dp)
 	allAppsPadding.right: 32.0px (16.0dp)
 	allAppsLeftRightMargin: 152.0px (76.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt
index 902885a..58c3890 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt
@@ -55,7 +55,7 @@
 	bottomSheetCloseDuration: 500
 	bottomSheetWorkspaceScale: 0.97
 	bottomSheetDepth: 0.0
-	allAppsShiftRange: 2019.0px (1009.5dp)
+	allAppsShiftRange: 2560.0px (1280.0dp)
 	allAppsOpenDuration: 500
 	allAppsCloseDuration: 500
 	allAppsIconSizePx: 120.0px (60.0dp)
@@ -66,7 +66,7 @@
 	allAppsBorderSpacePxX: 16.0px (8.0dp)
 	allAppsBorderSpacePxY: 32.0px (16.0dp)
 	numShownAllAppsColumns: 6
-	allAppsPadding.top: 541.0px (270.5dp)
+	allAppsPadding.top: 104.0px (52.0dp)
 	allAppsPadding.left: 32.0px (16.0dp)
 	allAppsPadding.right: 32.0px (16.0dp)
 	allAppsLeftRightMargin: 152.0px (76.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt
index 43e4a60..1e363a2 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt
@@ -55,7 +55,7 @@
 	bottomSheetCloseDuration: 500
 	bottomSheetWorkspaceScale: 0.97
 	bottomSheetDepth: 1.0
-	allAppsShiftRange: 1730.0px (659.0476dp)
+	allAppsShiftRange: 1840.0px (700.9524dp)
 	allAppsOpenDuration: 500
 	allAppsCloseDuration: 500
 	allAppsIconSizePx: 141.0px (53.714287dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt
index e7ea839..617b54b 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt
@@ -55,7 +55,7 @@
 	bottomSheetCloseDuration: 500
 	bottomSheetWorkspaceScale: 0.97
 	bottomSheetDepth: 1.0
-	allAppsShiftRange: 1730.0px (659.0476dp)
+	allAppsShiftRange: 1840.0px (700.9524dp)
 	allAppsOpenDuration: 500
 	allAppsCloseDuration: 500
 	allAppsIconSizePx: 141.0px (53.714287dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt
index 043380c..483b5e7 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt
@@ -55,7 +55,7 @@
 	bottomSheetCloseDuration: 500
 	bottomSheetWorkspaceScale: 0.97
 	bottomSheetDepth: 1.0
-	allAppsShiftRange: 2075.0px (790.4762dp)
+	allAppsShiftRange: 2208.0px (841.1429dp)
 	allAppsOpenDuration: 500
 	allAppsCloseDuration: 500
 	allAppsIconSizePx: 141.0px (53.714287dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt
index a1b3e95..8d0640c 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt
@@ -55,7 +55,7 @@
 	bottomSheetCloseDuration: 500
 	bottomSheetWorkspaceScale: 0.97
 	bottomSheetDepth: 1.0
-	allAppsShiftRange: 2075.0px (790.4762dp)
+	allAppsShiftRange: 2208.0px (841.1429dp)
 	allAppsOpenDuration: 500
 	allAppsCloseDuration: 500
 	allAppsIconSizePx: 141.0px (53.714287dp)
diff --git a/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java b/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java
index 5d41da0..cb30854 100644
--- a/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java
+++ b/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java
@@ -21,6 +21,8 @@
 import static com.android.launcher3.allapps.AllAppsStore.DEFER_UPDATES_TEST;
 import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
 import static com.android.launcher3.util.TestUtil.installDummyAppForUser;
+import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -40,10 +42,10 @@
 import com.android.launcher3.allapps.WorkProfileManager;
 import com.android.launcher3.tapl.LauncherInstrumentation;
 import com.android.launcher3.util.TestUtil;
+import com.android.launcher3.util.rule.TestStabilityRule;
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 
 import java.io.IOException;
@@ -135,8 +137,10 @@
                 LauncherInstrumentation.WAIT_TIME_MS);
     }
 
+    // Staging; will be promoted to presubmit if stable
+    @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT)
+
     @Test
-    @Ignore("b/243855320")
     public void toggleWorks() {
         assumeTrue(mWorkProfileSetupSuccessful);
         waitForWorkTabSetup();
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index b6b4a47..6c0010d 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -16,7 +16,10 @@
 
 package com.android.launcher3.tapl;
 
+import static android.view.KeyEvent.KEYCODE_ESCAPE;
+
 import static com.android.launcher3.tapl.LauncherInstrumentation.TASKBAR_RES_ID;
+import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
 
 import android.graphics.Rect;
 
@@ -27,15 +30,24 @@
 import androidx.test.uiautomator.Direction;
 import androidx.test.uiautomator.UiObject2;
 
+import com.android.launcher3.testing.shared.TestProtocol;
+
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 /**
  * Common overview panel for both Launcher and fallback recents
  */
 public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
+
+    private static final Pattern EVENT_ALT_ESC_DOWN = Pattern.compile(
+            "Key event: KeyEvent.*?action=ACTION_DOWN.*?keyCode=KEYCODE_ESCAPE.*?metaState=0");
+    private static final Pattern EVENT_ALT_ESC_UP = Pattern.compile(
+            "Key event: KeyEvent.*?action=ACTION_UP.*?keyCode=KEYCODE_ESCAPE.*?metaState=0");
+
     private static final int FLINGS_FOR_DISMISS_LIMIT = 40;
 
     BaseOverview(LauncherInstrumentation launcher) {
@@ -367,6 +379,23 @@
         return !task.isTaskSplit();
     }
 
+    /**
+     * Presses the esc key to dismiss Overview.
+     */
+    public Workspace dismissByEscKey() {
+        try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
+            mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ALT_ESC_DOWN);
+            mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ALT_ESC_UP);
+            mLauncher.runToState(
+                    () -> mLauncher.getDevice().pressKeyCode(KEYCODE_ESCAPE),
+                    NORMAL_STATE_ORDINAL, "pressing esc key");
+            try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+                    "pressed esc key")) {
+                return mLauncher.getWorkspace();
+            }
+        }
+    }
+
     private void verifyActionsViewVisibility() {
         try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
                 "want to assert overview actions view visibility")) {
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 2896ede..7d3807e 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -21,6 +21,7 @@
 import static android.content.pm.PackageManager.MATCH_ALL;
 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
 import static android.view.KeyEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_SCROLL;
 import static android.view.MotionEvent.ACTION_UP;
 import static android.view.MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT;
 
@@ -1703,6 +1704,16 @@
                 "scrolling");
     }
 
+    void pointerScroll(float pointerX, float pointerY, Direction direction) {
+        executeAndWaitForLauncherEvent(
+                () -> injectEvent(getPointerMotionEvent(
+                        ACTION_SCROLL, pointerX, pointerY, direction)),
+                event -> TestProtocol.SCROLL_FINISHED_MESSAGE.equals(event.getClassName()),
+                () -> "Didn't receive a scroll end message: " + direction + " scroll from ("
+                        + pointerX + ", " + pointerY + ")",
+                "scrolling");
+    }
+
     // Inject a swipe gesture. Inject exactly 'steps' motion points, incrementing event time by a
     // fixed interval each time.
     public void linearGesture(int startX, int startY, int endX, int endY, int steps,
@@ -1766,6 +1777,41 @@
         return getContext().getResources();
     }
 
+    private static MotionEvent getPointerMotionEvent(
+            int action, float x, float y, Direction direction) {
+        MotionEvent.PointerCoords[] coordinates = new MotionEvent.PointerCoords[1];
+        coordinates[0] = new MotionEvent.PointerCoords();
+        coordinates[0].x = x;
+        coordinates[0].y = y;
+        boolean isVertical = direction == Direction.UP || direction == Direction.DOWN;
+        boolean isForward = direction == Direction.RIGHT || direction == Direction.DOWN;
+        coordinates[0].setAxisValue(
+                isVertical ? MotionEvent.AXIS_VSCROLL : MotionEvent.AXIS_HSCROLL,
+                isForward ? 1f : -1f);
+
+        MotionEvent.PointerProperties[] properties = new MotionEvent.PointerProperties[1];
+        properties[0] = new MotionEvent.PointerProperties();
+        properties[0].id = 0;
+        properties[0].toolType = MotionEvent.TOOL_TYPE_MOUSE;
+
+        final long downTime = SystemClock.uptimeMillis();
+        return MotionEvent.obtain(
+                downTime,
+                downTime,
+                action,
+                /* pointerCount= */ 1,
+                properties,
+                coordinates,
+                /* metaState= */ 0,
+                /* buttonState= */ 0,
+                /* xPrecision= */ 1f,
+                /* yPrecision= */ 1f,
+                /* deviceId= */ 0,
+                /* edgeFlags= */ 0,
+                InputDevice.SOURCE_CLASS_POINTER,
+                /* flags= */ 0);
+    }
+
     private static MotionEvent getTrackpadMotionEvent(long downTime, long eventTime,
             int action, float x, float y, int pointerCount, TrackpadGestureType gestureType) {
         MotionEvent.PointerProperties[] pointerProperties =
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
index bd2c9c1..d7c40a0 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
@@ -89,8 +89,7 @@
     private SelectModeButtons getSelectModeButtons() {
         try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
                 "want to get select mode buttons")) {
-            UiObject2 selectModeButtons = mLauncher.waitForLauncherObject("select_mode_buttons");
-            return new SelectModeButtons(selectModeButtons, mLauncher);
+            return new SelectModeButtons(mLauncher);
         }
     }
 
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenu.java b/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenu.java
index 3d2914d..c6fa31d 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenu.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenu.java
@@ -16,6 +16,8 @@
 
 package com.android.launcher3.tapl;
 
+import static com.android.launcher3.testing.shared.TestProtocol.OVERVIEW_MODAL_TASK_STATE_ORDINAL;
+
 import androidx.annotation.NonNull;
 import androidx.test.uiautomator.By;
 import androidx.test.uiautomator.UiObject2;
@@ -72,6 +74,25 @@
         }
     }
 
+    /** Taps the select menu item from the overview task menu. */
+    @NonNull
+    public SelectModeButtons tapSelectMenuItem() {
+        try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+             LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+                     "before tapping the select menu item")) {
+
+            mLauncher.runToState(
+                    () -> mLauncher.clickLauncherObject(
+                            mLauncher.findObjectInContainer(mMenu, By.text("Select"))),
+                    OVERVIEW_MODAL_TASK_STATE_ORDINAL, "tapping select menu item");
+
+            try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
+                    "select menu item opened")) {
+                return new SelectModeButtons(mLauncher);
+            }
+        }
+    }
+
     /** Returns true if an item matching the given string is present in the menu. */
     public boolean hasMenuItem(String expectedMenuItemText) {
         UiObject2 menuItem = mLauncher.findObjectInContainer(mMenu, By.text(expectedMenuItemText));
diff --git a/tests/tapl/com/android/launcher3/tapl/SelectModeButtons.java b/tests/tapl/com/android/launcher3/tapl/SelectModeButtons.java
index e1b73a4..146a67c 100644
--- a/tests/tapl/com/android/launcher3/tapl/SelectModeButtons.java
+++ b/tests/tapl/com/android/launcher3/tapl/SelectModeButtons.java
@@ -16,9 +16,15 @@
 
 package com.android.launcher3.tapl;
 
+import static android.view.KeyEvent.KEYCODE_ESCAPE;
+
 import androidx.annotation.NonNull;
 import androidx.test.uiautomator.UiObject2;
 
+import com.android.launcher3.testing.shared.TestProtocol;
+
+import java.util.regex.Pattern;
+
 /**
  * View containing select mode buttons
  */
@@ -26,9 +32,14 @@
     private final UiObject2 mSelectModeButtons;
     private final LauncherInstrumentation mLauncher;
 
-    SelectModeButtons(UiObject2 selectModeButtons,
-            LauncherInstrumentation launcherInstrumentation) {
-        mSelectModeButtons = selectModeButtons;
+    private static final Pattern EVENT_ALT_ESC_DOWN = Pattern.compile(
+            "Key event: KeyEvent.*?action=ACTION_DOWN.*?keyCode=KEYCODE_ESCAPE.*?metaState=0");
+    private static final Pattern EVENT_ALT_ESC_UP = Pattern.compile(
+            "Key event: KeyEvent.*?action=ACTION_UP.*?keyCode=KEYCODE_ESCAPE.*?metaState=0");
+
+
+    SelectModeButtons(LauncherInstrumentation launcherInstrumentation) {
+        mSelectModeButtons = launcherInstrumentation.waitForLauncherObject("select_mode_buttons");
         mLauncher = launcherInstrumentation;
     }
 
@@ -48,4 +59,22 @@
             }
         }
     }
+
+    /**
+     * Close select mode when ESC key is pressed.
+     * @return The Overview
+     */
+    @NonNull
+    public Overview dismissByEscKey() {
+        try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
+            mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ALT_ESC_DOWN);
+            mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ALT_ESC_UP);
+            mLauncher.getDevice().pressKeyCode(KEYCODE_ESCAPE);
+            try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+                    "pressed esc key")) {
+                return new Overview(mLauncher);
+            }
+        }
+    }
+
 }
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index 75d6ed1..ada0a7f 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -708,10 +708,9 @@
      */
     public void flingForward() {
         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
-            final UiObject2 workspace = verifyActiveContainer();
-            mLauncher.scroll(workspace, Direction.RIGHT,
-                    new Rect(0, 0, mLauncher.getEdgeSensitivityWidth() + 1, 0),
-                    FLING_STEPS, false);
+            Rect workspaceBounds = mLauncher.getVisibleBounds(verifyActiveContainer());
+            mLauncher.pointerScroll(
+                    workspaceBounds.centerX(), workspaceBounds.centerY(), Direction.RIGHT);
             verifyActiveContainer();
         }
     }
@@ -722,10 +721,9 @@
      */
     public void flingBackward() {
         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
-            final UiObject2 workspace = verifyActiveContainer();
-            mLauncher.scroll(workspace, Direction.LEFT,
-                    new Rect(mLauncher.getEdgeSensitivityWidth() + 1, 0, 0, 0),
-                    FLING_STEPS, false);
+            Rect workspaceBounds = mLauncher.getVisibleBounds(verifyActiveContainer());
+            mLauncher.pointerScroll(
+                    workspaceBounds.centerX(), workspaceBounds.centerY(), Direction.LEFT);
             verifyActiveContainer();
         }
     }