Merge "Fix crash when handling recents animation canceled" into sc-dev
diff --git a/quickstep/res/drawable/ic_all_set.xml b/quickstep/res/drawable/ic_all_set.xml
index 656c596..f718b8b 100644
--- a/quickstep/res/drawable/ic_all_set.xml
+++ b/quickstep/res/drawable/ic_all_set.xml
@@ -14,10 +14,10 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="42dp"
-    android:height="42dp"
-    android:viewportWidth="42"
-    android:viewportHeight="42">
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
     <path
         android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"
         android:fillColor="#FFFFFF"/>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 28262a8..1f86d62 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -114,8 +114,8 @@
 
     <!-- All Set page -->
     <dimen name="allset_page_margin_horizontal">40dp</dimen>
-    <dimen name="allset_title_margin_top">28dp</dimen>
-    <dimen name="allset_title_icon_margin_top">80dp</dimen>
+    <dimen name="allset_title_margin_top">24dp</dimen>
+    <dimen name="allset_title_icon_margin_top">32dp</dimen>
     <dimen name="allset_hint_margin_bottom">52dp</dimen>
     <dimen name="allset_subtitle_margin_top">24dp</dimen>
 
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 2498d12..32e2f1a 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -20,10 +20,10 @@
 import static com.android.launcher3.LauncherState.FLAG_HIDE_BACK_BUTTON;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.NO_OFFSET;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
-import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
 
 import android.animation.AnimatorSet;
