Loading libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java +72 −1 Original line number Diff line number Diff line Loading @@ -16,12 +16,15 @@ package com.android.wm.shell.back; import static android.view.MotionEvent.ACTION_MOVE; import static android.view.RemoteAnimationTarget.MODE_CLOSING; import static android.view.RemoteAnimationTarget.MODE_OPENING; import static android.window.BackEvent.EDGE_RIGHT; import static com.android.internal.jank.InteractionJankMonitor.CUJ_PREDICTIVE_BACK_CROSS_TASK; import static com.android.window.flags.Flags.predictiveBackTimestampApi; import static com.android.wm.shell.back.BackAnimationConstants.UPDATE_SYSUI_FLAGS_THRESHOLD; import static com.android.wm.shell.back.CrossActivityBackAnimationKt.scaleCentered; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW; import android.animation.Animator; Loading @@ -36,11 +39,14 @@ import android.graphics.Rect; import android.graphics.RectF; import android.os.Handler; import android.os.RemoteException; import android.util.TimeUtils; import android.view.Choreographer; import android.view.IRemoteAnimationFinishedCallback; import android.view.IRemoteAnimationRunner; import android.view.MotionEvent; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import android.view.VelocityTracker; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import android.window.BackEvent; Loading @@ -48,6 +54,9 @@ import android.window.BackMotionEvent; import android.window.BackProgressAnimator; import android.window.IOnBackInvokedCallback; import com.android.internal.dynamicanimation.animation.FloatValueHolder; import com.android.internal.dynamicanimation.animation.SpringAnimation; import com.android.internal.dynamicanimation.animation.SpringForce; import com.android.internal.policy.ScreenDecorationsUtils; import com.android.internal.policy.SystemBarUtils; import com.android.internal.protolog.ProtoLog; Loading Loading @@ -81,6 +90,11 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { /** Duration of post animation after gesture committed. */ private static final int POST_ANIMATION_DURATION_MS = 500; private static final float SPRING_SCALE = 100f; private static final float DEFAULT_FLING_VELOCITY = 320f; private static final float MAX_FLING_VELOCITY = 1000f; private static final float FLING_SPRING_STIFFNESS = 320f; private final Rect mStartTaskRect = new Rect(); private float mCornerRadius; private int mStatusbarHeight; Loading Loading @@ -114,6 +128,14 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { private float mInterWindowMargin; private float mVerticalMargin; private final FloatValueHolder mPostCommitFlingScale = new FloatValueHolder(SPRING_SCALE); private final SpringForce mPostCommitFlingSpring = new SpringForce(SPRING_SCALE) .setStiffness(FLING_SPRING_STIFFNESS) .setDampingRatio(1f); private final VelocityTracker mVelocityTracker = VelocityTracker.obtain(); private float mGestureProgress = 0f; private long mDownTime = 0L; @Inject public CrossTaskBackAnimation(Context context, BackAnimationBackground background, @ShellMainThread Handler handler) { Loading Loading @@ -168,6 +190,7 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { if (mEnteringTarget == null || mClosingTarget == null) { return; } mGestureProgress = progress; float touchY = event.getTouchY(); Loading Loading @@ -229,6 +252,8 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { } mClosingCurrentRect.set(left, top, left + width, top + height); applyFlingScale(mClosingCurrentRect); applyTransform(mClosingTarget.leash, mClosingCurrentRect, mCornerRadius); } Loading @@ -239,9 +264,19 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { float height = mapRange(progress, mEnteringStartRect.height(), mStartTaskRect.height()); mEnteringCurrentRect.set(left, top, left + width, top + height); applyFlingScale(mEnteringCurrentRect); applyTransform(mEnteringTarget.leash, mEnteringCurrentRect, mCornerRadius); } private void applyFlingScale(RectF rect) { // apply a scale to the rect to account for fling velocity final float flingScale = Math.min(mPostCommitFlingScale.getValue() / SPRING_SCALE, 1f); if (flingScale >= 1f) return; scaleCentered(rect, flingScale, /* pivotX */ rect.right, /* pivotY */ rect.top + rect.height() / 2); } /** Transform the target window to match the target rect. */ private void applyTransform(SurfaceControl leash, RectF targetRect, float cornerRadius) { if (leash == null || !leash.isValid()) { Loading Loading @@ -280,6 +315,9 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { mTransformMatrix.reset(); mClosingCurrentRect.setEmpty(); mInitialTouchPos.set(0, 0); mGestureProgress = 0; mDownTime = 0; mVelocityTracker.clear(); if (mFinishCallback != null) { try { Loading @@ -295,10 +333,24 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { private void onGestureProgress(@NonNull BackEvent backEvent) { if (!mBackInProgress) { mBackInProgress = true; mDownTime = backEvent.getFrameTime(); } float progress = backEvent.getProgress(); mTouchPos.set(backEvent.getTouchX(), backEvent.getTouchY()); updateGestureBackProgress(getInterpolatedProgress(progress), backEvent); float interpolatedProgress = getInterpolatedProgress(progress); if (predictiveBackTimestampApi()) { mVelocityTracker.addMovement( MotionEvent.obtain( /* downTime */ mDownTime, /* eventTime */ backEvent.getFrameTime(), /* action */ ACTION_MOVE, /* x */ interpolatedProgress * SPRING_SCALE, /* y */ 0f, /* metaState */ 0 ) ); } updateGestureBackProgress(interpolatedProgress, backEvent); } private void onGestureCommitted() { Loading @@ -307,6 +359,25 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { return; } if (predictiveBackTimestampApi()) { // kick off spring animation with the current velocity from the pre-commit phase, this // affects the scaling of the closing and/or opening task during post-commit mVelocityTracker.computeCurrentVelocity(1000); float startVelocity = mGestureProgress < 0.1f ? -DEFAULT_FLING_VELOCITY : -mVelocityTracker.getXVelocity(); SpringAnimation flingAnimation = new SpringAnimation(mPostCommitFlingScale, SPRING_SCALE) .setStartVelocity(Math.max(-MAX_FLING_VELOCITY, Math.min(0f, startVelocity))) .setStartValue(SPRING_SCALE) .setMinimumVisibleChange(0.1f) .setSpring(mPostCommitFlingSpring); flingAnimation.start(); // do an animation-frame immediately to prevent idle frame flingAnimation.doAnimationFrame( Choreographer.getInstance().getLastFrameTimeNanos() / TimeUtils.NANOS_PER_MS ); } // We enter phase 2 of the animation, the starting coordinates for phase 2 are the current // coordinate of the gesture driven phase. mEnteringCurrentRect.round(mEnteringStartRect); Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java +72 −1 Original line number Diff line number Diff line Loading @@ -16,12 +16,15 @@ package com.android.wm.shell.back; import static android.view.MotionEvent.ACTION_MOVE; import static android.view.RemoteAnimationTarget.MODE_CLOSING; import static android.view.RemoteAnimationTarget.MODE_OPENING; import static android.window.BackEvent.EDGE_RIGHT; import static com.android.internal.jank.InteractionJankMonitor.CUJ_PREDICTIVE_BACK_CROSS_TASK; import static com.android.window.flags.Flags.predictiveBackTimestampApi; import static com.android.wm.shell.back.BackAnimationConstants.UPDATE_SYSUI_FLAGS_THRESHOLD; import static com.android.wm.shell.back.CrossActivityBackAnimationKt.scaleCentered; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW; import android.animation.Animator; Loading @@ -36,11 +39,14 @@ import android.graphics.Rect; import android.graphics.RectF; import android.os.Handler; import android.os.RemoteException; import android.util.TimeUtils; import android.view.Choreographer; import android.view.IRemoteAnimationFinishedCallback; import android.view.IRemoteAnimationRunner; import android.view.MotionEvent; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import android.view.VelocityTracker; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import android.window.BackEvent; Loading @@ -48,6 +54,9 @@ import android.window.BackMotionEvent; import android.window.BackProgressAnimator; import android.window.IOnBackInvokedCallback; import com.android.internal.dynamicanimation.animation.FloatValueHolder; import com.android.internal.dynamicanimation.animation.SpringAnimation; import com.android.internal.dynamicanimation.animation.SpringForce; import com.android.internal.policy.ScreenDecorationsUtils; import com.android.internal.policy.SystemBarUtils; import com.android.internal.protolog.ProtoLog; Loading Loading @@ -81,6 +90,11 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { /** Duration of post animation after gesture committed. */ private static final int POST_ANIMATION_DURATION_MS = 500; private static final float SPRING_SCALE = 100f; private static final float DEFAULT_FLING_VELOCITY = 320f; private static final float MAX_FLING_VELOCITY = 1000f; private static final float FLING_SPRING_STIFFNESS = 320f; private final Rect mStartTaskRect = new Rect(); private float mCornerRadius; private int mStatusbarHeight; Loading Loading @@ -114,6 +128,14 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { private float mInterWindowMargin; private float mVerticalMargin; private final FloatValueHolder mPostCommitFlingScale = new FloatValueHolder(SPRING_SCALE); private final SpringForce mPostCommitFlingSpring = new SpringForce(SPRING_SCALE) .setStiffness(FLING_SPRING_STIFFNESS) .setDampingRatio(1f); private final VelocityTracker mVelocityTracker = VelocityTracker.obtain(); private float mGestureProgress = 0f; private long mDownTime = 0L; @Inject public CrossTaskBackAnimation(Context context, BackAnimationBackground background, @ShellMainThread Handler handler) { Loading Loading @@ -168,6 +190,7 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { if (mEnteringTarget == null || mClosingTarget == null) { return; } mGestureProgress = progress; float touchY = event.getTouchY(); Loading Loading @@ -229,6 +252,8 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { } mClosingCurrentRect.set(left, top, left + width, top + height); applyFlingScale(mClosingCurrentRect); applyTransform(mClosingTarget.leash, mClosingCurrentRect, mCornerRadius); } Loading @@ -239,9 +264,19 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { float height = mapRange(progress, mEnteringStartRect.height(), mStartTaskRect.height()); mEnteringCurrentRect.set(left, top, left + width, top + height); applyFlingScale(mEnteringCurrentRect); applyTransform(mEnteringTarget.leash, mEnteringCurrentRect, mCornerRadius); } private void applyFlingScale(RectF rect) { // apply a scale to the rect to account for fling velocity final float flingScale = Math.min(mPostCommitFlingScale.getValue() / SPRING_SCALE, 1f); if (flingScale >= 1f) return; scaleCentered(rect, flingScale, /* pivotX */ rect.right, /* pivotY */ rect.top + rect.height() / 2); } /** Transform the target window to match the target rect. */ private void applyTransform(SurfaceControl leash, RectF targetRect, float cornerRadius) { if (leash == null || !leash.isValid()) { Loading Loading @@ -280,6 +315,9 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { mTransformMatrix.reset(); mClosingCurrentRect.setEmpty(); mInitialTouchPos.set(0, 0); mGestureProgress = 0; mDownTime = 0; mVelocityTracker.clear(); if (mFinishCallback != null) { try { Loading @@ -295,10 +333,24 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { private void onGestureProgress(@NonNull BackEvent backEvent) { if (!mBackInProgress) { mBackInProgress = true; mDownTime = backEvent.getFrameTime(); } float progress = backEvent.getProgress(); mTouchPos.set(backEvent.getTouchX(), backEvent.getTouchY()); updateGestureBackProgress(getInterpolatedProgress(progress), backEvent); float interpolatedProgress = getInterpolatedProgress(progress); if (predictiveBackTimestampApi()) { mVelocityTracker.addMovement( MotionEvent.obtain( /* downTime */ mDownTime, /* eventTime */ backEvent.getFrameTime(), /* action */ ACTION_MOVE, /* x */ interpolatedProgress * SPRING_SCALE, /* y */ 0f, /* metaState */ 0 ) ); } updateGestureBackProgress(interpolatedProgress, backEvent); } private void onGestureCommitted() { Loading @@ -307,6 +359,25 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { return; } if (predictiveBackTimestampApi()) { // kick off spring animation with the current velocity from the pre-commit phase, this // affects the scaling of the closing and/or opening task during post-commit mVelocityTracker.computeCurrentVelocity(1000); float startVelocity = mGestureProgress < 0.1f ? -DEFAULT_FLING_VELOCITY : -mVelocityTracker.getXVelocity(); SpringAnimation flingAnimation = new SpringAnimation(mPostCommitFlingScale, SPRING_SCALE) .setStartVelocity(Math.max(-MAX_FLING_VELOCITY, Math.min(0f, startVelocity))) .setStartValue(SPRING_SCALE) .setMinimumVisibleChange(0.1f) .setSpring(mPostCommitFlingSpring); flingAnimation.start(); // do an animation-frame immediately to prevent idle frame flingAnimation.doAnimationFrame( Choreographer.getInstance().getLastFrameTimeNanos() / TimeUtils.NANOS_PER_MS ); } // We enter phase 2 of the animation, the starting coordinates for phase 2 are the current // coordinate of the gesture driven phase. mEnteringCurrentRect.round(mEnteringStartRect); Loading