Merge "More logging for LogEventChecker appearing to skip events" into ub-launcher3-rvc-dev
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index e074b03..ceb7166 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -15,9 +15,16 @@
  */
 package com.android.launcher3.uioverrides;
 
+import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED;
+
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
+import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
+import static com.android.launcher3.testing.TestProtocol.HINT_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.QUICK_SWITCH_STATE_ORDINAL;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
 
 import android.content.Intent;
@@ -31,6 +38,8 @@
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
+import com.android.launcher3.Workspace;
+import com.android.launcher3.allapps.DiscoveryBounce;
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.folder.Folder;
@@ -56,7 +65,10 @@
 import com.android.quickstep.SysUINavigationMode.Mode;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.TaskView;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.stream.Stream;
 
@@ -174,6 +186,49 @@
     }
 
     @Override
+    public void onStateSetEnd(LauncherState state) {
+        super.onStateSetEnd(state);
+
+        switch (state.ordinal) {
+            case HINT_STATE_ORDINAL: {
+                Workspace workspace = getWorkspace();
+                boolean willMoveScreens = workspace.getNextPage() != Workspace.DEFAULT_PAGE;
+                getStateManager().goToState(NORMAL, true,
+                        willMoveScreens ? null : getScrimView()::startDragHandleEducationAnim);
+                if (willMoveScreens) {
+                    workspace.post(workspace::moveToDefaultScreen);
+                }
+                break;
+            }
+            case OVERVIEW_STATE_ORDINAL: {
+                DiscoveryBounce.showForOverviewIfNeeded(this);
+                RecentsView rv = getOverviewPanel();
+                sendCustomAccessibilityEvent(
+                        rv.getPageAt(rv.getCurrentPage()), TYPE_VIEW_FOCUSED, null);
+                break;
+            }
+            case QUICK_SWITCH_STATE_ORDINAL: {
+                RecentsView rv = getOverviewPanel();
+                TaskView tasktolaunch = rv.getTaskViewAt(0);
+                if (tasktolaunch != null) {
+                    tasktolaunch.launchTask(false, success -> {
+                        if (!success) {
+                            getStateManager().goToState(OVERVIEW);
+                            tasktolaunch.notifyTaskLaunchFailed(TAG);
+                        } else {
+                            getStateManager().moveToRestState();
+                        }
+                    }, MAIN_EXECUTOR.getHandler());
+                } else {
+                    getStateManager().goToState(NORMAL);
+                }
+                break;
+            }
+
+        }
+    }
+
+    @Override
     public TouchController[] createTouchControllers() {
         Mode mode = SysUINavigationMode.getMode(this);
 
@@ -233,4 +288,13 @@
             mActivity.getStateManager().setCurrentUserControlledAnimation(animController);
         }
     }
+
+    @Override
+    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+        super.dump(prefix, fd, writer, args);
+        RecentsView recentsView = getOverviewPanel();
+        writer.println("\nQuickstepLauncher:");
+        writer.println(prefix + "\tmOrientationState: " + (recentsView == null ? "recentsNull" :
+                recentsView.getPagedViewOrientedState()));
+    }
 }
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
index e57e841..357e9ec 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
@@ -17,22 +17,19 @@
 
 import android.content.Context;
 
-import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.allapps.AllAppsTransitionController;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.quickstep.util.LayoutUtils;
 import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.TaskView;
 
 /**
  * State indicating that the Launcher is behind an app
  */
 public class BackgroundAppState extends OverviewState {
 
-    private static final int STATE_FLAGS =
-            FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_DISABLE_ACCESSIBILITY
-                    | FLAG_DISABLE_INTERACTION;
+    private static final int STATE_FLAGS = FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI
+            | FLAG_WORKSPACE_INACCESSIBLE | FLAG_NON_INTERACTIVE | FLAG_CLOSE_POPUPS;
 
     public BackgroundAppState(int id) {
         this(id, LauncherLogProto.ContainerType.TASKSWITCHER);
@@ -43,11 +40,6 @@
     }
 
     @Override
-    public void onStateEnabled(Launcher launcher) {
-        AbstractFloatingView.closeAllOpenViews(launcher, false);
-    }
-
-    @Override
     public float getVerticalProgress(Launcher launcher) {
         if (launcher.getDeviceProfile().isVerticalBarLayout()) {
             return super.getVerticalProgress(launcher);
@@ -66,23 +58,7 @@
     }
 
     private float getOverviewScale(Launcher launcher) {
-        // Initialize the recents view scale to what it would be when starting swipe up
-        RecentsView recentsView = launcher.getOverviewPanel();
-        int taskCount = recentsView.getTaskViewCount();
-        if (taskCount == 0) return 1;
-
-        TaskView dummyTask;
-        if (recentsView.getCurrentPage() >= recentsView.getTaskViewStartIndex()) {
-            if (recentsView.getCurrentPage() <= taskCount - 1) {
-                dummyTask = recentsView.getCurrentPageTaskView();
-            } else {
-                dummyTask = recentsView.getTaskViewAt(taskCount - 1);
-            }
-        } else {
-            dummyTask = recentsView.getTaskViewAt(0);
-        }
-        return recentsView.getTempAppWindowAnimationHelper()
-                .updateForFullscreenOverview(dummyTask).getSrcToTargetScale();
+        return ((RecentsView) launcher.getOverviewPanel()).getMaxScaleForFullScreen();
     }
 
     @Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
index 868273a..4e868b0 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
@@ -15,6 +15,7 @@
  */
 package com.android.launcher3.uioverrides.states;
 
+import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Rect;
 
@@ -30,14 +31,14 @@
 public class OverviewModalTaskState extends OverviewState {
 
     private static final int STATE_FLAGS =
-            FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_DISABLE_ACCESSIBILITY;
+            FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_WORKSPACE_INACCESSIBLE;
 
     public OverviewModalTaskState(int id) {
         super(id, ContainerType.OVERVIEW, STATE_FLAGS);
     }
 
     @Override
-    public int getTransitionDuration(Launcher launcher) {
+    public int getTransitionDuration(Context launcher) {
         return 300;
     }
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
index fad9ea5..6f57281 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -37,17 +37,13 @@
 import android.content.Context;
 import android.graphics.Rect;
 import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.Interpolator;
 
-import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.R;
 import com.android.launcher3.Workspace;
-import com.android.launcher3.allapps.DiscoveryBounce;
-import com.android.launcher3.compat.AccessibilityManagerCompat;
 import com.android.launcher3.states.StateAnimationConfig;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -67,7 +63,8 @@
     protected static final Rect sTempRect = new Rect();
 
     private static final int STATE_FLAGS = FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED
-            | FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_DISABLE_ACCESSIBILITY;
+            | FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_WORKSPACE_INACCESSIBLE
+            | FLAG_CLOSE_POPUPS;
 
     public OverviewState(int id) {
         this(id, STATE_FLAGS);
@@ -82,9 +79,9 @@
     }
 
     @Override
-    public int getTransitionDuration(Launcher launcher) {
+    public int getTransitionDuration(Context context) {
         // In no-button mode, overview comes in all the way from the left, so give it more time.
-        boolean isNoButtonMode = SysUINavigationMode.INSTANCE.get(launcher).getMode() == NO_BUTTON;
+        boolean isNoButtonMode = SysUINavigationMode.INSTANCE.get(context).getMode() == NO_BUTTON;
         return isNoButtonMode && ENABLE_OVERVIEW_ACTIONS.get() ? 380 : 250;
     }
 
@@ -137,20 +134,6 @@
     }
 
     @Override
-    public void onStateEnabled(Launcher launcher) {
-        AbstractFloatingView.closeAllOpenViews(launcher);
-    }
-
-    @Override
-    public void onStateTransitionEnd(Launcher launcher) {
-        DiscoveryBounce.showForOverviewIfNeeded(launcher);
-        RecentsView recentsView = launcher.getOverviewPanel();
-        AccessibilityManagerCompat.sendCustomAccessibilityEvent(
-                recentsView.getPageAt(recentsView.getCurrentPage()),
-                AccessibilityEvent.TYPE_VIEW_FOCUSED, null);
-    }
-
-    @Override
     public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
         return new PageAlphaProvider(DEACCEL_2) {
             @Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java
index 7b4bb02..2c7373e 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java
@@ -15,24 +15,16 @@
  */
 package com.android.launcher3.uioverrides.states;
 
-import android.os.Handler;
-import android.os.Looper;
-
 import com.android.launcher3.Launcher;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
-import com.android.quickstep.GestureState;
-import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.TaskView;
 
 /**
  * State to indicate we are about to launch a recent task. Note that this state is only used when
  * quick switching from launcher; quick switching from an app uses LauncherSwipeHandler.
- * @see GestureState.GestureEndTarget#NEW_TASK
+ * @see com.android.quickstep.GestureState.GestureEndTarget#NEW_TASK
  */
 public class QuickSwitchState extends BackgroundAppState {
 
-    private static final String TAG = "QuickSwitchState";
-
     public QuickSwitchState(int id) {
         super(id, LauncherLogProto.ContainerType.APP);
     }
@@ -49,21 +41,4 @@
     public int getVisibleElements(Launcher launcher) {
         return NONE;
     }
-
-    @Override
-    public void onStateTransitionEnd(Launcher launcher) {
-        TaskView tasktolaunch = launcher.<RecentsView>getOverviewPanel().getTaskViewAt(0);
-        if (tasktolaunch != null) {
-            tasktolaunch.launchTask(false, success -> {
-                if (!success) {
-                    launcher.getStateManager().goToState(OVERVIEW);
-                    tasktolaunch.notifyTaskLaunchFailed(TAG);
-                } else {
-                    launcher.getStateManager().moveToRestState();
-                }
-            }, new Handler(Looper.getMainLooper()));
-        } else {
-            launcher.getStateManager().goToState(NORMAL);
-        }
-    }
 }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
index d22e5af..9540ccf 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
@@ -26,7 +26,6 @@
 import android.annotation.TargetApi;
 import android.content.Context;
 import android.content.Intent;
-import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.RectF;
@@ -265,8 +264,7 @@
         if (targets.minimizedHomeBounds != null && runningTaskTarget != null) {
             overviewStackBounds = mActivityInterface
                     .getOverviewWindowBounds(targets.minimizedHomeBounds, runningTaskTarget);
-            dp = dp.getMultiWindowProfile(mContext, new Point(
-                    overviewStackBounds.width(), overviewStackBounds.height()));
+            dp = dp.getMultiWindowProfile(mContext, overviewStackBounds);
         } else {
             // If we are not in multi-window mode, home insets should be same as system insets.
             dp = dp.copy(mContext);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
index 2214dd0..5ae45b9 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
@@ -18,6 +18,7 @@
 import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
 import static com.android.quickstep.fallback.FallbackRecentsView.ZOOM_PROGRESS;
+import static com.android.quickstep.util.WindowSizeStrategy.FALLBACK_RECENTS_SIZE_STRATEGY;
 import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
 
 import android.animation.Animator;
@@ -36,7 +37,6 @@
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.quickstep.fallback.FallbackRecentsView;
 import com.android.quickstep.util.ActivityInitListener;
-import com.android.quickstep.util.LayoutUtils;
 import com.android.quickstep.views.RecentsView;
 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
 
@@ -60,7 +60,7 @@
 
     @Override
     public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
-        LayoutUtils.calculateFallbackTaskSize(context, dp, outRect);
+        FALLBACK_RECENTS_SIZE_STRATEGY.calculateTaskSize(context, dp, outRect);
         if (dp.isVerticalBarLayout()
                 && SysUINavigationMode.INSTANCE.get(context).getMode() != NO_BUTTON) {
             Rect targetInsets = dp.getInsets();
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
index b4764dc..726322b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
@@ -26,6 +26,7 @@
 import static com.android.launcher3.anim.Interpolators.INSTANT;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.quickstep.LauncherSwipeHandler.RECENTS_ATTACH_DURATION;
+import static com.android.quickstep.util.WindowSizeStrategy.LAUNCHER_ACTIVITY_SIZE_STRATEGY;
 import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
 
 import android.animation.Animator;
@@ -82,7 +83,7 @@
 
     @Override
     public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
-        LayoutUtils.calculateLauncherTaskSize(context, dp, outRect);
+        LAUNCHER_ACTIVITY_SIZE_STRATEGY.calculateTaskSize(context, dp, outRect);
         if (dp.isVerticalBarLayout() && SysUINavigationMode.getMode(context) != Mode.NO_BUTTON) {
             Rect targetInsets = dp.getInsets();
             int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right;
@@ -211,7 +212,7 @@
         final LauncherState startState = launcher.getStateManager().getState();
 
         LauncherState resetState = startState;
-        if (startState.disableRestore) {
+        if (startState.shouldDisableRestore()) {
             resetState = launcher.getStateManager().getRestState();
         }
         launcher.getStateManager().setRestState(resetState);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
index 52b40a9..aef055a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
@@ -37,6 +37,7 @@
 import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
 import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.HIDE;
 import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.PEEK;
+import static com.android.quickstep.util.WindowSizeStrategy.LAUNCHER_ACTIVITY_SIZE_STRATEGY;
 import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
 
 import android.animation.Animator;
@@ -80,7 +81,6 @@
 import com.android.quickstep.inputconsumers.OverviewInputConsumer;
 import com.android.quickstep.util.ActiveGestureLog;
 import com.android.quickstep.util.AppWindowAnimationHelper.TargetAlphaProvider;
-import com.android.quickstep.util.LayoutUtils;
 import com.android.quickstep.util.RectFSpringAnim;
 import com.android.quickstep.util.ShelfPeekAnim;
 import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
@@ -208,8 +208,7 @@
         mTaskAnimationManager = taskAnimationManager;
         mTouchTimeMs = touchTimeMs;
         mContinuingLastGesture = continuingLastGesture;
-        mTaskViewSimulator = new TaskViewSimulator(
-                context, LayoutUtils::calculateLauncherTaskSize, true);
+        mTaskViewSimulator = new TaskViewSimulator(context, LAUNCHER_ACTIVITY_SIZE_STRATEGY);
 
         initAfterSubclassConstructor();
         initStateCallbacks();
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
index 52a2558..ff47f2c 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
@@ -121,7 +121,7 @@
     protected DeviceProfile createDeviceProfile() {
         DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(this).getDeviceProfile(this);
         return (mRecentsRootView != null) && isInMultiWindowMode()
-                ? dp.getMultiWindowProfile(this, mRecentsRootView.getLastKnownSize())
+                ? dp.getMultiWindowProfile(this, getMultiWindowDisplaySize())
                 : super.createDeviceProfile();
     }
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 3cf9b2c..559004c 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -16,22 +16,19 @@
 package com.android.quickstep.fallback;
 
 import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+import static com.android.quickstep.util.WindowSizeStrategy.FALLBACK_RECENTS_SIZE_STRATEGY;
 
 import android.app.ActivityManager.RunningTaskInfo;
 import android.content.Context;
 import android.graphics.Canvas;
-import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
 import android.view.View;
 
-import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Utilities;
 import com.android.quickstep.RecentsActivity;
-import com.android.quickstep.util.LayoutUtils;
 import com.android.quickstep.views.OverviewActionsView;
 import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.Task.TaskKey;
 
@@ -65,7 +62,7 @@
     }
 
     public FallbackRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr, false);
+        super(context, attrs, defStyleAttr, FALLBACK_RECENTS_SIZE_STRATEGY);
     }
 
     @Override
@@ -105,11 +102,6 @@
     }
 
     @Override
-    protected void getTaskSize(DeviceProfile dp, Rect outRect) {
-        LayoutUtils.calculateFallbackTaskSize(getContext(), dp, outRect);
-    }
-
-    @Override
     public boolean shouldUseMultiWindowTaskSizeStrategy() {
         // Just use the activity task size for multi-window as well.
         return false;
@@ -140,16 +132,7 @@
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
-
-        if (getTaskViewCount() == 0) {
-            mZoomScale = 1f;
-        } else {
-            TaskView dummyTask = getTaskViewAt(0);
-            mZoomScale = getTempAppWindowAnimationHelper()
-                    .updateForFullscreenOverview(dummyTask)
-                    .getSrcToTargetScale();
-        }
-
+        mZoomScale = getMaxScaleForFullScreen();
         setZoomProgress(mZoomInProgress);
     }
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
index 9781300..17284b0 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -61,7 +61,7 @@
 
     private final RecentsOrientedState mOrientationState;
     private final Context mContext;
-    private final TaskSizeProvider mSizeProvider;
+    private final WindowSizeStrategy mSizeStrategy;
 
     private final Rect mTaskRect = new Rect();
     private final PointF mPivot = new PointF();
@@ -95,14 +95,12 @@
     private boolean mLayoutValid = false;
     private boolean mScrollValid = false;
 
-    public TaskViewSimulator(Context context, TaskSizeProvider sizeProvider,
-            boolean rotationSupportedByActivity) {
+    public TaskViewSimulator(Context context, WindowSizeStrategy sizeStrategy) {
         mContext = context;
-        mSizeProvider = sizeProvider;
+        mSizeStrategy = sizeStrategy;
         mPositionHelper = new PreviewPositionHelper(context);
 
-        mOrientationState = new RecentsOrientedState(context, rotationSupportedByActivity,
-                i -> { });
+        mOrientationState = new RecentsOrientedState(context, sizeStrategy, i -> { });
         // We do not need to attach listeners as the simulator is created just for the gesture
         // duration, and any settings are unlikely to change during this
         mOrientationState.initWithoutListeners();
@@ -116,6 +114,7 @@
      */
     public void setDp(DeviceProfile dp, boolean isOpening) {
         mDp = dp;
+        mOrientationState.setMultiWindowMode(mDp.isMultiWindowMode);
         mBoostModeTargetLayers = isOpening ? MODE_OPENING : MODE_CLOSING;
         mLayoutValid = false;
     }
@@ -143,7 +142,7 @@
         if (mDp == null) {
             return 1;
         }
-        mSizeProvider.calculateTaskSize(mContext, mDp, mTaskRect);
+        mSizeStrategy.calculateTaskSize(mContext, mDp, mTaskRect);
         return mOrientationState.getFullScreenScaleAndPivot(mTaskRect, mDp, mPivot);
     }
 
@@ -161,8 +160,7 @@
 
         mThumbnailPosition.set(runningTarget.screenSpaceBounds);
         // TODO: Should sourceContainerBounds already have this offset?
-        mThumbnailPosition.offsetTo(mRunningTarget.position.x, mRunningTarget.position.y);
-
+        mThumbnailPosition.offset(-mRunningTarget.position.x, -mRunningTarget.position.y);
         mLayoutValid = false;
     }
 
@@ -198,7 +196,7 @@
                     ? mOrientationState.getDisplayRotation() : mPositionHelper.getCurrentRotation();
 
             mPositionHelper.updateThumbnailMatrix(mThumbnailPosition, mThumbnailData,
-                    mDp.isMultiWindowMode, mTaskRect.width(), mTaskRect.height());
+                    mTaskRect.width(), mTaskRect.height(), mDp);
 
             mPositionHelper.getMatrix().invert(mInversePositionMatrix);
 
@@ -209,6 +207,7 @@
             mScrollValid = false;
         }
 
+
         if (!mScrollValid) {
             mScrollValid = true;
             int start = mOrientationState.getOrientationHandler()
@@ -243,6 +242,8 @@
         postDisplayRotation(deltaRotation(
                 mOrientationState.getLauncherRotation(), mOrientationState.getDisplayRotation()),
                 mDp.widthPx, mDp.heightPx, mMatrix);
+        mMatrix.postTranslate(mDp.windowX - mRunningTarget.position.x,
+                mDp.windowY - mRunningTarget.position.y);
 
         // Crop rect is the inverse of thumbnail matrix
         mTempRectF.set(-insets.left, -insets.top,
@@ -298,16 +299,4 @@
         // Ideally we should use square-root. This is an optimization as one of the dimension is 0.
         return Math.max(Math.abs(mTempPoint[0]), Math.abs(mTempPoint[1]));
     }
-
-    /**
-     * Interface for calculating taskSize
-     */
-    public interface TaskSizeProvider {
-
-        /**
-         * Sets the outRect to the expected taskSize
-         */
-        void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect);
-    }
-
 }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/ClearAllButton.java
index e455939..1018211 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/ClearAllButton.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/ClearAllButton.java
@@ -56,7 +56,8 @@
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
-        mScrollOffset = mIsRtl ? mParent.getPaddingRight() / 2 : - mParent.getPaddingLeft() / 2;
+        PagedOrientationHandler orientationHandler = mParent.getPagedOrientationHandler();
+        mScrollOffset = orientationHandler.getClearAllScrollOffset(mParent, mIsRtl);
     }
 
     @Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
index 9005651..aafad0c 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -25,6 +25,7 @@
 import static com.android.launcher3.QuickstepAppTransitionManagerImpl.ALL_APPS_PROGRESS_OFF_SCREEN;
 import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
+import static com.android.quickstep.util.WindowSizeStrategy.LAUNCHER_ACTIVITY_SIZE_STRATEGY;
 
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
@@ -39,7 +40,6 @@
 import android.widget.FrameLayout;
 
 import com.android.launcher3.BaseQuickstepLauncher;
-import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Hotseat;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.LauncherStateManager.StateListener;
@@ -53,7 +53,6 @@
 import com.android.quickstep.SysUINavigationMode;
 import com.android.quickstep.util.AppWindowAnimationHelper;
 import com.android.quickstep.util.AppWindowAnimationHelper.TransformParams;
-import com.android.quickstep.util.LayoutUtils;
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.plugins.RecentsExtraCard;
 
@@ -96,7 +95,7 @@
     }
 
     public LauncherRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr, true);
