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

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

Merge "Implement double tap in PiP2" into main

parents 1b299b59 ff9cae05
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -127,8 +127,10 @@ public abstract class PipTransitionController implements Transitions.TransitionH


    /**
    /**
     * Called when the Shell wants to start resizing Pip transition/animation.
     * Called when the Shell wants to start resizing Pip transition/animation.
     *
     * @param duration the suggested duration for resize animation.
     */
     */
    public void startResizeTransition(WindowContainerTransaction wct) {
    public void startResizeTransition(WindowContainerTransaction wct, int duration) {
        // Default implementation does nothing.
        // Default implementation does nothing.
    }
    }


+8 −1
Original line number Original line Diff line number Diff line
@@ -47,9 +47,17 @@ public class PipResizeAnimator extends ValueAnimator
    @Nullable
    @Nullable
    private Runnable mAnimationEndCallback;
    private Runnable mAnimationEndCallback;
    private RectEvaluator mRectEvaluator;
    private RectEvaluator mRectEvaluator;

    // Bounds relative to which scaling/cropping must be done.
    private final Rect mBaseBounds = new Rect();
    private final Rect mBaseBounds = new Rect();

    // Bounds to animate from.
    private final Rect mStartBounds = new Rect();
    private final Rect mStartBounds = new Rect();

    // Target bounds.
    private final Rect mEndBounds = new Rect();
    private final Rect mEndBounds = new Rect();

    // Bounds updated by the evaluator as animator is running.
    private final Rect mAnimatedRect = new Rect();
    private final Rect mAnimatedRect = new Rect();
    private final float mDelta;
    private final float mDelta;


@@ -84,7 +92,6 @@ public class PipResizeAnimator extends ValueAnimator
        addListener(this);
        addListener(this);
        addUpdateListener(this);
        addUpdateListener(this);
        setEvaluator(mRectEvaluator);
        setEvaluator(mRectEvaluator);
        // TODO: change this
        setDuration(duration);
        setDuration(duration);
    }
    }


