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

Commit aff00b6b authored by Ikram Gabiyev's avatar Ikram Gabiyev
Browse files

Implement 3-btn-nav fixed rotation

Implement the 3-btn-nav bounds type
fixed rotation transition with the animation.

The flow looks as follows:

1. A direct TRANSIT_PIP or TRANSIT_OPEN is detected
with a fixed rotation change providing us with endFixedRotation hint.
2. Shell runs the fixed rotation animation in the original display
orientation.
3. Shell updates the relevant internal state to represent that in final
orientation
4. Core requests a CHANGE transition with a display change that we
listen to in PipController. We update the display layout state and sent
through the bounds as a WCT in the final orientation to match the layer
position.

Note: we might get a temporary late draw flicker after the animation is over,
this is a separate potentially Core-related being discussed in b/372767189.

Bug: 372310588
Flag: com.android.wm.shell.enable_pip2
Test: enter PiP from landscape to portrait

Change-Id: Ifff3caf5521cc60f66f8ccfbae360e45528c3a16
parent 972694be
Loading
Loading
Loading
Loading
+0 −11
Original line number Diff line number Diff line
@@ -665,17 +665,6 @@ public class PipTransition extends PipTransitionController {
        return null;
    }

    @Nullable
    private TransitionInfo.Change findFixedRotationChange(@NonNull TransitionInfo info) {
        for (int i = info.getChanges().size() - 1; i >= 0; --i) {
            final TransitionInfo.Change change = info.getChanges().get(i);
            if (change.getEndFixedRotation() != ROTATION_UNDEFINED) {
                return change;
            }
        }
        return null;
    }

    private void startExitAnimation(@NonNull TransitionInfo info,
            @NonNull SurfaceControl.Transaction startTransaction,
            @NonNull SurfaceControl.Transaction finishTransaction,
+16 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.wm.shell.pip;

import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.WindowManager.TRANSIT_PIP;

@@ -346,6 +347,21 @@ public abstract class PipTransitionController implements Transitions.TransitionH
        return false;
    }

    /**
     * Gets a change amongst the transition targets that is in a different final orientation than
     * the display, signalling a potential fixed rotation transition.
     */
    @Nullable
    public TransitionInfo.Change findFixedRotationChange(@NonNull TransitionInfo info) {
        for (int i = info.getChanges().size() - 1; i >= 0; --i) {
            final TransitionInfo.Change change = info.getChanges().get(i);
            if (change.getEndFixedRotation() != ROTATION_UNDEFINED) {
                return change;
            }
        }
        return null;
    }

    /** End the currently-playing PiP animation. */
    public void end() {
    }
+40 −4
Original line number Diff line number Diff line
@@ -16,10 +16,14 @@

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

import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;

