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

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

Merge "[PiP2] Implement expand in fixed rotation" into main

parents ba919351 e5e9121d
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import android.view.Choreographer;
import android.view.SurfaceControl;

import com.android.wm.shell.R;
import com.android.wm.shell.transition.Transitions;

/**
 * Abstracts the common operations on {@link SurfaceControl.Transaction} for PiP transition.
@@ -180,8 +179,7 @@ public class PipSurfaceTransactionHelper {
        // destination are different.
        final float scale = srcW <= srcH ? (float) destW / srcW : (float) destH / srcH;
        final Rect crop = mTmpDestinationRect;
        crop.set(0, 0, Transitions.SHELL_TRANSITIONS_ROTATION ? destH
                : destW, Transitions.SHELL_TRANSITIONS_ROTATION ? destW : destH);
        crop.set(0, 0, destW, destH);
        // Inverse scale for crop to fit in screen coordinates.
        crop.scale(1 / scale);
        crop.offset(insets.left, insets.top);
@@ -200,8 +198,8 @@ public class PipSurfaceTransactionHelper {
            }
        }
        mTmpTransform.setScale(scale, scale);
        mTmpTransform.postRotate(degrees);
        mTmpTransform.postTranslate(positionX, positionY);
        mTmpTransform.postRotate(degrees);
        tx.setMatrix(leash, mTmpTransform, mTmpFloat9).setCrop(leash, crop);
        return this;
    }
+31 −15
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.wm.shell.pip2.animation;

import static android.view.Surface.ROTATION_90;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.RectEvaluator;
@@ -73,6 +75,7 @@ public class PipExpandAnimator extends ValueAnimator {
                mAnimationStartCallback.run();
            }
            if (mStartTransaction != null) {
                onExpandAnimationUpdate(mStartTransaction, 0f);
                mStartTransaction.apply();
            }
        }
@@ -81,13 +84,7 @@ public class PipExpandAnimator extends ValueAnimator {
        public void onAnimationEnd(Animator animation) {
            super.onAnimationEnd(animation);
            if (mFinishTransaction != null) {
                // finishTransaction might override some state (eg. corner radii) so we want to
                // manually set the state to the end of the animation
                mPipSurfaceTransactionHelper.scaleAndCrop(mFinishTransaction, mLeash,
                                mSourceRectHint, mBaseBounds, mAnimatedRect, getInsets(1f),
                                false /* isInPipDirection */, 1f)
                        .round(mFinishTransaction, mLeash, false /* applyCornerRadius */)
                        .shadow(mFinishTransaction, mLeash, false /* applyCornerRadius */);
                onExpandAnimationUpdate(mFinishTransaction, 1f);
            }
            if (mAnimationEndCallback != null) {
                mAnimationEndCallback.run();
@@ -102,14 +99,7 @@ public class PipExpandAnimator extends ValueAnimator {
                    final SurfaceControl.Transaction tx =
                            mSurfaceControlTransactionFactory.getTransaction();
                    final float fraction = getAnimatedFraction();

                    // TODO (b/350801661): implement fixed rotation
                    Rect insets = getInsets(fraction);
                    mPipSurfaceTransactionHelper.scaleAndCrop(tx, mLeash, mSourceRectHint,
                                    mBaseBounds, mAnimatedRect,
                                    insets, false /* isInPipDirection */, fraction)
                            .round(tx, mLeash, false /* applyCornerRadius */)
                            .shadow(tx, mLeash, false /* applyCornerRadius */);
                    onExpandAnimationUpdate(tx, fraction);
                    tx.apply();
                }
            };
