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
This commit is contained in:
Sunny Goyal
2018-05-31 14:04:59 -07:00
parent f4392dbf5a
commit f46779fe01

View File

@@ -96,10 +96,12 @@ public abstract class InternalStateHandler extends Binder {
private WeakReference<InternalStateHandler> 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() {