Merge "Updating rotation transaction behaviour" into rvc-dev
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index 330b20e..a7dd53e4 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -224,6 +224,16 @@
         return new Rect(mLastReportedBounds);
     }
 
+    public Rect getCurrentOrAnimatingBounds() {
+        PipAnimationController.PipTransitionAnimator animator =
+                mPipAnimationController.getCurrentAnimator();
+        if (animator != null && animator.isRunning()) {
+            System.out.println("RUNNING ANIM: anim=" + animator.getDestinationBounds() + " last=" + getLastReportedBounds());
+            return new Rect(animator.getDestinationBounds());
+        }
+        return getLastReportedBounds();
+    }
+
     public boolean isInPip() {
         return mInPip;
     }
@@ -406,7 +416,7 @@
 
     private void sendOnPipTransitionStarted(
             @PipAnimationController.TransitionDirection int direction) {
-        mMainHandler.post(() -> {
+        runOnMainHandler(() -> {
             for (int i = mPipTransitionCallbacks.size() - 1; i >= 0; i--) {
                 final PipTransitionCallback callback = mPipTransitionCallbacks.get(i);
                 callback.onPipTransitionStarted(mTaskInfo.baseActivity, direction);
@@ -416,7 +426,7 @@
 
     private void sendOnPipTransitionFinished(
             @PipAnimationController.TransitionDirection int direction) {
-        mMainHandler.post(() -> {
+        runOnMainHandler(() -> {
             for (int i = mPipTransitionCallbacks.size() - 1; i >= 0; i--) {
                 final PipTransitionCallback callback = mPipTransitionCallbacks.get(i);
                 callback.onPipTransitionFinished(mTaskInfo.baseActivity, direction);
@@ -426,7 +436,7 @@
 
     private void sendOnPipTransitionCancelled(
             @PipAnimationController.TransitionDirection int direction) {
-        mMainHandler.post(() -> {
+        runOnMainHandler(() -> {
             for (int i = mPipTransitionCallbacks.size() - 1; i >= 0; i--) {
                 final PipTransitionCallback callback = mPipTransitionCallbacks.get(i);
                 callback.onPipTransitionCanceled(mTaskInfo.baseActivity, direction);
@@ -434,6 +444,14 @@
         });
     }
 
+    private void runOnMainHandler(Runnable r) {
+        if (Looper.getMainLooper() == Looper.myLooper()) {
+            r.run();
+        } else {
+            mMainHandler.post(r);
+        }
+    }
+
     /**
      * 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:
@@ -505,15 +523,29 @@
      */
     @SuppressWarnings("unchecked")
     public void onMovementBoundsChanged(Rect destinationBoundsOut, boolean fromRotation,
-            boolean fromImeAdjustment, boolean fromShelfAdjustment) {
+            boolean fromImeAdjustment, boolean fromShelfAdjustment,
+            WindowContainerTransaction wct) {
         final PipAnimationController.PipTransitionAnimator animator =
                 mPipAnimationController.getCurrentAnimator();
         if (animator == null || !animator.isRunning()
                 || animator.getTransitionDirection() != TRANSITION_DIRECTION_TO_PIP) {
             if (mInPip && fromRotation) {
-                // this could happen if rotation finishes before the animation
+                // If we are rotating while there is a current animation, immediately cancel the
+                // animation (remove the listeners so we don't trigger the normal finish resize
+                // call that should only happen on the update thread)
+                int direction = animator.getTransitionDirection();
+                animator.removeAllUpdateListeners();
+                animator.removeAllListeners();
+                animator.cancel();
+                // Do notify the listeners that this was canceled
+                sendOnPipTransitionCancelled(direction);
                 mLastReportedBounds.set(destinationBoundsOut);
-                scheduleFinishResizePip(mLastReportedBounds);
+
+                // Create a reset surface transaction for the new bounds and update the window
+                // container transaction
+                final SurfaceControl.Transaction tx = createFinishResizeSurfaceTransaction(
+                        destinationBoundsOut);
+                prepareFinishResizeTransaction(destinationBoundsOut, direction, tx, wct);
             } else  {
                 // There could be an animation on-going. If there is one on-going, last-reported
                 // bounds isn't yet updated. We'll use the animator's bounds instead.
@@ -622,7 +654,7 @@
      * {@link #scheduleResizePip}.
      */
     public void scheduleFinishResizePip(Rect destinationBounds) {
-        scheduleFinishResizePip(destinationBounds, null);
+        scheduleFinishResizePip(destinationBounds, null /* updateBoundsCallback */);
     }
 
     /**
@@ -630,30 +662,36 @@
      */
     public void scheduleFinishResizePip(Rect destinationBounds,
             Consumer<Rect> updateBoundsCallback) {
-        final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
-        mSurfaceTransactionHelper
-                .crop(tx, mLeash, destinationBounds)
-                .resetScale(tx, mLeash, destinationBounds)
-                .round(tx, mLeash, mInPip);
-        scheduleFinishResizePip(tx, destinationBounds, TRANSITION_DIRECTION_NONE,
-                updateBoundsCallback);
+        scheduleFinishResizePip(destinationBounds, TRANSITION_DIRECTION_NONE, updateBoundsCallback);
     }
 
-    private void scheduleFinishResizePip(SurfaceControl.Transaction tx,
-            Rect destinationBounds, @PipAnimationController.TransitionDirection int direction,
+    private void scheduleFinishResizePip(Rect destinationBounds,
+            @PipAnimationController.TransitionDirection int direction,
             Consumer<Rect> updateBoundsCallback) {
         if (!mInPip) {
             // can be initiated in other component, ignore if we are no longer in PIP
             return;
         }
+
         SomeArgs args = SomeArgs.obtain();
         args.arg1 = updateBoundsCallback;
-        args.arg2 = tx;
+        args.arg2 = createFinishResizeSurfaceTransaction(
+                destinationBounds);
         args.arg3 = destinationBounds;
         args.argi1 = direction;
         mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_FINISH_RESIZE, args));
     }
 
+    private SurfaceControl.Transaction createFinishResizeSurfaceTransaction(
+            Rect destinationBounds) {
+        final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
+        mSurfaceTransactionHelper
+                .crop(tx, mLeash, destinationBounds)
+                .resetScale(tx, mLeash, destinationBounds)
+                .round(tx, mLeash, mInPip);
+        return tx;
+    }
+
     /**
      * Offset the PiP window by a given offset on Y-axis, triggered also from screen rotation.
      */
@@ -741,7 +779,15 @@
             return;
         }
 
-        final WindowContainerTransaction wct = new WindowContainerTransaction();
+        WindowContainerTransaction wct = new WindowContainerTransaction();
+        prepareFinishResizeTransaction(destinationBounds, direction, tx, wct);
+        applyFinishBoundsResize(wct, direction);
+    }
+
+    private void prepareFinishResizeTransaction(Rect destinationBounds,
+            @PipAnimationController.TransitionDirection int direction,
+            SurfaceControl.Transaction tx,
+            WindowContainerTransaction wct) {
         final Rect taskBounds;
         if (isInPipDirection(direction)) {
             // If we are animating from fullscreen using a bounds animation, then reset the
@@ -762,7 +808,6 @@
 
         wct.setBounds(mToken, taskBounds);
         wct.setBoundsChangeTransaction(mToken, tx);
-        applyFinishBoundsResize(wct, direction);
     }
 
     /**
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 7a18ec3..1fbe58d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -36,6 +36,7 @@
 import android.util.Pair;
 import android.view.DisplayInfo;
 import android.view.IPinnedStackController;
+import android.view.SurfaceControl;
 import android.window.WindowContainerTransaction;
 
 import com.android.systemui.Dependency;
@@ -94,9 +95,12 @@
      */
     private final DisplayChangeController.OnDisplayChangingListener mRotationController = (
             int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) -> {
+        // If there is an animation running (ie. from a shelf offset), then ensure that we calculate
+        // the bounds for the next orientation using the destination bounds of the animation
+        // TODO: Techincally this should account for movement animation bounds as well
+        Rect currentBounds = mPipTaskOrganizer.getCurrentOrAnimatingBounds();
         final boolean changed = mPipBoundsHandler.onDisplayRotationChanged(mTmpNormalBounds,
-                mPipTaskOrganizer.getLastReportedBounds(), mTmpInsetBounds, displayId, fromRotation,
-                toRotation, t);
+                currentBounds, mTmpInsetBounds, displayId, fromRotation, toRotation, t);
         if (changed) {
             // If the pip was in the offset zone earlier, adjust the new bounds to the bottom of the
             // movement bounds
@@ -116,7 +120,7 @@
             }
 
             updateMovementBounds(mTmpNormalBounds, true /* fromRotation */,
-                    false /* fromImeAdjustment */, false /* fromShelfAdjustment */);
+                    false /* fromImeAdjustment */, false /* fromShelfAdjustment */, t);
         }
     };
 
@@ -194,7 +198,8 @@
         @Override
         public void onMovementBoundsChanged(boolean fromImeAdjustment) {
             mHandler.post(() -> updateMovementBounds(null /* toBounds */,
-                    false /* fromRotation */, fromImeAdjustment, false /* fromShelfAdjustment */));
+                    false /* fromRotation */, fromImeAdjustment, false /* fromShelfAdjustment */,
+                    null /* windowContainerTransaction */));
         }
 
         @Override
@@ -327,7 +332,7 @@
                 mTouchHandler.onShelfVisibilityChanged(visible, shelfHeight);
                 updateMovementBounds(mPipTaskOrganizer.getLastReportedBounds(),
                         false /* fromRotation */, false /* fromImeAdjustment */,
-                        true /* fromShelfAdjustment */);
+                        true /* fromShelfAdjustment */, null /* windowContainerTransaction */);
             }
         });
     }
@@ -387,15 +392,16 @@
     }
 
     private void updateMovementBounds(@Nullable Rect toBounds, boolean fromRotation,
-            boolean fromImeAdjustment, boolean fromShelfAdjustment) {
+            boolean fromImeAdjustment, boolean fromShelfAdjustment,
+            WindowContainerTransaction wct) {
         // Populate inset / normal bounds and DisplayInfo from mPipBoundsHandler before
         // passing to mTouchHandler/mPipTaskOrganizer
         final Rect outBounds = new Rect(toBounds);
         mPipBoundsHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds,
                 outBounds, mTmpDisplayInfo);
         // mTouchHandler would rely on the bounds populated from mPipTaskOrganizer
-        mPipTaskOrganizer.onMovementBoundsChanged(outBounds, fromRotation,
-                fromImeAdjustment, fromShelfAdjustment);
+        mPipTaskOrganizer.onMovementBoundsChanged(outBounds, fromRotation, fromImeAdjustment,
+                fromShelfAdjustment, wct);
         mTouchHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds,
                 outBounds, fromImeAdjustment, fromShelfAdjustment,
                 mTmpDisplayInfo.rotation);