import android.animation.Animator;
import android.animation.RectEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.Rect;
import android.view.Surface;
@@ -60,6 +64,11 @@ public class PipEnterAnimator extends ValueAnimator
    private final PointF mInitScale = new PointF();
    private final PointF mInitPos = new PointF();
    private final Rect mInitCrop = new Rect();
    private final PointF mInitActivityScale = new PointF();
    private final PointF mInitActivityPos = new PointF();

    Matrix mTransformTensor = new Matrix();
    final float[] mMatrixTmp = new float[9];

    public PipEnterAnimator(Context context,
            @NonNull SurfaceControl leash,
@@ -109,6 +118,10 @@ public class PipEnterAnimator extends ValueAnimator

    @Override
    public void onAnimationEnd(@NonNull Animator animation) {
        if (mFinishTransaction != null) {
            onEnterAnimationUpdate(mInitScale, mInitPos, mInitCrop,
                    1f /* fraction */, mFinishTransaction);
        }
        if (mAnimationEndCallback != null) {
            mAnimationEndCallback.run();
        }
@@ -126,16 +139,24 @@ public class PipEnterAnimator extends ValueAnimator
            float fraction, SurfaceControl.Transaction tx) {
        float scaleX = 1 + (initScale.x - 1) * (1 - fraction);
        float scaleY = 1 + (initScale.y - 1) * (1 - fraction);
        tx.setScale(mLeash, scaleX, scaleY);

        float posX = initPos.x + (mEndBounds.left - initPos.x) * fraction;
        float posY = initPos.y + (mEndBounds.top - initPos.y) * fraction;
        tx.setPosition(mLeash, posX, posY);

        int normalizedRotation = mRotation;
        if (normalizedRotation == ROTATION_270) {
            normalizedRotation = -ROTATION_90;
        }
        float degrees = -normalizedRotation * 90f * fraction;

        Rect endCrop = new Rect(mEndBounds);
        endCrop.offsetTo(0, 0);
        mRectEvaluator.evaluate(fraction, initCrop, endCrop);
        tx.setCrop(mLeash, mAnimatedRect);

        mTransformTensor.setScale(scaleX, scaleY);
        mTransformTensor.postTranslate(posX, posY);
        mTransformTensor.postRotate(degrees);
        tx.setMatrix(mLeash, mTransformTensor, mMatrixTmp);
    }

    // no-ops
@@ -153,7 +174,22 @@ public class PipEnterAnimator extends ValueAnimator
     * calculated differently from generic transitions.
     * @param pipChange PiP change received as a transition target.
     */
    public void setEnterStartState(@NonNull TransitionInfo.Change pipChange) {
    public void setEnterStartState(@NonNull TransitionInfo.Change pipChange,
            @NonNull TransitionInfo.Change pipActivityChange) {
        PipUtils.calcEndTransform(pipActivityChange, pipChange, mInitActivityScale,
                mInitActivityPos);
        if (mStartTransaction != null && pipActivityChange.getLeash() != null) {
            mStartTransaction.setCrop(pipActivityChange.getLeash(), null);
            mStartTransaction.setScale(pipActivityChange.getLeash(), mInitActivityScale.x,
                    mInitActivityScale.y);
            mStartTransaction.setPosition(pipActivityChange.getLeash(), mInitActivityPos.x,
                    mInitActivityPos.y);
            mFinishTransaction.setCrop(pipActivityChange.getLeash(), null);
            mFinishTransaction.setScale(pipActivityChange.getLeash(), mInitActivityScale.x,
                    mInitActivityScale.y);
            mFinishTransaction.setPosition(pipActivityChange.getLeash(), mInitActivityPos.x,
                    mInitActivityPos.y);
        }
        PipUtils.calcStartTransform(pipChange, mInitScale, mInitPos, mInitCrop);
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -157,6 +157,7 @@ public class PipExpandAnimator extends ValueAnimator
                .shadow(tx, mLeash, false /* applyCornerRadius */);
        tx.apply();
    }

    private Rect getInsets(float fraction) {
        final Rect startInsets = mSourceRectHintInsets;
        final Rect endInsets = mZeroInsets;
+23 −12
Original line number Diff line number Diff line
@@ -292,23 +292,34 @@ public class PipController implements ConfigurationChangeListener,
        setDisplayLayout(mDisplayController.getDisplayLayout(displayId));

        if (!mPipTransitionState.isInPip()) {
            // Skip the PiP-relevant updates if we aren't in a valid PiP state.
            if (mPipTransitionState.isInFixedRotation()) {
                ProtoLog.e(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                        "Fixed rotation flag shouldn't be set while in an invalid PiP state");
            }
            return;
        }

        mPipTouchHandler.updateMinMaxSize(mPipBoundsState.getAspectRatio());

        // Update the caches to reflect the new display layout in the movement bounds;
        // temporarily update bounds to be at the top left for the movement bounds calculation.
        if (mPipTransitionState.isInFixedRotation()) {
            // Do not change the bounds when in fixed rotation, but do update the movement bounds
            // based on the current bounds state and potentially new display layout.
            mPipTouchHandler.updateMovementBounds();
            mPipTransitionState.setInFixedRotation(false);
        } else {
            Rect toBounds = new Rect(0, 0,
                    (int) Math.ceil(mPipBoundsState.getMaxSize().x * boundsScale),
                    (int) Math.ceil(mPipBoundsState.getMaxSize().y * boundsScale));
            // Update the caches to reflect the new display layout in the movement bounds;
            // temporarily update bounds to be at the top left for the movement bounds calculation.
            mPipBoundsState.setBounds(toBounds);
            mPipTouchHandler.updateMovementBounds();

            // The policy is to keep PiP snap fraction invariant.
            mPipBoundsAlgorithm.applySnapFraction(toBounds, snapFraction);
            mPipBoundsState.setBounds(toBounds);
        t.setBounds(mPipTransitionState.mPipTaskToken, toBounds);
        }
        t.setBounds(mPipTransitionState.mPipTaskToken, mPipBoundsState.getBounds());
    }

    private void setDisplayLayout(DisplayLayout layout) {
Loading