summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2010-08-18 14:20:24 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2010-08-18 14:20:24 -0700
commit671cc0ec30dfd73e17c3f3bd0170341c06ac945e (patch)
treee9cbecb4b7aeb837ff4f2cceb4030e59cd48856d /libs
parentf96a508d06f765aa765044312ec3fd3533886d6e (diff)
parent8fd80e924a2f40f6a785f834914f8a6f18a3aa9d (diff)
downloadframeworks_base-671cc0ec30dfd73e17c3f3bd0170341c06ac945e.zip
frameworks_base-671cc0ec30dfd73e17c3f3bd0170341c06ac945e.tar.gz
frameworks_base-671cc0ec30dfd73e17c3f3bd0170341c06ac945e.tar.bz2
am 8fd80e92: am 72ce4235: Merge "Fix possible race conditions during channel unregistration." into gingerbread
Merge commit '8fd80e924a2f40f6a785f834914f8a6f18a3aa9d' * commit '8fd80e924a2f40f6a785f834914f8a6f18a3aa9d': Fix possible race conditions during channel unregistration.
Diffstat (limited to 'libs')
-rw-r--r--libs/ui/InputDispatcher.cpp32
1 files changed, 20 insertions, 12 deletions
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index b53f140..13030b5 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -433,8 +433,7 @@ void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTi
for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
- ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(
- inputTarget.inputChannel->getReceivePipeFd());
+ ssize_t connectionIndex = getConnectionIndex(inputTarget.inputChannel);
if (connectionIndex >= 0) {
sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
@@ -1367,12 +1366,10 @@ status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChan
LOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().string());
#endif
- int receiveFd;
{ // acquire lock
AutoMutex _l(mLock);
- receiveFd = inputChannel->getReceivePipeFd();
- if (mConnectionsByReceiveFd.indexOfKey(receiveFd) >= 0) {
+ if (getConnectionIndex(inputChannel) >= 0) {
LOGW("Attempted to register already registered input channel '%s'",
inputChannel->getName().string());
return BAD_VALUE;
@@ -1386,12 +1383,13 @@ status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChan
return status;
}
+ int32_t receiveFd = inputChannel->getReceivePipeFd();
mConnectionsByReceiveFd.add(receiveFd, connection);
+ mPollLoop->setCallback(receiveFd, POLLIN, handleReceiveCallback, this);
+
runCommandsLockedInterruptible();
} // release lock
-
- mPollLoop->setCallback(receiveFd, POLLIN, handleReceiveCallback, this);
return OK;
}
@@ -1400,12 +1398,10 @@ status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputCh
LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
#endif
- int32_t receiveFd;
{ // acquire lock
AutoMutex _l(mLock);
- receiveFd = inputChannel->getReceivePipeFd();
- ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(receiveFd);
+ ssize_t connectionIndex = getConnectionIndex(inputChannel);
if (connectionIndex < 0) {
LOGW("Attempted to unregister already unregistered input channel '%s'",
inputChannel->getName().string());
@@ -1417,20 +1413,32 @@ status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputCh
connection->status = Connection::STATUS_ZOMBIE;
+ mPollLoop->removeCallback(inputChannel->getReceivePipeFd());
+
nsecs_t currentTime = now();
abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
runCommandsLockedInterruptible();
} // release lock
- mPollLoop->removeCallback(receiveFd);
-
// Wake the poll loop because removing the connection may have changed the current
// synchronization state.
mPollLoop->wake();
return OK;
}
+ssize_t InputDispatcher::getConnectionIndex(const sp<InputChannel>& inputChannel) {
+ ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(inputChannel->getReceivePipeFd());
+ if (connectionIndex >= 0) {
+ sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
+ if (connection->inputChannel.get() == inputChannel.get()) {
+ return connectionIndex;
+ }
+ }
+
+ return -1;
+}
+
void InputDispatcher::activateConnectionLocked(Connection* connection) {
for (size_t i = 0; i < mActiveConnections.size(); i++) {
if (mActiveConnections.itemAt(i) == connection) {