+        super(context, attrs, defStyleAttr, LAUNCHER_ACTIVITY_SIZE_STRATEGY);
         mActivity.getStateManager().addStateListener(this);
     }
 
@@ -179,11 +178,6 @@
     }
 
     @Override
-    protected void getTaskSize(DeviceProfile dp, Rect outRect) {
-        LayoutUtils.calculateLauncherTaskSize(getContext(), dp, outRect);
-    }
-
-    @Override
     protected void onTaskLaunchAnimationUpdate(float progress, TaskView tv) {
         if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             if (tv.isRunningTask()) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index cd3abed..955cf5a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -122,6 +122,7 @@
 import com.android.quickstep.ViewUtils;
 import com.android.quickstep.util.AppWindowAnimationHelper;
 import com.android.quickstep.util.RecentsOrientedState;
+import com.android.quickstep.util.WindowSizeStrategy;
 import com.android.systemui.plugins.ResourceProvider;
 import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
 import com.android.systemui.shared.recents.model.Task;
@@ -202,6 +203,7 @@
             };
 
     protected final RecentsOrientedState mOrientationState;
+    protected final WindowSizeStrategy mSizeStrategy;
     protected RecentsAnimationController mRecentsAnimationController;
     protected RecentsAnimationTargets mRecentsAnimationTargets;
     protected AppWindowAnimationHelper mAppWindowAnimationHelper;
@@ -212,6 +214,7 @@
     protected final Rect mTempRect = new Rect();
     protected final RectF mTempRectF = new RectF();
     private final PointF mTempPointF = new PointF();
+    private final float[] mTempFloatPoint = new float[2];
 
     private static final int DISMISS_TASK_DURATION = 300;
     private static final int ADDITION_TASK_DURATION = 200;
@@ -225,7 +228,6 @@
     private final ClearAllButton mClearAllButton;
     private final Rect mClearAllButtonDeadZoneRect = new Rect();
     private final Rect mTaskViewDeadZoneRect = new Rect();
-    protected final AppWindowAnimationHelper mTempAppWindowAnimationHelper;
 
     private final ScrollState mScrollState = new ScrollState();
     // Keeps track of the previously known visible tasks for purposes of loading/unloading task data
@@ -373,20 +375,19 @@
     };
 
     public RecentsView(Context context, AttributeSet attrs, int defStyleAttr,
-            boolean rotationSupportedByActivity) {
+            WindowSizeStrategy sizeStrategy) {
         super(context, attrs, defStyleAttr);
         setPageSpacing(getResources().getDimensionPixelSize(R.dimen.recents_page_spacing));
         setEnableFreeScroll(true);
+        mSizeStrategy = sizeStrategy;
         mOrientationState = new RecentsOrientedState(
-                context, rotationSupportedByActivity, this::animateRecentsRotationInPlace);
+                context, mSizeStrategy, this::animateRecentsRotationInPlace);
 
         mFastFlingVelocity = getResources()
                 .getDimensionPixelSize(R.dimen.recents_fast_fling_velocity);
         mActivity = BaseActivity.fromContext(context);
         mModel = RecentsModel.INSTANCE.get(context);
         mIdp = InvariantDeviceProfile.INSTANCE.get(context);
-        mTempAppWindowAnimationHelper =
-            new AppWindowAnimationHelper(getPagedViewOrientedState(), context);
 
         mClearAllButton = (ClearAllButton) LayoutInflater.from(context)
                 .inflate(R.layout.overview_clear_all_button, this, false);
@@ -712,7 +713,7 @@
             final int pageIndex = requiredTaskCount - i - 1 + mTaskViewStartIndex;
             final Task task = tasks.get(i);
             final TaskView taskView = (TaskView) getChildAt(pageIndex);
-            taskView.bind(task, mOrientationState, mActivity.getDeviceProfile().isMultiWindowMode);
+            taskView.bind(task, mOrientationState);
         }
 
         if (mNextPage == INVALID_PAGE) {
@@ -802,7 +803,8 @@
     public void setInsets(Rect insets) {
         mInsets.set(insets);
         DeviceProfile dp = mActivity.getDeviceProfile();
-        getTaskSize(dp, mTempRect);
+        mOrientationState.setMultiWindowMode(dp.isMultiWindowMode);
+        getTaskSize(mTempRect);
         mTaskWidth = mTempRect.width();
         mTaskHeight = mTempRect.height();
 
@@ -812,10 +814,8 @@
                 dp.heightPx - mInsets.bottom - mTempRect.bottom);
     }
 
-    protected abstract void getTaskSize(DeviceProfile dp, Rect outRect);
-
     public void getTaskSize(Rect outRect) {
-        getTaskSize(mActivity.getDeviceProfile(), outRect);
+        mSizeStrategy.calculateTaskSize(mActivity, mActivity.getDeviceProfile(), outRect);
     }
 
     @Override
@@ -1068,8 +1068,7 @@
                     new ComponentName(getContext(), getClass()), 0, 0), null, null, "", "", 0, 0,
                     false, true, false, false, new ActivityManager.TaskDescription(), 0,
                     new ComponentName("", ""), false);
-            taskView.bind(mTmpRunningTask, mOrientationState,
-                    mActivity.getDeviceProfile().isMultiWindowMode);
+            taskView.bind(mTmpRunningTask, mOrientationState);
         }
 
         boolean runningTaskTileHidden = mRunningTaskTileHidden;
@@ -1653,6 +1652,7 @@
                 mTempRect, mActivity.getDeviceProfile(), mTempPointF);
         setPivotX(mTempPointF.x);
         setPivotY(mTempPointF.y);
+        setTaskModalness(mTaskModalness);
         updatePageOffsets();
     }
 
@@ -1764,7 +1764,7 @@
         int centerTaskIndex = getCurrentPage();
         boolean launchingCenterTask = taskIndex == centerTaskIndex;
 
