diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java index e5a755c35add6..48df28ee4cdea 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java @@ -89,6 +89,8 @@ public class PipTransition extends PipTransitionController { private final Rect mExitDestinationBounds = new Rect(); @Nullable private IBinder mExitTransition; + private IBinder mRequestedEnterTransition; + private WindowContainerToken mRequestedEnterTask; /** The Task window that is currently in PIP windowing mode. */ @Nullable private WindowContainerToken mCurrentPipTaskToken; @@ -201,6 +203,9 @@ public class PipTransition extends PipTransitionController { } mCurrentPipTaskToken = null; return true; + } else if (transition == mRequestedEnterTransition) { + mRequestedEnterTransition = null; + mRequestedEnterTask = null; } // The previous PIP Task is no longer in PIP, but this is not an exit transition (This can @@ -243,6 +248,8 @@ public class PipTransition extends PipTransitionController { if (request.getType() == TRANSIT_PIP) { WindowContainerTransaction wct = new WindowContainerTransaction(); if (mOneShotAnimationType == ANIM_TYPE_ALPHA) { + mRequestedEnterTransition = transition; + mRequestedEnterTask = request.getTriggerTask().token; wct.setActivityWindowingMode(request.getTriggerTask().token, WINDOWING_MODE_UNDEFINED); final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds(); @@ -254,6 +261,23 @@ public class PipTransition extends PipTransitionController { } } + @Override + public boolean handleRotateDisplay(int startRotation, int endRotation, + WindowContainerTransaction wct) { + if (mRequestedEnterTransition != null && mOneShotAnimationType == ANIM_TYPE_ALPHA) { + // A fade-in was requested but not-yet started. In this case, just recalculate the + // initial state under the new rotation. + int rotationDelta = deltaRotation(startRotation, endRotation); + if (rotationDelta != Surface.ROTATION_0) { + mPipBoundsState.getDisplayLayout().rotateTo(mContext.getResources(), endRotation); + final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds(); + wct.setBounds(mRequestedEnterTask, destinationBounds); + return true; + } + } + return false; + } + @Override public void onTransitionMerged(@NonNull IBinder transition) { if (transition != mExitTransition) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java index 02e713d2eaa36..24993c621e3c1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java @@ -195,6 +195,17 @@ public abstract class PipTransitionController implements Transitions.TransitionH mPipBoundsAlgorithm); } + /** + * Called when the display is going to rotate. + * + * @return {@code true} if it was handled, otherwise the existing pip logic + * will deal with rotation. + */ + public boolean handleRotateDisplay(int startRotation, int endRotation, + WindowContainerTransaction wct) { + return false; + } + /** * Callback interface for PiP transitions (both from and to PiP mode) */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index e86ebaaabbfe3..ba522c072f11f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java @@ -143,6 +143,9 @@ public class PipController implements PipTransitionController.PipTransitionCallb */ private final DisplayChangeController.OnDisplayChangingListener mRotationController = ( int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) -> { + if (mPipTransitionController.handleRotateDisplay(fromRotation, toRotation, t)) { + return; + } if (mPipBoundsState.getDisplayLayout().rotation() == toRotation) { // The same rotation may have been set by auto PiP-able or fixed rotation. So notify // the change with fromRotation=false to apply the rotated destination bounds from diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 21ca4bb6038bf..557ca4c978388 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -520,7 +520,6 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe // Legacy dispatch relies on this (for now). ar.mEnteringAnimation = visibleAtTransitionEnd; } - mController.dispatchLegacyAppTransitionFinished(ar); } final WallpaperWindowToken wt = mParticipants.valueAt(i).asWallpaperToken(); if (wt != null) { @@ -532,6 +531,15 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe } } } + // dispatch legacy callback in a different loop. This is because multiple legacy handlers + // (fixed-rotation/displaycontent) make global changes, so we want to ensure that we've + // processed all the participants first (in particular, we want to trigger pip-enter first) + for (int i = 0; i < mParticipants.size(); ++i) { + final ActivityRecord ar = mParticipants.valueAt(i).asActivityRecord(); + if (ar != null) { + mController.dispatchLegacyAppTransitionFinished(ar); + } + } if (activitiesWentInvisible) { // Always schedule stop processing when transition finishes because activities don't // stop while they are in a transition thus their stop could still be pending.