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

Commit a5373810 authored by Winson Chung's avatar Winson Chung
Browse files

Disallow concurrent recents transitions for the same display

- Launcher only handles a single recents transition at a time, and
  multiple running transitions can cause problems since the second
  will attempt to merge into the first started transition.
- Also tweak some protologs so they are easier to search for in the
  code

Bug: 432103567
Flag: EXEMPT bugfix
Test: atest RecentsTransitionHandlerTest
Change-Id: Ie7895fe77cb50e7703d0105cef9a18dc1156993f
parent fd0997af
Loading
Loading
Loading
Loading
+33 −16
Original line number Diff line number Diff line
@@ -203,9 +203,6 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
        // only care about latest one.
        mAnimApp = appThread;

        for (int i = 0; i < mStateListeners.size(); i++) {
            mStateListeners.get(i).onTransitionStateChanged(TRANSITION_STATE_REQUESTED);
        }
        // TODO(b/366021931): Formalize this later
        final boolean isSyntheticRequest = options.getBoolean(
                "is_synthetic_recents_transition", /* defaultValue= */ false);
@@ -215,6 +212,25 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
        if (displayId == INVALID_DISPLAY) {
            displayId = DEFAULT_DISPLAY;
        }

        // If there is an existing recents transition for the given display then we're not handling
        // the gesture correctly from the calling end. Canceling and starting a new transition is
        // possible but the legacy recents animation runner interface is not suited to handle events
        // from overlapping controllers. We just opt to log the error and preferably prevent this on
        // the calling end.
        final RecentsController lastController = findControllerForDisplay(displayId);
        if (lastController != null) {
            lastController.cancel(lastController.isSyntheticTransition()
                    ? "existing_running_synthetic_transition"
                    : "existing_running_transition");
            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                    "startRecentsTransition: Skipping due to existing transition");
            return null;
        }

        for (int i = 0; i < mStateListeners.size(); i++) {
            mStateListeners.get(i).onTransitionStateChanged(TRANSITION_STATE_REQUESTED);
        }
        if (isSyntheticRequest) {
            transition = startSyntheticRecentsTransition(listener, displayId);
        } else {
@@ -231,16 +247,9 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
            int displayId) {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                "RecentsTransitionHandler.startRecentsTransition(synthetic)");
        final RecentsController lastController = getLastController();
        if (lastController != null) {
            lastController.cancel(lastController.isSyntheticTransition()
                    ? "existing_running_synthetic_transition"
                    : "existing_running_transition");
            return null;
        }

        // Create a new synthetic transition and start it immediately
        final RecentsController controller = new RecentsController(listener);
        final RecentsController controller = new RecentsController(listener, displayId);
        controller.startSyntheticTransition(displayId);
        mControllers.add(controller);
        return SYNTHETIC_TRANSITION;
