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

Commit 16e51ba1 authored by Riddle Hsu's avatar Riddle Hsu Committed by Android (Google) Code Review
Browse files

Merge "Polish entering pip from fullscreen with shell transition" into udc-dev

parents d38421d0 c59a137d
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ import java.util.Objects;
 */
public class PipAnimationController {
    static final float FRACTION_START = 0f;
    private static final float FRACTION_END = 1f;
    static final float FRACTION_END = 1f;

    public static final int ANIM_TYPE_BOUNDS = 0;
    public static final int ANIM_TYPE_ALPHA = 1;
@@ -718,8 +718,10 @@ public class PipAnimationController {
                                .round(tx, leash, sourceBounds, bounds)
                                .shadow(tx, leash, shouldApplyShadowRadius());
                    }
                    if (!handlePipTransaction(leash, tx, bounds, 1f /* alpha */)) {
                        tx.apply();
                    }
                }

                private Rect computeInsets(float fraction) {
                    if (sourceHintRectInsets == null) {
+1 −0
Original line number Diff line number Diff line
@@ -828,6 +828,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,

    private void onEndOfSwipePipToHomeTransition() {
        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
            mPipTransitionController.setEnterAnimationType(ANIM_TYPE_BOUNDS);
            return;
        }

+92 −48
Original line number Diff line number Diff line
@@ -45,7 +45,6 @@ import android.animation.Animator;
import android.app.ActivityManager;
import android.app.TaskInfo;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.IBinder;
@@ -109,6 +108,17 @@ public class PipTransition extends PipTransitionController {
    /** Whether the PIP window has fade out for fixed rotation. */
    private boolean mHasFadeOut;

    /** Used for setting transform to a transaction from animator. */
    private final PipAnimationController.PipTransactionHandler mTransactionConsumer =
            new PipAnimationController.PipTransactionHandler() {
                @Override
                public boolean handlePipTransaction(SurfaceControl leash,
                        SurfaceControl.Transaction tx, Rect destinationBounds, float alpha) {
                    // Only set the operation to transaction but do not apply.
                    return true;
                }
            };

    public PipTransition(Context context,
            @NonNull ShellInit shellInit,
            @NonNull ShellTaskOrganizer shellTaskOrganizer,
@@ -338,7 +348,7 @@ public class PipTransition extends PipTransitionController {
    @Override
    public void onFinishResize(TaskInfo taskInfo, Rect destinationBounds,
            @PipAnimationController.TransitionDirection int direction,
            @Nullable SurfaceControl.Transaction tx) {
            @NonNull SurfaceControl.Transaction tx) {
        final boolean enteringPip = isInPipDirection(direction);
        if (enteringPip) {
            mPipTransitionState.setTransitionState(ENTERED_PIP);
@@ -348,13 +358,15 @@ public class PipTransition extends PipTransitionController {
        // (likely a remote like launcher), so don't fire the finish-callback here -- wait until
        // the exit transition is merged.
        if ((mExitTransition == null || isAnimatingLocally()) && mFinishCallback != null) {
            final SurfaceControl leash = mPipOrganizer.getSurfaceControl();
            final boolean hasValidLeash = leash != null && leash.isValid();
            WindowContainerTransaction wct = null;
            if (isOutPipDirection(direction)) {
                // Only need to reset surface properties. The server-side operations were already
                // done at the start. But if it is running fixed rotation, there will be a seamless
                // display transition later. So the last rotation transform needs to be kept to
                // avoid flickering, and then the display transition will reset the transform.
                if (tx != null && !mInFixedRotation) {
                if (!mInFixedRotation && mFinishTransaction != null) {
                    mFinishTransaction.merge(tx);
                }
            } else {
@@ -363,28 +375,37 @@ public class PipTransition extends PipTransitionController {
                    // If we are animating from fullscreen using a bounds animation, then reset the
                    // activity windowing mode, and set the task bounds to the final bounds
                    wct.setActivityWindowingMode(taskInfo.token, WINDOWING_MODE_UNDEFINED);
                    wct.scheduleFinishEnterPip(taskInfo.token, destinationBounds);
                    wct.setBounds(taskInfo.token, destinationBounds);
                } else {
                    wct.setBounds(taskInfo.token, null /* bounds */);
                }
                if (tx != null) {
                    wct.setBoundsChangeTransaction(taskInfo.token, tx);
                // Reset the scale with bounds change synchronously.
                if (hasValidLeash) {
                    mSurfaceTransactionHelper.crop(tx, leash, destinationBounds)
                            .resetScale(tx, leash, destinationBounds)
                            .round(tx, leash, true /* applyCornerRadius */);
                }
                wct.setBoundsChangeTransaction(taskInfo.token, tx);
            }
            final SurfaceControl leash = mPipOrganizer.getSurfaceControl();
            final int displayRotation = taskInfo.getConfiguration().windowConfiguration
                    .getDisplayRotation();
            if (enteringPip && mInFixedRotation && mEndFixedRotation != displayRotation
                    && leash != null && leash.isValid()) {
                    && hasValidLeash) {
                // Launcher may update the Shelf height during the animation, which will update the
                // destination bounds. Because this is in fixed rotation, We need to make sure the
                // finishTransaction is using the updated bounds in the display rotation.
                final PipAnimationController.PipTransitionAnimator<?> animator =
                        mPipAnimationController.getCurrentAnimator();
                final Rect displayBounds = mPipDisplayLayoutState.getDisplayBounds();
                final Rect finishBounds = new Rect(destinationBounds);
                rotateBounds(finishBounds, displayBounds, mEndFixedRotation, displayRotation);
                if (!finishBounds.equals(animator.getEndValue())) {
                    ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                            "%s: Destination bounds were changed during animation", TAG);
                    rotateBounds(finishBounds, displayBounds, mEndFixedRotation, displayRotation);
                    mSurfaceTransactionHelper.crop(mFinishTransaction, leash, finishBounds);
                }
            }
            mFinishTransaction = null;
            callFinishCallback(wct);
        }
@@ -665,9 +686,11 @@ public class PipTransition extends PipTransitionController {
    private void startExpandAnimation(final TaskInfo taskInfo, final SurfaceControl leash,
            final Rect baseBounds, final Rect startBounds, final Rect endBounds,
            final int rotationDelta) {
        final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect(
                taskInfo.pictureInPictureParams, endBounds);
        final PipAnimationController.PipTransitionAnimator animator =
                mPipAnimationController.getAnimator(taskInfo, leash, baseBounds, startBounds,
                        endBounds, null /* sourceHintRect */, TRANSITION_DIRECTION_LEAVE_PIP,
                        endBounds, sourceHintRect, TRANSITION_DIRECTION_LEAVE_PIP,
                        0 /* startingAngle */, rotationDelta);
        animator.setTransitionDirection(TRANSITION_DIRECTION_LEAVE_PIP)
                .setPipAnimationCallback(mPipAnimationCallback)
@@ -800,10 +823,6 @@ public class PipTransition extends PipTransitionController {
            computeEnterPipRotatedBounds(rotationDelta, startRotation, endRotation, taskInfo,
                    destinationBounds, sourceHintRect);
        }
        // Set corner radius for entering pip.
        mSurfaceTransactionHelper
                .crop(finishTransaction, leash, destinationBounds)
                .round(finishTransaction, leash, true /* applyCornerRadius */);
        if (!mPipOrganizer.shouldAttachMenuEarly()) {
            mTransitions.getMainExecutor().executeDelayed(
                    () -> mPipMenuController.attach(leash), 0);
@@ -812,41 +831,11 @@ public class PipTransition extends PipTransitionController {
        if (taskInfo.pictureInPictureParams != null
                && taskInfo.pictureInPictureParams.isAutoEnterEnabled()
                && mPipTransitionState.getInSwipePipToHomeTransition()) {
            final SurfaceControl swipePipToHomeOverlay = mPipOrganizer.mSwipePipToHomeOverlay;
            startTransaction.setMatrix(leash, Matrix.IDENTITY_MATRIX, new float[9])
                    .setPosition(leash, destinationBounds.left, destinationBounds.top)
                    .setWindowCrop(leash, destinationBounds.width(), destinationBounds.height());
            if (swipePipToHomeOverlay != null) {
                // Launcher fade in the overlay on top of the fullscreen Task. It is possible we
                // reparent the PIP activity to a new PIP task (in case there are other activities
                // in the original Task), so we should also reparent the overlay to the PIP task.
                startTransaction.reparent(swipePipToHomeOverlay, leash)
                        .setLayer(swipePipToHomeOverlay, Integer.MAX_VALUE);
                mPipOrganizer.mSwipePipToHomeOverlay = null;
            }
            startTransaction.apply();
            if (rotationDelta != Surface.ROTATION_0 && mInFixedRotation) {
                // For fixed rotation, set the destination bounds to the new rotation coordinates
                // at the end.
                destinationBounds.set(mPipBoundsAlgorithm.getEntryDestinationBounds());
            }
            mPipBoundsState.setBounds(destinationBounds);
            onFinishResize(taskInfo, destinationBounds, TRANSITION_DIRECTION_TO_PIP, null /* tx */);
            sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
            if (swipePipToHomeOverlay != null) {
                mPipOrganizer.fadeOutAndRemoveOverlay(swipePipToHomeOverlay,
                        null /* callback */, false /* withStartDelay */);
            }
            mPipTransitionState.setInSwipePipToHomeTransition(false);
            handleSwipePipToHomeTransition(startTransaction, finishTransaction, leash,
                    sourceHintRect, destinationBounds, rotationDelta, taskInfo);
            return;
        }

        if (rotationDelta != Surface.ROTATION_0) {
            Matrix tmpTransform = new Matrix();
            tmpTransform.postRotate(rotationDelta);
            startTransaction.setMatrix(leash, tmpTransform, new float[9]);
        }

        final int enterAnimationType = mEnterAnimationType;
        if (enterAnimationType == ANIM_TYPE_ALPHA) {
            startTransaction.setAlpha(leash, 0f);
@@ -880,11 +869,13 @@ public class PipTransition extends PipTransitionController {
        } else if (enterAnimationType == ANIM_TYPE_ALPHA) {
            animator = mPipAnimationController.getAnimator(taskInfo, leash, destinationBounds,
                    0f, 1f);
            mSurfaceTransactionHelper
                    .crop(finishTransaction, leash, destinationBounds)
                    .round(finishTransaction, leash, true /* applyCornerRadius */);
        } else {
            throw new RuntimeException("Unrecognized animation type: " + enterAnimationType);
        }
        animator.setTransitionDirection(TRANSITION_DIRECTION_TO_PIP)
                .setPipTransactionHandler(mPipOrganizer.getPipTransactionHandler())
                .setPipAnimationCallback(mPipAnimationCallback)
                .setDuration(mEnterExitAnimationDuration);
        if (rotationDelta != Surface.ROTATION_0 && mInFixedRotation) {
@@ -893,7 +884,15 @@ public class PipTransition extends PipTransitionController {
            // ComputeRotatedBounds has changed the DisplayLayout without affecting the animation.
            animator.setDestinationBounds(mPipBoundsAlgorithm.getEntryDestinationBounds());
        }
        animator.start();
        // Keep the last appearance when finishing the transition. The transform will be reset when
        // setting bounds.
        animator.setPipTransactionHandler(mTransactionConsumer).applySurfaceControlTransaction(
                leash, finishTransaction, PipAnimationController.FRACTION_END);
        // Remove the workaround after fixing ClosePipBySwipingDownTest that detects the shadow
        // as unexpected visible.
        finishTransaction.setShadowRadius(leash, 0);
        // Start to animate enter PiP.
        animator.setPipTransactionHandler(mPipOrganizer.getPipTransactionHandler()).start();
    }

    /** Computes destination bounds in old rotation and updates source hint rect if available. */
@@ -915,6 +914,51 @@ public class PipTransition extends PipTransitionController {
        }
    }

    private void handleSwipePipToHomeTransition(
            @NonNull SurfaceControl.Transaction startTransaction,
            @NonNull SurfaceControl.Transaction finishTransaction,
            @NonNull SurfaceControl leash, @Nullable Rect sourceHintRect,
            @NonNull Rect destinationBounds, int rotationDelta,
            @NonNull ActivityManager.RunningTaskInfo pipTaskInfo) {
        final SurfaceControl swipePipToHomeOverlay = mPipOrganizer.mSwipePipToHomeOverlay;
        if (swipePipToHomeOverlay != null) {
            // Launcher fade in the overlay on top of the fullscreen Task. It is possible we
            // reparent the PIP activity to a new PIP task (in case there are other activities
            // in the original Task), so we should also reparent the overlay to the PIP task.
            startTransaction.reparent(swipePipToHomeOverlay, leash)
                    .setLayer(swipePipToHomeOverlay, Integer.MAX_VALUE);
            mPipOrganizer.mSwipePipToHomeOverlay = null;
        }

        Rect sourceBounds = pipTaskInfo.configuration.windowConfiguration.getBounds();
        if (!Transitions.SHELL_TRANSITIONS_ROTATION && rotationDelta % 2 == 1) {
            // PipController#startSwipePipToHome has updated the display layout to new rotation,
            // so flip the source bounds to match the same orientation.
            sourceBounds = new Rect(0, 0, sourceBounds.height(), sourceBounds.width());
        }
        final PipAnimationController.PipTransitionAnimator animator =
                mPipAnimationController.getAnimator(pipTaskInfo, leash, sourceBounds, sourceBounds,
                        destinationBounds, sourceHintRect, TRANSITION_DIRECTION_TO_PIP,
                        0 /* startingAngle */, 0 /* rotationDelta */)
                        .setPipTransactionHandler(mTransactionConsumer)
                        .setTransitionDirection(TRANSITION_DIRECTION_TO_PIP);
        // The start state is the end state for swipe-auto-pip.
        startTransaction.merge(finishTransaction);
        animator.applySurfaceControlTransaction(leash, startTransaction,
                PipAnimationController.FRACTION_END);
        startTransaction.apply();

        mPipBoundsState.setBounds(destinationBounds);
        final SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
        onFinishResize(pipTaskInfo, destinationBounds, TRANSITION_DIRECTION_TO_PIP, tx);
        sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
        if (swipePipToHomeOverlay != null) {
            mPipOrganizer.fadeOutAndRemoveOverlay(swipePipToHomeOverlay,
                    null /* callback */, false /* withStartDelay */);
        }
        mPipTransitionState.setInSwipePipToHomeTransition(false);
    }

    private void startExitToSplitAnimation(@NonNull TransitionInfo info,
            @NonNull SurfaceControl.Transaction startTransaction,
            @NonNull SurfaceControl.Transaction finishTransaction,