diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java index 330b20edf985f..a7dd53e48a817 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 @@ public class PipTaskOrganizer extends TaskOrganizer implements 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 @@ public class PipTaskOrganizer extends TaskOrganizer implements 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 @@ public class PipTaskOrganizer extends TaskOrganizer implements 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 @@ public class PipTaskOrganizer extends TaskOrganizer implements 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 @@ public class PipTaskOrganizer extends TaskOrganizer implements }); } + 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 @@ public class PipTaskOrganizer extends TaskOrganizer implements */ @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 @@ public class PipTaskOrganizer extends TaskOrganizer implements * {@link #scheduleResizePip}. */ public void scheduleFinishResizePip(Rect destinationBounds) { - scheduleFinishResizePip(destinationBounds, null); + scheduleFinishResizePip(destinationBounds, null /* updateBoundsCallback */); } /** @@ -630,30 +662,36 @@ public class PipTaskOrganizer extends TaskOrganizer implements */ public void scheduleFinishResizePip(Rect destinationBounds, Consumer 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 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 @@ public class PipTaskOrganizer extends TaskOrganizer implements 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 @@ public class PipTaskOrganizer extends TaskOrganizer implements 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 7a18ec3618609..1fbe58d28d394 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.Log; 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 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio */ 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 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio } updateMovementBounds(mTmpNormalBounds, true /* fromRotation */, - false /* fromImeAdjustment */, false /* fromShelfAdjustment */); + false /* fromImeAdjustment */, false /* fromShelfAdjustment */, t); } }; @@ -194,7 +198,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio @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 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio mTouchHandler.onShelfVisibilityChanged(visible, shelfHeight); updateMovementBounds(mPipTaskOrganizer.getLastReportedBounds(), false /* fromRotation */, false /* fromImeAdjustment */, - true /* fromShelfAdjustment */); + true /* fromShelfAdjustment */, null /* windowContainerTransaction */); } }); } @@ -387,15 +392,16 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio } 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);