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

Commit 439a8ae0 authored by Ikram Gabiyev's avatar Ikram Gabiyev Committed by Android (Google) Code Review
Browse files

Merge "Reset the pip icon overlay scale and offset" into main

parents 17834277 9ce08994
Loading
Loading
Loading
Loading
+17 −9
Original line number Diff line number Diff line
@@ -193,19 +193,12 @@ public abstract class PipContentOverlay {
                    MAX_APP_ICON_SIZE_DP, context.getResources().getDisplayMetrics());
            mAppIconSizePx = Math.min(maxAppIconSizePx, appIconSizePx);

            final int appWidth = appBounds.width();
            final int appHeight = appBounds.height();

            // In order to have the overlay always cover the pip window during the transition, the
            // overlay will be drawn with the max size of the start and end bounds in different
            // rotation.
            final int overlaySize = Math.max(Math.max(appWidth, appHeight),
                    Math.max(destinationBounds.width(), destinationBounds.height())) + 1;
            final int overlaySize = getOverlaySize(appBounds, destinationBounds);
            mOverlayHalfSize = overlaySize >> 1;

            // When the activity is in the secondary split, make sure the scaling center is not
            // offset.
            mAppBounds = new Rect(0, 0, appWidth, appHeight);
            mAppBounds = new Rect(0, 0, appBounds.width(), appBounds.height());

            mBitmap = Bitmap.createBitmap(overlaySize, overlaySize, Bitmap.Config.ARGB_8888);
            prepareAppIconOverlay(appIcon);
