Merge "Update the scale on corner radii on scaled image drawable." into main
diff --git a/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt b/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt
index 9178062..189deda 100644
--- a/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt
+++ b/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt
@@ -44,11 +44,13 @@
     /** Launch desktop tasks from recents view */
     fun launchDesktopFromRecents(
         desktopTaskView: DesktopTaskView,
+        animated: Boolean,
         callback: Consumer<Boolean>? = null
     ) {
         val animRunner =
             RemoteDesktopLaunchTransitionRunner(
                 desktopTaskView,
+                animated,
                 stateManager,
                 depthController,
                 callback
@@ -64,6 +66,7 @@
 
     private class RemoteDesktopLaunchTransitionRunner(
         private val desktopTaskView: DesktopTaskView,
+        private val animated: Boolean,
         private val stateManager: StateManager<*, *>,
         private val depthController: DepthController?,
         private val successCallback: Consumer<Boolean>?
@@ -84,16 +87,21 @@
             }
 
             MAIN_EXECUTOR.execute {
-                TaskViewUtils.composeRecentsDesktopLaunchAnimator(
-                    desktopTaskView,
-                    stateManager,
-                    depthController,
-                    info,
-                    t
-                ) {
-                    errorHandlingFinishCallback.run()
-                    successCallback?.accept(true)
+                val animator =
+                    TaskViewUtils.composeRecentsDesktopLaunchAnimator(
+                        desktopTaskView,
+                        stateManager,
+                        depthController,
+                        info,
+                        t
+                    ) {
+                        errorHandlingFinishCallback.run()
+                        successCallback?.accept(true)
+                    }
+                if (!animated) {
+                    animator.setDuration(0)
                 }
+                animator.start()
             }
         }
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 7338485..f61840a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -267,7 +267,7 @@
 
         int setupSize = mControllers.taskbarActivityContext.getSetupWindowSize();
         Point p = DimensionUtils.getTaskbarPhoneDimensions(deviceProfile, resources,
-                mContext.isPhoneMode());
+                mContext.isPhoneMode(), mContext.isGestureNav());
         ViewGroup.LayoutParams navButtonsViewLayoutParams = mNavButtonsView.getLayoutParams();
         navButtonsViewLayoutParams.width = p.x;
         if (!mContext.isUserSetupComplete()) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 9c954d1..cd1eea2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -25,6 +25,7 @@
 import static android.window.SplashScreen.SPLASH_SCREEN_STYLE_UNDEFINED;
 
 import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
+import static com.android.launcher3.AbstractFloatingView.TYPE_ON_BOARD_POPUP;
 import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
 import static com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_OVERLAY_PROXY;
 import static com.android.launcher3.Flags.enableCursorHoverStates;
@@ -1514,6 +1515,12 @@
                 itemView.setHapticFeedbackEnabled(true);
                 return false;
             });
+
+            // Close any open taskbar tooltips.
+            if (AbstractFloatingView.hasOpenView(this, TYPE_ON_BOARD_POPUP)) {
+                AbstractFloatingView.getOpenView(this, TYPE_ON_BOARD_POPUP)
+                        .close(/* animate= */ false);
+            }
         });
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index efe42fb..5bbf4b2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -86,7 +86,7 @@
 import com.android.quickstep.util.LogUtils;
 import com.android.quickstep.util.MultiValueUpdateListener;
 import com.android.systemui.shared.recents.model.Task;
-import com.android.wm.shell.draganddrop.DragAndDropConstants;
+import com.android.wm.shell.shared.draganddrop.DragAndDropConstants;
 
 import java.io.PrintWriter;
 import java.util.Arrays;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index ff890fb..acf976f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -291,7 +291,7 @@
             if (mActivity.isPhoneMode()) {
                 Resources resources = mActivity.getResources();
                 Point taskbarDimensions = DimensionUtils.getTaskbarPhoneDimensions(deviceProfile,
-                        resources, true /* isPhoneMode */);
+                        resources, true /* isPhoneMode */, mActivity.isGestureNav());
                 return taskbarDimensions.y == -1 ?
                         deviceProfile.getDisplayInfo().currentSize.y :
                         taskbarDimensions.y;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarHoverToolTipController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarHoverToolTipController.java
index dd14109..8c7879d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarHoverToolTipController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarHoverToolTipController.java
@@ -18,30 +18,22 @@
 import static android.view.MotionEvent.ACTION_HOVER_ENTER;
 import static android.view.MotionEvent.ACTION_HOVER_EXIT;
 import static android.view.View.ALPHA;
-import static android.view.View.SCALE_Y;
-import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_TEXT;
 
-import static com.android.app.animation.Interpolators.LINEAR;
-import static com.android.launcher3.AbstractFloatingView.TYPE_ALL_EXCEPT_ON_BOARD_POPUP;
+import static com.android.launcher3.AbstractFloatingView.TYPE_FOLDER;
 import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS;
-import static com.android.launcher3.views.ArrowTipView.TEXT_ALPHA;
 
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.graphics.Rect;
-import android.os.Handler;
-import android.os.Looper;
 import android.view.ContextThemeWrapper;
 import android.view.MotionEvent;
 import android.view.View;
 
-import com.android.app.animation.Interpolators;
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.apppairs.AppPairIcon;
-import com.android.launcher3.compat.AccessibilityManagerCompat;
 import com.android.launcher3.folder.FolderIcon;
 import com.android.launcher3.views.ArrowTipView;
 
@@ -49,13 +41,9 @@
  * Controls showing a tooltip in the taskbar above each icon when it is hovered.
  */
 public class TaskbarHoverToolTipController implements View.OnHoverListener {
-
-    private static final int HOVER_TOOL_TIP_REVEAL_DURATION = 250;
-    private static final int HOVER_TOOL_TIP_EXIT_DURATION = 150;
-
-    private final Handler mHoverToolTipHandler = new Handler(Looper.getMainLooper());
-    private final Runnable mRevealHoverToolTipRunnable = this::revealHoverToolTip;
-    private final Runnable mHideHoverToolTipRunnable = this::hideHoverToolTip;
+    // Short duration to reveal tooltip, as it is positioned in the x/y via a post() call in
+    // parallel with the open animation. An instant animation could show in the wrong location.
+    private static final int HOVER_TOOL_TIP_REVEAL_DURATION = 15;
 
     private final TaskbarActivityContext mActivity;
     private final TaskbarView mTaskbarView;
@@ -90,35 +78,11 @@
                 R.dimen.taskbar_tooltip_horizontal_padding);
         mHoverToolTipView.findViewById(R.id.text).setPadding(horizontalPadding, verticalPadding,
                 horizontalPadding, verticalPadding);
-
-        AnimatorSet hoverCloseAnimator = new AnimatorSet();
-        ObjectAnimator textCloseAnimator = ObjectAnimator.ofInt(mHoverToolTipView, TEXT_ALPHA, 0);
-        textCloseAnimator.setInterpolator(Interpolators.clampToProgress(LINEAR, 0, 0.33f));
-        ObjectAnimator alphaCloseAnimator = ObjectAnimator.ofFloat(mHoverToolTipView, ALPHA, 0);
-        alphaCloseAnimator.setInterpolator(Interpolators.clampToProgress(LINEAR, 0.33f, 0.66f));
-        ObjectAnimator scaleCloseAnimator = ObjectAnimator.ofFloat(mHoverToolTipView, SCALE_Y, 0);
-        scaleCloseAnimator.setInterpolator(Interpolators.STANDARD);
-        hoverCloseAnimator.playTogether(
-                textCloseAnimator,
-                alphaCloseAnimator,
-                scaleCloseAnimator);
-        hoverCloseAnimator.setStartDelay(0);
-        hoverCloseAnimator.setDuration(HOVER_TOOL_TIP_EXIT_DURATION);
-        mHoverToolTipView.setCustomCloseAnimation(hoverCloseAnimator);
+        mHoverToolTipView.setAlpha(0);
 
         AnimatorSet hoverOpenAnimator = new AnimatorSet();
-        ObjectAnimator textOpenAnimator =
-                ObjectAnimator.ofInt(mHoverToolTipView, TEXT_ALPHA, 0, 255);
-        textOpenAnimator.setInterpolator(Interpolators.clampToProgress(LINEAR, 0.15f, 0.75f));
-        ObjectAnimator scaleOpenAnimator =
-                ObjectAnimator.ofFloat(mHoverToolTipView, SCALE_Y, 0f, 1f);
-        scaleOpenAnimator.setInterpolator(Interpolators.EMPHASIZED);
         ObjectAnimator alphaOpenAnimator = ObjectAnimator.ofFloat(mHoverToolTipView, ALPHA, 0f, 1f);
