Update config ordering when entering/leaving pip

- Always set the activity windowing mode to the previous windowing mode
  prior to pip until SysUI has a chance to update
- When entering with bounds animation, do the bounds animation before
  resetting the activity windowing mode and setting final bounds
- When entering with alpha animation, immediately reset the activity
  windowing mode and final bounds
- When exiting, set the activity windowing mode to fullscreen along with
  the task bounds and do an inverse scale animation from the previous
  size up to fullscreen
- Skip the animation when exiting to fullscreen in another orientation
- Dumping pip task org state

Bug: 149946388
Test: Enter/exit pip
Test: atest PinnedStackTests

Change-Id: Ia5a50a5e2ce7621c2c678d0ded3d8c02b1932302
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
index f72de11..13516a9 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
@@ -65,6 +65,10 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface TransitionDirection {}
 
+    public static boolean isInPipDirection(@TransitionDirection int direction) {
+        return direction == TRANSITION_DIRECTION_TO_PIP;
+    }
+
     public static boolean isOutPipDirection(@TransitionDirection int direction) {
         return direction == TRANSITION_DIRECTION_TO_FULLSCREEN
                 || direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN;
@@ -104,6 +108,12 @@
         if (mCurrentAnimator == null) {
             mCurrentAnimator = setupPipTransitionAnimator(
                     PipTransitionAnimator.ofBounds(leash, startBounds, endBounds));
+        } else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_ALPHA
+                && mCurrentAnimator.isRunning()) {
+            // If we are still animating the fade into pip, then just move the surface and ensure
+            // we update with the new destination bounds, but don't interrupt the existing animation
+            // with a new bounds
+            mCurrentAnimator.setDestinationBounds(endBounds);
         } else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_BOUNDS
                 && mCurrentAnimator.isRunning()) {
             mCurrentAnimator.setDestinationBounds(endBounds);
@@ -265,8 +275,7 @@
 
         boolean inScaleTransition() {
             if (mAnimationType != ANIM_TYPE_BOUNDS) return false;
-            final int direction = getTransitionDirection();
-            return !isOutPipDirection(direction) && direction != TRANSITION_DIRECTION_TO_PIP;
+            return !isInPipDirection(getTransitionDirection());
         }
 
         /**
@@ -354,7 +363,11 @@
                             getCastedFractionValue(start.bottom, end.bottom, fraction));
                     setCurrentValue(mTmpRect);
                     if (inScaleTransition()) {
-                        getSurfaceTransactionHelper().scale(tx, leash, start, mTmpRect);
+                        if (isOutPipDirection(getTransitionDirection())) {
+                            getSurfaceTransactionHelper().scale(tx, leash, end, mTmpRect);
+                        } else {
+                            getSurfaceTransactionHelper().scale(tx, leash, start, mTmpRect);
+                        }
                     } else {
                         getSurfaceTransactionHelper().crop(tx, leash, mTmpRect);
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
index 3eeadc3..394f997 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
@@ -209,6 +209,10 @@
         return new Rect(0, 0, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
     }
 
+    public int getDisplayRotation() {
+        return mDisplayInfo.rotation;
+    }
+
     /**
      * Responds to IPinnedStackListener on {@link DisplayInfo} change.
      * It will normally follow up with a
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index 7e2efc0..fd13890 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.pip;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 
 import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_ALPHA;
@@ -25,25 +28,30 @@
 import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_FULLSCREEN;
 import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;
 import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_SPLIT_SCREEN;
+import static com.android.systemui.pip.PipAnimationController.isInPipDirection;
 import static com.android.systemui.pip.PipAnimationController.isOutPipDirection;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.ActivityTaskManager;
 import android.app.PictureInPictureParams;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
+import android.os.RemoteException;
 import android.util.Log;
 import android.util.Size;
 import android.view.SurfaceControl;
 import android.window.TaskOrganizer;
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
+import android.window.WindowContainerTransactionCallback;
 import android.window.WindowOrganizer;
 
 import com.android.internal.os.SomeArgs;
@@ -51,6 +59,7 @@
 import com.android.systemui.pip.phone.PipUpdateThread;
 import com.android.systemui.stackdivider.Divider;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -90,7 +99,7 @@
     private final Rect mLastReportedBounds = new Rect();
     private final int mEnterExitAnimationDuration;
     private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
-    private final Map<IBinder, Rect> mBoundsToRestore = new HashMap<>();
+    private final Map<IBinder, Configuration> mInitialState = new HashMap<>();
     private final Divider mSplitDivider;
 
     // These callbacks are called on the update thread
@@ -110,7 +119,8 @@
         @Override
         public void onPipAnimationEnd(SurfaceControl.Transaction tx,
                 PipAnimationController.PipTransitionAnimator animator) {
-            finishResize(tx, animator.getDestinationBounds(), animator.getTransitionDirection());
+            finishResize(tx, animator.getDestinationBounds(), animator.getTransitionDirection(),
+                    animator.getAnimationType());
             mMainHandler.post(() -> {
                 for (int i = mPipTransitionCallbacks.size() - 1; i >= 0; i--) {
                     final PipTransitionCallback callback = mPipTransitionCallbacks.get(i);
@@ -170,7 +180,7 @@
             case MSG_FINISH_RESIZE: {
                 SurfaceControl.Transaction tx = (SurfaceControl.Transaction) args.arg2;
                 Rect toBounds = (Rect) args.arg3;
-                finishResize(tx, toBounds, args.argi1 /* direction */);
+                finishResize(tx, toBounds, args.argi1 /* direction */, -1);
                 if (updateBoundsCallback != null) {
                     updateBoundsCallback.accept(toBounds);
                 }
