summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/input/InputDispatcher.cpp57
-rw-r--r--services/input/InputDispatcher.h15
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(