@@ -167,6 +157,32 @@ public class PipExpandAnimator extends ValueAnimator {
        mAnimationEndCallback = runnable;
    }

    private void onExpandAnimationUpdate(SurfaceControl.Transaction tx, float fraction) {
        Rect insets = getInsets(fraction);
        if (mRotation == Surface.ROTATION_0) {
            mPipSurfaceTransactionHelper.scaleAndCrop(tx, mLeash, mSourceRectHint, mBaseBounds,
                    mAnimatedRect, insets, false /* isInPipDirection */, fraction);
        } else {
            // Fixed rotation case.
            Rect start = mStartBounds;
            Rect end = mEndBounds;
            float degrees, x, y;
            x = fraction * (end.left - start.left) + start.left;
            y = fraction * (end.top - start.top) + start.top;

            if (mRotation == ROTATION_90) {
                degrees = 90 * fraction;
            } else {
                degrees = -90 * fraction;
            }
            mPipSurfaceTransactionHelper.rotateAndScaleWithCrop(tx, mLeash, mBaseBounds,
                    mAnimatedRect, insets, degrees, x, y,
                    true /* isExpanding */, mRotation == ROTATION_90);
        }
        mPipSurfaceTransactionHelper.round(tx, mLeash, false /* applyCornerRadius */)
                .shadow(tx, mLeash, false /* applyShadowRadius */);
    }

    private Rect getInsets(float fraction) {
        final Rect startInsets = mSourceRectHintInsets;
        final Rect endInsets = mZeroInsets;
+5 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.view.SurfaceControl;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.internal.protolog.ProtoLog;
import com.android.internal.util.Preconditions;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.ShellExecutor;
@@ -36,6 +37,7 @@ import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
import com.android.wm.shell.common.pip.PipBoundsState;
import com.android.wm.shell.common.pip.PipUtils;
import com.android.wm.shell.pip2.animation.PipResizeAnimator;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.shared.annotations.ShellMainThread;

import java.util.ArrayList;
@@ -121,6 +123,9 @@ public class PipTaskListener implements ShellTaskOrganizer.TaskListener,
        if (mPictureInPictureParams.equals(params)) {
            return;
        }
        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                "onTaskInfoChanged: %s, state=%s oldParams=%s newParams=%s",
                taskInfo.topActivity, mPipTransitionState, mPictureInPictureParams, params);
        setPictureInPictureParams(params);
        float newAspectRatio = mPictureInPictureParams.getAspectRatioFloat();
        if (PipUtils.aspectRatioChanged(newAspectRatio, mPipBoundsState.getAspectRatio())) {
+69 −26
Original line number Diff line number Diff line
@@ -325,9 +325,7 @@ public class PipTransition extends PipTransitionController implements
            return false;
        }

        SurfaceControl pipLeash = pipChange.getLeash();
        Preconditions.checkNotNull(pipLeash, "Leash is null for swipe-up transition.");

        final SurfaceControl pipLeash = getLeash(pipChange);
        final Rect destinationBounds = pipChange.getEndAbsBounds();
        final SurfaceControl swipePipToHomeOverlay = mPipTransitionState.getSwipePipToHomeOverlay();
        if (swipePipToHomeOverlay != null) {
@@ -349,7 +347,7 @@ public class PipTransition extends PipTransitionController implements
                : startRotation - endRotation;
        if (delta != ROTATION_0) {
            mPipTransitionState.setInFixedRotation(true);
            handleBoundsTypeFixedRotation(pipChange, pipActivityChange, endRotation);
            handleBoundsEnterFixedRotation(pipChange, pipActivityChange, endRotation);
        }

        prepareConfigAtEndActivity(startTransaction, finishTransaction, pipChange,
@@ -414,15 +412,15 @@ public class PipTransition extends PipTransitionController implements
        }

        final TransitionInfo.Change fixedRotationChange = findFixedRotationChange(info);
        int startRotation = pipChange.getStartRotation();
        int endRotation = fixedRotationChange != null
        final int startRotation = pipChange.getStartRotation();
        final int endRotation = fixedRotationChange != null
                ? fixedRotationChange.getEndFixedRotation() : ROTATION_UNDEFINED;
        final int delta = endRotation == ROTATION_UNDEFINED ? ROTATION_0
                : startRotation - endRotation;

        if (delta != ROTATION_0) {
            mPipTransitionState.setInFixedRotation(true);
            handleBoundsTypeFixedRotation(pipChange, pipActivityChange,
            handleBoundsEnterFixedRotation(pipChange, pipActivityChange,
                    fixedRotationChange.getEndFixedRotation());
        }

@@ -459,7 +457,7 @@ public class PipTransition extends PipTransitionController implements
        animator.start();
    }

    private void handleBoundsTypeFixedRotation(TransitionInfo.Change pipTaskChange,
    private void handleBoundsEnterFixedRotation(TransitionInfo.Change pipTaskChange,
            TransitionInfo.Change pipActivityChange, int endRotation) {
        final Rect endBounds = pipTaskChange.getEndAbsBounds();
        final Rect endActivityBounds = pipActivityChange.getEndAbsBounds();
@@ -492,6 +490,26 @@ public class PipTransition extends PipTransitionController implements
                endBounds.top + activityEndOffset.y);
    }

    private void handleExpandFixedRotation(TransitionInfo.Change pipTaskChange, int endRotation) {
        final Rect endBounds = pipTaskChange.getEndAbsBounds();
        final int width = endBounds.width();
        final int height = endBounds.height();
        final int left = endBounds.left;
        final int top = endBounds.top;
        int newTop, newLeft;

        if (endRotation == Surface.ROTATION_90) {
            newLeft = top;
            newTop = -(left + width);
        } else {
            newLeft = -(height + top);
            newTop = left;
        }
        // Modify the endBounds, rotating and placing them potentially off-screen, so that
        // as we translate and rotate around the origin, we place them right into the target.
        endBounds.set(newLeft, newTop, newLeft + height, newTop + width);
    }


    private boolean startAlphaTypeEnterAnimation(@NonNull TransitionInfo info,
            @NonNull SurfaceControl.Transaction startTransaction,
@@ -544,33 +562,51 @@ public class PipTransition extends PipTransitionController implements
            }
        }

        // for multi activity, we need to manually set the leash layer
        if (pipChange.getTaskInfo() == null) {
            TransitionInfo.Change parent = getChangeByToken(info, pipChange.getParent());
            if (parent != null) {
                startTransaction.setLayer(parent.getLeash(), Integer.MAX_VALUE - 1);
            }
        // The parent change if we were in a multi-activity PiP; null if single activity PiP.
        final TransitionInfo.Change parentBeforePip = pipChange.getTaskInfo() == null
                ? getChangeByToken(info, pipChange.getParent()) : null;
        if (parentBeforePip != null) {
            // For multi activity, we need to manually set the leash layer
            startTransaction.setLayer(parentBeforePip.getLeash(), Integer.MAX_VALUE - 1);
        }

        Rect startBounds = pipChange.getStartAbsBounds();
        Rect endBounds = pipChange.getEndAbsBounds();
        SurfaceControl pipLeash = pipChange.getLeash();
        Preconditions.checkNotNull(pipLeash, "Leash is null for exit transition.");
        final Rect startBounds = pipChange.getStartAbsBounds();
        final Rect endBounds = pipChange.getEndAbsBounds();
        final SurfaceControl pipLeash = getLeash(pipChange);

        Rect sourceRectHint = null;
        if (pipChange.getTaskInfo() != null
                && pipChange.getTaskInfo().pictureInPictureParams != null) {
        PictureInPictureParams params = null;
        if (pipChange.getTaskInfo() != null) {
            // single activity
            sourceRectHint = pipChange.getTaskInfo().pictureInPictureParams.getSourceRectHint();
        } else if (mPipTaskListener.getPictureInPictureParams().hasSourceBoundsHint()) {
            params = pipChange.getTaskInfo().pictureInPictureParams;
        } else if (parentBeforePip != null && parentBeforePip.getTaskInfo() != null) {
            // multi activity
            sourceRectHint = mPipTaskListener.getPictureInPictureParams().getSourceRectHint();
            params = parentBeforePip.getTaskInfo().pictureInPictureParams;
        }
        final Rect sourceRectHint = PipBoundsAlgorithm.getValidSourceHintRect(params, endBounds,
                startBounds);

        final TransitionInfo.Change fixedRotationChange = findFixedRotationChange(info);
        final int startRotation = pipChange.getStartRotation();
        final int endRotation = fixedRotationChange != null
                ? fixedRotationChange.getEndFixedRotation() : ROTATION_UNDEFINED;
        final int delta = endRotation == ROTATION_UNDEFINED ? ROTATION_0
                : endRotation - startRotation;

        if (delta != ROTATION_0) {
            handleExpandFixedRotation(pipChange, endRotation);
        }

        PipExpandAnimator animator = new PipExpandAnimator(mContext, pipLeash,
                startTransaction, finishTransaction, endBounds, startBounds, endBounds,
                sourceRectHint, Surface.ROTATION_0);
        animator.setAnimationEndCallback(this::finishTransition);
                sourceRectHint, delta);
        animator.setAnimationEndCallback(() -> {
            if (parentBeforePip != null) {
                // TODO b/377362511: Animate local leash instead to also handle letterbox case.
                // For multi-activity, set the crop to be null
                finishTransaction.setCrop(pipLeash, null);
            }
            finishTransition();
        });
        animator.start();
        return true;
    }
@@ -717,6 +753,13 @@ public class PipTransition extends PipTransitionController implements
        }
    }

    @NonNull
    private SurfaceControl getLeash(TransitionInfo.Change change) {
        SurfaceControl leash = change.getLeash();
        Preconditions.checkNotNull(leash, "Leash is null for change=" + change);
        return leash;
    }

    //
    // Miscellaneous callbacks and listeners
    //
+6 −0
Original line number Diff line number Diff line
@@ -614,6 +614,12 @@ class WindowToken extends WindowContainer<WindowState> {
        final int rotation = getRelativeDisplayRotation();
        if (rotation == Surface.ROTATION_0) return mFixedRotationTransformLeash;
        if (mFixedRotationTransformLeash != null) return mFixedRotationTransformLeash;
        if (ActivityTaskManagerService.isPip2ExperimentEnabled() && asActivityRecord() != null
                && mTransitionController.getWindowingModeAtStart(
                asActivityRecord()) == WINDOWING_MODE_PINNED) {
            // PiP handles fixed rotation animation in Shell, so do not create the rotation leash.
            return null;
        }

        final SurfaceControl leash = makeSurface().setContainerLayer()
                .setParent(getParentSurfaceControl())