Merge "Moving zip rule to Multivalent to fix roboelectric test in A-studio" into main
diff --git a/aconfig/launcher_overview.aconfig b/aconfig/launcher_overview.aconfig
index 5749c51..7b1ebee 100644
--- a/aconfig/launcher_overview.aconfig
+++ b/aconfig/launcher_overview.aconfig
@@ -110,3 +110,13 @@
     description: "Enable wallpaper background for desktop tasks in overview."
     bug: "363257721"
 }
+
+flag {
+    name: "enable_show_enabled_shortcuts_in_accessibility_menu"
+    namespace: "launcher_overview"
+    description: "Enables showing the same shortcuts in the Task menu as well as the accessibility actions menu"
+    bug: "383662632"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
index 8555376..cc94824 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
@@ -165,7 +165,7 @@
                         processLoadedTasks(tasks, taskIdsToExclude);
                         mQuickSwitchViewController.updateQuickSwitchView(
                                 mTasks,
-                                mNumHiddenTasks,
+                                wasOpenedFromTaskbar ? 0 : mNumHiddenTasks,
                                 currentFocusIndexOverride,
                                 mHasDesktopTask,
                                 mWasDesktopTaskFilteredOut);
@@ -205,7 +205,7 @@
             // running. If not, focus that first task.
             mQuickSwitchViewController.openQuickSwitchView(
                     mTasks,
-                    mNumHiddenTasks,
+                    wasOpenedFromTaskbar ? 0 : mNumHiddenTasks,
                     /* updateTasks= */ false,
                     currentFocusedIndex == -1 && !mControllerCallbacks.isFirstTaskRunning()
                             ? 0 : currentFocusedIndex,
@@ -223,7 +223,7 @@
             // the correct index.
             mQuickSwitchViewController.openQuickSwitchView(
                     mTasks,
-                    mNumHiddenTasks,
+                    wasOpenedFromTaskbar ? 0 : mNumHiddenTasks,
                     /* updateTasks= */ true,
                     currentFocusedIndex == -1 && !mControllerCallbacks.isFirstTaskRunning()
                             ? 0 : currentFocusedIndex,
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.kt b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.kt
index 79328df..23dc81d 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.kt
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.kt
@@ -76,10 +76,7 @@
             if (state.displayOverviewTasksAsGrid(launcher.deviceProfile)) 1f else 0f,
         )
         if (enableDesktopExplodedView()) {
-            DESK_EXPLODE_PROGRESS.set(
-                recentsView,
-                if (state.displayOverviewTasksAsGrid(launcher.deviceProfile)) 1f else 0f,
-            )
+            DESK_EXPLODE_PROGRESS.set(recentsView, if (state.showExplodedDesktopView()) 1f else 0f)
         }
 
         TASK_THUMBNAIL_SPLASH_ALPHA.set(
@@ -168,7 +165,7 @@
             builder.setFloat(
                 recentsView,
                 DESK_EXPLODE_PROGRESS,
-                if (toState.isRecentsViewVisible) 1f else 0f,
+                if (toState.showExplodedDesktopView()) 1f else 0f,
                 getOverviewInterpolator(fromState, toState),
             )
         }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
index b1196af..a5b1ee7 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
@@ -97,6 +97,11 @@
     }
 
     @Override
+    public boolean showExplodedDesktopView() {
+        return false;
+    }
+
+    @Override
     protected float getDepthUnchecked(Context context) {
         if (Launcher.getLauncher(context).areDesktopTasksVisible()) {
             // Don't blur the background while desktop tasks are visible
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index 5fdedcc..963504f 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -16,6 +16,7 @@
 package com.android.launcher3.uioverrides.states;
 
 import static com.android.app.animation.Interpolators.DECELERATE_2;
+import static com.android.launcher3.Flags.enableDesktopExplodedView;
 import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
 
@@ -171,6 +172,11 @@
     }
 
     @Override
+    public boolean showExplodedDesktopView() {
+        return enableDesktopExplodedView();
+    }
+
+    @Override
     public boolean disallowTaskbarGlobalDrag() {
         // Disable global drag in overview
         return true;
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index a594e49..deb06c9 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -42,6 +42,7 @@
 import com.android.launcher3.util.ResourceBasedOverride;
 import com.android.launcher3.views.ActivityContext;
 import com.android.launcher3.views.Snackbar;
+import com.android.quickstep.task.thumbnail.TaskOverlayUiState;
 import com.android.quickstep.task.util.TaskOverlayHelper;
 import com.android.quickstep.util.RecentsOrientedState;
 import com.android.quickstep.views.DesktopTaskView;
@@ -168,9 +169,32 @@
                     : mTaskContainer.getThumbnailViewDeprecated().getThumbnail();
         }
 
-        protected boolean isRealSnapshot() {
-            return enableRefactorTaskThumbnail() ? mHelper.getEnabledState().isRealSnapshot()
-                    : mTaskContainer.getThumbnailViewDeprecated().isRealSnapshot();
+        /**
+         * Returns whether the snapshot is real. If the device is locked for the user of the task,
+         * the snapshot used will be an app-theme generated snapshot instead of a real snapshot.
+         */
+        public boolean isRealSnapshot() {
+            if (enableRefactorTaskThumbnail()) {
+                if (mHelper.getUiState() instanceof TaskOverlayUiState.Enabled) {
+                    return mHelper.getEnabledState().isRealSnapshot();
+                } else {
+                    return false;
+                }
+            }
+
+            return mTaskContainer.getThumbnailViewDeprecated().isRealSnapshot();
+        }
+
+        /**
+         * Returns whether the snapshot is rotated compared to the current task orientation.
+         */
+        public boolean isThumbnailRotationDifferentFromTask() {
+            if (enableRefactorTaskThumbnail()) {
+                return mHelper.getThumbnailPositionState().isRotated();
+            }
+
+            return mTaskContainer.getThumbnailViewDeprecated()
+                    .isThumbnailRotationDifferentFromTask();
         }
 
         protected T getActionsView() {
@@ -359,13 +383,10 @@
 
         private class ScreenshotSystemShortcut extends SystemShortcut {
 
-            private final RecentsViewContainer mContainer;
-
             ScreenshotSystemShortcut(RecentsViewContainer container, ItemInfo itemInfo,
                     View originalView) {
                 super(R.drawable.ic_screenshot, R.string.action_screenshot, container, itemInfo,
                         originalView);
-                mContainer = container;
             }
 
             @Override
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index f92581e..bc46ace 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -20,7 +20,9 @@
 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
 import static android.view.Surface.ROTATION_0;
 
+import static com.android.launcher3.Flags.enableGridOnlyOverview;
 import static com.android.launcher3.Flags.enableRefactorTaskThumbnail;
+import static com.android.launcher3.Flags.enableShowEnabledShortcutsInAccessibilityMenu;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_CLOSE_APP_TAP;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
@@ -42,7 +44,6 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Flags;
 import com.android.launcher3.R;
 import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
 import com.android.launcher3.model.WellbeingModel;
@@ -345,15 +346,20 @@
             boolean isTaskSplitNotSupported = !task.isDockable ||
                     (intentFlags & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
             boolean hideForExistingMultiWindow = container.getDeviceProfile().isMultiWindowMode;
-            boolean isLargeTile = deviceProfile.isTablet && taskView.isLargeTile();
-            boolean isTaskInExpectedScrollPosition =
-                    recentsView.isTaskInExpectedScrollPosition(taskView);
 
-            if (notEnoughTasksToSplit || isTaskSplitNotSupported || hideForExistingMultiWindow
-                    || (isLargeTile && isTaskInExpectedScrollPosition)) {
+            if (notEnoughTasksToSplit || isTaskSplitNotSupported || hideForExistingMultiWindow) {
                 return null;
             }
 
+            if (!enableShowEnabledShortcutsInAccessibilityMenu()) {
+                boolean isLargeTile = deviceProfile.isTablet && taskView.isLargeTile();
+                boolean isTaskInExpectedScrollPosition =
+                        recentsView.isTaskInExpectedScrollPosition(taskView);
+                if (isLargeTile && isTaskInExpectedScrollPosition) {
+                    return null;
+                }
+            }
+
             return orientationHandler.getSplitPositionOptions(deviceProfile)
                     .stream()
                     .map((Function<SplitPositionOption, SystemShortcut>) option ->
@@ -500,16 +506,23 @@
         @Override
         public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
                 TaskContainer taskContainer) {
-            boolean isTablet = container.getDeviceProfile().isTablet;
-            boolean isGridOnlyOverview = isTablet && Flags.enableGridOnlyOverview();
-            // Extra conditions if it's not grid-only overview
-            if (!isGridOnlyOverview) {
-                RecentsOrientedState orientedState = taskContainer.getTaskView().getOrientedState();
-                boolean isFakeLandscape = !orientedState.isRecentsActivityRotationAllowed()
-                        && orientedState.getTouchRotation() != ROTATION_0;
-                if (!isFakeLandscape) {
+            if (enableShowEnabledShortcutsInAccessibilityMenu()) {
+                if (!taskContainer.getOverlay().isRealSnapshot()) {
                     return null;
                 }
+            } else {
+                boolean isTablet = container.getDeviceProfile().isTablet;
+                boolean isGridOnlyOverview = isTablet && enableGridOnlyOverview();
+                // Extra conditions if it's not grid-only overview
+                if (!isGridOnlyOverview) {
+                    RecentsOrientedState orientedState = taskContainer.getTaskView()
+                            .getOrientedState();
+                    boolean isFakeLandscape = !orientedState.isRecentsActivityRotationAllowed()
+                            && orientedState.getTouchRotation() != ROTATION_0;
+                    if (!isFakeLandscape) {
+                        return null;
+                    }
+                }
             }
 
             SystemShortcut screenshotShortcut = taskContainer.getOverlay().getScreenshotShortcut(
@@ -527,10 +540,39 @@
         @Override
         public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
                 TaskContainer taskContainer) {
-            boolean isTablet = container.getDeviceProfile().isTablet;
-            boolean isGridOnlyOverview = isTablet && Flags.enableGridOnlyOverview();
-            if (!isGridOnlyOverview) {
-                return null;
+            if (enableShowEnabledShortcutsInAccessibilityMenu()) {
+                if (!taskContainer.getOverlay().isRealSnapshot()) {
+                    return null;
+                }
+
+                // Modal only works with grid size tiles with enableGridOnlyOverview enabled on
+                // tablets / foldables. With enableGridOnlyOverview off, for large tiles it works,
+                // but the tile needs to be in the center of Recents / Overview.
+                boolean isTablet = container.getDeviceProfile().isTablet;
+                RecentsView recentsView = container.getOverviewPanel();
+                boolean isLargeTileInCenterOfOverview = taskContainer.getTaskView().isLargeTile()
+                        && recentsView.isFocusedTaskInExpectedScrollPosition();
+                if (isTablet
+                        && !isLargeTileInCenterOfOverview
+                        && !enableGridOnlyOverview()) {
+                    return null;
+                }
+
+                boolean isFakeLandscape = !taskContainer.getTaskView().getPagedOrientationHandler()
+                        .isLayoutNaturalToLauncher();
+                if (isFakeLandscape) {
+                    return null;
+                }
+
+                if (taskContainer.getOverlay().isThumbnailRotationDifferentFromTask()) {
+                    return null;
+                }
+            } else {
+                boolean isTablet = container.getDeviceProfile().isTablet;
+                boolean isGridOnlyOverview = isTablet && enableGridOnlyOverview();
+                if (!isGridOnlyOverview) {
+                    return null;
+                }
             }
 
             SystemShortcut modalStateSystemShortcut =
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 37c2d1c..855ff98 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -22,6 +22,7 @@
 import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.app.animation.Interpolators.TOUCH_RESPONSE;
 import static com.android.app.animation.Interpolators.clampToProgress;
+import static com.android.launcher3.Flags.enableDesktopExplodedView;
 import static com.android.launcher3.Flags.enableGridOnlyOverview;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
@@ -201,6 +202,9 @@
                     recentsView.getSizeStrategy(), targets, forDesktop);
             if (forDesktop) {
                 remoteTargetHandles = gluer.assignTargetsForDesktop(targets, transitionInfo);
+                if (enableDesktopExplodedView()) {
+                    ((DesktopTaskView) taskView).setRemoteTargetHandles(remoteTargetHandles);
+                }
             } else if (taskView.containsMultipleTasks()) {
                 remoteTargetHandles = gluer.assignTargetsForSplitScreen(targets,
                         ((GroupedTaskView) taskView).getSplitBoundsConfig());
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
index 2631efe..554cea2 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
@@ -132,7 +132,8 @@
                     getOverviewInterpolator(state));
         }
         if (enableDesktopExplodedView()) {
-            setter.setFloat(mRecentsView, DESK_EXPLODE_PROGRESS, showAsGrid ? 1f : 0f,
+            setter.setFloat(mRecentsView, DESK_EXPLODE_PROGRESS,
+                    state.showExplodedDesktopView() ? 1f : 0f,
                     getOverviewInterpolator(state));
         }
 
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsState.java b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
index f722c5d..2c1a4eb 100644
--- a/quickstep/src/com/android/quickstep/fallback/RecentsState.java
+++ b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
@@ -15,6 +15,7 @@
  */
 package com.android.quickstep.fallback;
 
+import static com.android.launcher3.Flags.enableDesktopExplodedView;
 import static com.android.launcher3.Flags.enableDesktopWindowingCarouselDetach;
 import static com.android.launcher3.LauncherState.FLAG_CLOSE_POPUPS;
 import static com.android.launcher3.uioverrides.states.BackgroundAppState.getOverviewScaleAndOffsetForBackgroundState;
@@ -46,16 +47,18 @@
     private static final int FLAG_TASK_THUMBNAIL_SPLASH = BaseState.getFlag(8);
     private static final int FLAG_DETACH_DESKTOP_CAROUSEL = BaseState.getFlag(9);
     private static final int FLAG_ADD_DESK_BUTTON = BaseState.getFlag(10);
+    private static final int FLAG_SHOW_EXPLODED_DESKTOP_VIEW = BaseState.getFlag(11);
 
     private static final RecentsState[] sAllStates = new RecentsState[6];
 
     public static final RecentsState DEFAULT = new RecentsState(0,
             FLAG_DISABLE_RESTORE | FLAG_CLEAR_ALL_BUTTON | FLAG_OVERVIEW_ACTIONS | FLAG_SHOW_AS_GRID
                     | FLAG_SCRIM | FLAG_LIVE_TILE | FLAG_RECENTS_VIEW_VISIBLE
-                    | FLAG_ADD_DESK_BUTTON);
+                    | FLAG_ADD_DESK_BUTTON | FLAG_SHOW_EXPLODED_DESKTOP_VIEW);
     public static final RecentsState MODAL_TASK = new ModalState(1,
             FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_ACTIONS | FLAG_MODAL
-                    | FLAG_SHOW_AS_GRID | FLAG_SCRIM | FLAG_LIVE_TILE | FLAG_RECENTS_VIEW_VISIBLE);
+                    | FLAG_SHOW_AS_GRID | FLAG_SCRIM | FLAG_LIVE_TILE | FLAG_RECENTS_VIEW_VISIBLE
+                    | FLAG_SHOW_EXPLODED_DESKTOP_VIEW);
     public static final RecentsState BACKGROUND_APP = new BackgroundAppState(2,
             FLAG_DISABLE_RESTORE | FLAG_NON_INTERACTIVE | FLAG_FULL_SCREEN
                     | FLAG_RECENTS_VIEW_VISIBLE | FLAG_TASK_THUMBNAIL_SPLASH
@@ -64,7 +67,7 @@
     public static final RecentsState BG_LAUNCHER = new LauncherState(4, 0);
     public static final RecentsState OVERVIEW_SPLIT_SELECT = new RecentsState(5,
             FLAG_SHOW_AS_GRID | FLAG_SCRIM | FLAG_RECENTS_VIEW_VISIBLE | FLAG_CLOSE_POPUPS
-                    | FLAG_DISABLE_RESTORE);
+                    | FLAG_DISABLE_RESTORE | FLAG_SHOW_EXPLODED_DESKTOP_VIEW);
 
     /** Returns the corresponding RecentsState from ordinal provided */
     public static RecentsState stateFromOrdinal(int ordinal) {
@@ -174,6 +177,11 @@
         return hasFlag(FLAG_DETACH_DESKTOP_CAROUSEL) && enableDesktopWindowingCarouselDetach();
     }
 
+    @Override
+    public boolean showExplodedDesktopView() {
+        return hasFlag(FLAG_SHOW_EXPLODED_DESKTOP_VIEW) && enableDesktopExplodedView();
+    }
+
     /**
      * True if the state has overview panel visible.
      */
diff --git a/quickstep/src/com/android/quickstep/task/util/TaskOverlayHelper.kt b/quickstep/src/com/android/quickstep/task/util/TaskOverlayHelper.kt
index d4f567e..d8aea9d 100644
--- a/quickstep/src/com/android/quickstep/task/util/TaskOverlayHelper.kt
+++ b/quickstep/src/com/android/quickstep/task/util/TaskOverlayHelper.kt
@@ -47,7 +47,7 @@
     private val recentsCoroutineScope: CoroutineScope = RecentsDependencies.get(scope)
     private val dispatcherProvider: DispatcherProvider = RecentsDependencies.get(scope)
     private lateinit var overlayInitializedScope: CoroutineScope
-    private var uiState: TaskOverlayUiState = Disabled
+    var uiState: TaskOverlayUiState = Disabled
 
     private lateinit var viewModel: TaskOverlayViewModel
 
@@ -61,7 +61,7 @@
 
     fun getThumbnailMatrix() = getThumbnailPositionState().matrix
 
-    private fun getThumbnailPositionState() =
+    fun getThumbnailPositionState() =
         viewModel.getThumbnailPositionState(
             overlay.snapshotView.width,
             overlay.snapshotView.height,
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 3b94380..ee519b5 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -1587,7 +1587,10 @@
                 == getPagedOrientationHandler().getPrimaryScroll(this);
     }
 
-    private boolean isFocusedTaskInExpectedScrollPosition() {
+    /**
+     * Returns true if the focused TaskView is in expected scroll position.
+     */
+    public boolean isFocusedTaskInExpectedScrollPosition() {
         TaskView focusedTask = getFocusedTaskView();
         return focusedTask != null && isTaskInExpectedScrollPosition(focusedTask);
     }
@@ -2925,12 +2928,15 @@
             updateGridProperties();
         }
 
+        BaseState<?> endState = mSizeStrategy.stateFromGestureEndTarget(endTarget);
+        // Starting the desk exploded animation when the gesture from an app is released.
         if (enableDesktopExplodedView()) {
             if (animatorSet == null) {
-                mUtils.setDeskExplodeProgress(1);
+                mUtils.setDeskExplodeProgress(endState.showExplodedDesktopView() ? 1f : 0f);
             } else {
                 animatorSet.play(
-                        ObjectAnimator.ofFloat(this, DESK_EXPLODE_PROGRESS, 1));
+                        ObjectAnimator.ofFloat(this, DESK_EXPLODE_PROGRESS,
+                                endState.showExplodedDesktopView() ? 1f : 0f));
             }
 
             for (TaskView taskView : getTaskViews()) {
@@ -2940,7 +2946,6 @@
             }
         }
 
-        BaseState<?> endState = mSizeStrategy.stateFromGestureEndTarget(endTarget);
         if (endState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile())) {
             TaskView runningTaskView = getRunningTaskView();
             float runningTaskGridTranslationX = 0;
@@ -3014,9 +3019,11 @@
         animateActionsViewIn();
 
         if (mEnableDrawingLiveTile) {
-            for (TaskView taskView : getTaskViews()) {
-                if (taskView instanceof DesktopTaskView desktopTaskView) {
-                    desktopTaskView.setRemoteTargetHandles(mRemoteTargetHandles);
+            if (enableDesktopExplodedView()) {
+                for (TaskView taskView : getTaskViews()) {
+                    if (taskView instanceof DesktopTaskView desktopTaskView) {
+                        desktopTaskView.setRemoteTargetHandles(mRemoteTargetHandles);
+                    }
                 }
             }
             TaskView runningTaskView = getRunningTaskView();
@@ -5780,6 +5787,9 @@
         if (taskView instanceof DesktopTaskView) {
             anim.play(ObjectAnimator.ofArgb(mContainer.getScrimView(), VIEW_BACKGROUND_COLOR,
                     Color.TRANSPARENT));
+            if (enableDesktopExplodedView()) {
+                anim.play(ObjectAnimator.ofFloat(this, DESK_EXPLODE_PROGRESS, 1f, 0f));
+            }
         }
         DepthController depthController = getDepthController();
         if (depthController != null) {
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.kt b/quickstep/src/com/android/quickstep/views/TaskMenuView.kt
index ed034d0..200fd52 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.kt
@@ -208,7 +208,7 @@
                 taskContainer.stagePosition,
             )
         // Gravity set to Left instead of Start as sTempRect.left measures Left distance not Start
-        params.gravity = Gravity.START
+        params.gravity = Gravity.LEFT
         layoutParams = params
         scaleX = taskView.scaleX
         scaleY = taskView.scaleY
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java
index 5ee5e10..74d76e6 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java
@@ -412,7 +412,12 @@
                 thumbnailDataAspect, MAX_PCT_BEFORE_ASPECT_RATIOS_CONSIDERED_DIFFERENT);
     }
 
-    private boolean isThumbnailRotationDifferentFromTask() {
+    /**
+     * Returns whether or not the current thumbnail is a different orientation to the task.
+     * <p>
+     * Used to disable modal state when screenshot doesn't match the device orientation.
+     */
+    public boolean isThumbnailRotationDifferentFromTask() {
         RecentsView recents = mTaskView.getRecentsView();
         if (recents == null || mThumbnailData == null) {
             return false;
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
index 08ce5e7..ec245ee 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
@@ -24,7 +24,6 @@
 import androidx.test.filters.LargeTest;
 
 import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
-import com.android.launcher3.util.rule.ScreenRecordRule;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -124,7 +123,6 @@
     }
 
     @Test
-    @ScreenRecordRule.ScreenRecord // b/373417111
     public void testLaunchShortcut_fromTaskbarAllApps() {
         getTaskbar().openAllApps()
                 .getAppIcon(TEST_APP_NAME)
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 2f1af68..74d5098 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -433,20 +433,29 @@
         @UiEvent(doc = "Notification dismissed by swiping right.")
         LAUNCHER_NOTIFICATION_DISMISSED(652),
 
-        @UiEvent(doc = "Current grid size is changed to 6.")
-        LAUNCHER_GRID_SIZE_6(930),
+        @UiEvent(doc = "Current grid size is changed to 2x2")
+        LAUNCHER_GRID_SIZE_2_BY_2(2181),
 
-        @UiEvent(doc = "Current grid size is changed to 5.")
-        LAUNCHER_GRID_SIZE_5(662),
+        @UiEvent(doc = "Current grid size is changed to 3x3")
+        LAUNCHER_GRID_SIZE_3_BY_3(2182),
 
-        @UiEvent(doc = "Current grid size is changed to 4.")
-        LAUNCHER_GRID_SIZE_4(663),
+        @UiEvent(doc = "Current grid size is changed to 4x4")
+        LAUNCHER_GRID_SIZE_4_BY_4(2183),
 
-        @UiEvent(doc = "Current grid size is changed to 3.")
-        LAUNCHER_GRID_SIZE_3(664),
+        @UiEvent(doc = "Current grid size is changed to 4x5")
+        LAUNCHER_GRID_SIZE_4_BY_5(2184),
 
-        @UiEvent(doc = "Current grid size is changed to 2.")
-        LAUNCHER_GRID_SIZE_2(665),
+        @UiEvent(doc = "Current grid size is changed to 4x6")
+        LAUNCHER_GRID_SIZE_4_BY_6(2185),
+
+        @UiEvent(doc = "Current grid size is changed to 5x5")
+        LAUNCHER_GRID_SIZE_5_BY_5(2186),
+
+        @UiEvent(doc = "Current grid size is changed to 5x6")
+        LAUNCHER_GRID_SIZE_5_BY_6(2187),
+
+        @UiEvent(doc = "Current grid size is changed to 6x5")
+        LAUNCHER_GRID_SIZE_6_BY_5(2188),
 
         @UiEvent(doc = "Launcher entered into AllApps state.")
         LAUNCHER_ALLAPPS_ENTRY(692),
diff --git a/src/com/android/launcher3/model/DeviceGridState.java b/src/com/android/launcher3/model/DeviceGridState.java
index d06f541..96ce4c8 100644
--- a/src/com/android/launcher3/model/DeviceGridState.java
+++ b/src/com/android/launcher3/model/DeviceGridState.java
@@ -21,11 +21,6 @@
 import static com.android.launcher3.LauncherPrefs.DEVICE_TYPE;
 import static com.android.launcher3.LauncherPrefs.HOTSEAT_COUNT;
 import static com.android.launcher3.LauncherPrefs.WORKSPACE_SIZE;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_2;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_3;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_4;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_5;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_6;
 
 import android.content.Context;
 import android.text.TextUtils;
@@ -114,17 +109,23 @@
      */
     public LauncherEvent getWorkspaceSizeEvent() {
         if (!TextUtils.isEmpty(mGridSizeString)) {
-            switch (getColumns()) {
-                case 6:
-                    return LAUNCHER_GRID_SIZE_6;
-                case 5:
-                    return LAUNCHER_GRID_SIZE_5;
-                case 4:
-                    return LAUNCHER_GRID_SIZE_4;
-                case 3:
-                    return LAUNCHER_GRID_SIZE_3;
-                case 2:
-                    return LAUNCHER_GRID_SIZE_2;
+            switch (mGridSizeString) {
+                case "2,2":
+                    return LauncherEvent.LAUNCHER_GRID_SIZE_2_BY_2;
+                case "3,3":
+                    return LauncherEvent.LAUNCHER_GRID_SIZE_3_BY_3;
+                case "4,4":
+                    return LauncherEvent.LAUNCHER_GRID_SIZE_4_BY_4;
+                case "4,5":
+                    return LauncherEvent.LAUNCHER_GRID_SIZE_4_BY_5;
+                case "4,6":
+                    return LauncherEvent.LAUNCHER_GRID_SIZE_4_BY_6;
+                case "5,5":
+                    return LauncherEvent.LAUNCHER_GRID_SIZE_5_BY_5;
+                case "5,6":
+                    return LauncherEvent.LAUNCHER_GRID_SIZE_5_BY_6;
+                case "6,5":
+                    return LauncherEvent.LAUNCHER_GRID_SIZE_6_BY_5;
             }
         }
         return null;
diff --git a/src/com/android/launcher3/statemanager/BaseState.java b/src/com/android/launcher3/statemanager/BaseState.java
index b7dd2bf..ea54159 100644
--- a/src/com/android/launcher3/statemanager/BaseState.java
+++ b/src/com/android/launcher3/statemanager/BaseState.java
@@ -69,6 +69,13 @@
     }
 
     /**
+     * For this state, whether we should show desktop exploded view in Overview.
+     */
+    default boolean showExplodedDesktopView() {
+        return false;
+    }
+
+    /**
      * For this state, whether fullscreen and desktop quickswitch carousel are detached.
      */
     default boolean detachDesktopCarousel() {