From 433c5eae073416d7b30536b0335f91018443985c Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Fri, 18 Mar 2022 15:33:36 -0700 Subject: [PATCH] Sync PiP WM bounds to rotation immediately for fade-in When pip is fading-in, it should be reconfigured at the start of the animation. This means that if the display rotates, we want to immediately update the pip bounds to match otherwise the window content will be relayout-ed in the wrong place on screen -- usually resulting in unwanted insets. In this case, keep track of when we are expecting to start a fade-in and, in that situation, recalculate the bounds. Additionally, fix a non-deterministic ordering situation where some legacy per-activity callbacks would make global changes. This meant that the order of activities in mParticipants could effect which transition was actually requested. This CL moves all the legacy callbacks after the other per-activity logic in finishTransition. Bug: 222033492 Test: Open landscape auto-pip app. Open recents, tap on edge watch pip fade-in without content-flicker Change-Id: Iea3dc3ac4ddda02e1b464baedd11fb1cc9cbe930 --- .../android/wm/shell/pip/PipTransition.java | 24 +++++++++++++++++++ .../wm/shell/pip/PipTransitionController.java | 11 +++++++++ .../wm/shell/pip/phone/PipController.java | 3 +++ .../com/android/server/wm/Transition.java | 10 +++++++- 4 files changed, 47 insertions(+), 1 deletion(-) 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 be713a59a816e..f3af9594dcbd2 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; @@ -202,6 +204,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 @@ -239,6 +244,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(); @@ -250,6 +257,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 e7a1c4cca07e8..f13153ac90ce0 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.