Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 433c5eae authored by Evan Rosky's avatar Evan Rosky
Browse files

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
parent cde55d30
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -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) {
+11 −0
Original line number Diff line number Diff line
@@ -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)
     */
+3 −0
Original line number Diff line number Diff line
@@ -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
+9 −1
Original line number Diff line number Diff line
@@ -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.