Skip to content

Commit 074b8b7

Browse files
author
Jeff Brown
committed
Eliminate potential reentrance from unregisterInputChannel.
Ensure that all callbacks into the window manager policy occur on the input dispatcher thread in the right place. This fixes a potential deadlock that may occur if the window manager unregisters an input channel while holding its own lock. The change is simply to defer running asynchronous commands (usually callbacks into the policy) until the next iteration of the dispatch looper thread. Bug: 7382388 Change-Id: I90095580d717fcddb2209ef332df56400f837a34
1 parent c8dc8eb commit 074b8b7

File tree

2 files changed

+16
-6
lines changed

2 files changed

+16
-6
lines changed

services/input/InputDispatcher.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -224,10 +224,16 @@ void InputDispatcher::dispatchOnce() {
224224
AutoMutex _l(mLock);
225225
mDispatcherIsAliveCondition.broadcast();
226226

227-
dispatchOnceInnerLocked(&nextWakeupTime);
227+
// Run a dispatch loop if there are no pending commands.
228+
// The dispatch loop might enqueue commands to run afterwards.
229+
if (!haveCommandsLocked()) {
230+
dispatchOnceInnerLocked(&nextWakeupTime);
231+
}
228232

233+
// Run all pending commands if there are any.
234+
// If any commands were run then force the next poll to wake up immediately.
229235
if (runCommandsLockedInterruptible()) {
230-
nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
236+
nextWakeupTime = LONG_LONG_MIN;
231237
}
232238
} // release lock
233239

@@ -562,6 +568,10 @@ bool InputDispatcher::isStaleEventLocked(nsecs_t currentTime, EventEntry* entry)
562568
return currentTime - entry->eventTime >= STALE_EVENT_TIMEOUT;
563569
}
564570

571+
bool InputDispatcher::haveCommandsLocked() const {
572+
return !mCommandQueue.isEmpty();
573+
}
574+
565575
bool InputDispatcher::runCommandsLockedInterruptible() {
566576
if (mCommandQueue.isEmpty()) {
567577
return false;
@@ -3247,9 +3257,10 @@ status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChan
32473257
}
32483258

32493259
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
3250-
3251-
runCommandsLockedInterruptible();
32523260
} // release lock
3261+
3262+
// Wake the looper because some connections have changed.
3263+
mLooper->wake();
32533264
return OK;
32543265
}
32553266

@@ -3294,8 +3305,6 @@ status_t InputDispatcher::unregisterInputChannelLocked(const sp<InputChannel>& i
32943305
nsecs_t currentTime = now();
32953306
abortBrokenDispatchCycleLocked(currentTime, connection, notify);
32963307

3297-
runCommandsLockedInterruptible();
3298-
32993308
connection->status = Connection::STATUS_ZOMBIE;
33003309
return OK;
33013310
}

services/input/InputDispatcher.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,7 @@ class InputDispatcher : public InputDispatcherInterface {
899899
KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime);
900900

901901
// Deferred command processing.
902+
bool haveCommandsLocked() const;
902903
bool runCommandsLockedInterruptible();
903904
CommandEntry* postCommandLocked(Command command);
904905

0 commit comments

Comments
 (0)