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

Commit 1b8878fa authored by wilsonshih's avatar wilsonshih
Browse files

More stabilize predictive back animation.

The one way binder call may not invoke immediately, so it's also
possible that shell side received onAnimationStart after core has
canceled that animation. So in shell, validate the leashes of animation
targets before send it to runner, normally NavigationObserver should
receive cancel callback after that.

Also add the same check before send animation targets to shell, if
invalide, cancel the animation and notify onAnimationCancelled.

Bug: 327312316
Bug: 318294405
Test: simulate send invalidate animation targets to shell, verify it
won't crash systemui.

Change-Id: I4ffa8b6654806181763d6a58d2a748537675e030
parent a9b3adea
Loading
Loading
Loading
Loading
+22 −1
Original line number Original line Diff line number Diff line
@@ -173,6 +173,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
                        ProtoLog.i(WM_SHELL_BACK_PREVIEW, "Navigation window gone.");
                        ProtoLog.i(WM_SHELL_BACK_PREVIEW, "Navigation window gone.");
                        setTriggerBack(false);
                        setTriggerBack(false);
                        resetTouchTracker();
                        resetTouchTracker();
                        // Don't wait for animation start
                        mShellExecutor.removeCallbacks(mAnimationTimeoutRunnable);
                    });
                    });
                }
                }
            });
            });
@@ -950,7 +952,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
            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;
            return;
        }
        }
        if (mApps == null) {
        if (!validateAnimationTargets(mApps)) {
            ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Not starting animation due to mApps being null.");
            ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Not starting animation due to mApps being null.");
            return;
            return;
        }
        }
