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

Commit bda3851a authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge "Disallow concurrent recents transitions for the same display" into main

parents 35b7c339 a5373810
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);