-        alphaOpenAnimator.setInterpolator(Interpolators.clampToProgress(LINEAR, 0f, 0.33f));
-        hoverOpenAnimator.playTogether(
-                scaleOpenAnimator,
-                textOpenAnimator,
-                alphaOpenAnimator);
+        hoverOpenAnimator.play(alphaOpenAnimator);
         hoverOpenAnimator.setDuration(HOVER_TOOL_TIP_REVEAL_DURATION);
         mHoverToolTipView.setCustomOpenAnimation(hoverOpenAnimator);
 
@@ -131,28 +95,17 @@
 
     @Override
     public boolean onHover(View v, MotionEvent event) {
-        boolean isAnyOtherFloatingViewOpen =
-                AbstractFloatingView.hasOpenView(mActivity, TYPE_ALL_EXCEPT_ON_BOARD_POPUP);
-        if (isAnyOtherFloatingViewOpen) {
-            mHoverToolTipHandler.removeCallbacksAndMessages(null);
-        }
+        boolean isFolderOpen = AbstractFloatingView.hasOpenView(mActivity, TYPE_FOLDER);
         // If hover leaves a taskbar icon animate the tooltip closed.
         if (event.getAction() == ACTION_HOVER_EXIT) {
-            startHideHoverToolTip();
+            mHoverToolTipView.close(/* animate= */ false);
             mActivity.setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS, false);
-            return true;
-        } else if (!isAnyOtherFloatingViewOpen && event.getAction() == ACTION_HOVER_ENTER) {
-            // If hovering above a taskbar icon starts, animate the tooltip open. Do not
-            // reveal if any floating views such as folders or edu pop-ups are open.
-            startRevealHoverToolTip();
+        } else if (!isFolderOpen && event.getAction() == ACTION_HOVER_ENTER) {
+            // Do not reveal if any floating views such as folders or edu pop-ups are open.
+            revealHoverToolTip();
             mActivity.setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS, true);
-            return true;
         }
-        return false;
-    }
-
-    private void startRevealHoverToolTip() {
-        mHoverToolTipHandler.post(mRevealHoverToolTipRunnable);
+        return true;
     }
 
     private void revealHoverToolTip() {
@@ -170,14 +123,4 @@
         mHoverToolTipView.showAtLocation(mToolTipText, iconViewBounds.centerX(),
                 mTaskbarView.getTop(), /* shouldAutoClose= */ false);
     }
-
-    private void startHideHoverToolTip() {
-        int accessibilityHideTimeout = AccessibilityManagerCompat.getRecommendedTimeoutMillis(
-                mActivity, /* originalTimeout= */ 0, FLAG_CONTENT_TEXT);
-        mHoverToolTipHandler.postDelayed(mHideHoverToolTipRunnable, accessibilityHideTimeout);
-    }
-
-    private void hideHoverToolTip() {
-        mHoverToolTipView.close(/* animate = */ true);
-    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index e80ad7a..332eb95 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -185,10 +185,13 @@
 
     // Create a Stream of all applicable system shortcuts
     private Stream<SystemShortcut.Factory> getSystemShortcuts() {
-        // append split options to APP_INFO shortcut, the order here will reflect in the popup
+        // append split options to APP_INFO shortcut if not in Desktop Windowing mode, the order
+        // here will reflect in the popup
         ArrayList<SystemShortcut.Factory> shortcuts = new ArrayList<>();
         shortcuts.add(APP_INFO);
-        shortcuts.addAll(mControllers.uiController.getSplitMenuOptions().toList());
+        if (!mControllers.taskbarRecentAppsController.isInDesktopMode()) {
+            shortcuts.addAll(mControllers.uiController.getSplitMenuOptions().toList());
+        }
         if (com.android.wm.shell.Flags.enableBubbleAnything()) {
             shortcuts.add(BUBBLE);
         }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
index 1a168a9..737d031 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
@@ -81,7 +81,7 @@
     private val desktopVisibilityController: DesktopVisibilityController?
         get() = desktopVisibilityControllerProvider()
 
-    private val isInDesktopMode: Boolean
+    val isInDesktopMode: Boolean
         get() = desktopVisibilityController?.areDesktopTasksVisible() ?: false
 
     val runningTaskIds: Set<Int>
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
index 1a51861..a36d5f0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
@@ -168,10 +168,6 @@
         mBarView = bubbleView; // Need the view for inflating bubble views.
 
         mSystemUiProxy = SystemUiProxy.INSTANCE.get(context);
-
-        if (sBubbleBarEnabled) {
-            mSystemUiProxy.setBubblesListener(this);
-        }
     }
 
     public void onDestroy() {
@@ -197,6 +193,10 @@
             mBubbleBarViewController.setUpdateSelectedBubbleAfterCollapse(
                     key -> setSelectedBubbleInternal(mBubbles.get(key)));
             mBubbleBarViewController.setBoundsChangeListener(this::onBubbleBarBoundsChanged);
+
+            if (sBubbleBarEnabled) {
+                mSystemUiProxy.setBubblesListener(this);
+            }
         });
     }
 
@@ -286,9 +286,10 @@
             RemovedBubble removedBubble = update.removedBubbles.get(0);
             BubbleBarBubble bubbleToRemove = mBubbles.remove(removedBubble.getKey());
             mBubbles.put(update.addedBubble.getKey(), update.addedBubble);
+            boolean showOverflow = update.showOverflowChanged && update.showOverflow;
             if (bubbleToRemove != null) {
                 mBubbleBarViewController.addBubbleAndRemoveBubble(update.addedBubble,
-                        bubbleToRemove, isExpanding, suppressAnimation);
+                        bubbleToRemove, isExpanding, suppressAnimation, showOverflow);
             } else {
                 mBubbleBarViewController.addBubble(update.addedBubble, isExpanding,
                         suppressAnimation);
@@ -495,11 +496,6 @@
                 () -> mBubbleBarViewController.animateBubbleBarLocation(bubbleBarLocation));
     }
 
-    /** Notifies WMShell to show the expanded view. */
-    void showExpandedView() {
-        mSystemUiProxy.showExpandedView();
-    }
-
     //
     // Loading data for the bubbles
     //
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
index 819c473..ffab936 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
@@ -647,7 +647,9 @@
         }
         setAlphaDuringBubbleDrag(1f);
         setTranslationX(0f);
-        setAlpha(1f);
+        if (getBubbleChildCount() > 0) {
+            setAlpha(1f);
+        }
     }
 
     /**
@@ -756,7 +758,8 @@
     }
 
     /** Add a new bubble and remove an old bubble from the bubble bar. */