-        float toScale = appWindowAnimationHelper.getSrcToTargetScale();
+        float toScale = getMaxScaleForFullScreen();
         if (launchingCenterTask) {
             RecentsView recentsView = tv.getRecentsView();
             anim.play(ObjectAnimator.ofFloat(recentsView, SCALE_PROPERTY, toScale));
@@ -1786,6 +1786,15 @@
         return anim;
     }
 
+    /**
+     * Returns the scale up required on the view, so that it coves the screen completely
+     */
+    public float getMaxScaleForFullScreen() {
+        getTaskSize(mTempRect);
+        return getPagedViewOrientedState().getFullScreenScaleAndPivot(
+                mTempRect, mActivity.getDeviceProfile(), mTempPointF);
+    }
+
     public PendingAnimation createTaskLaunchAnimation(
             TaskView tv, long duration, Interpolator interpolator) {
         if (FeatureFlags.IS_STUDIO_BUILD && mPendingAnimation != null) {
@@ -2079,10 +2088,6 @@
         return mAppWindowAnimationHelper;
     }
 
-    public AppWindowAnimationHelper getTempAppWindowAnimationHelper() {
-        return mTempAppWindowAnimationHelper;
-    }
-
     public AppWindowAnimationHelper.TransformParams getLiveTileParams(
             boolean mightNeedToRefill) {
         return null;
@@ -2128,6 +2133,18 @@
         updatePageOffsets();
         if (getCurrentPageTaskView() != null) {
             getCurrentPageTaskView().setModalness(modalness);
+            TaskView tv = getCurrentPageTaskView();
+
+            // Move the task view up as it scales...
+            // ...the icon on taskview is hidden in modal state, so consider the top of the task
+            mTempFloatPoint[0] = 0;
+            mTempFloatPoint[1] = tv.getTop() + mTaskTopMargin;
+            // ...find the top after the transformation
+            getMatrix().mapPoints(mTempFloatPoint);
+
+            // ...make it match the top inset
+            float calcOffset = (mInsets.top - mTempFloatPoint[1]) * mTaskModalness;
+            tv.setTranslationY(calcOffset);
         }
     }
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
index e525842..aa08e86 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -36,12 +36,12 @@
 import android.graphics.Shader;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
-import android.util.Log;
 import android.util.Property;
 import android.view.Surface;
 import android.view.View;
 
 import com.android.launcher3.BaseActivity;
+import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
@@ -104,7 +104,6 @@
 
     private boolean mOverlayEnabled;
     private OverviewScreenshotActions mOverviewScreenshotActionsPlugin;
-    private boolean mIsMultiWindowMode;
 
     public TaskThumbnailView(Context context) {
         this(context, null);
@@ -126,8 +125,11 @@
         mPreviewPositionHelper = new PreviewPositionHelper(context);
     }
 
-    public void bind(Task task, boolean isMultiWindowMode) {
-        mIsMultiWindowMode = isMultiWindowMode;
+    /**
+     * Updates the thumbnail to draw the provided task
+     * @param task
+     */
+    public void bind(Task task) {
         mOverlay.reset();
         mTask = task;
         int color = task == null ? Color.BLACK : task.colorBackground | 0xFF000000;
@@ -353,7 +355,7 @@
             mPreviewRect.set(0, 0, mThumbnailData.thumbnail.getWidth(),
                     mThumbnailData.thumbnail.getHeight());
             mPreviewPositionHelper.updateThumbnailMatrix(mPreviewRect, mThumbnailData,
-                    mIsMultiWindowMode, getMeasuredWidth(), getMeasuredHeight());
+                    getMeasuredWidth(), getMeasuredHeight(), mActivity.getDeviceProfile());
 
             mBitmapShader.setLocalMatrix(mPreviewPositionHelper.mMatrix);
             mPaint.setShader(mBitmapShader);
@@ -439,13 +441,14 @@
          * Updates the matrix based on the provided parameters
          */
         public void updateThumbnailMatrix(Rect thumbnailPosition, ThumbnailData thumbnailData,
-                boolean isInMultiWindowMode, int canvasWidth, int canvasHeight) {
+                int canvasWidth, int canvasHeight, DeviceProfile dp) {
             boolean isRotated = false;
             boolean isOrientationDifferent;
             mClipBottom = -1;
 
             float scale = thumbnailData.scale;
             Rect thumbnailInsets = thumbnailData.insets;
+
             final float thumbnailWidth = thumbnailPosition.width()
                     - (thumbnailInsets.left + thumbnailInsets.right) * scale;
             final float thumbnailHeight = thumbnailPosition.height()
@@ -456,8 +459,9 @@
             int currentRotation = getCurrentRotation();
             int deltaRotate = getRotationDelta(currentRotation, thumbnailRotation);
 
+            Rect deviceInsets = dp.getInsets();
             // Landscape vs portrait change
-            boolean windowingModeSupportsRotation = !isInMultiWindowMode
+            boolean windowingModeSupportsRotation = !dp.isMultiWindowMode
                     && thumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN;
             isOrientationDifferent = isOrientationChange(deltaRotate)
                     && windowingModeSupportsRotation;
@@ -476,9 +480,10 @@
 
             if (!isRotated) {
                 // No Rotation
-                mClippedInsets.offsetTo(thumbnailInsets.left * scale,
-                        thumbnailInsets.top * scale);
-                mMatrix.setTranslate(-mClippedInsets.left, -mClippedInsets.top);
+                mClippedInsets.offsetTo(deviceInsets.left * scale, deviceInsets.top * scale);
+                mMatrix.setTranslate(
+                        -thumbnailInsets.left * scale,
+                        -thumbnailInsets.top * scale);
             } else {
                 setThumbnailRotation(deltaRotate, thumbnailInsets, scale, thumbnailPosition);
             }
@@ -495,8 +500,16 @@
             }
             mClippedInsets.left *= thumbnailScale;
             mClippedInsets.top *= thumbnailScale;
-            mClippedInsets.right = widthWithInsets - mClippedInsets.left - canvasWidth;
-            mClippedInsets.bottom = heightWithInsets - mClippedInsets.top - canvasHeight;
+
+            if (dp.isMultiWindowMode) {
+                mClippedInsets.right = deviceInsets.right * scale * thumbnailScale;
+                mClippedInsets.bottom = deviceInsets.bottom * scale * thumbnailScale;
+            } else {
+                mClippedInsets.right = Math.max(0,
+                        widthWithInsets - mClippedInsets.left - canvasWidth);
+                mClippedInsets.bottom = Math.max(0,
+                        heightWithInsets - mClippedInsets.top - canvasHeight);
+            }
 
             mMatrix.postScale(thumbnailScale, thumbnailScale);
 
@@ -557,9 +570,8 @@
         /**
          * Insets to used for clipping the thumbnail (in case it is drawing outside its own space)
          */
-        public RectF getInsetsToDrawInFullscreen(boolean isMultiWindowMode) {
-            // Don't show insets in multi window mode.
-            return isMultiWindowMode ? EMPTY_RECT_F : mClippedInsets;
+        public RectF getInsetsToDrawInFullscreen() {
+            return mClippedInsets;
         }
     }
 }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index aea5b8e..f8f927b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -274,10 +274,10 @@
      * TODO(b/142282126) Re-evaluate if we need to pass in isMultiWindowMode after
      *   that issue is fixed
      */
-    public void bind(Task task, RecentsOrientedState orientedState, boolean isMultiWindowMode) {
+    public void bind(Task task, RecentsOrientedState orientedState) {
         cancelPendingLoadTasks();
         mTask = task;
-        mSnapshotView.bind(task, isMultiWindowMode);
+        mSnapshotView.bind(task);
         setOrientationState(orientedState);
     }
 
@@ -1017,14 +1017,13 @@
          */
         public void setProgress(float fullscreenProgress, float parentScale, int previewWidth,
                 DeviceProfile dp, PreviewPositionHelper pph) {
-            boolean isMultiWindowMode = dp.isMultiWindowMode;
-            RectF insets = pph.getInsetsToDrawInFullscreen(isMultiWindowMode);
+            RectF insets = pph.getInsetsToDrawInFullscreen();
 
             float currentInsetsLeft = insets.left * fullscreenProgress;
             float currentInsetsRight = insets.right * fullscreenProgress;
             mCurrentDrawnInsets.set(currentInsetsLeft, insets.top * fullscreenProgress,
                     currentInsetsRight, insets.bottom * fullscreenProgress);
-            float fullscreenCornerRadius = isMultiWindowMode ? 0 : mWindowCornerRadius;
+            float fullscreenCornerRadius = dp.isMultiWindowMode ? 0 : mWindowCornerRadius;
 
             mCurrentDrawnCornerRadius =
                     Utilities.mapRange(fullscreenProgress, mCornerRadius, fullscreenCornerRadius)
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index af63a25..3bb8b07 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -17,6 +17,7 @@
 
 import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
 import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON;
+import static com.android.launcher3.LauncherState.FLAG_HIDE_BACK_BUTTON;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
@@ -257,7 +258,7 @@
     private void onLauncherStateOrFocusChanged() {
         Mode mode = SysUINavigationMode.getMode(this);
         boolean shouldBackButtonBeHidden = mode.hasGestures
-                && getStateManager().getState().hideBackButton
+                && getStateManager().getState().hasFlag(FLAG_HIDE_BACK_BUTTON)
                 && hasWindowFocus()
                 && (getActivityFlags() & ACTIVITY_STATE_TRANSITION_ACTIVE) == 0;
         if (shouldBackButtonBeHidden) {
diff --git a/quickstep/src/com/android/launcher3/statehandlers/BackButtonAlphaHandler.java b/quickstep/src/com/android/launcher3/statehandlers/BackButtonAlphaHandler.java
index 983702a..9145191 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/BackButtonAlphaHandler.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/BackButtonAlphaHandler.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher3.statehandlers;
 
+import static com.android.launcher3.LauncherState.FLAG_HIDE_BACK_BUTTON;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.quickstep.AnimatedFloat.VALUE;
 
@@ -59,7 +60,8 @@
         }
 
         mBackAlpha.value = SystemUiProxy.INSTANCE.get(mLauncher).getLastBackButtonAlpha();
-        animation.setFloat(mBackAlpha, VALUE, toState.hideBackButton ? 0 : 1, LINEAR);
+        animation.setFloat(mBackAlpha, VALUE,
+                toState.hasFlag(FLAG_HIDE_BACK_BUTTON) ? 0 : 1, LINEAR);
     }
 
     private void updateBackAlpha() {
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
index 5f5d6dc..8c778c0 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
@@ -193,8 +193,17 @@
         if (windowToken != null) {
             mWallpaperManager.setWallpaperZoomOut(windowToken, mDepth);
         }
+        final int blur;
+        if (mLauncher.isInState(LauncherState.ALL_APPS) && mDepth == 1) {
+            // All apps has a solid background. We don't need to draw blurs after it's fully
+            // visible. This will take us out of GPU composition, saving battery and increasing
+            // performance.
+            blur = 0;
+        } else {
+            blur = (int) (mDepth * mMaxBlurRadius);
+        }
         new TransactionCompat()
-                .setBackgroundBlurRadius(mSurface, (int) (mDepth * mMaxBlurRadius))
+                .setBackgroundBlurRadius(mSurface, blur)
                 .apply();
     }
 }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
index ac50d6d..47fff5e 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
@@ -107,7 +107,7 @@
         setter.setFloat(
                 mRecentsView, getTaskModalnessProperty(),
                 toState.getOverviewModalness(),
-                config.getInterpolator(ANIM_OVERVIEW_MODAL, AGGRESSIVE_EASE_IN_OUT));
+                config.getInterpolator(ANIM_OVERVIEW_MODAL, LINEAR));
     }
 
     abstract FloatProperty getTaskModalnessProperty();
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index 81d4224..e7cd393 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -21,7 +21,6 @@
 
 import android.content.Context;
 
