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

Commit 72b04b7d authored by Winson Chung's avatar Winson Chung
Browse files

Updating rotation transaction behaviour

- Ensure we use the final animation bounds to calculate the bounds in
  the new orientation if there is an animation running
- If there is an transition animation running during rotation, we need
  to cancel the animation and not schedule any WCT updates separate from
  the transaction passed to the display change listener.  For this
  transaction, we specify the bounds change + a surface transaction for
  the new bounds in the next orientation.

Bug: 159397143
Test: atest PinnedStackTests
Test: Enter pip in portrait, hold the phone in landscape physically and
      launch apps + go home repeatedly

Change-Id: Ib473654bd0e55492b2bc803faea6825db440bf13
parent 0cef70e5
Loading
Loading
Loading
Loading
+64 −19
Original line number Diff line number Diff line
@@ -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<Rect> 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<Rect> 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);
    }

    /**
+14 −8
Original line number Diff line number Diff line
@@ -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);