-    public void addBubbleAndRemoveBubble(BubbleView addedBubble, BubbleView removedBubble) {
+    public void addBubbleAndRemoveBubble(BubbleView addedBubble, BubbleView removedBubble,
+            Runnable onEndRunnable) {
         FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams((int) mIconSize, (int) mIconSize,
                 Gravity.LEFT);
         boolean isOverflowSelected = mSelectedBubbleView.isOverflow();
@@ -790,6 +793,9 @@
                 removeView(removedBubble);
                 updateWidth();
                 mBubbleAnimator = null;
+                if (onEndRunnable != null) {
+                    onEndRunnable.run();
+                }
             }
 
             @Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index 17ccfc5..4fe4ace 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -119,8 +119,7 @@
         mBubbleDragController = bubbleControllers.bubbleDragController;
         mTaskbarStashController = controllers.taskbarStashController;
         mTaskbarInsetsController = controllers.taskbarInsetsController;
-        mBubbleBarViewAnimator = new BubbleBarViewAnimator(
-                mBarView, mBubbleStashController, mBubbleBarController::showExpandedView);
+        mBubbleBarViewAnimator = new BubbleBarViewAnimator(mBarView, mBubbleStashController);
         mTaskbarViewPropertiesProvider = taskbarViewPropertiesProvider;
         onBubbleBarConfigurationChanged(/* animate= */ false);
         mActivity.addOnDeviceProfileChangeListener(
@@ -497,8 +496,10 @@
 
     /** Adds a new bubble and removes an old bubble at the same time. */
     public void addBubbleAndRemoveBubble(BubbleBarBubble addedBubble,
-            BubbleBarBubble removedBubble, boolean isExpanding, boolean suppressAnimation) {
-        mBarView.addBubbleAndRemoveBubble(addedBubble.getView(), removedBubble.getView());
+            BubbleBarBubble removedBubble, boolean isExpanding, boolean suppressAnimation,
+            boolean addOverflowToo) {
+        mBarView.addBubbleAndRemoveBubble(addedBubble.getView(), removedBubble.getView(),
+                addOverflowToo ? () -> showOverflow(true) : null);
         addedBubble.getView().setOnClickListener(mBubbleClickListener);
         addedBubble.getView().setController(mBubbleViewController);
         removedBubble.getView().setController(null);
@@ -532,7 +533,8 @@
     public void addOverflowAndRemoveBubble(BubbleBarBubble removedBubble) {
         if (mOverflowAdded) return;
         mOverflowAdded = true;
-        mBarView.addBubbleAndRemoveBubble(mOverflowBubble.getView(), removedBubble.getView());
+        mBarView.addBubbleAndRemoveBubble(mOverflowBubble.getView(), removedBubble.getView(),
+                null /* onEndRunnable */);
         mOverflowBubble.getView().setOnClickListener(mBubbleClickListener);
         mOverflowBubble.getView().setController(mBubbleViewController);
         removedBubble.getView().setController(null);
@@ -542,7 +544,8 @@
     public void removeOverflowAndAddBubble(BubbleBarBubble addedBubble) {
         if (!mOverflowAdded) return;
         mOverflowAdded = false;
-        mBarView.addBubbleAndRemoveBubble(addedBubble.getView(), mOverflowBubble.getView());
+        mBarView.addBubbleAndRemoveBubble(addedBubble.getView(), mOverflowBubble.getView(),
+                null /* onEndRunnable */);
         addedBubble.getView().setOnClickListener(mBubbleClickListener);
         addedBubble.getView().setController(mBubbleViewController);
         mOverflowBubble.getView().setController(null);
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java
index 5eebbd8..f554fcd 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java
@@ -30,7 +30,7 @@
 import com.android.launcher3.taskbar.TaskbarActivityContext;
 import com.android.launcher3.taskbar.TaskbarDragLayer;
 import com.android.wm.shell.common.bubbles.DismissView;
-import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
+import com.android.wm.shell.shared.magnetictarget.MagnetizedObject;
 
 /**
  * Controls dismiss view presentation for the bubble bar dismiss functionality.
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java
index 7aed2d2..87f466f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java
@@ -128,7 +128,7 @@
                         boolean wasFling, boolean canceled, float finalValue, float finalVelocity,
                         boolean allRelevantPropertyAnimationsEnded) -> {
                     if (canceled || allRelevantPropertyAnimationsEnded) {
-                        resetAnimatedViews(restingPosition);
+                        resetAnimatedViews(restingPosition, /* dismissed= */ false);
                         if (endActions != null) {
                             endActions.run();
                         }
@@ -197,7 +197,7 @@
                         boolean wasFling, boolean canceled, float finalValue, float finalVelocity,
                         boolean allRelevantPropertyAnimationsEnded) -> {
                     if (canceled || allRelevantPropertyAnimationsEnded) {
-                        resetAnimatedViews(initialPosition);
+                        resetAnimatedViews(initialPosition, /* dismissed= */ true);
                         if (endActions != null) endActions.run();
                     }
                 })
@@ -208,11 +208,14 @@
      * Reset the animated views to the initial state
      *
      * @param initialPosition position of the bubble
+     * @param dismissed whether the animated view was dismissed
      */
-    private void resetAnimatedViews(@NonNull PointF initialPosition) {
+    private void resetAnimatedViews(@NonNull PointF initialPosition, boolean dismissed) {
         mView.setScaleX(1f);
         mView.setScaleY(1f);
-        mView.setAlpha(1f);
+        if (!dismissed) {
+            mView.setAlpha(1f);
+        }
         mView.setTranslationX(initialPosition.x);
         mView.setTranslationY(initialPosition.y);
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
index f0f2872..eb3b24b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
@@ -34,9 +34,9 @@
 
 import com.android.launcher3.R;
 import com.android.launcher3.icons.DotRenderer;
-import com.android.wm.shell.animation.Interpolators;
 import com.android.wm.shell.common.bubbles.BubbleBarLocation;
 import com.android.wm.shell.common.bubbles.BubbleInfo;
+import com.android.wm.shell.shared.animation.Interpolators;
 
 // TODO: (b/276978250) This is will be similar to WMShell's BadgedImageView, it'd be nice to share.
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
index 99c50f2..2ed88d8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
@@ -36,7 +36,6 @@
 constructor(
     private val bubbleBarView: BubbleBarView,
     private val bubbleStashController: BubbleStashController,
-    private val onExpanded: Runnable,
     private val scheduler: Scheduler = HandlerScheduler(bubbleBarView)
 ) {
 
@@ -407,7 +406,7 @@
         springBackAnimation.spring(DynamicAnimation.TRANSLATION_Y, ty)
         springBackAnimation.addEndListener { _, _, _, _, _, _, _ ->
             if (animatingBubble?.expand == true) {
-                expandBubbleBar()
+                bubbleBarView.isExpanded = true
                 cancelHideAnimation()
             } else {
                 moveToState(AnimatingBubble.State.IN)
@@ -418,7 +417,7 @@
         ObjectAnimator.ofFloat(bubbleBarView, View.TRANSLATION_Y, ty - bubbleBarBounceDistanceInPx)
             .withDuration(BUBBLE_BAR_BOUNCE_ANIMATION_DURATION_MS)
             .withEndAction {
-                if (animatingBubble?.expand == true) expandBubbleBar()
+                if (animatingBubble?.expand == true) bubbleBarView.isExpanded = true
                 springBackAnimation.start()
             }
             .start()
@@ -452,7 +451,7 @@
         this.animatingBubble = animatingBubble.copy(expand = true)
         // if we're fully in and waiting to hide, cancel the hide animation and clean up
         if (animatingBubble.state == AnimatingBubble.State.IN) {
-            expandBubbleBar()
+            bubbleBarView.isExpanded = true
             cancelHideAnimation()
         }
     }
@@ -490,11 +489,6 @@
         this.animatingBubble = animatingBubble.copy(state = state)
     }
 
-    private fun expandBubbleBar() {
-        bubbleBarView.isExpanded = true
-        onExpanded.run()
-    }
-
     /**
      * Tracks the translation Y of the bubble bar during the animation. When the bubble bar expands
      * as part of the animation, the expansion should start after the bubble bar reaches the peak
@@ -516,7 +510,7 @@
             }
             val expand = animatingBubble?.expand ?: false
             if (reachedPeak && expand && !startedExpanding) {
-                expandBubbleBar()
+                bubbleBarView.isExpanded = true
                 startedExpanding = true
             }
             previousTy = ty
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index c3d3729..bb33c18 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -67,7 +67,7 @@
 import static com.android.quickstep.util.SplitAnimationTimings.TABLET_HOME_TO_SPLIT;
 import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.WALLPAPER_ACTIVITY;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
-import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50;
+import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_50_50;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index 3c7f335..eafc5b6 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -22,9 +22,9 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
+import android.graphics.Rect;
 import android.os.VibrationEffect;
 import android.view.MotionEvent;
-import android.view.View;
 import android.view.animation.Interpolator;
 
 import com.android.app.animation.Interpolators;
@@ -67,7 +67,7 @@
     protected final CONTAINER mContainer;
     private final SingleAxisSwipeDetector mDetector;
     private final RecentsView mRecentsView;
-    private final int[] mTempCords = new int[2];
+    private final Rect mTempRect = new Rect();
     private final boolean mIsRtl;
 
     private AnimatorPlaybackController mCurrentAnimation;
@@ -252,10 +252,8 @@
                     mTaskBeingDragged, maxDuration, currentInterpolator);
 
             // Since the thumbnail is what is filling the screen, based the end displacement on it.
-            View thumbnailView = mTaskBeingDragged.getFirstSnapshotView();
-            mTempCords[1] = orientationHandler.getSecondaryDimension(thumbnailView);
-            dl.getDescendantCoordRelativeToSelf(thumbnailView, mTempCords);
-            mEndDisplacement = secondaryLayerDimension - mTempCords[1];
+            mTaskBeingDragged.getThumbnailBounds(mTempRect, /*relativeToDragLayer=*/true);
+            mEndDisplacement = secondaryLayerDimension - mTempRect.bottom;
         }
         mEndDisplacement *= verticalFactor;
         mCurrentAnimation = pa.createPlaybackController();
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 540ab37..6109fd8 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -150,10 +150,10 @@
 import com.android.systemui.shared.system.SysUiStatsLog;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.system.TaskStackChangeListeners;
-import com.android.wm.shell.common.TransactionPool;
+import com.android.wm.shell.shared.TransactionPool;
 import com.android.wm.shell.shared.desktopmode.DesktopModeFlags;
 import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
-import com.android.wm.shell.startingsurface.SplashScreenExitAnimationUtils;
+import com.android.wm.shell.shared.startingsurface.SplashScreenExitAnimationUtils;
 
 import kotlin.Unit;
 
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 758ba41..ead5b7b 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -85,7 +85,6 @@
 import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource;
 import com.android.wm.shell.common.pip.IPip;
 import com.android.wm.shell.common.pip.IPipAnimationListener;
-import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition;
 import com.android.wm.shell.desktopmode.IDesktopMode;
 import com.android.wm.shell.desktopmode.IDesktopTaskListener;
 import com.android.wm.shell.draganddrop.IDragAndDrop;
@@ -95,6 +94,7 @@
 import com.android.wm.shell.shared.IShellTransitions;
 import com.android.wm.shell.shared.desktopmode.DesktopModeFlags;
 import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
+import com.android.wm.shell.shared.split.SplitScreenConstants.PersistentSnapPosition;
 import com.android.wm.shell.splitscreen.ISplitScreen;
 import com.android.wm.shell.splitscreen.ISplitScreenListener;
 import com.android.wm.shell.splitscreen.ISplitSelectListener;
@@ -934,17 +934,6 @@
         }
     }
 
-    /** Tells SysUI to show the expanded view. */
-    public void showExpandedView() {
-        try {
-            if (mBubbles != null) {
-                mBubbles.showExpandedView();
-            }
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed to call showExpandedView");
-        }
-    }
-
     //
     // Splitscreen
     //
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index bd44283..1a09691 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -232,9 +232,13 @@
                         TaskViewSimulator::setTaskRectTranslation, taskRectTranslationPrimary,
                         taskRectTranslationSecondary);
 