-import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.allapps.AllAppsContainerView;
@@ -33,7 +32,7 @@
  */
 public class AllAppsState extends LauncherState {
 
-    private static final int STATE_FLAGS = FLAG_DISABLE_ACCESSIBILITY;
+    private static final int STATE_FLAGS = FLAG_WORKSPACE_INACCESSIBLE | FLAG_CLOSE_POPUPS;
 
     private static final PageAlphaProvider PAGE_ALPHA_PROVIDER = new PageAlphaProvider(DEACCEL_2) {
         @Override
@@ -47,23 +46,11 @@
     }
 
     @Override
-    public int getTransitionDuration(Launcher launcher) {
+    public int getTransitionDuration(Context context) {
         return 320;
     }
 
     @Override
-    public void onStateEnabled(Launcher launcher) {
-        AbstractFloatingView.closeAllOpenViews(launcher);
-        dispatchWindowStateChanged(launcher);
-    }
-
-    @Override
-    public void onStateDisabled(Launcher launcher) {
-        super.onStateDisabled(launcher);
-        AbstractFloatingView.closeAllOpenViews(launcher);
-    }
-
-    @Override
     public String getDescription(Launcher launcher) {
         AllAppsContainerView appsView = launcher.getAppsView();
         return appsView.getDescription();
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
index 4edf2fb..14e5485 100644
--- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -17,31 +17,17 @@
 
 import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
 import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
-
-import static java.lang.annotation.RetentionPolicy.SOURCE;
+import static com.android.quickstep.util.WindowSizeStrategy.LAUNCHER_ACTIVITY_SIZE_STRATEGY;
 
 import android.content.Context;
-import android.content.res.Resources;
 import android.graphics.Rect;
 
-import androidx.annotation.AnyThread;
-import androidx.annotation.IntDef;
-
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
 import com.android.quickstep.SysUINavigationMode;
 
-import java.lang.annotation.Retention;
-
 public class LayoutUtils {
 
-    private static final int MULTI_WINDOW_STRATEGY_HALF_SCREEN = 1;
-    private static final int MULTI_WINDOW_STRATEGY_DEVICE_PROFILE = 2;
-
-    @Retention(SOURCE)
-    @IntDef({MULTI_WINDOW_STRATEGY_HALF_SCREEN, MULTI_WINDOW_STRATEGY_DEVICE_PROFILE})
-    private @interface MultiWindowStrategy {}
-
     /**
      * The height for the swipe up motion
      */
@@ -53,112 +39,11 @@
         return swipeHeight;
     }
 
-    public static void calculateLauncherTaskSize(Context context, DeviceProfile dp, Rect outRect) {
-        float extraSpace;
-        if (dp.isVerticalBarLayout()) {
-            extraSpace = 0;
-        } else {
-            Resources res = context.getResources();
-
-            if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context)) {
-                //TODO: this needs to account for the swipe gesture height and accessibility
-                // UI when shown.
-                extraSpace = res.getDimensionPixelSize(R.dimen.overview_actions_height);
-            } else {
-                extraSpace = getDefaultSwipeHeight(context, dp) + dp.workspacePageIndicatorHeight
-                        + res.getDimensionPixelSize(
-                                R.dimen.dynamic_grid_hotseat_extra_vertical_size)
-                        + res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
-            }
-        }
-        calculateTaskSize(context, dp, extraSpace, MULTI_WINDOW_STRATEGY_HALF_SCREEN, outRect);
-    }
-
-    public static void calculateFallbackTaskSize(Context context, DeviceProfile dp, Rect outRect) {
-        float extraSpace;
-        if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context)) {
-            extraSpace = context.getResources()
-                    .getDimensionPixelSize(R.dimen.overview_actions_height);
-        } else {
-            extraSpace = 0;
-        }
-        calculateTaskSize(context, dp, extraSpace, MULTI_WINDOW_STRATEGY_DEVICE_PROFILE, outRect);
-    }
-
-    @AnyThread
-    public static void calculateTaskSize(Context context, DeviceProfile dp,
-            float extraVerticalSpace, @MultiWindowStrategy int multiWindowStrategy, Rect outRect) {
-        float taskWidth, taskHeight, paddingHorz;
-        Resources res = context.getResources();
-        Rect insets = dp.getInsets();
-        final boolean overviewActionsEnabled = ENABLE_OVERVIEW_ACTIONS.get();
-
-        if (dp.isMultiWindowMode) {
-            if (multiWindowStrategy == MULTI_WINDOW_STRATEGY_HALF_SCREEN) {
-                DeviceProfile fullDp = dp.getFullScreenProfile();
-                // Use availableWidthPx and availableHeightPx instead of widthPx and heightPx to
-                // account for system insets
-                taskWidth = fullDp.availableWidthPx;
-                taskHeight = fullDp.availableHeightPx;
-                float halfDividerSize = res.getDimension(R.dimen.multi_window_task_divider_size)
-                        / 2;
-
-                if (fullDp.isLandscape) {
-                    taskWidth = taskWidth / 2 - halfDividerSize;
-                } else {
-                    taskHeight = taskHeight / 2 - halfDividerSize;
-                }
-            } else {
-                // multiWindowStrategy == MULTI_WINDOW_STRATEGY_DEVICE_PROFILE
-                taskWidth = dp.widthPx;
-                taskHeight = dp.heightPx;
-            }
-            paddingHorz = res.getDimension(R.dimen.multi_window_task_card_horz_space);
-        } else {
-            taskWidth = dp.availableWidthPx;
-            taskHeight = dp.availableHeightPx;
-
-            final int paddingResId;
-            if (dp.isVerticalBarLayout()) {
-                paddingResId = R.dimen.landscape_task_card_horz_space;
-            } else if (overviewActionsEnabled && removeShelfFromOverview(context)) {
-                paddingResId = R.dimen.portrait_task_card_horz_space_big_overview;
-            } else {
-                paddingResId = R.dimen.portrait_task_card_horz_space;
-            }
-            paddingHorz = res.getDimension(paddingResId);
-        }
-
-        float topIconMargin = res.getDimension(R.dimen.task_thumbnail_top_margin);
-        float paddingVert = overviewActionsEnabled && removeShelfFromOverview(context)
-                ? 0 : res.getDimension(R.dimen.task_card_vert_space);
-
-        // Note this should be same as dp.availableWidthPx and dp.availableHeightPx unless
-        // we override the insets ourselves.
-        int launcherVisibleWidth = dp.widthPx - insets.left - insets.right;
-        int launcherVisibleHeight = dp.heightPx - insets.top - insets.bottom;
-
-        float availableHeight = launcherVisibleHeight
-                - topIconMargin - extraVerticalSpace - paddingVert;
-        float availableWidth = launcherVisibleWidth - paddingHorz;
-
-        float scale = Math.min(availableWidth / taskWidth, availableHeight / taskHeight);
-        float outWidth = scale * taskWidth;
-        float outHeight = scale * taskHeight;
-
-        // Center in the visible space
-        float x = insets.left + (launcherVisibleWidth - outWidth) / 2;
-        float y = insets.top + Math.max(topIconMargin,
-                (launcherVisibleHeight - extraVerticalSpace - outHeight) / 2);
-        outRect.set(Math.round(x), Math.round(y),
-                Math.round(x) + Math.round(outWidth), Math.round(y) + Math.round(outHeight));
-    }
-
     public static int getShelfTrackingDistance(Context context, DeviceProfile dp) {
         // Track the bottom of the window.
         if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context)) {
             Rect taskSize = new Rect();
-            calculateLauncherTaskSize(context, dp, taskSize);
+            LAUNCHER_ACTIVITY_SIZE_STRATEGY.calculateTaskSize(context, dp, taskSize);
             return (dp.heightPx - taskSize.height()) / 2;
         }
         int shelfHeight = dp.hotseatBarSizePx + dp.getInsets().bottom;