@@ -181,7 +181,7 @@
     @Override
     protected void onScreenOff() {
         super.onScreenOff();
-        if (LIVE_TILE.get()) {
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             RecentsView recentsView = getOverviewPanel();
             recentsView.finishRecentsAnimation(true /* toRecents */, null);
         }
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 310e178..5bb76d6 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -725,7 +725,8 @@
                 floatingIconBounds.bottom += offsetY;
 
                 if (initOnly) {
-                    floatingView.update(mIconAlpha.value, 255, floatingIconBounds, percent, 0f,
+                    // For the init pass, we want full alpha since the window is not yet ready.
+                    floatingView.update(1f, 255, floatingIconBounds, percent, 0f,
                             mWindowRadius.value * scale, true /* isOpening */);
                     return;
                 }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index 521dd23..86c42ca 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -25,8 +25,8 @@
 import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
 import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_EDU;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE;
-import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
 
 import android.animation.ValueAnimator;
@@ -140,7 +140,7 @@
             AnimatorControllerWithResistance.createRecentsResistanceFromOverviewAnim(mLauncher,
                     builder);
 
-            if (LIVE_TILE.get()) {
+            if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
                 builder.addOnFrameCallback(recentsView::redrawLiveTile);
             }
 
@@ -189,7 +189,7 @@
         boolean success = interpolatedProgress >= SUCCESS_TRANSITION_PROGRESS
                 || (velocity < 0 && fling);
         if (success) {
-            if (LIVE_TILE.get()) {
+            if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
                 RecentsView recentsView = mLauncher.getOverviewPanel();
                 recentsView.switchToScreenshot(null,
                         () -> recentsView.finishRecentsAnimation(true /* toRecents */, null));
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 6e7db55..e867f07 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -25,6 +25,7 @@
 import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
 import static com.android.launcher3.anim.Interpolators.DEACCEL;
 import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE;
@@ -45,7 +46,6 @@
 import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_CANCELED;
 import static com.android.quickstep.GestureState.STATE_RECENTS_SCROLLING_FINISHED;
 import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
-import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
 import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
@@ -233,6 +233,7 @@
 
     // Used to control launcher components throughout the swipe gesture.
     private AnimatorControllerWithResistance mLauncherTransitionController;
+    private boolean mHasEndedLauncherTransition;
 
     private AnimationFactory mAnimationFactory = (t) -> { };
 
@@ -327,7 +328,7 @@
         mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED | STATE_FINISH_WITH_NO_END,
                 this::resetStateForAnimationCancel);
 
-        if (!LIVE_TILE.get()) {
+        if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             mStateCallback.addChangeListener(STATE_APP_CONTROLLER_RECEIVED | STATE_LAUNCHER_PRESENT
                             | STATE_SCREENSHOT_VIEW_SHOWN | STATE_CAPTURE_SCREENSHOT,
                     (b) -> mRecentsView.setRunningTaskHidden(!b));
@@ -384,10 +385,10 @@
         // Set up a entire animation lifecycle callback to notify the current recents view when
         // the animation is canceled
         mGestureState.runOnceAtState(STATE_RECENTS_ANIMATION_CANCELED, () -> {
-                ThumbnailData snapshot = mGestureState.getRecentsAnimationCanceledSnapshot();
+                ThumbnailData snapshot = mGestureState.consumeRecentsAnimationCanceledSnapshot();
                 if (snapshot != null) {
-                    RecentsModel.INSTANCE.get(mContext).onTaskSnapshotChanged(
-                            mRecentsView.getRunningTaskId(), snapshot);
+                    mRecentsView.switchToScreenshot(snapshot,
+                            () -> mRecentsAnimationController.cleanupScreenshot());
                     mRecentsView.onRecentsAnimationComplete();
                 }
             });
@@ -490,7 +491,7 @@
     }
 
     private void onDeferredActivityLaunch() {
-        if (LIVE_TILE.get()) {
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             mActivityInterface.switchRunningTaskViewToScreenshot(
                     null, () -> {
                         mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
@@ -617,11 +618,11 @@
 
     /**
      * We don't want to change mLauncherTransitionController if mGestureState.getEndTarget() == HOME
-     * (it has its own animation).
+     * (it has its own animation) or if we explicitly ended the controller already.
      * @return Whether we can create the launcher controller or update its progress.
      */
     private boolean canCreateNewOrUpdateExistingLauncherTransitionController() {
-        return mGestureState.getEndTarget() != HOME;
+        return mGestureState.getEndTarget() != HOME && !mHasEndedLauncherTransition;
     }
 
     @Override
@@ -1429,7 +1430,7 @@
     }
 
     private void invalidateHandler() {
-        if (!LIVE_TILE.get() || !mActivityInterface.isInLiveTileMode()
+        if (!ENABLE_QUICKSTEP_LIVE_TILE.get() || !mActivityInterface.isInLiveTileMode()
                 || mGestureState.getEndTarget() != RECENTS) {
             mInputConsumerProxy.destroy();
             mTaskAnimationManager.setLiveTileCleanUpHandler(null);
@@ -1455,6 +1456,8 @@
     }
 
     private void endLauncherTransitionController() {
+        mHasEndedLauncherTransition = true;
+
         if (mLauncherTransitionController != null) {
             // End the animation, but stay at the same visual progress.
             mLauncherTransitionController.getNormalController().dispatchSetInterpolator(
@@ -1474,7 +1477,7 @@
      */
     private void resetLauncherListeners() {
         // Reset the callback for deferred activity launches
-        if (!LIVE_TILE.get()) {
+        if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             mActivityInterface.setOnDeferredActivityLaunchCallback(null);
         }
         mActivity.getRootView().setOnApplyWindowInsetsListener(null);
@@ -1498,7 +1501,7 @@
             mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
         } else {
             final int runningTaskId = mGestureState.getRunningTaskId();
-            final boolean refreshView = !LIVE_TILE.get() /* refreshView */;
+            final boolean refreshView = !ENABLE_QUICKSTEP_LIVE_TILE.get() /* refreshView */;
             boolean finishTransitionPosted = false;
             if (mRecentsAnimationController != null) {
                 // Update the screenshot of the task
@@ -1554,7 +1557,7 @@
     }
 
     private void finishCurrentTransitionToRecents() {
-        if (LIVE_TILE.get()) {
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED);
             if (mRecentsAnimationController != null) {
                 mRecentsAnimationController.detachNavigationBarFromApp(true);
@@ -1608,7 +1611,7 @@
         }
         endLauncherTransitionController();
         mRecentsView.onSwipeUpAnimationSuccess();
-        if (LIVE_TILE.get()) {
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             mTaskAnimationManager.setLiveTileCleanUpHandler(mInputConsumerProxy::destroy);
             mTaskAnimationManager.enableLiveTileRestartListener();
         }
diff --git a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
index 906599f..f29d68a 100644
--- a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
@@ -15,6 +15,7 @@
  */
 package com.android.quickstep;
 
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
 import static com.android.quickstep.fallback.RecentsState.BACKGROUND_APP;
 import static com.android.quickstep.fallback.RecentsState.DEFAULT;
@@ -105,8 +106,12 @@
     @Override
     public RecentsView getVisibleRecentsView() {
         RecentsActivity activity = getCreatedActivity();
-        if (activity != null && activity.hasBeenResumed()) {
-            return activity.getOverviewPanel();
+        if (activity != null) {
+            RecentsView recentsView = activity.getOverviewPanel();
+            if (activity.hasBeenResumed() || (ENABLE_QUICKSTEP_LIVE_TILE.get() && isInLiveTileMode()
+                    && recentsView.getRunningTaskId() == -1)) {
+                return recentsView;
+            }
         }
         return null;
     }
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index 385b3b4..e3ae361 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -378,11 +378,14 @@
     }
 
     /**
-     * Returns the canceled animation thumbnail data. This call only returns a value while
-     * STATE_RECENTS_ANIMATION_CANCELED state is being set.
+     * Returns and clears the canceled animation thumbnail data. This call only returns a value
+     * while STATE_RECENTS_ANIMATION_CANCELED state is being set, and the caller is responsible for
+     * calling {@link RecentsAnimationController#cleanupScreenshot()}.
      */
-    ThumbnailData getRecentsAnimationCanceledSnapshot() {
-        return mRecentsAnimationCanceledSnapshot;
+    ThumbnailData consumeRecentsAnimationCanceledSnapshot() {
+        ThumbnailData data = mRecentsAnimationCanceledSnapshot;
+        mRecentsAnimationCanceledSnapshot = null;
+        return data;
     }
 
     void setSwipeUpStartTimeMs(long uptimeMs) {
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 30abfbb..fb1391a 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -21,6 +21,7 @@
 import static com.android.launcher3.LauncherState.QUICK_SWITCH;
 import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 
 import android.animation.Animator;
@@ -184,16 +185,24 @@
     @Override
     public RecentsView getVisibleRecentsView() {
         Launcher launcher = getVisibleLauncher();
-        return launcher != null && launcher.getStateManager().getState().overviewUi
-                ? launcher.getOverviewPanel() : null;
+        RecentsView recentsView =
+                launcher != null && launcher.getStateManager().getState().overviewUi
+                        ? launcher.getOverviewPanel() : null;
+        if (recentsView == null || (!launcher.hasBeenResumed()
+                && recentsView.getRunningTaskId() == -1)) {
+            // If live tile has ended, return null.
+            return null;
+        }
+        return recentsView;
     }
 
     @Nullable
     @UiThread
     private Launcher getVisibleLauncher() {
         Launcher launcher = getCreatedActivity();
-        return (launcher != null) && launcher.isStarted() && launcher.hasBeenResumed()
-                ? launcher : null;
+        return (launcher != null) && launcher.isStarted()
+                && ((ENABLE_QUICKSTEP_LIVE_TILE.get() && isInLiveTileMode())
+                || launcher.hasBeenResumed()) ? launcher : null;
     }
 
     @Override
@@ -202,6 +211,12 @@
         if (launcher == null) {
             return false;
         }
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isInLiveTileMode()) {
+            RecentsView recentsView = getVisibleRecentsView();
+            if (recentsView == null) {
+                return false;
+            }
+        }
 
         closeOverlay();
         launcher.getStateManager().goToState(OVERVIEW,
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 2beef0a..742d02d 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -15,6 +15,7 @@
  */
 package com.android.quickstep;
 
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
 
diff --git a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
index 192738f..65847f1 100644
--- a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
+++ b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
@@ -15,8 +15,6 @@
  */
 package com.android.quickstep;
 
-import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
-
 import android.annotation.TargetApi;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -61,8 +59,6 @@
 
         super.init(context);
 
-        LIVE_TILE.initialize(context);
-
         // Elevate GPU priority for Quickstep and Remote animations.
         ThreadedRendererCompat.setContextPriority(
                 ThreadedRendererCompat.EGL_CONTEXT_PRIORITY_HIGH_IMG);
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index fa5ab1c..9dfcd12 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -23,10 +23,10 @@
 import static com.android.launcher3.QuickstepTransitionManager.STATUS_BAR_TRANSITION_PRE_DELAY;
 import static com.android.launcher3.Utilities.createHomeIntent;
 import static com.android.launcher3.graphics.SysUiScrim.SYSUI_PROGRESS;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
 import static com.android.quickstep.TaskUtils.taskIsATargetWithMode;
 import static com.android.quickstep.TaskViewUtils.createRecentsWindowAnimator;
-import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
 
@@ -359,7 +359,7 @@
     }
 
     public void startHome() {
-        if (LIVE_TILE.get()) {
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             RecentsView recentsView = getOverviewPanel();
             recentsView.switchToScreenshot(() -> recentsView.finishRecentsAnimation(true,
                     this::startHomeInternal));
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index 223c46d..6c445e1 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -15,11 +15,11 @@
  */
 package com.android.quickstep;
 
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED;
 import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_STARTED;
-import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
 
 import android.app.ActivityManager;
 import android.content.Context;
@@ -64,7 +64,7 @@
                 return;
             }
             BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface();
-            if (LIVE_TILE.get() && activityInterface.isInLiveTileMode()
+            if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityInterface.isInLiveTileMode()
                     && activityInterface.getCreatedActivity() != null) {
                 RecentsView recentsView = activityInterface.getCreatedActivity().getOverviewPanel();
                 if (recentsView != null) {
@@ -139,7 +139,7 @@
             @Override
             public void onTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {
                 BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface();
-                if (LIVE_TILE.get() && activityInterface.isInLiveTileMode()
+                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityInterface.isInLiveTileMode()
                         && activityInterface.getCreatedActivity() != null) {
                     RecentsView recentsView =
                             activityInterface.getCreatedActivity().getOverviewPanel();
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index c1c85de..06a3c70 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -18,7 +18,7 @@
 
 import static android.view.Surface.ROTATION_0;
 
-import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.quickstep.views.OverviewActionsView.DISABLED_NO_THUMBNAIL;
 import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED;
 
@@ -88,6 +88,7 @@
             SystemShortcut screenshotShortcut = TaskShortcutFactory.SCREENSHOT
                     .getShortcut(activity, taskView);
             if (screenshotShortcut != null) {
+                screenshotShortcut.setHasFinishRecentsInAction(true);
                 shortcuts.add(screenshotShortcut);
             }
 
@@ -96,6 +97,7 @@
                 SystemShortcut modalShortcut = TaskShortcutFactory.MODAL
                         .getShortcut(activity, taskView);
                 if (modalShortcut != null) {
+                    modalShortcut.setHasFinishRecentsInAction(true);
                     shortcuts.add(modalShortcut);
                 }
             }
@@ -187,7 +189,7 @@
          * @param callback callback to run, after switching to screenshot
          */
         public void endLiveTileMode(@NonNull Runnable callback) {
-            if (LIVE_TILE.get()) {
+            if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
                 RecentsView recentsView = mThumbnailView.getTaskView().getRecentsView();
                 recentsView.switchToScreenshot(
                         () -> recentsView.finishRecentsAnimation(true /* toRecents */,
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 3293810..37fda73 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -34,7 +34,6 @@
 import static com.android.launcher3.anim.Interpolators.clampToProgress;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.launcher3.statehandlers.DepthController.DEPTH;
-import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
 
@@ -155,7 +154,7 @@
         boolean isRunningTask = v.isRunningTask();
         TransformParams params = null;
         TaskViewSimulator tsv = null;
-        if (LIVE_TILE.get() && isRunningTask) {
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask) {
             params = v.getRecentsView().getLiveTileParams();
             tsv = v.getRecentsView().getLiveTileTaskViewSimulator();
         }
@@ -176,7 +175,8 @@
         boolean isQuickSwitch = v.isEndQuickswitchCuj();
         v.setEndQuickswitchCuj(false);
 
-        boolean inLiveTileMode = LIVE_TILE.get() && v.getRecentsView().getRunningTaskIndex() != -1;
+        boolean inLiveTileMode =
+                ENABLE_QUICKSTEP_LIVE_TILE.get() && v.getRecentsView().getRunningTaskIndex() != -1;
         final RemoteAnimationTargets targets =
                 new RemoteAnimationTargets(appTargets, wallpaperTargets, nonAppTargets,
                         inLiveTileMode ? MODE_CLOSING : MODE_OPENING);
@@ -531,7 +531,7 @@
             };
         }
         pa.add(launcherAnim);
-        if (LIVE_TILE.get() && recentsView.getRunningTaskIndex() != -1) {
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get() && recentsView.getRunningTaskIndex() != -1) {
             pa.addOnFrameCallback(recentsView::redrawLiveTile);
         }
         anim.play(pa.buildAnim());
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 84f7e83..069ed11 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -21,9 +21,9 @@
 import static android.view.MotionEvent.ACTION_UP;
 
 import static com.android.launcher3.config.FeatureFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.quickstep.GestureState.DEFAULT_STATE;
-import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_ONE_HANDED;
 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_PIP;
@@ -737,7 +737,8 @@
                     runningComponent != null && runningComponent.equals(homeComponent);
         }
 
-        if (LIVE_TILE.get() && gestureState.getActivityInterface().isInLiveTileMode()) {
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get()
+                && gestureState.getActivityInterface().isInLiveTileMode()) {
             return createOverviewInputConsumer(
                     previousGestureState, gestureState, event, forceOverviewInputConsumer);
         } else if (gestureState.getRunningTask() == null) {
@@ -792,7 +793,8 @@
                 || previousGestureState.isRunningAnimationToLauncher()
                 || (ASSISTANT_GIVES_LAUNCHER_FOCUS.get()
                     && forceOverviewInputConsumer)
-                || (LIVE_TILE.get()) && gestureState.getActivityInterface().isInLiveTileMode()) {
+                || (ENABLE_QUICKSTEP_LIVE_TILE.get()
+                && gestureState.getActivityInterface().isInLiveTileMode())) {
             return new OverviewInputConsumer(gestureState, activity, mInputMonitorCompat,
                     false /* startingInActivityBounds */);
         } else {
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java b/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java
index 273d1f6..eca61bb 100644
--- a/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java
+++ b/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java
@@ -15,7 +15,7 @@
  */
 package com.android.quickstep.fallback;
 
-import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 
 import com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController;
 import com.android.quickstep.RecentsActivity;
@@ -28,7 +28,7 @@
 
     @Override
     protected boolean isRecentsInteractive() {
-        return mActivity.hasWindowFocus() || (LIVE_TILE.get()
+        return mActivity.hasWindowFocus() || (ENABLE_QUICKSTEP_LIVE_TILE.get()
                 && mActivity.getStateManager().getState().hasLiveTile());
     }
 
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
index 4af6338..b0df286 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
@@ -15,7 +15,7 @@
  */
 package com.android.quickstep.inputconsumers;
 
-import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
 
 import android.media.AudioManager;
@@ -102,7 +102,7 @@
 
     @Override
     public void onKeyEvent(KeyEvent ev) {
-        if (LIVE_TILE.get()) {
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             switch (ev.getKeyCode()) {
                 case KeyEvent.KEYCODE_VOLUME_DOWN:
                 case KeyEvent.KEYCODE_VOLUME_UP:
diff --git a/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java b/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java
deleted file mode 100644
index 60c7add..0000000
--- a/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2021 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_QUICKSTEP_LIVE_TILE;
-
-import android.content.Context;
-
-import com.android.quickstep.SysUINavigationMode;
-
-import java.util.function.Predicate;
-import java.util.function.Supplier;
-
-/** A feature flag that listens to navigation mode changes. */
-public class NavigationModeFeatureFlag implements
-        SysUINavigationMode.NavigationModeChangeListener {
-
-    public static final NavigationModeFeatureFlag LIVE_TILE = new NavigationModeFeatureFlag(
-            ENABLE_QUICKSTEP_LIVE_TILE::get, mode -> mode.hasGestures);
-
-    private final Supplier<Boolean> mBasePredicate;
-    private final Predicate<SysUINavigationMode.Mode> mModePredicate;
-    private boolean mSupported;
-
-    private NavigationModeFeatureFlag(Supplier<Boolean> basePredicate,
-            Predicate<SysUINavigationMode.Mode> modePredicate) {
-        mBasePredicate = basePredicate;
-        mModePredicate = modePredicate;
-    }
-
-    public boolean get() {
-        return mBasePredicate.get() && mSupported;
-    }
-
-    public void initialize(Context context) {
-        onNavigationModeChanged(SysUINavigationMode.INSTANCE.get(context).getMode());
-        SysUINavigationMode.INSTANCE.get(context).addModeChangeListener(this);
-    }
-
-    @Override
-    public void onNavigationModeChanged(SysUINavigationMode.Mode newMode) {
-        mSupported = mModePredicate.test(newMode);
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index b15bbf3..c97ca32 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -15,9 +15,9 @@
  */
 package com.android.quickstep.util;
 
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.launcher3.states.RotationHelper.deltaRotation;
 import static com.android.launcher3.touch.PagedOrientationHandler.MATRIX_POST_TRANSLATE;
-import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
 import static com.android.quickstep.util.RecentsOrientedState.postDisplayRotation;
 import static com.android.quickstep.util.RecentsOrientedState.preDisplayRotation;
 import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_FULLSCREEN;
@@ -302,7 +302,7 @@
                 .withWindowCrop(mTmpCropRect)
                 .withCornerRadius(getCurrentCornerRadius());
 
-        if (LIVE_TILE.get() && params.getRecentsSurface() != null) {
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get() && params.getRecentsSurface() != null) {
             // When relativeLayer = 0, it reverts the surfaces back to the original order.
             builder.withRelativeLayerTo(params.getRecentsSurface(),
                     mDrawsBelowRecents ? Integer.MIN_VALUE : 0);
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 1b1066a..d9b229a 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -38,6 +38,7 @@
 import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.anim.Interpolators.clampToProgress;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN;
@@ -47,7 +48,6 @@
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK;
 import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
-import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
 import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION;
 import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS;
 import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS;
@@ -131,6 +131,7 @@
 import com.android.launcher3.util.MultiValueAlpha;
 import com.android.launcher3.util.ResourceBasedOverride.Overrides;
 import com.android.launcher3.util.SplitConfigurationOptions;
+import com.android.launcher3.util.RunnableList;
 import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.util.TranslateEdgeEffect;
@@ -496,6 +497,7 @@
     private float mFocusedTaskRatio;
 
     private boolean mRunningTaskIconScaledDown = false;
+    private boolean mRunningTaskShowScreenshot = false;
 
     private boolean mOverviewStateEnabled;
     private boolean mHandleTaskStackChanges;
@@ -573,6 +575,8 @@
                 }
             };
 
+    private RunnableList mSideTaskLaunchCallback;
+
     public RecentsView(Context context, AttributeSet attrs, int defStyleAttr,
             BaseActivityInterface sizeStrategy) {
         super(context, attrs, defStyleAttr);
@@ -677,7 +681,8 @@
             }
             super.dispatchDraw(canvas);
         }
-        if (LIVE_TILE.get() && mEnableDrawingLiveTile && mLiveTileParams.getTargetSet() != null) {
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile
+                && mLiveTileParams.getTargetSet() != null) {
             redrawLiveTile();
         }
     }
@@ -801,6 +806,7 @@
         TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
         mSyncTransactionApplier = null;
         mLiveTileParams.setSyncTransactionApplier(null);
+        executeSideTaskLaunchCallback();
         RecentsModel.INSTANCE.get(getContext()).removeThumbnailChangeListener(this);
         SystemUiProxy.INSTANCE.get(getContext()).setPinnedStackAnimationListener(null);
         SplitScreenBounds.INSTANCE.removeOnChangeListener(this);
@@ -842,11 +848,27 @@
         super.draw(canvas);
     }
 
+    public void addSideTaskLaunchCallback(RunnableList callback) {
+        if (mSideTaskLaunchCallback == null) {
+            mSideTaskLaunchCallback = new RunnableList();
+        }
+        mSideTaskLaunchCallback.add(callback::executeAllAndDestroy);
+    }
+
+    private void executeSideTaskLaunchCallback() {
+        if (mSideTaskLaunchCallback != null) {
+            mSideTaskLaunchCallback.executeAllAndDestroy();
+            mSideTaskLaunchCallback = null;
+        }
+    }
+
     public void launchSideTaskInLiveTileModeForRestartedApp(int taskId) {
-        if (mRunningTaskId != -1 && mRunningTaskId == taskId &&
-                getLiveTileParams().getTargetSet().findTask(taskId) != null) {
+        if (mRunningTaskId != -1 && mRunningTaskId == taskId) {
             RemoteAnimationTargets targets = getLiveTileParams().getTargetSet();
-            launchSideTaskInLiveTileMode(taskId, targets.apps, targets.wallpapers, targets.nonApps);
+            if (targets != null && targets.findTask(taskId) != null) {
+                launchSideTaskInLiveTileMode(taskId, targets.apps, targets.wallpapers,
+                        targets.nonApps);
+            }
         }
     }
 
@@ -883,8 +905,8 @@
             TaskViewUtils.composeRecentsLaunchAnimator(anim, taskView, apps, wallpaper, nonApps,
                     true /* launcherClosing */, mActivity.getStateManager(), this,
                     getDepthController());
+            anim.start();
         }
-        anim.start();
     }
 
     private void updateTaskStartIndex(View affectingView) {
@@ -1087,6 +1109,12 @@
             return;
         }
 
+        int currentTaskId = -1;
+        TaskView currentTaskView = getTaskViewAtByAbsoluteIndex(mCurrentPage);
+        if (currentTaskView != null) {
+            currentTaskId = currentTaskView.getTask().key.id;
+        }
+
         // Unload existing visible task data
         unloadVisibleTaskData(TaskView.FLAG_UPDATE_ALL);
 
@@ -1126,6 +1154,11 @@
             } else if (getTaskViewCount() > 0) {
                 setCurrentPage(indexOfChild(getTaskViewAt(0)));
             }
+        } else if (currentTaskId != -1) {
+            currentTaskView = getTaskView(currentTaskId);
+            if (currentTaskView != null) {
+                setCurrentPage(indexOfChild(currentTaskView));
+            }
         }
 
         if (mIgnoreResetTaskId != -1 && getTaskView(mIgnoreResetTaskId) != ignoreResetTaskView) {
@@ -1179,7 +1212,7 @@
                 taskView.setModalness(mTaskModalness);
             }
         }
-        if (LIVE_TILE.get()) {
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             // Since we reuse the same mLiveTileTaskViewSimulator in the RecentsView, we need
             // to reset the params after it settles in Overview from swipe up so that we don't
             // render with obsolete param values.
@@ -1187,6 +1220,12 @@
             mLiveTileTaskViewSimulator.taskSecondaryTranslation.value = 0;
             mLiveTileTaskViewSimulator.fullScreenProgress.value = 0;
             mLiveTileTaskViewSimulator.recentsViewScale.value = 1;
+
+            // Similar to setRunningTaskHidden below, reapply the state before runningTaskView is
+            // null.
+            if (!mRunningTaskShowScreenshot) {
+                setRunningTaskViewShowScreenshot(mRunningTaskShowScreenshot);
+            }
         }
         if (mRunningTaskTileHidden) {
             setRunningTaskHidden(mRunningTaskTileHidden);
@@ -1247,8 +1286,14 @@
     }
 
     private void updateOrientationHandler() {
+        updateOrientationHandler(true);
+    }
+
+    private void updateOrientationHandler(boolean forceRecreateDragLayerControllers) {
         // Handle orientation changes.
+        PagedOrientationHandler oldOrientationHandler = mOrientationHandler;
         mOrientationHandler = mOrientationState.getOrientationHandler();
+
         mIsRtl = mOrientationHandler.getRecentsRtlSetting(getResources());
         setLayoutDirection(mIsRtl
                 ? View.LAYOUT_DIRECTION_RTL
@@ -1257,7 +1302,13 @@
                 ? View.LAYOUT_DIRECTION_LTR
                 : View.LAYOUT_DIRECTION_RTL);
         mClearAllButton.setRotation(mOrientationHandler.getDegreesRotated());
-        mActivity.getDragLayer().recreateControllers();
+
+        if (forceRecreateDragLayerControllers
+                || !mOrientationHandler.equals(oldOrientationHandler)) {
+            // Changed orientations, update controllers so they intercept accordingly.
+            mActivity.getDragLayer().recreateControllers();
+        }
+
         boolean isInLandscape = mOrientationState.getTouchRotation() != ROTATION_0
                 || mOrientationState.getRecentsActivityRotation() != ROTATION_0;
         mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION,
@@ -1559,7 +1610,7 @@
         mFocusedTaskId = -1;
 
         if (mRecentsAnimationController != null) {
-            if (LIVE_TILE.get() && mEnableDrawingLiveTile) {
+            if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile) {
                 // We are still drawing the live tile, finish it now to clean up.
                 finishRecentsAnimation(true /* toRecents */, null);
             } else {
@@ -1577,7 +1628,7 @@
             setCurrentPage(0);
             LayoutUtils.setViewEnabled(mActionsView, true);
             if (mOrientationState.setGestureActive(false)) {
-                updateOrientationHandler();
+                updateOrientationHandler(/* forceRecreateDragLayerControllers = */ false);
             }
         });
     }
@@ -1731,7 +1782,7 @@
 
         setEnableFreeScroll(true);
         setEnableDrawingLiveTile(mCurrentGestureEndTarget == GestureState.GestureEndTarget.RECENTS);
-        if (!LIVE_TILE.get()) {
+        if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             setRunningTaskViewShowScreenshot(true);
         }
         setRunningTaskHidden(false);
@@ -1837,10 +1888,11 @@
     }
 
     private void setRunningTaskViewShowScreenshot(boolean showScreenshot) {
-        if (LIVE_TILE.get()) {
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+            mRunningTaskShowScreenshot = showScreenshot;
             TaskView runningTaskView = getRunningTaskView();
             if (runningTaskView != null) {
-                runningTaskView.setShowScreenshot(showScreenshot);
+                runningTaskView.setShowScreenshot(mRunningTaskShowScreenshot);
             }
         }
     }
@@ -2230,7 +2282,8 @@
         anim.add(ObjectAnimator.ofFloat(taskView, dismissingTaskViewTranslate,
                 positiveNegativeFactor * translateDistance * 2).setDuration(duration), LINEAR, sp);
 
-        if (LIVE_TILE.get() && mEnableDrawingLiveTile && taskView.isRunningTask()) {
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile
+                && taskView.isRunningTask()) {
             anim.addOnFrameCallback(() -> {
                 mLiveTileTaskViewSimulator.taskSecondaryTranslation.value =
                         mOrientationHandler.getSecondaryValue(
@@ -2310,7 +2363,8 @@
                     anim.setFloat(child, translationProperty, scrollDiff, clampToProgress(LINEAR,
                             Utilities.boundToRange(INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
                                     + additionalDismissDuration, 0f, 1f), 1));
-                    if (LIVE_TILE.get() && mEnableDrawingLiveTile && child instanceof TaskView
+                    if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile
+                            && child instanceof TaskView
                             && ((TaskView) child).isRunningTask()) {
                         anim.addOnFrameCallback(() -> {
                             mLiveTileTaskViewSimulator.taskPrimaryTranslation.value =
@@ -2354,8 +2408,8 @@
         mPendingAnimation.addEndListener(new Consumer<Boolean>() {
             @Override
             public void accept(Boolean success) {
-                if (LIVE_TILE.get() && mEnableDrawingLiveTile && taskView.isRunningTask()
-                        && success) {
+                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile
+                        && taskView.isRunningTask() && success) {
                     finishRecentsAnimation(true /* toRecents */, false /* shouldPip */,
                             () -> onEnd(success));
                 } else {
@@ -2368,7 +2422,7 @@
                 if (success) {
                     if (shouldRemoveTask) {
                         if (taskView.getTask() != null) {
-                            if (LIVE_TILE.get() && taskView.isRunningTask()) {
+                            if (ENABLE_QUICKSTEP_LIVE_TILE.get() && taskView.isRunningTask()) {
                                 finishRecentsAnimation(true /* toRecents */, false /* shouldPip */,
                                         () -> removeTaskInternal(taskView));
                             } else {
@@ -2805,7 +2859,8 @@
                     ? ((TaskView) child).getPrimaryTaskOffsetTranslationProperty()
                     : mOrientationHandler.getPrimaryViewTranslate();
             translationProperty.set(child, totalTranslation);
-            if (LIVE_TILE.get() && mEnableDrawingLiveTile && i == getRunningTaskIndex()) {
+            if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile
+                    && i == getRunningTaskIndex()) {
                 mLiveTileTaskViewSimulator.taskPrimaryTranslation.value = totalTranslation;
                 redrawLiveTile();
             }
@@ -3164,7 +3219,7 @@
             anim.play(ObjectAnimator.ofFloat(getPageAt(centerTaskIndex),
                     mOrientationHandler.getPrimaryViewTranslate(), primaryTranslation));
             int runningTaskIndex = recentsView.getRunningTaskIndex();
-            if (LIVE_TILE.get() && runningTaskIndex != -1
+            if (ENABLE_QUICKSTEP_LIVE_TILE.get() && runningTaskIndex != -1
                     && runningTaskIndex != taskIndex) {
                 anim.play(ObjectAnimator.ofFloat(
                         recentsView.getLiveTileTaskViewSimulator().taskPrimaryTranslation,
@@ -3248,13 +3303,13 @@
 
         mPendingAnimation = new PendingAnimation(duration);
         mPendingAnimation.add(anim);
-        if (LIVE_TILE.get()) {
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             mLiveTileTaskViewSimulator.addOverviewToAppAnim(mPendingAnimation, interpolator);
             mPendingAnimation.addOnFrameCallback(this::redrawLiveTile);
         }
         mPendingAnimation.addEndListener(isSuccess -> {
             if (isSuccess) {
-                if (LIVE_TILE.get() && tv.isRunningTask()) {
+                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && tv.isRunningTask()) {
                     finishRecentsAnimation(false /* toRecents */, null);
                     onTaskLaunchAnimationEnd(true /* success */);
                 } else {
@@ -3373,7 +3428,7 @@
 
     public void finishRecentsAnimation(boolean toRecents, boolean shouldPip,
             Runnable onFinishComplete) {
-        if (!toRecents && LIVE_TILE.get()) {
+        if (!toRecents && ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             // Reset the minimized state since we force-toggled the minimized state when entering
             // overview, but never actually finished the recents animation.  This is a catch all for
             // cases where we haven't already reset it.
@@ -3419,6 +3474,7 @@
         // taps on QSB (3) user goes back to Overview and launch the most recent task.
         setCurrentTask(-1);
         mRecentsAnimationController = null;
+        executeSideTaskLaunchCallback();
     }
 
     public void setDisallowScrollToClearAll(boolean disallowScrollToClearAll) {
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index d663635..2c6533c 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -16,7 +16,7 @@
 
 package com.android.quickstep.views;
 
-import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA;
 
 import android.animation.Animator;
@@ -220,7 +220,7 @@
         menuOptionView.setEnabled(menuOption.isEnabled());
         menuOptionView.setAlpha(menuOption.isEnabled() ? 1 : 0.5f);
         menuOptionView.setOnClickListener(view -> {
-            if (LIVE_TILE.get()) {
+            if (ENABLE_QUICKSTEP_LIVE_TILE.get() && !menuOption.hasFinishRecentsInAction()) {
                 RecentsView recentsView = mTaskView.getRecentsView();
                 recentsView.switchToScreenshot(null,
                         () -> recentsView.finishRecentsAnimation(true /* toRecents */,
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index f730d2d..c70596d 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -19,7 +19,8 @@
 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
 
-import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
+import static com.android.launcher3.Utilities.comp;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_FULLSCREEN;
 
 import android.content.Context;
@@ -306,10 +307,19 @@
 
     public void drawOnCanvas(Canvas canvas, float x, float y, float width, float height,
             float cornerRadius) {
-        if (LIVE_TILE.get()) {
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             if (mTask != null && getTaskView().isRunningTask() && !getTaskView().showScreenshot()) {
-                canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mClearPaint);
-                canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius,
+                // TODO(b/189265196): Temporary fix to align the surface with the cutout perfectly.
+                // Round up only when the live tile task is displayed in Overview.
+                float rounding = comp(mFullscreenParams.mFullscreenProgress);
+                float left = x + rounding / 2;
+                float top = y + rounding / 2;
+                float right = width - rounding;
+                float bottom = height - rounding;
+
+                canvas.drawRoundRect(left, top, right, bottom, cornerRadius, cornerRadius,
+                        mClearPaint);
+                canvas.drawRoundRect(left, top, right, bottom, cornerRadius, cornerRadius,
                         mDimmingPaintAfterClearing);
                 return;
             }
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index ae429d9..6738e7d 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -34,11 +34,11 @@
 import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
 import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
@@ -540,7 +540,7 @@
         if (getTask() == null) {
             return;
         }
-        if (LIVE_TILE.get() && isRunningTask()) {
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask()) {
             if (!mIsClickableAsLiveTile) {
                 return;
             }
@@ -608,6 +608,13 @@
             ActivityOptionsWrapper opts =  mActivity.getActivityLaunchOptions(this, null);
             if (ActivityManagerWrapper.getInstance()
                     .startActivityFromRecents(mTask.key, opts.options)) {
+                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && getRecentsView().getRunningTaskId() != -1) {
+                    // Return a fresh callback in the live tile case, so that it's not accidentally
+                    // triggered by QuickstepTransitionManager.AppLaunchAnimationRunner.
+                    RunnableList callbackList = new RunnableList();
+                    getRecentsView().addSideTaskLaunchCallback(callbackList);
+                    return callbackList;
+                }
                 return opts.onEndCallback;
             } else {
                 notifyTaskLaunchFailed(TAG);
@@ -1482,6 +1489,7 @@
         private final float mCornerRadius;
         private final float mWindowCornerRadius;
 
+        public float mFullscreenProgress;
         public RectF mCurrentDrawnInsets = new RectF();
         public float mCurrentDrawnCornerRadius;
         /** The current scale we apply to the thumbnail to adjust for new left/right insets. */
@@ -1499,6 +1507,7 @@
          */
         public void setProgress(float fullscreenProgress, float parentScale, int previewWidth,
                 DeviceProfile dp, PreviewPositionHelper pph) {
+            mFullscreenProgress = fullscreenProgress;
             RectF insets = pph.getInsetsToDrawInFullscreen();
 
             float currentInsetsLeft = insets.left * fullscreenProgress;
diff --git a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
index 4f27e21..dc73a9a 100644
--- a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
+++ b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
@@ -16,7 +16,7 @@
 
 package com.android.quickstep;
 
-import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 
 import static org.junit.Assert.assertTrue;
 
@@ -75,7 +75,7 @@
 
     private boolean isInLiveTileMode(Launcher launcher,
             LauncherInstrumentation.ContainerType expectedContainerType) {
-        if (!LIVE_TILE.get()
+        if (!ENABLE_QUICKSTEP_LIVE_TILE.get()
                 || expectedContainerType != LauncherInstrumentation.ContainerType.OVERVIEW) {
             return false;
         }
diff --git a/res/drawable/rounded_action_button.xml b/res/drawable/rounded_action_button.xml
index 0c8755f..f043893 100644
--- a/res/drawable/rounded_action_button.xml
+++ b/res/drawable/rounded_action_button.xml
@@ -19,7 +19,7 @@
     xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     android:shape="rectangle">
     <corners android:radius="@dimen/rounded_button_radius" />
-    <stroke android:width="1dp" android:color="?androidprv:attr/colorAccentPrimaryVariant" />
+    <stroke android:width="1dp" android:color="@color/all_apps_tab_background_selected" />
     <padding
         android:left="@dimen/rounded_button_padding"
         android:right="@dimen/rounded_button_padding" />
diff --git a/res/drawable/work_card.xml b/res/drawable/work_card.xml
index 0e4b054..7048955 100644
--- a/res/drawable/work_card.xml
+++ b/res/drawable/work_card.xml
@@ -20,8 +20,5 @@
     android:shape="rectangle">
     <solid android:color="?androidprv:attr/colorSurface" />
     <corners android:radius="@dimen/work_edu_card_margin" />
-    <padding
-        android:left="@dimen/work_fab_radius"
-        android:right="@dimen/work_fab_radius" />
 </shape>
 
diff --git a/res/layout/work_apps_edu.xml b/res/layout/work_apps_edu.xml
index 919f1b2..2a3d154 100644
--- a/res/layout/work_apps_edu.xml
+++ b/res/layout/work_apps_edu.xml
@@ -16,13 +16,15 @@
 <com.android.launcher3.allapps.WorkEduCard xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:layout_marginTop="8dp"
     android:gravity="center">
 
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical"
-        android:padding="@dimen/work_edu_card_margin"
+        android:paddingHorizontal="@dimen/work_card_padding_horizontal"
+        android:paddingVertical="@dimen/work_card_padding_vertical"
         android:background="@drawable/work_card"
         android:layout_gravity="center_horizontal"
         android:gravity="center"
@@ -34,8 +36,7 @@
             android:id="@+id/work_apps_paused_title"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginTop="8dp"
-            android:layout_marginBottom="8dp"
+            android:layout_marginBottom="@dimen/work_card_padding_vertical"
             android:text="@string/work_profile_edu_work_apps"
             android:textAlignment="center"
             android:textSize="20sp" />
diff --git a/res/layout/work_apps_paused.xml b/res/layout/work_apps_paused.xml
index 02a50ca..ec34b47 100644
--- a/res/layout/work_apps_paused.xml
+++ b/res/layout/work_apps_paused.xml
@@ -28,18 +28,18 @@
         android:layout_marginTop="40dp"
         android:text="@string/work_apps_paused_title"
         android:textAlignment="center"
-        android:textSize="20sp" />
+        android:textSize="22sp" />
 
     <TextView
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:id="@+id/work_apps_paused_content"
-        android:textColor="?attr/workProfileOverlayTextColor"
+        android:textColor="?android:attr/textColorSecondary"
         android:text="@string/work_apps_paused_body"
         android:textAlignment="center"
         android:layout_marginTop="16dp"
         android:layout_marginBottom="24dp"
-        android:textSize="16sp" />
+        android:textSize="14sp" />
 
     <Button
         android:layout_width="wrap_content"
@@ -49,5 +49,7 @@
         android:text="@string/work_apps_enable_btn_text"
         android:textAlignment="center"
         android:background="@drawable/rounded_action_button"
+        android:paddingStart="16dp"
+        android:paddingEnd="16dp"
         android:textSize="14sp" />
 </com.android.launcher3.allapps.WorkPausedCard>
\ No newline at end of file
diff --git a/res/layout/work_mode_fab.xml b/res/layout/work_mode_fab.xml
index 7183817..04faa15 100644
--- a/res/layout/work_mode_fab.xml
+++ b/res/layout/work_mode_fab.xml
@@ -25,7 +25,7 @@
     android:textColor="@color/all_apps_tab_text"
     android:textSize="14sp"
     android:background="@drawable/work_apps_toggle_background"
-    android:drawablePadding="16dp"
+    android:drawablePadding="8dp"
     android:drawableStart="@drawable/ic_corp_off"
     android:layout_marginBottom="@dimen/work_fab_margin"
     android:layout_marginEnd="@dimen/work_fab_margin"
diff --git a/res/values-sw340dp/dimens.xml b/res/values-sw340dp/dimens.xml
index c9f2981..33b06f5 100644
--- a/res/values-sw340dp/dimens.xml
+++ b/res/values-sw340dp/dimens.xml
@@ -19,6 +19,5 @@
 
     <!-- Drag padding to add to the bottom of drop targets -->
     <dimen name="drop_target_drag_padding">20dp</dimen>
-    <dimen name="drop_target_text_size">16sp</dimen>
 
 </resources>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 270c92e..2a2cf89 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -119,14 +119,15 @@
     <dimen name="all_apps_divider_margin_vertical">8dp</dimen>
 
 <!-- Floating action button inside work tab to toggle work profile -->
-    <dimen name="work_fab_height">48dp</dimen>
+    <dimen name="work_fab_height">56dp</dimen>
     <dimen name="work_fab_radius">24dp</dimen>
+    <dimen name="work_card_padding_horizontal">24dp</dimen>
+    <dimen name="work_card_padding_vertical">32dp</dimen>
     <dimen name="work_fab_margin">16dp</dimen>
     <dimen name="work_profile_footer_padding">20dp</dimen>
     <dimen name="work_profile_footer_text_size">16sp</dimen>
     <dimen name="work_edu_card_margin">16dp</dimen>
 
-    <!-- rounded button shown inside card views, and snack bars  -->
     <dimen name="rounded_button_height">32dp</dimen>
     <dimen name="rounded_button_radius">16dp</dimen>
     <dimen name="rounded_button_padding">8dp</dimen>
@@ -189,8 +190,9 @@
 <!-- Dragging -->
     <!-- Drag padding to add to the bottom of drop targets -->
     <dimen name="drop_target_drag_padding">14dp</dimen>
-    <dimen name="drop_target_text_size">20sp</dimen>
+    <dimen name="drop_target_text_size">16sp</dimen>
     <dimen name="drop_target_shadow_elevation">2dp</dimen>
+    <dimen name="drop_target_bar_margin_horizontal">4dp</dimen>
 
     <!-- the distance an icon must be dragged before button drop targets accept it -->
     <dimen name="drag_distanceThreshold">30dp</dimen>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 416c711..24851f2 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -258,7 +258,7 @@
     <!-- Drop targets -->
     <style name="DropTargetButtonBase" parent="@android:style/TextAppearance.DeviceDefault">
         <item name="android:drawablePadding">8dp</item>
-        <item name="android:padding">16dp</item>
+        <item name="android:padding">14dp</item>
         <item name="android:textColor">@color/drop_target_text</item>
         <item name="android:textSize">@dimen/drop_target_text_size</item>
         <item name="android:singleLine">true</item>
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 23dd3bb..61b5564 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -20,15 +20,12 @@
 
 import static com.android.launcher3.LauncherState.NORMAL;
 
-import android.animation.AnimatorSet;
 import android.content.Context;
-import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
 import android.util.AttributeSet;
-import android.util.Property;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -40,6 +37,7 @@
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.dragndrop.DragOptions;
+import com.android.launcher3.dragndrop.DragView;
 import com.android.launcher3.model.data.ItemInfo;
 
 /**
@@ -212,18 +210,23 @@
             return;
         }
         final DragLayer dragLayer = mLauncher.getDragLayer();
+        final DragView dragView = d.dragView;
         final Rect from = new Rect();
         dragLayer.getViewRectRelativeToSelf(d.dragView, from);
 
         final Rect to = getIconRect(d);
         final float scale = (float) to.width() / from.width();
-        d.dragView.detachContentView(/* reattachToPreviousParent= */ true);
+        dragView.disableColorExtraction();
+        dragView.detachContentView(/* reattachToPreviousParent= */ true);
         mDropTargetBar.deferOnDragEnd();
 
         Runnable onAnimationEndRunnable = () -> {
             completeDrop(d);
             mDropTargetBar.onDragEnd();
             mLauncher.getStateManager().goToState(NORMAL);
+            // Only re-enable updates once the workspace is back to normal, which will be after the
+            // current frame.
+            post(dragView::resumeColorExtraction);
         };
 
         dragLayer.animateView(d.dragView, from, to, scale, 1f, 1f, 0.1f, 0.1f,
diff --git a/src/com/android/launcher3/DropTargetBar.java b/src/com/android/launcher3/DropTargetBar.java
index 4a1b084..88f6c49 100644
--- a/src/com/android/launcher3/DropTargetBar.java
+++ b/src/com/android/launcher3/DropTargetBar.java
@@ -105,7 +105,8 @@
                         / (2 * (grid.inv.numColumns + 1)))
                         + grid.edgeMarginPx;
             } else {
-                gap = grid.desiredWorkspaceLeftRightMarginPx - grid.inv.defaultWidgetPadding.right;
+                gap = getContext().getResources()
+                        .getDimensionPixelSize(R.dimen.drop_target_bar_margin_horizontal);
             }
             lp.width = grid.availableWidthPx - 2 * gap;
 
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index f28f54a..5bdc402 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1786,8 +1786,11 @@
             onDropExternal(touchXY, dropTargetLayout, d);
         } else {
             final View cell = mDragInfo.cell;
+            final DragView dragView = d.dragView;
             boolean droppedOnOriginalCellDuringTransition = false;
-            Runnable onCompleteRunnable = null;
+            Runnable onCompleteRunnable = dragView::resumeColorExtraction;
+
+            dragView.disableColorExtraction();
 
             if (dropTargetLayout != null && !d.cancelled) {
                 // Move internally
@@ -1898,7 +1901,9 @@
                         AppWidgetProviderInfo pInfo = hostView.getAppWidgetInfo();
                         if (pInfo != null && pInfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE
                                 && !options.isAccessibleDrag) {
+                            final Runnable previousRunnable = onCompleteRunnable;
                             onCompleteRunnable = () -> {
+                                previousRunnable.run();
                                 if (!isPageInTransition()) {
                                     AppWidgetResizeFrame.showForWidget(hostView, cellLayout);
                                 }
@@ -1967,7 +1972,7 @@
             parent.onDropChild(cell);
 
             mLauncher.getStateManager().goToState(NORMAL, SPRING_LOADED_EXIT_DELAY,
-                    onCompleteRunnable == null ? null : forSuccessCallback(onCompleteRunnable));
+                    forSuccessCallback(onCompleteRunnable));
             mStatsLogManager.logger().withItemInfo(d.dragInfo).withInstanceId(d.logInstanceId)
                     .log(LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED);
         }
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index d1e643f..516af59 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -51,7 +51,6 @@
 import androidx.annotation.StringRes;
 import androidx.annotation.VisibleForTesting;
 import androidx.core.graphics.ColorUtils;
-import androidx.core.os.BuildCompat;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
@@ -188,11 +187,11 @@
         Bundle state = (Bundle) sparseArray.get(R.id.work_tab_state_id, null);
         if (state != null) {
             int currentPage = state.getInt(BUNDLE_KEY_CURRENT_PAGE, 0);
-            if (currentPage != 0) {
+            if (currentPage != 0 && mViewPager != null) {
                 mViewPager.setCurrentPage(currentPage);
                 rebindAdapters(true);
             } else {
-                mSearchUiManager.resetSearch();
+                reset(true);
             }
         }
 
@@ -260,21 +259,6 @@
         mWorkAdapterProvider.updateCurrentState(isEnabled);
     }
 
-    private void hideInput() {
-        if (!BuildCompat.isAtLeastR() || !FeatureFlags.ENABLE_DEVICE_SEARCH.get()) return;
-
-        WindowInsets insets = getRootWindowInsets();
-        if (insets == null) return;
-
-        if (insets.isVisible(WindowInsets.Type.ime())) {
-            hideIme();
-        }
-    }
-
-    protected void hideIme() {
-        getWindowInsetsController().hide(WindowInsets.Type.ime());
-    }
-
     /**
      * Returns whether the view itself will handle the touch event or not.
      */
@@ -290,7 +274,6 @@
         }
         if (rv.getScrollbar().getThumbOffsetY() >= 0 &&
                 mLauncher.getDragLayer().isEventOverView(rv.getScrollbar(), ev)) {
-            hideInput();
             return false;
         }
         return rv.shouldContainerScroll(ev, mLauncher.getDragLayer());
diff --git a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
index 1eb726c..f64b7cb 100644
--- a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
@@ -15,8 +15,6 @@
  */
 package com.android.launcher3.allapps;
 
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_KEYBOARD_CLOSED;
-
 import android.content.Context;
 import android.graphics.Rect;
 import android.util.AttributeSet;
@@ -88,10 +86,4 @@
     public void onActivePageChanged(int currentActivePage) {
         super.onActivePageChanged(currentActivePage);
     }
-
-    @Override
-    protected void hideIme() {
-        super.hideIme();
-        mLauncher.getStatsLogManager().logger().log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED);
-    }
 }
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index 1664980..3fdb256 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -66,6 +66,7 @@
 import com.android.launcher3.util.RunnableList;
 import com.android.launcher3.util.Thunk;
 import com.android.launcher3.views.BaseDragLayer;
+import com.android.launcher3.widget.LauncherAppWidgetHostView;
 
 /** A custom view for rendering an icon, folder, shortcut or widget during drag-n-drop. */
 public class DragView extends FrameLayout implements StateListener<LauncherState> {
@@ -471,12 +472,12 @@
             mContent.draw(picture.beginRecording(mWidth, mHeight));
             picture.endRecording();
             View view = new View(mLauncher);
-            view.setClipToOutline(mContent.getClipToOutline());
-            view.setOutlineProvider(mContent.getOutlineProvider());
             view.setBackground(new PictureDrawable(picture));
             view.measure(makeMeasureSpec(mWidth, EXACTLY), makeMeasureSpec(mHeight, EXACTLY));
             view.layout(mContent.getLeft(), mContent.getTop(),
                     mContent.getRight(), mContent.getBottom());
+            setClipToOutline(mContent.getClipToOutline());
+            setOutlineProvider(mContent.getOutlineProvider());
             addViewInLayout(view, indexOfChild(mContent), mContent.getLayoutParams(), true);
 
             removeViewInLayout(mContent);
@@ -491,6 +492,24 @@
     }
 
     /**
+     * If the drag view uses color extraction, block it.
+     */
+    public void disableColorExtraction() {
+        if (mContent instanceof LauncherAppWidgetHostView) {
+            ((LauncherAppWidgetHostView) mContent).disableColorExtraction();
+        }
+    }
+
+    /**
+     * If the drag view uses color extraction, restores it.
+     */
+    public void resumeColorExtraction() {
+        if (mContent instanceof LauncherAppWidgetHostView) {
+            ((LauncherAppWidgetHostView) mContent).enableColorExtraction(/* updateColors= */ false);
+        }
+    }
+
+    /**
      * Removes this view from the {@link DragLayer}.
      *
      * <p>If the drag content is a {@link #mContent}, this call doesn't reattach the
diff --git a/src/com/android/launcher3/folder/PreviewItemManager.java b/src/com/android/launcher3/folder/PreviewItemManager.java
index a6674fc..8bef6ad 100644
--- a/src/com/android/launcher3/folder/PreviewItemManager.java
+++ b/src/com/android/launcher3/folder/PreviewItemManager.java
@@ -269,6 +269,9 @@
             setDrawable(p, items.get(i));
 
             if (!animate) {
+                if (p.anim != null) {
+                    p.anim.cancel();
+                }
                 computePreviewItemDrawingParams(i, numItemsInFirstPagePreview, p);
                 if (mReferenceDrawable == null) {
                     mReferenceDrawable = p.drawable;
diff --git a/src/com/android/launcher3/model/data/SearchActionItemInfo.java b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
index 7ca283e..b3057d5 100644
--- a/src/com/android/launcher3/model/data/SearchActionItemInfo.java
+++ b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
@@ -25,7 +25,6 @@
 
 import androidx.annotation.Nullable;
 
-import com.android.launcher3.Utilities;
 import com.android.launcher3.logger.LauncherAtom.ItemInfo;
 import com.android.launcher3.logger.LauncherAtom.SearchActionItem;
 
@@ -35,7 +34,6 @@
 public class SearchActionItemInfo extends ItemInfoWithIcon {
 
     public static final int FLAG_SHOULD_START = 1 << 1;
-    @Deprecated
     public static final int FLAG_SHOULD_START_FOR_RESULT = FLAG_SHOULD_START | 1 << 2;
     public static final int FLAG_BADGE_WITH_PACKAGE = 1 << 3;
     public static final int FLAG_PRIMARY_ICON_FROM_TITLE = 1 << 4;
@@ -91,13 +89,10 @@
      * Setter for mIntent with assertion for null value mPendingIntent
      */
     public void setIntent(Intent intent) {
-        if (mPendingIntent != null && intent != null && Utilities.IS_DEBUG_DEVICE) {
+        if (mPendingIntent != null && intent != null) {
             throw new RuntimeException(
                     "SearchActionItemInfo can only have either an Intent or a PendingIntent");
         }
-        if (intent != null) {
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        }
         mIntent = intent;
     }
 
@@ -109,7 +104,7 @@
      * Setter of mPendingIntent with assertion for null value mIntent
      */
     public void setPendingIntent(PendingIntent pendingIntent) {
-        if (mIntent != null && pendingIntent != null && Utilities.IS_DEBUG_DEVICE) {
+        if (mIntent != null && pendingIntent != null) {
             throw new RuntimeException(
                     "SearchActionItemInfo can only have either an Intent or a PendingIntent");
         }
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index e5424cf..d3f4909 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -50,6 +50,8 @@
      */
     private boolean isEnabled = true;
 
+    private boolean mHasFinishRecentsInAction = false;
+
     public SystemShortcut(int iconResId, int labelResId, T target, ItemInfo itemInfo) {
         mIconResId = iconResId;
         mLabelResId = labelResId;
@@ -100,6 +102,14 @@
         return mAccessibilityActionId == action;
     }
 
+    public void setHasFinishRecentsInAction(boolean hasFinishRecentsInAction) {
+        mHasFinishRecentsInAction = hasFinishRecentsInAction;
+    }
+
+    public boolean hasFinishRecentsInAction() {
+        return mHasFinishRecentsInAction;
+    }
+
     public interface Factory<T extends BaseDraggingActivity> {
 
         @Nullable SystemShortcut<T> getShortcut(T activity, ItemInfo itemInfo);
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index 408ba28..b53f96e 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -262,12 +262,19 @@
      */
     public static void onClickSearchAction(Launcher launcher, SearchActionItemInfo itemInfo) {
         if (itemInfo.getIntent() != null) {
-            launcher.startActivity(itemInfo.getIntent());
+            if (itemInfo.hasFlags(SearchActionItemInfo.FLAG_SHOULD_START_FOR_RESULT)) {
+                launcher.startActivityForResult(itemInfo.getIntent(), 0);
+            } else {
+                launcher.startActivity(itemInfo.getIntent());
+            }
         } else if (itemInfo.getPendingIntent() != null) {
             try {
                 PendingIntent pendingIntent = itemInfo.getPendingIntent();
                 if (!itemInfo.hasFlags(SearchActionItemInfo.FLAG_SHOULD_START)) {
                     pendingIntent.send();
+                } else if (itemInfo.hasFlags(SearchActionItemInfo.FLAG_SHOULD_START_FOR_RESULT)) {
+                    launcher.startIntentSenderForResult(pendingIntent.getIntentSender(), 0, null, 0,
+                            0, 0);
                 } else {
                     launcher.startIntentSender(pendingIntent.getIntentSender(), null, 0, 0, 0);
                 }
diff --git a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
index 867c770..4ec7e60 100644
--- a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
+++ b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
@@ -417,7 +417,8 @@
             previewHeight = drawable.getIntrinsicHeight();
         } else {
             DeviceProfile dp = launcher.getDeviceProfile();
-            Size widgetSize = WidgetSizes.getWidgetSizePx(dp, spanX, spanY);
+            Size widgetSize = WidgetSizes.getWidgetPaddedSizePx(mContext, info.provider, dp, spanX,
+                    spanY);
             previewWidth = widgetSize.getWidth();
             previewHeight = widgetSize.getHeight();
         }
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
index ea08a25..63bc416 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -57,7 +57,6 @@
 import com.android.launcher3.widget.dragndrop.AppWidgetHostViewDragListener;
 
 import java.util.List;
-import java.util.Optional;
 
 /**
  * {@inheritDoc}
@@ -118,7 +117,9 @@
     private final ViewGroupFocusHelper mDragLayerRelativeCoordinateHelper;
     private long mDeferUpdatesUntilMillis = 0;
     private RemoteViews mDeferredRemoteViews;
-    private Optional<SparseIntArray> mDeferredColorChange = Optional.empty();
+    private boolean mHasDeferredColorChange = false;
+    private @Nullable SparseIntArray mDeferredColorChange = null;
+    private boolean mEnableColorExtraction = true;
 
     public LauncherAppWidgetHostView(Context context) {
         super(context);
@@ -243,18 +244,23 @@
      */
     public void endDeferringUpdates() {
         RemoteViews remoteViews;
-        Optional<SparseIntArray> deferredColors;
+        SparseIntArray deferredColors;
+        boolean hasDeferredColors;
         synchronized (mUpdateLock) {
             mDeferUpdatesUntilMillis = 0;
             remoteViews = mDeferredRemoteViews;
             mDeferredRemoteViews = null;
             deferredColors = mDeferredColorChange;
-            mDeferredColorChange = Optional.empty();
+            hasDeferredColors = mHasDeferredColorChange;
+            mDeferredColorChange = null;
+            mHasDeferredColorChange = false;
         }
         if (remoteViews != null) {
             updateAppWidget(remoteViews);
         }
-        deferredColors.ifPresent(colors -> onColorsChanged(null /* rectF */, colors));
+        if (hasDeferredColors) {
+            onColorsChanged(null /* rectF */, deferredColors);
+        }
     }
 
     public boolean onInterceptTouchEvent(MotionEvent ev) {
@@ -342,13 +348,7 @@
         }
 
         mIsScrollable = checkScrollableRecursively(this);
-        if (!mIsInDragMode && getTag() instanceof LauncherAppWidgetInfo) {
-
-            LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) getTag();
-            mDragLayerRelativeCoordinateHelper.viewToRect(this, mCurrentWidgetSize);
-            updateColorExtraction(mCurrentWidgetSize,
-                    mWorkspace.getPageIndexForScreenId(info.screenId));
-        }
+        updateColorExtraction();
 
         enforceRoundedCorners();
     }
@@ -377,6 +377,7 @@
      * @param pageId The workspace page the widget is on.
      */
     private void updateColorExtraction(Rect rectInDragLayer, int pageId) {
+        if (!mEnableColorExtraction) return;
         mColorExtractor.getExtractedRectForViewRect(mLauncher, pageId, rectInDragLayer, mTempRectF);
 
         if (mTempRectF.isEmpty()) {
@@ -391,6 +392,38 @@
         }
     }
 
+    /**
+     * Update the color extraction, using the current position of the app widget.
+     */
+    private void updateColorExtraction() {
+        if (!mIsInDragMode && getTag() instanceof LauncherAppWidgetInfo) {
+            LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) getTag();
+            mDragLayerRelativeCoordinateHelper.viewToRect(this, mCurrentWidgetSize);
+            updateColorExtraction(mCurrentWidgetSize,
+                    mWorkspace.getPageIndexForScreenId(info.screenId));
+        }
+    }
+
+    /**
+     * Enables the local color extraction.
+     *
+     * @param updateColors If true, this will update the color extraction using the current location
+     *                    of the App Widget.
+     */
+    public void enableColorExtraction(boolean updateColors) {
+        mEnableColorExtraction = true;
+        if (updateColors) {
+            updateColorExtraction();
+        }
+    }
+
+    /**
+     * Disables the local color extraction.
+     */
+    public void disableColorExtraction() {
+        mEnableColorExtraction = false;
+    }
+
     // Compare two location rectangles. Locations are always in the [0;1] range.
     private static boolean isSameLocation(@NonNull RectF rect1, @Nullable RectF rect2,
             float epsilon) {
@@ -409,10 +442,12 @@
     public void onColorsChanged(RectF rectF, SparseIntArray colors) {
         synchronized (mUpdateLock) {
             if (isDeferringUpdates()) {
-                mDeferredColorChange = Optional.ofNullable(colors);
+                mDeferredColorChange = colors;
+                mHasDeferredColorChange = true;
                 return;
             }
-            mDeferredColorChange = Optional.empty();
+            mDeferredColorChange = null;
+            mHasDeferredColorChange = false;
         }
 
         // setColorResources will reapply the view, which must happen in the UI thread.
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index 8798332..c3edcce 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -363,7 +363,9 @@
     /** Sets the widget preview image size, in number of cells, and preview scale. */
     public Size setPreviewSize(int spanX, int spanY, float previewScale) {
         DeviceProfile deviceProfile = mActivity.getDeviceProfile();
-        Size widgetSize = WidgetSizes.getWidgetSizePx(deviceProfile, spanX, spanY);
+        Size widgetSize =
+                mItem != null ? WidgetSizes.getWidgetItemSizePx(getContext(), deviceProfile, mItem)
+                : WidgetSizes.getWidgetSizePx(deviceProfile, spanX, spanY);
         mPreviewWidth = widgetSize.getWidth();
         mPreviewHeight = widgetSize.getHeight();
         mPreviewScale = previewScale;
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
index 08a2263..1125b82 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
@@ -296,11 +296,8 @@
             for (int i = 0; i < entry.mWidgets.size(); i++) {
                 WidgetItem widgetItem = entry.mWidgets.get(i);
                 DeviceProfile deviceProfile = activity.getDeviceProfile();
-                Size widgetSize =
-                        WidgetSizes.getWidgetSizePx(
-                                deviceProfile,
-                                widgetItem.spanX,
-                                widgetItem.spanY);
+                Size widgetSize = WidgetSizes.getWidgetItemSizePx(mContext, deviceProfile,
+                        widgetItem);
                 if (widgetItem.isShortcut()) {
                     widgetSize =
                             new Size(
diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
index 6fc6848..3800ede 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
@@ -155,8 +155,8 @@
             float rowHeight = 0;
             for (int j = 0; j < widgetItems.size(); j++) {
                 WidgetItem widgetItem = widgetItems.get(j);
-                Size widgetSize = WidgetSizes.getWidgetSizePx(
-                        deviceProfile, widgetItem.spanX, widgetItem.spanY);
+                Size widgetSize = WidgetSizes.getWidgetItemSizePx(getContext(), deviceProfile,
+                        widgetItem);
                 float previewHeight = widgetSize.getHeight() * previewScale;
                 rowHeight = Math.max(rowHeight,
                         previewHeight + mWidgetCellTextViewsHeight + mWidgetCellVerticalPadding);
diff --git a/src/com/android/launcher3/widget/util/WidgetSizes.java b/src/com/android/launcher3/widget/util/WidgetSizes.java
index 5c8ea72..e2c84b5 100644
--- a/src/com/android/launcher3/widget/util/WidgetSizes.java
+++ b/src/com/android/launcher3/widget/util/WidgetSizes.java
@@ -17,9 +17,7 @@
 
 import static android.appwidget.AppWidgetHostView.getDefaultPaddingForWidget;
 
-import static com.android.launcher3.Utilities.ATLEAST_S;
 
-import android.annotation.SuppressLint;
 import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetManager;
 import android.content.ComponentName;
@@ -34,24 +32,34 @@
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.model.WidgetItem;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.stream.Collectors;
 
 /** A utility class for widget sizes related calculations. */
 public final class WidgetSizes {
 
     /**
      * Returns the list of all possible sizes, in dp, for a widget of given spans on this device.
+     *
+     * <p>The returned sizes already take into account the system padding, and whether it is applied
+     * or not in that specific configuration.
      */
-    public static ArrayList<SizeF> getWidgetSizes(Context context, int spanX, int spanY) {
+    public static ArrayList<SizeF> getWidgetPaddedSizes(Context context, ComponentName provider,
+            int spanX, int spanY) {
+        Rect padding = getDefaultPaddingForWidget(context, provider, /* padding= */ null);
+
         ArrayList<SizeF> sizes = new ArrayList<>(2);
         final float density = context.getResources().getDisplayMetrics().density;
         final Point cellSize = new Point();
 
         for (DeviceProfile profile : LauncherAppState.getIDP(context).supportedProfiles) {
             Size widgetSizePx = getWidgetSizePx(profile, spanX, spanY, cellSize);
+            if (!profile.shouldInsetWidgets()) {
+                widgetSizePx = new Size(widgetSizePx.getWidth() - padding.left - padding.right,
+                        widgetSizePx.getHeight() - padding.top - padding.bottom);
+            }
             sizes.add(new SizeF(widgetSizePx.getWidth() / density,
                     widgetSizePx.getHeight() / density));
         }
@@ -63,6 +71,32 @@
         return getWidgetSizePx(profile, spanX, spanY, /* recycledCellSize= */ null);
     }
 
+    /**
+     * Returns the size, in pixels and removing padding, a widget of given spans & {@code profile}.
+     */
+    public static Size getWidgetPaddedSizePx(Context context, ComponentName component,
+            DeviceProfile profile, int spanX, int spanY) {
+        Size size = getWidgetSizePx(profile, spanX, spanY);
+        if (profile.shouldInsetWidgets()) {
+            return size;
+        }
+        Rect padding = getDefaultPaddingForWidget(context, component, /* padding= */ null);
+        return new Size(size.getWidth() - padding.left - padding.right,
+                size.getHeight() - padding.top - padding.bottom);
+    }
+
+    /**
+     * Returns the size of a WidgetItem.
+     */
+    public static Size getWidgetItemSizePx(Context context, DeviceProfile profile,
+            WidgetItem widgetItem) {
+        if (widgetItem.isShortcut()) {
+            return getWidgetSizePx(profile, widgetItem.spanX, widgetItem.spanY);
+        }
+        return getWidgetPaddedSizePx(context, widgetItem.componentName, profile, widgetItem.spanX,
+                widgetItem.spanY);
+    }
+
     private static Size getWidgetSizePx(DeviceProfile profile, int spanX, int spanY,
             @Nullable Point recycledCellSize) {
         final int hBorderSpacing = (spanX - 1) * profile.cellLayoutBorderSpacingPx;
@@ -81,17 +115,22 @@
      * <p>On Android S+, it also updates the given {@code widgetView} with a list of sizes derived
      * from {@code spanX}, {@code spanY} in all supported device profiles.
      */
-    @SuppressLint("NewApi") // Already added API check.
     public static void updateWidgetSizeRanges(AppWidgetHostView widgetView, Context context,
             int spanX, int spanY) {
-        List<SizeF> sizes = getWidgetSizes(context, spanX, spanY);
-        if (ATLEAST_S) {
-            widgetView.updateAppWidgetSize(new Bundle(), sizes);
-        } else {
-            Rect bounds = getMinMaxSizes(sizes);
-            widgetView.updateAppWidgetSize(new Bundle(), bounds.left, bounds.top, bounds.right,
-                    bounds.bottom);
+        AppWidgetManager widgetManager = AppWidgetManager.getInstance(context);
+        int widgetId = widgetView.getAppWidgetId();
+        if (widgetId <= 0) {
+            return;
         }
+        Bundle sizeOptions = getWidgetSizeOptions(context, widgetView.getAppWidgetInfo().provider,
+                spanX, spanY);
+        if (sizeOptions.<SizeF>getParcelableArrayList(
+                AppWidgetManager.OPTION_APPWIDGET_SIZES).equals(
+                widgetManager.getAppWidgetOptions(widgetId).<SizeF>getParcelableArrayList(
+                        AppWidgetManager.OPTION_APPWIDGET_SIZES))) {
+            return;
+        }
+        widgetManager.updateAppWidgetOptions(widgetId, sizeOptions);
     }
 
     /**
@@ -99,17 +138,7 @@
      */
     public static Bundle getWidgetSizeOptions(Context context, ComponentName provider, int spanX,
             int spanY) {
-        ArrayList<SizeF> sizes = getWidgetSizes(context, spanX, spanY);
-        Rect padding = getDefaultPaddingForWidget(context, provider, null);
-        float density = context.getResources().getDisplayMetrics().density;
-        float xPaddingDips = (padding.left + padding.right) / density;
-        float yPaddingDips = (padding.top + padding.bottom) / density;
-
-        ArrayList<SizeF> paddedSizes = sizes.stream()
-                .map(size -> new SizeF(
-                        Math.max(0.f, size.getWidth() - xPaddingDips),
-                        Math.max(0.f, size.getHeight() - yPaddingDips)))
-                .collect(Collectors.toCollection(ArrayList::new));
+        ArrayList<SizeF> paddedSizes = getWidgetPaddedSizes(context, provider, spanX, spanY);
 
         Rect rect = getMinMaxSizes(paddedSizes);
         Bundle options = new Bundle();