-                // Fade in the task during the initial 20% of the animation
-                out.addFloat(targetHandle.getTransformParams(), TransformParams.TARGET_ALPHA, 0, 1,
-                        clampToProgress(LINEAR, 0, 0.2f));
+                if (v instanceof DesktopTaskView) {
+                    targetHandle.getTransformParams().setTargetAlpha(1f);
+                } else {
+                    // Fade in the task during the initial 20% of the animation
+                    out.addFloat(targetHandle.getTransformParams(), TransformParams.TARGET_ALPHA, 0,
+                            1, clampToProgress(LINEAR, 0, 0.2f));
+                }
             }
         }
 
@@ -558,7 +562,7 @@
     /**
      * Start recents to desktop animation
      */
-    public static void composeRecentsDesktopLaunchAnimator(
+    public static AnimatorSet composeRecentsDesktopLaunchAnimator(
             @NonNull DesktopTaskView launchingTaskView,
             @NonNull StateManager stateManager, @Nullable DepthController depthController,
             @NonNull TransitionInfo transitionInfo,
@@ -588,7 +592,7 @@
                 true /* launcherClosing */, stateManager, launchingTaskView.getRecentsView(),
                 depthController);
 
-        animatorSet.start();
+        return animatorSet;
     }
 
     public static void composeRecentsLaunchAnimator(@NonNull AnimatorSet anim, @NonNull View v,
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 5c940a3..88ab528 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -49,16 +49,16 @@
 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER;
 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER;
 import static com.android.wm.shell.Flags.enableBubblesLongPressNavHandle;
-import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION;
-import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BUBBLES;
-import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DESKTOP_MODE;
-import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DRAG_AND_DROP;
-import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_ONE_HANDED;
-import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_PIP;
-import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_RECENT_TASKS;
-import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SHELL_TRANSITIONS;
-import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SPLIT_SCREEN;
-import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_STARTING_WINDOW;
+import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION;
+import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_BUBBLES;
+import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_DESKTOP_MODE;
+import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_DRAG_AND_DROP;
+import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_ONE_HANDED;
+import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_PIP;
+import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_RECENT_TASKS;
+import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_SHELL_TRANSITIONS;
+import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_SPLIT_SCREEN;
+import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_STARTING_WINDOW;
 
 import android.app.PendingIntent;
 import android.app.Service;
diff --git a/quickstep/src/com/android/quickstep/util/AppPairsController.java b/quickstep/src/com/android/quickstep/util/AppPairsController.java
index 8478ac9..ac4032c 100644
--- a/quickstep/src/com/android/quickstep/util/AppPairsController.java
+++ b/quickstep/src/com/android/quickstep/util/AppPairsController.java
@@ -26,11 +26,11 @@
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
-import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50;
-import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_NONE;
-import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
-import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
-import static com.android.wm.shell.common.split.SplitScreenConstants.isPersistentSnapPosition;
+import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_50_50;
+import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_NONE;
+import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
+import static com.android.wm.shell.shared.split.SplitScreenConstants.isPersistentSnapPosition;
 
 import android.content.Context;
 import android.content.Intent;
@@ -70,7 +70,7 @@
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
-import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition;
+import com.android.wm.shell.shared.split.SplitScreenConstants.PersistentSnapPosition;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index 770ec5a..2ff8e45 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -34,8 +34,8 @@
 import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_PENDINGINTENT;
 import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_SHORTCUT;
 import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_TASK;
-import static com.android.wm.shell.common.split.SplitScreenConstants.KEY_EXTRA_WIDGET_INTENT;
-import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50;
+import static com.android.wm.shell.shared.split.SplitScreenConstants.KEY_EXTRA_WIDGET_INTENT;
+import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_50_50;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -100,7 +100,7 @@
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
 import com.android.systemui.shared.system.QuickStepContract;
-import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition;
+import com.android.wm.shell.shared.split.SplitScreenConstants.PersistentSnapPosition;
 import com.android.wm.shell.splitscreen.ISplitSelectListener;
 
 import java.io.PrintWriter;
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index d9b7d20..e5c54bb 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -171,7 +171,6 @@
             mTaskRect.set(mFullTaskSize);
             mOrientationState.getOrientationHandler()
                     .setSplitTaskSwipeRect(mDp, mTaskRect, mSplitBounds, mStagePosition);
-            mTaskRect.offset(mTaskRectTranslationX, mTaskRectTranslationY);
         } else if (mIsDesktopTask) {
             // For desktop, tasks can take up only part of the screen size.
             // Full task size represents the whole screen size, but scaled down to fit in recents.
@@ -185,10 +184,19 @@
             mTaskRect.scale(scale);
             // Ensure the task rect is inside the full task rect
             mTaskRect.offset(mFullTaskSize.left, mFullTaskSize.top);
+
+            Rect taskDimension = new Rect(0, 0, (int) fullscreenTaskDimension.x,
+                    (int) fullscreenTaskDimension.y);
+            mTmpCropRect.set(mThumbnailPosition);
+            if (mTmpCropRect.setIntersect(taskDimension, mThumbnailPosition)) {
+                mTmpCropRect.offset(-mThumbnailPosition.left, -mThumbnailPosition.top);
+            } else {
+                mTmpCropRect.setEmpty();
+            }
         } else {
             mTaskRect.set(mFullTaskSize);
-            mTaskRect.offset(mTaskRectTranslationX, mTaskRectTranslationY);
         }
+        mTaskRect.offset(mTaskRectTranslationX, mTaskRectTranslationY);
     }
 
     /**
@@ -486,10 +494,12 @@
                 recentsViewPrimaryTranslation.value);
         applyWindowToHomeRotation(mMatrix);
 
-        // Crop rect is the inverse of thumbnail matrix
-        mTempRectF.set(0, 0, taskWidth, taskHeight);
-        mInversePositionMatrix.mapRect(mTempRectF);
-        mTempRectF.roundOut(mTmpCropRect);
+        if (!mIsDesktopTask) {
+            // Crop rect is the inverse of thumbnail matrix
+            mTempRectF.set(0, 0, taskWidth, taskHeight);
+            mInversePositionMatrix.mapRect(mTempRectF);
+            mTempRectF.roundOut(mTmpCropRect);
+        }
 
         params.setProgress(1f - fullScreenProgress);
         params.applySurfaceParams(surfaceTransaction == null
diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt b/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt
index e242dfd..8e48f22 100644
--- a/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt
+++ b/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt
@@ -242,7 +242,7 @@
         }
     }
 
-    override fun launchTaskAnimated(): RunnableList? {
+    private fun launchTaskWithDesktopController(animated: Boolean): RunnableList? {
         val recentsView = recentsView ?: return null
         TestLogging.recordEvent(
             TestProtocol.SEQUENCE_MAIN,
@@ -252,17 +252,23 @@
         val endCallback = RunnableList()
         val desktopController = recentsView.desktopRecentsController
         checkNotNull(desktopController) { "recentsController is null" }
-        desktopController.launchDesktopFromRecents(this) { endCallback.executeAllAndDestroy() }
-        Log.d(TAG, "launchTaskAnimated - launchDesktopFromRecents: ${taskIds.contentToString()}")
+        desktopController.launchDesktopFromRecents(this, animated) {
+            endCallback.executeAllAndDestroy()
+        }
+        Log.d(
+            TAG,
+            "launchTaskAnimated - launchTaskWithDesktopController: ${taskIds.contentToString()}, withRemoteTransition: $animated"
+        )
 
         // Callbacks get run from recentsView for case when recents animation already running
         recentsView.addSideTaskLaunchCallback(endCallback)
         return endCallback
     }
 
+    override fun launchTaskAnimated() = launchTaskWithDesktopController(animated = true)
+
     override fun launchTask(callback: (launched: Boolean) -> Unit, isQuickSwitch: Boolean) {
-        launchTasks()
-        callback(true)
+        launchTaskWithDesktopController(animated = false)?.add { callback(true) } ?: callback(false)
     }
 
     // Desktop tile can't be in split screen
@@ -272,8 +278,7 @@
     override fun setOverlayEnabled(overlayEnabled: Boolean) {}
 
     override fun onFullscreenProgressChanged(fullscreenProgress: Float) {
-        // Don't show background while we are transitioning to/from fullscreen
-        backgroundView.visibility = if (fullscreenProgress > 0) INVISIBLE else VISIBLE
+        backgroundView.alpha = 1 - fullscreenProgress
     }
 
     override fun updateCurrentFullscreenParams() {
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt b/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt
index 6523ba7..a046c42 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt
@@ -36,7 +36,7 @@
 import com.android.quickstep.util.SplitSelectStateController
 import com.android.systemui.shared.recents.model.Task
 import com.android.systemui.shared.system.InteractionJankMonitorWrapper
-import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition
+import com.android.wm.shell.shared.split.SplitScreenConstants.PersistentSnapPosition
 
 /**
  * TaskView that contains and shows thumbnails for not one, BUT TWO(!!) tasks
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 5a6c278..53e6e72 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -40,6 +40,7 @@
 import static com.android.launcher3.Flags.enableRefactorTaskThumbnail;
 import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
 import static com.android.launcher3.LauncherState.BACKGROUND_APP;
 import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION;
 import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
@@ -57,6 +58,7 @@
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
 import static com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK;
+import static com.android.quickstep.BaseContainerInterface.getTaskDimension;
 import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
 import static com.android.quickstep.util.LogUtils.splitFailureMessage;
 import static com.android.quickstep.util.TaskGridNavHelper.DIRECTION_DOWN;
@@ -90,6 +92,7 @@
 import android.graphics.Bitmap;
 import android.graphics.BlendMode;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Matrix;
 import android.graphics.Point;
 import android.graphics.PointF;
@@ -5232,23 +5235,37 @@
      * to the right.
      */
     @SuppressLint("Recycle")
