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

Commit 6c613212 authored by Tiger's avatar Tiger
Browse files

Always call onStateChanged/onControlsChanged from the handler thread

InsetsController#mRunningAnimations might be accessed while these
methods are called, and it is not safe to be accessed from multiple
threads.

Fix: 309555866
Test: 1. Swipe to show status bar while watching a video in fullscreen
         in YouTube, and wait for the bar being hidden.
      2. Receive a heads up notification while watching a video in
         fullscreen in YouTube, and wait for the bar being hidden.
      Make sure there is no crash while doing 1 and 2.
Change-Id: Ifdbab981a8e37027a4e017a0050052f3fd8c6a48
parent 3fa36e3c
Loading
Loading
Loading
Loading
+21 −12
Original line number Diff line number Diff line
@@ -101,10 +101,8 @@ class InsetsPolicy {
        mPolicy = displayContent.getDisplayPolicy();
        final Resources r = mPolicy.getContext().getResources();
        mHideNavBarForKeyboard = r.getBoolean(R.bool.config_hideNavBarForKeyboard);
        mTransientControlTarget = new ControlTarget(
                stateController, displayContent.mWmService.mH, "TransientControlTarget");
        mPermanentControlTarget = new ControlTarget(
                stateController, displayContent.mWmService.mH, "PermanentControlTarget");
        mTransientControlTarget = new ControlTarget(displayContent, "TransientControlTarget");
        mPermanentControlTarget = new ControlTarget(displayContent, "PermanentControlTarget");
    }

    /** Updates the target which can control system bars. */
@@ -699,25 +697,36 @@ class InsetsPolicy {
        }
    }

    private static class ControlTarget implements InsetsControlTarget {
    private static class ControlTarget implements InsetsControlTarget, Runnable {

        private final Handler mHandler;
        private final Object mGlobalLock;
        private final InsetsState mState = new InsetsState();
        private final InsetsController mInsetsController;
        private final InsetsStateController mStateController;
        private final InsetsController mInsetsController;
        private final String mName;

        ControlTarget(InsetsStateController stateController, Handler handler, String name) {
            mStateController = stateController;
            mInsetsController = new InsetsController(new Host(handler, name));
        ControlTarget(DisplayContent displayContent, String name) {
            mHandler = displayContent.mWmService.mH;
            mGlobalLock = displayContent.mWmService.mGlobalLock;
            mStateController = displayContent.getInsetsStateController();
            mInsetsController = new InsetsController(new Host(mHandler, name));
            mName = name;
        }

        @Override
        public void notifyInsetsControlChanged() {
            mHandler.post(this);
        }

        @Override
        public void run() {
            synchronized (mGlobalLock) {
                mState.set(mStateController.getRawInsetsState(), true /* copySources */);
                mInsetsController.onStateChanged(mState);
                mInsetsController.onControlsChanged(mStateController.getControlsForDispatch(this));
            }
        }

        @Override
        public String toString() {