Merge "Remove FLAG_SPLIT_TOUCH from launcher code" into main
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.kt b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.kt
index 810fa6f..1ac2d7c 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.kt
+++ b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.kt
@@ -40,7 +40,8 @@
 import com.android.quickstep.fallback.RecentsState
 import com.android.wm.shell.desktopmode.DisplayDeskState
 import com.android.wm.shell.desktopmode.IDesktopTaskListener.Stub
-import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.enableMultipleDesktops
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.useRoundedCorners
 import java.io.PrintWriter
 import java.lang.ref.WeakReference
 import javax.inject.Inject
@@ -89,8 +90,7 @@
     private val taskbarDesktopModeListeners: MutableSet<TaskbarDesktopModeListener> = HashSet()
 
     // This simply indicates that user is currently in desktop mode or not.
-    var isInDesktopMode = false
-        private set
+    @Deprecated("Does not work with multi-desks") private var isInDesktopModeDeprecated = false
 
     // to track if any pending notification to be done.
     var isNotifyingDesktopVisibilityPending = false
@@ -104,12 +104,16 @@
      * Number of visible desktop windows in desktop mode. This can be > 0 when user goes to overview
      * from desktop window mode.
      */
-    var visibleDesktopTasksCount: Int = 0
+    @Deprecated("Does not work with multi-desks")
+    var visibleDesktopTasksCountDeprecated: Int = 0
         /**
          * Sets the number of desktop windows that are visible and updates launcher visibility based
          * on it.
          */
         set(visibleTasksCount) {
+            if (enableMultipleDesktops(context)) {
+                return
+            }
             if (DEBUG) {
                 Log.d(
                     TAG,
@@ -121,11 +125,11 @@
             }
 
             if (visibleTasksCount != field) {
-                if (visibleDesktopTasksCount == 0 && visibleTasksCount == 1) {
-                    isInDesktopMode = true
+                if (visibleDesktopTasksCountDeprecated == 0 && visibleTasksCount == 1) {
+                    isInDesktopModeDeprecated = true
                 }
-                if (visibleDesktopTasksCount == 1 && visibleTasksCount == 0) {
-                    isInDesktopMode = false
+                if (visibleDesktopTasksCountDeprecated == 1 && visibleTasksCount == 0) {
+                    isInDesktopModeDeprecated = false
                 }
                 val wasVisible = field > 0
                 val isVisible = visibleTasksCount > 0
@@ -171,7 +175,7 @@
     private var desktopTaskListener: DesktopTaskListenerImpl?
 
     init {
-        desktopTaskListener = DesktopTaskListenerImpl(this, context.displayId)
+        desktopTaskListener = DesktopTaskListenerImpl(this, context, context.displayId)
         systemUiProxy.setDesktopTaskListener(desktopTaskListener)
 
         lifecycleTracker.addCloseable {
@@ -185,7 +189,7 @@
      * [INACTIVE_DESK_ID] if no desk is currently active or the multiple desks feature is disabled.
      */
     fun getActiveDeskId(displayId: Int): Int {
-        if (!DesktopModeStatus.enableMultipleDesktops(context)) {
+        if (!enableMultipleDesktops(context)) {
             // When the multiple desks feature is disabled, callers should not rely on the concept
             // of a desk ID.
             return INACTIVE_DESK_ID
@@ -196,8 +200,8 @@
 
     /** Returns whether a desk is currently active on the display with the given [displayId]. */
     fun isInDesktopMode(displayId: Int): Boolean {
-        if (!DesktopModeStatus.enableMultipleDesktops(context)) {
-            return isInDesktopMode
+        if (!enableMultipleDesktops(context)) {
+            return isInDesktopModeDeprecated
         }
 
         val activeDeskId = getDisplayDeskConfig(displayId)?.activeDeskId ?: INACTIVE_DESK_ID
@@ -213,7 +217,7 @@
      * Overview is not active.
      */
     fun isInDesktopModeAndNotInOverview(displayId: Int): Boolean {
-        if (!DesktopModeStatus.enableMultipleDesktops(context)) {
+        if (!enableMultipleDesktops(context)) {
             return areDesktopTasksVisibleAndNotInOverview()
         }
 
@@ -225,7 +229,7 @@
 
     /** Whether desktop tasks are visible in desktop mode. */
     private fun areDesktopTasksVisibleAndNotInOverview(): Boolean {
-        val desktopTasksVisible: Boolean = visibleDesktopTasksCount > 0
+        val desktopTasksVisible: Boolean = visibleDesktopTasksCountDeprecated > 0
         if (DEBUG) {
             Log.d(
                 TAG,
@@ -309,7 +313,7 @@
             inOverviewState = overviewStateEnabled
             val areDesktopTasksVisibleNow = areDesktopTasksVisibleAndNotInOverview()
 
-            if (!DesktopModeStatus.enableMultipleDesktops(context)) {
+            if (!enableMultipleDesktops(context)) {
                 if (wereDesktopTasksVisibleBefore != areDesktopTasksVisibleNow) {
                     notifyIsInDesktopModeChanged(DEFAULT_DISPLAY, areDesktopTasksVisibleNow)
                 }
@@ -504,7 +508,7 @@
         displayDeskStates: Array<DisplayDeskState>,
         canCreateDesks: Boolean,
     ) {
-        if (!DesktopModeStatus.enableMultipleDesktops(context)) {
+        if (!enableMultipleDesktops(context)) {
             return
         }
 
@@ -527,7 +531,7 @@
             ?: null.also { Slog.e(TAG, "Expected non-null desk config for display: $displayId") }
 
     private fun onCanCreateDesksChanged(canCreateDesks: Boolean) {
-        if (!DesktopModeStatus.enableMultipleDesktops(context)) {
+        if (!enableMultipleDesktops(context)) {
             return
         }
 
@@ -535,7 +539,7 @@
     }
 
     private fun onDeskAdded(displayId: Int, deskId: Int) {
-        if (!DesktopModeStatus.enableMultipleDesktops(context)) {
+        if (!enableMultipleDesktops(context)) {
             return
         }
 
@@ -549,7 +553,7 @@
     }
 
     private fun onDeskRemoved(displayId: Int, deskId: Int) {
-        if (!DesktopModeStatus.enableMultipleDesktops(context)) {
+        if (!enableMultipleDesktops(context)) {
             return
         }
 
@@ -566,7 +570,7 @@
     }
 
     private fun onActiveDeskChanged(displayId: Int, newActiveDesk: Int, oldActiveDesk: Int) {
-        if (!DesktopModeStatus.enableMultipleDesktops(context)) {
+        if (!enableMultipleDesktops(context)) {
             return
         }
 
@@ -626,7 +630,7 @@
         pw.println(prefix + "DesktopVisibilityController:")
 
         pw.println("$prefix\tdesktopVisibilityListeners=$desktopVisibilityListeners")
-        pw.println("$prefix\tvisibleDesktopTasksCount=$visibleDesktopTasksCount")
+        pw.println("$prefix\tvisibleDesktopTasksCount=$visibleDesktopTasksCountDeprecated")
         pw.println("$prefix\tinOverviewState=$inOverviewState")
         pw.println("$prefix\tbackgroundStateEnabled=$backgroundStateEnabled")
         pw.println("$prefix\tgestureInProgress=$gestureInProgress")
@@ -640,6 +644,7 @@
      */
     private class DesktopTaskListenerImpl(
         controller: DesktopVisibilityController,
+        @ApplicationContext private val context: Context,
         private val displayId: Int,
     ) : Stub() {
         private val controller = WeakReference(controller)
@@ -660,7 +665,7 @@
                     if (DEBUG) {
                         Log.d(TAG, "desktop visible tasks count changed=$visibleTasksCount")
                     }
-                    visibleDesktopTasksCount = visibleTasksCount
+                    visibleDesktopTasksCountDeprecated = visibleTasksCount
                 }
             }
         }
@@ -670,7 +675,7 @@
         }
 
         override fun onTaskbarCornerRoundingUpdate(doesAnyTaskRequireTaskbarRounding: Boolean) {
-            if (!DesktopModeStatus.useRoundedCorners()) return
+            if (!useRoundedCorners()) return
             MAIN_EXECUTOR.execute {
                 controller.get()?.apply {
                     Log.d(
@@ -683,7 +688,10 @@
             }
         }
 
+        // TODO: b/402496827 - The multi-desks backend needs to be updated to call this API only
+        //  once, not between desk switches.
         override fun onEnterDesktopModeTransitionStarted(transitionDuration: Int) {
+            val controller = controller.get() ?: return
             MAIN_EXECUTOR.execute {
                 Log.d(
                     TAG,
@@ -691,15 +699,19 @@
                         "duration= " +
                         transitionDuration),
                 )
-                val controller = controller.get()
-                if (controller != null && !controller.isInDesktopMode) {
-                    controller.isInDesktopMode = true
+                if (enableMultipleDesktops(context)) {
+                    controller.notifyTaskbarDesktopModeListenersForEntry(transitionDuration)
+                } else if (!controller.isInDesktopModeDeprecated) {
+                    controller.isInDesktopModeDeprecated = true
                     controller.notifyTaskbarDesktopModeListenersForEntry(transitionDuration)
                 }
             }
         }
 
+        // TODO: b/402496827 - The multi-desks backend needs to be updated to call this API only
+        //  once, not between desk switches.
         override fun onExitDesktopModeTransitionStarted(transitionDuration: Int) {
+            val controller = controller.get() ?: return
             MAIN_EXECUTOR.execute {
                 Log.d(
                     TAG,
@@ -707,9 +719,10 @@
                         "duration= " +
                         transitionDuration),
                 )
-                val controller = controller.get()
-                if (controller != null && controller.isInDesktopMode) {
-                    controller.isInDesktopMode = false
+                if (enableMultipleDesktops(context)) {
+                    controller.notifyTaskbarDesktopModeListenersForExit(transitionDuration)
+                } else if (controller.isInDesktopModeDeprecated) {
+                    controller.isInDesktopModeDeprecated = false
                     controller.notifyTaskbarDesktopModeListenersForExit(transitionDuration)
                 }
             }
diff --git a/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java b/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java
index aa3feb7..b82e6ed 100644
--- a/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java
@@ -23,7 +23,7 @@
 
 import com.android.launcher3.popup.SystemShortcut;
 import com.android.launcher3.util.BaseContext;
-import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.NavigationMode;
 import com.android.launcher3.util.Themes;
 import com.android.quickstep.SystemUiProxy;
 
@@ -33,21 +33,49 @@
         implements SystemShortcut.BubbleActivityStarter {
 
     protected final LayoutInflater mLayoutInflater;
-    private final boolean mIsPrimaryDisplay;
 
     public BaseTaskbarContext(Context windowContext, boolean isPrimaryDisplay) {
         super(windowContext, Themes.getActivityThemeRes(windowContext));
         mLayoutInflater = LayoutInflater.from(this).cloneInContext(this);
-        mIsPrimaryDisplay = isPrimaryDisplay;
     }
 
-    public boolean isTransientTaskbar() {
-        return DisplayController.isTransientTaskbar(this) && mIsPrimaryDisplay;
-    }
+    /**
+     * Returns whether taskbar is transient or persistent. External displays will be persistent.
+     *
+     * @return {@code true} if transient, {@code false} if persistent.
+     */
+    public abstract boolean isTransientTaskbar();
 
-    public boolean isPrimaryDisplay() {
-        return mIsPrimaryDisplay;
-    }
+    /**
+     * Returns whether the taskbar is pinned in gesture navigation mode.
+     */
+    public abstract boolean isPinnedTaskbar();
+
+    /**
+     * Returns the current navigation mode. External displays will be in THREE_BUTTONS mode.
+     */
+    public abstract NavigationMode getNavigationMode();
+
+    /**
+     * Returns whether the taskbar is in desktop mode.
+     */
+    public abstract boolean isInDesktopMode();
+
+    /**
+     * Returns whether the taskbar is forced to be pinned when home is visible.
+     */
+    public abstract  boolean showLockedTaskbarOnHome();
+
+    /**
+     * Returns whether desktop taskbar (pinned taskbar that shows desktop tasks) is to be used on
+     * the display because the display is a freeform display.
+     */
+    public abstract  boolean showDesktopTaskbarForFreeformDisplay();
+
+    /**
+     * Returns whether the taskbar is displayed on primary or external display.
+     */
+    public abstract boolean isPrimaryDisplay();
 
     @Override
     public final LayoutInflater getLayoutInflater() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 6e210e3..913035a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -223,7 +223,8 @@
         if (!Flags.predictiveBackToHomePolish()) {
             shouldOverrideToFastAnimation |= mLauncher.getPredictiveBackToHomeInProgress();
         }
-        boolean isPinnedTaskbar = DisplayController.isPinnedTaskbar(mLauncher);
+        boolean isPinnedTaskbar =
+                mControllers.taskbarActivityContext.isPinnedTaskbar();
         if (isVisible || isPinnedTaskbar) {
             return getTaskbarToHomeDuration(shouldOverrideToFastAnimation, isPinnedTaskbar);
         } else {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 6ea0a2b..66887d0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -417,9 +417,41 @@
         dispatchDeviceProfileChanged();
     }
 
-    /** Returns whether current taskbar is transient. */
+    @Override
     public boolean isTransientTaskbar() {
-        return super.isTransientTaskbar() && !isPhoneMode();
+        return DisplayController.isTransientTaskbar(this) && mIsPrimaryDisplay && !isPhoneMode();
+    }
+
+    @Override
+    public boolean isPinnedTaskbar() {
+        return DisplayController.isPinnedTaskbar(this);
+    }
+
+    @Override
+    public NavigationMode getNavigationMode() {
+        return isPrimaryDisplay() ? DisplayController.getNavigationMode(this)
+                : NavigationMode.THREE_BUTTONS;
+    }
+
+    @Override
+    public boolean isInDesktopMode() {
+        return mControllers != null
+                && mControllers.taskbarDesktopModeController.isInDesktopMode(getDisplayId());
+    }
+
+    @Override
+    public boolean showLockedTaskbarOnHome() {
+        return DisplayController.showLockedTaskbarOnHome(this);
+    }
+
+    @Override
+    public boolean showDesktopTaskbarForFreeformDisplay() {
+        return DisplayController.showDesktopTaskbarForFreeformDisplay(this);
+    }
+
+    @Override
+    public boolean isPrimaryDisplay() {
+        return mIsPrimaryDisplay;
     }
 
     /**
@@ -455,9 +487,7 @@
                     .setIsTransientTaskbar(true)
                     .build();
         }
-        mNavMode = (DesktopExperienceFlags.ENABLE_TASKBAR_CONNECTED_DISPLAYS.isTrue()
-                && !mIsPrimaryDisplay) ? NavigationMode.THREE_BUTTONS
-                : DisplayController.getNavigationMode(this);
+        mNavMode = getNavigationMode();
     }
 
     /** Called when the visibility of the bubble bar changed. */
@@ -1425,11 +1455,6 @@
         mControllers.uiController.startSplitSelection(splitSelectSource);
     }
 
-    boolean isInDesktopMode() {
-        return mControllers != null
-                && mControllers.taskbarDesktopModeController.isInDesktopMode(getDisplayId());
-    }
-
     protected void onTaskbarIconClicked(View view) {
         TaskbarUIController taskbarUIController = mControllers.uiController;
         RecentsView recents = taskbarUIController.getRecentsView();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDesktopModeController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarDesktopModeController.kt
index ca8e4ca..e96e67d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDesktopModeController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDesktopModeController.kt
@@ -20,7 +20,6 @@
 import com.android.launcher3.statehandlers.DesktopVisibilityController
 import com.android.launcher3.statehandlers.DesktopVisibilityController.TaskbarDesktopModeListener
 import com.android.launcher3.taskbar.TaskbarBackgroundRenderer.Companion.MAX_ROUNDNESS
-import com.android.launcher3.util.DisplayController
 
 /** Handles Taskbar in Desktop Windowing mode. */
 class TaskbarDesktopModeController(
@@ -30,9 +29,6 @@
     private lateinit var taskbarControllers: TaskbarControllers
     private lateinit var taskbarSharedState: TaskbarSharedState
 
-    val isInDesktopMode: Boolean
-        get() = desktopVisibilityController.isInDesktopMode
-
     fun init(controllers: TaskbarControllers, sharedState: TaskbarSharedState) {
         taskbarControllers = controllers
         taskbarSharedState = sharedState
@@ -52,9 +48,10 @@
     }
 
     fun shouldShowDesktopTasksInTaskbar(): Boolean {
+        val activityContext = taskbarControllers.taskbarActivityContext
         return isInDesktopMode(context.displayId) ||
-            DisplayController.showDesktopTaskbarForFreeformDisplay(context) ||
-            (DisplayController.showLockedTaskbarOnHome(context) &&
+            activityContext.showDesktopTaskbarForFreeformDisplay() ||
+            (activityContext.showLockedTaskbarOnHome() &&
                 taskbarControllers.taskbarStashController.isOnHome)
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
index 7a23006..038e374 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
@@ -44,7 +44,6 @@
 import com.android.launcher3.config.FeatureFlags.enableTaskbarPinning
 import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_EDU_OPEN
 import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
-import com.android.launcher3.util.DisplayController
 import com.android.launcher3.util.OnboardingPrefs.TASKBAR_EDU_TOOLTIP_STEP
 import com.android.launcher3.util.OnboardingPrefs.TASKBAR_SEARCH_EDU_SEEN
 import com.android.launcher3.util.ResourceBasedOverride
@@ -319,7 +318,7 @@
     fun maybeShowSearchEdu() {
         if (
             !enableTaskbarPinning() ||
-                !DisplayController.isPinnedTaskbar(activityContext) ||
+                !activityContext.isPinnedTaskbar ||
                 !isTooltipEnabled ||
                 !shouldShowSearchEdu ||
                 userHasSeenSearchEdu ||
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 3af2ab6..f342fa5 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -51,7 +51,6 @@
 import com.android.launcher3.config.FeatureFlags.enableTaskbarNoRecreate
 import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
 import com.android.launcher3.testing.shared.ResourceUtils
-import com.android.launcher3.util.DisplayController
 import com.android.launcher3.util.Executors
 import java.io.PrintWriter
 import kotlin.jvm.optionals.getOrNull
@@ -150,7 +149,7 @@
         if (
             taskbarStashController.isInApp ||
                 controllers.uiController.isInOverviewUi ||
-                DisplayController.showLockedTaskbarOnHome(context)
+                context.showLockedTaskbarOnHome()
         ) {
             // only add the taskbar touch region if not on home
             val bottom = windowLayoutParams.height
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index b510e7e..98415d1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -40,7 +40,6 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
-import android.content.Context;
 import android.os.SystemClock;
 import android.util.Log;
 import android.view.animation.Interpolator;
@@ -61,7 +60,6 @@
 import com.android.launcher3.statemanager.StateManager;
 import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController.BubbleLauncherState;
 import com.android.launcher3.uioverrides.QuickstepLauncher;
-import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
 import com.android.quickstep.RecentsAnimationCallbacks;
 import com.android.quickstep.RecentsAnimationController;
@@ -225,11 +223,9 @@
                     updateStateForFlag(FLAG_LAUNCHER_IN_STATE_TRANSITION, true);
                     if (!mShouldDelayLauncherStateAnim) {
                         if (toState == LauncherState.NORMAL) {
+                            TaskbarActivityContext activity = mControllers.taskbarActivityContext;
                             boolean isPinnedTaskbarAndNotInDesktopMode =
-                                    DisplayController.isPinnedTaskbar(
-                                            mControllers.taskbarActivityContext)
-                                            && !DisplayController.isInDesktopMode(
-                                            mControllers.taskbarActivityContext);
+                                    !activity.isInDesktopMode() && activity.isPinnedTaskbar();
                             applyState(QuickstepTransitionManager.getTaskbarToHomeDuration(
                                     isPinnedTaskbarAndNotInDesktopMode));
                         } else {
@@ -475,8 +471,8 @@
         final boolean isIconAlignedWithHotseat = isIconAlignedWithHotseat();
         final float toAlignment = isIconAlignedWithHotseat ? 1 : 0;
         boolean handleOpenFloatingViews = false;
-        boolean isPinnedTaskbar = DisplayController.isPinnedTaskbar(
-                mControllers.taskbarActivityContext);
+        boolean isPinnedTaskbar =
+                mControllers.taskbarActivityContext.isPinnedTaskbar();
         if (DEBUG) {
             Log.d(TAG, "onStateChangeApplied - isInLauncher: " + isInLauncher
                     + ", mLauncherState: " + mLauncherState
@@ -590,7 +586,8 @@
         float backgroundAlpha = isInLauncher && isTaskbarAlignedWithHotseat() ? 0 : 1;
         AnimatedFloat taskbarBgOffset =
                 mControllers.taskbarDragLayerController.getTaskbarBackgroundOffset();
-        boolean showTaskbar = shouldShowTaskbar(mLauncher, isInLauncher, isInOverview);
+        boolean showTaskbar = shouldShowTaskbar(mControllers.taskbarActivityContext, isInLauncher,
+                isInOverview);
         float taskbarBgOffsetEnd = showTaskbar ? 0f : 1f;
         float taskbarBgOffsetStart = showTaskbar ? 1f : 0f;
 
@@ -727,13 +724,13 @@
         return animatorSet;
     }
 
-    private static boolean shouldShowTaskbar(Context context, boolean isInLauncher,
-            boolean isInOverview) {
-        if (DisplayController.showDesktopTaskbarForFreeformDisplay(context)) {
+    private static boolean shouldShowTaskbar(TaskbarActivityContext activityContext,
+            boolean isInLauncher, boolean isInOverview) {
+        if (activityContext.showDesktopTaskbarForFreeformDisplay()) {
             return true;
         }
 
-        if (DisplayController.showLockedTaskbarOnHome(context) && isInLauncher) {
+        if (activityContext.showLockedTaskbarOnHome() && isInLauncher) {
             return true;
         }
         return !isInLauncher || isInOverview;
@@ -788,11 +785,11 @@
      * This refers to the intended state - a transition to this state might be in progress.
      */
     public boolean isTaskbarAlignedWithHotseat() {
-        if (DisplayController.showDesktopTaskbarForFreeformDisplay(mLauncher)) {
+        if (mControllers.taskbarActivityContext.showDesktopTaskbarForFreeformDisplay()) {
             return false;
         }
 
-        if (DisplayController.showLockedTaskbarOnHome(mLauncher) && isInLauncher()) {
+        if (mControllers.taskbarActivityContext.showLockedTaskbarOnHome() && isInLauncher()) {
             return false;
         }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index b5e271d..1521715 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -227,7 +227,7 @@
                     }
                     // Only Handles Special Exit Cases for Desktop Mode Taskbar Recreation.
                     if (taskbarActivityContext != null
-                            && !DisplayController.showLockedTaskbarOnHome(context)) {
+                            && !taskbarActivityContext.showLockedTaskbarOnHome()) {
                         recreateTaskbars();
                     }
                 } else {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index eaf00b6..e597148 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -66,7 +66,6 @@
 import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.anim.AnimationSuccessListener;
 import com.android.launcher3.anim.AnimatorListeners;
-import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.util.SystemUiFlagUtils;
@@ -307,8 +306,8 @@
         // TODO(b/390665752): Feature to "lock" pinned taskbar to home screen will be superseded by
         //     pinning, in other launcher states, at which point this variable can be removed.
         mInAppStateAffectsDesktopTasksVisibilityInTaskbar =
-                !DisplayController.showDesktopTaskbarForFreeformDisplay(mActivity)
-                        && DisplayController.showLockedTaskbarOnHome(mActivity);
+                !mActivity.showDesktopTaskbarForFreeformDisplay()
+                        && mActivity.showLockedTaskbarOnHome();
 
         mTaskbarBackgroundDuration = activity.getResources().getInteger(
                 R.integer.taskbar_background_duration);
@@ -413,7 +412,7 @@
      * Returns how long the stash/unstash animation should play.
      */
     public long getStashDuration() {
-        if (DisplayController.isPinnedTaskbar(mActivity)) {
+        if (mActivity.isPinnedTaskbar()) {
             return PINNED_TASKBAR_TRANSITION_DURATION;
         }
         return mActivity.isTransientTaskbar() ? TRANSIENT_TASKBAR_STASH_DURATION
@@ -1186,7 +1185,7 @@
         }
 
         // Do not stash if pinned taskbar, hardware keyboard is attached and no IME is docked
-        if (mActivity.isHardwareKeyboard() && DisplayController.isPinnedTaskbar(mActivity)
+        if (mActivity.isHardwareKeyboard() && mActivity.isPinnedTaskbar()
                 && !mActivity.isImeDocked()) {
             return false;
         }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
index dcb9fbf..d0886e0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
@@ -36,7 +36,6 @@
 
 import com.android.internal.jank.Cuj;
 import com.android.launcher3.taskbar.bubbles.BubbleBarViewController;
-import com.android.launcher3.util.DisplayController;
 import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
 import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
 
@@ -67,8 +66,8 @@
         InteractionJankMonitorWrapper.begin(v, Cuj.CUJ_LAUNCHER_OPEN_ALL_APPS,
                 /* tag= */ "TASKBAR_BUTTON");
         mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP);
-        if (DisplayController.showLockedTaskbarOnHome(mActivity)
-                || DisplayController.showDesktopTaskbarForFreeformDisplay(mActivity)) {
+        if (mActivity.showLockedTaskbarOnHome()
+                || mActivity.showDesktopTaskbarForFreeformDisplay()) {
             // If the taskbar can be shown on the home screen, use mAllAppsToggler to toggle all
             // apps, which will toggle the launcher activity all apps when on home screen.
             // TODO(b/395913143): Reconsider this if a gap in taskbar all apps functionality that
@@ -248,8 +247,7 @@
 
         /** Returns true if the taskbar pinning popup view was shown for {@code event}. */
         private boolean maybeShowPinningView(@NonNull MotionEvent event) {
-            if (!DisplayController.isPinnedTaskbar(mActivity) || mTaskbarView.isEventOverAnyItem(
-                    event)) {
+            if (!mActivity.isPinnedTaskbar() || mTaskbarView.isEventOverAnyItem(event)) {
                 return false;
             }
             mControllers.taskbarPinningController.showPinningView(mTaskbarView, event.getRawX());
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 6786aed..c5b97e7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -19,6 +19,7 @@
 import static android.animation.LayoutTransition.CHANGE_APPEARING;
 import static android.animation.LayoutTransition.CHANGE_DISAPPEARING;
 import static android.animation.LayoutTransition.DISAPPEARING;
+import static android.view.Display.DEFAULT_DISPLAY;
 import static android.window.DesktopModeFlags.ENABLE_TASKBAR_RECENTS_LAYOUT_TRANSITION;
 
 import static com.android.app.animation.Interpolators.EMPHASIZED;
@@ -86,7 +87,6 @@
 import com.android.launcher3.taskbar.bubbles.BubbleControllers;
 import com.android.launcher3.taskbar.customization.TaskbarAllAppsButtonContainer;
 import com.android.launcher3.taskbar.customization.TaskbarDividerContainer;
-import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.ItemInfoMatcher;
 import com.android.launcher3.util.LauncherBindableItemsContainer;
 import com.android.launcher3.util.MultiPropertyFactory;
@@ -747,7 +747,8 @@
     }
 
     private boolean shouldUpdateIconContentDescription(BubbleTextView btv) {
-        boolean isInDesktopMode = mControllers.taskbarDesktopModeController.isInDesktopMode();
+        boolean isInDesktopMode = mControllers.taskbarDesktopModeController.isInDesktopMode(
+                DEFAULT_DISPLAY);
         boolean isAllAppsButton = btv instanceof TaskbarAllAppsButtonContainer;
         boolean isDividerButton = btv instanceof TaskbarDividerContainer;
         return isInDesktopMode && !isAllAppsButton && !isDividerButton;
@@ -930,7 +931,9 @@
     private AnimatorPlaybackController createIconAlignmentController(DeviceProfile launcherDp) {
         PendingAnimation setter = new PendingAnimation(100);
         // icon alignment not needed for pinned taskbar.
-        if (DisplayController.isPinnedTaskbar(mActivity)) return setter.createPlaybackController();
+        if (mActivity.isPinnedTaskbar()) {
+            return setter.createPlaybackController();
+        }
         mOnControllerPreCreateCallback.run();
         DeviceProfile taskbarDp = mActivity.getDeviceProfile();
         Rect hotseatPadding = launcherDp.getHotseatLayoutPadding(mActivity);
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
index dd91d17..8574b89 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
@@ -31,6 +31,7 @@
 import com.android.launcher3.taskbar.TaskbarUIController;
 import com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView;
 import com.android.launcher3.taskbar.allapps.TaskbarSearchSessionController;
+import com.android.launcher3.util.NavigationMode;
 import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
 
 /**
@@ -142,6 +143,41 @@
     }
 
     @Override
+    public boolean isTransientTaskbar() {
+        return mTaskbarContext.isTransientTaskbar();
+    }
+
+    @Override
+    public boolean isPinnedTaskbar() {
+        return mTaskbarContext.isPinnedTaskbar();
+    }
+
+    @Override
+    public NavigationMode getNavigationMode() {
+        return mTaskbarContext.getNavigationMode();
+    }
+
+    @Override
+    public boolean isInDesktopMode() {
+        return mTaskbarContext.isInDesktopMode();
+    }
+
+    @Override
+    public boolean showLockedTaskbarOnHome() {
+        return mTaskbarContext.showLockedTaskbarOnHome();
+    }
+
+    @Override
+    public boolean showDesktopTaskbarForFreeformDisplay() {
+        return mTaskbarContext.showDesktopTaskbarForFreeformDisplay();
+    }
+
+    @Override
+    public boolean isPrimaryDisplay() {
+        return mTaskbarContext.isPrimaryDisplay();
+    }
+
+    @Override
     public void onDragStart() {}
 
     @Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.kt b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.kt
index 23dc81d..c9f791c 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.kt
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.kt
@@ -21,6 +21,7 @@
 import com.android.app.animation.Interpolators.INSTANT
 import com.android.app.animation.Interpolators.LINEAR
 import com.android.launcher3.Flags.enableDesktopExplodedView
+import com.android.launcher3.Flags.enableGridOnlyOverview
 import com.android.launcher3.Flags.enableLargeDesktopWindowingTile
 import com.android.launcher3.LauncherState
 import com.android.launcher3.anim.AnimatedFloat
@@ -143,7 +144,11 @@
             recentsView,
             TASK_MODALNESS,
             toState.overviewModalness,
-            config.getInterpolator(ANIM_OVERVIEW_MODAL, LINEAR),
+            config.getInterpolator(
+                ANIM_OVERVIEW_MODAL,
+                if (enableGridOnlyOverview() && !toState.isRecentsViewVisible) FINAL_FRAME
+                else LINEAR,
+            ),
         )
 
         val fromState = launcher.stateManager.state
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
index 0c0b4fd..ae82f82 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
@@ -15,11 +15,11 @@
  */
 package com.android.launcher3.uioverrides.states;
 
+import static com.android.launcher3.Flags.enableGridOnlyOverview;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
 
 import android.graphics.Rect;
 
-import com.android.launcher3.Flags;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.views.ActivityContext;
@@ -50,6 +50,9 @@
 
     @Override
     public float[] getOverviewScaleAndOffset(Launcher launcher) {
+        if (enableGridOnlyOverview()) {
+            return super.getOverviewScaleAndOffset(launcher);
+        }
         return getOverviewScaleAndOffsetForModalState(launcher.getOverviewPanel());
     }
 
@@ -65,7 +68,7 @@
 
     @Override
     public boolean isTaskbarStashed(Launcher launcher) {
-        if (Flags.enableGridOnlyOverview()) {
+        if (enableGridOnlyOverview()) {
             return true;
         }
         return super.isTaskbarStashed(launcher);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewDismissTouchController.kt b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewDismissTouchController.kt
index 454a307..76eb138 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewDismissTouchController.kt
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewDismissTouchController.kt
@@ -63,6 +63,7 @@
     private var hasDismissThresholdHapticRun = false
     private var initialDisplacement: Float = 0f
     private var recentsScaleAnimation: SpringAnimation? = null
+    private var isBlockedDuringDismissal = false
 
     private fun canInterceptTouch(ev: MotionEvent): Boolean =
         when {
@@ -137,6 +138,7 @@
     }
 
     override fun onDragStart(start: Boolean, startDisplacement: Float) {
+        if (isBlockedDuringDismissal) return
         val taskBeingDragged = taskBeingDragged ?: return
 
         initialDisplacement =
@@ -149,6 +151,7 @@
     }
 
     override fun onDrag(displacement: Float): Boolean {
+        if (isBlockedDuringDismissal) return true
         val taskBeingDragged = taskBeingDragged ?: return false
         val currentDisplacement = displacement + initialDisplacement
         val boundedDisplacement =
@@ -204,6 +207,7 @@
     }
 
     override fun onDragEnd(velocity: Float) {
+        if (isBlockedDuringDismissal) return
         val taskBeingDragged = taskBeingDragged ?: return
 
         val currentDisplacement =
@@ -234,6 +238,7 @@
                         if (isDismissing) (dismissLength * verticalFactor).toFloat() else 0f
                     )
                 }
+        isBlockedDuringDismissal = true
         recentsScaleAnimation =
             recentsView.animateRecentsScale(RECENTS_SCALE_DEFAULT).addEndListener { _, _, _, _ ->
                 recentsScaleAnimation = null
@@ -246,6 +251,7 @@
         taskBeingDragged?.translationZ = 0f
         taskBeingDragged = null
         springAnimation = null
+        isBlockedDuringDismissal = false
     }
 
     private fun getRecentsScale(dismissFraction: Float): Float {
diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
index f96bbcb..943f543 100644
--- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
+++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
@@ -68,8 +68,10 @@
      * running tasks
      */
     public RemoteTargetGluer(Context context, BaseContainerInterface sizingStrategy) {
+        // TODO: b/403344864 Make sure init with correct number of RemoteTargetHandle with
+        //  multi-desks feature enabled as well.
         int visibleTasksCount = DesktopVisibilityController.INSTANCE.get(context)
-                .getVisibleDesktopTasksCount();
+                .getVisibleDesktopTasksCountDeprecated();
         if (visibleTasksCount > 0) {
             // Allocate +1 to account for a new task added to the desktop mode
             int numHandles = visibleTasksCount + 1;
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
index 554cea2..7db1813 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
@@ -19,6 +19,7 @@
 import static com.android.app.animation.Interpolators.INSTANT;
 import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.Flags.enableDesktopExplodedView;
+import static com.android.launcher3.Flags.enableGridOnlyOverview;
 import static com.android.launcher3.Flags.enableLargeDesktopWindowingTile;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
@@ -118,7 +119,9 @@
                 config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR));
 
         setter.setFloat(mRecentsView, TASK_MODALNESS, state.getOverviewModalness(),
-                config.getInterpolator(ANIM_OVERVIEW_MODAL, LINEAR));
+                config.getInterpolator(ANIM_OVERVIEW_MODAL,
+                        enableGridOnlyOverview() && !state.isRecentsViewVisible() ? FINAL_FRAME
+                                : LINEAR));
         setter.setFloat(mRecentsView, FULLSCREEN_PROGRESS, state.isFullScreen() ? 1 : 0, LINEAR);
         boolean showAsGrid =
                 state.displayOverviewTasksAsGrid(mRecentsViewContainer.getDeviceProfile());
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 29b6626..695c77c 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -17,6 +17,7 @@
 
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 
+import static com.android.launcher3.Flags.enableGridOnlyOverview;
 import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
 import static com.android.quickstep.fallback.RecentsState.DEFAULT;
 import static com.android.quickstep.fallback.RecentsState.MODAL_TASK;
@@ -252,7 +253,14 @@
     @Override
     public void onStateTransitionStart(RecentsState toState) {
         setOverviewStateEnabled(true);
-        setOverviewGridEnabled(toState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile()));
+        if (enableGridOnlyOverview()) {
+            if (toState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile())) {
+                setOverviewGridEnabled(true);
+            }
+        } else {
+            setOverviewGridEnabled(
+                    toState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile()));
+        }
         setOverviewFullscreenEnabled(toState.isFullScreen());
         if (toState == MODAL_TASK) {
             setOverviewSelectEnabled(true);
@@ -271,6 +279,11 @@
     @Override
     public void onStateTransitionComplete(RecentsState finalState) {
         DesktopVisibilityController.INSTANCE.get(mContainer).onLauncherStateChanged(finalState);
+        if (enableGridOnlyOverview()) {
+            if (!finalState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile())) {
+                setOverviewGridEnabled(false);
+            }
+        }
         if (!finalState.isRecentsViewVisible()) {
             // Clean-up logic that occurs when recents is no longer in use/visible.
             reset();
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsState.java b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
index 2c1a4eb..00aa109 100644
--- a/quickstep/src/com/android/quickstep/fallback/RecentsState.java
+++ b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
@@ -17,6 +17,7 @@
 
 import static com.android.launcher3.Flags.enableDesktopExplodedView;
 import static com.android.launcher3.Flags.enableDesktopWindowingCarouselDetach;
+import static com.android.launcher3.Flags.enableGridOnlyOverview;
 import static com.android.launcher3.LauncherState.FLAG_CLOSE_POPUPS;
 import static com.android.launcher3.uioverrides.states.BackgroundAppState.getOverviewScaleAndOffsetForBackgroundState;
 import static com.android.launcher3.uioverrides.states.OverviewModalTaskState.getOverviewScaleAndOffsetForModalState;
@@ -197,6 +198,9 @@
 
         @Override
         public float[] getOverviewScaleAndOffset(RecentsViewContainer container) {
+            if (enableGridOnlyOverview()) {
+                return super.getOverviewScaleAndOffset(container);
+            }
             return getOverviewScaleAndOffsetForModalState(container.getOverviewPanel());
         }
     }
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 74de2ac..c1282b9 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -18,6 +18,7 @@
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY;
 
+import static com.android.launcher3.Flags.enableGridOnlyOverview;
 import static com.android.launcher3.LauncherState.CLEAR_ALL_BUTTON;
 import static com.android.launcher3.LauncherState.ADD_DESK_BUTTON;
 import static com.android.launcher3.LauncherState.NORMAL;
@@ -151,7 +152,14 @@
     public void onStateTransitionStart(LauncherState toState) {
         setOverviewStateEnabled(toState.isRecentsViewVisible);
 
-        setOverviewGridEnabled(toState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile()));
+        if (enableGridOnlyOverview()) {
+            if (toState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile())) {
+                setOverviewGridEnabled(true);
+            }
+        } else {
+            setOverviewGridEnabled(
+                    toState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile()));
+        }
         setOverviewFullscreenEnabled(toState.getOverviewFullscreenProgress() == 1);
         if (toState == OVERVIEW_MODAL_TASK) {
             setOverviewSelectEnabled(true);
@@ -170,6 +178,11 @@
     @Override
     public void onStateTransitionComplete(LauncherState finalState) {
         DesktopVisibilityController.INSTANCE.get(mContainer).onLauncherStateChanged(finalState);
+        if (enableGridOnlyOverview()) {
+            if (!finalState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile())) {
+                setOverviewGridEnabled(false);
+            }
+        }
 
         if (!finalState.isRecentsViewVisible) {
             // Clean-up logic that occurs when recents is no longer in use/visible.
diff --git a/quickstep/src/com/android/quickstep/views/RecentsDismissUtils.kt b/quickstep/src/com/android/quickstep/views/RecentsDismissUtils.kt
index d39b528..db18394 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsDismissUtils.kt
+++ b/quickstep/src/com/android/quickstep/views/RecentsDismissUtils.kt
@@ -82,6 +82,7 @@
                             runTaskGridReflowSpringAnimation(
                                 draggedTaskView,
                                 getDismissedTaskGapForReflow(draggedTaskView),
+                                onEndRunnable,
                             )
                         } else {
                             recentsView.dismissTaskView(
@@ -89,11 +90,12 @@
                                 /* animateTaskView = */ false,
                                 /* removeTask = */ true,
                             )
+                            onEndRunnable()
                         }
                     } else {
                         recentsView.onDismissAnimationEnds()
+                        onEndRunnable()
                     }
-                    onEndRunnable()
                 }
         if (!isDismissing) {
             addNeighborSettlingSpringAnimations(
@@ -295,7 +297,7 @@
         val maxDismissSettlingVelocity =
             recentsView.pagedOrientationHandler.getSecondaryDimension(recentsView)
         MSDLPlayerWrapper.INSTANCE.get(recentsView.context)
-            .playToken(
+            ?.playToken(
                 MSDLToken.CANCEL,
                 InteractionProperties.DynamicVibrationScale(
                     boundToRange(abs(velocity) / maxDismissSettlingVelocity, 0f, 1f),
@@ -339,6 +341,7 @@
     private fun runTaskGridReflowSpringAnimation(
         dismissedTaskView: TaskView,
         dismissedTaskGap: Float,
+        onEndRunnable: () -> Unit,
     ) {
         // Empty spring animation exists for conditional start, and to drive neighboring springs.
         val springAnimationDriver =
@@ -427,12 +430,17 @@
                 driverProgressThreshold = dismissedTaskGap,
                 isSpringDirectionVertical = false,
             )
+        } else {
+            springAnimationDriver.addEndListener { _, _, _, _ ->
+                // Play the same haptic as when neighbors spring into place.
+                MSDLPlayerWrapper.INSTANCE.get(recentsView.context)?.playToken(MSDLToken.CANCEL)
+            }
         }
 
         // Start animations and remove the dismissed task at the end, dismiss immediately if no
         // neighboring tasks exist.
         val runGridEndAnimationAndRelayout = {
-            recentsView.expressiveDismissTaskView(dismissedTaskView)
+            recentsView.expressiveDismissTaskView(dismissedTaskView, onEndRunnable)
         }
         springAnimationDriver?.apply {
             addEndListener { _, _, _, _ -> runGridEndAnimationAndRelayout() }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 8c7fe26..aa25738 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -275,7 +275,7 @@
         HighResLoadingState.HighResLoadingStateChangedCallback,
         TaskVisualsChangeListener, DesktopVisibilityListener {
 
-    private static final String TAG = "RecentsView";
+    protected static final String TAG = "RecentsView";
     private static final boolean DEBUG = false;
 
     public static final FloatProperty<RecentsView<?, ?>> CONTENT_ALPHA =
@@ -534,7 +534,6 @@
     protected final Rect mLastComputedTaskSize = new Rect();
     protected final Rect mLastComputedGridSize = new Rect();
     protected final Rect mLastComputedGridTaskSize = new Rect();
-    private TaskView mSelectedTask = null;
     // How much a task that is directly offscreen will be pushed out due to RecentsView scale/pivot.
     @Nullable
     protected Float mLastComputedTaskStartPushOutDistance = null;
@@ -2418,21 +2417,28 @@
     }
 
     /**
-     * Sets the last TaskView selected.
+     * Returns the currently selected TaskView in Select mode.
+     */
+    @Nullable
+    public TaskView getSelectedTaskView() {
+        return mUtils.getSelectedTaskView();
+    }
+
+    /**
+     * Sets the selected TaskView in Select mode.
      */
     public void setSelectedTask(int lastSelectedTaskId) {
-        mSelectedTask = getTaskViewByTaskId(lastSelectedTaskId);
+        mUtils.setSelectedTaskView(getTaskViewByTaskId(lastSelectedTaskId));
     }
 
     /**
      * Returns the bounds of the task selected to enter modal state.
      */
     public Rect getSelectedTaskBounds() {
-        if (mSelectedTask == null) {
-            return enableGridOnlyOverview() && mContainer.getDeviceProfile().isTablet
-                    ? mLastComputedGridTaskSize : mLastComputedTaskSize;
+        if (getSelectedTaskView() == null) {
+            return mLastComputedTaskSize;
         }
-        return getTaskBounds(mSelectedTask);
+        return getTaskBounds(getSelectedTaskView());
     }
 
     /**
@@ -2448,7 +2454,7 @@
         return deviceProfile.overviewTaskThumbnailTopMarginPx / 2.0f;
     }
 
-    private Rect getTaskBounds(TaskView taskView) {
+    protected Rect getTaskBounds(TaskView taskView) {
         int selectedPage = indexOfChild(taskView);
         int primaryScroll = getPagedOrientationHandler().getPrimaryScroll(this);
         int selectedPageScroll = getScrollForPage(selectedPage);
@@ -3937,7 +3943,7 @@
                 newClearAllShortTotalWidthTranslation = expectedFirstTaskStart - firstTaskStart;
             }
         }
-        if (lastGridTaskView != null && (lastGridTaskView.isVisibleToUser() || (
+        if (lastGridTaskView != null && (isTaskViewVisible(lastGridTaskView) || (
                 isExpressiveDismiss && lastGridTaskView == dismissedTaskView))) {
             // After dismissal, animate translation of the remaining tasks to fill any gap left
             // between the end of the grid and the clear all button. Only animate if the clear
@@ -4734,11 +4740,12 @@
         runDismissAnimation(pa);
     }
 
-    protected void expressiveDismissTaskView(TaskView taskView) {
+    protected void expressiveDismissTaskView(TaskView taskView, Function0<Unit> onEndRunnable) {
         PendingAnimation pa = new PendingAnimation(DISMISS_TASK_DURATION);
         createTaskDismissAnimation(pa, taskView, false /* animateTaskView */, true /* removeTask */,
                 DISMISS_TASK_DURATION, false /* dismissingForSplitSelection*/,
                 true /* isExpressiveDismiss */);
+        pa.addEndListener((success) -> onEndRunnable.invoke());
         runDismissAnimation(pa);
     }
 
@@ -5011,15 +5018,8 @@
     }
 
     private void updatePivots() {
-        if (mOverviewSelectEnabled) {
-            if (enableGridOnlyOverview()) {
-                getModalTaskSize(mTempRect);
-                Rect selectedTaskPosition = getSelectedTaskBounds();
-                Utilities.getPivotsForScalingRectToRect(mTempRect, selectedTaskPosition,
-                        mTempPointF);
-            } else {
-                mTempPointF.set(mLastComputedTaskSize.centerX(), mLastComputedTaskSize.bottom);
-            }
+        if (mOverviewSelectEnabled && !enableGridOnlyOverview()) {
+            mTempPointF.set(mLastComputedTaskSize.centerX(), mLastComputedTaskSize.bottom);
         } else {
             mTempRect.set(mLastComputedTaskSize);
             getPagedViewOrientedState().getFullScreenScaleAndPivot(mTempRect,
@@ -5065,7 +5065,7 @@
                 && (enableGridOnlyOverview() || enableLargeDesktopWindowingTile())
                 && mTaskModalness > 0;
         if (shouldCalculateOffsetForAllTasks) {
-            modalMidpoint = indexOfChild(mSelectedTask);
+            modalMidpoint = indexOfChild(getSelectedTaskView());
         }
 
         float midpointOffsetSize = 0;
@@ -5273,7 +5273,7 @@
      */
     private float getVerticalOffsetSize(TaskView taskView, float offsetProgress) {
         if (offsetProgress == 0 || !(showAsGrid() && enableGridOnlyOverview())
-                || mSelectedTask == null) {
+                || getSelectedTaskView() == null) {
             // Don't bother calculating everything below if we won't offset vertically.
             return 0;
         }
@@ -5281,7 +5281,7 @@
         // First, get the position of the task relative to the top row.
         Rect taskPosition = getTaskBounds(taskView);
 
-        boolean isSelectedTaskTopRow = mTopRowIdSet.contains(mSelectedTask.getTaskViewId());
+        boolean isSelectedTaskTopRow = mTopRowIdSet.contains(getSelectedTaskView().getTaskViewId());
         boolean isChildTopRow = mTopRowIdSet.contains(taskView.getTaskViewId());
         // Whether the task should be shifted to the top.
         boolean isTopShift = !isSelectedTaskTopRow && isChildTopRow;
@@ -5335,8 +5335,8 @@
      * Resets the visuals when exit modal state.
      */
     public void resetModalVisuals() {
-        if (mSelectedTask != null) {
-            mSelectedTask.taskContainers.forEach(
+        if (getSelectedTaskView() != null) {
+            getSelectedTaskView().taskContainers.forEach(
                     taskContainer -> taskContainer.getOverlay().resetModalVisuals());
         }
     }
@@ -6717,8 +6717,14 @@
     private void setTaskModalness(float modalness) {
         mTaskModalness = modalness;
         updatePageOffsets();
-        if (mSelectedTask != null) {
-            mSelectedTask.setModalness(modalness);
+        if (getSelectedTaskView() != null) {
+            if (enableGridOnlyOverview()) {
+                for (TaskView taskView : getTaskViews()) {
+                    taskView.setModalness(modalness);
+                }
+            } else {
+                getSelectedTaskView().setModalness(modalness);
+            }
         } else if (getCurrentPageTaskView() != null) {
             getCurrentPageTaskView().setModalness(modalness);
         }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt b/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt
index 9c35913..51a5d0f 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt
+++ b/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt
@@ -16,6 +16,7 @@
 
 package com.android.quickstep.views
 
+import android.graphics.PointF
 import android.graphics.Rect
 import android.util.FloatProperty
 import android.view.KeyEvent
@@ -25,9 +26,11 @@
 import androidx.core.view.children
 import com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU
 import com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType
+import com.android.launcher3.Flags.enableGridOnlyOverview
 import com.android.launcher3.Flags.enableLargeDesktopWindowingTile
 import com.android.launcher3.Flags.enableOverviewIconMenu
 import com.android.launcher3.Flags.enableSeparateExternalDisplayTasks
+import com.android.launcher3.Utilities.getPivotsForScalingRectToRect
 import com.android.launcher3.statehandlers.DesktopVisibilityController
 import com.android.launcher3.statehandlers.DesktopVisibilityController.Companion.INACTIVE_DESK_ID
 import com.android.launcher3.util.IntArray
@@ -38,6 +41,7 @@
 import com.android.quickstep.views.RecentsView.RUNNING_TASK_ATTACH_ALPHA
 import com.android.systemui.shared.recents.model.ThumbnailData
 import java.util.function.BiConsumer
+import kotlin.math.min
 import kotlin.reflect.KMutableProperty1
 
 /**
@@ -393,6 +397,47 @@
             taskViews.filterIsInstance<DesktopTaskView>().forEach { it.explodeProgress = field }
         }
 
+    var selectedTaskView: TaskView? = null
+        set(newValue) {
+            val oldValue = field
+            field = newValue
+            if (oldValue != newValue) {
+                onSelectedTaskViewUpdated(oldValue, newValue)
+            }
+        }
+
+    private fun onSelectedTaskViewUpdated(
+        oldSelectedTaskView: TaskView?,
+        newSelectedTaskView: TaskView?,
+    ) {
+        if (!enableGridOnlyOverview()) return
+        with(recentsView) {
+            oldSelectedTaskView?.modalScale = 1f
+            oldSelectedTaskView?.modalPivot = null
+
+            if (newSelectedTaskView == null) return
+
+            val modalTaskBounds = mTempRect
+            getModalTaskSize(modalTaskBounds)
+            val selectedTaskBounds = getTaskBounds(newSelectedTaskView)
+
+            // Map bounds to selectedTaskView's coordinate system.
+            modalTaskBounds.offset(-selectedTaskBounds.left, -selectedTaskBounds.top)
+            selectedTaskBounds.offset(-selectedTaskBounds.left, -selectedTaskBounds.top)
+
+            val modalScale =
+                min(
+                    (modalTaskBounds.height().toFloat() / selectedTaskBounds.height()),
+                    (modalTaskBounds.width().toFloat() / selectedTaskBounds.width()),
+                )
+            val modalPivot = PointF()
+            getPivotsForScalingRectToRect(modalTaskBounds, selectedTaskBounds, modalPivot)
+
+            newSelectedTaskView.modalScale = modalScale
+            newSelectedTaskView.modalPivot = modalPivot
+        }
+    }
+
     companion object {
         class RecentsViewFloatProperty(
             private val utilsProperty: KMutableProperty1<RecentsViewUtils, Float>
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.kt b/quickstep/src/com/android/quickstep/views/TaskView.kt
index 3d1643c..3835e48 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskView.kt
@@ -33,6 +33,7 @@
 import android.view.Display
 import android.view.MotionEvent
 import android.view.View
+import android.view.View.OnClickListener
 import android.view.ViewGroup
 import android.view.ViewStub
 import android.view.accessibility.AccessibilityNodeInfo
@@ -147,6 +148,9 @@
     val isRunningTask: Boolean
         get() = this === recentsView?.runningTaskView
 
+    private val isSelectedTask: Boolean
+        get() = this === recentsView?.selectedTaskView
+
     open val displayId: Int
         get() = taskContainers.firstOrNull()?.task.displayId
 
@@ -337,6 +341,12 @@
             onModalnessUpdated(field)
         }
 
+    var modalPivot: PointF? = null
+        set(value) {
+            field = value
+            updatePivots()
+        }
+
     var splitSplashAlpha = 0f
         set(value) {
             field = value
@@ -361,6 +371,12 @@
             applyScale()
         }
 
+    var modalScale = 1f
+        set(value) {
+            field = value
+            applyScale()
+        }
+
     private var dismissTranslationX = 0f
         set(value) {
             field = value
@@ -446,9 +462,10 @@
         }
 
     private val taskViewAlpha = MultiValueAlpha(this, Alpha.entries.size)
-    protected var stableAlpha by MultiPropertyDelegate(taskViewAlpha, Alpha.STABLE)
-    var attachAlpha by MultiPropertyDelegate(taskViewAlpha, Alpha.ATTACH)
-    var splitAlpha by MultiPropertyDelegate(taskViewAlpha, Alpha.SPLIT)
+    protected var stableAlpha by MultiPropertyDelegate(taskViewAlpha, Alpha.Stable)
+    var attachAlpha by MultiPropertyDelegate(taskViewAlpha, Alpha.Attach)
+    var splitAlpha by MultiPropertyDelegate(taskViewAlpha, Alpha.Split)
+    private var modalAlpha by MultiPropertyDelegate(taskViewAlpha, Alpha.Modal)
 
     protected var shouldShowScreenshot = false
         get() = !isRunningTask || field
@@ -628,14 +645,7 @@
 
     override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
         super.onLayout(changed, left, top, right, bottom)
-        val thumbnailTopMargin = container.deviceProfile.overviewTaskThumbnailTopMarginPx
-        if (container.deviceProfile.isTablet) {
-            pivotX = (if (layoutDirection == LAYOUT_DIRECTION_RTL) 0 else right - left).toFloat()
-            pivotY = thumbnailTopMargin.toFloat()
-        } else {
-            pivotX = (right - left) * 0.5f
-            pivotY = thumbnailTopMargin + (height - thumbnailTopMargin) * 0.5f
-        }
+        updatePivots()
         systemGestureExclusionRects =
             SYSTEM_GESTURE_EXCLUSION_RECT.onEach {
                 it.right = width
@@ -646,6 +656,24 @@
         }
     }
 
+    private fun updatePivots() {
+        val modalPivot = modalPivot
+        if (modalPivot != null) {
+            pivotX = modalPivot.x
+            pivotY = modalPivot.y
+        } else {
+            val thumbnailTopMargin = container.deviceProfile.overviewTaskThumbnailTopMarginPx
+            if (container.deviceProfile.isTablet) {
+                pivotX =
+                    (if (layoutDirection == LAYOUT_DIRECTION_RTL) 0 else right - left).toFloat()
+                pivotY = thumbnailTopMargin.toFloat()
+            } else {
+                pivotX = (right - left) * 0.5f
+                pivotY = thumbnailTopMargin + (height - thumbnailTopMargin) * 0.5f
+            }
+        }
+    }
+
     override fun onRecycle() {
         resetPersistentViewTransforms()
 
@@ -653,6 +681,9 @@
         attachAlpha = 1f
         splitAlpha = 1f
         splitSplashAlpha = 0f
+        modalAlpha = 1f
+        modalScale = 1f
+        modalPivot = null
         taskThumbnailSplashAlpha = 0f
         // Clear any references to the thumbnail (it will be re-read either from the cache or the
         // system on next bind)
@@ -1286,7 +1317,7 @@
                 targets.apps,
                 targets.wallpapers,
                 targets.nonApps,
-                true /* launcherClosing */,
+                true, /* launcherClosing */
                 recentsView.stateManager,
                 recentsView,
                 recentsView.depthController,
@@ -1722,7 +1753,7 @@
     fun getSizeAdjustment(fullscreenEnabled: Boolean) = if (fullscreenEnabled) nonGridScale else 1f
 
     private fun applyScale() {
-        val scale = persistentScale * dismissScale
+        val scale = persistentScale * dismissScale * Utilities.mapRange(modalness, 1f, modalScale)
         scaleX = scale
         scaleY = scale
         updateFullscreenParams()
@@ -1784,9 +1815,13 @@
     private fun onModalnessUpdated(modalness: Float) {
         isClickable = modalness == 0f
         taskContainers.forEach {
-            it.iconView.setModalAlpha(1 - modalness)
+            it.iconView.setModalAlpha(1f - modalness)
             it.digitalWellBeingToast?.bannerOffsetPercentage = modalness
         }
+        if (enableGridOnlyOverview()) {
+            modalAlpha = if (isSelectedTask) 1f else (1f - modalness)
+            applyScale()
+        }
     }
 
     fun resetPersistentViewTransforms() {
@@ -1842,9 +1877,10 @@
         private const val TAG = "TaskView"
 
         private enum class Alpha {
-            STABLE,
-            ATTACH,
-            SPLIT,
+            Stable,
+            Attach,
+            Split,
+            Modal,
         }
 
         private enum class SettledProgress {
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt
index 8758d7c..334d8ab 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt
@@ -960,7 +960,7 @@
     private fun setInDesktopMode(inDesktopMode: Boolean) {
         whenever(taskbarControllers.taskbarDesktopModeController.shouldShowDesktopTasksInTaskbar())
             .thenReturn(inDesktopMode)
-        whenever(taskbarControllers.taskbarDesktopModeController.isInDesktopMode)
+        whenever(taskbarControllers.taskbarDesktopModeController.isInDesktopMode(DEFAULT_DISPLAY))
             .thenReturn(inDesktopMode)
     }
 
diff --git a/res/values-sw600dp/styles.xml b/res/values-sw600dp/styles.xml
index 63bd46b..db49a3e 100644
--- a/res/values-sw600dp/styles.xml
+++ b/res/values-sw600dp/styles.xml
@@ -14,8 +14,11 @@
   ~ limitations under the License.
   -->
 
-<resources>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
     <style name="CellStyleDefault">
         <item name="iconDrawablePadding">7dp</item>
     </style>
+    <style name="DropTargetButton" parent="DropTargetButtonBase">
+        <item name="android:fontFamily" android:featureFlag="com.android.launcher3.gsf_res">variable-title-large</item>
+    </style>
 </resources>
\ No newline at end of file
diff --git a/res/values-v31/styles.xml b/res/values-v31/styles.xml
index 932ce38..6ed7dd6 100644
--- a/res/values-v31/styles.xml
+++ b/res/values-v31/styles.xml
@@ -17,7 +17,7 @@
 */
 -->
 
-<resources>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
 
     <style name="HomeSettings.Theme" parent="@android:style/Theme.DeviceDefault.Settings">
         <item name="android:listPreferredItemPaddingEnd">16dp</item>
@@ -29,6 +29,7 @@
         <item name="android:windowActionBar">false</item>
         <item name="android:windowNoTitle">true</item>
         <item name="preferenceTheme">@style/HomeSettings.PreferenceTheme</item>
+        <item name="android:fontFamily" android:featureFlag="com.android.launcher3.gsf_res">google-sans-flex</item>
     </style>
 
     <style name="HomeSettings.PreferenceTheme" parent="@style/PreferenceThemeOverlay">
@@ -80,11 +81,13 @@
 
     <style name="HomeSettings.CollapsedToolbarTitle"
             parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
-        <item name="android:fontFamily">google-sans</item>
+        <item name="android:fontFamily" android:featureFlag="!com.android.launcher3.gsf_res">google-sans</item>
+        <item name="android:fontFamily" android:featureFlag="com.android.launcher3.gsf_res">variable-title-large</item>
         <item name="android:textSize">20sp</item>
     </style>
 
     <style name="HomeSettings.ExpandedToolbarTitle" parent="HomeSettings.CollapsedToolbarTitle">
+        <item name="android:fontFamily" android:featureFlag="com.android.launcher3.gsf_res">variable-display-small</item>
         <item name="android:textSize">36sp</item>
     </style>
 </resources>
\ No newline at end of file
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 39206d3..cf6c560 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -373,7 +373,9 @@
         <item name="android:background">@drawable/drop_target_background</item>
     </style>
 
-    <style name="DropTargetButton" parent="DropTargetButtonBase" />
+    <style name="DropTargetButton" parent="DropTargetButtonBase">
+        <item name="android:fontFamily" android:featureFlag="com.android.launcher3.gsf_res">variable-title-medium</item>
+    </style>
 
     <style name="TextHeadline" parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle" />
 
diff --git a/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt b/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
index a30261e..dc49ba0 100644
--- a/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
@@ -39,7 +39,6 @@
 import com.android.launcher3.util.SandboxContext
 import com.android.launcher3.util.WindowBounds
 import com.android.launcher3.util.rule.TestStabilityRule
-import com.android.launcher3.util.rule.ZipFilesRule
 import com.android.launcher3.util.rule.setFlags
 import com.android.launcher3.util.window.CachedDisplayInfo
 import com.android.launcher3.util.window.WindowManagerProxy
@@ -52,7 +51,6 @@
 import java.io.StringWriter
 import kotlin.math.max
 import kotlin.math.min
-import org.junit.ClassRule
 import org.junit.Rule
 import org.mockito.kotlin.any
 import org.mockito.kotlin.doReturn
@@ -82,13 +80,6 @@
 
     @Rule @JvmField val limitDevicesRule = LimitDevicesRule()
 
-    companion object {
-        @ClassRule
-        @JvmField
-        val resultZipRule =
-            ZipFilesRule(InstrumentationRegistry.getInstrumentation().targetContext, "DumpTest")
-    }
-
     class DeviceSpec(
         val naturalSize: Pair<Int, Int>,
         var densityDpi: Int,
@@ -375,7 +366,6 @@
     private fun writeToDevice(context: Context, fileName: String, content: String) {
         val file = File(context.getDir("dumpTests", Context.MODE_PRIVATE), fileName)
         file.writeText(content)
-        resultZipRule.write(file)
     }
 
     protected fun Float.dpToPx(): Float {