+1 −0
Original line number Original line Diff line number Diff line
@@ -352,6 +352,7 @@ public class PipController implements ConfigurationChangeListener,
        mPipBoundsAlgorithm.dump(pw, innerPrefix);
        mPipBoundsAlgorithm.dump(pw, innerPrefix);
        mPipBoundsState.dump(pw, innerPrefix);
        mPipBoundsState.dump(pw, innerPrefix);
        mPipDisplayLayoutState.dump(pw, innerPrefix);
        mPipDisplayLayoutState.dump(pw, innerPrefix);
        mPipTransitionState.dump(pw, innerPrefix);
    }
    }


    /**
    /**
+87 −25
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


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


import static androidx.dynamicanimation.animation.SpringForce.DAMPING_RATIO_LOW_BOUNCY;
import static androidx.dynamicanimation.animation.SpringForce.DAMPING_RATIO_NO_BOUNCY;
import static androidx.dynamicanimation.animation.SpringForce.DAMPING_RATIO_NO_BOUNCY;
import static androidx.dynamicanimation.animation.SpringForce.STIFFNESS_LOW;
import static androidx.dynamicanimation.animation.SpringForce.STIFFNESS_LOW;
import static androidx.dynamicanimation.animation.SpringForce.STIFFNESS_MEDIUM;
import static androidx.dynamicanimation.animation.SpringForce.STIFFNESS_MEDIUM;
@@ -25,6 +26,7 @@ import static com.android.wm.shell.common.pip.PipBoundsState.STASH_TYPE_NONE;
import static com.android.wm.shell.common.pip.PipBoundsState.STASH_TYPE_RIGHT;
import static com.android.wm.shell.common.pip.PipBoundsState.STASH_TYPE_RIGHT;
import static com.android.wm.shell.pip2.phone.PipMenuView.ANIM_TYPE_DISMISS;
import static com.android.wm.shell.pip2.phone.PipMenuView.ANIM_TYPE_DISMISS;
import static com.android.wm.shell.pip2.phone.PipMenuView.ANIM_TYPE_NONE;
import static com.android.wm.shell.pip2.phone.PipMenuView.ANIM_TYPE_NONE;
import static com.android.wm.shell.pip2.phone.PipTransition.ANIMATING_BOUNDS_CHANGE_DURATION;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
@@ -36,6 +38,7 @@ import android.os.Debug;
import android.view.SurfaceControl;
import android.view.SurfaceControl;


import com.android.internal.protolog.ProtoLog;
import com.android.internal.protolog.ProtoLog;
import com.android.internal.util.Preconditions;
import com.android.wm.shell.R;
import com.android.wm.shell.R;
import com.android.wm.shell.animation.FloatProperties;
import com.android.wm.shell.animation.FloatProperties;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.FloatingContentCoordinator;
@@ -45,6 +48,7 @@ import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
import com.android.wm.shell.common.pip.PipBoundsState;
import com.android.wm.shell.common.pip.PipBoundsState;
import com.android.wm.shell.common.pip.PipPerfHintController;
import com.android.wm.shell.common.pip.PipPerfHintController;
import com.android.wm.shell.common.pip.PipSnapAlgorithm;
import com.android.wm.shell.common.pip.PipSnapAlgorithm;
import com.android.wm.shell.pip2.animation.PipResizeAnimator;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.shared.animation.PhysicsAnimator;
import com.android.wm.shell.shared.animation.PhysicsAnimator;


@@ -62,6 +66,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
        PipTransitionState.PipTransitionStateChangedListener {
        PipTransitionState.PipTransitionStateChangedListener {
    private static final String TAG = "PipMotionHelper";
    private static final String TAG = "PipMotionHelper";
    private static final String FLING_BOUNDS_CHANGE = "fling_bounds_change";
    private static final String FLING_BOUNDS_CHANGE = "fling_bounds_change";
    private static final String ANIMATING_BOUNDS_CHANGE = "animating_bounds_change";
    private static final boolean DEBUG = false;
    private static final boolean DEBUG = false;


    private static final int SHRINK_STACK_FROM_MENU_DURATION = 250;
    private static final int SHRINK_STACK_FROM_MENU_DURATION = 250;
@@ -113,7 +118,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,


    /** SpringConfig to use for fling-then-spring animations. */
    /** SpringConfig to use for fling-then-spring animations. */
    private final PhysicsAnimator.SpringConfig mSpringConfig =
    private final PhysicsAnimator.SpringConfig mSpringConfig =
            new PhysicsAnimator.SpringConfig(700f, DAMPING_RATIO_NO_BOUNCY);
            new PhysicsAnimator.SpringConfig(300f, DAMPING_RATIO_LOW_BOUNCY);


    /** SpringConfig used for animating into the dismiss region, matches the one in
    /** SpringConfig used for animating into the dismiss region, matches the one in
     * {@link MagnetizedObject}. */
     * {@link MagnetizedObject}. */