-    public AnimatorSet createAdjacentPageAnimForTaskLaunch(TaskView tv) {
+    public AnimatorSet createAdjacentPageAnimForTaskLaunch(TaskView taskView) {
         AnimatorSet anim = new AnimatorSet();
 
-        int taskIndex = indexOfChild(tv);
+        int taskIndex = indexOfChild(taskView);
         int centerTaskIndex = getCurrentPage();
 
         float toScale = getMaxScaleForFullScreen();
         boolean showAsGrid = showAsGrid();
-        boolean launchingCenterTask = showAsGrid
-                ? tv.isFocusedTask() && isTaskViewFullyVisible(tv)
+        boolean zoomInTaskView = showAsGrid
+                ? ((taskView.isFocusedTask() && isTaskViewFullyVisible(taskView))
+                || taskView instanceof DesktopTaskView)
                 : taskIndex == centerTaskIndex;
-        if (launchingCenterTask) {
+        if (zoomInTaskView) {
             anim.play(ObjectAnimator.ofFloat(this, RECENTS_SCALE_PROPERTY, toScale));
             anim.play(ObjectAnimator.ofFloat(this, FULLSCREEN_PROGRESS, 1));
+            anim.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationStart(@NonNull Animator animation, boolean isReverse) {
+                    taskView.getThumbnailBounds(mTempRect, /*relativeToDragLayer=*/true);
+                    getTaskDimension(mContext, mContainer.getDeviceProfile(), mTempPointF);
+                    Rect fullscreenBounds = new Rect(0, 0, (int) mTempPointF.x,
+                            (int) mTempPointF.y);
+                    Utilities.getPivotsForScalingRectToRect(mTempRect, fullscreenBounds,
+                            mTempPointF);
+                    setPivotX(mTempPointF.x);
+                    setPivotY(mTempPointF.y);
+                }
+            });
         } else if (!showAsGrid) {
             // We are launching an adjacent task, so parallax the center and other adjacent task.
-            float displacementX = tv.getWidth() * (toScale - 1f);
+            float displacementX = taskView.getWidth() * (toScale - 1f);
             float primaryTranslation = mIsRtl ? -displacementX : displacementX;
             anim.play(ObjectAnimator.ofFloat(getPageAt(centerTaskIndex),
                     getPagedOrientationHandler().getPrimaryViewTranslate(), primaryTranslation));
@@ -5276,6 +5293,17 @@
             }
         }
         anim.play(ObjectAnimator.ofFloat(this, TASK_THUMBNAIL_SPLASH_ALPHA, 0, 1));
+        if (taskView instanceof DesktopTaskView) {
+            anim.play(ObjectAnimator.ofArgb(mContainer.getScrimView(), VIEW_BACKGROUND_COLOR,
+                    Color.TRANSPARENT));
+        }
+        DepthController depthController = getDepthController();
+        if (depthController != null) {
+            float targetDepth = taskView instanceof DesktopTaskView ? 0 : BACKGROUND_APP.getDepth(
+                    mContainer);
+            anim.play(ObjectAnimator.ofFloat(depthController.stateDepth, MULTI_PROPERTY_VALUE,
+                    targetDepth));
+        }
         return anim;
     }
 
@@ -5301,7 +5329,7 @@
     }
 
     public PendingAnimation createTaskLaunchAnimation(
-            TaskView tv, long duration, Interpolator interpolator) {
+            TaskView taskView, long duration, Interpolator interpolator) {
         if (FeatureFlags.IS_STUDIO_BUILD && mPendingAnimation != null) {
             throw new IllegalStateException("Another pending animation is still running");
         }
@@ -5316,13 +5344,13 @@
         updateGridProperties();
         updateScrollSynchronously();
 
-        int targetSysUiFlags = tv.getTaskContainers().getFirst().getSysUiStatusNavFlags();
+        int targetSysUiFlags = taskView.getTaskContainers().getFirst().getSysUiStatusNavFlags();
         final boolean[] passedOverviewThreshold = new boolean[]{false};
-        ValueAnimator progressAnim = ValueAnimator.ofFloat(0, 1);
-        progressAnim.addUpdateListener(animator -> {
+        AnimatorSet anim = createAdjacentPageAnimForTaskLaunch(taskView);
+        anim.play(new AnimatedFloat(v -> {
             // Once we pass a certain threshold, update the sysui flags to match the target
             // tasks' flags
-            if (animator.getAnimatedFraction() > UPDATE_SYSUI_FLAGS_THRESHOLD) {
+            if (v > UPDATE_SYSUI_FLAGS_THRESHOLD) {
                 mContainer.getSystemUiController().updateUiState(
                         UI_STATE_FULLSCREEN_TASK, targetSysUiFlags);
             } else {
@@ -5330,8 +5358,7 @@
             }
 
             // Passing the threshold from taskview to fullscreen app will vibrate
-            final boolean passed = animator.getAnimatedFraction() >=
-                    SUCCESS_TRANSITION_PROGRESS;
+            final boolean passed = v >= SUCCESS_TRANSITION_PROGRESS;
             if (passed != passedOverviewThreshold[0]) {
                 passedOverviewThreshold[0] = passed;
                 performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
@@ -5341,19 +5368,7 @@
                     mRecentsAnimationController.setWillFinishToHome(!passed);
                 }
             }
-        });
-
-        AnimatorSet anim = createAdjacentPageAnimForTaskLaunch(tv);
-
-        DepthController depthController = getDepthController();
-        if (depthController != null) {
-            ObjectAnimator depthAnimator = ObjectAnimator.ofFloat(depthController.stateDepth,
-                    MULTI_PROPERTY_VALUE, BACKGROUND_APP.getDepth(mContainer));
-            anim.play(depthAnimator);
-        }
-        anim.play(ObjectAnimator.ofFloat(this, TASK_THUMBNAIL_SPLASH_ALPHA, 0f, 1f));
-
-        anim.play(progressAnim);
+        }).animateToValue(0f, 1f));
         anim.setInterpolator(interpolator);
 
         mPendingAnimation = new PendingAnimation(duration);
@@ -5362,9 +5377,18 @@
                 remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator()
                         .addOverviewToAppAnim(mPendingAnimation, interpolator));
         mPendingAnimation.addOnFrameCallback(this::redrawLiveTile);