@@ -169,6 +54,7 @@
 
     /**
      * Gets the scale that should be applied to the TaskView so that it matches the target
+     * TODO: Remove this method
      */
     public static float getTaskScale(RecentsOrientedState orientedState,
             float srcWidth, float srcHeight, float targetWidth, float targetHeight) {
diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
index 74daeca..5ca2095 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
+++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
@@ -44,6 +44,7 @@
 import android.view.Surface;
 
 import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Utilities;
@@ -64,7 +65,7 @@
 public final class RecentsOrientedState implements SharedPreferences.OnSharedPreferenceChangeListener {
 
     private static final String TAG = "RecentsOrientedState";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = true;
 
     private static final String FIXED_ROTATION_TRANSFORM_SETTING_NAME = "fixed_rotation_transform";
 
@@ -94,28 +95,29 @@
     private static final int FLAG_HOME_ROTATION_ALLOWED_IN_PREFS = 1 << 3;
     // If the user has enabled system rotation
     private static final int FLAG_SYSTEM_ROTATION_ALLOWED = 1 << 4;
+    // Multiple orientation is not supported in multiwindow mode
+    private static final int FLAG_MULTIWINDOW_ROTATION_ALLOWED = 1 << 5;
     // Whether to rotation sensor is supported on the device
-    private static final int FLAG_ROTATION_WATCHER_SUPPORTED = 1 << 5;
+    private static final int FLAG_ROTATION_WATCHER_SUPPORTED = 1 << 6;
     // Whether to enable rotation watcher when multi-rotation is supported
-    private static final int FLAG_ROTATION_WATCHER_ENABLED = 1 << 6;
+    private static final int FLAG_ROTATION_WATCHER_ENABLED = 1 << 7;
 
     private static final int MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE =
             FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY
             | FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_DENSITY
             | FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_FLAG;
 
-    private static final int MASK_ACTIVITY_ROTATING =
-            FLAG_HOME_ROTATION_ALLOWED_IN_PREFS | FLAG_SYSTEM_ROTATION_ALLOWED;
-
-    // State for which rotation watcher will be enabled.
-    // We skip it when home rotation is enabled as in that case, activity itself rotates
+    // State for which rotation watcher will be enabled. We skip it when home rotation or
+    // multi-window is enabled as in that case, activity itself rotates.
     private static final int VALUE_ROTATION_WATCHER_ENABLED =
             MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE | FLAG_SYSTEM_ROTATION_ALLOWED
                     | FLAG_ROTATION_WATCHER_SUPPORTED | FLAG_ROTATION_WATCHER_ENABLED;
 
+    private final Context mContext;
     private final ContentResolver mContentResolver;
     private final SharedPreferences mSharedPrefs;
     private final OrientationEventListener mOrientationListener;
+    private final WindowSizeStrategy mSizeStrategy;
 
     private final Matrix mTmpMatrix = new Matrix();
     private final Matrix mTmpInverseMatrix = new Matrix();
@@ -128,10 +130,12 @@
      *                              is enabled
      * @see #setRotationWatcherEnabled(boolean)
      */
-    public RecentsOrientedState(Context context, boolean rotationSupportedByActivity,
+    public RecentsOrientedState(Context context, WindowSizeStrategy sizeStrategy,
             IntConsumer rotationChangeListener) {
+        mContext = context;
         mContentResolver = context.getContentResolver();
         mSharedPrefs = Utilities.getPrefs(context);
+        mSizeStrategy = sizeStrategy;
         mOrientationListener = new OrientationEventListener(context) {
             @Override
             public void onOrientationChanged(int degrees) {
@@ -143,7 +147,8 @@
             }
         };
 
-        mFlags = rotationSupportedByActivity ? FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY : 0;
+        mFlags = sizeStrategy.rotationSupportedByActivity
+                ? FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY : 0;
 
         Resources res = context.getResources();
         int originalSmallestWidth = res.getConfiguration().smallestScreenWidthDp
@@ -160,6 +165,13 @@
     }
 
     /**
+     * Sets if the host is in multi-window mode
+     */
+    public void setMultiWindowMode(boolean isMultiWindow) {
+        setFlag(FLAG_MULTIWINDOW_ROTATION_ALLOWED, isMultiWindow);
+    }
+
+    /**
      * Sets the appropriate {@link PagedOrientationHandler} for {@link #mOrientationHandler}
      * @param touchRotation The rotation the nav bar region that is touched is in
      * @param displayRotation Rotation of the display/device
@@ -296,11 +308,12 @@
     }
 
     public boolean isHomeRotationAllowed() {
-        return (mFlags & FLAG_HOME_ROTATION_ALLOWED_IN_PREFS) != 0;
+        return (mFlags & (FLAG_HOME_ROTATION_ALLOWED_IN_PREFS | FLAG_MULTIWINDOW_ROTATION_ALLOWED))
+                != 0;
     }
 
     public boolean canLauncherRotate() {
-        return (mFlags & MASK_ACTIVITY_ROTATING) == MASK_ACTIVITY_ROTATING;
+        return (mFlags & FLAG_SYSTEM_ROTATION_ALLOWED) != 0 && isHomeRotationAllowed();
     }
 
     /**
@@ -331,11 +344,22 @@
         Rect insets = dp.getInsets();
         float fullWidth = dp.widthPx - insets.left - insets.right;
         float fullHeight = dp.heightPx - insets.top - insets.bottom;
-        final float scale = LayoutUtils.getTaskScale(this,
-                fullWidth, fullHeight, taskView.width(), taskView.height());
+
+        if (dp.isMultiWindowMode) {
+            mSizeStrategy.getMultiWindowSize(mContext, dp, outPivot);
+        } else {
+            outPivot.set(fullWidth, fullHeight);
+        }
+        final float scale = Math.min(outPivot.x / taskView.width(), outPivot.y / taskView.height());
 
         if (scale == 1) {
             outPivot.set(fullWidth / 2, fullHeight / 2);
+        } else if (dp.isMultiWindowMode) {
+            float denominator = 1 / (scale - 1);
+            // Ensure that the task aligns to right bottom for the root view
+            float y = (scale * taskView.bottom - fullHeight) * denominator;
+            float x = (scale * taskView.right - fullWidth) * denominator;
+            outPivot.set(x, y);
         } else {
             float factor = scale / (scale - 1);
             outPivot.set(taskView.left * factor, taskView.top * factor);
@@ -440,4 +464,19 @@
         return Settings.Global.getInt(
                 context.getContentResolver(), FIXED_ROTATION_TRANSFORM_SETTING_NAME, 1) == 1;
     }
+
+    @NonNull
+    @Override
+    public String toString() {
+        boolean systemRotationOn = (mFlags & FLAG_SYSTEM_ROTATION_ALLOWED) != 0;
+        return "["
+                + "mDisplayRotation=" + mDisplayRotation
+                + " mTouchRotation=" + mTouchRotation
+                + " mLauncherRotation=" + mLauncherRotation
+                + " mHomeRotation=" + isHomeRotationAllowed()
+                + " mSystemRotation=" + systemRotationOn
+                + " mFlags=" + mFlags
+                + " mOrientationHandler=" + mOrientationHandler
+                + "]";
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/util/WindowSizeStrategy.java b/quickstep/src/com/android/quickstep/util/WindowSizeStrategy.java
new file mode 100644
index 0000000..8bb0d70
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/WindowSizeStrategy.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util;
+
+import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
+import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
+import static com.android.quickstep.util.LayoutUtils.getDefaultSwipeHeight;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.PointF;
+import android.graphics.Rect;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.R;
+
+/**
+ * Utility class to wrap different layout behavior for Launcher and RecentsView
+ * TODO: Merge is with {@link com.android.quickstep.BaseActivityInterface} once we remove the
+ * state dependent members from {@link com.android.quickstep.LauncherActivityInterface}
+ */
+public abstract class WindowSizeStrategy {
+
+    private final PointF mTempPoint = new PointF();
+    public final boolean rotationSupportedByActivity;
+
+    private WindowSizeStrategy(boolean rotationSupportedByActivity) {
+        this.rotationSupportedByActivity = rotationSupportedByActivity;
+    }
+
+    /**
+     * Sets the expected window size in multi-window mode
+     */
+    public abstract void getMultiWindowSize(Context context, DeviceProfile dp, PointF out);
+
+    /**
+     * Calculates the taskView size for the provided device configuration
+     */
+    public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect) {
+        calculateTaskSize(context, dp, getExtraSpace(context, dp), outRect);
+    }
+
+    abstract float getExtraSpace(Context context, DeviceProfile dp);
+
+    private void calculateTaskSize(
+            Context context, DeviceProfile dp, float extraVerticalSpace, Rect outRect) {
+        float taskWidth, taskHeight, paddingHorz;
+        Resources res = context.getResources();
+        Rect insets = dp.getInsets();
+        final boolean showLargeTaskSize = showOverviewActions(context);
+
+        if (dp.isMultiWindowMode) {
+            getMultiWindowSize(context, dp, mTempPoint);
+            taskWidth = mTempPoint.x;
+            taskHeight = mTempPoint.y;
+            paddingHorz = res.getDimension(R.dimen.multi_window_task_card_horz_space);
+        } else {
+            taskWidth = dp.availableWidthPx;
+            taskHeight = dp.availableHeightPx;
+
+            final int paddingResId;
+            if (dp.isVerticalBarLayout()) {
+                paddingResId = R.dimen.landscape_task_card_horz_space;
+            } else if (showLargeTaskSize) {
+                paddingResId = R.dimen.portrait_task_card_horz_space_big_overview;
+            } else {
+                paddingResId = R.dimen.portrait_task_card_horz_space;
+            }
+            paddingHorz = res.getDimension(paddingResId);
+        }
+
+        float topIconMargin = res.getDimension(R.dimen.task_thumbnail_top_margin);
+        float paddingVert = showLargeTaskSize
+                ? 0 : res.getDimension(R.dimen.task_card_vert_space);
+
+        // Note this should be same as dp.availableWidthPx and dp.availableHeightPx unless
+        // we override the insets ourselves.
+        int launcherVisibleWidth = dp.widthPx - insets.left - insets.right;
+        int launcherVisibleHeight = dp.heightPx - insets.top - insets.bottom;
+
+        float availableHeight = launcherVisibleHeight
+                - topIconMargin - extraVerticalSpace - paddingVert;
+        float availableWidth = launcherVisibleWidth - paddingHorz;
+
+        float scale = Math.min(availableWidth / taskWidth, availableHeight / taskHeight);
+        float outWidth = scale * taskWidth;
+        float outHeight = scale * taskHeight;
+
+        // Center in the visible space
+        float x = insets.left + (launcherVisibleWidth - outWidth) / 2;
+        float y = insets.top + Math.max(topIconMargin,
+                (launcherVisibleHeight - extraVerticalSpace - outHeight) / 2);
+        outRect.set(Math.round(x), Math.round(y),
+                Math.round(x) + Math.round(outWidth), Math.round(y) + Math.round(outHeight));
+    }
+
+
+    public static final WindowSizeStrategy LAUNCHER_ACTIVITY_SIZE_STRATEGY =
+            new WindowSizeStrategy(true) {
+
+        @Override
+        public void getMultiWindowSize(Context context, DeviceProfile dp, PointF out) {
+            DeviceProfile fullDp = dp.getFullScreenProfile();
+            // Use availableWidthPx and availableHeightPx instead of widthPx and heightPx to
+            // account for system insets
+            out.set(fullDp.availableWidthPx, fullDp.availableHeightPx);
+            float halfDividerSize = context.getResources()
+                    .getDimension(R.dimen.multi_window_task_divider_size) / 2;
+
+            if (fullDp.isLandscape) {
+                out.x = out.x / 2 - halfDividerSize;
+            } else {
+                out.y = out.y / 2 - halfDividerSize;
+            }
+        }
+
+        @Override
+        float getExtraSpace(Context context, DeviceProfile dp) {
+            if (dp.isVerticalBarLayout()) {
+                return  0;
+            } else {
+                Resources res = context.getResources();
+                if (showOverviewActions(context)) {
+                    //TODO: this needs to account for the swipe gesture height and accessibility
+                    // UI when shown.
+                    return res.getDimensionPixelSize(R.dimen.overview_actions_height);
+                } else {
+                    return getDefaultSwipeHeight(context, dp) + dp.workspacePageIndicatorHeight
+                            + res.getDimensionPixelSize(
+                                    R.dimen.dynamic_grid_hotseat_extra_vertical_size)
+                            + res.getDimensionPixelSize(
+                                    R.dimen.dynamic_grid_hotseat_bottom_padding);
+                }
+            }
+        }
+    };
+
+    public static final WindowSizeStrategy FALLBACK_RECENTS_SIZE_STRATEGY =
+            new WindowSizeStrategy(false) {
+        @Override
+        public void getMultiWindowSize(Context context, DeviceProfile dp, PointF out) {
+            out.set(dp.widthPx, dp.heightPx);
+        }
+
+        @Override
+        float getExtraSpace(Context context, DeviceProfile dp) {
+            return showOverviewActions(context)
+                    ? context.getResources().getDimensionPixelSize(R.dimen.overview_actions_height)
+                    : 0;
+        }
+    };
+
+    static boolean showOverviewActions(Context context) {
+        return ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context);
+    }
+}
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index d72f3bb..c8b2876 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -80,7 +80,7 @@
     <string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Fonds d\'écran"</string>
     <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Styles et fonds d\'écran"</string>
-    <string name="settings_button_text" msgid="8873672322605444408">"Paramètres d\'écran d\'accueil"</string>
+    <string name="settings_button_text" msgid="8873672322605444408">"Paramètres d\'accueil"</string>
     <string name="msg_disabled_by_admin" msgid="6898038085516271325">"Désactivé par votre administrateur"</string>
     <string name="allow_rotation_title" msgid="7728578836261442095">"Autoriser la rotation de l\'écran d\'accueil"</string>
     <string name="allow_rotation_desc" msgid="8662546029078692509">"Lorsque vous faites pivoter le téléphone"</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index f69248c..3fa16ab 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -139,8 +139,7 @@
     <string name="work_profile_edu_accept" msgid="6069788082535149071">"बुझेँ"</string>
     <string name="work_apps_paused_title" msgid="2389865654362803723">"कार्यालयको प्रोफाइल अस्थायी रूपमा रोक्का गरिएको छ"</string>
     <string name="work_apps_paused_body" msgid="5388070126389079077">"कामसम्बन्धी एपहरूले तपाईंलाई सूचना पठाउन, तपाईंको ब्याट्री प्रयोग गर्न वा तपाईंको स्थानसम्बन्धी जानकारीमाथि पहुँच राख्न सक्दैनन्"</string>
-    <!-- no translation found for work_apps_paused_content_description (7553586952985486433) -->
-    <skip />
+    <string name="work_apps_paused_content_description" msgid="7553586952985486433">"कार्यालयको प्रोफाइल अस्थायी रूपमा रोक्का गरिएको छ। कामसम्बन्धी एपहरूले तपाईंलाई सूचना पठाउन, तपाईंको यन्त्रको ब्याट्री प्रयोग गर्न वा तपाईंको स्थान हेर्न सक्दैनन्"</string>
     <string name="work_switch_tip" msgid="808075064383839144">"कामसम्बन्धी एप र सूचनाहरू अस्थायी रूपमा रोक्का गर्नुहोस्"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"कार्य पूरा गर्न सकिएन: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
 </resources>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index b2cf426..e548b87 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -139,7 +139,7 @@
     <string name="work_profile_edu_accept" msgid="6069788082535149071">"ବୁଝିଗଲି"</string>
     <string name="work_apps_paused_title" msgid="2389865654362803723">"ୱାର୍କ ପ୍ରୋଫାଇଲକୁ ବିରତ କରାଯାଇଛି"</string>
     <string name="work_apps_paused_body" msgid="5388070126389079077">"କାର୍ଯ୍ୟସ୍ଥଳୀ ଆପ୍ ଆପଣଙ୍କୁ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ପଠାଇପାରିବ ନାହିଁ, ଆପଣଙ୍କ ବ୍ୟାଟେରୀକୁ ବ୍ୟବହାର କରିପାରିବ ନାହିଁ କିମ୍ବା ଆପଣଙ୍କ ଲୋକେସନକୁ ଆକ୍ସେସ୍ କରିପାରିବ ନାହିଁ"</string>
-    <string name="work_apps_paused_content_description" msgid="7553586952985486433">"ୱାର୍କ ପ୍ରୋଫାଇଲ୍ ବିରତ କରାଯାଇଛି। କାର୍ଯ୍ୟସ୍ଥଳୀ ଆପ୍ ଆପଣଙ୍କୁ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ପଠାଇପାରିବ ନାହିଁ, ଆପଣଙ୍କ ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରନ୍ତୁ କିମ୍ବା ଆପଣଙ୍କ ଲୋକେସନ୍ ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
+    <string name="work_apps_paused_content_description" msgid="7553586952985486433">"ୱାର୍କ ପ୍ରୋଫାଇଲ୍ ବିରତ କରାଯାଇଛି। କାର୍ଯ୍ୟସ୍ଥଳୀ ଆପ୍ ଆପଣଙ୍କୁ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ପଠାଇପାରିବ ନାହିଁ, ଆପଣଙ୍କ ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରନ୍ତୁ କିମ୍ବା ଆପଣଙ୍କ ଲୋକେସନ୍ ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
     <string name="work_switch_tip" msgid="808075064383839144">"କାର୍ଯ୍ୟସ୍ଥଳୀ ଆପ୍ ଏବଂ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ବିରତ କରନ୍ତୁ"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"ବିଫଳ ହୋଇଛି: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
 </resources>
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index e4f201c..db69341 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -24,6 +24,7 @@
 import android.content.Intent;
 import android.content.pm.LauncherApps;
 import android.content.res.Configuration;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Process;
@@ -31,6 +32,7 @@
 import android.os.UserHandle;
 import android.util.Log;
 import android.view.ActionMode;
+import android.view.Display;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.Toast;
@@ -270,4 +272,16 @@
     }
 
     protected abstract void reapplyUi();
+
+    protected Rect getMultiWindowDisplaySize() {
+        if (Utilities.ATLEAST_R) {
+            return new Rect(getWindowManager().getCurrentWindowMetrics().getBounds());
+        }
+        // Note: Calls to getSize() can't rely on our cached DefaultDisplay since it can return
+        // the app window size
+        Display display = getWindowManager().getDefaultDisplay();
+        Point mwSize = new Point();
+        display.getSize(mwSize);
+        return new Rect(0, 0, mwSize.x, mwSize.y);
+    }
 }
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index a5f98c0..47824b2 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -45,6 +45,8 @@
     public final boolean isLandscape;
     public final boolean isMultiWindowMode;
 
+    public final int windowX;
+    public final int windowY;
     public final int widthPx;
     public final int heightPx;
     public final int availableWidthPx;
@@ -133,13 +135,16 @@
     public DotRenderer mDotRendererWorkSpace;
     public DotRenderer mDotRendererAllApps;
 