@@ -240,28 +250,76 @@
     }
 
     /**
-     * Dismiss PiP, this is done in two phases using {@link WindowContainerTransaction}
-     * - setActivityWindowingMode to undefined at beginning of the transaction. without changing
-     *   the windowing mode of the Task itself. This makes sure the activity render it's final
-     *   configuration while the Task is still in PiP.
+     * Expands PiP to the previous bounds, this is done in two phases using
+     * {@link WindowContainerTransaction}
+     * - setActivityWindowingMode to either fullscreen or split-secondary at beginning of the
+     *   transaction. without changing the windowing mode of the Task itself. This makes sure the
+     *   activity render it's final configuration while the Task is still in PiP.
      * - setWindowingMode to undefined at the end of transition
      * @param animationDurationMs duration in millisecond for the exiting PiP transition
      */
-    public void dismissPip(int animationDurationMs) {
+    public void exitPip(int animationDurationMs) {
         if (!mInPip || mToken == null) {
-            Log.wtf(TAG, "Not allowed to dismissPip in current state"
+            Log.wtf(TAG, "Not allowed to exitPip in current state"
                     + " mInPip=" + mInPip + " mToken=" + mToken);
             return;
         }
+
+        final Configuration initialConfig = mInitialState.remove(mToken.asBinder());
+        final boolean orientationDiffers = initialConfig.windowConfiguration.getRotation()
+                != mPipBoundsHandler.getDisplayRotation();
         final WindowContainerTransaction wct = new WindowContainerTransaction();
-        wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
-        WindowOrganizer.applyTransaction(wct);
-        final Rect destinationBounds = mBoundsToRestore.remove(mToken.asBinder());
-        final int direction = syncWithSplitScreenBounds(destinationBounds)
-                ? TRANSITION_DIRECTION_TO_SPLIT_SCREEN : TRANSITION_DIRECTION_TO_FULLSCREEN;
-        scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
-                direction, animationDurationMs, null /* updateBoundsCallback */);
-        mInPip = false;
+        if (orientationDiffers) {
+            // Don't bother doing an animation if the display rotation differs or if it's in
+            // a non-supported windowing mode
+            wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
+            wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
+            WindowOrganizer.applyTransaction(wct);
+            mInPip = false;
+        } else {
+            final Rect destinationBounds = initialConfig.windowConfiguration.getBounds();
+            final int direction = syncWithSplitScreenBounds(destinationBounds)
+                    ? TRANSITION_DIRECTION_TO_SPLIT_SCREEN
+                    : TRANSITION_DIRECTION_TO_FULLSCREEN;
+            final SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
+            mSurfaceTransactionHelper.scale(tx, mLeash, destinationBounds,
+                    mLastReportedBounds);
+            tx.setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height());
+            wct.setActivityWindowingMode(mToken, direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN
+                    ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
+                    : WINDOWING_MODE_FULLSCREEN);
+            wct.setBounds(mToken, destinationBounds);
+            wct.setBoundsChangeTransaction(mToken, tx);
+            applySyncTransaction(wct, new WindowContainerTransactionCallback() {
+                @Override
+                public void onTransactionReady(int id, SurfaceControl.Transaction t) {
+                    t.apply();
+                    scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
+                            direction, animationDurationMs, null /* updateBoundsCallback */);
+                    mInPip = false;
+                }
+            });
+        }
+    }
+
+    /**
+     * Removes PiP immediately.
+     */
+    public void removePip() {
+        if (!mInPip || mToken == null) {
+            Log.wtf(TAG, "Not allowed to removePip in current state"
+                    + " mInPip=" + mInPip + " mToken=" + mToken);
+            return;
+        }
+        getUpdateHandler().post(() -> {
+            try {
+                ActivityTaskManager.getService().removeStacksInWindowingModes(
+                        new int[]{ WINDOWING_MODE_PINNED });
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to remove PiP", e);
+            }
+        });
+        mInitialState.remove(mToken.asBinder());
     }
 
     @Override
