diff options
9 files changed, 163 insertions, 57 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java index ccbe94c4c780..8d36db97c511 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java @@ -127,8 +127,10 @@ public abstract class PipTransitionController implements Transitions.TransitionH /** * 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. } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipResizeAnimator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipResizeAnimator.java index 5c561fed89c7..88f9e4c740e3 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipResizeAnimator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipResizeAnimator.java @@ -47,9 +47,17 @@ public class PipResizeAnimator extends ValueAnimator @Nullable private Runnable mAnimationEndCallback; private RectEvaluator mRectEvaluator; + + // Bounds relative to which scaling/cropping must be done. private final Rect mBaseBounds = new Rect(); + + // Bounds to animate from. private final Rect mStartBounds = new Rect(); + + // Target bounds. private final Rect mEndBounds = new Rect(); + + // Bounds updated by the evaluator as animator is running. private final Rect mAnimatedRect = new Rect(); private final float mDelta; @@ -84,7 +92,6 @@ public class PipResizeAnimator extends ValueAnimator addListener(this); addUpdateListener(this); setEvaluator(mRectEvaluator); - // TODO: change this setDuration(duration); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java index 68202ef642c4..06adad626e9f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java @@ -352,6 +352,7 @@ public class PipController implements ConfigurationChangeListener, mPipBoundsAlgorithm.dump(pw, innerPrefix); mPipBoundsState.dump(pw, innerPrefix); mPipDisplayLayoutState.dump(pw, innerPrefix); + mPipTransitionState.dump(pw, innerPrefix); } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java index cec246923e2c..e277a8dbeb13 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java @@ -16,6 +16,7 @@ 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.STIFFNESS_LOW; 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.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.PipTransition.ANIMATING_BOUNDS_CHANGE_DURATION; import android.annotation.NonNull; import android.annotation.Nullable; @@ -36,6 +38,7 @@ import android.os.Debug; import android.view.SurfaceControl; import com.android.internal.protolog.ProtoLog; +import com.android.internal.util.Preconditions; import com.android.wm.shell.R; import com.android.wm.shell.animation.FloatProperties; 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.PipPerfHintController; 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.shared.animation.PhysicsAnimator; @@ -62,6 +66,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, PipTransitionState.PipTransitionStateChangedListener { private static final String TAG = "PipMotionHelper"; 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 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. */ 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 * {@link MagnetizedObject}. */ @@ -152,9 +157,16 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, 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 @@ -634,6 +646,9 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, // 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. 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 // mBounds instead of its normal bounds. Bundle extra = new Bundle(); @@ -673,6 +688,11 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, * Directly resizes the PiP to the given {@param bounds}. */ 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) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%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. // This is so all the proper callbacks are performed. - - // mPipTaskOrganizer.scheduleAnimateResizePip(toBounds, duration, - // TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND, null /* updateBoundsCallback */); - // setAnimatingToBounds(toBounds); + setAnimatingToBounds(toBounds); + Bundle extra = new Bundle(); + extra.putBoolean(ANIMATING_BOUNDS_CHANGE, true); + extra.putInt(ANIMATING_BOUNDS_CHANGE_DURATION, duration); + mPipTransitionState.setState(PipTransitionState.SCHEDULED_BOUNDS_CHANGE, extra); } @Override @@ -694,7 +715,11 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, @Nullable Bundle extra) { switch (newState) { 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( mPipBoundsState.getMotionBoundsState().getBoundsInMotion())) { @@ -709,30 +734,30 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, break; } - // If touch is turned off and we are in a fling animation, schedule a transition. - mWaitingForBoundsChangeTransition = true; + // Delay config until the end, if we are animating after scheduling the transition. mPipScheduler.scheduleAnimateResizePip( - mPipBoundsState.getMotionBoundsState().getBoundsInMotion()); + mPipBoundsState.getMotionBoundsState().getAnimatingToBounds(), + mWaitingToPlayBoundsChangeTransition, + extra.getInt(ANIMATING_BOUNDS_CHANGE_DURATION, + PipTransition.BOUNDS_CHANGE_JUMPCUT_DURATION)); break; 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( PipTransition.PIP_START_TX, SurfaceControl.Transaction.class); + SurfaceControl.Transaction finishTx = extra.getParcelable( + PipTransition.PIP_FINISH_TX, SurfaceControl.Transaction.class); Rect destinationBounds = extra.getParcelable( PipTransition.PIP_DESTINATION_BOUNDS, Rect.class); - startTx.setPosition(mPipTransitionState.mPinnedTaskLeash, - destinationBounds.left, destinationBounds.top); - startTx.apply(); - - // All motion operations have actually finished, so make bounds cache updates. - settlePipBoundsAfterPhysicsAnimation(false /* animatingAfter */); - cleanUpHighPerfSessionMaybe(); - - // Signal that the transition is done - should update transition state by default. - mPipScheduler.scheduleFinishResizePip(false /* configAtEnd */); + 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 @@ -740,9 +765,46 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, 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, + destinationBounds.left, destinationBounds.top); + startTx.apply(); + + // All motion operations have actually finished, so make bounds cache updates. + settlePipBoundsAfterPhysicsAnimation(false /* animatingAfter */); + cleanUpHighPerfSessionMaybe(); + + // Signal that the transition is done - should update transition state by default. + mPipScheduler.scheduleFinishResizePip(false /* configAtEnd */); + } + + 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) { if (!animatingAfter) { // The physics animation ended, though we may not necessarily be done animating, such as diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java index 33e80bd80988..5b0ca1837a1c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java @@ -16,6 +16,7 @@ package com.android.wm.shell.pip2.phone; 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.content.Context; @@ -535,7 +536,8 @@ public class PipResizeGestureHandler implements mWaitingForBoundsChangeTransition = true; // 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; case PipTransitionState.CHANGING_PIP_BOUNDS: if (!mWaitingForBoundsChangeTransition) break; @@ -550,12 +552,15 @@ public class PipResizeGestureHandler implements PipTransition.PIP_START_TX, SurfaceControl.Transaction.class); SurfaceControl.Transaction finishTx = extra.getParcelable( 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(), mPipBoundsState.getBounds().height()); PipResizeAnimator animator = new PipResizeAnimator(mContext, pipLeash, startTx, finishTx, mPipBoundsState.getBounds(), mStartBoundsAfterRelease, - mLastResizeBounds, PINCH_RESIZE_SNAP_DURATION, mAngle); + mLastResizeBounds, duration, mAngle); animator.setAnimationEndCallback(() -> { // All motion operations have actually finished, so make bounds cache updates. mUpdateResizeBoundsCallback.accept(mLastResizeBounds); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java index 4f62192eaf5b..ac670cf3f828 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java @@ -162,6 +162,18 @@ public class PipScheduler { * @param configAtEnd true if we are delaying config updates until the transition ends. */ public void scheduleAnimateResizePip(Rect toBounds, boolean configAtEnd) { + scheduleAnimateResizePip(toBounds, configAtEnd, + PipTransition.BOUNDS_CHANGE_JUMPCUT_DURATION); + } + + /** + * Animates resizing of the pinned stack given the duration. + * + * @param configAtEnd true if we are delaying config updates until the transition ends. + * @param duration the suggested duration to run the animation; the component responsible + * for running the animator will get this as an extra. + */ + public void scheduleAnimateResizePip(Rect toBounds, boolean configAtEnd, int duration) { if (mPipTransitionState.mPipTaskToken == null || !mPipTransitionState.isInPip()) { return; } @@ -170,7 +182,7 @@ public class PipScheduler { if (configAtEnd) { wct.deferConfigToTransitionEnd(mPipTransitionState.mPipTaskToken); } - mPipTransitionController.startResizeTransition(wct); + mPipTransitionController.startResizeTransition(wct, duration); } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java index a9f3b54006d9..0c4ed268fd28 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java @@ -713,15 +713,13 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha } } - private void animateToMaximizedState(Runnable callback) { - Rect maxMovementBounds = new Rect(); + private void animateToMaximizedState() { Rect maxBounds = new Rect(0, 0, mPipBoundsState.getMaxSize().x, mPipBoundsState.getMaxSize().y); - mPipBoundsAlgorithm.getMovementBounds(maxBounds, mInsetBounds, maxMovementBounds, - mIsImeShowing ? mImeHeight : 0); + mSavedSnapFraction = mMotionHelper.animateToExpandedState(maxBounds, - mPipBoundsState.getMovementBounds(), maxMovementBounds, - callback); + getMovementBounds(mPipBoundsState.getBounds()), + getMovementBounds(maxBounds), null /* callback */); } private void animateToNormalSize(Runnable callback) { @@ -729,22 +727,20 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds()); final Size minMenuSize = mMenuController.getEstimatedMinMenuSize(); - final Rect normalBounds = mPipBoundsState.getNormalBounds(); - final Rect destBounds = mPipBoundsAlgorithm.adjustNormalBoundsToFitMenu(normalBounds, - minMenuSize); - Rect restoredMovementBounds = new Rect(); - mPipBoundsAlgorithm.getMovementBounds(destBounds, - mInsetBounds, restoredMovementBounds, mIsImeShowing ? mImeHeight : 0); - mSavedSnapFraction = mMotionHelper.animateToExpandedState(destBounds, - mPipBoundsState.getMovementBounds(), restoredMovementBounds, callback); + final Size defaultSize = mSizeSpecSource.getDefaultSize(mPipBoundsState.getAspectRatio()); + final Rect normalBounds = new Rect(0, 0, defaultSize.getWidth(), defaultSize.getHeight()); + final Rect adjustedNormalBounds = mPipBoundsAlgorithm.adjustNormalBoundsToFitMenu( + normalBounds, minMenuSize); + + mSavedSnapFraction = mMotionHelper.animateToExpandedState(adjustedNormalBounds, + getMovementBounds(mPipBoundsState.getBounds()), + getMovementBounds(adjustedNormalBounds), callback /* callback */); } private void animateToUnexpandedState(Rect restoreBounds) { - Rect restoredMovementBounds = new Rect(); - mPipBoundsAlgorithm.getMovementBounds(restoreBounds, - mInsetBounds, restoredMovementBounds, mIsImeShowing ? mImeHeight : 0); mMotionHelper.animateToUnexpandedState(restoreBounds, mSavedSnapFraction, - restoredMovementBounds, mPipBoundsState.getMovementBounds(), false /* immediate */); + getMovementBounds(restoreBounds), + getMovementBounds(mPipBoundsState.getBounds()), false /* immediate */); mSavedSnapFraction = -1f; } @@ -919,10 +915,6 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha && mMenuState != MENU_STATE_FULL) { // If using pinch to zoom, double-tap functions as resizing between max/min size if (mPipResizeGestureHandler.isUsingPinchToZoom()) { - final boolean toExpand = mPipBoundsState.getBounds().width() - < mPipBoundsState.getMaxSize().x - && mPipBoundsState.getBounds().height() - < mPipBoundsState.getMaxSize().y; if (mMenuController.isMenuVisible()) { mMenuController.hideMenu(ANIM_TYPE_NONE, false /* resize */); } @@ -934,7 +926,7 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha // actually toggle to the size chosen if (nextSize == PipDoubleTapHelper.SIZE_SPEC_MAX) { mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds()); - animateToMaximizedState(null); + animateToMaximizedState(); } else if (nextSize == PipDoubleTapHelper.SIZE_SPEC_DEFAULT) { mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds()); animateToNormalSize(null); @@ -1045,7 +1037,9 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha private Rect getMovementBounds(Rect curBounds) { Rect movementBounds = new Rect(); - mPipBoundsAlgorithm.getMovementBounds(curBounds, mInsetBounds, + Rect insetBounds = new Rect(); + mPipBoundsAlgorithm.getInsetBounds(insetBounds); + mPipBoundsAlgorithm.getMovementBounds(curBounds, insetBounds, movementBounds, mIsImeShowing ? mImeHeight : 0); return movementBounds; } @@ -1091,6 +1085,7 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha case PipTransitionState.ENTERED_PIP: onActivityPinned(); mTouchState.setAllowInputEvents(true); + mTouchState.reset(); break; case PipTransitionState.EXITED_PIP: mTouchState.setAllowInputEvents(false); @@ -1101,6 +1096,7 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha break; case PipTransitionState.CHANGED_PIP_BOUNDS: mTouchState.setAllowInputEvents(true); + mTouchState.reset(); break; } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java index 57dc5f92b2b6..683d30d59b33 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java @@ -71,6 +71,9 @@ public class PipTransition extends PipTransitionController implements static final String PIP_START_TX = "pip_start_tx"; static final String PIP_FINISH_TX = "pip_finish_tx"; static final String PIP_DESTINATION_BOUNDS = "pip_dest_bounds"; + static final String ANIMATING_BOUNDS_CHANGE_DURATION = + "animating_bounds_change_duration"; + static final int BOUNDS_CHANGE_JUMPCUT_DURATION = 0; /** * The fixed start delay in ms when fading out the content overlay from bounds animation. @@ -87,7 +90,7 @@ public class PipTransition extends PipTransitionController implements private final PipTransitionState mPipTransitionState; // - // Transition tokens + // Transition caches // @Nullable @@ -96,6 +99,8 @@ public class PipTransition extends PipTransitionController implements private IBinder mExitViaExpandTransition; @Nullable private IBinder mResizeTransition; + private int mBoundsChangeDuration = BOUNDS_CHANGE_JUMPCUT_DURATION; + // // Internal state and relevant cached info @@ -152,11 +157,12 @@ public class PipTransition extends PipTransitionController implements } @Override - public void startResizeTransition(WindowContainerTransaction wct) { + public void startResizeTransition(WindowContainerTransaction wct, int duration) { if (wct == null) { return; } mResizeTransition = mTransitions.startTransition(TRANSIT_RESIZE_PIP, wct, this); + mBoundsChangeDuration = duration; } @Nullable @@ -272,6 +278,10 @@ public class PipTransition extends PipTransitionController implements extra.putParcelable(PIP_START_TX, startTransaction); extra.putParcelable(PIP_FINISH_TX, finishTransaction); extra.putParcelable(PIP_DESTINATION_BOUNDS, pipChange.getEndAbsBounds()); + if (mBoundsChangeDuration > BOUNDS_CHANGE_JUMPCUT_DURATION) { + extra.putInt(ANIMATING_BOUNDS_CHANGE_DURATION, mBoundsChangeDuration); + mBoundsChangeDuration = BOUNDS_CHANGE_JUMPCUT_DURATION; + } mFinishCallback = finishCallback; mPipTransitionState.setState(PipTransitionState.CHANGING_PIP_BOUNDS, extra); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransitionState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransitionState.java index 9d599caf13dd..29272be6e9bd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransitionState.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransitionState.java @@ -29,6 +29,7 @@ import androidx.annotation.Nullable; import com.android.internal.util.Preconditions; import com.android.wm.shell.shared.annotations.ShellMainThread; +import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -62,6 +63,8 @@ import java.util.List; * and throw an <code>IllegalStateException</code> otherwise.</p> */ public class PipTransitionState { + private static final String TAG = PipTransitionState.class.getSimpleName(); + public static final int UNDEFINED = 0; // State for Launcher animating the swipe PiP to home animation. @@ -190,8 +193,9 @@ public class PipTransitionState { "No extra bundle for " + stateToString(state) + " state."); } if (mState != state) { - dispatchPipTransitionStateChanged(mState, state, extra); + final int prevState = mState; mState = state; + dispatchPipTransitionStateChanged(prevState, mState, extra); } } @@ -319,4 +323,11 @@ public class PipTransitionState { return String.format("PipTransitionState(mState=%s, mInSwipePipToHomeTransition=%b)", stateToString(mState), mInSwipePipToHomeTransition); } + + /** Dumps internal state. */ + public void dump(PrintWriter pw, String prefix) { + final String innerPrefix = prefix + " "; + pw.println(prefix + TAG); + pw.println(innerPrefix + "mState=" + stateToString(mState)); + } } |