@@ -152,9 +157,16 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
    private boolean mDismissalPending = false;
    private boolean mDismissalPending = false;


    /**
    /**
     * Set to true if bounds change transition has been scheduled from PipMotionHelper.
     * Set to true if bounds change transition has been scheduled from PipMotionHelper
     * after animating is over.
     */
     */
    private boolean mWaitingForBoundsChangeTransition = false;
    private boolean mWaitingForFlingTransition = false;

    /**
     * Set to true if bounds change transition has been scheduled from PipMotionHelper,
     * and if the animation is supposed to run while transition is playing.
     */
    private boolean mWaitingToPlayBoundsChangeTransition = false;


    /**
    /**
     * Gets set in {@link #animateToExpandedState(Rect, Rect, Rect, Runnable)}, this callback is
     * Gets set in {@link #animateToExpandedState(Rect, Rect, Rect, Runnable)}, this callback is
@@ -634,6 +646,9 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
        // The physics animation ended, though we may not necessarily be done animating, such as
        // The physics animation ended, though we may not necessarily be done animating, such as
        // when we're still dragging after moving out of the magnetic target.
        // when we're still dragging after moving out of the magnetic target.
        if (!mDismissalPending && !mSpringingToTouch && !mMagnetizedPip.getObjectStuckToTarget()) {
        if (!mDismissalPending && !mSpringingToTouch && !mMagnetizedPip.getObjectStuckToTarget()) {
            // Update the earlier estimate on bounds we are animating towards, since physics
            // animator is non-deterministic.
            setAnimatingToBounds(mPipBoundsState.getMotionBoundsState().getBoundsInMotion());
            // do not schedule resize if PiP is dismissing, which may cause app re-open to
            // do not schedule resize if PiP is dismissing, which may cause app re-open to
            // mBounds instead of its normal bounds.
            // mBounds instead of its normal bounds.
            Bundle extra = new Bundle();
            Bundle extra = new Bundle();
@@ -673,6 +688,11 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
     * Directly resizes the PiP to the given {@param bounds}.
     * Directly resizes the PiP to the given {@param bounds}.
     */
     */
    private void resizeAndAnimatePipUnchecked(Rect toBounds, int duration) {
    private void resizeAndAnimatePipUnchecked(Rect toBounds, int duration) {
        if (mPipBoundsState.getMotionBoundsState().isInMotion()) {
            // Do not carry out any resizing if we are dragging or physics animator is running.
            return;
        }

        if (DEBUG) {
        if (DEBUG) {
            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: resizeAndAnimatePipUnchecked: toBounds=%s"
                    "%s: resizeAndAnimatePipUnchecked: toBounds=%s"
@@ -682,10 +702,11 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,


        // Intentionally resize here even if the current bounds match the destination bounds.
        // Intentionally resize here even if the current bounds match the destination bounds.
        // This is so all the proper callbacks are performed.
        // This is so all the proper callbacks are performed.

        setAnimatingToBounds(toBounds);
        // mPipTaskOrganizer.scheduleAnimateResizePip(toBounds, duration,
        Bundle extra = new Bundle();
        //         TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND, null /* updateBoundsCallback */);
        extra.putBoolean(ANIMATING_BOUNDS_CHANGE, true);
        // setAnimatingToBounds(toBounds);
        extra.putInt(ANIMATING_BOUNDS_CHANGE_DURATION, duration);
        mPipTransitionState.setState(PipTransitionState.SCHEDULED_BOUNDS_CHANGE, extra);
    }
    }


    @Override
    @Override
@@ -694,7 +715,11 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
            @Nullable Bundle extra) {
            @Nullable Bundle extra) {
        switch (newState) {
        switch (newState) {
            case PipTransitionState.SCHEDULED_BOUNDS_CHANGE:
            case PipTransitionState.SCHEDULED_BOUNDS_CHANGE:
                if (!extra.getBoolean(FLING_BOUNDS_CHANGE)) break;
                mWaitingForFlingTransition = extra.getBoolean(FLING_BOUNDS_CHANGE);
                mWaitingToPlayBoundsChangeTransition = extra.getBoolean(ANIMATING_BOUNDS_CHANGE);
                if (!mWaitingForFlingTransition && !mWaitingToPlayBoundsChangeTransition) {
                    break;
                }


                if (mPipBoundsState.getBounds().equals(
                if (mPipBoundsState.getBounds().equals(
                        mPipBoundsState.getMotionBoundsState().getBoundsInMotion())) {
                        mPipBoundsState.getMotionBoundsState().getBoundsInMotion())) {
@@ -709,20 +734,43 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
                    break;
                    break;
                }
                }


                // If touch is turned off and we are in a fling animation, schedule a transition.
                // Delay config until the end, if we are animating after scheduling the transition.
                mWaitingForBoundsChangeTransition = true;
                mPipScheduler.scheduleAnimateResizePip(
                mPipScheduler.scheduleAnimateResizePip(
                        mPipBoundsState.getMotionBoundsState().getBoundsInMotion());
                        mPipBoundsState.getMotionBoundsState().getAnimatingToBounds(),
                        mWaitingToPlayBoundsChangeTransition,
                        extra.getInt(ANIMATING_BOUNDS_CHANGE_DURATION,
                                PipTransition.BOUNDS_CHANGE_JUMPCUT_DURATION));
                break;
                break;
            case PipTransitionState.CHANGING_PIP_BOUNDS:
            case PipTransitionState.CHANGING_PIP_BOUNDS:
                if (!mWaitingForBoundsChangeTransition) break;

                // If bounds change transition was scheduled from this class, handle leash updates.
                mWaitingForBoundsChangeTransition = false;
                SurfaceControl.Transaction startTx = extra.getParcelable(
                SurfaceControl.Transaction startTx = extra.getParcelable(
                        PipTransition.PIP_START_TX, SurfaceControl.Transaction.class);
                        PipTransition.PIP_START_TX, SurfaceControl.Transaction.class);
                SurfaceControl.Transaction finishTx = extra.getParcelable(
                        PipTransition.PIP_FINISH_TX, SurfaceControl.Transaction.class);
                Rect destinationBounds = extra.getParcelable(
                Rect destinationBounds = extra.getParcelable(
                        PipTransition.PIP_DESTINATION_BOUNDS, Rect.class);
                        PipTransition.PIP_DESTINATION_BOUNDS, Rect.class);
                final int duration = extra.getInt(ANIMATING_BOUNDS_CHANGE_DURATION,
                        PipTransition.BOUNDS_CHANGE_JUMPCUT_DURATION);

                if (mWaitingForFlingTransition) {
                    mWaitingForFlingTransition = false;
                    handleFlingTransition(startTx, finishTx, destinationBounds);
                } else if (mWaitingToPlayBoundsChangeTransition) {
                    mWaitingToPlayBoundsChangeTransition = false;
                    startResizeAnimation(startTx, finishTx, destinationBounds, duration);
                }
                break;
            case PipTransitionState.EXITING_PIP:
                // We need to force finish any local animators if about to leave PiP, to avoid
                // breaking the state (e.g. leashes are cleaned up upon exit).
                if (!mPipBoundsState.getMotionBoundsState().isInMotion()) break;
                cancelPhysicsAnimation();
                settlePipBoundsAfterPhysicsAnimation(false /* animatingAfter */);
                break;
        }
    }

    private void handleFlingTransition(SurfaceControl.Transaction startTx,
            SurfaceControl.Transaction finishTx, Rect destinationBounds) {
        startTx.setPosition(mPipTransitionState.mPinnedTaskLeash,
        startTx.setPosition(mPipTransitionState.mPinnedTaskLeash,
                destinationBounds.left, destinationBounds.top);
                destinationBounds.left, destinationBounds.top);
        startTx.apply();
        startTx.apply();
@@ -733,14 +781,28 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,


        // Signal that the transition is done - should update transition state by default.
        // Signal that the transition is done - should update transition state by default.
        mPipScheduler.scheduleFinishResizePip(false /* configAtEnd */);
        mPipScheduler.scheduleFinishResizePip(false /* configAtEnd */);
                break;
            case PipTransitionState.EXITING_PIP:
                // We need to force finish any local animators if about to leave PiP, to avoid
                // breaking the state (e.g. leashes are cleaned up upon exit).
                if (!mPipBoundsState.getMotionBoundsState().isInMotion()) break;
                cancelPhysicsAnimation();
                settlePipBoundsAfterPhysicsAnimation(false /* animatingAfter */);
    }
    }

    private void startResizeAnimation(SurfaceControl.Transaction startTx,
            SurfaceControl.Transaction finishTx, Rect destinationBounds, int duration) {
        SurfaceControl pipLeash = mPipTransitionState.mPinnedTaskLeash;
        Preconditions.checkState(pipLeash != null,
                "No leash cached by mPipTransitionState=" + mPipTransitionState);

        startTx.setWindowCrop(pipLeash, mPipBoundsState.getBounds().width(),
                mPipBoundsState.getBounds().height());

        PipResizeAnimator animator = new PipResizeAnimator(mContext, pipLeash,
                startTx, finishTx, mPipBoundsState.getBounds(), mPipBoundsState.getBounds(),
                destinationBounds, duration, 0f /* angle */);
        animator.setAnimationEndCallback(() -> {
            mPipBoundsState.setBounds(destinationBounds);
            // All motion operations have actually finished, so make bounds cache updates.
            cleanUpHighPerfSessionMaybe();
            // Signal that we are done with resize transition
            mPipScheduler.scheduleFinishResizePip(true /* configAtEnd */);
        });
        animator.start();
    }
    }


    private void settlePipBoundsAfterPhysicsAnimation(boolean animatingAfter) {
    private void settlePipBoundsAfterPhysicsAnimation(boolean animatingAfter) {
+7 −2
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.wm.shell.pip2.phone;
package com.android.wm.shell.pip2.phone;


import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_NONE;
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_NONE;
import static com.android.wm.shell.pip2.phone.PipTransition.ANIMATING_BOUNDS_CHANGE_DURATION;


import android.annotation.Nullable;
import android.annotation.Nullable;
import android.content.Context;
import android.content.Context;
@@ -535,7 +536,8 @@ public class PipResizeGestureHandler implements
                mWaitingForBoundsChangeTransition = true;
                mWaitingForBoundsChangeTransition = true;


                // Schedule PiP resize transition, but delay any config updates until very end.
                // Schedule PiP resize transition, but delay any config updates until very end.
                mPipScheduler.scheduleAnimateResizePip(mLastResizeBounds, true /* configAtEnd */);
                mPipScheduler.scheduleAnimateResizePip(mLastResizeBounds,
                        true /* configAtEnd */, PINCH_RESIZE_SNAP_DURATION);
                break;
                break;
            case PipTransitionState.CHANGING_PIP_BOUNDS:
            case PipTransitionState.CHANGING_PIP_BOUNDS:
                if (!mWaitingForBoundsChangeTransition) break;
                if (!mWaitingForBoundsChangeTransition) break;
@@ -550,12 +552,15 @@ public class PipResizeGestureHandler implements
                        PipTransition.PIP_START_TX, SurfaceControl.Transaction.class);
                        PipTransition.PIP_START_TX, SurfaceControl.Transaction.class);
                SurfaceControl.Transaction finishTx = extra.getParcelable(
                SurfaceControl.Transaction finishTx = extra.getParcelable(
                        PipTransition.PIP_FINISH_TX, SurfaceControl.Transaction.class);
                        PipTransition.PIP_FINISH_TX, SurfaceControl.Transaction.class);
                final int duration = extra.getInt(ANIMATING_BOUNDS_CHANGE_DURATION,
                        PipTransition.BOUNDS_CHANGE_JUMPCUT_DURATION);

                startTx.setWindowCrop(pipLeash, mPipBoundsState.getBounds().width(),
                startTx.setWindowCrop(pipLeash, mPipBoundsState.getBounds().width(),
                        mPipBoundsState.getBounds().height());
                        mPipBoundsState.getBounds().height());


                PipResizeAnimator animator = new PipResizeAnimator(mContext, pipLeash,
                PipResizeAnimator animator = new PipResizeAnimator(mContext, pipLeash,
                        startTx, finishTx, mPipBoundsState.getBounds(), mStartBoundsAfterRelease,
                        startTx, finishTx, mPipBoundsState.getBounds(), mStartBoundsAfterRelease,
                        mLastResizeBounds, PINCH_RESIZE_SNAP_DURATION, mAngle);
                        mLastResizeBounds, duration, mAngle);
                animator.setAnimationEndCallback(() -> {
                animator.setAnimationEndCallback(() -> {
                    // All motion operations have actually finished, so make bounds cache updates.
                    // All motion operations have actually finished, so make bounds cache updates.
                    mUpdateResizeBoundsCallback.accept(mLastResizeBounds);
                    mUpdateResizeBoundsCallback.accept(mLastResizeBounds);
Loading