@@ -277,19 +335,37 @@
         mInPip = true;
         mLeash = leash;
 
+        // TODO: Skip enter animation when entering pip from another orientation
         final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
-        mBoundsToRestore.put(mToken.asBinder(), currentBounds);
+        mInitialState.put(mToken.asBinder(), new Configuration(mTaskInfo.configuration));
+
         if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
             scheduleAnimateResizePip(currentBounds, destinationBounds,
                     TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
                     null /* updateBoundsCallback */);
         } else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
-            mUpdateHandler.post(() -> mPipAnimationController
-                    .getAnimator(mLeash, destinationBounds, 0f, 1f)
-                    .setTransitionDirection(TRANSITION_DIRECTION_TO_PIP)
-                    .setPipAnimationCallback(mPipAnimationCallback)
-                    .setDuration(mEnterExitAnimationDuration)
-                    .start());
+            // If we are fading the PIP in, then we should move the pip to the final location as
+            // soon as possible, but set the alpha immediately since the transaction can take a
+            // while to process
+            final SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
+            tx.setAlpha(mLeash, 0f);
+            tx.apply();
+            final WindowContainerTransaction wct = new WindowContainerTransaction();
+            wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
+            wct.setBounds(mToken, destinationBounds);
+            wct.scheduleFinishEnterPip(mToken, destinationBounds);
+            applySyncTransaction(wct, new WindowContainerTransactionCallback() {
+                @Override
+                public void onTransactionReady(int id, SurfaceControl.Transaction t) {
+                    t.apply();
+                    mUpdateHandler.post(() -> mPipAnimationController
+                            .getAnimator(mLeash, destinationBounds, 0f, 1f)
+                            .setTransitionDirection(TRANSITION_DIRECTION_TO_PIP)
+                            .setPipAnimationCallback(mPipAnimationCallback)
+                            .setDuration(mEnterExitAnimationDuration)
+                            .start());
+                }
+            });
             mOneShotAnimationType = ANIM_TYPE_BOUNDS;
         } else {
             throw new RuntimeException("Unrecognized animation type: " + mOneShotAnimationType);
@@ -297,7 +373,7 @@
     }
 
     /**
-     * Note that dismissing PiP is now originated from SystemUI, see {@link #dismissPip(int)}.
+     * Note that dismissing PiP is now originated from SystemUI, see {@link #exitPip(int)}.
      * Meanwhile this callback is invoked whenever the task is removed. For instance:
      *   - as a result of removeStacksInWindowingModes from WM
      *   - activity itself is died
@@ -411,6 +487,7 @@
             // can be initiated in other component, ignore if we are no longer in PIP
             return;
         }
+
         SomeArgs args = SomeArgs.obtain();
         args.arg1 = updateBoundsCallback;
         args.arg2 = currentBounds;
@@ -509,7 +586,7 @@
             throw new RuntimeException("Callers should call scheduleResizePip() instead of this "
                     + "directly");
         }
-        // Could happen when dismissPip
+        // Could happen when exitPip
         if (mToken == null || mLeash == null) {
             Log.w(TAG, "Abort animation, invalid leash");
             return;
@@ -526,7 +603,7 @@
             throw new RuntimeException("Callers should call scheduleUserResizePip() instead of "
                     + "this directly");
         }
-        // Could happen when dismissPip
+        // Could happen when exitPip
         if (mToken == null || mLeash == null) {
             Log.w(TAG, "Abort animation, invalid leash");
             return;
@@ -537,32 +614,43 @@
     }
 
     private void finishResize(SurfaceControl.Transaction tx, Rect destinationBounds,
-            @PipAnimationController.TransitionDirection int direction) {
+            @PipAnimationController.TransitionDirection int direction,
+            @PipAnimationController.AnimationType int type) {
         if (Looper.myLooper() != mUpdateHandler.getLooper()) {
             throw new RuntimeException("Callers should call scheduleResizePip() instead of this "
                     + "directly");
         }
         mLastReportedBounds.set(destinationBounds);
+        if (isInPipDirection(direction) && type == ANIM_TYPE_ALPHA) {
+            return;
+        }
+
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         final Rect taskBounds;
-        if (isOutPipDirection(direction)) {
+        if (isInPipDirection(direction)) {
+            // If we are animating from fullscreen using a bounds animation, then reset the
+            // activity windowing mode set by WM, and set the task bounds to the final bounds
+            taskBounds = destinationBounds;
+            wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
+            wct.scheduleFinishEnterPip(mToken, destinationBounds);
+        } else if (isOutPipDirection(direction)) {
             // If we are animating to fullscreen, then we need to reset the override bounds
             // on the task to ensure that the task "matches" the parent's bounds.
             taskBounds = (direction == TRANSITION_DIRECTION_TO_FULLSCREEN)
                     ? null : destinationBounds;
-            // As for the final windowing mode, simply reset it to undefined.
+            // As for the final windowing mode, simply reset it to undefined and reset the activity
+            // mode set prior to the animation running
             wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
+            wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
             if (mSplitDivider != null && direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN) {
                 wct.reparent(mToken, mSplitDivider.getSecondaryRoot(), true /* onTop */);
             }
         } else {
+            // Just a resize in PIP
             taskBounds = destinationBounds;
         }
