diff options
| author | 2022-03-18 15:33:36 -0700 | |
|---|---|---|
| committer | 2022-03-18 15:33:36 -0700 | |
| commit | 433c5eae073416d7b30536b0335f91018443985c (patch) | |
| tree | 3252a6d2a73b95654ac2b0d2c823c8698a020bc6 | |
| parent | cde55d305f5b7d43f5b026812ba0b149bac6d5cf (diff) | |
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
4 files changed, 47 insertions, 1 deletions
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 be713a59a816..f3af9594dcbd 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(); @@ -251,6 +258,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) { return; 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 02e713d2eaa3..24993c621e3c 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 @@ -196,6 +196,17 @@ public abstract class PipTransitionController implements Transitions.TransitionH } /** + * 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) */ public interface PipTransitionCallback { 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 e7a1c4cca07e..f13153ac90ce 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 21ca4bb6038b..557ca4c97838 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. |