Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7d569c54 authored by Johannes Gallmann's avatar Johannes Gallmann Committed by Android (Google) Code Review
Browse files

Merge "Play predictive animation when quickly restarting back gesture after cancel" into main

parents b779f47e 95ba9d4c
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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;
+72 −44
Original line number Diff line number Diff line
@@ -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;
@@ -156,6 +156,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont

    @Nullable
    private IOnBackInvokedCallback mActiveCallback;
    @Nullable
    private RemoteAnimationTarget[] mApps;

    @VisibleForTesting
    final RemoteCallback mNavigationObserver = new RemoteCallback(
@@ -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;
@@ -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);
        }
    }
@@ -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;
@@ -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;
@@ -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
+5 −0
Original line number Diff line number Diff line
@@ -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)
+7 −2
Original line number Diff line number Diff line
@@ -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();
@@ -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);
        }
+5 −0
Original line number Diff line number Diff line
@@ -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