+        if (taskView instanceof DesktopTaskView && mRemoteTargetHandles != null) {
+            mPendingAnimation.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationStart(Animator animation) {
+                    runActionOnRemoteHandles(remoteTargetHandle ->
+                            remoteTargetHandle.getTaskViewSimulator().setDrawsBelowRecents(false));
+                }
+            });
+        }
         mPendingAnimation.addEndListener(isSuccess -> {
             if (isSuccess) {
-                if (tv instanceof GroupedTaskView && hasAllValidTaskIds(tv.getTaskIds())
+                if (taskView instanceof GroupedTaskView && hasAllValidTaskIds(taskView.getTaskIds())
                         && mRemoteTargetHandles != null) {
                     // TODO(b/194414938): make this part of the animations instead.
                     TaskViewUtils.createSplitAuxiliarySurfacesAnimator(
@@ -5374,13 +5398,13 @@
                                 dividerAnimator.end();
                             });
                 }
-                if (tv.isRunningTask()) {
+                if (taskView.isRunningTask()) {
                     finishRecentsAnimation(false /* toRecents */, null);
                     onTaskLaunchAnimationEnd(true /* success */);
                 } else {
-                    tv.launchTask(this::onTaskLaunchAnimationEnd);
+                    taskView.launchTask(this::onTaskLaunchAnimationEnd);
                 }
-                mContainer.getStatsLogManager().logger().withItemInfo(tv.getFirstItemInfo())
+                mContainer.getStatsLogManager().logger().withItemInfo(taskView.getFirstItemInfo())
                         .log(LAUNCHER_TASK_LAUNCH_SWIPE_DOWN);
             } else {
                 onTaskLaunchAnimationEnd(false);
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
index 7928ce9..4da06e1 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
@@ -64,7 +64,6 @@
     private lateinit var bubble: BubbleBarBubble
     private lateinit var bubbleBarView: BubbleBarView
     private lateinit var bubbleStashController: BubbleStashController
-    private val onExpandedNoOp = Runnable {}
 
     @Before
     fun setUp() {
@@ -82,12 +81,7 @@
         whenever(bubbleStashController.getStashedHandlePhysicsAnimator()).thenReturn(handleAnimator)
 
         val animator =
-            BubbleBarViewAnimator(
-                bubbleBarView,
-                bubbleStashController,
-                onExpandedNoOp,
-                animatorScheduler
-            )
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
             animator.animateBubbleInForStashed(bubble, isExpanding = false)
@@ -131,12 +125,7 @@
         whenever(bubbleStashController.getStashedHandlePhysicsAnimator()).thenReturn(handleAnimator)
 
         val animator =
-            BubbleBarViewAnimator(
-                bubbleBarView,
-                bubbleStashController,
-                onExpandedNoOp,
-                animatorScheduler
-            )
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
             animator.animateBubbleInForStashed(bubble, isExpanding = false)
@@ -179,12 +168,7 @@
         whenever(bubbleStashController.getStashedHandlePhysicsAnimator()).thenReturn(handleAnimator)
 
         val animator =
-            BubbleBarViewAnimator(
-                bubbleBarView,
-                bubbleStashController,
-                onExpandedNoOp,
-                animatorScheduler
-            )
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
             animator.animateBubbleInForStashed(bubble, isExpanding = false)
@@ -224,12 +208,7 @@
         whenever(bubbleStashController.getStashedHandlePhysicsAnimator()).thenReturn(handleAnimator)
 
         val animator =
-            BubbleBarViewAnimator(
-                bubbleBarView,
-                bubbleStashController,
-                onExpandedNoOp,
-                animatorScheduler
-            )
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
             animator.animateBubbleInForStashed(bubble, isExpanding = false)
@@ -270,12 +249,7 @@
         whenever(bubbleStashController.getStashedHandlePhysicsAnimator()).thenReturn(handleAnimator)
 
         val animator =
-            BubbleBarViewAnimator(
-                bubbleBarView,
-                bubbleStashController,
-                onExpandedNoOp,
-                animatorScheduler
-            )
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
             animator.animateBubbleInForStashed(bubble, isExpanding = false)
@@ -304,15 +278,8 @@
         val handleAnimator = PhysicsAnimator.getInstance(handle)
         whenever(bubbleStashController.getStashedHandlePhysicsAnimator()).thenReturn(handleAnimator)
 
-        var notifiedExpanded = false
-        val onExpanded = Runnable { notifiedExpanded = true }
         val animator =
-            BubbleBarViewAnimator(
-                bubbleBarView,
-                bubbleStashController,
-                onExpanded,
-                animatorScheduler
-            )
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
             animator.animateBubbleInForStashed(bubble, isExpanding = true)
@@ -336,7 +303,6 @@
         assertThat(animatorScheduler.delayedBlock).isNull()
 
         verify(bubbleStashController).showBubbleBarImmediate()
-        assertThat(notifiedExpanded).isTrue()
     }
 
     @Test
@@ -348,15 +314,8 @@
         val handleAnimator = PhysicsAnimator.getInstance(handle)
         whenever(bubbleStashController.getStashedHandlePhysicsAnimator()).thenReturn(handleAnimator)
 
-        var notifiedExpanded = false
-        val onExpanded = Runnable { notifiedExpanded = true }
         val animator =
-            BubbleBarViewAnimator(
-                bubbleBarView,
-                bubbleStashController,
-                onExpanded,
-                animatorScheduler
-            )
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
             animator.animateBubbleInForStashed(bubble, isExpanding = false)
@@ -386,7 +345,6 @@
             .isEqualTo(DIFF_BETWEEN_HANDLE_AND_BAR_CENTERS + BAR_TRANSLATION_Y_FOR_TASKBAR)
         verifyBubbleBarIsExpandedWithTranslation(BAR_TRANSLATION_Y_FOR_TASKBAR)
         assertThat(animator.isAnimating).isFalse()
-        assertThat(notifiedExpanded).isTrue()
     }
 
     @Test
@@ -398,15 +356,8 @@
         val handleAnimator = PhysicsAnimator.getInstance(handle)
         whenever(bubbleStashController.getStashedHandlePhysicsAnimator()).thenReturn(handleAnimator)
 
-        var notifiedExpanded = false
-        val onExpanded = Runnable { notifiedExpanded = true }
         val animator =
-            BubbleBarViewAnimator(
-                bubbleBarView,
-                bubbleStashController,
-                onExpanded,
-                animatorScheduler
-            )
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
             animator.animateBubbleInForStashed(bubble, isExpanding = false)
@@ -433,7 +384,6 @@
             .isEqualTo(DIFF_BETWEEN_HANDLE_AND_BAR_CENTERS + BAR_TRANSLATION_Y_FOR_TASKBAR)
         verifyBubbleBarIsExpandedWithTranslation(BAR_TRANSLATION_Y_FOR_TASKBAR)
         assertThat(animator.isAnimating).isFalse()
-        assertThat(notifiedExpanded).isTrue()
     }
 
     @Test
@@ -450,12 +400,7 @@
         val barAnimator = PhysicsAnimator.getInstance(bubbleBarView)
 
         val animator =
-            BubbleBarViewAnimator(
-                bubbleBarView,
-                bubbleStashController,
-                onExpandedNoOp,
-                animatorScheduler
-            )
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
             animator.animateToInitialState(bubble, isInApp = true, isExpanding = false)
@@ -497,15 +442,8 @@
 
         val barAnimator = PhysicsAnimator.getInstance(bubbleBarView)
 
-        var notifiedExpanded = false
-        val onExpanded = Runnable { notifiedExpanded = true }
         val animator =
-            BubbleBarViewAnimator(
-                bubbleBarView,
-                bubbleStashController,
-                onExpanded,
-                animatorScheduler
-            )
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
             animator.animateToInitialState(bubble, isInApp = true, isExpanding = true)
@@ -521,7 +459,6 @@
 
         assertThat(animatorScheduler.delayedBlock).isNull()
         verify(bubbleStashController).showBubbleBarImmediate()
-        assertThat(notifiedExpanded).isTrue()
     }
 
     @Test
@@ -534,12 +471,7 @@
         val barAnimator = PhysicsAnimator.getInstance(bubbleBarView)
 
         val animator =
-            BubbleBarViewAnimator(
-                bubbleBarView,
-                bubbleStashController,
-                onExpandedNoOp,
-                animatorScheduler
-            )
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
             animator.animateToInitialState(bubble, isInApp = false, isExpanding = false)
@@ -570,15 +502,8 @@
         whenever(bubbleStashController.bubbleBarTranslationY)
             .thenReturn(BAR_TRANSLATION_Y_FOR_HOTSEAT)
 
-        var notifiedExpanded = false
-        val onExpanded = Runnable { notifiedExpanded = true }
         val animator =
-            BubbleBarViewAnimator(
-                bubbleBarView,
-                bubbleStashController,
-                onExpanded,
-                animatorScheduler
-            )
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
             animator.animateToInitialState(bubble, isInApp = false, isExpanding = false)
@@ -608,7 +533,6 @@
         verifyBubbleBarIsExpandedWithTranslation(BAR_TRANSLATION_Y_FOR_HOTSEAT)
         assertThat(animator.isAnimating).isFalse()
         verify(bubbleStashController).showBubbleBarImmediate()
-        assertThat(notifiedExpanded).isTrue()
     }
 
     @Test
@@ -618,15 +542,8 @@
         whenever(bubbleStashController.bubbleBarTranslationY)
             .thenReturn(BAR_TRANSLATION_Y_FOR_HOTSEAT)
 
-        var notifiedExpanded = false
-        val onExpanded = Runnable { notifiedExpanded = true }
         val animator =
