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

Commit f46779fe authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Do not run StateHandler code while holding the lock

Deadlock:
Main thread:
  InternalStateHandler.run() =>
  	 LauncherFrameDrawn =>
  	 Switch MotionEventQueue to Main thread =>
  	 Try to acquire MotionEventQueue lock while holding InternalStateHandler lock

Remote UI thread
  Recents Animation cancel on MotionEventQueue =>
     Cancel SwipeHandler =>
     Clear previously registered InternalStateHandler =>
     Try to acquire InternalStateHandler lock while holding MotionEventQueue lock

Bug: 80536505
Change-Id: I75e522edea2a76f8bc90e8abc2a174583cc709c4
parent f4392dbf
Loading
Loading
Loading
Loading
+15 −11
Original line number Diff line number Diff line
@@ -96,11 +96,13 @@ public abstract class InternalStateHandler extends Binder {
        private WeakReference<InternalStateHandler> mPendingHandler = new WeakReference<>(null);
        private MainThreadExecutor mMainThreadExecutor;

        public synchronized void schedule(InternalStateHandler handler) {
        public void schedule(InternalStateHandler handler) {
            synchronized (this) {
                mPendingHandler = new WeakReference<>(handler);
                if (mMainThreadExecutor == null) {
                    mMainThreadExecutor = new MainThreadExecutor();
                }
            }
            mMainThreadExecutor.execute(this);
        }

@@ -118,24 +120,26 @@ public abstract class InternalStateHandler extends Binder {
            initIfPending(launcher, launcher.isStarted());
        }

        public synchronized boolean initIfPending(Launcher launcher, boolean alreadyOnHome) {
        public boolean initIfPending(Launcher launcher, boolean alreadyOnHome) {
            InternalStateHandler pendingHandler = mPendingHandler.get();
            if (pendingHandler != null) {
                if (!pendingHandler.init(launcher, alreadyOnHome)) {
                    mPendingHandler.clear();
                    clearReference(pendingHandler);
                }
                return true;
            }
            return false;
        }

        public synchronized boolean clearReference(InternalStateHandler handler) {
        public boolean clearReference(InternalStateHandler handler) {
            synchronized (this) {
                if (mPendingHandler.get() == handler) {
                    mPendingHandler.clear();
                    return true;
                }
                return false;
            }
        }

        public boolean hasPending() {
            return mPendingHandler.get() != null;