From f46779fe014ba78478d0a0a88b3fd654d635f18b Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 31 May 2018 14:04:59 -0700 Subject: [PATCH] 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 --- .../states/InternalStateHandler.java | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/com/android/launcher3/states/InternalStateHandler.java b/src/com/android/launcher3/states/InternalStateHandler.java index cf7c6ba398..c6370c5c5f 100644 --- a/src/com/android/launcher3/states/InternalStateHandler.java +++ b/src/com/android/launcher3/states/InternalStateHandler.java @@ -96,10 +96,12 @@ public abstract class InternalStateHandler extends Binder { private WeakReference mPendingHandler = new WeakReference<>(null); private MainThreadExecutor mMainThreadExecutor; - public synchronized void schedule(InternalStateHandler handler) { - mPendingHandler = new WeakReference<>(handler); - if (mMainThreadExecutor == null) { - mMainThreadExecutor = new MainThreadExecutor(); + public void schedule(InternalStateHandler handler) { + synchronized (this) { + mPendingHandler = new WeakReference<>(handler); + if (mMainThreadExecutor == null) { + mMainThreadExecutor = new MainThreadExecutor(); + } } mMainThreadExecutor.execute(this); } @@ -118,23 +120,25 @@ 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) { - if (mPendingHandler.get() == handler) { - mPendingHandler.clear(); - return true; + public boolean clearReference(InternalStateHandler handler) { + synchronized (this) { + if (mPendingHandler.get() == handler) { + mPendingHandler.clear(); + return true; + } + return false; } - return false; } public boolean hasPending() {