Merge "Do not show task bar edu in folded state with task bar / nav bar unification" into main
diff --git a/quickstep/Android.bp b/quickstep/Android.bp
index 638ce27..ec4f6fc 100644
--- a/quickstep/Android.bp
+++ b/quickstep/Android.bp
@@ -41,6 +41,7 @@
         "tests/src/com/android/quickstep/TaskbarModeSwitchRule.java",
         "tests/src/com/android/quickstep/NavigationModeSwitchRule.java",
         "tests/src/com/android/quickstep/AbstractQuickStepTest.java",
+        "tests/src/com/android/quickstep/TaplOverviewIconTest.java",
         "tests/src/com/android/quickstep/TaplTestsQuickstep.java",
         "tests/src/com/android/quickstep/TaplTestsSplitscreen.java",
     ]
diff --git a/quickstep/src/com/android/launcher3/HomeTransitionController.java b/quickstep/src/com/android/launcher3/HomeTransitionController.java
new file mode 100644
index 0000000..b264115
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/HomeTransitionController.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3;
+
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.quickstep.SystemUiProxy;
+import com.android.wm.shell.transition.IHomeTransitionListener;
+
+/**
+ * Controls launcher response to home activity visibility changing.
+ */
+public class HomeTransitionController {
+
+    private final QuickstepLauncher mLauncher;
+    @Nullable private IHomeTransitionListener mHomeTransitionListener;
+
+    public HomeTransitionController(QuickstepLauncher launcher) {
+        mLauncher = launcher;
+    }
+
+    public void registerHomeTransitionListener() {
+        mHomeTransitionListener = new IHomeTransitionListener.Stub() {
+            @Override
+            public void onHomeVisibilityChanged(boolean isVisible) {
+                MAIN_EXECUTOR.execute(() -> {
+                    if (mLauncher.getTaskbarUIController() != null) {
+                        mLauncher.getTaskbarUIController().onLauncherVisibilityChanged(isVisible);
+                    }
+                });
+            }
+        };
+
+        SystemUiProxy.INSTANCE.get(mLauncher).setHomeTransitionListener(mHomeTransitionListener);
+    }
+
+    public void unregisterHomeTransitionListener() {
+        SystemUiProxy.INSTANCE.get(mLauncher).setHomeTransitionListener(null);
+        mHomeTransitionListener = null;
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index d2be94a..e77d2c6 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -77,7 +77,6 @@
 import android.app.WindowConfiguration;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.graphics.Color;
@@ -187,9 +186,6 @@
      */
     public static final int STATUS_BAR_TRANSITION_PRE_DELAY = 96;
 
-    private static final String CONTROL_REMOTE_APP_TRANSITION_PERMISSION =
-            "android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS";
-
     public static final long APP_LAUNCH_DURATION = 500;
 
     private static final long APP_LAUNCH_ALPHA_DURATION = 50;
@@ -292,8 +288,8 @@
 
         mLauncher.addOnDeviceProfileChangeListener(this);
 
-        if (supportsSSplashScreen()) {
-            mTaskStartParams = new LinkedHashMap<Integer, Pair<Integer, Integer>>(MAX_NUM_TASKS) {
+        if (ENABLE_SHELL_STARTING_SURFACE) {
+            mTaskStartParams = new LinkedHashMap<>(MAX_NUM_TASKS) {
                 @Override
                 protected boolean removeEldestEntry(Entry<Integer, Pair<Integer, Integer>> entry) {
                     return size() > MAX_NUM_TASKS;
@@ -681,7 +677,7 @@
         mDragLayer.getLocationOnScreen(dragLayerBounds);
 
         final boolean hasSplashScreen;
-        if (supportsSSplashScreen()) {
+        if (ENABLE_SHELL_STARTING_SURFACE) {
             int taskId = openingTargets.getFirstAppTargetTaskId();
             Pair<Integer, Integer> defaultParams = Pair.create(STARTING_WINDOW_TYPE_NONE, 0);
             Pair<Integer, Integer> taskParams =
@@ -926,7 +922,7 @@
 
         RemoteAnimationTarget openingTarget = openingTargets.getFirstAppTarget();
         int fallbackBackgroundColor = 0;
-        if (openingTarget != null && supportsSSplashScreen()) {
+        if (openingTarget != null && ENABLE_SHELL_STARTING_SURFACE) {
             fallbackBackgroundColor = mTaskStartParams.containsKey(openingTarget.taskId)
                     ? mTaskStartParams.get(openingTarget.taskId).second : 0;
             mTaskStartParams.remove(openingTarget.taskId);
@@ -1102,11 +1098,9 @@
         if (SEPARATE_RECENTS_ACTIVITY.get()) {
             return;
         }
-        if (hasControlRemoteAppTransitionPermission()) {
-            RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
-            addRemoteAnimations(definition);
-            mLauncher.registerRemoteAnimations(definition);
-        }
+        RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
+        addRemoteAnimations(definition);
+        mLauncher.registerRemoteAnimations(definition);
     }
 
     /**
@@ -1144,28 +1138,27 @@
         if (SEPARATE_RECENTS_ACTIVITY.get()) {
             return;
         }
-        if (hasControlRemoteAppTransitionPermission()) {
-            mWallpaperOpenTransitionRunner = createWallpaperOpenRunner(false /* fromUnlock */);
-            mLauncherOpenTransition = new RemoteTransition(
-                    new LauncherAnimationRunner(mHandler, mWallpaperOpenTransitionRunner,
-                            false /* startAtFrontOfQueue */).toRemoteTransition(),
-                    mLauncher.getIApplicationThread(), "QuickstepLaunchHome");
 
-            TransitionFilter homeCheck = new TransitionFilter();
-            // No need to handle the transition that also dismisses keyguard.
-            homeCheck.mNotFlags = TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
-            homeCheck.mRequirements =
-                    new TransitionFilter.Requirement[]{new TransitionFilter.Requirement(),
-                            new TransitionFilter.Requirement()};
-            homeCheck.mRequirements[0].mActivityType = ACTIVITY_TYPE_HOME;
-            homeCheck.mRequirements[0].mTopActivity = mLauncher.getComponentName();
-            homeCheck.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
-            homeCheck.mRequirements[0].mOrder = CONTAINER_ORDER_TOP;
-            homeCheck.mRequirements[1].mActivityType = ACTIVITY_TYPE_STANDARD;
-            homeCheck.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK};
-            SystemUiProxy.INSTANCE.get(mLauncher)
-                    .registerRemoteTransition(mLauncherOpenTransition, homeCheck);
-        }
+        mWallpaperOpenTransitionRunner = createWallpaperOpenRunner(false /* fromUnlock */);
+        mLauncherOpenTransition = new RemoteTransition(
+                new LauncherAnimationRunner(mHandler, mWallpaperOpenTransitionRunner,
+                        false /* startAtFrontOfQueue */).toRemoteTransition(),
+                mLauncher.getIApplicationThread(), "QuickstepLaunchHome");
+
+        TransitionFilter homeCheck = new TransitionFilter();
+        // No need to handle the transition that also dismisses keyguard.
+        homeCheck.mNotFlags = TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
+        homeCheck.mRequirements =
+                new TransitionFilter.Requirement[]{new TransitionFilter.Requirement(),
+                        new TransitionFilter.Requirement()};
+        homeCheck.mRequirements[0].mActivityType = ACTIVITY_TYPE_HOME;
+        homeCheck.mRequirements[0].mTopActivity = mLauncher.getComponentName();
+        homeCheck.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
+        homeCheck.mRequirements[0].mOrder = CONTAINER_ORDER_TOP;
+        homeCheck.mRequirements[1].mActivityType = ACTIVITY_TYPE_STANDARD;
+        homeCheck.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK};
+        SystemUiProxy.INSTANCE.get(mLauncher)
+                .registerRemoteTransition(mLauncherOpenTransition, homeCheck);
         if (mBackAnimationController != null) {
             mBackAnimationController.registerBackCallbacks(mHandler);
         }
@@ -1183,15 +1176,13 @@
         if (SEPARATE_RECENTS_ACTIVITY.get()) {
             return;
         }
-        if (hasControlRemoteAppTransitionPermission()) {
-            mLauncher.unregisterRemoteAnimations();
+        mLauncher.unregisterRemoteAnimations();
 
-            // Also clear strong references to the runners registered with the remote animation
-            // definition so we don't have to wait for the system gc
-            mWallpaperOpenRunner = null;
-            mAppLaunchRunner = null;
-            mKeyguardGoingAwayRunner = null;
-        }
+        // Also clear strong references to the runners registered with the remote animation
+        // definition so we don't have to wait for the system gc
+        mWallpaperOpenRunner = null;
+        mAppLaunchRunner = null;
+        mKeyguardGoingAwayRunner = null;
     }
 
     protected void unregisterRemoteTransitions() {
@@ -1201,13 +1192,11 @@
         if (SEPARATE_RECENTS_ACTIVITY.get()) {
             return;
         }
-        if (hasControlRemoteAppTransitionPermission()) {
-            if (mLauncherOpenTransition == null) return;
-            SystemUiProxy.INSTANCE.get(mLauncher).unregisterRemoteTransition(
-                    mLauncherOpenTransition);
-            mLauncherOpenTransition = null;
-            mWallpaperOpenTransitionRunner = null;
-        }
+        if (mLauncherOpenTransition == null) return;
+        SystemUiProxy.INSTANCE.get(mLauncher).unregisterRemoteTransition(
+                mLauncherOpenTransition);
+        mLauncherOpenTransition = null;
+        mWallpaperOpenTransitionRunner = null;
         if (mBackAnimationController != null) {
             mBackAnimationController.unregisterBackCallbacks();
             mBackAnimationController = null;
@@ -1553,20 +1542,6 @@
         return closingAnimator;
     }
 
-    private boolean supportsSSplashScreen() {
-        return hasControlRemoteAppTransitionPermission()
-                && Utilities.ATLEAST_S
-                && ENABLE_SHELL_STARTING_SURFACE;
-    }
-
-    /**
-     * Returns true if we have permission to control remote app transisions
-     */
-    public boolean hasControlRemoteAppTransitionPermission() {
-        return mLauncher.checkSelfPermission(CONTROL_REMOTE_APP_TRANSITION_PERMISSION)
-                == PackageManager.PERMISSION_GRANTED;
-    }
-
     private void addCujInstrumentation(Animator anim, int cuj) {
         anim.addListener(new AnimationSuccessListener() {
             @Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index a321734..445a1bd 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -16,9 +16,10 @@
 package com.android.launcher3.taskbar;
 
 import static com.android.launcher3.QuickstepTransitionManager.TRANSIENT_TASKBAR_TRANSITION_DURATION;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_HOME_TRANSITION_LISTENER;
 import static com.android.launcher3.statemanager.BaseState.FLAG_NON_INTERACTIVE;
 import static com.android.launcher3.taskbar.TaskbarEduTooltipControllerKt.TOOLTIP_STEP_FEATURES;
-import static com.android.launcher3.taskbar.TaskbarLauncherStateController.FLAG_RESUMED;
+import static com.android.launcher3.taskbar.TaskbarLauncherStateController.FLAG_VISIBLE;
 import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
 
 import android.animation.Animator;
@@ -100,7 +101,9 @@
 
         mLauncher.setTaskbarUIController(this);
 
-        onLauncherResumedOrPaused(mLauncher.hasBeenResumed(), true /* fromInit */);
+        if (!ENABLE_HOME_TRANSITION_LISTENER.get()) {
+            onLauncherVisibilityChanged(mLauncher.hasBeenResumed(), true /* fromInit */);
+        }
 
         onStashedInAppChanged(mLauncher.getDeviceProfile());
         mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
@@ -119,7 +122,7 @@
     @Override
     protected void onDestroy() {
         super.onDestroy();
-        onLauncherResumedOrPaused(false);
+        onLauncherVisibilityChanged(false);
         mTaskbarLauncherStateController.onDestroy();
 
         mLauncher.setTaskbarUIController(null);
@@ -160,8 +163,9 @@
      *                            sub-animations are properly coordinated. This duration should not
      *                            actually be used since this animation tracks a swipe progress.
      */
-    protected void addLauncherResumeAnimation(AnimatorSet animation, int placeholderDuration) {
-        animation.play(onLauncherResumedOrPaused(
+    protected void addLauncherVisibilityChangedAnimation(AnimatorSet animation,
+            int placeholderDuration) {
+        animation.play(onLauncherVisibilityChanged(
                 /* isResumed= */ true,
                 /* fromInit= */ false,
                 /* startAnimation= */ false,
@@ -171,41 +175,41 @@
     /**
      * Should be called from onResume() and onPause(), and animates the Taskbar accordingly.
      */
-    public void onLauncherResumedOrPaused(boolean isResumed) {
-        onLauncherResumedOrPaused(isResumed, false /* fromInit */);
+    public void onLauncherVisibilityChanged(boolean isVisible) {
+        onLauncherVisibilityChanged(isVisible, false /* fromInit */);
     }
 
-    private void onLauncherResumedOrPaused(boolean isResumed, boolean fromInit) {
-        onLauncherResumedOrPaused(
-                isResumed,
+    private void onLauncherVisibilityChanged(boolean isVisible, boolean fromInit) {
+        onLauncherVisibilityChanged(
+                isVisible,
                 fromInit,
                 /* startAnimation= */ true,
                 DisplayController.isTransientTaskbar(mLauncher)
                         ? TRANSIENT_TASKBAR_TRANSITION_DURATION
-                        : (!isResumed
+                        : (!isVisible
                                 ? QuickstepTransitionManager.TASKBAR_TO_APP_DURATION
                                 : QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION));
     }
 
     @Nullable
-    private Animator onLauncherResumedOrPaused(
-            boolean isResumed, boolean fromInit, boolean startAnimation, int duration) {
+    private Animator onLauncherVisibilityChanged(
+            boolean isVisible, boolean fromInit, boolean startAnimation, int duration) {
         // Launcher is resumed during the swipe-to-overview gesture under shell-transitions, so
         // avoid updating taskbar state in that situation (when it's non-interactive -- or
         // "background") to avoid premature animations.
-        if (ENABLE_SHELL_TRANSITIONS && isResumed
+        if (ENABLE_SHELL_TRANSITIONS && isVisible
                 && mLauncher.getStateManager().getState().hasFlag(FLAG_NON_INTERACTIVE)
                 && !mLauncher.getStateManager().getState().isTaskbarAlignedWithHotseat(mLauncher)) {
             return null;
         }
 
-        mTaskbarLauncherStateController.updateStateForFlag(FLAG_RESUMED, isResumed);
+        mTaskbarLauncherStateController.updateStateForFlag(FLAG_VISIBLE, isVisible);
         return mTaskbarLauncherStateController.applyState(fromInit ? 0 : duration, startAnimation);
     }
 
     @Override
     public void refreshResumedState() {
-        onLauncherResumedOrPaused(mLauncher.hasBeenResumed());
+        onLauncherVisibilityChanged(mLauncher.hasBeenResumed());
     }
 
     @Override
@@ -353,7 +357,7 @@
     @Override
     public void onExpandPip() {
         super.onExpandPip();
-        mTaskbarLauncherStateController.updateStateForFlag(FLAG_RESUMED, false);
+        mTaskbarLauncherStateController.updateStateForFlag(FLAG_VISIBLE, false);
         mTaskbarLauncherStateController.applyState();
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index d4faf47..d4d6b26 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -26,9 +26,11 @@
 import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
 import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
 import static com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_OVERLAY_PROXY;
+import static com.android.launcher3.Flags.enableCursorHoverStates;
+import static com.android.launcher3.Utilities.calculateTextHeight;
 import static com.android.launcher3.Utilities.isRunningInTestHarness;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_PINNING;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NO_RECREATION;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_PINNING;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN;
 import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_DRAGGING;
 import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_FULLSCREEN;
@@ -847,6 +849,13 @@
         boolean shouldTreatAsTransient = DisplayController.isTransientTaskbar(this)
                 || (ENABLE_TASKBAR_PINNING.get() && !isThreeButtonNav());
 
+        int extraHeightForTaskbarTooltips = enableCursorHoverStates()
+                ? resources.getDimensionPixelSize(R.dimen.arrow_toast_arrow_height)
+                + (resources.getDimensionPixelSize(R.dimen.taskbar_tooltip_vertical_padding) * 2)
+                + calculateTextHeight(
+                        resources.getDimensionPixelSize(R.dimen.arrow_toast_text_size))
+                : 0;
+
         // Return transient taskbar window height when pinning feature is enabled, so taskbar view
         // does not get cut off during pinning animation.
         if (shouldTreatAsTransient) {
@@ -855,11 +864,14 @@
 
             return transientTaskbarDp.taskbarHeight
                     + (2 * transientTaskbarDp.taskbarBottomMargin)
-                    + resources.getDimensionPixelSize(R.dimen.transient_taskbar_shadow_blur);
+                    + Math.max(extraHeightForTaskbarTooltips, resources.getDimensionPixelSize(
+                            R.dimen.transient_taskbar_shadow_blur));
         }
 
+
         return mDeviceProfile.taskbarHeight
-                + Math.max(getLeftCornerRadius(), getRightCornerRadius());
+                + Math.max(getLeftCornerRadius(), getRightCornerRadius())
+                + extraHeightForTaskbarTooltips;
     }
 
     public int getSetupWindowHeight() {
@@ -1236,7 +1248,7 @@
 
         TaskbarUIController uiController = mControllers.uiController;
         if (uiController instanceof LauncherTaskbarUIController) {
-            ((LauncherTaskbarUIController) uiController).addLauncherResumeAnimation(
+            ((LauncherTaskbarUIController) uiController).addLauncherVisibilityChangedAnimation(
                     fullAnimation, duration);
         }
         mControllers.taskbarStashController.addUnstashToHotseatAnimation(fullAnimation, duration);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarHoverToolTipController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarHoverToolTipController.java
index 2c72b2c..0443197 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarHoverToolTipController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarHoverToolTipController.java
@@ -139,15 +139,6 @@
             mActivity.setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS, false);
             return true;
         } else if (!isAnyOtherFloatingViewOpen && event.getAction() == ACTION_HOVER_ENTER) {
-            if (!mActivity.isTaskbarWindowFullscreen()) {
-                // First time we want to animate a tooltip open, we set the drag layer to
-                // fullscreen so the tooltip will fit within the window. This causes a layout
-                // pass which will trigger a hover exit and hover enter event while still
-                // hovering the view, so we do not animate open on the first hover enter if we
-                // are not already in fullscreen.
-                mActivity.setTaskbarWindowFullscreen(true);
-                return false;
-            }
             // If hovering above a taskbar icon starts, animate the tooltip open. Do not
             // reveal if any floating views such as folders or edu pop-ups are open.
             startRevealHoverToolTip();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 3bfeee8..56ba460 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -68,13 +68,13 @@
     private static final String TAG = TaskbarLauncherStateController.class.getSimpleName();
     private static final boolean DEBUG = false;
 
-    /** Launcher activity is resumed and focused. */
-    public static final int FLAG_RESUMED = 1 << 0;
+    /** Launcher activity is visible and focused. */
+    public static final int FLAG_VISIBLE = 1 << 0;
 
     /**
-     * A external transition / animation is running that will result in FLAG_RESUMED being set.
+     * A external transition / animation is running that will result in FLAG_VISIBLE being set.
      **/
-    public static final int FLAG_TRANSITION_TO_RESUMED = 1 << 1;
+    public static final int FLAG_TRANSITION_TO_VISIBLE = 1 << 1;
 
     /**
      * Set while the launcher state machine is performing a state transition, see {@link
@@ -118,7 +118,7 @@
      */
     private static final int FLAG_TASKBAR_HIDDEN = 1 << 6;
 
-    private static final int FLAGS_LAUNCHER_ACTIVE = FLAG_RESUMED | FLAG_TRANSITION_TO_RESUMED;
+    private static final int FLAGS_LAUNCHER_ACTIVE = FLAG_VISIBLE | FLAG_TRANSITION_TO_VISIBLE;
     /** Equivalent to an int with all 1s for binary operation purposes */
     private static final int FLAGS_ALL = ~0;
 
@@ -207,7 +207,7 @@
                     // TODO(b/279514548) Cleans up bad state that can occur when user interacts with
                     // taskbar on top of transparent activity.
                     if (finalState == LauncherState.NORMAL && mLauncher.hasBeenResumed()) {
-                        updateStateForFlag(FLAG_RESUMED, true);
+                        updateStateForFlag(FLAG_VISIBLE, true);
                     }
                     applyState();
                     boolean disallowLongClick =
@@ -282,7 +282,7 @@
         }
         stashController.updateStateForFlag(FLAG_IN_APP, false);
 
-        updateStateForFlag(FLAG_TRANSITION_TO_RESUMED, true);
+        updateStateForFlag(FLAG_TRANSITION_TO_VISIBLE, true);
         animatorSet.play(stashController.createApplyStateAnimator(duration));
         animatorSet.play(applyState(duration, false));
 
@@ -433,7 +433,7 @@
             if (launcherTransitionCompleted
                     && mLauncherState == LauncherState.QUICK_SWITCH_FROM_HOME) {
                 // We're about to be paused, set immediately to ensure seamless handoff.
-                updateStateForFlag(FLAG_RESUMED, false);
+                updateStateForFlag(FLAG_VISIBLE, false);
                 applyState(0 /* duration */);
             }
             if (mLauncherState == LauncherState.NORMAL) {
@@ -759,10 +759,10 @@
             mTaskBarRecentsAnimationListener = null;
             ((RecentsView) mLauncher.getOverviewPanel()).setTaskLaunchListener(null);
 
-            // Update the resumed state immediately to ensure a seamless handoff
-            boolean launcherResumed = !finishedToApp;
-            updateStateForFlag(FLAG_TRANSITION_TO_RESUMED, false);
-            updateStateForFlag(FLAG_RESUMED, launcherResumed);
+            // Update the visible state immediately to ensure a seamless handoff
+            boolean launcherVisible = !finishedToApp;
+            updateStateForFlag(FLAG_TRANSITION_TO_VISIBLE, false);
+            updateStateForFlag(FLAG_VISIBLE, launcherVisible);
             applyState();
 
             TaskbarStashController controller = mControllers.taskbarStashController;
@@ -776,8 +776,8 @@
 
     private static String getStateString(int flags) {
         StringJoiner result = new StringJoiner("|");
-        appendFlag(result, flags, FLAG_RESUMED, "resumed");
-        appendFlag(result, flags, FLAG_TRANSITION_TO_RESUMED, "transition_to_resumed");
+        appendFlag(result, flags, FLAG_VISIBLE, "flag_visible");
+        appendFlag(result, flags, FLAG_TRANSITION_TO_VISIBLE, "transition_to_visible");
         appendFlag(result, flags, FLAG_LAUNCHER_IN_STATE_TRANSITION,
                 "launcher_in_state_transition");
         appendFlag(result, flags, FLAG_AWAKE, "awake");
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 1ff2804..5f58de5 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -18,9 +18,9 @@
 import static android.content.pm.PackageManager.FEATURE_PC;
 import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
 
+import static com.android.launcher3.Flags.enableCursorHoverStates;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_PINNING;
-import static com.android.launcher3.config.FeatureFlags.enableCursorHoverStates;
 import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
 
 import android.content.Context;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 7d88f05..4c739fa 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -33,6 +33,7 @@
 import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
 import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
 import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_HOME_TRANSITION_LISTENER;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
 import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
@@ -92,6 +93,7 @@
 import com.android.app.viewcapture.SettingsAwareViewCapture;
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.HomeTransitionController;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.LauncherState;
@@ -231,6 +233,8 @@
 
     private boolean mEnableWidgetDepth;
 
+    private HomeTransitionController mHomeTransitionController;
+
     @Override
     protected void setupViews() {
         super.setupViews();
@@ -261,6 +265,11 @@
         mAppTransitionManager.registerRemoteAnimations();
         mAppTransitionManager.registerRemoteTransitions();
 
+        if (ENABLE_HOME_TRANSITION_LISTENER.get()) {
+            mHomeTransitionController = new HomeTransitionController(this);
+            mHomeTransitionController.registerHomeTransitionListener();
+        }
+
         mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
         mDepthController = new DepthController(this);
         mDesktopVisibilityController = new DesktopVisibilityController(this);
@@ -368,8 +377,8 @@
         }
 
         if ((changeBits & ACTIVITY_STATE_RESUMED) != 0) {
-            if (mTaskbarUIController != null) {
-                mTaskbarUIController.onLauncherResumedOrPaused(hasBeenResumed());
+            if (!ENABLE_HOME_TRANSITION_LISTENER.get() && mTaskbarUIController != null) {
+                mTaskbarUIController.onLauncherVisibilityChanged(hasBeenResumed());
             }
         }
 
@@ -482,6 +491,10 @@
             mLauncherUnfoldAnimationController.onDestroy();
         }
 
+        if (mHomeTransitionController != null) {
+            mHomeTransitionController.unregisterHomeTransitionListener();
+        }
+
         if (mDesktopVisibilityController != null) {
             mDesktopVisibilityController.unregisterSystemUiListener();
         }
@@ -1021,7 +1034,7 @@
 
     @Override
     public boolean supportsAdaptiveIconAnimation(View clickedView) {
-        return mAppTransitionManager.hasControlRemoteAppTransitionPermission();
+        return true;
     }
 
     @Override
@@ -1056,10 +1069,7 @@
 
     @Override
     public ActivityOptionsWrapper getActivityLaunchOptions(View v, @Nullable ItemInfo item) {
-        ActivityOptionsWrapper activityOptions =
-                mAppTransitionManager.hasControlRemoteAppTransitionPermission()
-                        ? mAppTransitionManager.getActivityLaunchOptions(v)
-                        : super.getActivityLaunchOptions(v, item);
+        ActivityOptionsWrapper activityOptions = mAppTransitionManager.getActivityLaunchOptions(v);
         if (mLastTouchUpTime > 0) {
             activityOptions.options.setSourceInfo(ActivityOptions.SourceInfo.TYPE_LAUNCHER,
                     mLastTouchUpTime);
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 56765e5..468d96a 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -17,6 +17,7 @@
 
 import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
 
+import static com.android.launcher3.config.FeatureFlags.ENABLE_HOME_TRANSITION_LISTENER;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
@@ -92,6 +93,7 @@
 import com.android.wm.shell.splitscreen.ISplitSelectListener;
 import com.android.wm.shell.startingsurface.IStartingWindow;
 import com.android.wm.shell.startingsurface.IStartingWindowListener;
+import com.android.wm.shell.transition.IHomeTransitionListener;
 import com.android.wm.shell.transition.IShellTransitions;
 import com.android.wm.shell.util.GroupedRecentTaskInfo;
 
@@ -147,6 +149,7 @@
     private IOnBackInvokedCallback mBackToLauncherCallback;
     private IRemoteAnimationRunner mBackToLauncherRunner;
     private IDragAndDrop mDragAndDrop;
+    private IHomeTransitionListener mHomeTransitionListener;
 
     // Used to dedupe calls to SystemUI
     private int mLastShelfHeight;
@@ -248,6 +251,7 @@
         setBubblesListener(mBubblesListener);
         registerSplitScreenListener(mSplitScreenListener);
         registerSplitSelectListener(mSplitSelectListener);
+        setHomeTransitionListener(mHomeTransitionListener);
         setStartingWindowListener(mStartingWindowListener);
         setLauncherUnlockAnimationController(
                 mLauncherActivityClass, mLauncherUnlockAnimationController);
@@ -1043,6 +1047,24 @@
         mRemoteTransitions.remove(remoteTransition);
     }
 
+    public void setHomeTransitionListener(IHomeTransitionListener listener) {
+        if (!ENABLE_HOME_TRANSITION_LISTENER.get()) {
+            return;
+        }
+
+        mHomeTransitionListener = listener;
+
+        if (mShellTransitions != null) {
+            try {
+                mShellTransitions.setHomeTransitionListener(listener);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed call setHomeTransitionListener", e);
+            }
+        } else  {
+            Log.w(TAG, "Unable to call setHomeTransitionListener because ShellTransitions is null");
+        }
+    }
+
     /**
      * Use SystemUI's transaction-queue instead of Launcher's independent one. This is necessary
      * if Launcher and SystemUI need to coordinate transactions (eg. for shell transitions).
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
index f6a9440..12a8bd9 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
@@ -20,9 +20,9 @@
 import static android.view.MotionEvent.ACTION_UP;
 import static android.view.MotionEvent.INVALID_POINTER_ID;
 
+import static com.android.launcher3.Flags.enableCursorHoverStates;
 import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent;
 import static com.android.launcher3.Utilities.squaredHypot;
-import static com.android.launcher3.config.FeatureFlags.enableCursorHoverStates;
 import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_TOUCHING;
 
 import android.content.Context;
diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
index 7cc2c46..fce38e1 100644
--- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
@@ -145,6 +145,12 @@
             sourceRectHint = null;
         }
 
+        if (sourceRectHint != null && !appBounds.contains(sourceRectHint)) {
+            // This is a situation in which the source hint rect is outside the app bounds, so it is
+            // not a valid rectangle to use for cropping app surface
+            sourceRectHint = null;
+        }
+
         if (sourceRectHint == null) {
             mSourceRectHint.setEmpty();
             mSourceHintRectInsets = null;
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 92b942d..beb10ef 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -23,9 +23,10 @@
 import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
 import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
 import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.launcher3.Flags.enableCursorHoverStates;
+import static com.android.launcher3.Flags.enableOverviewIconMenu;
 import static com.android.launcher3.LauncherState.BACKGROUND_APP;
 import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
-import static com.android.launcher3.Flags.enableOverviewIconMenu;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
@@ -115,8 +116,6 @@
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.QuickStepContract;
 
-import kotlin.Unit;
-
 import java.lang.annotation.Retention;
 import java.util.Arrays;
 import java.util.Collections;
@@ -125,6 +124,8 @@
 import java.util.function.Consumer;
 import java.util.stream.Stream;
 
+import kotlin.Unit;
+
 /**
  * A task in the Recents view.
  */
@@ -445,7 +446,7 @@
 
         boolean keyboardFocusHighlightEnabled = FeatureFlags.ENABLE_KEYBOARD_QUICK_SWITCH.get()
                 || DesktopTaskView.DESKTOP_MODE_SUPPORTED;
-        boolean cursorHoverStatesEnabled = FeatureFlags.enableCursorHoverStates();
+        boolean cursorHoverStatesEnabled = enableCursorHoverStates();
 
         setWillNotDraw(!keyboardFocusHighlightEnabled && !cursorHoverStatesEnabled);
 
@@ -561,7 +562,7 @@
 
     @Override
     public boolean onInterceptHoverEvent(MotionEvent event) {
-        if (FeatureFlags.enableCursorHoverStates()) {
+        if (enableCursorHoverStates()) {
             // avoid triggering hover event on child elements which would cause HOVER_EXIT for this
             // task view
             return true;
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarHoverToolTipControllerTest.java b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarHoverToolTipControllerTest.java
index 1b208a7..9ed3906 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarHoverToolTipControllerTest.java
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarHoverToolTipControllerTest.java
@@ -22,12 +22,10 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -125,7 +123,6 @@
     public void onHover_hoverEnterIcon_revealToolTip() {
         when(mMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
         when(mMotionEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
-        when(taskbarActivityContext.isTaskbarWindowFullscreen()).thenReturn(true);
 
         boolean hoverHandled =
                 mTaskbarHoverToolTipController.onHover(mHoverBubbleTextView, mMotionEvent);
@@ -134,23 +131,6 @@
         assertThat(hoverHandled).isTrue();
         verify(taskbarActivityContext).setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS,
                 true);
-        verify(taskbarActivityContext, never()).setTaskbarWindowFullscreen(anyBoolean());
-    }
-
-    @Test
-    public void onHover_hoverEnterIcon_setFullScreenFirstHover() {
-        when(mMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
-        when(mMotionEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
-        when(taskbarActivityContext.isTaskbarWindowFullscreen()).thenReturn(false);
-
-        boolean hoverHandled =
-                mTaskbarHoverToolTipController.onHover(mHoverBubbleTextView, mMotionEvent);
-        waitForIdleSync();
-
-        assertThat(hoverHandled).isFalse();
-        verify(taskbarActivityContext, never()).setAutohideSuspendFlag(
-                FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS, true);
-        verify(taskbarActivityContext).setTaskbarWindowFullscreen(true);
     }
 
     @Test
@@ -171,7 +151,6 @@
     public void onHover_hoverEnterFolderIcon_revealToolTip() {
         when(mMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
         when(mMotionEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
-        when(taskbarActivityContext.isTaskbarWindowFullscreen()).thenReturn(true);
 
         boolean hoverHandled =
                 mTaskbarHoverToolTipController.onHover(mHoverFolderIcon, mMotionEvent);
@@ -180,7 +159,6 @@
         assertThat(hoverHandled).isTrue();
         verify(taskbarActivityContext).setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS,
                 true);
-        verify(taskbarActivityContext, never()).setTaskbarWindowFullscreen(anyBoolean());
     }
 
     @Test
diff --git a/tests/src/com/android/launcher3/appiconmenu/TaplOverviewIconAppChipMenuTest.java b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconAppChipMenuTest.java
similarity index 96%
rename from tests/src/com/android/launcher3/appiconmenu/TaplOverviewIconAppChipMenuTest.java
rename to quickstep/tests/src/com/android/quickstep/TaplOverviewIconAppChipMenuTest.java
index 4070c03..15952c1 100644
--- a/tests/src/com/android/launcher3/appiconmenu/TaplOverviewIconAppChipMenuTest.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconAppChipMenuTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.launcher3.appiconmenu;
+package com.android.quickstep;
 
 import com.android.launcher3.Flags;
 import com.android.launcher3.InvariantDeviceProfile;
diff --git a/tests/src/com/android/launcher3/appiconmenu/TaplOverviewIconTest.java b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java
similarity index 98%
rename from tests/src/com/android/launcher3/appiconmenu/TaplOverviewIconTest.java
rename to quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java
index 7340264..eba3252 100644
--- a/tests/src/com/android/launcher3/appiconmenu/TaplOverviewIconTest.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.launcher3.appiconmenu;
+package com.android.quickstep;
 
 import static com.android.launcher3.ui.TaplTestsLauncher3.initialize;
 
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 61f1f74..d45c225 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -16,7 +16,6 @@
 
 package com.android.quickstep;
 
-import static com.android.launcher3.config.FeatureFlags.ENABLE_CURSOR_HOVER_STATES;
 import static com.android.quickstep.TaskbarModeSwitchRule.Mode.PERSISTENT;
 import static com.android.quickstep.TaskbarModeSwitchRule.Mode.TRANSIENT;
 
@@ -45,7 +44,6 @@
 import com.android.launcher3.tapl.OverviewTask;
 import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
 import com.android.launcher3.ui.TaplTestsLauncher3;
-import com.android.launcher3.util.TestUtil;
 import com.android.launcher3.util.Wait;
 import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
 import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
@@ -226,7 +224,7 @@
     @Test
     @TaskbarModeSwitch(mode = TRANSIENT)
     public void testSwitchToOverviewWithStashedTaskbar() throws Exception {
-        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
+        try {
             startTestAppsWithCheck();
             // Set ignoreTaskbarVisibility, as transient taskbar will be stashed after app launch.
             mLauncher.setIgnoreTaskbarVisibility(true);
@@ -356,6 +354,7 @@
     @PortraitLandscape
     @TaskbarModeSwitch(mode = PERSISTENT)
     @PlatinumTest(focusArea = "launcher")
+    @ScreenRecord
     public void testOverviewForTablet() throws Exception {
         assumeTrue(mLauncher.isTablet());
 
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java
index fc23a05..db23cc0 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java
@@ -15,14 +15,15 @@
  */
 package com.android.quickstep;
 
-import static com.android.launcher3.config.FeatureFlags.ENABLE_CURSOR_HOVER_STATES;
+import static com.android.launcher3.Flags.enableCursorHoverStates;
 import static com.android.launcher3.util.TestConstants.AppNames.TEST_APP_NAME;
 import static com.android.quickstep.TaskbarModeSwitchRule.Mode.TRANSIENT;
 
+import static org.junit.Assume.assumeTrue;
+
 import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.launcher3.util.TestUtil;
 import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
 
 import org.junit.Test;
@@ -35,42 +36,32 @@
     @Test
     @TaskbarModeSwitch(mode = TRANSIENT)
     public void testShowTaskbarUnstashHintOnHover() {
-        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
-            getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
-            mLauncher.getLaunchedAppState().hoverToShowTaskbarUnstashHint();
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
+        assumeTrue(enableCursorHoverStates());
+        getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+        mLauncher.getLaunchedAppState().hoverToShowTaskbarUnstashHint();
     }
 
     @Test
     @TaskbarModeSwitch(mode = TRANSIENT)
     public void testUnstashTaskbarOnScreenBottomEdgeHover() {
-        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
-            getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
-            mLauncher.getLaunchedAppState().hoverScreenBottomEdgeToUnstashTaskbar();
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
+        assumeTrue(enableCursorHoverStates());
+        getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+        mLauncher.getLaunchedAppState().hoverScreenBottomEdgeToUnstashTaskbar();
     }
 
     @Test
     @TaskbarModeSwitch(mode = TRANSIENT)
     public void testHoverBelowHintedTaskbarToUnstash() {
-        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
-            getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
-            mLauncher.getLaunchedAppState().hoverBelowHintedTaskbarToUnstash();
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
+        assumeTrue(enableCursorHoverStates());
+        getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+        mLauncher.getLaunchedAppState().hoverBelowHintedTaskbarToUnstash();
     }
 
     @Test
     @TaskbarModeSwitch(mode = TRANSIENT)
     public void testClickHoveredTaskbarToGoHome() throws Exception {
-        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
-            getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
-            mLauncher.getLaunchedAppState().clickStashedTaskbarToGoHome();
-        }
+        assumeTrue(enableCursorHoverStates());
+        getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+        mLauncher.getLaunchedAppState().clickStashedTaskbarToGoHome();
     }
 }
diff --git a/res/layout/arrow_toast.xml b/res/layout/arrow_toast.xml
index 004e778..9e44917 100644
--- a/res/layout/arrow_toast.xml
+++ b/res/layout/arrow_toast.xml
@@ -29,11 +29,11 @@
         android:background="@drawable/arrow_toast_rounded_background"
         android:elevation="@dimen/arrow_toast_elevation"
         android:textColor="?attr/arrowTipTextColor"
-        android:textSize="14sp"/>
+        android:textSize="@dimen/arrow_toast_text_size"/>
 
     <View
         android:id="@+id/arrow"
         android:elevation="@dimen/arrow_toast_elevation"
         android:layout_width="@dimen/arrow_toast_arrow_width"
-        android:layout_height="10dp"/>
+        android:layout_height="@dimen/arrow_toast_arrow_height"/>
 </merge>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 070d024..e532dad 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -132,6 +132,8 @@
     <dimen name="arrow_toast_corner_radius">2dp</dimen>
     <dimen name="arrow_toast_elevation">2dp</dimen>
     <dimen name="arrow_toast_arrow_width">10dp</dimen>
+    <dimen name="arrow_toast_arrow_height">10dp</dimen>
+    <dimen name="arrow_toast_text_size">14sp</dimen>
 
     <dimen name="all_apps_divider_margin_vertical">8dp</dimen>
 
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index d7b50a0..ddcb1e6 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -17,8 +17,9 @@
 package com.android.launcher3;
 
 import static android.text.Layout.Alignment.ALIGN_NORMAL;
+
+import static com.android.launcher3.Flags.enableCursorHoverStates;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_ICON_LABEL_AUTO_SCALING;
-import static com.android.launcher3.config.FeatureFlags.enableCursorHoverStates;
 import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
 import static com.android.launcher3.icons.BitmapInfo.FLAG_NO_BADGE;
 import static com.android.launcher3.icons.BitmapInfo.FLAG_THEMED;
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 91fbe53..94e5970 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -57,6 +57,7 @@
 import android.view.accessibility.AccessibilityEvent;
 
 import androidx.annotation.IntDef;
+import androidx.annotation.Px;
 import androidx.core.graphics.ColorUtils;
 import androidx.core.view.ViewCompat;
 
@@ -175,6 +176,8 @@
 
     private final TimeInterpolator mEaseOutInterpolator;
     protected final ShortcutAndWidgetContainer mShortcutsAndWidgets;
+    @Px
+    protected int mSpaceBetweenCellLayoutsPx = 0;
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({WORKSPACE, HOTSEAT, FOLDER})
@@ -636,12 +639,19 @@
                 mVisualizeGridPaint.setColor(Color.argb((int) (alpha),
                         Color.red(mGridColor), Color.green(mGridColor), Color.blue(mGridColor)));
 
+                canvas.save();
+                canvas.translate(getMarginForGivenCellParams(params), 0);
                 canvas.drawRoundRect(mVisualizeGridRect, mGridVisualizationRoundingRadius,
                         mGridVisualizationRoundingRadius, mVisualizeGridPaint);
+                canvas.restore();
             }
         }
     }
 
+    protected float getMarginForGivenCellParams(CellLayoutLayoutParams params) {
+        return 0;
+    }
+
     @Override
     protected void dispatchDraw(Canvas canvas) {
         super.dispatchDraw(canvas);
@@ -2844,4 +2854,8 @@
     public boolean isRegionVacant(int x, int y, int spanX, int spanY) {
         return mOccupied.isRegionVacant(x, y, spanX, spanY);
     }
+
+    public void setSpaceBetweenCellLayoutsPx(@Px int spaceBetweenCellLayoutsPx) {
+        mSpaceBetweenCellLayoutsPx = spaceBetweenCellLayoutsPx;
+    }
 }
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 7d62045..b629ec2 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -2595,12 +2595,13 @@
             Trace.endAsyncSection(DISPLAY_WORKSPACE_TRACE_METHOD_NAME,
                     DISPLAY_WORKSPACE_TRACE_COOKIE);
         }
+        mStartupLatencyLogger
+                .logCardinality(workspaceItemCount)
+                .logEnd(isBindSync
+                        ? LAUNCHER_LATENCY_STARTUP_WORKSPACE_LOADER_SYNC
+                        : LAUNCHER_LATENCY_STARTUP_WORKSPACE_LOADER_ASYNC);
         MAIN_EXECUTOR.getHandler().postAtFrontOfQueue(() -> {
             mStartupLatencyLogger
-                    .logCardinality(workspaceItemCount)
-                    .logEnd(isBindSync
-                            ? LAUNCHER_LATENCY_STARTUP_WORKSPACE_LOADER_SYNC
-                            : LAUNCHER_LATENCY_STARTUP_WORKSPACE_LOADER_ASYNC)
                     .logEnd(LAUNCHER_LATENCY_STARTUP_TOTAL_DURATION)
                     .log()
                     .reset();
diff --git a/src/com/android/launcher3/MultipageCellLayout.java b/src/com/android/launcher3/MultipageCellLayout.java
index 44a1414..4b5c9ef 100644
--- a/src/com/android/launcher3/MultipageCellLayout.java
+++ b/src/com/android/launcher3/MultipageCellLayout.java
@@ -26,6 +26,7 @@
 import com.android.launcher3.celllayout.MulticellReorderAlgorithm;
 import com.android.launcher3.util.CellAndSpan;
 import com.android.launcher3.util.GridOccupancy;
+import com.android.launcher3.util.MultiTranslateDelegate;
 
 /**
  * CellLayout that simulates a split in the middle for use in foldable devices.
@@ -139,18 +140,59 @@
 
     @Override
     protected void onDraw(Canvas canvas) {
+        float animatedWorkspaceMargin = mSpaceBetweenCellLayoutsPx * mSpringLoadedProgress;
         if (mLeftBackground.getAlpha() > 0) {
+            canvas.save();
+            canvas.translate(-animatedWorkspaceMargin, 0);
             mLeftBackground.setState(mBackground.getState());
             mLeftBackground.draw(canvas);
+            canvas.restore();
         }
         if (mRightBackground.getAlpha() > 0) {
+            canvas.save();
+            canvas.translate(animatedWorkspaceMargin, 0);
             mRightBackground.setState(mBackground.getState());
             mRightBackground.draw(canvas);
+            canvas.restore();
         }
-
         super.onDraw(canvas);
     }
 
+    private void updateMarginBetweenCellLayouts() {
+        for (int i = 0; i < mShortcutsAndWidgets.getChildCount(); i++) {
+            View workspaceItem = mShortcutsAndWidgets.getChildAt(i);
+            if (!(workspaceItem instanceof Reorderable)) {
+                continue;
+            }
+            CellLayoutLayoutParams params =
+                    (CellLayoutLayoutParams) workspaceItem.getLayoutParams();
+            ((Reorderable) workspaceItem).getTranslateDelegate().setTranslation(
+                    MultiTranslateDelegate.INDEX_CELLAYOUT_MULTIPAGE_SPACING,
+                    getMarginForGivenCellParams(params),
+                    0
+            );
+
+        }
+    }
+
+    @Override
+    protected float getMarginForGivenCellParams(CellLayoutLayoutParams params) {
+        float margin = mSpaceBetweenCellLayoutsPx * mSpringLoadedProgress;
+        return params.getCellX() >= mCountX / 2 ? margin : -margin;
+    }
+
+    @Override
+    public void setSpringLoadedProgress(float progress) {
+        super.setSpringLoadedProgress(progress);
+        updateMarginBetweenCellLayouts();
+    }
+
+    @Override
+    public void setSpaceBetweenCellLayoutsPx(int spaceBetweenCellLayoutsPx) {
+        super.setSpaceBetweenCellLayoutsPx(spaceBetweenCellLayoutsPx);
+        updateMarginBetweenCellLayouts();
+    }
+
     @Override
     protected void updateBgAlpha() {
         mLeftBackground.setAlpha((int) (mSpringLoadedProgress * 255));
@@ -161,8 +203,9 @@
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         super.onLayout(changed, l, t, r, b);
         Rect rect = mBackground.getBounds();
-        mLeftBackground.setBounds(rect.left, rect.top, rect.right / 2 - 20, rect.bottom);
-        mRightBackground.setBounds(rect.right / 2 + 20, rect.top, rect.right, rect.bottom);
+        int middlePointInPixels = rect.centerX();
+        mLeftBackground.setBounds(rect.left, rect.top, middlePointInPixels, rect.bottom);
+        mRightBackground.setBounds(middlePointInPixels, rect.top, rect.right, rect.bottom);
     }
 
     public void setCountX(int countX) {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index eeb5fe0..30f3f5f 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -349,7 +349,7 @@
             setPageSpacing(Math.max(maxInsets, maxPadding));
         }
 
-        updateCellLayoutPadding();
+        updateCellLayoutMeasures();
         updateWorkspaceWidgetsSizes();
         setPageIndicatorInset();
     }
@@ -373,10 +373,12 @@
         mPageIndicator.setLayoutParams(lp);
     }
 
-    private void updateCellLayoutPadding() {
+    private void updateCellLayoutMeasures() {
         Rect padding = mLauncher.getDeviceProfile().cellLayoutPaddingPx;
-        mWorkspaceScreens.forEach(
-                s -> s.setPadding(padding.left, padding.top, padding.right, padding.bottom));
+        mWorkspaceScreens.forEach(cellLayout -> {
+            cellLayout.setPadding(padding.left, padding.top, padding.right, padding.bottom);
+            cellLayout.setSpaceBetweenCellLayoutsPx(getPageSpacing() / 4);
+        });
     }
 
     private void updateWorkspaceWidgetsSizes() {
@@ -690,7 +692,7 @@
                 mLauncher.getStateManager().getState(), newScreen, insertIndex);
 
         updatePageScrollValues();
-        updateCellLayoutPadding();
+        updateCellLayoutMeasures();
         return newScreen;
     }
 
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index e4f34ae..84d3805 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -34,6 +34,7 @@
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.WORKSPACE_PAGE_INDICATOR;
 import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
+import static com.android.launcher3.config.FeatureFlags.FOLDABLE_SINGLE_PAGE;
 import static com.android.launcher3.graphics.Scrim.SCRIM_PROGRESS;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE;
@@ -172,9 +173,13 @@
                 scaleAndTranslation.translationY, translationInterpolator);
         PageTranslationProvider pageTranslationProvider = state.getWorkspacePageTranslationProvider(
                 mLauncher);
-        for (int i = 0; i < childCount; i++) {
-            applyPageTranslation((CellLayout) mWorkspace.getChildAt(i), i, pageTranslationProvider,
-                    propertySetter, config);
+
+        if (!FOLDABLE_SINGLE_PAGE.get()) {
+            for (int i = 0; i < childCount; i++) {
+                applyPageTranslation((CellLayout) mWorkspace.getChildAt(i), i,
+                        pageTranslationProvider,
+                        propertySetter, config);
+            }
         }
 
         Interpolator hotseatTranslationInterpolator = config.getInterpolator(
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 3f3b3ce..b8787fd 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -238,7 +238,7 @@
 
     // Aconfig migration complete for ENABLE_TWOLINE_ALLAPPS.
     public static final BooleanFlag ENABLE_TWOLINE_ALLAPPS = getDebugFlag(270390937,
-            "ENABLE_TWOLINE_ALLAPPS", DISABLED, "Enables two line label inside all apps.");
+            "ENABLE_TWOLINE_ALLAPPS", ENABLED, "Enables two line label inside all apps.");
     public static boolean enableTwolineAllapps() {
         return ENABLE_TWOLINE_ALLAPPS.get() || Flags.enableTwolineAllapps();
     }
@@ -308,6 +308,10 @@
             "ENABLE_DYNAMIC_TASKBAR_THRESHOLDS", ENABLED,
             "Enables taskbar thresholds that scale based on screen size.");
 
+    public static final BooleanFlag ENABLE_HOME_TRANSITION_LISTENER = getDebugFlag(306053414,
+            "ENABLE_HOME_TRANSITION_LISTENER", DISABLED,
+            "Enables launcher to listen to all transitions that include home activity.");
+
     // TODO(Block 21): Clean up flags
     public static final BooleanFlag ENABLE_APP_ICON_FOR_INLINE_SHORTCUTS = getDebugFlag(270395087,
             "ENABLE_APP_ICON_IN_INLINE_SHORTCUTS", DISABLED, "Show app icon for inline shortcut");
@@ -323,15 +327,6 @@
                     + "waiting for SystemUI and then merging the SystemUI progress whenever we "
                     + "start receiving the events");
 
-    // Aconfig migration complete for ENABLE_CURSOR_HOVER_STATES.
-    @VisibleForTesting
-    public static final BooleanFlag ENABLE_CURSOR_HOVER_STATES = getDebugFlag(243191650,
-            "ENABLE_CURSOR_HOVER_STATES", TEAMFOOD,
-            "Enables cursor hover states for certain elements.");
-    public static boolean enableCursorHoverStates() {
-        return ENABLE_CURSOR_HOVER_STATES.get() || Flags.enableCursorHoverStates();
-    }
-
     // TODO(Block 24): Clean up flags
     public static final BooleanFlag ENABLE_NEW_MIGRATION_LOGIC = getDebugFlag(270393455,
             "ENABLE_NEW_MIGRATION_LOGIC", ENABLED,
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index d00d901..cb1dc4f 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -16,7 +16,7 @@
 
 package com.android.launcher3.folder;
 
-import static com.android.launcher3.config.FeatureFlags.enableCursorHoverStates;
+import static com.android.launcher3.Flags.enableCursorHoverStates;
 import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.ICON_OVERLAP_FACTOR;
 import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
 import static com.android.launcher3.folder.PreviewItemManager.INITIAL_ITEM_ANIMATION_DURATION;
diff --git a/src/com/android/launcher3/util/MultiTranslateDelegate.java b/src/com/android/launcher3/util/MultiTranslateDelegate.java
index 0e32ba7..6f6392f 100644
--- a/src/com/android/launcher3/util/MultiTranslateDelegate.java
+++ b/src/com/android/launcher3/util/MultiTranslateDelegate.java
@@ -37,8 +37,11 @@
     public static final int INDEX_TASKBAR_ALIGNMENT_ANIM = 3;
     public static final int INDEX_TASKBAR_REVEAL_ANIM = 4;
 
+    // Affect all items inside of a MultipageCellLayout
+    public static final int INDEX_CELLAYOUT_MULTIPAGE_SPACING = 3;
+
     // Specific for widgets
-    public static final int INDEX_WIDGET_CENTERING = 3;
+    public static final int INDEX_WIDGET_CENTERING = 4;
 
     // Specific for hotseat items when adjusting for bubbles
     public static final int INDEX_BUBBLE_ADJUSTMENT_ANIM = 3;
diff --git a/tests/Android.bp b/tests/Android.bp
index 29a45aa..4988dbd 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -45,7 +45,6 @@
       "src/com/android/launcher3/allapps/TaplOpenCloseAllApps.java",
       "src/com/android/launcher3/allapps/TaplTestsAllAppsIconsWorking.java",
       "src/com/android/launcher3/appiconmenu/TaplAppIconMenuTest.java",
-      "src/com/android/launcher3/appiconmenu/TaplOverviewIconTest.java",
       "src/com/android/launcher3/dragging/TaplDragTest.java",
       "src/com/android/launcher3/dragging/TaplUninstallRemove.java",
       "src/com/android/launcher3/ui/AbstractLauncherUiTest.java",
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt
index ec32680..82e46f4 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt
@@ -61,7 +61,7 @@
 	allAppsIconSizePx: 147.0px (56.0dp)
 	allAppsIconTextSizePx: 38.0px (14.476191dp)
 	allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
-	allAppsCellHeightPx: 315.0px (120.0dp)
+	allAppsCellHeightPx: 366.0px (139.42857dp)
 	allAppsCellWidthPx: 189.0px (72.0dp)
 	allAppsBorderSpacePxX: 42.0px (16.0dp)
 	allAppsBorderSpacePxY: 42.0px (16.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt
index d69be3f..674d68c 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt
@@ -61,7 +61,7 @@
 	allAppsIconSizePx: 147.0px (56.0dp)
 	allAppsIconTextSizePx: 38.0px (14.476191dp)
 	allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
-	allAppsCellHeightPx: 315.0px (120.0dp)
+	allAppsCellHeightPx: 366.0px (139.42857dp)
 	allAppsCellWidthPx: 189.0px (72.0dp)
 	allAppsBorderSpacePxX: 42.0px (16.0dp)
 	allAppsBorderSpacePxY: 42.0px (16.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt
index 7e92620..1c30c15 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt
@@ -61,7 +61,7 @@
 	allAppsIconSizePx: 147.0px (56.0dp)
 	allAppsIconTextSizePx: 38.0px (14.476191dp)
 	allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
-	allAppsCellHeightPx: 321.0px (122.28571dp)
+	allAppsCellHeightPx: 372.0px (141.71428dp)
 	allAppsCellWidthPx: 189.0px (72.0dp)
 	allAppsBorderSpacePxX: 42.0px (16.0dp)
 	allAppsBorderSpacePxY: 42.0px (16.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt
index a9bee2b..52142a0 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt
@@ -61,7 +61,7 @@
 	allAppsIconSizePx: 147.0px (56.0dp)
 	allAppsIconTextSizePx: 38.0px (14.476191dp)
 	allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
-	allAppsCellHeightPx: 321.0px (122.28571dp)
+	allAppsCellHeightPx: 372.0px (141.71428dp)
 	allAppsCellWidthPx: 189.0px (72.0dp)
 	allAppsBorderSpacePxX: 42.0px (16.0dp)
 	allAppsBorderSpacePxY: 42.0px (16.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt
index 42b022b..8e0818d 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt
@@ -61,7 +61,7 @@
 	allAppsIconSizePx: 120.0px (60.0dp)
 	allAppsIconTextSizePx: 28.0px (14.0dp)
 	allAppsIconDrawablePaddingPx: 9.0px (4.5dp)
-	allAppsCellHeightPx: 284.0px (142.0dp)
+	allAppsCellHeightPx: 322.0px (161.0dp)
 	allAppsCellWidthPx: 252.0px (126.0dp)
 	allAppsBorderSpacePxX: 32.0px (16.0dp)
 	allAppsBorderSpacePxY: 32.0px (16.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt
index 53f8580..ab13e50 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt
@@ -61,7 +61,7 @@
 	allAppsIconSizePx: 120.0px (60.0dp)
 	allAppsIconTextSizePx: 28.0px (14.0dp)
 	allAppsIconDrawablePaddingPx: 9.0px (4.5dp)
-	allAppsCellHeightPx: 284.0px (142.0dp)
+	allAppsCellHeightPx: 322.0px (161.0dp)
 	allAppsCellWidthPx: 252.0px (126.0dp)
 	allAppsBorderSpacePxX: 32.0px (16.0dp)
 	allAppsBorderSpacePxY: 32.0px (16.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt
index 87189fa..e2b1f69 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt
@@ -54,14 +54,14 @@
 	bottomSheetCloseDuration: 500
 	bottomSheetWorkspaceScale: 0.97
 	bottomSheetDepth: 0.0
-	allAppsShiftRange: 1810.0px (905.0dp)
-	allAppsTopPadding: 750.0px (375.0dp)
+	allAppsShiftRange: 2019.0px (1009.5dp)
+	allAppsTopPadding: 541.0px (270.5dp)
 	allAppsOpenDuration: 500
 	allAppsCloseDuration: 500
 	allAppsIconSizePx: 120.0px (60.0dp)
 	allAppsIconTextSizePx: 28.0px (14.0dp)
 	allAppsIconDrawablePaddingPx: 9.0px (4.5dp)
-	allAppsCellHeightPx: 316.0px (158.0dp)
+	allAppsCellHeightPx: 354.0px (177.0dp)
 	allAppsCellWidthPx: 192.0px (96.0dp)
 	allAppsBorderSpacePxX: 16.0px (8.0dp)
 	allAppsBorderSpacePxY: 32.0px (16.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt
index 0ade560..e838c06 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt
@@ -54,14 +54,14 @@
 	bottomSheetCloseDuration: 500
 	bottomSheetWorkspaceScale: 0.97
 	bottomSheetDepth: 0.0
-	allAppsShiftRange: 1810.0px (905.0dp)
-	allAppsTopPadding: 750.0px (375.0dp)
+	allAppsShiftRange: 2019.0px (1009.5dp)
+	allAppsTopPadding: 541.0px (270.5dp)
 	allAppsOpenDuration: 500
 	allAppsCloseDuration: 500
 	allAppsIconSizePx: 120.0px (60.0dp)
 	allAppsIconTextSizePx: 28.0px (14.0dp)
 	allAppsIconDrawablePaddingPx: 9.0px (4.5dp)
-	allAppsCellHeightPx: 316.0px (158.0dp)
+	allAppsCellHeightPx: 354.0px (177.0dp)
 	allAppsCellWidthPx: 192.0px (96.0dp)
 	allAppsBorderSpacePxX: 16.0px (8.0dp)
 	allAppsBorderSpacePxY: 32.0px (16.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt
index d24457d..903235a 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt
@@ -61,7 +61,7 @@
 	allAppsIconSizePx: 141.0px (53.714287dp)
 	allAppsIconTextSizePx: 34.0px (12.952381dp)
 	allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
-	allAppsCellHeightPx: 315.0px (120.0dp)
+	allAppsCellHeightPx: 361.0px (137.5238dp)
 	allAppsCellWidthPx: 183.0px (69.71429dp)
 	allAppsBorderSpacePxX: 42.0px (16.0dp)
 	allAppsBorderSpacePxY: 42.0px (16.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt
index 38dc2c9..d3c3458 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt
@@ -61,7 +61,7 @@
 	allAppsIconSizePx: 141.0px (53.714287dp)
 	allAppsIconTextSizePx: 34.0px (12.952381dp)
 	allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
-	allAppsCellHeightPx: 315.0px (120.0dp)
+	allAppsCellHeightPx: 361.0px (137.5238dp)
 	allAppsCellWidthPx: 183.0px (69.71429dp)
 	allAppsBorderSpacePxX: 42.0px (16.0dp)
 	allAppsBorderSpacePxY: 42.0px (16.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt
index 5d23147..64b3721 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt
@@ -54,14 +54,14 @@
 	bottomSheetCloseDuration: 500
 	bottomSheetWorkspaceScale: 0.97
 	bottomSheetDepth: 1.0
-	allAppsShiftRange: 1826.0px (695.619dp)
-	allAppsTopPadding: 382.0px (145.5238dp)
+	allAppsShiftRange: 2075.0px (790.4762dp)
+	allAppsTopPadding: 133.0px (50.666668dp)
 	allAppsOpenDuration: 500
 	allAppsCloseDuration: 500
 	allAppsIconSizePx: 141.0px (53.714287dp)
 	allAppsIconTextSizePx: 34.0px (12.952381dp)
 	allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
-	allAppsCellHeightPx: 315.0px (120.0dp)
+	allAppsCellHeightPx: 361.0px (137.5238dp)
 	allAppsCellWidthPx: 183.0px (69.71429dp)
 	allAppsBorderSpacePxX: 42.0px (16.0dp)
 	allAppsBorderSpacePxY: 42.0px (16.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt
index 5b53509..584a3b5 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt
@@ -54,14 +54,14 @@
 	bottomSheetCloseDuration: 500
 	bottomSheetWorkspaceScale: 0.97
 	bottomSheetDepth: 1.0
-	allAppsShiftRange: 1826.0px (695.619dp)
-	allAppsTopPadding: 382.0px (145.5238dp)
+	allAppsShiftRange: 2075.0px (790.4762dp)
+	allAppsTopPadding: 133.0px (50.666668dp)
 	allAppsOpenDuration: 500
 	allAppsCloseDuration: 500
 	allAppsIconSizePx: 141.0px (53.714287dp)
 	allAppsIconTextSizePx: 34.0px (12.952381dp)
 	allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
-	allAppsCellHeightPx: 315.0px (120.0dp)
+	allAppsCellHeightPx: 361.0px (137.5238dp)
 	allAppsCellWidthPx: 183.0px (69.71429dp)
 	allAppsBorderSpacePxX: 42.0px (16.0dp)
 	allAppsBorderSpacePxY: 42.0px (16.0dp)
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 56a74a9..669aaab 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -89,7 +89,7 @@
 import java.util.function.Supplier;
 
 /**
- * Base class for all instrumentation tests providing various utility methods.
+ * Base class for all instrumentation tests providing various utility methods. RUN 4
  */
 public abstract class AbstractLauncherUiTest {
 
@@ -252,6 +252,12 @@
     public void setUp() throws Exception {
         mLauncher.onTestStart();
 
+        if (TestStabilityRule.isPresubmit()) {
+            aggressivelyUnlockSysUi();
+        } else {
+            verifyKeyguardInvisible();
+        }
+
         final String launcherPackageName = mDevice.getLauncherPackageName();
         try {
             final Context context = InstrumentationRegistry.getContext();
@@ -285,7 +291,27 @@
         verifyKeyguardInvisible();
     }
 
-    /** Fail if lock screen is present */
+    private boolean hasSystemUiObject(String resId) {
+        return mDevice.hasObject(By.res(SYSTEMUI_PACKAGE, resId));
+    }
+
+    // Seeing if this will decrease: b/303755862
+    void aggressivelyUnlockSysUi() {
+        for (int i = 0; i < 10 && hasSystemUiObject("keyguard_status_view"); ++i) {
+            Log.d(TAG, "Before attempting to unlock the phone");
+            try {
+                mDevice.executeShellCommand("input keyevent 82");
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+            mDevice.waitForIdle();
+        }
+        Assert.assertTrue("Keyguard still visible",
+                TestHelpers.wait(
+                        Until.gone(By.res(SYSTEMUI_PACKAGE, "keyguard_status_view")), 60000));
+        Log.d(TAG, "Keyguard is not visible");
+    }
+
     public static void verifyKeyguardInvisible() {
         final boolean keyguardAlreadyVisible = sSeenKeyguard;
 
diff --git a/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java b/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java
index b019414..0d15300 100644
--- a/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java
+++ b/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java
@@ -22,6 +22,7 @@
 import static com.android.launcher3.BubbleTextView.DISPLAY_PREDICTION_ROW;
 import static com.android.launcher3.BubbleTextView.DISPLAY_SEARCH_RESULT;
 import static com.android.launcher3.BubbleTextView.DISPLAY_SEARCH_RESULT_SMALL;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TWOLINE_ALLAPPS;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -32,8 +33,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Typeface;
-import android.platform.test.flag.junit.SetFlagsRule;
 import android.os.UserHandle;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.view.ViewGroup;
 
 import com.android.launcher3.BubbleTextView;
@@ -45,6 +46,7 @@
 import com.android.launcher3.util.ActivityContextWrapper;
 import com.android.launcher3.util.FlagOp;
 import com.android.launcher3.util.IntArray;
+import com.android.launcher3.util.TestUtil;
 import com.android.launcher3.views.BaseDragLayer;
 
 import org.junit.Before;
@@ -128,149 +130,189 @@
     @Test
     public void testEmptyString_flagOn() {
         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS);
-        mItemInfoWithIcon.title = EMPTY_STRING;
-        mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT);
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
+            mItemInfoWithIcon.title = EMPTY_STRING;
+            mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT);
 
-        mBubbleTextView.onPreDraw();
+            mBubbleTextView.onPreDraw();
 
-        assertNotEquals(TWO_LINE, mBubbleTextView.getMaxLines());
+            assertNotEquals(TWO_LINE, mBubbleTextView.getMaxLines());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
     public void testEmptyString_flagOff() {
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS);
-        mItemInfoWithIcon.title = EMPTY_STRING;
-        mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT);
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) {
+            mItemInfoWithIcon.title = EMPTY_STRING;
+            mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT);
 
-        mBubbleTextView.onPreDraw();
+            mBubbleTextView.onPreDraw();
 
-        assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+            assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
     public void testStringWithSpaceLongerThanCharLimit_flagOn() {
         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS);
-        // test string: "Battery Stats"
-        mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT);
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
+            // test string: "Battery Stats"
+            mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT);
 
-        mBubbleTextView.onPreDraw();
+            mBubbleTextView.onPreDraw();
 
-        assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
+            assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
     public void testStringWithSpaceLongerThanCharLimit_flagOff() {
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS);
-        // test string: "Battery Stats"
-        mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT);
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) {
+            // test string: "Battery Stats"
+            mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT);
 
-        mBubbleTextView.onPreDraw();
+            mBubbleTextView.onPreDraw();
 
-        assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+            assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
     public void testLongStringNoSpaceLongerThanCharLimit_flagOn() {
         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS);
-        // test string: "flutterappflorafy"
-        mItemInfoWithIcon.title = TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT);
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
+            // test string: "flutterappflorafy"
+            mItemInfoWithIcon.title = TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT);
 
-        mBubbleTextView.onPreDraw();
+            mBubbleTextView.onPreDraw();
 
-        assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+            assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
     public void testLongStringNoSpaceLongerThanCharLimit_flagOff() {
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS);
-        // test string: "flutterappflorafy"
-        mItemInfoWithIcon.title = TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT);
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) {
+            // test string: "flutterappflorafy"
+            mItemInfoWithIcon.title = TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT);
 
-        mBubbleTextView.onPreDraw();
+            mBubbleTextView.onPreDraw();
 
-        assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+            assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
     public void testLongStringWithSpaceLongerThanCharLimit_flagOn() {
         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS);
-        // test string: "System UWB Field Test"
-        mItemInfoWithIcon.title = TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT);
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
+            // test string: "System UWB Field Test"
+            mItemInfoWithIcon.title = TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT);
 
-        mBubbleTextView.onPreDraw();
+            mBubbleTextView.onPreDraw();
 
-        assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
+            assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
     public void testLongStringWithSpaceLongerThanCharLimit_flagOff() {
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS);
-        // test string: "System UWB Field Test"
-        mItemInfoWithIcon.title = TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT);
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) {
+            // test string: "System UWB Field Test"
+            mItemInfoWithIcon.title = TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT);
 
-        mBubbleTextView.onPreDraw();
+            mBubbleTextView.onPreDraw();
 
-        assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+            assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
     public void testLongStringSymbolLongerThanCharLimit_flagOn() {
         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS);
-        // test string: "LEGO®Builder"
-        mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT);
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
+            // test string: "LEGO®Builder"
+            mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT);
 
-        mBubbleTextView.onPreDraw();
+            mBubbleTextView.onPreDraw();
 
-        assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
+            assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
     public void testLongStringSymbolLongerThanCharLimit_flagOff() {
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS);
-        // test string: "LEGO®Builder"
-        mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT);
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) {
+            // test string: "LEGO®Builder"
+            mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT);
 
-        mBubbleTextView.onPreDraw();
+            mBubbleTextView.onPreDraw();
 
-        assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+            assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
@@ -332,45 +374,57 @@
     @Test
     public void testEnsurePredictionRowIsTwoLine() {
         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS);
-        // test string: "Battery Stats"
-        mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.setDisplay(DISPLAY_PREDICTION_ROW);
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT);
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
+            // test string: "Battery Stats"
+            mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.setDisplay(DISPLAY_PREDICTION_ROW);
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT);
 
-        mBubbleTextView.onPreDraw();
+            mBubbleTextView.onPreDraw();
 
-        assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
+            assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
     public void modifyTitleToSupportMultiLine_whenLimitedHeight_shouldBeOneLine() {
         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS);
-        // test string: "LEGO®Builder"
-        mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT);
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
+            // test string: "LEGO®Builder"
+            mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT);
 
-        mBubbleTextView.onPreDraw();
+            mBubbleTextView.onPreDraw();
 
-        assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+            assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
     public void modifyTitleToSupportMultiLine_whenUnlimitedHeight_shouldBeTwoLine() {
         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS);
-        // test string: "LEGO®Builder"
-        mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT);
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
+            // test string: "LEGO®Builder"
+            mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT);
 
-        mBubbleTextView.onPreDraw();
+            mBubbleTextView.onPreDraw();
 
-        assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
+            assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
diff --git a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
index b8ca43f..d94e4a5 100644
--- a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
+++ b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
@@ -1,7 +1,5 @@
 package com.android.launcher3.ui;
 
-import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_PRESUBMIT;
-
 import android.util.Log;
 import android.view.Surface;
 
@@ -38,7 +36,7 @@
                 // If running in presubmit, don't run in both orientations.
                 // It's important to keep presubmits fast even if we will occasionally miss
                 // regressions in presubmit.
-                || TestStabilityRule.getRunFlavor() == PLATFORM_PRESUBMIT) {
+                || TestStabilityRule.isPresubmit()) {
             return base;
         }
 
diff --git a/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java b/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java
index 38de071..b51045f 100644
--- a/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java
+++ b/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java
@@ -146,4 +146,8 @@
 
         return sRunFlavor;
     }
+
+    public static boolean isPresubmit() {
+        return getRunFlavor() == PLATFORM_PRESUBMIT;
+    }
 }