blob: 13030b56e01f57e544261a8470de7e22152d3dbc [file] [log] [blame]
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4// The input dispatcher.
5//
6#define LOG_TAG "InputDispatcher"
7
8//#define LOG_NDEBUG 0
9
10// Log detailed debug messages about each inbound event notification to the dispatcher.
Jeff Brown349703e2010-06-22 01:27:15 -070011#define DEBUG_INBOUND_EVENT_DETAILS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070012
13// Log detailed debug messages about each outbound event processed by the dispatcher.
Jeff Brown349703e2010-06-22 01:27:15 -070014#define DEBUG_OUTBOUND_EVENT_DETAILS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070015
16// Log debug messages about batching.
Jeff Brown349703e2010-06-22 01:27:15 -070017#define DEBUG_BATCHING 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070018
19// Log debug messages about the dispatch cycle.
Jeff Brown349703e2010-06-22 01:27:15 -070020#define DEBUG_DISPATCH_CYCLE 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070021
Jeff Brown9c3cda02010-06-15 01:31:58 -070022// Log debug messages about registrations.
Jeff Brown349703e2010-06-22 01:27:15 -070023#define DEBUG_REGISTRATION 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070024
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070025// Log debug messages about performance statistics.
Jeff Brown349703e2010-06-22 01:27:15 -070026#define DEBUG_PERFORMANCE_STATISTICS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070027
Jeff Brown7fbdc842010-06-17 20:52:56 -070028// Log debug messages about input event injection.
Jeff Brown349703e2010-06-22 01:27:15 -070029#define DEBUG_INJECTION 0
Jeff Brown7fbdc842010-06-17 20:52:56 -070030
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070031#include <cutils/log.h>
32#include <ui/InputDispatcher.h>
33
34#include <stddef.h>
35#include <unistd.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070036#include <errno.h>
37#include <limits.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070038
39namespace android {
40
41// TODO, this needs to be somewhere else, perhaps in the policy
42static inline bool isMovementKey(int32_t keyCode) {
Jeff Brownfd0358292010-06-30 16:10:35 -070043 return keyCode == AKEYCODE_DPAD_UP
44 || keyCode == AKEYCODE_DPAD_DOWN
45 || keyCode == AKEYCODE_DPAD_LEFT
46 || keyCode == AKEYCODE_DPAD_RIGHT;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070047}
48
Jeff Brown7fbdc842010-06-17 20:52:56 -070049static inline nsecs_t now() {
50 return systemTime(SYSTEM_TIME_MONOTONIC);
51}
52
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070053// --- InputDispatcher ---
54
Jeff Brown9c3cda02010-06-15 01:31:58 -070055InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070056 mPolicy(policy) {
Dianne Hackborn85448bb2010-07-07 14:27:31 -070057 mPollLoop = new PollLoop(false);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070058
59 mInboundQueue.head.refCount = -1;
60 mInboundQueue.head.type = EventEntry::TYPE_SENTINEL;
61 mInboundQueue.head.eventTime = LONG_LONG_MIN;
62
63 mInboundQueue.tail.refCount = -1;
64 mInboundQueue.tail.type = EventEntry::TYPE_SENTINEL;
65 mInboundQueue.tail.eventTime = LONG_LONG_MAX;
66
67 mKeyRepeatState.lastKeyEntry = NULL;
Jeff Brown9c3cda02010-06-15 01:31:58 -070068
69 mCurrentInputTargetsValid = false;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070070}
71
72InputDispatcher::~InputDispatcher() {
73 resetKeyRepeatLocked();
74
75 while (mConnectionsByReceiveFd.size() != 0) {
76 unregisterInputChannel(mConnectionsByReceiveFd.valueAt(0)->inputChannel);
77 }
78
79 for (EventEntry* entry = mInboundQueue.head.next; entry != & mInboundQueue.tail; ) {
80 EventEntry* next = entry->next;
81 mAllocator.releaseEventEntry(next);
82 entry = next;
83 }
84}
85
86void InputDispatcher::dispatchOnce() {
Jeff Brown9c3cda02010-06-15 01:31:58 -070087 nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070088
Jeff Brown9c3cda02010-06-15 01:31:58 -070089 bool skipPoll = false;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070090 nsecs_t currentTime;
91 nsecs_t nextWakeupTime = LONG_LONG_MAX;
92 { // acquire lock
93 AutoMutex _l(mLock);
Jeff Brown7fbdc842010-06-17 20:52:56 -070094 currentTime = now();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070095
96 // Reset the key repeat timer whenever we disallow key events, even if the next event
97 // is not a key. This is to ensure that we abort a key repeat if the device is just coming
98 // out of sleep.
99 // XXX we should handle resetting input state coming out of sleep more generally elsewhere
Jeff Brown9c3cda02010-06-15 01:31:58 -0700100 if (keyRepeatTimeout < 0) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700101 resetKeyRepeatLocked();
102 }
103
Jeff Brown7fbdc842010-06-17 20:52:56 -0700104 // Detect and process timeouts for all connections and determine if there are any
105 // synchronous event dispatches pending. This step is entirely non-interruptible.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700106 bool hasPendingSyncTarget = false;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700107 size_t activeConnectionCount = mActiveConnections.size();
108 for (size_t i = 0; i < activeConnectionCount; i++) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700109 Connection* connection = mActiveConnections.itemAt(i);
110
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700111 if (connection->hasPendingSyncTarget()) {
112 hasPendingSyncTarget = true;
113 }
114
Jeff Brown7fbdc842010-06-17 20:52:56 -0700115 nsecs_t connectionTimeoutTime = connection->nextTimeoutTime;
116 if (connectionTimeoutTime <= currentTime) {
117 mTimedOutConnections.add(connection);
118 } else if (connectionTimeoutTime < nextWakeupTime) {
119 nextWakeupTime = connectionTimeoutTime;
120 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700121 }
122
Jeff Brown7fbdc842010-06-17 20:52:56 -0700123 size_t timedOutConnectionCount = mTimedOutConnections.size();
124 for (size_t i = 0; i < timedOutConnectionCount; i++) {
125 Connection* connection = mTimedOutConnections.itemAt(i);
126 timeoutDispatchCycleLocked(currentTime, connection);
127 skipPoll = true;
128 }
129 mTimedOutConnections.clear();
130
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700131 // If we don't have a pending sync target, then we can begin delivering a new event.
132 // (Otherwise we wait for dispatch to complete for that target.)
133 if (! hasPendingSyncTarget) {
134 if (mInboundQueue.isEmpty()) {
135 if (mKeyRepeatState.lastKeyEntry) {
136 if (currentTime >= mKeyRepeatState.nextRepeatTime) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700137 processKeyRepeatLockedInterruptible(currentTime, keyRepeatTimeout);
138 skipPoll = true;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700139 } else {
140 if (mKeyRepeatState.nextRepeatTime < nextWakeupTime) {
141 nextWakeupTime = mKeyRepeatState.nextRepeatTime;
142 }
143 }
144 }
145 } else {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700146 // Inbound queue has at least one entry.
147 // Start processing it but leave it on the queue until later so that the
148 // input reader can keep appending samples onto a motion event between the
149 // time we started processing it and the time we finally enqueue dispatch
150 // entries for it.
151 EventEntry* entry = mInboundQueue.head.next;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700152
153 switch (entry->type) {
154 case EventEntry::TYPE_CONFIGURATION_CHANGED: {
155 ConfigurationChangedEntry* typedEntry =
156 static_cast<ConfigurationChangedEntry*>(entry);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700157 processConfigurationChangedLockedInterruptible(currentTime, typedEntry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700158 break;
159 }
160
161 case EventEntry::TYPE_KEY: {
162 KeyEntry* typedEntry = static_cast<KeyEntry*>(entry);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700163 processKeyLockedInterruptible(currentTime, typedEntry, keyRepeatTimeout);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700164 break;
165 }
166
167 case EventEntry::TYPE_MOTION: {
168 MotionEntry* typedEntry = static_cast<MotionEntry*>(entry);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700169 processMotionLockedInterruptible(currentTime, typedEntry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700170 break;
171 }
172
173 default:
174 assert(false);
175 break;
176 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700177
178 // Dequeue and release the event entry that we just processed.
179 mInboundQueue.dequeue(entry);
180 mAllocator.releaseEventEntry(entry);
181 skipPoll = true;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700182 }
183 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700184
185 // Run any deferred commands.
186 skipPoll |= runCommandsLockedInterruptible();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700187 } // release lock
188
Jeff Brown9c3cda02010-06-15 01:31:58 -0700189 // If we dispatched anything, don't poll just now. Wait for the next iteration.
190 // Contents may have shifted during flight.
191 if (skipPoll) {
192 return;
193 }
194
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700195 // Wait for callback or timeout or wake.
196 nsecs_t timeout = nanoseconds_to_milliseconds(nextWakeupTime - currentTime);
197 int32_t timeoutMillis = timeout > INT_MAX ? -1 : timeout > 0 ? int32_t(timeout) : 0;
198 mPollLoop->pollOnce(timeoutMillis);
199}
200
Jeff Brown9c3cda02010-06-15 01:31:58 -0700201bool InputDispatcher::runCommandsLockedInterruptible() {
202 if (mCommandQueue.isEmpty()) {
203 return false;
204 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700205
Jeff Brown9c3cda02010-06-15 01:31:58 -0700206 do {
207 CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
208
209 Command command = commandEntry->command;
210 (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
211
Jeff Brown7fbdc842010-06-17 20:52:56 -0700212 commandEntry->connection.clear();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700213 mAllocator.releaseCommandEntry(commandEntry);
214 } while (! mCommandQueue.isEmpty());
215 return true;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700216}
217
Jeff Brown9c3cda02010-06-15 01:31:58 -0700218InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
219 CommandEntry* commandEntry = mAllocator.obtainCommandEntry(command);
220 mCommandQueue.enqueueAtTail(commandEntry);
221 return commandEntry;
222}
223
224void InputDispatcher::processConfigurationChangedLockedInterruptible(
225 nsecs_t currentTime, ConfigurationChangedEntry* entry) {
226#if DEBUG_OUTBOUND_EVENT_DETAILS
227 LOGD("processConfigurationChanged - eventTime=%lld", entry->eventTime);
228#endif
229
Jeff Brown0b72e822010-06-29 16:52:21 -0700230 // Reset key repeating in case a keyboard device was added or removed or something.
231 resetKeyRepeatLocked();
232
Jeff Brown9c3cda02010-06-15 01:31:58 -0700233 mLock.unlock();
234
235 mPolicy->notifyConfigurationChanged(entry->eventTime);
236
237 mLock.lock();
238}
239
240void InputDispatcher::processKeyLockedInterruptible(
241 nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700242#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brownc5ed5912010-07-14 18:48:53 -0700243 LOGD("processKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700244 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
Jeff Brownc5ed5912010-07-14 18:48:53 -0700245 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, entry->action,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700246 entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
247 entry->downTime);
248#endif
249
Jeff Brownc5ed5912010-07-14 18:48:53 -0700250 if (entry->action == AKEY_EVENT_ACTION_DOWN && ! entry->isInjected()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700251 if (mKeyRepeatState.lastKeyEntry
252 && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
253 // We have seen two identical key downs in a row which indicates that the device
254 // driver is automatically generating key repeats itself. We take note of the
255 // repeat here, but we disable our own next key repeat timer since it is clear that
256 // we will not need to synthesize key repeats ourselves.
257 entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
258 resetKeyRepeatLocked();
259 mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
260 } else {
261 // Not a repeat. Save key down state in case we do see a repeat later.
262 resetKeyRepeatLocked();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700263 mKeyRepeatState.nextRepeatTime = entry->eventTime + keyRepeatTimeout;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700264 }
265 mKeyRepeatState.lastKeyEntry = entry;
266 entry->refCount += 1;
267 } else {
268 resetKeyRepeatLocked();
269 }
270
Jeff Brown9c3cda02010-06-15 01:31:58 -0700271 identifyInputTargetsAndDispatchKeyLockedInterruptible(currentTime, entry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700272}
273
Jeff Brown9c3cda02010-06-15 01:31:58 -0700274void InputDispatcher::processKeyRepeatLockedInterruptible(
275 nsecs_t currentTime, nsecs_t keyRepeatTimeout) {
Jeff Brown349703e2010-06-22 01:27:15 -0700276 KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
277
278 // Search the inbound queue for a key up corresponding to this device.
279 // It doesn't make sense to generate a key repeat event if the key is already up.
280 for (EventEntry* queuedEntry = mInboundQueue.head.next;
281 queuedEntry != & mInboundQueue.tail; queuedEntry = entry->next) {
282 if (queuedEntry->type == EventEntry::TYPE_KEY) {
283 KeyEntry* queuedKeyEntry = static_cast<KeyEntry*>(queuedEntry);
284 if (queuedKeyEntry->deviceId == entry->deviceId
Jeff Brownc5ed5912010-07-14 18:48:53 -0700285 && entry->action == AKEY_EVENT_ACTION_UP) {
Jeff Brown349703e2010-06-22 01:27:15 -0700286 resetKeyRepeatLocked();
287 return;
288 }
289 }
290 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700291
292 // Synthesize a key repeat after the repeat timeout expired.
Jeff Brown349703e2010-06-22 01:27:15 -0700293 // Reuse the repeated key entry if it is otherwise unreferenced.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700294 uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700295 if (entry->refCount == 1) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700296 entry->eventTime = currentTime;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700297 entry->policyFlags = policyFlags;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700298 entry->repeatCount += 1;
299 } else {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700300 KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700301 entry->deviceId, entry->source, policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700302 entry->action, entry->flags, entry->keyCode, entry->scanCode,
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700303 entry->metaState, entry->repeatCount + 1, entry->downTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700304
305 mKeyRepeatState.lastKeyEntry = newEntry;
306 mAllocator.releaseKeyEntry(entry);
307
308 entry = newEntry;
309 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700310
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700311 if (entry->repeatCount == 1) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700312 entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700313 }
314
Jeff Brown9c3cda02010-06-15 01:31:58 -0700315 mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatTimeout;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700316
317#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brownc5ed5912010-07-14 18:48:53 -0700318 LOGD("processKeyRepeat - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700319 "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
320 "repeatCount=%d, downTime=%lld",
Jeff Brownc5ed5912010-07-14 18:48:53 -0700321 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700322 entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
323 entry->repeatCount, entry->downTime);
324#endif
325
Jeff Brown9c3cda02010-06-15 01:31:58 -0700326 identifyInputTargetsAndDispatchKeyLockedInterruptible(currentTime, entry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700327}
328
Jeff Brown9c3cda02010-06-15 01:31:58 -0700329void InputDispatcher::processMotionLockedInterruptible(
330 nsecs_t currentTime, MotionEntry* entry) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700331#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brownc5ed5912010-07-14 18:48:53 -0700332 LOGD("processMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700333 "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
Jeff Brownc5ed5912010-07-14 18:48:53 -0700334 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, entry->action,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700335 entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
336 entry->downTime);
337
338 // Print the most recent sample that we have available, this may change due to batching.
339 size_t sampleCount = 1;
340 MotionSample* sample = & entry->firstSample;
341 for (; sample->next != NULL; sample = sample->next) {
342 sampleCount += 1;
343 }
344 for (uint32_t i = 0; i < entry->pointerCount; i++) {
345 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
346 i, entry->pointerIds[i],
347 sample->pointerCoords[i].x,
348 sample->pointerCoords[i].y,
349 sample->pointerCoords[i].pressure,
350 sample->pointerCoords[i].size);
351 }
352
353 // Keep in mind that due to batching, it is possible for the number of samples actually
354 // dispatched to change before the application finally consumed them.
Jeff Brownc5ed5912010-07-14 18:48:53 -0700355 if (entry->action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700356 LOGD(" ... Total movement samples currently batched %d ...", sampleCount);
357 }
358#endif
359
Jeff Brown9c3cda02010-06-15 01:31:58 -0700360 identifyInputTargetsAndDispatchMotionLockedInterruptible(currentTime, entry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700361}
362
Jeff Brown9c3cda02010-06-15 01:31:58 -0700363void InputDispatcher::identifyInputTargetsAndDispatchKeyLockedInterruptible(
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700364 nsecs_t currentTime, KeyEntry* entry) {
365#if DEBUG_DISPATCH_CYCLE
366 LOGD("identifyInputTargetsAndDispatchKey");
367#endif
368
Jeff Brown9c3cda02010-06-15 01:31:58 -0700369 entry->dispatchInProgress = true;
370 mCurrentInputTargetsValid = false;
371 mLock.unlock();
372
Jeff Brownc5ed5912010-07-14 18:48:53 -0700373 mReusableKeyEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700374 entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
375 entry->downTime, entry->eventTime);
376
377 mCurrentInputTargets.clear();
Jeff Brown349703e2010-06-22 01:27:15 -0700378 int32_t injectionResult = mPolicy->waitForKeyEventTargets(& mReusableKeyEvent,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700379 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700380 mCurrentInputTargets);
381
Jeff Brown9c3cda02010-06-15 01:31:58 -0700382 mLock.lock();
383 mCurrentInputTargetsValid = true;
384
Jeff Brown7fbdc842010-06-17 20:52:56 -0700385 setInjectionResultLocked(entry, injectionResult);
386
Jeff Brown349703e2010-06-22 01:27:15 -0700387 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
388 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
389 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700390}
391
Jeff Brown9c3cda02010-06-15 01:31:58 -0700392void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700393 nsecs_t currentTime, MotionEntry* entry) {
394#if DEBUG_DISPATCH_CYCLE
395 LOGD("identifyInputTargetsAndDispatchMotion");
396#endif
397
Jeff Brown9c3cda02010-06-15 01:31:58 -0700398 entry->dispatchInProgress = true;
399 mCurrentInputTargetsValid = false;
400 mLock.unlock();
401
Jeff Brownc5ed5912010-07-14 18:48:53 -0700402 mReusableMotionEvent.initialize(entry->deviceId, entry->source, entry->action,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700403 entry->edgeFlags, entry->metaState,
Jeff Brown5c225b12010-06-16 01:53:36 -0700404 0, 0, entry->xPrecision, entry->yPrecision,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700405 entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds,
406 entry->firstSample.pointerCoords);
407
408 mCurrentInputTargets.clear();
Jeff Brown349703e2010-06-22 01:27:15 -0700409 int32_t injectionResult = mPolicy->waitForMotionEventTargets(& mReusableMotionEvent,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700410 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700411 mCurrentInputTargets);
412
Jeff Brown9c3cda02010-06-15 01:31:58 -0700413 mLock.lock();
414 mCurrentInputTargetsValid = true;
415
Jeff Brown7fbdc842010-06-17 20:52:56 -0700416 setInjectionResultLocked(entry, injectionResult);
417
Jeff Brown349703e2010-06-22 01:27:15 -0700418 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
419 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
420 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700421}
422
423void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
424 EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
425#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700426 LOGD("dispatchEventToCurrentInputTargets - "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700427 "resumeWithAppendedMotionSample=%s",
428 resumeWithAppendedMotionSample ? "true" : "false");
429#endif
430
Jeff Brown9c3cda02010-06-15 01:31:58 -0700431 assert(eventEntry->dispatchInProgress); // should already have been set to true
432
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700433 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
434 const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
435
Jeff Brown2cbecea2010-08-17 15:59:26 -0700436 ssize_t connectionIndex = getConnectionIndex(inputTarget.inputChannel);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700437 if (connectionIndex >= 0) {
438 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700439 prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700440 resumeWithAppendedMotionSample);
441 } else {
442 LOGW("Framework requested delivery of an input event to channel '%s' but it "
443 "is not registered with the input dispatcher.",
444 inputTarget.inputChannel->getName().string());
445 }
446 }
447}
448
Jeff Brown7fbdc842010-06-17 20:52:56 -0700449void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
450 const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700451 bool resumeWithAppendedMotionSample) {
452#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700453 LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, timeout=%lldns, "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700454 "xOffset=%f, yOffset=%f, resumeWithAppendedMotionSample=%s",
455 connection->getInputChannelName(), inputTarget->flags, inputTarget->timeout,
456 inputTarget->xOffset, inputTarget->yOffset,
457 resumeWithAppendedMotionSample ? "true" : "false");
458#endif
459
460 // Skip this event if the connection status is not normal.
461 // We don't want to queue outbound events at all if the connection is broken or
462 // not responding.
463 if (connection->status != Connection::STATUS_NORMAL) {
464 LOGV("channel '%s' ~ Dropping event because the channel status is %s",
Jeff Brown9c3cda02010-06-15 01:31:58 -0700465 connection->getStatusLabel());
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700466 return;
467 }
468
469 // Resume the dispatch cycle with a freshly appended motion sample.
470 // First we check that the last dispatch entry in the outbound queue is for the same
471 // motion event to which we appended the motion sample. If we find such a dispatch
472 // entry, and if it is currently in progress then we try to stream the new sample.
473 bool wasEmpty = connection->outboundQueue.isEmpty();
474
475 if (! wasEmpty && resumeWithAppendedMotionSample) {
476 DispatchEntry* motionEventDispatchEntry =
477 connection->findQueuedDispatchEntryForEvent(eventEntry);
478 if (motionEventDispatchEntry) {
479 // If the dispatch entry is not in progress, then we must be busy dispatching an
480 // earlier event. Not a problem, the motion event is on the outbound queue and will
481 // be dispatched later.
482 if (! motionEventDispatchEntry->inProgress) {
483#if DEBUG_BATCHING
484 LOGD("channel '%s' ~ Not streaming because the motion event has "
485 "not yet been dispatched. "
486 "(Waiting for earlier events to be consumed.)",
487 connection->getInputChannelName());
488#endif
489 return;
490 }
491
492 // If the dispatch entry is in progress but it already has a tail of pending
493 // motion samples, then it must mean that the shared memory buffer filled up.
494 // Not a problem, when this dispatch cycle is finished, we will eventually start
495 // a new dispatch cycle to process the tail and that tail includes the newly
496 // appended motion sample.
497 if (motionEventDispatchEntry->tailMotionSample) {
498#if DEBUG_BATCHING
499 LOGD("channel '%s' ~ Not streaming because no new samples can "
500 "be appended to the motion event in this dispatch cycle. "
501 "(Waiting for next dispatch cycle to start.)",
502 connection->getInputChannelName());
503#endif
504 return;
505 }
506
507 // The dispatch entry is in progress and is still potentially open for streaming.
508 // Try to stream the new motion sample. This might fail if the consumer has already
509 // consumed the motion event (or if the channel is broken).
510 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
511 status_t status = connection->inputPublisher.appendMotionSample(
512 appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
513 if (status == OK) {
514#if DEBUG_BATCHING
515 LOGD("channel '%s' ~ Successfully streamed new motion sample.",
516 connection->getInputChannelName());
517#endif
518 return;
519 }
520
521#if DEBUG_BATCHING
522 if (status == NO_MEMORY) {
523 LOGD("channel '%s' ~ Could not append motion sample to currently "
524 "dispatched move event because the shared memory buffer is full. "
525 "(Waiting for next dispatch cycle to start.)",
526 connection->getInputChannelName());
527 } else if (status == status_t(FAILED_TRANSACTION)) {
528 LOGD("channel '%s' ~ Could not append motion sample to currently "
Jeff Brown349703e2010-06-22 01:27:15 -0700529 "dispatched move event because the event has already been consumed. "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700530 "(Waiting for next dispatch cycle to start.)",
531 connection->getInputChannelName());
532 } else {
533 LOGD("channel '%s' ~ Could not append motion sample to currently "
534 "dispatched move event due to an error, status=%d. "
535 "(Waiting for next dispatch cycle to start.)",
536 connection->getInputChannelName(), status);
537 }
538#endif
539 // Failed to stream. Start a new tail of pending motion samples to dispatch
540 // in the next cycle.
541 motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
542 return;
543 }
544 }
545
546 // This is a new event.
547 // Enqueue a new dispatch entry onto the outbound queue for this connection.
548 DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry); // increments ref
549 dispatchEntry->targetFlags = inputTarget->flags;
550 dispatchEntry->xOffset = inputTarget->xOffset;
551 dispatchEntry->yOffset = inputTarget->yOffset;
552 dispatchEntry->timeout = inputTarget->timeout;
553 dispatchEntry->inProgress = false;
554 dispatchEntry->headMotionSample = NULL;
555 dispatchEntry->tailMotionSample = NULL;
556
Jeff Brown6ec402b2010-07-28 15:48:59 -0700557 if (dispatchEntry->isSyncTarget()) {
558 eventEntry->pendingSyncDispatches += 1;
559 }
560
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700561 // Handle the case where we could not stream a new motion sample because the consumer has
562 // already consumed the motion event (otherwise the corresponding dispatch entry would
563 // still be in the outbound queue for this connection). We set the head motion sample
564 // to the list starting with the newly appended motion sample.
565 if (resumeWithAppendedMotionSample) {
566#if DEBUG_BATCHING
567 LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
568 "that cannot be streamed because the motion event has already been consumed.",
569 connection->getInputChannelName());
570#endif
571 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
572 dispatchEntry->headMotionSample = appendedMotionSample;
573 }
574
575 // Enqueue the dispatch entry.
576 connection->outboundQueue.enqueueAtTail(dispatchEntry);
577
578 // If the outbound queue was previously empty, start the dispatch cycle going.
579 if (wasEmpty) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700580 activateConnectionLocked(connection.get());
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700581 startDispatchCycleLocked(currentTime, connection);
582 }
583}
584
Jeff Brown7fbdc842010-06-17 20:52:56 -0700585void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
586 const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700587#if DEBUG_DISPATCH_CYCLE
588 LOGD("channel '%s' ~ startDispatchCycle",
589 connection->getInputChannelName());
590#endif
591
592 assert(connection->status == Connection::STATUS_NORMAL);
593 assert(! connection->outboundQueue.isEmpty());
594
595 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
596 assert(! dispatchEntry->inProgress);
597
598 // TODO throttle successive ACTION_MOVE motion events for the same device
599 // possible implementation could set a brief poll timeout here and resume starting the
600 // dispatch cycle when elapsed
601
602 // Publish the event.
603 status_t status;
604 switch (dispatchEntry->eventEntry->type) {
605 case EventEntry::TYPE_KEY: {
606 KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
607
608 // Apply target flags.
609 int32_t action = keyEntry->action;
610 int32_t flags = keyEntry->flags;
611 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700612 flags |= AKEY_EVENT_FLAG_CANCELED;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700613 }
614
615 // Publish the key event.
Jeff Brownc5ed5912010-07-14 18:48:53 -0700616 status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700617 action, flags, keyEntry->keyCode, keyEntry->scanCode,
618 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
619 keyEntry->eventTime);
620
621 if (status) {
622 LOGE("channel '%s' ~ Could not publish key event, "
623 "status=%d", connection->getInputChannelName(), status);
624 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
625 return;
626 }
627 break;
628 }
629
630 case EventEntry::TYPE_MOTION: {
631 MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
632
633 // Apply target flags.
634 int32_t action = motionEntry->action;
635 if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700636 action = AMOTION_EVENT_ACTION_OUTSIDE;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700637 }
638 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700639 action = AMOTION_EVENT_ACTION_CANCEL;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700640 }
641
642 // If headMotionSample is non-NULL, then it points to the first new sample that we
643 // were unable to dispatch during the previous cycle so we resume dispatching from
644 // that point in the list of motion samples.
645 // Otherwise, we just start from the first sample of the motion event.
646 MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
647 if (! firstMotionSample) {
648 firstMotionSample = & motionEntry->firstSample;
649 }
650
Jeff Brownd3616592010-07-16 17:21:06 -0700651 // Set the X and Y offset depending on the input source.
652 float xOffset, yOffset;
653 if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
654 xOffset = dispatchEntry->xOffset;
655 yOffset = dispatchEntry->yOffset;
656 } else {
657 xOffset = 0.0f;
658 yOffset = 0.0f;
659 }
660
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700661 // Publish the motion event and the first motion sample.
662 status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700663 motionEntry->source, action, motionEntry->edgeFlags, motionEntry->metaState,
Jeff Brownd3616592010-07-16 17:21:06 -0700664 xOffset, yOffset,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700665 motionEntry->xPrecision, motionEntry->yPrecision,
666 motionEntry->downTime, firstMotionSample->eventTime,
667 motionEntry->pointerCount, motionEntry->pointerIds,
668 firstMotionSample->pointerCoords);
669
670 if (status) {
671 LOGE("channel '%s' ~ Could not publish motion event, "
672 "status=%d", connection->getInputChannelName(), status);
673 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
674 return;
675 }
676
677 // Append additional motion samples.
678 MotionSample* nextMotionSample = firstMotionSample->next;
679 for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
680 status = connection->inputPublisher.appendMotionSample(
681 nextMotionSample->eventTime, nextMotionSample->pointerCoords);
682 if (status == NO_MEMORY) {
683#if DEBUG_DISPATCH_CYCLE
684 LOGD("channel '%s' ~ Shared memory buffer full. Some motion samples will "
685 "be sent in the next dispatch cycle.",
686 connection->getInputChannelName());
687#endif
688 break;
689 }
690 if (status != OK) {
691 LOGE("channel '%s' ~ Could not append motion sample "
692 "for a reason other than out of memory, status=%d",
693 connection->getInputChannelName(), status);
694 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
695 return;
696 }
697 }
698
699 // Remember the next motion sample that we could not dispatch, in case we ran out
700 // of space in the shared memory buffer.
701 dispatchEntry->tailMotionSample = nextMotionSample;
702 break;
703 }
704
705 default: {
706 assert(false);
707 }
708 }
709
710 // Send the dispatch signal.
711 status = connection->inputPublisher.sendDispatchSignal();
712 if (status) {
713 LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
714 connection->getInputChannelName(), status);
715 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
716 return;
717 }
718
719 // Record information about the newly started dispatch cycle.
720 dispatchEntry->inProgress = true;
721
722 connection->lastEventTime = dispatchEntry->eventEntry->eventTime;
723 connection->lastDispatchTime = currentTime;
724
725 nsecs_t timeout = dispatchEntry->timeout;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700726 connection->setNextTimeoutTime(currentTime, timeout);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700727
728 // Notify other system components.
729 onDispatchCycleStartedLocked(currentTime, connection);
730}
731
Jeff Brown7fbdc842010-06-17 20:52:56 -0700732void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
733 const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700734#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700735 LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700736 "%01.1fms since dispatch",
737 connection->getInputChannelName(),
738 connection->getEventLatencyMillis(currentTime),
739 connection->getDispatchLatencyMillis(currentTime));
740#endif
741
Jeff Brown9c3cda02010-06-15 01:31:58 -0700742 if (connection->status == Connection::STATUS_BROKEN
743 || connection->status == Connection::STATUS_ZOMBIE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700744 return;
745 }
746
747 // Clear the pending timeout.
748 connection->nextTimeoutTime = LONG_LONG_MAX;
749
750 if (connection->status == Connection::STATUS_NOT_RESPONDING) {
751 // Recovering from an ANR.
752 connection->status = Connection::STATUS_NORMAL;
753
754 // Notify other system components.
755 onDispatchCycleFinishedLocked(currentTime, connection, true /*recoveredFromANR*/);
756 } else {
757 // Normal finish. Not much to do here.
758
759 // Notify other system components.
760 onDispatchCycleFinishedLocked(currentTime, connection, false /*recoveredFromANR*/);
761 }
762
763 // Reset the publisher since the event has been consumed.
764 // We do this now so that the publisher can release some of its internal resources
765 // while waiting for the next dispatch cycle to begin.
766 status_t status = connection->inputPublisher.reset();
767 if (status) {
768 LOGE("channel '%s' ~ Could not reset publisher, status=%d",
769 connection->getInputChannelName(), status);
770 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
771 return;
772 }
773
774 // Start the next dispatch cycle for this connection.
775 while (! connection->outboundQueue.isEmpty()) {
776 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
777 if (dispatchEntry->inProgress) {
778 // Finish or resume current event in progress.
779 if (dispatchEntry->tailMotionSample) {
780 // We have a tail of undispatched motion samples.
781 // Reuse the same DispatchEntry and start a new cycle.
782 dispatchEntry->inProgress = false;
783 dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
784 dispatchEntry->tailMotionSample = NULL;
785 startDispatchCycleLocked(currentTime, connection);
786 return;
787 }
788 // Finished.
789 connection->outboundQueue.dequeueAtHead();
Jeff Brown6ec402b2010-07-28 15:48:59 -0700790 if (dispatchEntry->isSyncTarget()) {
791 decrementPendingSyncDispatchesLocked(dispatchEntry->eventEntry);
792 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700793 mAllocator.releaseDispatchEntry(dispatchEntry);
794 } else {
795 // If the head is not in progress, then we must have already dequeued the in
796 // progress event, which means we actually aborted it (due to ANR).
797 // So just start the next event for this connection.
798 startDispatchCycleLocked(currentTime, connection);
799 return;
800 }
801 }
802
803 // Outbound queue is empty, deactivate the connection.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700804 deactivateConnectionLocked(connection.get());
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700805}
806
Jeff Brown7fbdc842010-06-17 20:52:56 -0700807void InputDispatcher::timeoutDispatchCycleLocked(nsecs_t currentTime,
808 const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700809#if DEBUG_DISPATCH_CYCLE
810 LOGD("channel '%s' ~ timeoutDispatchCycle",
811 connection->getInputChannelName());
812#endif
813
814 if (connection->status != Connection::STATUS_NORMAL) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700815 return;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700816 }
817
818 // Enter the not responding state.
819 connection->status = Connection::STATUS_NOT_RESPONDING;
820 connection->lastANRTime = currentTime;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700821
822 // Notify other system components.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700823 // This enqueues a command which will eventually either call
824 // resumeAfterTimeoutDispatchCycleLocked or abortDispatchCycleLocked.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700825 onDispatchCycleANRLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700826}
827
Jeff Brown7fbdc842010-06-17 20:52:56 -0700828void InputDispatcher::resumeAfterTimeoutDispatchCycleLocked(nsecs_t currentTime,
829 const sp<Connection>& connection, nsecs_t newTimeout) {
830#if DEBUG_DISPATCH_CYCLE
831 LOGD("channel '%s' ~ resumeAfterTimeoutDispatchCycleLocked",
832 connection->getInputChannelName());
833#endif
834
835 if (connection->status != Connection::STATUS_NOT_RESPONDING) {
836 return;
837 }
838
839 // Resume normal dispatch.
840 connection->status = Connection::STATUS_NORMAL;
841 connection->setNextTimeoutTime(currentTime, newTimeout);
842}
843
844void InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime,
845 const sp<Connection>& connection, bool broken) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700846#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700847 LOGD("channel '%s' ~ abortDispatchCycle - broken=%s",
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700848 connection->getInputChannelName(), broken ? "true" : "false");
849#endif
850
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700851 // Clear the pending timeout.
852 connection->nextTimeoutTime = LONG_LONG_MAX;
853
854 // Clear the outbound queue.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700855 if (! connection->outboundQueue.isEmpty()) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700856 do {
857 DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
Jeff Brown6ec402b2010-07-28 15:48:59 -0700858 if (dispatchEntry->isSyncTarget()) {
859 decrementPendingSyncDispatchesLocked(dispatchEntry->eventEntry);
860 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700861 mAllocator.releaseDispatchEntry(dispatchEntry);
862 } while (! connection->outboundQueue.isEmpty());
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700863
Jeff Brown7fbdc842010-06-17 20:52:56 -0700864 deactivateConnectionLocked(connection.get());
Jeff Brown9c3cda02010-06-15 01:31:58 -0700865 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700866
867 // Handle the case where the connection appears to be unrecoverably broken.
Jeff Brown9c3cda02010-06-15 01:31:58 -0700868 // Ignore already broken or zombie connections.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700869 if (broken) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700870 if (connection->status == Connection::STATUS_NORMAL
871 || connection->status == Connection::STATUS_NOT_RESPONDING) {
872 connection->status = Connection::STATUS_BROKEN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700873
Jeff Brown9c3cda02010-06-15 01:31:58 -0700874 // Notify other system components.
875 onDispatchCycleBrokenLocked(currentTime, connection);
876 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700877 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700878}
879
880bool InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
881 InputDispatcher* d = static_cast<InputDispatcher*>(data);
882
883 { // acquire lock
884 AutoMutex _l(d->mLock);
885
886 ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
887 if (connectionIndex < 0) {
888 LOGE("Received spurious receive callback for unknown input channel. "
889 "fd=%d, events=0x%x", receiveFd, events);
890 return false; // remove the callback
891 }
892
Jeff Brown7fbdc842010-06-17 20:52:56 -0700893 nsecs_t currentTime = now();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700894
895 sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
896 if (events & (POLLERR | POLLHUP | POLLNVAL)) {
897 LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
898 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700899 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700900 d->runCommandsLockedInterruptible();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700901 return false; // remove the callback
902 }
903
904 if (! (events & POLLIN)) {
905 LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
906 "events=0x%x", connection->getInputChannelName(), events);
907 return true;
908 }
909
910 status_t status = connection->inputPublisher.receiveFinishedSignal();
911 if (status) {
912 LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
913 connection->getInputChannelName(), status);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700914 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700915 d->runCommandsLockedInterruptible();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700916 return false; // remove the callback
917 }
918
Jeff Brown7fbdc842010-06-17 20:52:56 -0700919 d->finishDispatchCycleLocked(currentTime, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700920 d->runCommandsLockedInterruptible();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700921 return true;
922 } // release lock
923}
924
Jeff Brown9c3cda02010-06-15 01:31:58 -0700925void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700926#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown9c3cda02010-06-15 01:31:58 -0700927 LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700928#endif
929
930 bool wasEmpty;
931 { // acquire lock
932 AutoMutex _l(mLock);
933
Jeff Brown7fbdc842010-06-17 20:52:56 -0700934 ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700935
936 wasEmpty = mInboundQueue.isEmpty();
937 mInboundQueue.enqueueAtTail(newEntry);
938 } // release lock
939
940 if (wasEmpty) {
941 mPollLoop->wake();
942 }
943}
944
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700945void InputDispatcher::notifyAppSwitchComing(nsecs_t eventTime) {
946#if DEBUG_INBOUND_EVENT_DETAILS
947 LOGD("notifyAppSwitchComing - eventTime=%lld", eventTime);
948#endif
949
950 // Remove movement keys from the queue from most recent to least recent, stopping at the
951 // first non-movement key.
952 // TODO: Include a detailed description of why we do this...
953
954 { // acquire lock
955 AutoMutex _l(mLock);
956
957 for (EventEntry* entry = mInboundQueue.tail.prev; entry != & mInboundQueue.head; ) {
958 EventEntry* prev = entry->prev;
959
960 if (entry->type == EventEntry::TYPE_KEY) {
961 KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
962 if (isMovementKey(keyEntry->keyCode)) {
963 LOGV("Dropping movement key during app switch: keyCode=%d, action=%d",
964 keyEntry->keyCode, keyEntry->action);
965 mInboundQueue.dequeue(keyEntry);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700966
967 setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
968
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700969 mAllocator.releaseKeyEntry(keyEntry);
970 } else {
971 // stop at last non-movement key
972 break;
973 }
974 }
975
976 entry = prev;
977 }
978 } // release lock
979}
980
Jeff Brownc5ed5912010-07-14 18:48:53 -0700981void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700982 uint32_t policyFlags, int32_t action, int32_t flags,
983 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
984#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brownc5ed5912010-07-14 18:48:53 -0700985 LOGD("notifyKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700986 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
Jeff Brownc5ed5912010-07-14 18:48:53 -0700987 eventTime, deviceId, source, policyFlags, action, flags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700988 keyCode, scanCode, metaState, downTime);
989#endif
990
991 bool wasEmpty;
992 { // acquire lock
993 AutoMutex _l(mLock);
994
Jeff Brown7fbdc842010-06-17 20:52:56 -0700995 int32_t repeatCount = 0;
996 KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700997 deviceId, source, policyFlags, action, flags, keyCode, scanCode,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700998 metaState, repeatCount, downTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700999
1000 wasEmpty = mInboundQueue.isEmpty();
1001 mInboundQueue.enqueueAtTail(newEntry);
1002 } // release lock
1003
1004 if (wasEmpty) {
1005 mPollLoop->wake();
1006 }
1007}
1008
Jeff Brownc5ed5912010-07-14 18:48:53 -07001009void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001010 uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
1011 uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
1012 float xPrecision, float yPrecision, nsecs_t downTime) {
1013#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brownc5ed5912010-07-14 18:48:53 -07001014 LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001015 "action=0x%x, metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, "
1016 "downTime=%lld",
Jeff Brownc5ed5912010-07-14 18:48:53 -07001017 eventTime, deviceId, source, policyFlags, action, metaState, edgeFlags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001018 xPrecision, yPrecision, downTime);
1019 for (uint32_t i = 0; i < pointerCount; i++) {
1020 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
1021 i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
1022 pointerCoords[i].pressure, pointerCoords[i].size);
1023 }
1024#endif
1025
1026 bool wasEmpty;
1027 { // acquire lock
1028 AutoMutex _l(mLock);
1029
1030 // Attempt batching and streaming of move events.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001031 if (action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001032 // BATCHING CASE
1033 //
1034 // Try to append a move sample to the tail of the inbound queue for this device.
1035 // Give up if we encounter a non-move motion event for this device since that
1036 // means we cannot append any new samples until a new motion event has started.
1037 for (EventEntry* entry = mInboundQueue.tail.prev;
1038 entry != & mInboundQueue.head; entry = entry->prev) {
1039 if (entry->type != EventEntry::TYPE_MOTION) {
1040 // Keep looking for motion events.
1041 continue;
1042 }
1043
1044 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
1045 if (motionEntry->deviceId != deviceId) {
1046 // Keep looking for this device.
1047 continue;
1048 }
1049
Jeff Brownc5ed5912010-07-14 18:48:53 -07001050 if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown7fbdc842010-06-17 20:52:56 -07001051 || motionEntry->pointerCount != pointerCount
1052 || motionEntry->isInjected()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001053 // Last motion event in the queue for this device is not compatible for
1054 // appending new samples. Stop here.
1055 goto NoBatchingOrStreaming;
1056 }
1057
1058 // The last motion event is a move and is compatible for appending.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001059 // Do the batching magic.
Jeff Brown7fbdc842010-06-17 20:52:56 -07001060 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001061#if DEBUG_BATCHING
1062 LOGD("Appended motion sample onto batch for most recent "
1063 "motion event for this device in the inbound queue.");
1064#endif
Jeff Brown9c3cda02010-06-15 01:31:58 -07001065
1066 // Sanity check for special case because dispatch is interruptible.
1067 // The dispatch logic is partially interruptible and releases its lock while
1068 // identifying targets. However, as soon as the targets have been identified,
1069 // the dispatcher proceeds to write a dispatch entry into all relevant outbound
1070 // queues and then promptly removes the motion entry from the queue.
1071 //
1072 // Consequently, we should never observe the case where the inbound queue contains
1073 // an in-progress motion entry unless the current input targets are invalid
1074 // (currently being computed). Check for this!
1075 assert(! (motionEntry->dispatchInProgress && mCurrentInputTargetsValid));
1076
1077 return; // done!
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001078 }
1079
1080 // STREAMING CASE
1081 //
1082 // There is no pending motion event (of any kind) for this device in the inbound queue.
1083 // Search the outbound queues for a synchronously dispatched motion event for this
1084 // device. If found, then we append the new sample to that event and then try to
1085 // push it out to all current targets. It is possible that some targets will already
1086 // have consumed the motion event. This case is automatically handled by the
1087 // logic in prepareDispatchCycleLocked by tracking where resumption takes place.
1088 //
1089 // The reason we look for a synchronously dispatched motion event is because we
1090 // want to be sure that no other motion events have been dispatched since the move.
1091 // It's also convenient because it means that the input targets are still valid.
1092 // This code could be improved to support streaming of asynchronously dispatched
1093 // motion events (which might be significantly more efficient) but it may become
1094 // a little more complicated as a result.
1095 //
1096 // Note: This code crucially depends on the invariant that an outbound queue always
1097 // contains at most one synchronous event and it is always last (but it might
1098 // not be first!).
Jeff Brown9c3cda02010-06-15 01:31:58 -07001099 if (mCurrentInputTargetsValid) {
1100 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1101 Connection* connection = mActiveConnections.itemAt(i);
1102 if (! connection->outboundQueue.isEmpty()) {
1103 DispatchEntry* dispatchEntry = connection->outboundQueue.tail.prev;
Jeff Brown6ec402b2010-07-28 15:48:59 -07001104 if (dispatchEntry->isSyncTarget()) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001105 if (dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION) {
1106 goto NoBatchingOrStreaming;
1107 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001108
Jeff Brown9c3cda02010-06-15 01:31:58 -07001109 MotionEntry* syncedMotionEntry = static_cast<MotionEntry*>(
1110 dispatchEntry->eventEntry);
Jeff Brownc5ed5912010-07-14 18:48:53 -07001111 if (syncedMotionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown9c3cda02010-06-15 01:31:58 -07001112 || syncedMotionEntry->deviceId != deviceId
Jeff Brown7fbdc842010-06-17 20:52:56 -07001113 || syncedMotionEntry->pointerCount != pointerCount
1114 || syncedMotionEntry->isInjected()) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001115 goto NoBatchingOrStreaming;
1116 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001117
Jeff Brown9c3cda02010-06-15 01:31:58 -07001118 // Found synced move entry. Append sample and resume dispatch.
1119 mAllocator.appendMotionSample(syncedMotionEntry, eventTime,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001120 pointerCoords);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001121 #if DEBUG_BATCHING
1122 LOGD("Appended motion sample onto batch for most recent synchronously "
1123 "dispatched motion event for this device in the outbound queues.");
1124 #endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001125 nsecs_t currentTime = now();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001126 dispatchEventToCurrentInputTargetsLocked(currentTime, syncedMotionEntry,
1127 true /*resumeWithAppendedMotionSample*/);
1128
1129 runCommandsLockedInterruptible();
1130 return; // done!
1131 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001132 }
1133 }
1134 }
1135
1136NoBatchingOrStreaming:;
1137 }
1138
1139 // Just enqueue a new motion event.
Jeff Brown7fbdc842010-06-17 20:52:56 -07001140 MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -07001141 deviceId, source, policyFlags, action, metaState, edgeFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001142 xPrecision, yPrecision, downTime,
1143 pointerCount, pointerIds, pointerCoords);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001144
1145 wasEmpty = mInboundQueue.isEmpty();
1146 mInboundQueue.enqueueAtTail(newEntry);
1147 } // release lock
1148
1149 if (wasEmpty) {
1150 mPollLoop->wake();
1151 }
1152}
1153
Jeff Brown7fbdc842010-06-17 20:52:56 -07001154int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
Jeff Brown6ec402b2010-07-28 15:48:59 -07001155 int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001156#if DEBUG_INBOUND_EVENT_DETAILS
1157 LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
Jeff Brown6ec402b2010-07-28 15:48:59 -07001158 "syncMode=%d, timeoutMillis=%d",
1159 event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001160#endif
1161
1162 nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
1163
1164 EventEntry* injectedEntry;
1165 bool wasEmpty;
1166 { // acquire lock
1167 AutoMutex _l(mLock);
1168
1169 injectedEntry = createEntryFromInputEventLocked(event);
1170 injectedEntry->refCount += 1;
1171 injectedEntry->injectorPid = injectorPid;
1172 injectedEntry->injectorUid = injectorUid;
1173
Jeff Brown6ec402b2010-07-28 15:48:59 -07001174 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
1175 injectedEntry->injectionIsAsync = true;
1176 }
1177
Jeff Brown7fbdc842010-06-17 20:52:56 -07001178 wasEmpty = mInboundQueue.isEmpty();
1179 mInboundQueue.enqueueAtTail(injectedEntry);
1180
1181 } // release lock
1182
1183 if (wasEmpty) {
1184 mPollLoop->wake();
1185 }
1186
1187 int32_t injectionResult;
1188 { // acquire lock
1189 AutoMutex _l(mLock);
1190
Jeff Brown6ec402b2010-07-28 15:48:59 -07001191 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
1192 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1193 } else {
1194 for (;;) {
1195 injectionResult = injectedEntry->injectionResult;
1196 if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
1197 break;
1198 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07001199
Jeff Brown7fbdc842010-06-17 20:52:56 -07001200 nsecs_t remainingTimeout = endTime - now();
1201 if (remainingTimeout <= 0) {
Jeff Brown6ec402b2010-07-28 15:48:59 -07001202#if DEBUG_INJECTION
1203 LOGD("injectInputEvent - Timed out waiting for injection result "
1204 "to become available.");
1205#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001206 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1207 break;
1208 }
1209
Jeff Brown6ec402b2010-07-28 15:48:59 -07001210 mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
1211 }
1212
1213 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
1214 && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
1215 while (injectedEntry->pendingSyncDispatches != 0) {
1216#if DEBUG_INJECTION
1217 LOGD("injectInputEvent - Waiting for %d pending synchronous dispatches.",
1218 injectedEntry->pendingSyncDispatches);
1219#endif
1220 nsecs_t remainingTimeout = endTime - now();
1221 if (remainingTimeout <= 0) {
1222#if DEBUG_INJECTION
1223 LOGD("injectInputEvent - Timed out waiting for pending synchronous "
1224 "dispatches to finish.");
1225#endif
1226 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1227 break;
1228 }
1229
1230 mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
1231 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07001232 }
1233 }
1234
1235 mAllocator.releaseEventEntry(injectedEntry);
1236 } // release lock
1237
Jeff Brown6ec402b2010-07-28 15:48:59 -07001238#if DEBUG_INJECTION
1239 LOGD("injectInputEvent - Finished with result %d. "
1240 "injectorPid=%d, injectorUid=%d",
1241 injectionResult, injectorPid, injectorUid);
1242#endif
1243
Jeff Brown7fbdc842010-06-17 20:52:56 -07001244 return injectionResult;
1245}
1246
1247void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
1248 if (entry->isInjected()) {
1249#if DEBUG_INJECTION
1250 LOGD("Setting input event injection result to %d. "
1251 "injectorPid=%d, injectorUid=%d",
1252 injectionResult, entry->injectorPid, entry->injectorUid);
1253#endif
1254
Jeff Brown6ec402b2010-07-28 15:48:59 -07001255 if (entry->injectionIsAsync) {
1256 // Log the outcome since the injector did not wait for the injection result.
1257 switch (injectionResult) {
1258 case INPUT_EVENT_INJECTION_SUCCEEDED:
1259 LOGV("Asynchronous input event injection succeeded.");
1260 break;
1261 case INPUT_EVENT_INJECTION_FAILED:
1262 LOGW("Asynchronous input event injection failed.");
1263 break;
1264 case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
1265 LOGW("Asynchronous input event injection permission denied.");
1266 break;
1267 case INPUT_EVENT_INJECTION_TIMED_OUT:
1268 LOGW("Asynchronous input event injection timed out.");
1269 break;
1270 }
1271 }
1272
Jeff Brown7fbdc842010-06-17 20:52:56 -07001273 entry->injectionResult = injectionResult;
1274 mInjectionResultAvailableCondition.broadcast();
1275 }
1276}
1277
Jeff Brown6ec402b2010-07-28 15:48:59 -07001278void InputDispatcher::decrementPendingSyncDispatchesLocked(EventEntry* entry) {
1279 entry->pendingSyncDispatches -= 1;
1280
1281 if (entry->isInjected() && entry->pendingSyncDispatches == 0) {
1282 mInjectionSyncFinishedCondition.broadcast();
1283 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07001284}
1285
1286InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked(
1287 const InputEvent* event) {
1288 switch (event->getType()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001289 case AINPUT_EVENT_TYPE_KEY: {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001290 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
1291 uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
1292
1293 KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
Jeff Brownc5ed5912010-07-14 18:48:53 -07001294 keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001295 keyEvent->getAction(), keyEvent->getFlags(),
1296 keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
1297 keyEvent->getRepeatCount(), keyEvent->getDownTime());
1298 return keyEntry;
1299 }
1300
Jeff Brownc5ed5912010-07-14 18:48:53 -07001301 case AINPUT_EVENT_TYPE_MOTION: {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001302 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
1303 uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
1304
1305 const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
1306 const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
1307 size_t pointerCount = motionEvent->getPointerCount();
1308
1309 MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
Jeff Brownc5ed5912010-07-14 18:48:53 -07001310 motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001311 motionEvent->getAction(), motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
1312 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
1313 motionEvent->getDownTime(), uint32_t(pointerCount),
1314 motionEvent->getPointerIds(), samplePointerCoords);
1315 for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
1316 sampleEventTimes += 1;
1317 samplePointerCoords += pointerCount;
1318 mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
1319 }
1320 return motionEntry;
1321 }
1322
1323 default:
1324 assert(false);
1325 return NULL;
1326 }
1327}
1328
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001329void InputDispatcher::resetKeyRepeatLocked() {
1330 if (mKeyRepeatState.lastKeyEntry) {
1331 mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
1332 mKeyRepeatState.lastKeyEntry = NULL;
1333 }
1334}
1335
Jeff Brown349703e2010-06-22 01:27:15 -07001336void InputDispatcher::preemptInputDispatch() {
1337#if DEBUG_DISPATCH_CYCLE
1338 LOGD("preemptInputDispatch");
1339#endif
1340
1341 bool preemptedOne = false;
1342 { // acquire lock
1343 AutoMutex _l(mLock);
1344
1345 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1346 Connection* connection = mActiveConnections[i];
1347 if (connection->hasPendingSyncTarget()) {
1348#if DEBUG_DISPATCH_CYCLE
1349 LOGD("channel '%s' ~ Preempted pending synchronous dispatch",
1350 connection->getInputChannelName());
1351#endif
1352 connection->outboundQueue.tail.prev->targetFlags &= ~ InputTarget::FLAG_SYNC;
1353 preemptedOne = true;
1354 }
1355 }
1356 } // release lock
1357
1358 if (preemptedOne) {
1359 // Wake up the poll loop so it can get a head start dispatching the next event.
1360 mPollLoop->wake();
1361 }
1362}
1363
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001364status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001365#if DEBUG_REGISTRATION
Jeff Brown349703e2010-06-22 01:27:15 -07001366 LOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().string());
Jeff Brown9c3cda02010-06-15 01:31:58 -07001367#endif
1368
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001369 { // acquire lock
1370 AutoMutex _l(mLock);
1371
Jeff Brown2cbecea2010-08-17 15:59:26 -07001372 if (getConnectionIndex(inputChannel) >= 0) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001373 LOGW("Attempted to register already registered input channel '%s'",
1374 inputChannel->getName().string());
1375 return BAD_VALUE;
1376 }
1377
1378 sp<Connection> connection = new Connection(inputChannel);
1379 status_t status = connection->initialize();
1380 if (status) {
1381 LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
1382 inputChannel->getName().string(), status);
1383 return status;
1384 }
1385
Jeff Brown2cbecea2010-08-17 15:59:26 -07001386 int32_t receiveFd = inputChannel->getReceivePipeFd();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001387 mConnectionsByReceiveFd.add(receiveFd, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001388
Jeff Brown2cbecea2010-08-17 15:59:26 -07001389 mPollLoop->setCallback(receiveFd, POLLIN, handleReceiveCallback, this);
1390
Jeff Brown9c3cda02010-06-15 01:31:58 -07001391 runCommandsLockedInterruptible();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001392 } // release lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001393 return OK;
1394}
1395
1396status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001397#if DEBUG_REGISTRATION
Jeff Brown349703e2010-06-22 01:27:15 -07001398 LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
Jeff Brown9c3cda02010-06-15 01:31:58 -07001399#endif
1400
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001401 { // acquire lock
1402 AutoMutex _l(mLock);
1403
Jeff Brown2cbecea2010-08-17 15:59:26 -07001404 ssize_t connectionIndex = getConnectionIndex(inputChannel);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001405 if (connectionIndex < 0) {
1406 LOGW("Attempted to unregister already unregistered input channel '%s'",
1407 inputChannel->getName().string());
1408 return BAD_VALUE;
1409 }
1410
1411 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1412 mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
1413
1414 connection->status = Connection::STATUS_ZOMBIE;
1415
Jeff Brown2cbecea2010-08-17 15:59:26 -07001416 mPollLoop->removeCallback(inputChannel->getReceivePipeFd());
1417
Jeff Brown7fbdc842010-06-17 20:52:56 -07001418 nsecs_t currentTime = now();
1419 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001420
1421 runCommandsLockedInterruptible();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001422 } // release lock
1423
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001424 // Wake the poll loop because removing the connection may have changed the current
1425 // synchronization state.
1426 mPollLoop->wake();
1427 return OK;
1428}
1429
Jeff Brown2cbecea2010-08-17 15:59:26 -07001430ssize_t InputDispatcher::getConnectionIndex(const sp<InputChannel>& inputChannel) {
1431 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(inputChannel->getReceivePipeFd());
1432 if (connectionIndex >= 0) {
1433 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1434 if (connection->inputChannel.get() == inputChannel.get()) {
1435 return connectionIndex;
1436 }
1437 }
1438
1439 return -1;
1440}
1441
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001442void InputDispatcher::activateConnectionLocked(Connection* connection) {
1443 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1444 if (mActiveConnections.itemAt(i) == connection) {
1445 return;
1446 }
1447 }
1448 mActiveConnections.add(connection);
1449}
1450
1451void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
1452 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1453 if (mActiveConnections.itemAt(i) == connection) {
1454 mActiveConnections.removeAt(i);
1455 return;
1456 }
1457 }
1458}
1459
Jeff Brown9c3cda02010-06-15 01:31:58 -07001460void InputDispatcher::onDispatchCycleStartedLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07001461 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001462}
1463
Jeff Brown9c3cda02010-06-15 01:31:58 -07001464void InputDispatcher::onDispatchCycleFinishedLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07001465 nsecs_t currentTime, const sp<Connection>& connection, bool recoveredFromANR) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001466 if (recoveredFromANR) {
1467 LOGI("channel '%s' ~ Recovered from ANR. %01.1fms since event, "
1468 "%01.1fms since dispatch, %01.1fms since ANR",
1469 connection->getInputChannelName(),
1470 connection->getEventLatencyMillis(currentTime),
1471 connection->getDispatchLatencyMillis(currentTime),
1472 connection->getANRLatencyMillis(currentTime));
1473
Jeff Brown9c3cda02010-06-15 01:31:58 -07001474 CommandEntry* commandEntry = postCommandLocked(
1475 & InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001476 commandEntry->connection = connection;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001477 }
1478}
1479
Jeff Brown9c3cda02010-06-15 01:31:58 -07001480void InputDispatcher::onDispatchCycleANRLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07001481 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001482 LOGI("channel '%s' ~ Not responding! %01.1fms since event, %01.1fms since dispatch",
1483 connection->getInputChannelName(),
1484 connection->getEventLatencyMillis(currentTime),
1485 connection->getDispatchLatencyMillis(currentTime));
1486
Jeff Brown9c3cda02010-06-15 01:31:58 -07001487 CommandEntry* commandEntry = postCommandLocked(
1488 & InputDispatcher::doNotifyInputChannelANRLockedInterruptible);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001489 commandEntry->connection = connection;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001490}
1491
Jeff Brown9c3cda02010-06-15 01:31:58 -07001492void InputDispatcher::onDispatchCycleBrokenLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07001493 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001494 LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
1495 connection->getInputChannelName());
1496
Jeff Brown9c3cda02010-06-15 01:31:58 -07001497 CommandEntry* commandEntry = postCommandLocked(
1498 & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001499 commandEntry->connection = connection;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001500}
1501
Jeff Brown9c3cda02010-06-15 01:31:58 -07001502void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
1503 CommandEntry* commandEntry) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001504 sp<Connection> connection = commandEntry->connection;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001505
Jeff Brown7fbdc842010-06-17 20:52:56 -07001506 if (connection->status != Connection::STATUS_ZOMBIE) {
1507 mLock.unlock();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001508
Jeff Brown7fbdc842010-06-17 20:52:56 -07001509 mPolicy->notifyInputChannelBroken(connection->inputChannel);
1510
1511 mLock.lock();
1512 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001513}
1514
1515void InputDispatcher::doNotifyInputChannelANRLockedInterruptible(
1516 CommandEntry* commandEntry) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001517 sp<Connection> connection = commandEntry->connection;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001518
Jeff Brown7fbdc842010-06-17 20:52:56 -07001519 if (connection->status != Connection::STATUS_ZOMBIE) {
1520 mLock.unlock();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001521
Jeff Brown7fbdc842010-06-17 20:52:56 -07001522 nsecs_t newTimeout;
1523 bool resume = mPolicy->notifyInputChannelANR(connection->inputChannel, newTimeout);
1524
1525 mLock.lock();
1526
1527 nsecs_t currentTime = now();
1528 if (resume) {
1529 resumeAfterTimeoutDispatchCycleLocked(currentTime, connection, newTimeout);
1530 } else {
1531 abortDispatchCycleLocked(currentTime, connection, false /*(not) broken*/);
1532 }
1533 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001534}
1535
1536void InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible(
1537 CommandEntry* commandEntry) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001538 sp<Connection> connection = commandEntry->connection;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001539
Jeff Brown7fbdc842010-06-17 20:52:56 -07001540 if (connection->status != Connection::STATUS_ZOMBIE) {
1541 mLock.unlock();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001542
Jeff Brown7fbdc842010-06-17 20:52:56 -07001543 mPolicy->notifyInputChannelRecoveredFromANR(connection->inputChannel);
1544
1545 mLock.lock();
1546 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001547}
1548
1549
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001550// --- InputDispatcher::Allocator ---
1551
1552InputDispatcher::Allocator::Allocator() {
1553}
1554
Jeff Brown7fbdc842010-06-17 20:52:56 -07001555void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
1556 nsecs_t eventTime) {
1557 entry->type = type;
1558 entry->refCount = 1;
1559 entry->dispatchInProgress = false;
Christopher Tatee91a5db2010-06-23 16:50:30 -07001560 entry->eventTime = eventTime;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001561 entry->injectionResult = INPUT_EVENT_INJECTION_PENDING;
Jeff Brown6ec402b2010-07-28 15:48:59 -07001562 entry->injectionIsAsync = false;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001563 entry->injectorPid = -1;
1564 entry->injectorUid = -1;
Jeff Brown6ec402b2010-07-28 15:48:59 -07001565 entry->pendingSyncDispatches = 0;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001566}
1567
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001568InputDispatcher::ConfigurationChangedEntry*
Jeff Brown7fbdc842010-06-17 20:52:56 -07001569InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001570 ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
Jeff Brown7fbdc842010-06-17 20:52:56 -07001571 initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001572 return entry;
1573}
1574
Jeff Brown7fbdc842010-06-17 20:52:56 -07001575InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -07001576 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001577 int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
1578 int32_t repeatCount, nsecs_t downTime) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001579 KeyEntry* entry = mKeyEntryPool.alloc();
Jeff Brown7fbdc842010-06-17 20:52:56 -07001580 initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime);
1581
1582 entry->deviceId = deviceId;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001583 entry->source = source;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001584 entry->policyFlags = policyFlags;
1585 entry->action = action;
1586 entry->flags = flags;
1587 entry->keyCode = keyCode;
1588 entry->scanCode = scanCode;
1589 entry->metaState = metaState;
1590 entry->repeatCount = repeatCount;
1591 entry->downTime = downTime;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001592 return entry;
1593}
1594
Jeff Brown7fbdc842010-06-17 20:52:56 -07001595InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -07001596 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001597 int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
1598 nsecs_t downTime, uint32_t pointerCount,
1599 const int32_t* pointerIds, const PointerCoords* pointerCoords) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001600 MotionEntry* entry = mMotionEntryPool.alloc();
Jeff Brown7fbdc842010-06-17 20:52:56 -07001601 initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime);
1602
1603 entry->eventTime = eventTime;
1604 entry->deviceId = deviceId;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001605 entry->source = source;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001606 entry->policyFlags = policyFlags;
1607 entry->action = action;
1608 entry->metaState = metaState;
1609 entry->edgeFlags = edgeFlags;
1610 entry->xPrecision = xPrecision;
1611 entry->yPrecision = yPrecision;
1612 entry->downTime = downTime;
1613 entry->pointerCount = pointerCount;
1614 entry->firstSample.eventTime = eventTime;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001615 entry->firstSample.next = NULL;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001616 entry->lastSample = & entry->firstSample;
1617 for (uint32_t i = 0; i < pointerCount; i++) {
1618 entry->pointerIds[i] = pointerIds[i];
1619 entry->firstSample.pointerCoords[i] = pointerCoords[i];
1620 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001621 return entry;
1622}
1623
1624InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
1625 EventEntry* eventEntry) {
1626 DispatchEntry* entry = mDispatchEntryPool.alloc();
1627 entry->eventEntry = eventEntry;
1628 eventEntry->refCount += 1;
1629 return entry;
1630}
1631
Jeff Brown9c3cda02010-06-15 01:31:58 -07001632InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
1633 CommandEntry* entry = mCommandEntryPool.alloc();
1634 entry->command = command;
1635 return entry;
1636}
1637
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001638void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
1639 switch (entry->type) {
1640 case EventEntry::TYPE_CONFIGURATION_CHANGED:
1641 releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
1642 break;
1643 case EventEntry::TYPE_KEY:
1644 releaseKeyEntry(static_cast<KeyEntry*>(entry));
1645 break;
1646 case EventEntry::TYPE_MOTION:
1647 releaseMotionEntry(static_cast<MotionEntry*>(entry));
1648 break;
1649 default:
1650 assert(false);
1651 break;
1652 }
1653}
1654
1655void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
1656 ConfigurationChangedEntry* entry) {
1657 entry->refCount -= 1;
1658 if (entry->refCount == 0) {
1659 mConfigurationChangeEntryPool.free(entry);
1660 } else {
1661 assert(entry->refCount > 0);
1662 }
1663}
1664
1665void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
1666 entry->refCount -= 1;
1667 if (entry->refCount == 0) {
1668 mKeyEntryPool.free(entry);
1669 } else {
1670 assert(entry->refCount > 0);
1671 }
1672}
1673
1674void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
1675 entry->refCount -= 1;
1676 if (entry->refCount == 0) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001677 for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
1678 MotionSample* next = sample->next;
1679 mMotionSamplePool.free(sample);
1680 sample = next;
1681 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001682 mMotionEntryPool.free(entry);
1683 } else {
1684 assert(entry->refCount > 0);
1685 }
1686}
1687
1688void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
1689 releaseEventEntry(entry->eventEntry);
1690 mDispatchEntryPool.free(entry);
1691}
1692
Jeff Brown9c3cda02010-06-15 01:31:58 -07001693void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
1694 mCommandEntryPool.free(entry);
1695}
1696
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001697void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001698 nsecs_t eventTime, const PointerCoords* pointerCoords) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001699 MotionSample* sample = mMotionSamplePool.alloc();
1700 sample->eventTime = eventTime;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001701 uint32_t pointerCount = motionEntry->pointerCount;
1702 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001703 sample->pointerCoords[i] = pointerCoords[i];
1704 }
1705
1706 sample->next = NULL;
1707 motionEntry->lastSample->next = sample;
1708 motionEntry->lastSample = sample;
1709}
1710
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001711// --- InputDispatcher::Connection ---
1712
1713InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
1714 status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
1715 nextTimeoutTime(LONG_LONG_MAX),
1716 lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX),
1717 lastANRTime(LONG_LONG_MAX) {
1718}
1719
1720InputDispatcher::Connection::~Connection() {
1721}
1722
1723status_t InputDispatcher::Connection::initialize() {
1724 return inputPublisher.initialize();
1725}
1726
Jeff Brown7fbdc842010-06-17 20:52:56 -07001727void InputDispatcher::Connection::setNextTimeoutTime(nsecs_t currentTime, nsecs_t timeout) {
1728 nextTimeoutTime = (timeout >= 0) ? currentTime + timeout : LONG_LONG_MAX;
1729}
1730
Jeff Brown9c3cda02010-06-15 01:31:58 -07001731const char* InputDispatcher::Connection::getStatusLabel() const {
1732 switch (status) {
1733 case STATUS_NORMAL:
1734 return "NORMAL";
1735
1736 case STATUS_BROKEN:
1737 return "BROKEN";
1738
1739 case STATUS_NOT_RESPONDING:
1740 return "NOT_RESPONDING";
1741
1742 case STATUS_ZOMBIE:
1743 return "ZOMBIE";
1744
1745 default:
1746 return "UNKNOWN";
1747 }
1748}
1749
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001750InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
1751 const EventEntry* eventEntry) const {
1752 for (DispatchEntry* dispatchEntry = outboundQueue.tail.prev;
1753 dispatchEntry != & outboundQueue.head; dispatchEntry = dispatchEntry->prev) {
1754 if (dispatchEntry->eventEntry == eventEntry) {
1755 return dispatchEntry;
1756 }
1757 }
1758 return NULL;
1759}
1760
Jeff Brown9c3cda02010-06-15 01:31:58 -07001761// --- InputDispatcher::CommandEntry ---
1762
1763InputDispatcher::CommandEntry::CommandEntry() {
1764}
1765
1766InputDispatcher::CommandEntry::~CommandEntry() {
1767}
1768
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001769
1770// --- InputDispatcherThread ---
1771
1772InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
1773 Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
1774}
1775
1776InputDispatcherThread::~InputDispatcherThread() {
1777}
1778
1779bool InputDispatcherThread::threadLoop() {
1780 mDispatcher->dispatchOnce();
1781 return true;
1782}
1783
1784} // namespace android