-            BubbleBarViewAnimator(
-                bubbleBarView,
-                bubbleStashController,
-                onExpanded,
-                animatorScheduler
-            )
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
             animator.animateToInitialState(bubble, isInApp = false, isExpanding = false)
@@ -649,7 +566,6 @@
 
         verifyBubbleBarIsExpandedWithTranslation(BAR_TRANSLATION_Y_FOR_HOTSEAT)
         assertThat(animator.isAnimating).isFalse()
-        assertThat(notifiedExpanded).isTrue()
     }
 
     @Test
@@ -662,12 +578,7 @@
         val barAnimator = PhysicsAnimator.getInstance(bubbleBarView)
 
         val animator =
-            BubbleBarViewAnimator(
-                bubbleBarView,
-                bubbleStashController,
-                onExpandedNoOp,
-                animatorScheduler
-            )
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
             animator.animateBubbleBarForCollapsed(bubble, isExpanding = false)
@@ -706,15 +617,8 @@
 
         val barAnimator = PhysicsAnimator.getInstance(bubbleBarView)
 
-        var notifiedExpanded = false
-        val onExpanded = Runnable { notifiedExpanded = true }
         val animator =
-            BubbleBarViewAnimator(
-                bubbleBarView,
-                bubbleStashController,
-                onExpanded,
-                animatorScheduler
-            )
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
             animator.animateBubbleBarForCollapsed(bubble, isExpanding = true)
@@ -741,7 +645,6 @@
         assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_HOTSEAT)
         assertThat(bubbleBarView.isExpanded).isTrue()
         verify(bubbleStashController).showBubbleBarImmediate()
-        assertThat(notifiedExpanded).isTrue()
     }
 
     @Test
@@ -753,15 +656,8 @@
 
         val barAnimator = PhysicsAnimator.getInstance(bubbleBarView)
 
-        var notifiedExpanded = false
-        val onExpanded = Runnable { notifiedExpanded = true }
         val animator =
-            BubbleBarViewAnimator(
-                bubbleBarView,
-                bubbleStashController,
-                onExpanded,
-                animatorScheduler
-            )
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
             animator.animateBubbleBarForCollapsed(bubble, isExpanding = false)
@@ -799,7 +695,6 @@
         assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_HOTSEAT)
         assertThat(bubbleBarView.isExpanded).isTrue()
         verify(bubbleStashController).showBubbleBarImmediate()
-        assertThat(notifiedExpanded).isTrue()
     }
 
     @Test
@@ -811,15 +706,8 @@
 
         val barAnimator = PhysicsAnimator.getInstance(bubbleBarView)
 
-        var notifiedExpanded = false
-        val onExpanded = Runnable { notifiedExpanded = true }
         val animator =
-            BubbleBarViewAnimator(
-                bubbleBarView,
-                bubbleStashController,
-                onExpanded,
-                animatorScheduler
-            )
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
             animator.animateBubbleBarForCollapsed(bubble, isExpanding = false)
@@ -854,7 +742,6 @@
         assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_HOTSEAT)
         assertThat(bubbleBarView.isExpanded).isTrue()
         verify(bubbleStashController).showBubbleBarImmediate()
-        assertThat(notifiedExpanded).isTrue()
     }
 
     private fun setUpBubbleBar() {
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/AppPairsControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/AppPairsControllerTest.kt
index ece67af..99d3121 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/AppPairsControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/AppPairsControllerTest.kt
@@ -28,9 +28,9 @@
 import com.android.quickstep.TopTaskTracker.CachedTaskInfo
 import com.android.systemui.shared.recents.model.Task
 import com.android.systemui.shared.recents.model.Task.TaskKey
-import com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_30_70
-import com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50
-import com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_70_30
+import com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_30_70
+import com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_50_50
+import com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_70_30
 import java.util.function.Consumer
 import org.junit.Assert.assertEquals
 import org.junit.Before
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/GroupTaskTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/GroupTaskTest.kt
index f11cd0b..7b1c066 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/GroupTaskTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/GroupTaskTest.kt
@@ -23,7 +23,7 @@
 import com.android.launcher3.util.SplitConfigurationOptions
 import com.android.quickstep.views.TaskViewType
 import com.android.systemui.shared.recents.model.Task
-import com.android.wm.shell.common.split.SplitScreenConstants
+import com.android.wm.shell.shared.split.SplitScreenConstants
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
index bab84ef..fc4c4f6 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
@@ -39,7 +39,7 @@
 import com.android.quickstep.util.SplitSelectStateController.SplitFromDesktopController
 import com.android.quickstep.views.RecentsViewContainer
 import com.android.systemui.shared.recents.model.Task
-import com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50
+import com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_50_50
 import java.util.function.Consumer
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarHoverToolTipControllerTest.java b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarHoverToolTipControllerTest.java
index ef3a833..67a0ee4 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarHoverToolTipControllerTest.java
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarHoverToolTipControllerTest.java
@@ -202,7 +202,7 @@
         boolean hoverHandled =
                 mTaskbarHoverToolTipController.onHover(mHoverFolderIcon, mMotionEvent);
 
-        assertThat(hoverHandled).isFalse();
+        assertThat(hoverHandled).isTrue();
     }
 
     @Test
@@ -213,7 +213,7 @@
         boolean hoverHandled =
                 mTaskbarHoverToolTipController.onHover(mHoverFolderIcon, mMotionEvent);
 
-        assertThat(hoverHandled).isFalse();
+        assertThat(hoverHandled).isTrue();
     }
 
     @Test
diff --git a/res/layout/private_space_header.xml b/res/layout/private_space_header.xml
index e68f0f3..6bce220 100644
--- a/res/layout/private_space_header.xml
+++ b/res/layout/private_space_header.xml
@@ -100,6 +100,7 @@
         android:gravity="center_vertical"
         android:layout_marginStart="@dimen/ps_header_layout_margin"
         android:text="@string/ps_container_title"
+        android:maxLines="1"
         android:theme="@style/PrivateSpaceHeaderTextStyle"
         android:importantForAccessibility="no"/>
 
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index 876b643..d3ee364 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -138,9 +138,6 @@
     public static final int TYPE_TOUCH_CONTROLLER_NO_INTERCEPT = TYPE_ALL & ~TYPE_DISCOVERY_BOUNCE
             & ~TYPE_LISTENER & ~TYPE_TASKBAR_OVERLAYS;
 
-    public static final int TYPE_ALL_EXCEPT_ON_BOARD_POPUP = TYPE_ALL & ~TYPE_ON_BOARD_POPUP
-            & ~TYPE_PIN_IME_POPUP;
-
     protected boolean mIsOpen;
 
     public AbstractFloatingView(Context context, AttributeSet attrs) {
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 6c706be..fac372b 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -2708,6 +2708,10 @@
         mWidgetPickerDataProvider.dump(prefix, writer);
         mDeviceProfile.dump(this, prefix, writer);
         mAppsView.getAppsStore().dump(prefix, writer);
+        mAppsView.getPersonalAppList().dump(prefix, writer);
+        if (mAppsView.shouldShowTabs()) {
+            mAppsView.getWorkAppList().dump(prefix, writer);
+        }
 
         try {
             FileLog.flushAll(writer);
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index ad660d2..227ac2b 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -18,6 +18,7 @@
 import static com.android.launcher3.Flags.enableExpandingPauseWorkButton;
 import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.MAIN;
 import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.SEARCH;
+import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.WORK;
 import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_PRIVATE_SPACE_HEADER;
 import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_WORK_DISABLED_CARD;
 import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_WORK_EDU_CARD;
@@ -1313,6 +1314,10 @@
         return mAH.get(MAIN).mAppsList;
     }
 
+    public AlphabeticalAppsList<T> getWorkAppList() {
+        return mAH.get(WORK).mAppsList;
+    }
+
     public FloatingHeaderView getFloatingHeaderView() {
         return mHeader;
     }
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index a3cabc2..6dd811a 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -26,6 +26,7 @@
 import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.style.ImageSpan;
+import android.util.Log;
 
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
@@ -39,6 +40,7 @@
 import com.android.launcher3.util.LabelComparator;
 import com.android.launcher3.views.ActivityContext;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
@@ -270,6 +272,7 @@
         List<AdapterItem> oldItems = new ArrayList<>(mAdapterItems);
         // Prepare to update the list of sections, filtered apps, etc.
         mFastScrollerSections.clear();
+        Log.d(TAG, "Clearing FastScrollerSections.");
         mAdapterItems.clear();
         mAccessibilityResultsCount = 0;
 
@@ -290,6 +293,7 @@
                     mFastScrollerSections.add(new FastScrollSectionInfo(
                             mActivityContext.getResources().getString(
                                     R.string.work_profile_edu_section), 0));
+                    Log.d(TAG, "Adding FastScrollSection for work edu card.");
                 }
                 position = addAppsWithSections(mApps, position);
             }
