diff options
Diffstat (limited to 'services/input')
-rw-r--r-- | services/input/InputDispatcher.cpp | 57 | ||||
-rw-r--r-- | services/input/InputDispatcher.h | 15 |
2 files changed, 54 insertions, 18 deletions
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp index a63b6f5..d04aa68 100644 --- a/services/input/InputDispatcher.cpp +++ b/services/input/InputDispatcher.cpp @@ -1872,7 +1872,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry); // Publish the key event. - status = connection->inputPublisher.publishKeyEvent( + status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq, keyEntry->deviceId, keyEntry->source, dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags, keyEntry->keyCode, keyEntry->scanCode, @@ -1916,7 +1916,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, } // Publish the motion event. - status = connection->inputPublisher.publishMotionEvent( + status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq, motionEntry->deviceId, motionEntry->source, dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags, motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState, @@ -1967,10 +1967,10 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, } void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime, - const sp<Connection>& connection, bool handled) { + const sp<Connection>& connection, uint32_t seq, bool handled) { #if DEBUG_DISPATCH_CYCLE - ALOGD("channel '%s' ~ finishDispatchCycle - handled=%s", - connection->getInputChannelName(), toString(handled)); + ALOGD("channel '%s' ~ finishDispatchCycle - seq=%u, handled=%s", + connection->getInputChannelName(), seq, toString(handled)); #endif connection->inputPublisherBlocked = false; @@ -1981,7 +1981,7 @@ void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime, } // Notify other system components and prepare to start the next dispatch cycle. - onDispatchCycleFinishedLocked(currentTime, connection, handled); + onDispatchCycleFinishedLocked(currentTime, connection, seq, handled); } void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime, @@ -2047,12 +2047,13 @@ int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) { bool gotOne = false; status_t status; for (;;) { - bool handled = false; - status = connection->inputPublisher.receiveFinishedSignal(&handled); + uint32_t seq; + bool handled; + status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled); if (status) { break; } - d->finishDispatchCycleLocked(currentTime, connection, handled); + d->finishDispatchCycleLocked(currentTime, connection, seq, handled); gotOne = true; } if (gotOne) { @@ -3171,10 +3172,11 @@ ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputC } void InputDispatcher::onDispatchCycleFinishedLocked( - nsecs_t currentTime, const sp<Connection>& connection, bool handled) { + nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled) { CommandEntry* commandEntry = postCommandLocked( & InputDispatcher::doDispatchCycleFinishedLockedInterruptible); commandEntry->connection = connection; + commandEntry->seq = seq; commandEntry->handled = handled; } @@ -3268,12 +3270,13 @@ void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible( void InputDispatcher::doDispatchCycleFinishedLockedInterruptible( CommandEntry* commandEntry) { sp<Connection> connection = commandEntry->connection; + uint32_t seq = commandEntry->seq; bool handled = commandEntry->handled; - if (!connection->waitQueue.isEmpty()) { - // Handle post-event policy actions. + // Handle post-event policy actions. + DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq); + if (dispatchEntry) { bool restartEvent; - DispatchEntry* dispatchEntry = connection->waitQueue.head; if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) { KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry); restartEvent = afterKeyEventLockedInterruptible(connection, @@ -3290,8 +3293,8 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible( // Note that because the lock might have been released, it is possible that the // contents of the wait queue to have been drained, so we need to double-check // a few things. - if (connection->waitQueue.head == dispatchEntry) { - connection->waitQueue.dequeueAtHead(); + if (dispatchEntry == connection->findWaitQueueEntry(seq)) { + connection->waitQueue.dequeue(dispatchEntry); if (restartEvent && connection->status == Connection::STATUS_NORMAL) { connection->outboundQueue.enqueueAtHead(dispatchEntry); } else { @@ -3635,8 +3638,11 @@ InputDispatcher::MotionEntry::~MotionEntry() { // --- InputDispatcher::DispatchEntry --- +volatile int32_t InputDispatcher::DispatchEntry::sNextSeqAtomic; + InputDispatcher::DispatchEntry::DispatchEntry(EventEntry* eventEntry, int32_t targetFlags, float xOffset, float yOffset, float scaleFactor) : + seq(nextSeq()), eventEntry(eventEntry), targetFlags(targetFlags), xOffset(xOffset), yOffset(yOffset), scaleFactor(scaleFactor), resolvedAction(0), resolvedFlags(0) { @@ -3647,6 +3653,15 @@ InputDispatcher::DispatchEntry::~DispatchEntry() { eventEntry->release(); } +uint32_t InputDispatcher::DispatchEntry::nextSeq() { + // Sequence number 0 is reserved and will never be returned. + uint32_t seq; + do { + seq = android_atomic_inc(&sNextSeqAtomic); + } while (!seq); + return seq; +} + // --- InputDispatcher::InputState --- @@ -3999,11 +4014,21 @@ const char* InputDispatcher::Connection::getStatusLabel() const { } } +InputDispatcher::DispatchEntry* InputDispatcher::Connection::findWaitQueueEntry(uint32_t seq) { + for (DispatchEntry* entry = waitQueue.head; entry != NULL; entry = entry->next) { + if (entry->seq == seq) { + return entry; + } + } + return NULL; +} + // --- InputDispatcher::CommandEntry --- InputDispatcher::CommandEntry::CommandEntry(Command command) : - command(command), eventTime(0), keyEntry(NULL), userActivityEventType(0), handled(false) { + command(command), eventTime(0), keyEntry(NULL), userActivityEventType(0), + seq(0), handled(false) { } InputDispatcher::CommandEntry::~CommandEntry() { diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h index 1311465..03a824b 100644 --- a/services/input/InputDispatcher.h +++ b/services/input/InputDispatcher.h @@ -27,6 +27,7 @@ #include <utils/String8.h> #include <utils/Looper.h> #include <utils/BitSet.h> +#include <cutils/atomic.h> #include <stddef.h> #include <unistd.h> @@ -522,6 +523,8 @@ private: // Tracks the progress of dispatching a particular event to a particular connection. struct DispatchEntry : Link<DispatchEntry> { + const uint32_t seq; // unique sequence number, never 0 + EventEntry* eventEntry; // the event to dispatch int32_t targetFlags; float xOffset; @@ -543,6 +546,11 @@ private: inline bool isSplit() const { return targetFlags & InputTarget::FLAG_SPLIT; } + + private: + static volatile int32_t sNextSeqAtomic; + + static uint32_t nextSeq(); }; // A command entry captures state and behavior for an action to be performed in the @@ -578,6 +586,7 @@ private: sp<InputApplicationHandle> inputApplicationHandle; sp<InputWindowHandle> inputWindowHandle; int32_t userActivityEventType; + uint32_t seq; bool handled; }; @@ -797,6 +806,8 @@ private: inline const char* getInputChannelName() const { return inputChannel->getName().string(); } const char* getStatusLabel() const; + + DispatchEntry* findWaitQueueEntry(uint32_t seq); }; enum DropReason { @@ -1000,7 +1011,7 @@ private: EventEntry* eventEntry, const InputTarget* inputTarget, int32_t dispatchMode); void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection); void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, - bool handled); + uint32_t seq, bool handled); void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, bool notify); void drainDispatchQueueLocked(Queue<DispatchEntry>* queue); @@ -1034,7 +1045,7 @@ private: // Interesting events that we might like to log or tell the framework about. void onDispatchCycleFinishedLocked( - nsecs_t currentTime, const sp<Connection>& connection, bool handled); + nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled); void onDispatchCycleBrokenLocked( nsecs_t currentTime, const sp<Connection>& connection); void onANRLocked( |