-        if (direction == TRANSITION_DIRECTION_TO_PIP) {
-            wct.scheduleFinishEnterPip(mToken, taskBounds);
-        } else {
-            wct.setBounds(mToken, taskBounds);
-        }
+
+        wct.setBounds(mToken, taskBounds);
         wct.setBoundsChangeTransaction(mToken, tx);
         WindowOrganizer.applyTransaction(wct);
     }
@@ -573,17 +661,17 @@
             throw new RuntimeException("Callers should call scheduleAnimateResizePip() instead of "
                     + "this directly");
         }
-        // Could happen when dismissPip
+        // Could happen when exitPip
         if (mToken == null || mLeash == null) {
             Log.w(TAG, "Abort animation, invalid leash");
             return;
         }
-        mUpdateHandler.post(() -> mPipAnimationController
+        mPipAnimationController
                 .getAnimator(mLeash, currentBounds, destinationBounds)
                 .setTransitionDirection(direction)
                 .setPipAnimationCallback(mPipAnimationCallback)
                 .setDuration(durationMs)
-                .start());
+                .start();
     }
 
     private Size getMinimalSize(ActivityInfo activityInfo) {
@@ -624,6 +712,27 @@
     }
 
     /**
+     * Dumps internal states.
+     */
+    public void dump(PrintWriter pw, String prefix) {
+        final String innerPrefix = prefix + "  ";
+        pw.println(prefix + TAG);
+        pw.println(innerPrefix + "mTaskInfo=" + mTaskInfo);
+        pw.println(innerPrefix + "mToken=" + mToken
+                + " binder=" + (mToken != null ? mToken.asBinder() : null));
+        pw.println(innerPrefix + "mLeash=" + mLeash);
+        pw.println(innerPrefix + "mInPip=" + mInPip);
+        pw.println(innerPrefix + "mOneShotAnimationType=" + mOneShotAnimationType);
+        pw.println(innerPrefix + "mPictureInPictureParams=" + mPictureInPictureParams);
+        pw.println(innerPrefix + "mLastReportedBounds=" + mLastReportedBounds);
+        pw.println(innerPrefix + "mInitialState:");
+        for (Map.Entry<IBinder, Configuration> e : mInitialState.entrySet()) {
+            pw.println(innerPrefix + "  binder=" + e.getKey()
+                    + " winConfig=" + e.getValue().windowConfiguration);
+        }
+    }
+
+    /**
      * Callback interface for PiP transitions (both from and to PiP mode)
      */
     public interface PipTransitionCallback {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
index 84f7e89..f1eef43 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
@@ -101,7 +101,7 @@
                     result = true;
                     break;
                 case AccessibilityNodeInfo.ACTION_EXPAND:
-                    mMotionHelper.expandPip();
+                    mMotionHelper.expandPipToFullscreen();
                     result = true;
                     break;
                 default:
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 0841bb7..30d6cd9 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -25,7 +25,6 @@
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.app.IActivityManager;
-import android.app.IActivityTaskManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
@@ -140,7 +139,7 @@
                     != WINDOWING_MODE_PINNED) {
                 return;
             }