@@ -215,6 +208,21 @@ public abstract class PipContentOverlay {
                    .build();
        }

        /**
         * Returns the size of the app icon overlay.
         *
         * In order to have the overlay always cover the pip window during the transition,
         * the overlay will be drawn with the max size of the start and end bounds in different
         * rotation.
         */
        public static int getOverlaySize(Rect appBounds, Rect destinationBounds) {
            final int appWidth = appBounds.width();
            final int appHeight = appBounds.height();

            return Math.max(Math.max(appWidth, appHeight),
                    Math.max(destinationBounds.width(), destinationBounds.height())) + 1;
        }

        @Override
        public void attach(SurfaceControl.Transaction tx, SurfaceControl parentLeash) {
            tx.show(mLeash);
+86 −14
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP_TO_SP
import static com.android.wm.shell.transition.Transitions.TRANSIT_REMOVE_PIP;

import android.animation.Animator;
import android.annotation.IntDef;
import android.app.ActivityManager;
import android.app.TaskInfo;
import android.content.Context;
@@ -76,6 +77,8 @@ import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.util.TransitionUtil;

import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Optional;

/**
@@ -86,6 +89,18 @@ public class PipTransition extends PipTransitionController {

    private static final String TAG = PipTransition.class.getSimpleName();

    /** No fixed rotation, or fixed rotation state is undefined. */
    private static final int FIXED_ROTATION_UNDEFINED = 0;
    /**
     * Fixed rotation detected via callbacks (see PipController#startSwipePipToHome());
     * this is used in the swipe PiP to home case, since the transitions itself isn't supposed to
     * see the fixed rotation.
     */
    private static final int FIXED_ROTATION_CALLBACK = 1;

    /** Fixed rotation detected in the incoming transition. */
    private static final int FIXED_ROTATION_TRANSITION = 2;

    private final Context mContext;
    private final PipTransitionState mPipTransitionState;
    private final PipDisplayLayoutState mPipDisplayLayoutState;
@@ -106,17 +121,28 @@ public class PipTransition extends PipTransitionController {
    /** The Task window that is currently in PIP windowing mode. */
    @Nullable
    private WindowContainerToken mCurrentPipTaskToken;
    /** Whether display is in fixed rotation. */
    private boolean mInFixedRotation;

    @IntDef(prefix = { "FIXED_ROTATION_" }, value =  {
            FIXED_ROTATION_UNDEFINED,
            FIXED_ROTATION_CALLBACK,
            FIXED_ROTATION_TRANSITION
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface FixedRotationState {}

    /** Fixed rotation state of the display. */
    private @FixedRotationState int mFixedRotationState = FIXED_ROTATION_UNDEFINED;
    /**
     * The rotation that the display will apply after expanding PiP to fullscreen. This is only
     * meaningful if {@link #mInFixedRotation} is true.
     * meaningful if {@link #mFixedRotationState} is {@link #FIXED_ROTATION_TRANSITION}.
     */
    @Surface.Rotation
    private int mEndFixedRotation;
    /** Whether the PIP window has fade out for fixed rotation. */
    private boolean mHasFadeOut;

    private Rect mInitBounds = new Rect();

    /** Used for setting transform to a transaction from animator. */
    private final PipAnimationController.PipTransactionHandler mTransactionConsumer =
            new PipAnimationController.PipTransactionHandler() {
@@ -181,8 +207,16 @@ public class PipTransition extends PipTransitionController {
            @NonNull Transitions.TransitionFinishCallback finishCallback) {
        final TransitionInfo.Change currentPipTaskChange = findCurrentPipTaskChange(info);
        final TransitionInfo.Change fixedRotationChange = findFixedRotationChange(info);
        mInFixedRotation = fixedRotationChange != null;
        mEndFixedRotation = mInFixedRotation
        if (mFixedRotationState == FIXED_ROTATION_TRANSITION) {
            // If we are just about to process potential fixed rotation information,
            // then fixed rotation state should either be UNDEFINED or CALLBACK.
            ProtoLog.w(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                    "%s: startAnimation() should start with clear fixed rotation state", TAG);
            mFixedRotationState = FIXED_ROTATION_UNDEFINED;
        }
        mFixedRotationState = fixedRotationChange != null
                ? FIXED_ROTATION_TRANSITION : mFixedRotationState;
        mEndFixedRotation = mFixedRotationState == FIXED_ROTATION_TRANSITION
                ? fixedRotationChange.getEndFixedRotation()
                : ROTATION_UNDEFINED;

@@ -347,6 +381,10 @@ public class PipTransition extends PipTransitionController {
    @Override
    public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
            @Nullable SurfaceControl.Transaction finishT) {
        // Transition either finished pre-emptively, got merged, or aborted,
        // so update fixed rotation state to default.
        mFixedRotationState = FIXED_ROTATION_UNDEFINED;

        if (transition != mExitTransition) {
            return;
        }
@@ -408,7 +446,8 @@ public class PipTransition extends PipTransitionController {
                // 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 (!mInFixedRotation && mFinishTransaction != null) {
                if (mFixedRotationState != FIXED_ROTATION_TRANSITION
                        && mFinishTransaction != null) {
                    mFinishTransaction.merge(tx);
                }
            } else {
@@ -426,12 +465,27 @@ public class PipTransition extends PipTransitionController {
                    mSurfaceTransactionHelper.crop(tx, leash, destinationBounds)
                            .resetScale(tx, leash, destinationBounds)
                            .round(tx, leash, true /* applyCornerRadius */);
                    if (mPipOrganizer.mSwipePipToHomeOverlay != null && !mInitBounds.isEmpty()) {
                        // Resetting the scale for pinned task while re-adjusting its crop,
                        // also scales the overlay. So we need to update the overlay leash too.
                        Rect overlayBounds = new Rect(destinationBounds);
                        final int overlaySize = PipContentOverlay.PipAppIconOverlay
                                .getOverlaySize(mInitBounds, destinationBounds);

                        overlayBounds.offsetTo(
                                (destinationBounds.width() - overlaySize) / 2,
                                (destinationBounds.height() - overlaySize) / 2);
                        mSurfaceTransactionHelper.resetScale(tx,
                                mPipOrganizer.mSwipePipToHomeOverlay, overlayBounds);
                    }
                }
                mInitBounds.setEmpty();
                wct.setBoundsChangeTransaction(taskInfo.token, tx);
            }
            final int displayRotation = taskInfo.getConfiguration().windowConfiguration
                    .getDisplayRotation();
            if (enteringPip && mInFixedRotation && mEndFixedRotation != displayRotation
            if (enteringPip && mFixedRotationState == FIXED_ROTATION_TRANSITION
                    && mEndFixedRotation != displayRotation
                    && 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
@@ -451,6 +505,8 @@ public class PipTransition extends PipTransitionController {
            mFinishTransaction = null;
            callFinishCallback(wct);
        }
        // This is the end of transition on the Shell side so update the fixed rotation state.
        mFixedRotationState = FIXED_ROTATION_UNDEFINED;
        finishResizeForMenu(destinationBounds);
    }

@@ -467,6 +523,7 @@ public class PipTransition extends PipTransitionController {
        // mFinishCallback might be null with an outdated mCurrentPipTaskToken
        // for example, when app crashes while in PiP and exit transition has not started
        mCurrentPipTaskToken = null;
        mFixedRotationState = FIXED_ROTATION_UNDEFINED;
        if (mFinishCallback == null) return;
        mFinishCallback.onTransitionFinished(null /* wct */);
        mFinishCallback = null;
@@ -475,6 +532,9 @@ public class PipTransition extends PipTransitionController {

    @Override
    public void onFixedRotationStarted() {
        if (mFixedRotationState == FIXED_ROTATION_UNDEFINED) {
            mFixedRotationState = FIXED_ROTATION_CALLBACK;
        }
        fadeEnteredPipIfNeed(false /* show */);
    }

@@ -656,7 +716,7 @@ public class PipTransition extends PipTransitionController {

        // Check if it is fixed rotation.
        final int rotationDelta;
        if (mInFixedRotation) {
        if (mFixedRotationState == FIXED_ROTATION_TRANSITION) {
            final int startRotation = pipChange.getStartRotation();
            final int endRotation = mEndFixedRotation;
            rotationDelta = deltaRotation(startRotation, endRotation);
@@ -873,11 +933,13 @@ public class PipTransition extends PipTransitionController {
        final int startRotation = pipChange.getStartRotation();
        // Check again in case some callers use startEnterAnimation directly so the flag was not
        // set in startAnimation, e.g. from DefaultMixedHandler.
        if (!mInFixedRotation) {
        if (mFixedRotationState != FIXED_ROTATION_TRANSITION) {
            mEndFixedRotation = pipChange.getEndFixedRotation();
            mInFixedRotation = mEndFixedRotation != ROTATION_UNDEFINED;
            mFixedRotationState = mEndFixedRotation != ROTATION_UNDEFINED
                    ? FIXED_ROTATION_TRANSITION : mFixedRotationState;
        }
        final int endRotation = mInFixedRotation ? mEndFixedRotation : pipChange.getEndRotation();
        final int endRotation = mFixedRotationState == FIXED_ROTATION_TRANSITION
                ? mEndFixedRotation : pipChange.getEndRotation();

        setBoundsStateForEntry(taskInfo.topActivity, taskInfo.pictureInPictureParams,
                taskInfo.topActivityInfo);
@@ -888,10 +950,15 @@ public class PipTransition extends PipTransitionController {

        final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
        final Rect currentBounds = pipChange.getStartAbsBounds();

        // Cache the start bounds for overlay manipulations as a part of finishCallback.
        mInitBounds.set(currentBounds);

        int rotationDelta = deltaRotation(startRotation, endRotation);
        Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect(
                taskInfo.pictureInPictureParams, currentBounds, destinationBounds);
        if (rotationDelta != Surface.ROTATION_0 && mInFixedRotation) {
        if (rotationDelta != Surface.ROTATION_0
                && mFixedRotationState == FIXED_ROTATION_TRANSITION) {
            // Need to get the bounds of new rotation in old rotation for fixed rotation,
            computeEnterPipRotatedBounds(rotationDelta, startRotation, endRotation, taskInfo,
                    destinationBounds, sourceHintRect);
@@ -958,7 +1025,8 @@ public class PipTransition extends PipTransitionController {
        animator.setTransitionDirection(TRANSITION_DIRECTION_TO_PIP)
                .setPipAnimationCallback(mPipAnimationCallback)
                .setDuration(mEnterExitAnimationDuration);
        if (rotationDelta != Surface.ROTATION_0 && mInFixedRotation) {
        if (rotationDelta != Surface.ROTATION_0
                && mFixedRotationState == FIXED_ROTATION_TRANSITION) {
            // For fixed rotation, the animation destination bounds is in old rotation coordinates.
            // Set the destination bounds to new coordinates after the animation is finished.
            // ComputeRotatedBounds has changed the DisplayLayout without affecting the animation.
@@ -997,13 +1065,17 @@ public class PipTransition extends PipTransitionController {
            @NonNull SurfaceControl leash, @Nullable Rect sourceHintRect,
            @NonNull Rect destinationBounds,
            @NonNull ActivityManager.RunningTaskInfo pipTaskInfo) {
        if (mInFixedRotation) {
        if (mFixedRotationState == FIXED_ROTATION_TRANSITION) {
            // If rotation changes when returning to home, the transition should contain both the
            // entering PiP and the display change (PipController#startSwipePipToHome has updated
            // the display layout to new rotation). So it is not expected to see fixed rotation.
            ProtoLog.w(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                    "%s: SwipePipToHome should not use fixed rotation %d", TAG, mEndFixedRotation);
        }
        Rect appBounds = pipTaskInfo.configuration.windowConfiguration.getAppBounds();
        if (mFixedRotationState == FIXED_ROTATION_CALLBACK && appBounds != null) {
            mInitBounds.set(appBounds);
        }
        final SurfaceControl swipePipToHomeOverlay = mPipOrganizer.mSwipePipToHomeOverlay;
        if (swipePipToHomeOverlay != null) {
            // Launcher fade in the overlay on top of the fullscreen Task. It is possible we