-    public DeviceProfile(Context context, InvariantDeviceProfile inv, DefaultDisplay.Info info,
+    DeviceProfile(Context context, InvariantDeviceProfile inv, DefaultDisplay.Info info,
             Point minSize, Point maxSize, int width, int height, boolean isLandscape,
-            boolean isMultiWindowMode, boolean transposeLayoutWithOrientation) {
+            boolean isMultiWindowMode, boolean transposeLayoutWithOrientation,
+            Point windowPosition) {
 
         this.inv = inv;
         this.isLandscape = isLandscape;
         this.isMultiWindowMode = isMultiWindowMode;
+        windowX = windowPosition.x;
+        windowY = windowPosition.y;
 
         // Determine sizes.
         widthPx = width;
@@ -244,6 +249,7 @@
         return new Builder(context, inv, mInfo)
                 .setSizeRange(size, size)
                 .setSize(widthPx, heightPx)
+                .setWindowPosition(windowX, windowY)
                 .setMultiWindowMode(isMultiWindowMode);
     }
 
@@ -254,10 +260,11 @@
     /**
      * TODO: Move this to the builder as part of setMultiWindowMode
      */
-    public DeviceProfile getMultiWindowProfile(Context context, Point mwSize) {
+    public DeviceProfile getMultiWindowProfile(Context context, Rect windowPosition) {
         // We take the minimum sizes of this profile and it's multi-window variant to ensure that
         // the system decor is always excluded.
-        mwSize.set(Math.min(availableWidthPx, mwSize.x), Math.min(availableHeightPx, mwSize.y));
+        Point mwSize = new Point(Math.min(availableWidthPx, windowPosition.width()),
+                Math.min(availableHeightPx, windowPosition.height()));
 
         // In multi-window mode, we can have widthPx = availableWidthPx
         // and heightPx = availableHeightPx because Launcher uses the InvariantDeviceProfiles'
@@ -265,6 +272,7 @@
         DeviceProfile profile = toBuilder(context)
                 .setSizeRange(mwSize, mwSize)
                 .setSize(mwSize.x, mwSize.y)
+                .setWindowPosition(windowPosition.left, windowPosition.top)
                 .setMultiWindowMode(true)
                 .build();
 
@@ -286,7 +294,7 @@
     }
 
     /**
-     * Inverse of {@link #getMultiWindowProfile(Context, Point)}
+     * Inverse of {@link #getMultiWindowProfile(Context, Rect)}
      * @return device profile corresponding to the current orientation in non multi-window mode.
      */
     public DeviceProfile getFullScreenProfile() {
@@ -649,6 +657,7 @@
         private InvariantDeviceProfile mInv;
         private DefaultDisplay.Info mInfo;
 
+        private final Point mWindowPosition = new Point();
         private Point mMinSize, mMaxSize;
         private int mWidth, mHeight;
 
@@ -682,6 +691,14 @@
             return this;
         }
 
+        /**
+         * Sets the window position if not full-screen
+         */
+        public Builder setWindowPosition(int x, int y) {
+            mWindowPosition.set(x, y);
+            return this;
+        }
+
         public Builder setTransposeLayoutWithOrientation(boolean transposeLayoutWithOrientation) {
             mTransposeLayoutWithOrientation = transposeLayoutWithOrientation;
             return this;
@@ -690,7 +707,7 @@
         public DeviceProfile build() {
             return new DeviceProfile(mContext, mInv, mInfo, mMinSize, mMaxSize,
                     mWidth, mHeight, mIsLandscape, mIsMultiWindowMode,
-                    mTransposeLayoutWithOrientation);
+                    mTransposeLayoutWithOrientation, mWindowPosition);
         }
     }
 
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 070a392..c75bd95 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -18,23 +18,30 @@
 
 import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
+import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
 
 import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
 import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
 import static com.android.launcher3.AbstractFloatingView.TYPE_SNACKBAR;
+import static com.android.launcher3.InstallShortcutReceiver.FLAG_DRAG_AND_DROP;
 import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
 import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.LauncherState.FLAG_CLOSE_POPUPS;
+import static com.android.launcher3.LauncherState.FLAG_MULTI_PAGE;
+import static com.android.launcher3.LauncherState.FLAG_NON_INTERACTIVE;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.NO_OFFSET;
 import static com.android.launcher3.LauncherState.NO_SCALE;
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.LauncherState.OVERVIEW_PEEK;
+import static com.android.launcher3.LauncherState.SPRING_LOADED;
 import static com.android.launcher3.Utilities.postAsyncCallback;
 import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_LAUNCHER_LOAD;
 import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
 import static com.android.launcher3.popup.SystemShortcut.APP_INFO;
 import static com.android.launcher3.popup.SystemShortcut.INSTALL;
 import static com.android.launcher3.popup.SystemShortcut.WIDGETS;
+import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK;
 import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
 
 import android.animation.Animator;
@@ -57,7 +64,6 @@
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.database.sqlite.SQLiteDatabase;
-import android.graphics.Point;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.CancellationSignal;
@@ -69,7 +75,6 @@
 import android.text.method.TextKeyListener;
 import android.util.Log;
 import android.util.SparseArray;
-import android.view.Display;
 import android.view.KeyEvent;
 import android.view.KeyboardShortcutGroup;
 import android.view.KeyboardShortcutInfo;
@@ -94,6 +99,7 @@
 import com.android.launcher3.allapps.AllAppsTransitionController;
 import com.android.launcher3.allapps.DiscoveryBounce;
 import com.android.launcher3.anim.PropertyListBuilder;
+import com.android.launcher3.compat.AccessibilityManagerCompat;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dot.DotInfo;
 import com.android.launcher3.dragndrop.DragController;
@@ -560,12 +566,8 @@
         // Load configuration-specific DeviceProfile
         mDeviceProfile = idp.getDeviceProfile(this);
         if (isInMultiWindowMode()) {
-            // Note: Calls to getSize() can't rely on our cached DefaultDisplay since it can return
-            // the app window size
-            Display display = getWindowManager().getDefaultDisplay();
-            Point mwSize = new Point();
-            display.getSize(mwSize);
-            mDeviceProfile = mDeviceProfile.getMultiWindowProfile(this, mwSize);
+            mDeviceProfile = mDeviceProfile.getMultiWindowProfile(
+                    this, getMultiWindowDisplaySize());
         }
 
         onDeviceProfileInitiated();
@@ -921,8 +923,6 @@
                 }
             });
         }
-
-        TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "Activity.onStop");
     }
 
     @Override
@@ -936,11 +936,10 @@
 
         mAppWidgetHost.setListenIfResumed(true);
         TraceHelper.INSTANCE.endSection(traceToken);
