Loading core/java/android/window/BackProgressAnimator.java +8 −0 Original line number Diff line number Diff line Loading @@ -155,6 +155,14 @@ public class BackProgressAnimator { mSpring.animateToFinalPosition(0); } /** * Removes the finishCallback passed into {@link #onBackCancelled} */ public void removeOnBackCancelledFinishCallback() { mSpring.removeEndListener(mOnAnimationEndListener); mBackCancelledFinishRunnable = null; } /** Returns true if the back animation is in progress. */ boolean isBackAnimationInProgress() { return mBackAnimationInProgress; Loading libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +72 −44 Original line number Diff line number Diff line Loading @@ -147,7 +147,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont private final Runnable mAnimationTimeoutRunnable = () -> { ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Animation didn't finish in %d ms. Resetting...", MAX_ANIMATION_DURATION); onBackAnimationFinished(); finishBackAnimation(); }; private IBackAnimationFinishedCallback mBackAnimationFinishedCallback; Loading @@ -156,6 +156,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont @Nullable private IOnBackInvokedCallback mActiveCallback; @Nullable private RemoteAnimationTarget[] mApps; @VisibleForTesting final RemoteCallback mNavigationObserver = new RemoteCallback( Loading Loading @@ -466,6 +468,14 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } private void onGestureStarted(float touchX, float touchY, @BackEvent.SwipeEdge int swipeEdge) { boolean interruptCancelPostCommitAnimation = mPostCommitAnimationInProgress && mCurrentTracker.isFinished() && !mCurrentTracker.getTriggerBack() && mQueuedTracker.isInInitialState(); if (interruptCancelPostCommitAnimation) { // If a system animation is currently in the post-commit phase animating an // onBackCancelled event, let's interrupt it and start animating a new back gesture resetTouchTracker(); } TouchTracker touchTracker; if (mCurrentTracker.isInInitialState()) { touchTracker = mCurrentTracker; Loading @@ -480,9 +490,15 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont touchTracker.setState(TouchTracker.TouchTrackerState.ACTIVE); mBackGestureStarted = true; if (touchTracker == mCurrentTracker) { if (interruptCancelPostCommitAnimation) { // post-commit cancel is currently running. let's interrupt it and dispatch a new // onBackStarted event. mPostCommitAnimationInProgress = false; mShellExecutor.removeCallbacks(mAnimationTimeoutRunnable); startSystemAnimation(); } else if (touchTracker == mCurrentTracker) { // Only start the back navigation if no other gesture is being processed. Otherwise, // the back navigation will be started once the current gesture has finished. // the back navigation will fall back to legacy back event injection. startBackNavigation(mCurrentTracker); } } Loading Loading @@ -818,6 +834,20 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont */ @VisibleForTesting void onBackAnimationFinished() { if (!mPostCommitAnimationInProgress) { // This can happen when a post-commit cancel animation was interrupted by a new back // gesture but the timing of interruption was bad such that the back-callback // implementation finished in between the time of the new gesture having started and // the time of the back-callback receiving the new onBackStarted event. Due to the // asynchronous APIs this isn't an unlikely case. To handle this, let's return early. // The back-callback implementation will call onBackAnimationFinished again when it is // done with animating the second gesture. return; } finishBackAnimation(); } private void finishBackAnimation() { // Stop timeout runner. mShellExecutor.removeCallbacks(mAnimationTimeoutRunnable); mPostCommitAnimationInProgress = false; Loading Loading @@ -878,6 +908,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont void finishBackNavigation(boolean triggerBack) { ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: finishBackNavigation()"); mActiveCallback = null; mApps = null; mShouldStartOnNextMoveEvent = false; mOnBackStartDispatched = false; mPointerPilfered = false; Loading Loading @@ -914,60 +945,57 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont mTrackingLatency = false; } private void createAdapter() { IBackAnimationRunner runner = new IBackAnimationRunner.Stub() { @Override public void onAnimationStart( RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, IBackAnimationFinishedCallback finishedCallback) { mShellExecutor.execute( () -> { endLatencyTracking(); private void startSystemAnimation() { if (mBackNavigationInfo == null) { ProtoLog.e(WM_SHELL_BACK_PREVIEW, "Lack of navigation info to start animation."); ProtoLog.e(WM_SHELL_BACK_PREVIEW, "Lack of navigation info to start animation."); return; } if (mApps == null) { ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Not starting animation due to mApps being null."); return; } final BackAnimationRunner runner = mShellBackAnimationRegistry.getAnimationRunnerAndInit( mBackNavigationInfo); mShellBackAnimationRegistry.getAnimationRunnerAndInit(mBackNavigationInfo); if (runner == null) { if (finishedCallback != null) { if (mBackAnimationFinishedCallback != null) { try { finishedCallback.onAnimationFinished(false); mBackAnimationFinishedCallback.onAnimationFinished(false); } catch (RemoteException e) { Log.w( TAG, "Failed call IBackNaviAnimationController", e); Log.w(TAG, "Failed call IBackNaviAnimationController", e); } } return; } mActiveCallback = runner.getCallback(); mBackAnimationFinishedCallback = finishedCallback; ProtoLog.d( WM_SHELL_BACK_PREVIEW, "BackAnimationController: startAnimation()"); runner.startAnimation( apps, wallpapers, nonApps, () -> mShellExecutor.execute( BackAnimationController.this ::onBackAnimationFinished)); ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: startAnimation()"); runner.startAnimation(mApps, /*wallpapers*/ null, /*nonApps*/ null, () -> mShellExecutor.execute(this::onBackAnimationFinished)); if (apps.length >= 1) { if (mApps.length >= 1) { mCurrentTracker.updateStartLocation(); BackMotionEvent startEvent = mCurrentTracker.createStartEvent(apps[0]); BackMotionEvent startEvent = mCurrentTracker.createStartEvent(mApps[0]); dispatchOnBackStarted(mActiveCallback, startEvent); } } private void createAdapter() { IBackAnimationRunner runner = new IBackAnimationRunner.Stub() { @Override public void onAnimationStart( RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, IBackAnimationFinishedCallback finishedCallback) { mShellExecutor.execute( () -> { endLatencyTracking(); mBackAnimationFinishedCallback = finishedCallback; mApps = apps; startSystemAnimation(); // Dispatch the first progress after animation start for // smoothing the initial animation, instead of waiting for next Loading libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt +5 −0 Original line number Diff line number Diff line Loading @@ -283,6 +283,11 @@ class CrossActivityBackAnimation @Inject constructor( private inner class Callback : IOnBackInvokedCallback.Default() { override fun onBackStarted(backMotionEvent: BackMotionEvent) { // in case we're still animating an onBackCancelled event, let's remove the finish- // callback from the progress animator to prevent calling finishAnimation() before // restarting a new animation progressAnimator.removeOnBackCancelledFinishCallback(); startBackAnimation(backMotionEvent) progressAnimator.onBackStarted(backMotionEvent) { backEvent: BackEvent -> onGestureProgress(backEvent) Loading libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java +7 −2 Original line number Diff line number Diff line Loading @@ -275,8 +275,6 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { private void onGestureProgress(@NonNull BackEvent backEvent) { if (!mBackInProgress) { mIsRightEdge = backEvent.getSwipeEdge() == EDGE_RIGHT; mInitialTouchPos.set(backEvent.getTouchX(), backEvent.getTouchY()); mBackInProgress = true; } float progress = backEvent.getProgress(); Loading Loading @@ -326,6 +324,13 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { private final class Callback extends IOnBackInvokedCallback.Default { @Override public void onBackStarted(BackMotionEvent backEvent) { // in case we're still animating an onBackCancelled event, let's remove the finish- // callback from the progress animator to prevent calling finishAnimation() before // restarting a new animation mProgressAnimator.removeOnBackCancelledFinishCallback(); mIsRightEdge = backEvent.getSwipeEdge() == EDGE_RIGHT; mInitialTouchPos.set(backEvent.getTouchX(), backEvent.getTouchY()); mProgressAnimator.onBackStarted(backEvent, CrossTaskBackAnimation.this::onGestureProgress); } Loading libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java +5 −0 Original line number Diff line number Diff line Loading @@ -285,6 +285,11 @@ public class CustomizeActivityAnimation extends ShellBackAnimation { private final class Callback extends IOnBackInvokedCallback.Default { @Override public void onBackStarted(BackMotionEvent backEvent) { // in case we're still animating an onBackCancelled event, let's remove the finish- // callback from the progress animator to prevent calling finishAnimation() before // restarting a new animation mProgressAnimator.removeOnBackCancelledFinishCallback(); mProgressAnimator.onBackStarted(backEvent, CustomizeActivityAnimation.this::onGestureProgress); } Loading Loading
core/java/android/window/BackProgressAnimator.java +8 −0 Original line number Diff line number Diff line Loading @@ -155,6 +155,14 @@ public class BackProgressAnimator { mSpring.animateToFinalPosition(0); } /** * Removes the finishCallback passed into {@link #onBackCancelled} */ public void removeOnBackCancelledFinishCallback() { mSpring.removeEndListener(mOnAnimationEndListener); mBackCancelledFinishRunnable = null; } /** Returns true if the back animation is in progress. */ boolean isBackAnimationInProgress() { return mBackAnimationInProgress; Loading
libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +72 −44 Original line number Diff line number Diff line Loading @@ -147,7 +147,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont private final Runnable mAnimationTimeoutRunnable = () -> { ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Animation didn't finish in %d ms. Resetting...", MAX_ANIMATION_DURATION); onBackAnimationFinished(); finishBackAnimation(); }; private IBackAnimationFinishedCallback mBackAnimationFinishedCallback; Loading @@ -156,6 +156,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont @Nullable private IOnBackInvokedCallback mActiveCallback; @Nullable private RemoteAnimationTarget[] mApps; @VisibleForTesting final RemoteCallback mNavigationObserver = new RemoteCallback( Loading Loading @@ -466,6 +468,14 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } private void onGestureStarted(float touchX, float touchY, @BackEvent.SwipeEdge int swipeEdge) { boolean interruptCancelPostCommitAnimation = mPostCommitAnimationInProgress && mCurrentTracker.isFinished() && !mCurrentTracker.getTriggerBack() && mQueuedTracker.isInInitialState(); if (interruptCancelPostCommitAnimation) { // If a system animation is currently in the post-commit phase animating an // onBackCancelled event, let's interrupt it and start animating a new back gesture resetTouchTracker(); } TouchTracker touchTracker; if (mCurrentTracker.isInInitialState()) { touchTracker = mCurrentTracker; Loading @@ -480,9 +490,15 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont touchTracker.setState(TouchTracker.TouchTrackerState.ACTIVE); mBackGestureStarted = true; if (touchTracker == mCurrentTracker) { if (interruptCancelPostCommitAnimation) { // post-commit cancel is currently running. let's interrupt it and dispatch a new // onBackStarted event. mPostCommitAnimationInProgress = false; mShellExecutor.removeCallbacks(mAnimationTimeoutRunnable); startSystemAnimation(); } else if (touchTracker == mCurrentTracker) { // Only start the back navigation if no other gesture is being processed. Otherwise, // the back navigation will be started once the current gesture has finished. // the back navigation will fall back to legacy back event injection. startBackNavigation(mCurrentTracker); } } Loading Loading @@ -818,6 +834,20 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont */ @VisibleForTesting void onBackAnimationFinished() { if (!mPostCommitAnimationInProgress) { // This can happen when a post-commit cancel animation was interrupted by a new back // gesture but the timing of interruption was bad such that the back-callback // implementation finished in between the time of the new gesture having started and // the time of the back-callback receiving the new onBackStarted event. Due to the // asynchronous APIs this isn't an unlikely case. To handle this, let's return early. // The back-callback implementation will call onBackAnimationFinished again when it is // done with animating the second gesture. return; } finishBackAnimation(); } private void finishBackAnimation() { // Stop timeout runner. mShellExecutor.removeCallbacks(mAnimationTimeoutRunnable); mPostCommitAnimationInProgress = false; Loading Loading @@ -878,6 +908,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont void finishBackNavigation(boolean triggerBack) { ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: finishBackNavigation()"); mActiveCallback = null; mApps = null; mShouldStartOnNextMoveEvent = false; mOnBackStartDispatched = false; mPointerPilfered = false; Loading Loading @@ -914,60 +945,57 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont mTrackingLatency = false; } private void createAdapter() { IBackAnimationRunner runner = new IBackAnimationRunner.Stub() { @Override public void onAnimationStart( RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, IBackAnimationFinishedCallback finishedCallback) { mShellExecutor.execute( () -> { endLatencyTracking(); private void startSystemAnimation() { if (mBackNavigationInfo == null) { ProtoLog.e(WM_SHELL_BACK_PREVIEW, "Lack of navigation info to start animation."); ProtoLog.e(WM_SHELL_BACK_PREVIEW, "Lack of navigation info to start animation."); return; } if (mApps == null) { ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Not starting animation due to mApps being null."); return; } final BackAnimationRunner runner = mShellBackAnimationRegistry.getAnimationRunnerAndInit( mBackNavigationInfo); mShellBackAnimationRegistry.getAnimationRunnerAndInit(mBackNavigationInfo); if (runner == null) { if (finishedCallback != null) { if (mBackAnimationFinishedCallback != null) { try { finishedCallback.onAnimationFinished(false); mBackAnimationFinishedCallback.onAnimationFinished(false); } catch (RemoteException e) { Log.w( TAG, "Failed call IBackNaviAnimationController", e); Log.w(TAG, "Failed call IBackNaviAnimationController", e); } } return; } mActiveCallback = runner.getCallback(); mBackAnimationFinishedCallback = finishedCallback; ProtoLog.d( WM_SHELL_BACK_PREVIEW, "BackAnimationController: startAnimation()"); runner.startAnimation( apps, wallpapers, nonApps, () -> mShellExecutor.execute( BackAnimationController.this ::onBackAnimationFinished)); ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: startAnimation()"); runner.startAnimation(mApps, /*wallpapers*/ null, /*nonApps*/ null, () -> mShellExecutor.execute(this::onBackAnimationFinished)); if (apps.length >= 1) { if (mApps.length >= 1) { mCurrentTracker.updateStartLocation(); BackMotionEvent startEvent = mCurrentTracker.createStartEvent(apps[0]); BackMotionEvent startEvent = mCurrentTracker.createStartEvent(mApps[0]); dispatchOnBackStarted(mActiveCallback, startEvent); } } private void createAdapter() { IBackAnimationRunner runner = new IBackAnimationRunner.Stub() { @Override public void onAnimationStart( RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, IBackAnimationFinishedCallback finishedCallback) { mShellExecutor.execute( () -> { endLatencyTracking(); mBackAnimationFinishedCallback = finishedCallback; mApps = apps; startSystemAnimation(); // Dispatch the first progress after animation start for // smoothing the initial animation, instead of waiting for next Loading
libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt +5 −0 Original line number Diff line number Diff line Loading @@ -283,6 +283,11 @@ class CrossActivityBackAnimation @Inject constructor( private inner class Callback : IOnBackInvokedCallback.Default() { override fun onBackStarted(backMotionEvent: BackMotionEvent) { // in case we're still animating an onBackCancelled event, let's remove the finish- // callback from the progress animator to prevent calling finishAnimation() before // restarting a new animation progressAnimator.removeOnBackCancelledFinishCallback(); startBackAnimation(backMotionEvent) progressAnimator.onBackStarted(backMotionEvent) { backEvent: BackEvent -> onGestureProgress(backEvent) Loading
libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java +7 −2 Original line number Diff line number Diff line Loading @@ -275,8 +275,6 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { private void onGestureProgress(@NonNull BackEvent backEvent) { if (!mBackInProgress) { mIsRightEdge = backEvent.getSwipeEdge() == EDGE_RIGHT; mInitialTouchPos.set(backEvent.getTouchX(), backEvent.getTouchY()); mBackInProgress = true; } float progress = backEvent.getProgress(); Loading Loading @@ -326,6 +324,13 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { private final class Callback extends IOnBackInvokedCallback.Default { @Override public void onBackStarted(BackMotionEvent backEvent) { // in case we're still animating an onBackCancelled event, let's remove the finish- // callback from the progress animator to prevent calling finishAnimation() before // restarting a new animation mProgressAnimator.removeOnBackCancelledFinishCallback(); mIsRightEdge = backEvent.getSwipeEdge() == EDGE_RIGHT; mInitialTouchPos.set(backEvent.getTouchX(), backEvent.getTouchY()); mProgressAnimator.onBackStarted(backEvent, CrossTaskBackAnimation.this::onGestureProgress); } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java +5 −0 Original line number Diff line number Diff line Loading @@ -285,6 +285,11 @@ public class CustomizeActivityAnimation extends ShellBackAnimation { private final class Callback extends IOnBackInvokedCallback.Default { @Override public void onBackStarted(BackMotionEvent backEvent) { // in case we're still animating an onBackCancelled event, let's remove the finish- // callback from the progress animator to prevent calling finishAnimation() before // restarting a new animation mProgressAnimator.removeOnBackCancelledFinishCallback(); mProgressAnimator.onBackStarted(backEvent, CustomizeActivityAnimation.this::onGestureProgress); } Loading