@@ -303,6 +307,7 @@
                 mFastScrollerSections.add(new FastScrollSectionInfo(
                         mFastScrollerSections.get(mFastScrollerSections.size() - 1).sectionName,
                         position++));
+                Log.d(TAG, "Adding FastScrollSection duplicate to scroll to the bottom.");
             }
         }
         mAccessibilityResultsCount = (int) mAdapterItems.stream()
@@ -346,6 +351,7 @@
                 && !mPrivateApps.isEmpty()) {
             // Always add PS Header if Space is present and visible.
             position = mPrivateProviderManager.addPrivateSpaceHeader(mAdapterItems);
+            Log.d(TAG, "Adding FastScrollSection for Private Space header. ");
             mFastScrollerSections.add(new FastScrollSectionInfo(
                     mPrivateProfileAppScrollerBadge, position));
             int privateSpaceState = mPrivateProviderManager.getCurrentState();
@@ -407,6 +413,7 @@
             hasPrivateApps = appList.stream().
                     allMatch(mPrivateProviderManager.getItemInfoMatcher());
         }
+        Log.d(TAG, "Adding apps with sections. HasPrivateApps: " + hasPrivateApps);
         for (int i = 0; i < appList.size(); i++) {
             AppInfo info = appList.get(i);
             // Apply decorator to private apps.
@@ -421,6 +428,8 @@
             String sectionName = info.sectionName;
             // Create a new section if the section names do not match
             if (!sectionName.equals(lastSectionName)) {
+                Log.d(TAG, "addAppsWithSections: adding sectionName: " + sectionName
+                    + " with appInfoTitle: " + info.title);
                 lastSectionName = sectionName;
                 mFastScrollerSections.add(new FastScrollSectionInfo(hasPrivateApps ?
                         mPrivateProfileAppScrollerBadge : sectionName, position));
@@ -471,6 +480,13 @@
         return mPrivateProviderManager;
     }
 
+    public void dump(String prefix, PrintWriter writer) {
+        writer.println(prefix + "SectionInfo[] size: " + mFastScrollerSections.size());
+        for (int i = 0; i < mFastScrollerSections.size(); i++) {
+            writer.println("\tFastScrollSection: " + mFastScrollerSections.get(i).sectionName);
+        }
+    }
+
     private static class MyDiffCallback extends DiffUtil.Callback {
 
         private final List<AdapterItem> mOldList;
diff --git a/src/com/android/launcher3/compat/AlphabeticIndexCompat.java b/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
index 4f8d53e..d593f80 100644
--- a/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
+++ b/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
@@ -3,6 +3,7 @@
 import android.content.Context;
 import android.icu.text.AlphabeticIndex;
 import android.os.LocaleList;
+import android.util.Log;
 
 import androidx.annotation.NonNull;
 
@@ -12,6 +13,9 @@
 
 public class AlphabeticIndexCompat {
 
+    // TODO(b/336947811): Set to false after root causing is done.
+    private static final boolean DEBUG = true;
+    private static final String TAG = "AlphabeticIndexCompat";
     private static final String MID_DOT = "\u2219";
     private final String mDefaultMiscLabel;
 
@@ -49,6 +53,9 @@
     public String computeSectionName(@NonNull CharSequence cs) {
         String s = Utilities.trim(cs);
         String sectionName = mBaseIndex.getBucket(mBaseIndex.getBucketIndex(s)).getLabel();
+        if (DEBUG) {
+            Log.d(TAG, "computeSectionName: cs: " + cs + " sectionName: " + sectionName);
+        }
         if (Utilities.trim(sectionName).isEmpty() && s.length() > 0) {
             int c = s.codePointAt(0);
             boolean startsWithDigit = Character.isDigit(c);
diff --git a/src/com/android/launcher3/keyboard/ItemFocusIndicatorHelper.java b/src/com/android/launcher3/keyboard/ItemFocusIndicatorHelper.java
index 480e8f3..ec0efe0 100644
--- a/src/com/android/launcher3/keyboard/ItemFocusIndicatorHelper.java
+++ b/src/com/android/launcher3/keyboard/ItemFocusIndicatorHelper.java
@@ -199,6 +199,10 @@
     }
 
     protected void changeFocus(T item, boolean hasFocus) {
+        if (mLastFocusedItem != item && !hasFocus) {
+            return;
+        }
+
         if (hasFocus) {
             endCurrentAnimation();
 
diff --git a/src/com/android/launcher3/util/DimensionUtils.kt b/src/com/android/launcher3/util/DimensionUtils.kt
index 63e919a..821dda7 100644
--- a/src/com/android/launcher3/util/DimensionUtils.kt
+++ b/src/com/android/launcher3/util/DimensionUtils.kt
@@ -31,7 +31,8 @@
     fun getTaskbarPhoneDimensions(
             deviceProfile: DeviceProfile,
             res: Resources,
-            isPhoneMode: Boolean
+            isPhoneMode: Boolean,
+            isGestureNav: Boolean,
     ): Point {
         val p = Point()
         // Taskbar for large screen
@@ -42,7 +43,7 @@
         }
 
         // Taskbar on phone using gesture nav, it will always be stashed
-        if (deviceProfile.isGestureMode) {
+        if (isGestureNav) {
             p.x = ViewGroup.LayoutParams.MATCH_PARENT
             p.y = res.getDimensionPixelSize(R.dimen.taskbar_stashed_size)
             return p
diff --git a/tests/multivalentTests/src/com/android/launcher3/icons/IconCacheUpdateHandlerTest.kt b/tests/multivalentTests/src/com/android/launcher3/icons/IconCacheUpdateHandlerTest.kt
new file mode 100644
index 0000000..e27926f
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/icons/IconCacheUpdateHandlerTest.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.icons
+
+import android.content.ComponentName
+import android.content.pm.PackageInfo
+import android.database.Cursor
+import android.os.UserHandle
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.icons.cache.BaseIconCache
+import com.android.launcher3.icons.cache.CachingLogic
+import com.android.launcher3.icons.cache.IconCacheUpdateHandler
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.doReturn
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class IconCacheUpdateHandlerTest {
+
+    @Mock private lateinit var cursor: Cursor
+    @Mock private lateinit var user: UserHandle
+    @Mock private lateinit var cachingLogic: CachingLogic<String>
+    @Mock private lateinit var baseIconCache: BaseIconCache
+
+    private var componentMap: HashMap<ComponentName, String> = hashMapOf()
+    private var ignorePackages: Set<String> = setOf()
+    private var packageInfoMap: HashMap<String, PackageInfo> = hashMapOf()
+
+    private val dummyRowData =
+        IconCacheRowData(
+            "com.android.fake/.FakeActivity",
+            System.currentTimeMillis(),
+            1,
+            1.0.toLong(),
+            "stateOfConfusion"
+        )
+
+    @Before
+    fun setup() {
+
+        MockitoAnnotations.initMocks(this)
+        // Load in a specific row to the database
+        doReturn(0).`when`(cursor).getColumnIndex(BaseIconCache.IconDB.COLUMN_COMPONENT)
+        doReturn(1).`when`(cursor).getColumnIndex(BaseIconCache.IconDB.COLUMN_LAST_UPDATED)
+        doReturn(2).`when`(cursor).getColumnIndex(BaseIconCache.IconDB.COLUMN_VERSION)
+        doReturn(3).`when`(cursor).getColumnIndex(BaseIconCache.IconDB.COLUMN_ROWID)
+        doReturn(4).`when`(cursor).getColumnIndex(BaseIconCache.IconDB.COLUMN_SYSTEM_STATE)
+        doReturn(dummyRowData.component).`when`(cursor).getString(0)
+        doReturn(dummyRowData.lastUpdated).`when`(cursor).getLong(1)
+        doReturn(dummyRowData.version).`when`(cursor).getInt(2)
+        doReturn(dummyRowData.row).`when`(cursor).getLong(3)
+        doReturn(dummyRowData.systemState).`when`(cursor).getString(4)
+    }
+
+    @Test
+    fun `IconCacheUpdateHandler returns null if the component name is malformed`() {
+        val updateHandlerUnderTest = IconCacheUpdateHandler(packageInfoMap, baseIconCache)
+
+        val result =
+            updateHandlerUnderTest.updateOrDeleteIcon(
+                cursor,
+                componentMap,
+                ignorePackages,
+                user,
+                cachingLogic
+            )
+
+        assert(result == null)
+    }
+}
+
+data class IconCacheRowData(
+    val component: String,
+    val lastUpdated: Long,
+    val version: Int,
+    val row: Long,
+    val systemState: String
+)
diff --git a/tests/src/com/android/launcher3/testcomponent/TouchEventGenerator.java b/tests/multivalentTests/src/com/android/launcher3/testcomponent/TouchEventGenerator.java
similarity index 100%
rename from tests/src/com/android/launcher3/testcomponent/TouchEventGenerator.java
rename to tests/multivalentTests/src/com/android/launcher3/testcomponent/TouchEventGenerator.java