-        TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "Activity.onStart");
     }
 
     private void handleDeferredResume() {
-        if (hasBeenResumed() && !mStateManager.getState().disableInteraction) {
+        if (hasBeenResumed() && !mStateManager.getState().hasFlag(FLAG_NON_INTERACTIVE)) {
             logStopAndResume(Action.Command.RESUME);
             getUserEventDispatcher().startSession();
 
@@ -988,7 +987,8 @@
         if (!mDeferOverlayCallbacks) {
             return;
         }
-        if (isStarted() && (!hasBeenResumed() || mStateManager.getState().disableInteraction)) {
+        if (isStarted() && (!hasBeenResumed()
+                || mStateManager.getState().hasFlag(FLAG_NON_INTERACTIVE))) {
             return;
         }
         mDeferOverlayCallbacks = false;
@@ -1023,13 +1023,42 @@
             scheduleDeferredCheck();
         }
         addActivityFlags(ACTIVITY_STATE_TRANSITION_ACTIVE);
+
+        if (state.hasFlag(FLAG_CLOSE_POPUPS)) {
+            AbstractFloatingView.closeAllOpenViews(this, !state.hasFlag(FLAG_NON_INTERACTIVE));
+        }
+
+        if (state == SPRING_LOADED) {
+            // Prevent any Un/InstallShortcutReceivers from updating the db while we are
+            // not on homescreen
+            InstallShortcutReceiver.enableInstallQueue(FLAG_DRAG_AND_DROP);
+            getRotationHelper().setCurrentStateRequest(REQUEST_LOCK);
+
+            mWorkspace.showPageIndicatorAtCurrentScroll();
+            mWorkspace.setClipChildren(false);
+        }
+        // When multiple pages are visible, show persistent page indicator
+        mWorkspace.getPageIndicator().setShouldAutoHide(!state.hasFlag(FLAG_MULTI_PAGE));
     }
 
     public void onStateSetEnd(LauncherState state) {
         getAppWidgetHost().setResumed(state == LauncherState.NORMAL);
-        getWorkspace().setClipChildren(!state.disablePageClipping);
+        getWorkspace().setClipChildren(!state.hasFlag(FLAG_MULTI_PAGE));
+
         finishAutoCancelActionMode();
         removeActivityFlags(ACTIVITY_STATE_TRANSITION_ACTIVE);
+
+        // dispatch window state changed
+        getWindow().getDecorView().sendAccessibilityEvent(TYPE_WINDOW_STATE_CHANGED);
+        AccessibilityManagerCompat.sendStateEventToTest(this, state.ordinal);
+
+        if (state == NORMAL) {
+            // Re-enable any Un/InstallShortcutReceiver and now process any queued items
+            InstallShortcutReceiver.disableAndFlushInstallQueue(FLAG_DRAG_AND_DROP, this);
+
+            // Clear any rotation locks when going to normal state
+            getRotationHelper().setCurrentStateRequest(REQUEST_NONE);
+        }
     }
 
     @Override
@@ -1100,7 +1129,7 @@
         int stateOrdinal = savedState.getInt(RUNTIME_STATE, NORMAL.ordinal);
         LauncherState[] stateValues = LauncherState.values();
         LauncherState state = stateValues[stateOrdinal];
-        if (!state.disableRestore) {
+        if (!state.shouldDisableRestore()) {
             mStateManager.goToState(state, false /* animated */);
         }
 
diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java
index b4fbbc3..226a924 100644
--- a/src/com/android/launcher3/LauncherRootView.java
+++ b/src/com/android/launcher3/LauncherRootView.java
@@ -64,15 +64,8 @@
     private void handleSystemWindowInsets(Rect insets) {
         mConsumedInsets.setEmpty();
         boolean drawInsetBar = false;
-        if (mLauncher.isInMultiWindowMode()
-                && (insets.left > 0 || insets.right > 0 || insets.bottom > 0)) {
-            mConsumedInsets.left = insets.left;
-            mConsumedInsets.right = insets.right;
-            mConsumedInsets.bottom = insets.bottom;
-            insets.set(0, insets.top, 0, 0);
-            drawInsetBar = true;
-        } else  if ((insets.right > 0 || insets.left > 0) &&
-                getContext().getSystemService(ActivityManager.class).isLowRamDevice()) {
+        if ((insets.right > 0 || insets.left > 0)
+                && getContext().getSystemService(ActivityManager.class).isLowRamDevice()) {
             mConsumedInsets.left = insets.left;
             mConsumedInsets.right = insets.right;
             insets.set(0, insets.top, 0, insets.bottom);
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index e2b867e..686a241 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -15,10 +15,7 @@
  */
 package com.android.launcher3;
 
-import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
-import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
 import static android.view.View.VISIBLE;
-import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
 
 import static com.android.launcher3.anim.Interpolators.ACCEL;
 import static com.android.launcher3.anim.Interpolators.ACCEL_2;
@@ -26,7 +23,6 @@
 import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
 import static com.android.launcher3.anim.Interpolators.clampToProgress;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
-import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
@@ -62,7 +58,6 @@
  */
 public abstract class LauncherState {
 
-
     /**
      * Set of elements indicating various workspace elements which change visibility across states
      * Note that workspace is not included here as in that case, we animate individual pages
@@ -80,16 +75,27 @@
     public static final int APPS_VIEW_ITEM_MASK =
             HOTSEAT_SEARCH_BOX | ALL_APPS_HEADER | ALL_APPS_HEADER_EXTRA | ALL_APPS_CONTENT;
 
-    protected static final int FLAG_MULTI_PAGE = 1 << 0;
-    protected static final int FLAG_DISABLE_ACCESSIBILITY = 1 << 1;
-    protected static final int FLAG_DISABLE_RESTORE = 1 << 2;
-    protected static final int FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED = 1 << 3;
-    protected static final int FLAG_DISABLE_PAGE_CLIPPING = 1 << 4;
-    protected static final int FLAG_PAGE_BACKGROUNDS = 1 << 5;
-    protected static final int FLAG_DISABLE_INTERACTION = 1 << 6;
-    protected static final int FLAG_OVERVIEW_UI = 1 << 7;
-    protected static final int FLAG_HIDE_BACK_BUTTON = 1 << 8;
-    protected static final int FLAG_HAS_SYS_UI_SCRIM = 1 << 9;
+    // Flag indicating workspace has multiple pages visible.
+    public static final int FLAG_MULTI_PAGE = 1 << 0;
+    // Flag indicating that workspace and its contents are not accessible
+    public static final int FLAG_WORKSPACE_INACCESSIBLE = 1 << 1;
+
+    public static final int FLAG_DISABLE_RESTORE = 1 << 2;
+    // Flag indicating the state allows workspace icons to be dragged.
+    public static final int FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED = 1 << 3;
+    // Flag to indicate that workspace should draw page background
+    public static final int FLAG_WORKSPACE_HAS_BACKGROUNDS = 1 << 4;
+    // Flag to indicate that Launcher is non-interactive in this state
+    public static final int FLAG_NON_INTERACTIVE = 1 << 5;
+    // True if the back button should be hidden when in this state (assuming no floating views are
+    // open, launcher has window focus, etc).
+    public static final int FLAG_HIDE_BACK_BUTTON = 1 << 6;
+    // Flag to indicate if the state would have scrim over sysui region: statu sbar and nav bar
+    public static final int FLAG_HAS_SYS_UI_SCRIM = 1 << 7;
+    // Flag to inticate that all popups should be closed when this state is enabled.
+    public static final int FLAG_CLOSE_POPUPS = 1 << 8;
+    public static final int FLAG_OVERVIEW_UI = 1 << 9;
+
 
     public static final float NO_OFFSET = 0;
     public static final float NO_SCALE = 1;
@@ -112,7 +118,7 @@
             FLAG_DISABLE_RESTORE | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED | FLAG_HIDE_BACK_BUTTON |
                     FLAG_HAS_SYS_UI_SCRIM) {
         @Override
-        public int getTransitionDuration(Launcher launcher) {
+        public int getTransitionDuration(Context context) {
             // Arbitrary duration, when going to NORMAL we use the state we're coming from instead.
             return 0;
         }
@@ -144,86 +150,42 @@
     public final int containerType;
 
     /**
-     * True if the state can be persisted across activity restarts.
-     */
-    public final boolean disableRestore;
-
-    /**
-     * True if workspace has multiple pages visible.
-     */
-    public final boolean hasMultipleVisiblePages;
-
-    /**
-     * Accessibility flag for workspace and its pages.
-     * @see android.view.View#setImportantForAccessibility(int)
-     */
-    public final int workspaceAccessibilityFlag;
-
-    /**
-     * Properties related to state transition animation
-     *
-     * @see WorkspaceStateTransitionAnimation
-     */
-    public final boolean hasWorkspacePageBackground;
-
-    /**
-     * True if the state allows workspace icons to be dragged.
-     */
-    public final boolean workspaceIconsCanBeDragged;
-
-    /**
-     * True if the workspace pages should not be clipped relative to the workspace bounds
-     * for this state.
-     */
-    public final boolean disablePageClipping;
-
-    /**
-     * True if launcher can not be directly interacted in this state;
-     */
-    public final boolean disableInteraction;
-
-    /**
      * True if the state has overview panel visible.
      */
     public final boolean overviewUi;
 
-    /**
-     * True if the back button should be hidden when in this state (assuming no floating views are
-     * open, launcher has window focus, etc).
-     */
-    public final boolean hideBackButton;
-
-    public final boolean hasSysUiScrim;
+    private final int mFlags;
 
     public LauncherState(int id, int containerType, int flags) {
         this.containerType = containerType;
-
-        this.hasWorkspacePageBackground = (flags & FLAG_PAGE_BACKGROUNDS) != 0;
-        this.hasMultipleVisiblePages = (flags & FLAG_MULTI_PAGE) != 0;
-        this.workspaceAccessibilityFlag = (flags & FLAG_DISABLE_ACCESSIBILITY) != 0
-                ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
-                : IMPORTANT_FOR_ACCESSIBILITY_AUTO;
-        this.disableRestore = (flags & FLAG_DISABLE_RESTORE) != 0;
-        this.workspaceIconsCanBeDragged = (flags & FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED) != 0;
-        this.disablePageClipping = (flags & FLAG_DISABLE_PAGE_CLIPPING) != 0;
-        this.disableInteraction = (flags & FLAG_DISABLE_INTERACTION) != 0;
+        this.mFlags = flags;
         this.overviewUi = (flags & FLAG_OVERVIEW_UI) != 0;
-        this.hideBackButton = (flags & FLAG_HIDE_BACK_BUTTON) != 0;
-        this.hasSysUiScrim = (flags & FLAG_HAS_SYS_UI_SCRIM) != 0;
-
         this.ordinal = id;
         sAllStates[id] = this;
     }
 
+    /**
+     * Returns if the state has the provided flag
+     */
+    public final boolean hasFlag(int mask) {
+        return (mFlags & mask) != 0;
+    }
+
+    /**
+     * @return true if the state can be persisted across activity restarts.
+     */
+    public final boolean shouldDisableRestore() {
+        return hasFlag(FLAG_DISABLE_RESTORE);
+    }
+
     public static LauncherState[] values() {
         return Arrays.copyOf(sAllStates, sAllStates.length);
     }
 
     /**
      * @return How long the animation to this state should take (or from this state to NORMAL).
-     * @param launcher
      */
-    public abstract int getTransitionDuration(Launcher launcher);
+    public abstract int getTransitionDuration(Context context);
 
     public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
         return new ScaleAndTranslation(NO_SCALE, NO_OFFSET, NO_OFFSET);
@@ -252,12 +214,6 @@
         return 0;
     }
 
-    public void onStateEnabled(Launcher launcher) {
-        dispatchWindowStateChanged(launcher);
-    }
-
-    public void onStateDisabled(Launcher launcher) { }
-
     public int getVisibleElements(Launcher launcher) {
         if (launcher.getDeviceProfile().isVerticalBarLayout()) {
             return HOTSEAT_ICONS | VERTICAL_SWIPE_INDICATOR;
@@ -329,16 +285,6 @@
         return NORMAL;
     }
 
-    /**
-     * Called when the start transition ends and the user settles on this particular state.
-     */
-    public void onStateTransitionEnd(Launcher launcher) {
-        if (this == NORMAL) {
-            // Clear any rotation locks when going to normal state
-            launcher.getRotationHelper().setCurrentStateRequest(REQUEST_NONE);
-        }
-    }
-
     public void onBackPressed(Launcher launcher) {
         if (this != NORMAL) {
             LauncherStateManager lsm = launcher.getStateManager();
@@ -396,10 +342,6 @@
         }
     }
 
-    protected static void dispatchWindowStateChanged(Launcher launcher) {
-        launcher.getWindow().getDecorView().sendAccessibilityEvent(TYPE_WINDOW_STATE_CHANGED);
-    }
-
     public static abstract class PageAlphaProvider {
 
         public final Interpolator interpolator;
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index 1d2e866..ea41fc4 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -29,7 +29,6 @@
 import com.android.launcher3.anim.AnimationSuccessListener;
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.anim.PendingAnimation;
-import com.android.launcher3.compat.AccessibilityManagerCompat;
 import com.android.launcher3.states.StateAnimationConfig;
 import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
 
@@ -355,18 +354,9 @@
     }
 
     private void onStateTransitionStart(LauncherState state) {
-        if (mState != state) {
-            mState.onStateDisabled(mLauncher);
-        }
         mState = state;
-        mState.onStateEnabled(mLauncher);
         mLauncher.onStateSetStart(mState);
 
-        if (state.disablePageClipping) {
-            // Only disable clipping if needed, otherwise leave it as previous value.
-            mLauncher.getWorkspace().setClipChildren(false);
-        }
-
         for (int i = mListeners.size() - 1; i >= 0; i--) {
             mListeners.get(i).onStateTransitionStart(state);
         }
@@ -379,9 +369,7 @@
             mCurrentStableState = state;
         }
 
-        state.onStateTransitionEnd(mLauncher);
         mLauncher.onStateSetEnd(state);
-
         if (state == NORMAL) {
             setRestState(null);
         }
@@ -389,8 +377,6 @@
         for (int i = mListeners.size() - 1; i >= 0; i--) {
             mListeners.get(i).onStateTransitionComplete(state);
         }
-
-        AccessibilityManagerCompat.sendStateEventToTest(mLauncher, state.ordinal);
     }
 
     public LauncherState getLastState() {
@@ -402,7 +388,7 @@
             // The user is doing something. Lets not mess it up
             return;
         }
-        if (mState.disableRestore) {
+        if (mState.shouldDisableRestore()) {
             goToState(getRestState());
             // Reset history
             mLastStableState = NORMAL;
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 7baee95..8e33406 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -63,6 +63,8 @@
 import android.view.ViewConfiguration;
 import android.view.animation.Interpolator;
 
+import androidx.core.os.BuildCompat;
+
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
 import com.android.launcher3.graphics.GridOptionsProvider;
@@ -104,6 +106,8 @@
     public static final String[] EMPTY_STRING_ARRAY = new String[0];
     public static final Person[] EMPTY_PERSON_ARRAY = new Person[0];
 
+    public static final boolean ATLEAST_R = BuildCompat.isAtLeastR();
+
     public static final boolean ATLEAST_Q = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
 
     public static final boolean ATLEAST_P =
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 70a5cc5..10c05d3 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -19,6 +19,9 @@
 import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
 import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.LauncherState.FLAG_MULTI_PAGE;
+import static com.android.launcher3.LauncherState.FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED;
+import static com.android.launcher3.LauncherState.FLAG_WORKSPACE_INACCESSIBLE;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.LauncherState.SPRING_LOADED;
@@ -1208,7 +1211,7 @@
 
     /** Returns whether a drag should be allowed to be started from the current workspace state. */
     public boolean workspaceIconsCanBeDragged() {
-        return mLauncher.getStateManager().getState().workspaceIconsCanBeDragged;
+        return mLauncher.getStateManager().getState().hasFlag(FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED);
     }
 
     private void updateChildrenLayersEnabled() {
@@ -1318,7 +1321,7 @@
 
         // Invalidate the pages now, so that we have the visible pages before the
         // animation is started
-        if (toState.hasMultipleVisiblePages) {
+        if (toState.hasFlag(FLAG_MULTI_PAGE)) {
             mForceDrawAdjacentPages = true;
         }
         invalidate(); // This will call dispatchDraw(), which calls getVisiblePages().
@@ -1336,7 +1339,10 @@
 
     public void updateAccessibilityFlags() {
         // TODO: Update the accessibility flags appropriately when dragging.
-        int accessibilityFlag = mLauncher.getStateManager().getState().workspaceAccessibilityFlag;
+        int accessibilityFlag =
+                mLauncher.getStateManager().getState().hasFlag(FLAG_WORKSPACE_INACCESSIBLE)
+                        ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
+                        : IMPORTANT_FOR_ACCESSIBILITY_AUTO;
         if (!mLauncher.getAccessibilityDelegate().isInAccessibleDrag()) {
             int total = getPageCount();
             for (int i = 0; i < total; i++) {
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index c4c4377..29cf803 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -21,6 +21,8 @@
 import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
+import static com.android.launcher3.LauncherState.FLAG_HAS_SYS_UI_SCRIM;
+import static com.android.launcher3.LauncherState.FLAG_WORKSPACE_HAS_BACKGROUNDS;
 import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.anim.Interpolators.ZOOM_OUT;
@@ -161,7 +163,8 @@
         WorkspaceAndHotseatScrim scrim = mLauncher.getDragLayer().getScrim();
         propertySetter.setFloat(scrim, SCRIM_PROGRESS, state.getWorkspaceScrimAlpha(mLauncher),
                 LINEAR);
-        propertySetter.setFloat(scrim, SYSUI_PROGRESS, state.hasSysUiScrim ? 1 : 0, LINEAR);
+        propertySetter.setFloat(scrim, SYSUI_PROGRESS,
+                state.hasFlag(FLAG_HAS_SYS_UI_SCRIM) ? 1 : 0, LINEAR);
     }
 
     public void applyChildState(LauncherState state, CellLayout cl, int childIndex) {
@@ -173,7 +176,8 @@
             PageAlphaProvider pageAlphaProvider, PropertySetter propertySetter,
             StateAnimationConfig config) {
         float pageAlpha = pageAlphaProvider.getPageAlpha(childIndex);
-        int drawableAlpha = Math.round(pageAlpha * (state.hasWorkspacePageBackground ? 255 : 0));
+        int drawableAlpha = state.hasFlag(FLAG_WORKSPACE_HAS_BACKGROUNDS)
+                ? Math.round(pageAlpha * 255) : 0;
 
         if (!config.onlyPlayAtomicComponent()) {
             // Don't update the scrim during the atomic animation.
diff --git a/src/com/android/launcher3/allapps/AllAppsStore.java b/src/com/android/launcher3/allapps/AllAppsStore.java
index d2dcfd2..b11312c 100644
--- a/src/com/android/launcher3/allapps/AllAppsStore.java
+++ b/src/com/android/launcher3/allapps/AllAppsStore.java
@@ -18,7 +18,6 @@
 import static com.android.launcher3.model.data.AppInfo.COMPONENT_KEY_COMPARATOR;
 import static com.android.launcher3.model.data.AppInfo.EMPTY_ARRAY;
 
-import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -32,6 +31,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
 
@@ -50,14 +50,12 @@
 
     private AppInfo[] mApps = EMPTY_ARRAY;
 
-    private final List<OnUpdateListener> mUpdateListeners = new ArrayList<>();
+    private final List<OnUpdateListener> mUpdateListeners = new CopyOnWriteArrayList<>();
     private final ArrayList<ViewGroup> mIconContainers = new ArrayList<>();
 
     private int mDeferUpdatesFlags = 0;
     private boolean mUpdatePending = false;
 
-    private boolean mListenerUpdateInProgress = false;
-
     public AppInfo[] getApps() {
         return mApps;
     }
@@ -102,12 +100,9 @@
             mUpdatePending = true;
             return;
         }
-        mListenerUpdateInProgress = true;
-        int count = mUpdateListeners.size();
-        for (int i = 0; i < count; i++) {
-            mUpdateListeners.get(i).onAppsUpdated();
+        for (OnUpdateListener listener : mUpdateListeners) {
+            listener.onAppsUpdated();
         }
-        mListenerUpdateInProgress = false;
     }
 
     public void addUpdateListener(OnUpdateListener listener) {
@@ -115,9 +110,6 @@
     }
 
     public void removeUpdateListener(OnUpdateListener listener) {
-        if (mListenerUpdateInProgress) {
-            Log.e("AllAppsStore", "Trying to remove listener during update", new Exception());
-        }
         mUpdateListeners.remove(listener);
     }
 
diff --git a/src/com/android/launcher3/states/HintState.java b/src/com/android/launcher3/states/HintState.java
index 43f30f1..9ea8436 100644
--- a/src/com/android/launcher3/states/HintState.java
+++ b/src/com/android/launcher3/states/HintState.java
@@ -15,10 +15,10 @@
  */
 package com.android.launcher3.states;
 
+import android.content.Context;
+
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
-import com.android.launcher3.LauncherStateManager;
-import com.android.launcher3.Workspace;
 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
 
 /**
@@ -26,7 +26,7 @@
  */
 public class HintState extends LauncherState {
 
-    private static final int STATE_FLAGS = FLAG_DISABLE_ACCESSIBILITY | FLAG_DISABLE_RESTORE
+    private static final int STATE_FLAGS = FLAG_WORKSPACE_INACCESSIBLE | FLAG_DISABLE_RESTORE
             | FLAG_HAS_SYS_UI_SCRIM;
 
     public HintState(int id) {
@@ -34,7 +34,7 @@
     }
 
     @Override
-    public int getTransitionDuration(Launcher launcher) {
+    public int getTransitionDuration(Context context) {
         return 80;
     }
 
@@ -48,16 +48,4 @@
         // Treat the QSB as part of the hotseat so they move together.
         return getHotseatScaleAndTranslation(launcher);
     }
-
-    @Override
-    public void onStateTransitionEnd(Launcher launcher) {
-        LauncherStateManager stateManager = launcher.getStateManager();
-        Workspace workspace = launcher.getWorkspace();
-        boolean willMoveScreens = workspace.getNextPage() != Workspace.DEFAULT_PAGE;
-        stateManager.goToState(NORMAL, true, willMoveScreens ? null
-                : launcher.getScrimView()::startDragHandleEducationAnim);
-        if (willMoveScreens) {
-            workspace.post(workspace::moveToDefaultScreen);
-        }
-    }
 }
diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java
index b2ff69a..f0e0557 100644
--- a/src/com/android/launcher3/states/SpringLoadedState.java
+++ b/src/com/android/launcher3/states/SpringLoadedState.java
@@ -15,13 +15,10 @@
  */
 package com.android.launcher3.states;
 
-import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK;
-
 import android.content.Context;
 import android.graphics.Rect;
 
 import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.InstallShortcutReceiver;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.Workspace;
@@ -32,16 +29,17 @@
  */
 public class SpringLoadedState extends LauncherState {
 
-    private static final int STATE_FLAGS = FLAG_MULTI_PAGE |
-            FLAG_DISABLE_ACCESSIBILITY | FLAG_DISABLE_RESTORE | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED |
-            FLAG_DISABLE_PAGE_CLIPPING | FLAG_PAGE_BACKGROUNDS | FLAG_HIDE_BACK_BUTTON;
+    private static final int STATE_FLAGS = FLAG_MULTI_PAGE
+            | FLAG_WORKSPACE_INACCESSIBLE | FLAG_DISABLE_RESTORE
+            | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED | FLAG_WORKSPACE_HAS_BACKGROUNDS
+            | FLAG_HIDE_BACK_BUTTON;
 
     public SpringLoadedState(int id) {
         super(id, ContainerType.OVERVIEW, STATE_FLAGS);
     }
 
     @Override
-    public int getTransitionDuration(Launcher launcher) {
+    public int getTransitionDuration(Context context) {
         return 150;
     }
 
@@ -88,28 +86,7 @@
     }
 
     @Override
-    public void onStateEnabled(Launcher launcher) {
-        Workspace ws = launcher.getWorkspace();
-        ws.showPageIndicatorAtCurrentScroll();
-        ws.getPageIndicator().setShouldAutoHide(false);
-
-        // Prevent any Un/InstallShortcutReceivers from updating the db while we are
-        // in spring loaded mode
-        InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_DRAG_AND_DROP);
-        launcher.getRotationHelper().setCurrentStateRequest(REQUEST_LOCK);
-    }
-
-    @Override
     public float getWorkspaceScrimAlpha(Launcher launcher) {
         return 0.3f;
     }
-
-    @Override
-    public void onStateDisabled(final Launcher launcher) {
-        launcher.getWorkspace().getPageIndicator().setShouldAutoHide(true);
-
-        // Re-enable any Un/InstallShortcutReceiver and now process any queued items
-        InstallShortcutReceiver.disableAndFlushInstallQueue(
-                InstallShortcutReceiver.FLAG_DRAG_AND_DROP, launcher);
-    }
 }
diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
index dc50053..86d3c61 100644
--- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
@@ -126,6 +126,11 @@
     }
 
     @Override
+    public int getClearAllScrollOffset(View view, boolean isRtl) {
+        return (isRtl ? view.getPaddingBottom() : - view.getPaddingTop()) / 2;
+    }
+
+    @Override
     public int getSecondaryDimension(View view) {
         return view.getWidth();
     }
diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java
index cc15f99..02a020f 100644
--- a/src/com/android/launcher3/touch/PagedOrientationHandler.java
+++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java
@@ -62,6 +62,7 @@
     float getPrimaryVelocity(VelocityTracker velocityTracker, int pointerId);
     int getMeasuredSize(View view);
     float getPrimarySize(RectF rect);
+    int getClearAllScrollOffset(View view, boolean isRtl);
     int getSecondaryDimension(View view);
     FloatProperty<View> getPrimaryViewTranslate();
     FloatProperty<View> getSecondaryViewTranslate();
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index 7c30e29..b253e7d 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -123,6 +123,11 @@
     }
 
     @Override
+    public int getClearAllScrollOffset(View view, boolean isRtl) {
+        return (isRtl ? view.getPaddingRight() : - view.getPaddingLeft()) / 2;
+    }
+
+    @Override
     public int getSecondaryDimension(View view) {
         return view.getHeight();
     }
diff --git a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
index 7beb7f7..e86ec3b 100644
--- a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
@@ -75,4 +75,15 @@
     public float getTaskMenuY(float y, View thumbnailView) {
         return y + thumbnailView.getMeasuredHeight();
     }
+
+    @Override
+    public int getClearAllScrollOffset(View view, boolean isRtl) {
+        return (isRtl ? view.getPaddingTop() : - view.getPaddingBottom()) / 2;
+    }
+
+    @Override
+    public void setPrimaryAndResetSecondaryTranslate(View view, float translation) {
+        view.setTranslationX(0);
+        view.setTranslationY(-translation);
+    }
 }
diff --git a/src/com/android/launcher3/views/WorkEduView.java b/src/com/android/launcher3/views/WorkEduView.java
index 552f662..859b9d0 100644
--- a/src/com/android/launcher3/views/WorkEduView.java
+++ b/src/com/android/launcher3/views/WorkEduView.java
@@ -33,6 +33,7 @@
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.LauncherStateManager;
+import com.android.launcher3.LauncherStateManager.StateListener;
 import com.android.launcher3.R;
 import com.android.launcher3.allapps.AllAppsContainerView;
 import com.android.launcher3.allapps.AllAppsPagedView;
@@ -43,7 +44,7 @@
 /**
  * On boarding flow for users right after setting up work profile
  */
-public class WorkEduView extends AbstractSlideInView implements Insettable {
+public class WorkEduView extends AbstractSlideInView implements Insettable, StateListener {
 
     private static final int DEFAULT_CLOSE_DURATION = 200;
     public static final String KEY_WORK_EDU_STEP = "showed_work_profile_edu";
@@ -82,6 +83,12 @@
     }
 
     @Override
+    protected void onCloseComplete() {
+        super.onCloseComplete();
+        mLauncher.getStateManager().removeStateListener(this);
+    }
+
+    @Override
     public void logActionCommand(int command) {
         // Since this is on-boarding popup, it is not a user controlled action.
     }
@@ -150,6 +157,7 @@
     private void show() {
         attachToContainer();
         animateOpen();
+        mLauncher.getStateManager().addStateListener(this);
     }
 
     @Override
@@ -222,4 +230,9 @@
     private static boolean hasSeenLegacyEdu(Launcher launcher) {
         return launcher.getSharedPrefs().getBoolean(KEY_LEGACY_WORK_EDU_SEEN, false);
     }
+
+    @Override
+    public void onStateTransitionComplete(LauncherState finalState) {
+        close(false);
+    }
 }
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
index 313ea05..ec3f93f 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -16,9 +16,9 @@
 package com.android.launcher3.uioverrides.states;
 
 import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
-import static com.android.launcher3.util.OnboardingPrefs.HOME_BOUNCE_SEEN;
 
-import com.android.launcher3.AbstractFloatingView;
+import android.content.Context;
+
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.R;
@@ -31,7 +31,7 @@
 
     private static final float PARALLAX_COEFFICIENT = .125f;
 
-    private static final int STATE_FLAGS = FLAG_DISABLE_ACCESSIBILITY;
+    private static final int STATE_FLAGS = FLAG_WORKSPACE_INACCESSIBLE;
 
     private static final PageAlphaProvider PAGE_ALPHA_PROVIDER = new PageAlphaProvider(DEACCEL_2) {
         @Override
@@ -45,21 +45,11 @@
     }
 
     @Override
-    public int getTransitionDuration(Launcher context) {
+    public int getTransitionDuration(Context context) {
         return 320;
     }
 
     @Override
-    public void onStateEnabled(Launcher launcher) {
-        if (!launcher.getSharedPrefs().getBoolean(HOME_BOUNCE_SEEN, false)) {
-            launcher.getSharedPrefs().edit().putBoolean(HOME_BOUNCE_SEEN, true).apply();
-        }
-
-        AbstractFloatingView.closeAllOpenViews(launcher);
-        dispatchWindowStateChanged(launcher);
-    }
-
-    @Override
     public String getDescription(Launcher launcher) {
         return launcher.getString(R.string.all_apps_button_label);
     }
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java b/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java
index 507ff59..7a6332c 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -15,7 +15,8 @@
  */
 package com.android.launcher3.uioverrides.states;
 
-import com.android.launcher3.Launcher;
+import android.content.Context;
+
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
 
@@ -29,7 +30,7 @@
     }
 
     @Override
-    public int getTransitionDuration(Launcher context) {
+    public int getTransitionDuration(Context context) {
         return 250;
     }
 
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 80b8e89..94ab780 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -71,7 +71,6 @@
     }
 
     protected void goToOverviewUnchecked() {
-        final boolean launcherWasVisible = mLauncher.isLauncherVisible();
         switch (mLauncher.getNavigationModel()) {
             case ZERO_BUTTON: {
                 final int centerX = mLauncher.getDevice().getDisplayWidth() / 2;
@@ -138,11 +137,6 @@
                 break;
         }
         expectSwitchToOverviewEvents();
-
-        if (!launcherWasVisible) {
-            mLauncher.expectEvent(
-                    TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_START_ACTIVITY);
-        }
     }
 
     private void expectSwitchToOverviewEvents() {
@@ -192,11 +186,6 @@
                 }
                 final boolean isZeroButton = mLauncher.getNavigationModel()
                         == LauncherInstrumentation.NavigationModel.ZERO_BUTTON;
-                if (!launcherWasVisible) {
-                    mLauncher.expectEvent(
-                            TestProtocol.SEQUENCE_MAIN,
-                            LauncherInstrumentation.EVENT_START_ACTIVITY);
-                }
                 mLauncher.swipeToState(startX, startY, endX, endY, 20, expectedState,
                         launcherWasVisible && isZeroButton
                                 ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
@@ -208,11 +197,6 @@
                 // Double press the recents button.
                 UiObject2 recentsButton = mLauncher.waitForSystemUiObject("recent_apps");
                 mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
-                if (!launcherWasVisible) {
-                    mLauncher.expectEvent(
-                            TestProtocol.SEQUENCE_MAIN,
-                            LauncherInstrumentation.EVENT_START_ACTIVITY);
-                }
                 mLauncher.runToState(() -> recentsButton.click(), OVERVIEW_STATE_ORDINAL);
                 mLauncher.getOverview();
                 mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
@@ -220,8 +204,6 @@
                 break;
         }
         mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, TASK_START_EVENT);
-        mLauncher.expectEvent(
-                TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_STOP_ACTIVITY);
     }
 
     protected String getSwipeHeightRequestName() {
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index df7436c..13ecfb8 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -25,8 +25,6 @@
 import androidx.test.uiautomator.UiObject2;
 import androidx.test.uiautomator.Until;
 
-import com.android.launcher3.testing.TestProtocol;
-
 /**
  * Ancestor for AppIcon and AppMenuItem.
  */
@@ -64,8 +62,6 @@
                 event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
                 () -> "Launching an app didn't open a new window: " + mObject.getText());
         expectActivityStartEvents();
-        mLauncher.expectEvent(
-                TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_STOP_ACTIVITY);
 
         mLauncher.assertTrue(
                 "App didn't start: " + selector,
@@ -76,7 +72,8 @@
 
     /**
      * Drags an object to the center of homescreen.
-     * @param startsActivity whether it's expected to start an activity.
+     *
+     * @param startsActivity   whether it's expected to start an activity.
      * @param isWidgetShortcut whether we drag a widget shortcut
      */
     public void dragToWorkspace(boolean startsActivity, boolean isWidgetShortcut) {
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index d46845f..bad8be5 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -97,8 +97,6 @@
     private static final Pattern EVENT_TOUCH_UP = getTouchEventPattern("ACTION_UP");
     private static final Pattern EVENT_TOUCH_CANCEL = getTouchEventPattern("ACTION_CANCEL");
     private static final Pattern EVENT_PILFER_POINTERS = Pattern.compile("pilferPointers");
-    static final Pattern EVENT_START_ACTIVITY = Pattern.compile("Activity\\.onStart");
-    static final Pattern EVENT_STOP_ACTIVITY = Pattern.compile("Activity\\.onStop");
     static final Pattern EVENT_START = Pattern.compile("start:");
 
     static final Pattern EVENT_TOUCH_DOWN_TIS = getTouchEventPatternTIS("ACTION_DOWN");
@@ -680,14 +678,8 @@
                                         ? GestureScope.INSIDE_TO_OUTSIDE
                                         : GestureScope.OUTSIDE);
                     }
-                    if (!launcherWasVisible) {
-                        expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_START_ACTIVITY);
-                    }
                 }
             } else {
-                if (!launcherWasVisible) {
-                    expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_START_ACTIVITY);
-                }
                 log("Hierarchy before clicking home:");
                 dumpViewHierarchy();
                 log(action = "clicking home button from " + getVisibleStateMessage());
diff --git a/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenuItem.java b/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenuItem.java
index d1268cc..42b6bc9 100644
--- a/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenuItem.java
+++ b/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenuItem.java
@@ -15,8 +15,6 @@
  */
 package com.android.launcher3.tapl;
 
-import android.os.Build;
-
 import androidx.annotation.NonNull;
 import androidx.test.uiautomator.By;
 import androidx.test.uiautomator.UiObject2;
@@ -44,12 +42,6 @@
                     + mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
             mLauncher.clickLauncherObject(mObject);
             mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_START);
-            if (!Build.MODEL.contains("Cuttlefish") ||
-                    Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q &&
-                            !"R".equals(Build.VERSION.CODENAME)) {
-                mLauncher.expectEvent(
-                        TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_STOP_ACTIVITY);
-            }
             mLauncher.assertTrue(
                     "App didn't start: " + By.pkg(expectedPackageName),
                     mLauncher.getDevice().wait(Until.hasObject(By.pkg(expectedPackageName)),
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
index fae5f19..b235919 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
@@ -79,8 +79,6 @@
                         () -> "Launching task didn't open a new window: "
                                 + mTask.getParent().getContentDescription());
                 mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, TASK_START_EVENT);
-                mLauncher.expectEvent(
-                        TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_STOP_ACTIVITY);
             }
             return new Background(mLauncher);
         }
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index 0d91dc2..9f80917 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -229,10 +229,6 @@
         if (startsActivity || isWidgetShortcut) {
             launcher.expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_START);
         }
-        if (startsActivity) {
-            launcher.expectEvent(
-                    TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_STOP_ACTIVITY);
-        }
         LauncherInstrumentation.log("dragIconToWorkspace: end");
         launcher.waitUntilGone("drop_target_bar");
     }