Loading libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt +27 −4 Original line number Diff line number Diff line Loading @@ -39,6 +39,8 @@ import android.view.animation.DecelerateInterpolator import android.view.animation.Interpolator import android.view.animation.Transformation import android.window.BackEvent import android.window.BackEvent.EDGE_LEFT import android.window.BackEvent.EDGE_RIGHT import android.window.BackMotionEvent import android.window.BackNavigationInfo import android.window.BackProgressAnimator Loading @@ -50,6 +52,7 @@ import com.android.internal.jank.Cuj import com.android.internal.policy.ScreenDecorationsUtils import com.android.internal.policy.SystemBarUtils import com.android.internal.protolog.ProtoLog import com.android.window.flags.Flags.predictiveBackTimestampApi import com.android.wm.shell.R import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.protolog.ShellProtoLogGroup Loading Loading @@ -118,7 +121,9 @@ abstract class CrossActivityBackAnimation( private val postCommitFlingSpring = SpringForce(SPRING_SCALE) .setStiffness(SpringForce.STIFFNESS_LOW) .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY) private var swipeEdge = EDGE_LEFT protected var gestureProgress = 0f private val velocityTracker = ProgressVelocityTracker() /** Background color to be used during the animation, also see [getBackgroundColor] */ protected var customizedBackgroundColor = 0 Loading Loading @@ -175,6 +180,7 @@ abstract class CrossActivityBackAnimation( ) return } swipeEdge = backMotionEvent.swipeEdge triggerBack = backMotionEvent.triggerBack initialTouchPos.set(backMotionEvent.touchX, backMotionEvent.touchY) Loading Loading @@ -241,6 +247,9 @@ abstract class CrossActivityBackAnimation( ) applyTransaction() background.customizeStatusBarAppearance(currentClosingRect.top.toInt()) if (predictiveBackTimestampApi()) { velocityTracker.addPosition(backEvent.frameTimeMillis, progress) } } private fun getYOffset(centeredRect: RectF, touchY: Float): Float { Loading Loading @@ -272,10 +281,19 @@ abstract class CrossActivityBackAnimation( // kick off spring animation with the current velocity from the pre-commit phase, this // affects the scaling of the closing and/or opening activity during post-commit val startVelocity = if (gestureProgress < 0.1f) -DEFAULT_FLING_VELOCITY else -velocity * SPRING_SCALE var startVelocity = if (predictiveBackTimestampApi()) { // pronounce fling animation more for gestures val velocityFactor = if (swipeEdge == EDGE_LEFT || swipeEdge == EDGE_RIGHT) 2f else 1f velocity * SPRING_SCALE * (1f - MAX_SCALE) * velocityFactor } else { velocity * SPRING_SCALE } if (gestureProgress < 0.1f) { startVelocity = startVelocity.coerceAtLeast(DEFAULT_FLING_VELOCITY) } val flingAnimation = SpringAnimation(postCommitFlingScale, SPRING_SCALE) .setStartVelocity(startVelocity.coerceIn(-MAX_FLING_VELOCITY, 0f)) .setStartVelocity(-startVelocity.coerceIn(0f, MAX_FLING_VELOCITY)) .setStartValue(SPRING_SCALE) .setSpring(postCommitFlingSpring) flingAnimation.start() Loading Loading @@ -338,6 +356,7 @@ abstract class CrossActivityBackAnimation( lastPostCommitFlingScale = SPRING_SCALE gestureProgress = 0f triggerBack = false velocityTracker.resetTracking() } protected fun applyTransform( Loading Loading @@ -520,9 +539,13 @@ abstract class CrossActivityBackAnimation( override fun onBackInvoked() { triggerBack = true progressAnimator.reset() if (predictiveBackTimestampApi()) { onGestureCommitted(velocityTracker.calculateVelocity()) } else { onGestureCommitted(progressAnimator.velocity) } } } private inner class Runner : IRemoteAnimationRunner.Default() { override fun onAnimationStart( Loading libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java +5 −20 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ 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; Loading @@ -43,10 +42,8 @@ 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 Loading @@ -132,9 +129,8 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { private final SpringForce mPostCommitFlingSpring = new SpringForce(SPRING_SCALE) .setStiffness(FLING_SPRING_STIFFNESS) .setDampingRatio(1f); private final VelocityTracker mVelocityTracker = VelocityTracker.obtain(); private final ProgressVelocityTracker mVelocityTracker = new ProgressVelocityTracker(); private float mGestureProgress = 0f; private long mDownTime = 0L; @Inject public CrossTaskBackAnimation(Context context, BackAnimationBackground background, Loading Loading @@ -316,8 +312,7 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { mClosingCurrentRect.setEmpty(); mInitialTouchPos.set(0, 0); mGestureProgress = 0; mDownTime = 0; mVelocityTracker.clear(); mVelocityTracker.resetTracking(); if (mFinishCallback != null) { try { Loading @@ -333,22 +328,13 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { private void onGestureProgress(@NonNull BackEvent backEvent) { if (!mBackInProgress) { mBackInProgress = true; mDownTime = backEvent.getFrameTimeMillis(); } float progress = backEvent.getProgress(); mTouchPos.set(backEvent.getTouchX(), backEvent.getTouchY()); float interpolatedProgress = getInterpolatedProgress(progress); if (predictiveBackTimestampApi()) { mVelocityTracker.addMovement( MotionEvent.obtain( /* downTime */ mDownTime, /* eventTime */ backEvent.getFrameTimeMillis(), /* action */ ACTION_MOVE, /* x */ interpolatedProgress * SPRING_SCALE, /* y */ 0f, /* metaState */ 0 ) ); mVelocityTracker.addPosition(backEvent.getFrameTimeMillis(), interpolatedProgress * SPRING_SCALE); } updateGestureBackProgress(interpolatedProgress, backEvent); } Loading @@ -362,9 +348,8 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { 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(); ? -DEFAULT_FLING_VELOCITY : -mVelocityTracker.calculateVelocity(); SpringAnimation flingAnimation = new SpringAnimation(mPostCommitFlingScale, SPRING_SCALE) .setStartVelocity(Math.max(-MAX_FLING_VELOCITY, Math.min(0f, startVelocity))) Loading libs/WindowManager/Shell/src/com/android/wm/shell/back/ProgressVelocityTracker.kt 0 → 100644 +50 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.back import android.view.MotionEvent import android.view.VelocityTracker internal class ProgressVelocityTracker { private val velocityTracker: VelocityTracker = VelocityTracker.obtain() private var downTime = -1L fun addPosition(timeMillis: Long, position: Float) { if (downTime == -1L) downTime = timeMillis velocityTracker.addMovement( MotionEvent.obtain( /* downTime */ downTime, /* eventTime */ timeMillis, /* action */ MotionEvent.ACTION_MOVE, /* x */ position, /* y */ 0f, /* metaState */0 ) ) } /** calculates current velocity (unit: progress per second) */ fun calculateVelocity(): Float { velocityTracker.computeCurrentVelocity(1000) return velocityTracker.xVelocity } fun resetTracking() { velocityTracker.clear() downTime = -1L } } No newline at end of file Loading
libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt +27 −4 Original line number Diff line number Diff line Loading @@ -39,6 +39,8 @@ import android.view.animation.DecelerateInterpolator import android.view.animation.Interpolator import android.view.animation.Transformation import android.window.BackEvent import android.window.BackEvent.EDGE_LEFT import android.window.BackEvent.EDGE_RIGHT import android.window.BackMotionEvent import android.window.BackNavigationInfo import android.window.BackProgressAnimator Loading @@ -50,6 +52,7 @@ import com.android.internal.jank.Cuj import com.android.internal.policy.ScreenDecorationsUtils import com.android.internal.policy.SystemBarUtils import com.android.internal.protolog.ProtoLog import com.android.window.flags.Flags.predictiveBackTimestampApi import com.android.wm.shell.R import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.protolog.ShellProtoLogGroup Loading Loading @@ -118,7 +121,9 @@ abstract class CrossActivityBackAnimation( private val postCommitFlingSpring = SpringForce(SPRING_SCALE) .setStiffness(SpringForce.STIFFNESS_LOW) .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY) private var swipeEdge = EDGE_LEFT protected var gestureProgress = 0f private val velocityTracker = ProgressVelocityTracker() /** Background color to be used during the animation, also see [getBackgroundColor] */ protected var customizedBackgroundColor = 0 Loading Loading @@ -175,6 +180,7 @@ abstract class CrossActivityBackAnimation( ) return } swipeEdge = backMotionEvent.swipeEdge triggerBack = backMotionEvent.triggerBack initialTouchPos.set(backMotionEvent.touchX, backMotionEvent.touchY) Loading Loading @@ -241,6 +247,9 @@ abstract class CrossActivityBackAnimation( ) applyTransaction() background.customizeStatusBarAppearance(currentClosingRect.top.toInt()) if (predictiveBackTimestampApi()) { velocityTracker.addPosition(backEvent.frameTimeMillis, progress) } } private fun getYOffset(centeredRect: RectF, touchY: Float): Float { Loading Loading @@ -272,10 +281,19 @@ abstract class CrossActivityBackAnimation( // kick off spring animation with the current velocity from the pre-commit phase, this // affects the scaling of the closing and/or opening activity during post-commit val startVelocity = if (gestureProgress < 0.1f) -DEFAULT_FLING_VELOCITY else -velocity * SPRING_SCALE var startVelocity = if (predictiveBackTimestampApi()) { // pronounce fling animation more for gestures val velocityFactor = if (swipeEdge == EDGE_LEFT || swipeEdge == EDGE_RIGHT) 2f else 1f velocity * SPRING_SCALE * (1f - MAX_SCALE) * velocityFactor } else { velocity * SPRING_SCALE } if (gestureProgress < 0.1f) { startVelocity = startVelocity.coerceAtLeast(DEFAULT_FLING_VELOCITY) } val flingAnimation = SpringAnimation(postCommitFlingScale, SPRING_SCALE) .setStartVelocity(startVelocity.coerceIn(-MAX_FLING_VELOCITY, 0f)) .setStartVelocity(-startVelocity.coerceIn(0f, MAX_FLING_VELOCITY)) .setStartValue(SPRING_SCALE) .setSpring(postCommitFlingSpring) flingAnimation.start() Loading Loading @@ -338,6 +356,7 @@ abstract class CrossActivityBackAnimation( lastPostCommitFlingScale = SPRING_SCALE gestureProgress = 0f triggerBack = false velocityTracker.resetTracking() } protected fun applyTransform( Loading Loading @@ -520,9 +539,13 @@ abstract class CrossActivityBackAnimation( override fun onBackInvoked() { triggerBack = true progressAnimator.reset() if (predictiveBackTimestampApi()) { onGestureCommitted(velocityTracker.calculateVelocity()) } else { onGestureCommitted(progressAnimator.velocity) } } } private inner class Runner : IRemoteAnimationRunner.Default() { override fun onAnimationStart( Loading
libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java +5 −20 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ 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; Loading @@ -43,10 +42,8 @@ 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 Loading @@ -132,9 +129,8 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { private final SpringForce mPostCommitFlingSpring = new SpringForce(SPRING_SCALE) .setStiffness(FLING_SPRING_STIFFNESS) .setDampingRatio(1f); private final VelocityTracker mVelocityTracker = VelocityTracker.obtain(); private final ProgressVelocityTracker mVelocityTracker = new ProgressVelocityTracker(); private float mGestureProgress = 0f; private long mDownTime = 0L; @Inject public CrossTaskBackAnimation(Context context, BackAnimationBackground background, Loading Loading @@ -316,8 +312,7 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { mClosingCurrentRect.setEmpty(); mInitialTouchPos.set(0, 0); mGestureProgress = 0; mDownTime = 0; mVelocityTracker.clear(); mVelocityTracker.resetTracking(); if (mFinishCallback != null) { try { Loading @@ -333,22 +328,13 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { private void onGestureProgress(@NonNull BackEvent backEvent) { if (!mBackInProgress) { mBackInProgress = true; mDownTime = backEvent.getFrameTimeMillis(); } float progress = backEvent.getProgress(); mTouchPos.set(backEvent.getTouchX(), backEvent.getTouchY()); float interpolatedProgress = getInterpolatedProgress(progress); if (predictiveBackTimestampApi()) { mVelocityTracker.addMovement( MotionEvent.obtain( /* downTime */ mDownTime, /* eventTime */ backEvent.getFrameTimeMillis(), /* action */ ACTION_MOVE, /* x */ interpolatedProgress * SPRING_SCALE, /* y */ 0f, /* metaState */ 0 ) ); mVelocityTracker.addPosition(backEvent.getFrameTimeMillis(), interpolatedProgress * SPRING_SCALE); } updateGestureBackProgress(interpolatedProgress, backEvent); } Loading @@ -362,9 +348,8 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { 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(); ? -DEFAULT_FLING_VELOCITY : -mVelocityTracker.calculateVelocity(); SpringAnimation flingAnimation = new SpringAnimation(mPostCommitFlingScale, SPRING_SCALE) .setStartVelocity(Math.max(-MAX_FLING_VELOCITY, Math.min(0f, startVelocity))) Loading
libs/WindowManager/Shell/src/com/android/wm/shell/back/ProgressVelocityTracker.kt 0 → 100644 +50 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.back import android.view.MotionEvent import android.view.VelocityTracker internal class ProgressVelocityTracker { private val velocityTracker: VelocityTracker = VelocityTracker.obtain() private var downTime = -1L fun addPosition(timeMillis: Long, position: Float) { if (downTime == -1L) downTime = timeMillis velocityTracker.addMovement( MotionEvent.obtain( /* downTime */ downTime, /* eventTime */ timeMillis, /* action */ MotionEvent.ACTION_MOVE, /* x */ position, /* y */ 0f, /* metaState */0 ) ) } /** calculates current velocity (unit: progress per second) */ fun calculateVelocity(): Float { velocityTracker.computeCurrentVelocity(1000) return velocityTracker.xVelocity } fun resetTracking() { velocityTracker.clear() downTime = -1L } } No newline at end of file