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

Commit 8df3b4e9 authored by Ben Lin's avatar Ben Lin Committed by Android (Google) Code Review
Browse files

Merge changes Ie9be757c,I2e239d23

* changes:
  PiP pinch-to-resize: Enable two finger movement and slight rotation.
  PiP pinch-to-resize: add double-tap to max/min size.
parents f1304712 70a82b90
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -17,4 +17,5 @@

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.wm.shell">
    <uses-permission android:name="android.permission.ROTATE_SURFACE_FLINGER" />
</manifest>
+15 −9
Original line number Diff line number Diff line
@@ -116,7 +116,8 @@ public class PipAnimationController {
     * Construct and return an animator that animates from the {@param startBounds} to the
     * {@param endBounds} with the given {@param direction}. If {@param direction} is type
     * {@link ANIM_TYPE_BOUNDS}, then {@param sourceHintRect} will be used to animate
     * in a better, more smooth manner.
     * in a better, more smooth manner. If the original bound was rotated and a reset needs to
     * happen, pass in {@param startingAngle}.
     *
     * In the case where one wants to start animation during an intermediate animation (for example,
     * if the user is currently doing a pinch-resize, and upon letting go now PiP needs to animate
@@ -128,11 +129,11 @@ public class PipAnimationController {
    @VisibleForTesting
    public PipTransitionAnimator getAnimator(SurfaceControl leash, Rect baseBounds,
            Rect startBounds, Rect endBounds, Rect sourceHintRect,
            @PipAnimationController.TransitionDirection int direction) {
            @PipAnimationController.TransitionDirection int direction, float startingAngle) {
        if (mCurrentAnimator == null) {
            mCurrentAnimator = setupPipTransitionAnimator(
                    PipTransitionAnimator.ofBounds(leash, startBounds, startBounds, endBounds,
                            sourceHintRect, direction));
                            sourceHintRect, direction, 0 /* startingAngle */));
        } else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_ALPHA
                && mCurrentAnimator.isRunning()) {
            // If we are still animating the fade into pip, then just move the surface and ensure
@@ -148,7 +149,7 @@ public class PipAnimationController {
            mCurrentAnimator.cancel();
            mCurrentAnimator = setupPipTransitionAnimator(
                    PipTransitionAnimator.ofBounds(leash, baseBounds, startBounds, endBounds,
                            sourceHintRect, direction));
                            sourceHintRect, direction, startingAngle));
        }
        return mCurrentAnimator;
    }