@@ -280,7 +289,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
            setTransitionForMixer.accept(transition);
        }

        final RecentsController controller = new RecentsController(listener);
        final RecentsController controller = new RecentsController(listener, displayId);
        if (transition != null) {
            controller.setTransition(transition);
            mControllers.add(controller);
@@ -303,11 +312,17 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
    }

    /**
     * Returns if there is currently a pending or active recents transition.
     * Finds an existing controller for the provided {@param displayId}.
     */
    @Nullable
    private RecentsController getLastController() {
        return !mControllers.isEmpty() ? mControllers.getLast() : null;
    private RecentsController findControllerForDisplay(int displayId) {
        for (int i = 0; i < mControllers.size(); i++) {
            final RecentsController controller = mControllers.get(i);
            if (controller.mDisplayId == displayId) {
                return controller;
            }
        }
        return null;
    }

    /**
@@ -392,6 +407,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
    class RecentsController extends IRecentsAnimationController.Stub {

        private final int mInstanceId;
        private final int mDisplayId;

        private IRecentsAnimationRunner mListener;
        private IBinder.DeathRecipient mDeathHandler;
@@ -461,8 +477,9 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
        // This stores the pending finish transaction to merge with the actual finish transaction
        private SurfaceControl.Transaction mPendingFinishTransaction;

        RecentsController(IRecentsAnimationRunner listener) {
        RecentsController(IRecentsAnimationRunner listener, int displayId) {
            mInstanceId = System.identityHashCode(this);
            mDisplayId = displayId;
            mListener = listener;
            mDeathHandler = () -> {
                mExecutor.execute(() -> {
+6 −6
Original line number Diff line number Diff line
@@ -525,22 +525,22 @@ public class DefaultMixedHandler implements MixedTransitionHandler,
    }

    private void setRecentsTransitionDuringSplit(IBinder transition, int displayId) {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a recents request while "
                + "Split-Screen is foreground, so treat it as Mixed.");
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                " Got a recents request while Split-Screen is foreground, so treat it as Mixed.");
        mActiveTransitions.add(createRecentsMixedTransition(
                MixedTransition.TYPE_RECENTS_DURING_SPLIT, transition, displayId));
    }

    private void setRecentsTransitionDuringKeyguard(IBinder transition, int displayId) {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a recents request while "
                + "keyguard is visible, so treat it as Mixed.");
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                " Got a recents request while keyguard is visible, so treat it as Mixed.");
        mActiveTransitions.add(createRecentsMixedTransition(
                MixedTransition.TYPE_RECENTS_DURING_KEYGUARD, transition, displayId));
    }

    private void setRecentsTransitionDuringDesktop(IBinder transition, int displayId) {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a recents request while "
                + "desktop mode is active, so treat it as Mixed.");
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                " Got a recents request while desktop mode is active, so treat it as Mixed.");
        mActiveTransitions.add(createRecentsMixedTransition(
                MixedTransition.TYPE_RECENTS_DURING_DESKTOP, transition, displayId));
    }
+9 −8
Original line number Diff line number Diff line
@@ -89,8 +89,8 @@ class RecentsMixedTransition extends DefaultMixedHandler.MixedTransition {
            @NonNull SurfaceControl.Transaction startTransaction,
            @NonNull SurfaceControl.Transaction finishTransaction,
            @NonNull Transitions.TransitionFinishCallback finishCallback) {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition for Recents during"
                + " Desktop #%d", info.getDebugId());
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                "Transition for Recents during Desktop #%d", info.getDebugId());

        if (mInfo == null) {
            mInfo = info;
@@ -124,12 +124,13 @@ class RecentsMixedTransition extends DefaultMixedHandler.MixedTransition {
            @NonNull SurfaceControl.Transaction startTransaction,
            @NonNull SurfaceControl.Transaction finishTransaction,
            @NonNull Transitions.TransitionFinishCallback finishCallback) {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Mixed transition for Recents during"
                + " Keyguard #%d", info.getDebugId());
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                "Mixed transition for Recents during Keyguard #%d", info.getDebugId());

        if (!mKeyguardHandler.isKeyguardShowing() || mKeyguardHandler.isKeyguardAnimating()) {
            ProtoLog.w(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Cancel mixed transition because "
                    + "keyguard state was changed #%d", info.getDebugId());
            ProtoLog.w(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                    "Cancel mixed transition because keyguard state was changed #%d",
                    info.getDebugId());
            return false;
        }
        if (mInfo == null) {
@@ -145,8 +146,8 @@ class RecentsMixedTransition extends DefaultMixedHandler.MixedTransition {
            @NonNull SurfaceControl.Transaction startTransaction,
            @NonNull SurfaceControl.Transaction finishTransaction,
            @NonNull Transitions.TransitionFinishCallback finishCallback) {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Mixed transition for Recents during"
                + " split screen #%d", info.getDebugId());
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                "Mixed transition for Recents during split screen #%d", info.getDebugId());

        for (int i = info.getChanges().size() - 1; i >= 0; --i) {
            final TransitionInfo.Change change = info.getChanges().get(i);
+19 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -215,6 +216,24 @@ public class RecentsTransitionHandlerTest extends ShellTestCase {
        }
    }

    @Test
    public void testStartRecentsTransitionTwiceCancelsFirst() throws Exception {
        final IRecentsAnimationRunner runner1 = mock(IRecentsAnimationRunner.class);
        final IRecentsAnimationRunner runner2 = mock(IRecentsAnimationRunner.class);

        final IBinder transition1 = startRecentsTransition(/* synthetic= */ true, runner1);
        verify(runner1).onAnimationStart(any(), any(), any(), any(), any(), any());

        // Start a new recents transition and verify the original runner is canceled and we don't
        // start the new transition either
        final IBinder transition2 = startRecentsTransition(/* synthetic= */ true, runner2);
        assertNull(transition2);
        verify(runner1).onAnimationCanceled(any(), any());
        verify(runner2, never()).onAnimationStart(any(), any(), any(), any(), any(), any());

        assertNull(mRecentsTransitionHandler.findController(transition1));
    }

    @Test
    public void testStartSyntheticRecentsTransition_callsOnAnimationStartAndFinishCallback() throws Exception {
        final IRecentsAnimationRunner runner = mock(IRecentsAnimationRunner.class);