diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index a9daceefbb..0ebaea2234 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -45,8 +45,6 @@ import static com.android.quickstep.GestureState.STATE_END_TARGET_SET; import static com.android.quickstep.GestureState.STATE_RECENTS_SCROLLING_FINISHED; import static com.android.quickstep.MultiStateCallback.DEBUG_STATES; import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE; -import static com.android.quickstep.util.SwipePipToHomeAnimator.FRACTION_END; -import static com.android.quickstep.util.SwipePipToHomeAnimator.FRACTION_START; import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD; import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME; @@ -248,7 +246,6 @@ public abstract class AbsSwipeUpHandler, private final Runnable mOnDeferredActivityLaunch = this::onDeferredActivityLaunch; - private static final long SWIPE_PIP_TO_HOME_DURATION = 425; private SwipePipToHomeAnimator mSwipePipToHomeAnimator; protected boolean mIsSwipingPipToHome; @@ -1134,17 +1131,14 @@ public abstract class AbsSwipeUpHandler, createHomeAnimationFactory(cookies, duration, isTranslucent, appCanEnterPip, runningTaskTarget); mIsSwipingPipToHome = homeAnimFactory.supportSwipePipToHome() && appCanEnterPip; + final RectFSpringAnim windowAnim; if (mIsSwipingPipToHome) { - mSwipePipToHomeAnimator = getSwipePipToHomeAnimator( + mSwipePipToHomeAnimator = createWindowAnimationToPip( homeAnimFactory, runningTaskTarget, start); - mSwipePipToHomeAnimator.setDuration(SWIPE_PIP_TO_HOME_DURATION); - mSwipePipToHomeAnimator.setInterpolator(interpolator); - mSwipePipToHomeAnimator.setFloatValues(FRACTION_START, FRACTION_END); - mSwipePipToHomeAnimator.start(); - mRunningWindowAnim = RunningWindowAnim.wrap(mSwipePipToHomeAnimator); + windowAnim = mSwipePipToHomeAnimator; } else { mSwipePipToHomeAnimator = null; - RectFSpringAnim windowAnim = createWindowAnimationToHome(start, homeAnimFactory); + windowAnim = createWindowAnimationToHome(start, homeAnimFactory); windowAnim.addAnimatorListener(new AnimationSuccessListener() { @Override public void onAnimationSuccess(Animator animator) { @@ -1158,9 +1152,9 @@ public abstract class AbsSwipeUpHandler, mGestureState.setState(STATE_END_TARGET_ANIMATION_FINISHED); } }); - windowAnim.start(mContext, velocityPxPerMs); - mRunningWindowAnim = RunningWindowAnim.wrap(windowAnim); } + windowAnim.start(mContext, velocityPxPerMs); + mRunningWindowAnim = RunningWindowAnim.wrap(windowAnim); homeAnimFactory.setSwipeVelocity(velocityPxPerMs.y); homeAnimFactory.playAtomicAnimation(velocityPxPerMs.y); mLauncherTransitionController = null; @@ -1216,7 +1210,7 @@ public abstract class AbsSwipeUpHandler, } } - private SwipePipToHomeAnimator getSwipePipToHomeAnimator(HomeAnimationFactory homeAnimFactory, + private SwipePipToHomeAnimator createWindowAnimationToPip(HomeAnimationFactory homeAnimFactory, RemoteAnimationTargetCompat runningTaskTarget, float startProgress) { // Directly animate the app to PiP (picture-in-picture) mode final ActivityManager.RunningTaskInfo taskInfo = mGestureState.getRunningTask(); @@ -1229,16 +1223,15 @@ public abstract class AbsSwipeUpHandler, runningTaskTarget.taskInfo.pictureInPictureParams, homeRotation, mDp.hotseatBarSizePx); - final Rect startBounds = new Rect(); - updateProgressForStartRect(new Matrix(), startProgress).round(startBounds); final SwipePipToHomeAnimator swipePipToHomeAnimator = new SwipePipToHomeAnimator( + mContext, runningTaskTarget.taskId, taskInfo.topActivity, runningTaskTarget.leash.getSurfaceControl(), TaskInfoCompat.getPipSourceRectHint( runningTaskTarget.taskInfo.pictureInPictureParams), TaskInfoCompat.getWindowConfigurationBounds(taskInfo), - startBounds, + updateProgressForStartRect(new Matrix(), startProgress), destinationBounds, mRecentsView.getPipCornerRadius(), mRecentsView); @@ -1250,7 +1243,7 @@ public abstract class AbsSwipeUpHandler, } AnimatorPlaybackController activityAnimationToHome = homeAnimFactory.createActivityAnimationToHome(); - swipePipToHomeAnimator.addListener(new AnimatorListenerAdapter() { + swipePipToHomeAnimator.addAnimatorListener(new AnimatorListenerAdapter() { private boolean mHasAnimationEnded; @Override public void onAnimationStart(Animator animation) { diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java index 61a2eafe6d..67a635b70b 100644 --- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java +++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java @@ -20,8 +20,8 @@ import static com.android.systemui.shared.system.InteractionJankMonitorWrapper.C import android.animation.Animator; import android.animation.RectEvaluator; -import android.animation.ValueAnimator; import android.content.ComponentName; +import android.content.Context; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Rect; @@ -44,30 +44,24 @@ import com.android.systemui.shared.pip.PipSurfaceTransactionHelper; import com.android.systemui.shared.system.InteractionJankMonitorWrapper; /** - * An {@link Animator} that animates an Activity to PiP (picture-in-picture) window when - * swiping up (in gesture navigation mode). Note that this class is derived from - * {@link com.android.wm.shell.pip.PipAnimationController.PipTransitionAnimator}. - * - * TODO: consider sharing this class including the animator and leash operations between - * Launcher and SysUI. Also, there should be one source of truth for the corner radius of the - * PiP window, which would ideally be on SysUI side as well. + * Subclass of {@link RectFSpringAnim} that animates an Activity to PiP (picture-in-picture) window + * when swiping up (in gesture navigation mode). */ -public class SwipePipToHomeAnimator extends ValueAnimator { +public class SwipePipToHomeAnimator extends RectFSpringAnim { private static final String TAG = SwipePipToHomeAnimator.class.getSimpleName(); - public static final float FRACTION_START = 0f; - public static final float FRACTION_END = 1f; + private static final float END_PROGRESS = 1.0f; private final int mTaskId; private final ComponentName mComponentName; private final SurfaceControl mLeash; private final Rect mAppBounds = new Rect(); private final Rect mStartBounds = new Rect(); + private final Rect mCurrentBounds = new Rect(); private final Rect mDestinationBounds = new Rect(); private final PipSurfaceTransactionHelper mSurfaceTransactionHelper; - /** for calculating the transform in {@link #onAnimationUpdate(ValueAnimator)} */ - private final RectEvaluator mRectEvaluator = new RectEvaluator(new Rect()); + /** for calculating transform in {@link #onAnimationUpdate(AppCloseConfig, RectF, float)} */ private final RectEvaluator mInsetsEvaluator = new RectEvaluator(new Rect()); private final Rect mSourceHintRectInsets; private final Rect mSourceInsets = new Rect(); @@ -90,6 +84,7 @@ public class SwipePipToHomeAnimator extends ValueAnimator { private SurfaceControl mContentOverlay; /** + * @param context {@link Context} provides Launcher resources * @param taskId Task id associated with this animator, see also {@link #getTaskId()} * @param componentName Component associated with this animator, * see also {@link #getComponentName()} @@ -102,20 +97,22 @@ public class SwipePipToHomeAnimator extends ValueAnimator { * @param destinationBounds Bounds of the destination this animator ends to * @param cornerRadius Corner radius in pixel value for PiP window */ - public SwipePipToHomeAnimator(int taskId, + public SwipePipToHomeAnimator(@NonNull Context context, + int taskId, @NonNull ComponentName componentName, @NonNull SurfaceControl leash, @Nullable Rect sourceRectHint, @NonNull Rect appBounds, - @NonNull Rect startBounds, + @NonNull RectF startBounds, @NonNull Rect destinationBounds, int cornerRadius, @NonNull View view) { + super(startBounds, new RectF(destinationBounds), context); mTaskId = taskId; mComponentName = componentName; mLeash = leash; mAppBounds.set(appBounds); - mStartBounds.set(startBounds); + startBounds.round(mStartBounds); mDestinationBounds.set(destinationBounds); mDestinationBoundsTransformed.set(mDestinationBounds); mDestinationBoundsAnimation.set(mDestinationBounds); @@ -151,10 +148,10 @@ public class SwipePipToHomeAnimator extends ValueAnimator { t.reparent(mContentOverlay, mLeash); t.apply(); - addUpdateListener(valueAnimator -> { - float alpha = valueAnimator.getAnimatedFraction() < 0.5f + addOnUpdateListener((values, currentRect, progress) -> { + float alpha = progress < 0.5f ? 0 - : Utilities.mapToRange(valueAnimator.getAnimatedFraction(), 0.5f, 1f, + : Utilities.mapToRange(Math.min(progress, 1f), 0.5f, 1f, 0f, 1f, Interpolators.FAST_OUT_SLOW_IN); t.setAlpha(mContentOverlay, alpha); t.apply(); @@ -166,7 +163,7 @@ public class SwipePipToHomeAnimator extends ValueAnimator { appBounds.bottom - sourceRectHint.bottom); } - addListener(new AnimationSuccessListener() { + addAnimatorListener(new AnimationSuccessListener() { @Override public void onAnimationStart(Animator animation) { InteractionJankMonitorWrapper.begin(view, CUJ_APP_CLOSE_TO_PIP); @@ -191,7 +188,7 @@ public class SwipePipToHomeAnimator extends ValueAnimator { mHasAnimationEnded = true; } }); - addUpdateListener(this::onAnimationUpdate); + addOnUpdateListener(this::onAnimationUpdate); } /** sets the from rotation if it's different from the target rotation. */ @@ -219,34 +216,34 @@ public class SwipePipToHomeAnimator extends ValueAnimator { mAppBounds.top + mDestinationBounds.height()); } - private void onAnimationUpdate(ValueAnimator animator) { + private void onAnimationUpdate(@Nullable AppCloseConfig values, RectF currentRect, + float progress) { if (mHasAnimationEnded) return; final SurfaceControl.Transaction tx = PipSurfaceTransactionHelper.newSurfaceControlTransaction(); - onAnimationUpdate(tx, animator.getAnimatedFraction()); + onAnimationUpdate(tx, currentRect, progress); tx.apply(); } private PictureInPictureSurfaceTransaction onAnimationUpdate(SurfaceControl.Transaction tx, - float fraction) { - final Rect bounds = mRectEvaluator.evaluate(fraction, mStartBounds, - mDestinationBoundsAnimation); + RectF currentRect, float progress) { + currentRect.round(mCurrentBounds); final PictureInPictureSurfaceTransaction op; if (mSourceHintRectInsets == null) { // no source rect hint been set, directly scale the window down - op = onAnimationScale(fraction, tx, bounds); + op = onAnimationScale(progress, tx, mCurrentBounds); } else { // scale and crop according to the source rect hint - op = onAnimationScaleAndCrop(fraction, tx, bounds); + op = onAnimationScaleAndCrop(progress, tx, mCurrentBounds); } return op; } /** scale the window directly with no source rect hint being set */ private PictureInPictureSurfaceTransaction onAnimationScale( - float fraction, SurfaceControl.Transaction tx, Rect bounds) { + float progress, SurfaceControl.Transaction tx, Rect bounds) { if (mFromRotation == Surface.ROTATION_90 || mFromRotation == Surface.ROTATION_270) { - final RotatedPosition rotatedPosition = getRotatedPosition(fraction); + final RotatedPosition rotatedPosition = getRotatedPosition(progress); return mSurfaceTransactionHelper.scale(tx, mLeash, mAppBounds, bounds, rotatedPosition.degree, rotatedPosition.positionX, rotatedPosition.positionY); } else { @@ -256,12 +253,12 @@ public class SwipePipToHomeAnimator extends ValueAnimator { /** scale and crop the window with source rect hint */ private PictureInPictureSurfaceTransaction onAnimationScaleAndCrop( - float fraction, SurfaceControl.Transaction tx, + float progress, SurfaceControl.Transaction tx, Rect bounds) { - final Rect insets = mInsetsEvaluator.evaluate(fraction, mSourceInsets, + final Rect insets = mInsetsEvaluator.evaluate(progress, mSourceInsets, mSourceHintRectInsets); if (mFromRotation == Surface.ROTATION_90 || mFromRotation == Surface.ROTATION_270) { - final RotatedPosition rotatedPosition = getRotatedPosition(fraction); + final RotatedPosition rotatedPosition = getRotatedPosition(progress); return mSurfaceTransactionHelper.scaleAndRotate(tx, mLeash, mAppBounds, bounds, insets, rotatedPosition.degree, rotatedPosition.positionX, rotatedPosition.positionY); } else { @@ -291,22 +288,22 @@ public class SwipePipToHomeAnimator extends ValueAnimator { // get the final leash operations but do not apply to the leash. final SurfaceControl.Transaction tx = PipSurfaceTransactionHelper.newSurfaceControlTransaction(); - return onAnimationUpdate(tx, FRACTION_END); + return onAnimationUpdate(tx, new RectF(mDestinationBounds), END_PROGRESS); } - private RotatedPosition getRotatedPosition(float fraction) { + private RotatedPosition getRotatedPosition(float progress) { final float degree, positionX, positionY; if (mFromRotation == Surface.ROTATION_90) { - degree = -90 * fraction; - positionX = fraction * (mDestinationBoundsTransformed.left - mStartBounds.left) + degree = -90 * progress; + positionX = progress * (mDestinationBoundsTransformed.left - mStartBounds.left) + mStartBounds.left; - positionY = fraction * (mDestinationBoundsTransformed.bottom - mStartBounds.top) + positionY = progress * (mDestinationBoundsTransformed.bottom - mStartBounds.top) + mStartBounds.top; } else { - degree = 90 * fraction; - positionX = fraction * (mDestinationBoundsTransformed.right - mStartBounds.left) + degree = 90 * progress; + positionX = progress * (mDestinationBoundsTransformed.right - mStartBounds.left) + mStartBounds.left; - positionY = fraction * (mDestinationBoundsTransformed.top - mStartBounds.top) + positionY = progress * (mDestinationBoundsTransformed.top - mStartBounds.top) + mStartBounds.top; } return new RotatedPosition(degree, positionX, positionY);