@@ -201,6 +202,7 @@ public class PipAnimationController {
        protected T mCurrentValue;
        protected T mStartValue;
        private T mEndValue;
        private float mStartingAngle;
        private PipAnimationCallback mPipAnimationCallback;
        private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory
                mSurfaceControlTransactionFactory;
@@ -208,13 +210,15 @@ public class PipAnimationController {
        private @TransitionDirection int mTransitionDirection;

        private PipTransitionAnimator(SurfaceControl leash, @AnimationType int animationType,
                Rect destinationBounds, T baseValue, T startValue, T endValue) {
                Rect destinationBounds, T baseValue, T startValue, T endValue,
                float startingAngle) {
            mLeash = leash;
            mAnimationType = animationType;
            mDestinationBounds.set(destinationBounds);
            mBaseValue = baseValue;
            mStartValue = startValue;
            mEndValue = endValue;
            mStartingAngle = startingAngle;
            addListener(this);
            addUpdateListener(this);
            mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
@@ -363,7 +367,7 @@ public class PipAnimationController {
        static PipTransitionAnimator<Float> ofAlpha(SurfaceControl leash,
                Rect destinationBounds, float startValue, float endValue) {
            return new PipTransitionAnimator<Float>(leash, ANIM_TYPE_ALPHA,
                    destinationBounds, startValue, startValue, endValue) {
                    destinationBounds, startValue, startValue, endValue, 0) {
                @Override
                void applySurfaceControlTransaction(SurfaceControl leash,
                        SurfaceControl.Transaction tx, float fraction) {
@@ -397,7 +401,7 @@ public class PipAnimationController {

        static PipTransitionAnimator<Rect> ofBounds(SurfaceControl leash,
                Rect baseValue, Rect startValue, Rect endValue, Rect sourceHintRect,
                @PipAnimationController.TransitionDirection int direction) {
                @PipAnimationController.TransitionDirection int direction, float startingAngle) {
            // Just for simplicity we'll interpolate between the source rect hint insets and empty
            // insets to calculate the window crop
            final Rect initialSourceValue;
@@ -420,7 +424,8 @@ public class PipAnimationController {

            // construct new Rect instances in case they are recycled
            return new PipTransitionAnimator<Rect>(leash, ANIM_TYPE_BOUNDS,
                    endValue, new Rect(baseValue), new Rect(startValue), new Rect(endValue)) {
                    endValue, new Rect(baseValue), new Rect(startValue), new Rect(endValue),
                    startingAngle) {
                private final RectEvaluator mRectEvaluator = new RectEvaluator(new Rect());
                private final RectEvaluator mInsetsEvaluator = new RectEvaluator(new Rect());

@@ -431,13 +436,14 @@ public class PipAnimationController {
                    final Rect start = getStartValue();
                    final Rect end = getEndValue();
                    Rect bounds = mRectEvaluator.evaluate(fraction, start, end);
                    float angle = (1.0f - fraction) * startingAngle;
                    setCurrentValue(bounds);
                    if (inScaleTransition() || sourceHintRect == null) {

                        if (isOutPipDirection(direction)) {
                            getSurfaceTransactionHelper().scale(tx, leash, end, bounds);
                        } else {
                            getSurfaceTransactionHelper().scale(tx, leash, base, bounds);
                            getSurfaceTransactionHelper().scale(tx, leash, base, bounds, angle);
                        }
                    } else {
                        final Rect insets;
+21 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.Size;
import android.view.DisplayInfo;
@@ -59,6 +60,8 @@ public final class PipBoundsState {
    private final @NonNull Rect mExpandedBounds = new Rect();
    private final @NonNull Rect mNormalMovementBounds = new Rect();
    private final @NonNull Rect mExpandedMovementBounds = new Rect();
    private final Point mMaxSize = new Point();
    private final Point mMinSize = new Point();
    private final @NonNull Context mContext;
    private float mAspectRatio;
    private int mStashedState = STASH_TYPE_NONE;
@@ -151,6 +154,24 @@ public final class PipBoundsState {
        mExpandedMovementBounds.set(bounds);
    }

    /** Sets the max possible size for resize. */
    public void setMaxSize(int width, int height) {
        mMaxSize.set(width, height);
    }

    /** Sets the min possible size for resize. */
    public void setMinSize(int width, int height) {
        mMinSize.set(width, height);
    }

    public Point getMaxSize() {
        return mMaxSize;
    }

    public Point getMinSize() {
        return mMinSize;
    }

    /** Returns the expanded movement bounds. */
    @NonNull
    public Rect getExpandedMovementBounds() {
+10 −0
Original line number Diff line number Diff line
@@ -84,9 +84,19 @@ public class PipSurfaceTransactionHelper {
     */
    public PipSurfaceTransactionHelper scale(SurfaceControl.Transaction tx, SurfaceControl leash,
            Rect sourceBounds, Rect destinationBounds) {
        return scale(tx, leash, sourceBounds, destinationBounds, 0 /* degrees */);
    }

    /**
     * Operates the scale (setMatrix) on a given transaction and leash, along with a rotation.
     * @return same {@link PipSurfaceTransactionHelper} instance for method chaining
     */
    public PipSurfaceTransactionHelper scale(SurfaceControl.Transaction tx, SurfaceControl leash,
            Rect sourceBounds, Rect destinationBounds, float degrees) {
        mTmpSourceRectF.set(sourceBounds);
        mTmpDestinationRectF.set(destinationBounds);
        mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
        mTmpTransform.postRotate(degrees);
        tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
                .setPosition(leash, mTmpDestinationRectF.left, mTmpDestinationRectF.top);
        return this;
+37 −17
Original line number Diff line number Diff line
@@ -195,9 +195,10 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
                Rect currentBounds = (Rect) args.arg2;
                Rect toBounds = (Rect) args.arg3;
                Rect sourceHintRect = (Rect) args.arg4;
                float startingAngle = (float) args.arg5;
                int duration = args.argi2;
                animateResizePip(currentBounds, toBounds, sourceHintRect,
                        args.argi1 /* direction */, duration);
                        args.argi1 /* direction */, duration, startingAngle);
                if (updateBoundsCallback != null) {
                    updateBoundsCallback.accept(toBounds);
                }
@@ -227,7 +228,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
            case MSG_RESIZE_USER: {
                Rect startBounds = (Rect) args.arg2;
                Rect toBounds = (Rect) args.arg3;
                userResizePip(startBounds, toBounds);
                float degrees = (float) args.arg4;
                userResizePip(startBounds, toBounds, degrees);
                if (updateBoundsCallback != null) {
                    updateBoundsCallback.accept(toBounds);
                }
@@ -427,7 +429,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
                    final Rect sourceHintRect = getValidSourceHintRect(mPictureInPictureParams,
                            destinationBounds);
                    scheduleAnimateResizePip(mPipBoundsState.getBounds(), destinationBounds,
                            sourceHintRect, direction, animationDurationMs,
                            0 /* startingAngle */, sourceHintRect, direction, animationDurationMs,
                            null /* updateBoundsCallback */);
                    mState = State.EXITING_PIP;
                }
@@ -535,8 +537,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
            mPipMenuController.attach(mLeash);
            final Rect sourceHintRect = getValidSourceHintRect(info.pictureInPictureParams,
                    currentBounds);
            scheduleAnimateResizePip(currentBounds, destinationBounds, sourceHintRect,
                    TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
            scheduleAnimateResizePip(currentBounds, destinationBounds, 0 /* startingAngle */,
                    sourceHintRect, TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
                    null /* updateBoundsCallback */);
            mState = State.ENTERING_PIP;
        } else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
@@ -822,8 +824,9 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
            Log.d(TAG, "skip scheduleAnimateResizePip, entering pip deferred");
            return;
        }
        scheduleAnimateResizePip(mPipBoundsState.getBounds(), toBounds, null /* sourceHintRect */,
                TRANSITION_DIRECTION_NONE, duration, updateBoundsCallback);
        scheduleAnimateResizePip(mPipBoundsState.getBounds(), toBounds, 0 /* startingAngle */,
                null /* sourceHintRect */, TRANSITION_DIRECTION_NONE, duration,
                updateBoundsCallback);
    }

    /**
@@ -831,18 +834,23 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
     * This is used when the starting bounds is not the current PiP bounds.
     */
    public void scheduleAnimateResizePip(Rect fromBounds, Rect toBounds, int duration,
            Consumer<Rect> updateBoundsCallback) {
            float startingAngle, Consumer<Rect> updateBoundsCallback) {
        if (mWaitForFixedRotation) {
            Log.d(TAG, "skip scheduleAnimateResizePip, entering pip deferred");
            return;
        }
        scheduleAnimateResizePip(fromBounds, toBounds, null /* sourceHintRect */,
        scheduleAnimateResizePip(fromBounds, toBounds, startingAngle, null /* sourceHintRect */,
                TRANSITION_DIRECTION_SNAP_AFTER_RESIZE, duration, updateBoundsCallback);
    }

    /**
     * Animates resizing of the pinned stack given the duration and start bounds.
     * This always animates the angle to zero from the starting angle.
     */
    private void scheduleAnimateResizePip(Rect currentBounds, Rect destinationBounds,
            Rect sourceHintRect, @PipAnimationController.TransitionDirection int direction,
            int durationMs, Consumer<Rect> updateBoundsCallback) {
            float startingAngle, Rect sourceHintRect,
            @PipAnimationController.TransitionDirection int direction, int durationMs,
            Consumer<Rect> updateBoundsCallback) {
        if (!mState.isInPip()) {
            // TODO: tend to use shouldBlockResizeRequest here as well but need to consider
            // the fact that when in exitPip, scheduleAnimateResizePip is executed in the window
@@ -855,6 +863,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        args.arg2 = currentBounds;
        args.arg3 = destinationBounds;
        args.arg4 = sourceHintRect;
        args.arg5 = startingAngle;
        args.argi1 = direction;
        args.argi2 = durationMs;
        mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_RESIZE_ANIMATE, args));
@@ -871,16 +880,26 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_RESIZE_IMMEDIATE, args));
    }

    /**
     * Directly perform manipulation/resize on the leash, along with rotation. This will not perform
     * any {@link WindowContainerTransaction} until {@link #scheduleFinishResizePip} is called.
     */
    public void scheduleUserResizePip(Rect startBounds, Rect toBounds,
            Consumer<Rect> updateBoundsCallback) {
        scheduleUserResizePip(startBounds, toBounds, 0 /* degrees */, updateBoundsCallback);
    }

    /**
     * Directly perform a scaled matrix transformation on the leash. This will not perform any
     * {@link WindowContainerTransaction} until {@link #scheduleFinishResizePip} is called.
     */
    public void scheduleUserResizePip(Rect startBounds, Rect toBounds,
    public void scheduleUserResizePip(Rect startBounds, Rect toBounds, float degrees,
            Consumer<Rect> updateBoundsCallback) {
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = updateBoundsCallback;
        args.arg2 = startBounds;
        args.arg3 = toBounds;
        args.arg4 = degrees;
        mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_RESIZE_USER, args));
    }

@@ -959,7 +978,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        final Rect destinationBounds = new Rect(originalBounds);
        destinationBounds.offset(xOffset, yOffset);
        animateResizePip(originalBounds, destinationBounds, null /* sourceHintRect */,
                TRANSITION_DIRECTION_SAME, durationMs);
                TRANSITION_DIRECTION_SAME, durationMs, 0);
    }

    private void resizePip(Rect destinationBounds) {
@@ -985,7 +1004,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        }
    }

    private void userResizePip(Rect startBounds, Rect destinationBounds) {
    private void userResizePip(Rect startBounds, Rect destinationBounds, float degrees) {
        if (Looper.myLooper() != mUpdateHandler.getLooper()) {
            throw new RuntimeException("Callers should call scheduleUserResizePip() instead of "
                    + "this directly");
@@ -1002,7 +1021,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        }

        final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
        mSurfaceTransactionHelper.scale(tx, mLeash, startBounds, destinationBounds);
        mSurfaceTransactionHelper.scale(tx, mLeash, startBounds, destinationBounds, degrees);
        if (mPipMenuController.isMenuVisible()) {
            runOnMainHandler(() ->
                    mPipMenuController.movePipMenu(mLeash, tx, destinationBounds));
@@ -1089,7 +1108,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
    }

    private void animateResizePip(Rect currentBounds, Rect destinationBounds, Rect sourceHintRect,
            @PipAnimationController.TransitionDirection int direction, int durationMs) {
            @PipAnimationController.TransitionDirection int direction, int durationMs,
            float startingAngle) {
        if (Looper.myLooper() != mUpdateHandler.getLooper()) {
            throw new RuntimeException("Callers should call scheduleAnimateResizePip() instead of "
                    + "this directly");
@@ -1103,7 +1123,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
                ? mPipBoundsState.getBounds() : currentBounds;
        mPipAnimationController
                .getAnimator(mLeash, baseBounds, currentBounds, destinationBounds, sourceHintRect,
                        direction)
                        direction, startingAngle)
                .setTransitionDirection(direction)
                .setPipAnimationCallback(mPipAnimationCallback)
                .setDuration(durationMs)
Loading