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

Commit 46ecdc5c authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Avoid getting crashed by slow transition

This avoids extreme cases when the device is slow or the load of
system/systemui is heavy.

SystemUI crashes:
1. OPEN transition T1
2. Swipe up, queued transition T2
3. T1 timed out, moveToPlaying
   (added to mPlayingTransitions)
4. T2 starts collecting
5. startTransition of T1
   (STATE_PLAYING -> STATE_STARTED)
6. finishTransition from RemoteTransitionHandler
7. Got crash by "Can't finish a non-playing transition"
   (in mPlayingTransitions but with STATE_STARTED)

System server crashes:
When executing a non-CHANGE transition with a display change,
(open an activity and request to change display orientation)
if IDisplayChangeWindowCallback#continueDisplayChange is called
from remote after transition timeout, the exception "Trying to
rotate outside a transition" will throw at display thread.

Bug: 265852118
Bug: 261645736
Test: Set break point at WindowOrganizerController#startTransition
      to simulate the slowness. Launch app, swipe up, rotate.
      The device still works normally after resuming the break point.
Test: CtsWindowManagerDeviceTestCases
Change-Id: Ia0d97823886eff1c935a0cd7f6f6ac6abf3659d5
parent f558dd2d
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -605,11 +605,16 @@ public class ActivityStartController {
        final Task task = r.getTask();
        mService.deferWindowLayout();
        try {
            r.mTransitionController.requestStartTransition(transition,
                    task, remoteTransition, null /* displayChange */);
            r.mTransitionController.collect(task);
            r.mTransitionController.setTransientLaunch(r,
                    TaskDisplayArea.getRootTaskAbove(rootTask));
            final TransitionController controller = r.mTransitionController;
            if (controller.getTransitionPlayer() != null) {
                controller.requestStartTransition(transition, task, remoteTransition,
                        null /* displayChange */);
                controller.collect(task);
                controller.setTransientLaunch(r, TaskDisplayArea.getRootTaskAbove(rootTask));
            } else {
                // The transition player might be died when executing the queued transition.
                transition.abort();
            }
            task.moveToFront("startExistingRecents");
            task.mInResumeTopActivity = true;
            task.resumeTopActivity(null /* prev */, options, true /* deferPause */);
+2 −1
Original line number Diff line number Diff line
@@ -635,7 +635,8 @@ public class DisplayRotation {

        if (mDisplayContent.mTransitionController.isShellTransitionsEnabled()) {
            if (!mDisplayContent.mTransitionController.isCollecting()) {
                throw new IllegalStateException("Trying to rotate outside a transition");
                // The remote may be too slow to response before transition timeout.
                Slog.e(TAG, "Trying to continue rotation outside a transition");
            }
            mDisplayContent.mTransitionController.collect(mDisplayContent);
        }
+4 −1
Original line number Diff line number Diff line
@@ -418,7 +418,10 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
        if (mState < STATE_COLLECTING) {
            throw new IllegalStateException("Can't start Transition which isn't collecting.");
        } else if (mState >= STATE_STARTED) {
            Slog.w(TAG, "Transition already started: " + mSyncId);
            Slog.w(TAG, "Transition already started id=" + mSyncId + " state=" + mState);
            // The transition may be aborted (STATE_ABORT) or timed out (STATE_PLAYING by
            // SyncGroup#finishNow), so do not revert the state to STATE_STARTED.
            return;
        }
        mState = STATE_STARTED;
        ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Starting Transition %d",