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

Commit 5ce3e5d6 authored by Chris Li's avatar Chris Li
Browse files

Fix crash when continueTransitionReady without collecting transition

1. When deferTransitionReady is called, it should un-ready the sync
   group.
2. Do not call continueTransitionReady when the transition is no
   longer collecting, such as transition timeout or abort.

Bug: 207070762
Test: atest WmTests:TransitionTests
Change-Id: I33a211d574da54ed220c7d0f7c12e201c5e1f681
parent 38a3a662
Loading
Loading
Loading
Loading
+18 −12
Original line number Diff line number Diff line
@@ -2041,12 +2041,6 @@
      "group": "WM_DEBUG_CONFIGURATION",
      "at": "com\/android\/server\/wm\/ActivityRecord.java"
    },
    "-108248992": {
      "message": "Defer transition ready for TaskFragmentTransaction=%s",
      "level": "VERBOSE",
      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
      "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java"
    },
    "-106400104": {
      "message": "Preload recents with %s",
      "level": "DEBUG",
@@ -2095,12 +2089,6 @@
      "group": "WM_DEBUG_STATES",
      "at": "com\/android\/server\/wm\/TaskFragment.java"
    },
    "-79016993": {
      "message": "Continue transition ready for TaskFragmentTransaction=%s",
      "level": "VERBOSE",
      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
      "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java"
    },
    "-70719599": {
      "message": "Unregister remote animations for organizer=%s uid=%d pid=%d",
      "level": "VERBOSE",
@@ -3085,6 +3073,12 @@
      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
    },
    "851368695": {
      "message": "Deferred transition id=%d has been continued before the TaskFragmentTransaction=%s is finished",
      "level": "WARN",
      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
      "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java"
    },
    "872933199": {
      "message": "Changing focus from %s to %s displayId=%d Callers=%s",
      "level": "DEBUG",
@@ -3277,6 +3271,12 @@
      "group": "WM_DEBUG_CONFIGURATION",
      "at": "com\/android\/server\/wm\/ActivityRecord.java"
    },
    "1046228706": {
      "message": "Defer transition id=%d for TaskFragmentTransaction=%s",
      "level": "VERBOSE",
      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
      "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java"
    },
    "1046922686": {
      "message": "requestScrollCapture: caught exception dispatching callback: %s",
      "level": "WARN",
@@ -3319,6 +3319,12 @@
      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
      "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java"
    },
    "1075460705": {
      "message": "Continue transition id=%d for TaskFragmentTransaction=%s",
      "level": "VERBOSE",
      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
      "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java"
    },
    "1087494661": {
      "message": "Clear window stuck on animatingExit status: %s",
      "level": "WARN",
+25 −10
Original line number Diff line number Diff line
@@ -138,12 +138,12 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
                new SparseArray<>();

        /**
         * List of {@link TaskFragmentTransaction#getTransactionToken()} that have been sent to the
         * organizer. If the transaction is sent during a transition, the
         * {@link TransitionController} will wait until the transaction is finished.
         * Map from {@link TaskFragmentTransaction#getTransactionToken()} to the
         * {@link Transition#getSyncId()} that has been deferred. {@link TransitionController} will
         * wait until the organizer finished handling the {@link TaskFragmentTransaction}.
         * @see #onTransactionFinished(IBinder)
         */
        private final List<IBinder> mRunningTransactions = new ArrayList<>();
        private final ArrayMap<IBinder, Integer> mDeferredTransitions = new ArrayMap<>();

        TaskFragmentOrganizerState(ITaskFragmentOrganizer organizer, int pid, int uid) {
            mOrganizer = organizer;
@@ -190,9 +190,9 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
                taskFragment.removeImmediately();
                mOrganizedTaskFragments.remove(taskFragment);
            }
            for (int i = mRunningTransactions.size() - 1; i >= 0; i--) {
            for (int i = mDeferredTransitions.size() - 1; i >= 0; i--) {
                // Cleanup any running transaction to unblock the current transition.
                onTransactionFinished(mRunningTransactions.get(i));
                onTransactionFinished(mDeferredTransitions.keyAt(i));
            }
            mOrganizer.asBinder().unlinkToDeath(this, 0 /*flags*/);
        }
@@ -357,19 +357,34 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
            if (!mWindowOrganizerController.getTransitionController().isCollecting()) {
                return;
            }
            final int transitionId = mWindowOrganizerController.getTransitionController()
                    .getCollectingTransitionId();
            ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
                    "Defer transition ready for TaskFragmentTransaction=%s", transactionToken);
            mRunningTransactions.add(transactionToken);
                    "Defer transition id=%d for TaskFragmentTransaction=%s", transitionId,
                    transactionToken);
            mDeferredTransitions.put(transactionToken, transitionId);
            mWindowOrganizerController.getTransitionController().deferTransitionReady();
        }

        /** Called when the transaction is finished. */
        void onTransactionFinished(@NonNull IBinder transactionToken) {
            if (!mRunningTransactions.remove(transactionToken)) {
            if (!mDeferredTransitions.containsKey(transactionToken)) {
                return;
            }
            final int transitionId = mDeferredTransitions.remove(transactionToken);
            if (!mWindowOrganizerController.getTransitionController().isCollecting()
                    || mWindowOrganizerController.getTransitionController()
                    .getCollectingTransitionId() != transitionId) {
                // This can happen when the transition is timeout or abort.
                ProtoLog.w(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
                        "Deferred transition id=%d has been continued before the"
                                + " TaskFragmentTransaction=%s is finished",
                        transitionId, transactionToken);
                return;
            }
            ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
                    "Continue transition ready for TaskFragmentTransaction=%s", transactionToken);
                    "Continue transition id=%d for TaskFragmentTransaction=%s", transitionId,
                    transactionToken);
            mWindowOrganizerController.getTransitionController().continueTransitionReady();
        }
    }
+2 −0
Original line number Diff line number Diff line
@@ -1880,6 +1880,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
     */
    void deferTransitionReady() {
        ++mReadyTracker.mDeferReadyDepth;
        // Make sure it wait until #continueTransitionReady() is called.
        mSyncEngine.setReady(mSyncId, false);
    }

    /** This undoes one call to {@link #deferTransitionReady}. */
+11 −0
Original line number Diff line number Diff line
@@ -226,6 +226,17 @@ class TransitionController {
        return mCollectingTransition != null;
    }

    /**
     * @return the collecting transition sync Id. This should only be called when there is a
     * collecting transition.
     */
    int getCollectingTransitionId() {
        if (mCollectingTransition == null) {
            throw new IllegalStateException("There is no collecting transition");
        }
        return mCollectingTransition.getSyncId();
    }

    /**
     * @return {@code true} if transition is actively collecting changes and `wc` is one of them.
     *                      This is {@code false} once a transition is playing.
+1 −0
Original line number Diff line number Diff line
@@ -1119,6 +1119,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
        final ArgumentCaptor<WindowContainerTransaction> wctCaptor =
                ArgumentCaptor.forClass(WindowContainerTransaction.class);
        doReturn(true).when(mTransitionController).isCollecting();
        doReturn(10).when(mTransitionController).getCollectingTransitionId();

        mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
        mController.dispatchPendingEvents();
Loading