@@ -981,6 +983,21 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
        }
        }
    }
    }


    /**
     * Validate animation targets.
     */
    static boolean validateAnimationTargets(RemoteAnimationTarget[] apps) {
        if (apps == null || apps.length == 0) {
            return false;
        }
        for (int i = apps.length - 1; i >= 0; --i) {
            if (!apps[i].leash.isValid()) {
                return false;
            }
        }
        return true;
    }

    private void createAdapter() {
    private void createAdapter() {
        IBackAnimationRunner runner =
        IBackAnimationRunner runner =
                new IBackAnimationRunner.Stub() {
                new IBackAnimationRunner.Stub() {
@@ -993,6 +1010,10 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
                        mShellExecutor.execute(
                        mShellExecutor.execute(
                                () -> {
                                () -> {
                                    endLatencyTracking();
                                    endLatencyTracking();
                                    if (!validateAnimationTargets(apps)) {
                                        Log.e(TAG, "Invalid animation targets!");
                                        return;
                                    }
                                    mBackAnimationFinishedCallback = finishedCallback;
                                    mBackAnimationFinishedCallback = finishedCallback;
                                    mApps = apps;
                                    mApps = apps;
                                    startSystemAnimation();
                                    startSystemAnimation();
+3 −2
Original line number Original line Diff line number Diff line
@@ -69,7 +69,6 @@ import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.sysui.ShellSharedConstants;
import com.android.wm.shell.sysui.ShellSharedConstants;



import org.junit.Before;
import org.junit.Before;
import org.junit.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runner.RunWith;
@@ -182,7 +181,9 @@ public class BackAnimationControllerTest extends ShellTestCase {
    }
    }


    RemoteAnimationTarget createAnimationTarget() {
    RemoteAnimationTarget createAnimationTarget() {
        SurfaceControl topWindowLeash = new SurfaceControl();
        SurfaceControl topWindowLeash = new SurfaceControl.Builder()
                .setName("FakeLeash")
                .build();
        return new RemoteAnimationTarget(-1, RemoteAnimationTarget.MODE_CLOSING, topWindowLeash,
        return new RemoteAnimationTarget(-1, RemoteAnimationTarget.MODE_CLOSING, topWindowLeash,
                false, new Rect(), new Rect(), -1,
                false, new Rect(), new Rect(), -1,
                new Point(0, 0), new Rect(), new Rect(), new WindowConfiguration(),
                new Point(0, 0), new Rect(), new Rect(), new WindowConfiguration(),
+37 −9
Original line number Original line Diff line number Diff line
@@ -359,6 +359,7 @@ class BackNavigationController {
                        mAnimationHandler.prepareAnimation(
                        mAnimationHandler.prepareAnimation(
                                backType,
                                backType,
                                adapter,
                                adapter,
                                mNavigationMonitor,
                                currentTask,
                                currentTask,
                                prevTask,
                                prevTask,
                                currentActivity,
                                currentActivity,
@@ -667,7 +668,8 @@ class BackNavigationController {
        mAnimationHandler.markWindowHasDrawn(openActivity);
        mAnimationHandler.markWindowHasDrawn(openActivity);
    }
    }


    private class NavigationMonitor {
    @VisibleForTesting
    class NavigationMonitor {
        // The window which triggering the back navigation.
        // The window which triggering the back navigation.
        private WindowState mNavigatingWindow;
        private WindowState mNavigatingWindow;
        private RemoteCallback mObserver;
        private RemoteCallback mObserver;
@@ -1492,28 +1494,31 @@ class BackNavigationController {
        ScheduleAnimationBuilder prepareAnimation(
        ScheduleAnimationBuilder prepareAnimation(
                int backType,
                int backType,
                BackAnimationAdapter adapter,
                BackAnimationAdapter adapter,
                NavigationMonitor monitor,
                Task currentTask,
                Task currentTask,
                Task previousTask,
                Task previousTask,
                ActivityRecord currentActivity,
                ActivityRecord currentActivity,
                ArrayList<ActivityRecord> previousActivity,
                ArrayList<ActivityRecord> previousActivity,
                WindowContainer removedWindowContainer) {
                WindowContainer removedWindowContainer) {
            final ScheduleAnimationBuilder builder =
                    new ScheduleAnimationBuilder(backType, adapter, monitor);
            switch (backType) {
            switch (backType) {
                case BackNavigationInfo.TYPE_RETURN_TO_HOME:
                case BackNavigationInfo.TYPE_RETURN_TO_HOME:
                    return new ScheduleAnimationBuilder(backType, adapter)
                    return builder
                            .setIsLaunchBehind(true)
                            .setIsLaunchBehind(true)
                            .setComposeTarget(currentTask, previousTask);
                            .setComposeTarget(currentTask, previousTask);
                case BackNavigationInfo.TYPE_CROSS_ACTIVITY:
                case BackNavigationInfo.TYPE_CROSS_ACTIVITY:
                    ActivityRecord[] prevActs = new ActivityRecord[previousActivity.size()];
                    ActivityRecord[] prevActs = new ActivityRecord[previousActivity.size()];
                    prevActs = previousActivity.toArray(prevActs);
                    prevActs = previousActivity.toArray(prevActs);
                    return new ScheduleAnimationBuilder(backType, adapter)
                    return builder
                            .setComposeTarget(currentActivity, prevActs)
                            .setComposeTarget(currentActivity, prevActs)
                            .setIsLaunchBehind(false);
                            .setIsLaunchBehind(false);
                case BackNavigationInfo.TYPE_CROSS_TASK:
                case BackNavigationInfo.TYPE_CROSS_TASK:
                    return new ScheduleAnimationBuilder(backType, adapter)
                    return builder
                            .setComposeTarget(currentTask, previousTask)
                            .setComposeTarget(currentTask, previousTask)
                            .setIsLaunchBehind(false);
                            .setIsLaunchBehind(false);
                case BackNavigationInfo.TYPE_DIALOG_CLOSE:
                case BackNavigationInfo.TYPE_DIALOG_CLOSE:
                    return new ScheduleAnimationBuilder(backType, adapter)
                    return builder
                            .setComposeTarget(removedWindowContainer, currentActivity)
                            .setComposeTarget(removedWindowContainer, currentActivity)
                            .setIsLaunchBehind(false);
                            .setIsLaunchBehind(false);
            }
            }
@@ -1523,13 +1528,16 @@ class BackNavigationController {
        class ScheduleAnimationBuilder {
        class ScheduleAnimationBuilder {
            final int mType;
            final int mType;
            final BackAnimationAdapter mBackAnimationAdapter;
            final BackAnimationAdapter mBackAnimationAdapter;
            final NavigationMonitor mNavigationMonitor;
            WindowContainer mCloseTarget;
            WindowContainer mCloseTarget;
            WindowContainer[] mOpenTargets;
            WindowContainer[] mOpenTargets;
            boolean mIsLaunchBehind;
            boolean mIsLaunchBehind;


            ScheduleAnimationBuilder(int type, BackAnimationAdapter backAnimationAdapter) {
            ScheduleAnimationBuilder(int type, BackAnimationAdapter adapter,
                    NavigationMonitor monitor) {
                mType = type;
                mType = type;
                mBackAnimationAdapter = backAnimationAdapter;
                mBackAnimationAdapter = adapter;
                mNavigationMonitor = monitor;
            }
            }


            ScheduleAnimationBuilder setComposeTarget(@NonNull WindowContainer close,
            ScheduleAnimationBuilder setComposeTarget(@NonNull WindowContainer close,
@@ -1610,8 +1618,13 @@ class BackNavigationController {


                return () -> {
                return () -> {
                    try {
                    try {
                        if (hasTargetDetached() || !validateAnimationTargets(targets)) {
                            mNavigationMonitor.cancelBackNavigating("cancelAnimation");
                            mBackAnimationAdapter.getRunner().onAnimationCancelled();
                        } else {
                            mBackAnimationAdapter.getRunner().onAnimationStart(
                            mBackAnimationAdapter.getRunner().onAnimationStart(
                                    targets, null, null, callback);
                                    targets, null, null, callback);
                        }
                    } catch (RemoteException e) {
                    } catch (RemoteException e) {
                        e.printStackTrace();
                        e.printStackTrace();
                    }
                    }
@@ -1640,6 +1653,21 @@ class BackNavigationController {
        }
        }
    }
    }


    /**
     * Validate animation targets.
     */
    private static boolean validateAnimationTargets(RemoteAnimationTarget[] apps) {
        if (apps == null || apps.length == 0) {
            return false;
        }
        for (int i = apps.length - 1; i >= 0; --i) {
            if (!apps[i].leash.isValid()) {
                return false;
            }
        }
        return true;
    }

    /**
    /**
     * Finds next opening activity(ies) based on open targets, which could be:
     * Finds next opening activity(ies) based on open targets, which could be:
     * 1. If the open window is Task, then the open activity can either be an activity, or
     * 1. If the open window is Task, then the open activity can either be an activity, or
+4 −0
Original line number Original line Diff line number Diff line
@@ -94,6 +94,7 @@ public class BackNavigationControllerTests extends WindowTestsBase {
    private BackNavigationController mBackNavigationController;
    private BackNavigationController mBackNavigationController;
    private WindowManagerInternal mWindowManagerInternal;
    private WindowManagerInternal mWindowManagerInternal;
    private BackAnimationAdapter mBackAnimationAdapter;
    private BackAnimationAdapter mBackAnimationAdapter;
    private BackNavigationController.NavigationMonitor mNavigationMonitor;
    private Task mRootHomeTask;
    private Task mRootHomeTask;


    @Before
    @Before
@@ -105,6 +106,7 @@ public class BackNavigationControllerTests extends WindowTestsBase {
        mWindowManagerInternal = mock(WindowManagerInternal.class);
        mWindowManagerInternal = mock(WindowManagerInternal.class);
        LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
        LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
        mBackAnimationAdapter = mock(BackAnimationAdapter.class);
        mBackAnimationAdapter = mock(BackAnimationAdapter.class);
        mNavigationMonitor = mock(BackNavigationController.NavigationMonitor.class);
        mRootHomeTask = initHomeActivity();
        mRootHomeTask = initHomeActivity();
    }
    }


@@ -813,6 +815,7 @@ public class BackNavigationControllerTests extends WindowTestsBase {
                animationHandler.prepareAnimation(
                animationHandler.prepareAnimation(
                        BackNavigationInfo.TYPE_RETURN_TO_HOME,
                        BackNavigationInfo.TYPE_RETURN_TO_HOME,
                        mBackAnimationAdapter,
                        mBackAnimationAdapter,
                        mNavigationMonitor,
                        task,
                        task,
                        mRootHomeTask,
                        mRootHomeTask,
                        bottomActivity,
                        bottomActivity,
@@ -832,6 +835,7 @@ public class BackNavigationControllerTests extends WindowTestsBase {
                animationHandler.prepareAnimation(
                animationHandler.prepareAnimation(
                        BackNavigationInfo.TYPE_CROSS_ACTIVITY,
                        BackNavigationInfo.TYPE_CROSS_ACTIVITY,
                        mBackAnimationAdapter,
                        mBackAnimationAdapter,
                        mNavigationMonitor,
                        task,
                        task,
                        task,
                        task,
                        topActivity,
                        topActivity,