-            mTouchHandler.getMotionHelper().expandPip(clearedTask /* skipAnimation */);
+            mTouchHandler.getMotionHelper().expandPipToFullscreen(clearedTask /* skipAnimation */);
         }
     };
 
@@ -214,7 +213,6 @@
         }
         ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
 
-        final IActivityTaskManager activityTaskManager = ActivityTaskManager.getService();
         mPipBoundsHandler = pipBoundsHandler;
         mPipTaskOrganizer = pipTaskOrganizer;
         mPipTaskOrganizer.registerPipTransitionCallback(this);
@@ -222,7 +220,7 @@
         mMediaController = new PipMediaController(context, mActivityManager, broadcastDispatcher);
         mMenuController = new PipMenuActivityController(context, mMediaController,
                 mInputConsumerController);
-        mTouchHandler = new PipTouchHandler(context, mActivityManager, activityTaskManager,
+        mTouchHandler = new PipTouchHandler(context, mActivityManager,
                 mMenuController, mInputConsumerController, mPipBoundsHandler, mPipTaskOrganizer,
                 floatingContentCoordinator, deviceConfig, pipSnapAlgorithm);
         mAppOpsListener = new PipAppOpsListener(context, mActivityManager,
@@ -237,7 +235,7 @@
 
         try {
             mPipTaskOrganizer.registerOrganizer(WINDOWING_MODE_PINNED);
-            ActivityManager.StackInfo stackInfo = activityTaskManager.getStackInfo(
+            ActivityManager.StackInfo stackInfo = ActivityTaskManager.getService().getStackInfo(
                     WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
             if (stackInfo != null) {
                 // If SystemUI restart, and it already existed a pinned stack,
@@ -261,7 +259,7 @@
      */
     @Override
     public void expandPip() {
-        mTouchHandler.getMotionHelper().expandPip(false /* skipAnimation */);
+        mTouchHandler.getMotionHelper().expandPipToFullscreen(false /* skipAnimation */);
     }
 
     /**
@@ -378,5 +376,6 @@
         mMenuController.dump(pw, innerPrefix);
         mTouchHandler.dump(pw, innerPrefix);
         mPipBoundsHandler.dump(pw, innerPrefix);
+        mPipTaskOrganizer.dump(pw, innerPrefix);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index 08d4222..d099597 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -16,16 +16,12 @@
 
 package com.android.systemui.pip.phone;
 
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.IActivityTaskManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.Debug;
-import android.os.RemoteException;
 import android.util.Log;
 
 import androidx.dynamicanimation.animation.SpringForce;
@@ -33,7 +29,6 @@
 import com.android.systemui.pip.PipSnapAlgorithm;
 import com.android.systemui.pip.PipTaskOrganizer;
 import com.android.systemui.shared.system.WindowManagerWrapper;
-import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.util.FloatingContentCoordinator;
 import com.android.systemui.util.animation.FloatProperties;
 import com.android.systemui.util.animation.PhysicsAnimator;
@@ -60,12 +55,10 @@
     private static final float DEFAULT_FRICTION = 2f;
 
     private final Context mContext;
-    private final IActivityTaskManager mActivityTaskManager;
     private final PipTaskOrganizer mPipTaskOrganizer;
 
     private PipMenuActivityController mMenuController;
     private PipSnapAlgorithm mSnapAlgorithm;
-    private FlingAnimationUtils mFlingAnimationUtils;
 
     private final Rect mStableInsets = new Rect();
 
@@ -147,16 +140,13 @@
         public void onPipTransitionCanceled(ComponentName activity, int direction) {}
     };
 
-    public PipMotionHelper(Context context, IActivityTaskManager activityTaskManager,
-            PipTaskOrganizer pipTaskOrganizer, PipMenuActivityController menuController,
-            PipSnapAlgorithm snapAlgorithm, FlingAnimationUtils flingAnimationUtils,
+    public PipMotionHelper(Context context, PipTaskOrganizer pipTaskOrganizer,
+            PipMenuActivityController menuController, PipSnapAlgorithm snapAlgorithm,
             FloatingContentCoordinator floatingContentCoordinator) {
         mContext = context;
-        mActivityTaskManager = activityTaskManager;
         mPipTaskOrganizer = pipTaskOrganizer;
         mMenuController = menuController;
         mSnapAlgorithm = snapAlgorithm;
-        mFlingAnimationUtils = flingAnimationUtils;
         mFloatingContentCoordinator = floatingContentCoordinator;
         onConfigurationChanged();
         mPipTaskOrganizer.registerPipTransitionCallback(mPipTransitionCallback);
@@ -267,22 +257,24 @@
     /**
      * Resizes the pinned stack back to fullscreen.
      */
-    void expandPip() {
-        expandPip(false /* skipAnimation */);
+    void expandPipToFullscreen() {
+        expandPipToFullscreen(false /* skipAnimation */);
     }
 
     /**
      * Resizes the pinned stack back to fullscreen.
      */
-    void expandPip(boolean skipAnimation) {
+    void expandPipToFullscreen(boolean skipAnimation) {
         if (DEBUG) {
-            Log.d(TAG, "expandPip: skipAnimation=" + skipAnimation
+            Log.d(TAG, "exitPip: skipAnimation=" + skipAnimation
                     + " callers=\n" + Debug.getCallers(5, "    "));
         }
         cancelAnimations();
         mMenuController.hideMenuWithoutResize();
         mPipTaskOrganizer.getUpdateHandler().post(() -> {
-            mPipTaskOrganizer.dismissPip(skipAnimation ? 0 : EXPAND_STACK_TO_FULLSCREEN_DURATION);
+            mPipTaskOrganizer.exitPip(skipAnimation
+                    ? 0
+                    : EXPAND_STACK_TO_FULLSCREEN_DURATION);
         });
     }
 
@@ -292,18 +284,11 @@
     @Override
     public void dismissPip() {
         if (DEBUG) {
-            Log.d(TAG, "dismissPip: callers=\n" + Debug.getCallers(5, "    "));
+            Log.d(TAG, "removePip: callers=\n" + Debug.getCallers(5, "    "));
         }
         cancelAnimations();
         mMenuController.hideMenuWithoutResize();
-        mPipTaskOrganizer.getUpdateHandler().post(() -> {
-            try {
-                mActivityTaskManager.removeStacksInWindowingModes(
-                        new int[]{ WINDOWING_MODE_PINNED });
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to remove PiP", e);
-            }
-        });
+        mPipTaskOrganizer.removePip();
     }
 
     /** Sets the movement bounds to use to constrain PIP position animations. */
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index b70fb3f..ca73a6c 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -23,7 +23,6 @@
 
 import android.annotation.SuppressLint;
 import android.app.IActivityManager;
-import android.app.IActivityTaskManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Resources;
@@ -188,7 +187,7 @@
 
         @Override
         public void onPipExpand() {
-            mMotionHelper.expandPip();
+            mMotionHelper.expandPipToFullscreen();
         }
 
         @Override
@@ -210,7 +209,7 @@
 
     @SuppressLint("InflateParams")
     public PipTouchHandler(Context context, IActivityManager activityManager,
-            IActivityTaskManager activityTaskManager, PipMenuActivityController menuController,
+            PipMenuActivityController menuController,
             InputConsumerController inputConsumerController,
             PipBoundsHandler pipBoundsHandler,
             PipTaskOrganizer pipTaskOrganizer,
@@ -228,8 +227,8 @@
         mFlingAnimationUtils = new FlingAnimationUtils(context.getResources().getDisplayMetrics(),
                 2.5f);
         mGesture = new DefaultPipTouchGesture();
-        mMotionHelper = new PipMotionHelper(mContext, activityTaskManager, pipTaskOrganizer,
-                mMenuController, mSnapAlgorithm, mFlingAnimationUtils, floatingContentCoordinator);
+        mMotionHelper = new PipMotionHelper(mContext, pipTaskOrganizer, mMenuController,
+                mSnapAlgorithm, floatingContentCoordinator);
         mPipResizeGestureHandler =
                 new PipResizeGestureHandler(context, pipBoundsHandler, mMotionHelper,
                         deviceConfig, pipTaskOrganizer);
@@ -905,7 +904,7 @@
                 // Expand to fullscreen if this is a double tap
                 // the PiP should be frozen until the transition ends
                 setTouchEnabled(false);
-                mMotionHelper.expandPip();
+                mMotionHelper.expandPipToFullscreen();
             } else if (mMenuState != MENU_STATE_FULL) {
                 if (!mTouchState.isWaitingForDoubleTap()) {
                     // User has stalled long enough for this not to be a drag or a double tap, just
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index f49732d..6282236 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -468,7 +468,7 @@
             mPipTaskOrganizer.scheduleAnimateResizePip(mCurrentPipBounds, mResizeAnimationDuration,
                     null);
         } else {
-            mPipTaskOrganizer.dismissPip(mResizeAnimationDuration);
+            mPipTaskOrganizer.exitPip(mResizeAnimationDuration);
         }
     }