blob: 0ccde0d3125299e678cf910a96aef48df7c6a6b0 [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.
11#define DEBUG_INBOUND_EVENT_DETAILS 1
12
13// Log detailed debug messages about each outbound event processed by the dispatcher.
14#define DEBUG_OUTBOUND_EVENT_DETAILS 1
15
16// Log debug messages about batching.
17#define DEBUG_BATCHING 1
18
19// Log debug messages about the dispatch cycle.
20#define DEBUG_DISPATCH_CYCLE 1
21
22// Log debug messages about performance statistics.
23#define DEBUG_PERFORMANCE_STATISTICS 1
24
25#include <cutils/log.h>
26#include <ui/InputDispatcher.h>
27
28#include <stddef.h>
29#include <unistd.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070030#include <errno.h>
31#include <limits.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070032
33namespace android {
34
35// TODO, this needs to be somewhere else, perhaps in the policy
36static inline bool isMovementKey(int32_t keyCode) {
37 return keyCode == KEYCODE_DPAD_UP
38 || keyCode == KEYCODE_DPAD_DOWN
39 || keyCode == KEYCODE_DPAD_LEFT
40 || keyCode == KEYCODE_DPAD_RIGHT;
41}
42
43// --- InputDispatcher ---
44
45InputDispatcher::InputDispatcher(const sp<InputDispatchPolicyInterface>& policy) :
46 mPolicy(policy) {
47 mPollLoop = new PollLoop();
48
49 mInboundQueue.head.refCount = -1;
50 mInboundQueue.head.type = EventEntry::TYPE_SENTINEL;
51 mInboundQueue.head.eventTime = LONG_LONG_MIN;
52
53 mInboundQueue.tail.refCount = -1;
54 mInboundQueue.tail.type = EventEntry::TYPE_SENTINEL;
55 mInboundQueue.tail.eventTime = LONG_LONG_MAX;
56
57 mKeyRepeatState.lastKeyEntry = NULL;
58}
59
60InputDispatcher::~InputDispatcher() {
61 resetKeyRepeatLocked();
62
63 while (mConnectionsByReceiveFd.size() != 0) {
64 unregisterInputChannel(mConnectionsByReceiveFd.valueAt(0)->inputChannel);
65 }
66
67 for (EventEntry* entry = mInboundQueue.head.next; entry != & mInboundQueue.tail; ) {
68 EventEntry* next = entry->next;
69 mAllocator.releaseEventEntry(next);
70 entry = next;
71 }
72}
73
74void InputDispatcher::dispatchOnce() {
75 bool allowKeyRepeat = mPolicy->allowKeyRepeat();
76
77 nsecs_t currentTime;
78 nsecs_t nextWakeupTime = LONG_LONG_MAX;
79 { // acquire lock
80 AutoMutex _l(mLock);
81 currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
82
83 // Reset the key repeat timer whenever we disallow key events, even if the next event
84 // is not a key. This is to ensure that we abort a key repeat if the device is just coming
85 // out of sleep.
86 // XXX we should handle resetting input state coming out of sleep more generally elsewhere
87 if (! allowKeyRepeat) {
88 resetKeyRepeatLocked();
89 }
90
91 // Process timeouts for all connections and determine if there are any synchronous
92 // event dispatches pending.
93 bool hasPendingSyncTarget = false;
94 for (size_t i = 0; i < mActiveConnections.size(); ) {
95 Connection* connection = mActiveConnections.itemAt(i);
96
97 nsecs_t connectionTimeoutTime = connection->nextTimeoutTime;
98 if (connectionTimeoutTime <= currentTime) {
99 bool deactivated = timeoutDispatchCycleLocked(currentTime, connection);
100 if (deactivated) {
101 // Don't increment i because the connection has been removed
102 // from mActiveConnections (hence, deactivated).
103 continue;
104 }
105 }
106
107 if (connectionTimeoutTime < nextWakeupTime) {
108 nextWakeupTime = connectionTimeoutTime;
109 }
110
111 if (connection->hasPendingSyncTarget()) {
112 hasPendingSyncTarget = true;
113 }
114
115 i += 1;
116 }
117
118 // If we don't have a pending sync target, then we can begin delivering a new event.
119 // (Otherwise we wait for dispatch to complete for that target.)
120 if (! hasPendingSyncTarget) {
121 if (mInboundQueue.isEmpty()) {
122 if (mKeyRepeatState.lastKeyEntry) {
123 if (currentTime >= mKeyRepeatState.nextRepeatTime) {
124 processKeyRepeatLocked(currentTime);
125 return; // dispatched once
126 } else {
127 if (mKeyRepeatState.nextRepeatTime < nextWakeupTime) {
128 nextWakeupTime = mKeyRepeatState.nextRepeatTime;
129 }
130 }
131 }
132 } else {
133 // Inbound queue has at least one entry. Dequeue it and begin dispatching.
134 // Note that we do not hold the lock for this process because dispatching may
135 // involve making many callbacks.
136 EventEntry* entry = mInboundQueue.dequeueAtHead();
137
138 switch (entry->type) {
139 case EventEntry::TYPE_CONFIGURATION_CHANGED: {
140 ConfigurationChangedEntry* typedEntry =
141 static_cast<ConfigurationChangedEntry*>(entry);
142 processConfigurationChangedLocked(currentTime, typedEntry);
143 mAllocator.releaseConfigurationChangedEntry(typedEntry);
144 break;
145 }
146
147 case EventEntry::TYPE_KEY: {
148 KeyEntry* typedEntry = static_cast<KeyEntry*>(entry);
149 processKeyLocked(currentTime, typedEntry);
150 mAllocator.releaseKeyEntry(typedEntry);
151 break;
152 }
153
154 case EventEntry::TYPE_MOTION: {
155 MotionEntry* typedEntry = static_cast<MotionEntry*>(entry);
156 processMotionLocked(currentTime, typedEntry);
157 mAllocator.releaseMotionEntry(typedEntry);
158 break;
159 }
160
161 default:
162 assert(false);
163 break;
164 }
165 return; // dispatched once
166 }
167 }
168 } // release lock
169
170 // Wait for callback or timeout or wake.
171 nsecs_t timeout = nanoseconds_to_milliseconds(nextWakeupTime - currentTime);
172 int32_t timeoutMillis = timeout > INT_MAX ? -1 : timeout > 0 ? int32_t(timeout) : 0;
173 mPollLoop->pollOnce(timeoutMillis);
174}
175
176void InputDispatcher::processConfigurationChangedLocked(nsecs_t currentTime,
177 ConfigurationChangedEntry* entry) {
178#if DEBUG_OUTBOUND_EVENT_DETAILS
179 LOGD("processConfigurationChanged - eventTime=%lld, touchScreenConfig=%d, "
180 "keyboardConfig=%d, navigationConfig=%d", entry->eventTime,
181 entry->touchScreenConfig, entry->keyboardConfig, entry->navigationConfig);
182#endif
183
184 mPolicy->notifyConfigurationChanged(entry->eventTime, entry->touchScreenConfig,
185 entry->keyboardConfig, entry->navigationConfig);
186}
187
188void InputDispatcher::processKeyLocked(nsecs_t currentTime, KeyEntry* entry) {
189#if DEBUG_OUTBOUND_EVENT_DETAILS
190 LOGD("processKey - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, action=0x%x, "
191 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
192 entry->eventTime, entry->deviceId, entry->nature, entry->policyFlags, entry->action,
193 entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
194 entry->downTime);
195#endif
196
197 // TODO: Poke user activity.
198
199 if (entry->action == KEY_EVENT_ACTION_DOWN) {
200 if (mKeyRepeatState.lastKeyEntry
201 && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
202 // We have seen two identical key downs in a row which indicates that the device
203 // driver is automatically generating key repeats itself. We take note of the
204 // repeat here, but we disable our own next key repeat timer since it is clear that
205 // we will not need to synthesize key repeats ourselves.
206 entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
207 resetKeyRepeatLocked();
208 mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
209 } else {
210 // Not a repeat. Save key down state in case we do see a repeat later.
211 resetKeyRepeatLocked();
212 mKeyRepeatState.nextRepeatTime = entry->eventTime + mPolicy->getKeyRepeatTimeout();
213 }
214 mKeyRepeatState.lastKeyEntry = entry;
215 entry->refCount += 1;
216 } else {
217 resetKeyRepeatLocked();
218 }
219
220 identifyInputTargetsAndDispatchKeyLocked(currentTime, entry);
221}
222
223void InputDispatcher::processKeyRepeatLocked(nsecs_t currentTime) {
224 // TODO Old WindowManagerServer code sniffs the input queue for following key up
225 // events and drops the repeat if one is found. We should do something similar.
226 // One good place to do it is in notifyKey as soon as the key up enters the
227 // inbound event queue.
228
229 // Synthesize a key repeat after the repeat timeout expired.
230 // We reuse the previous key entry if otherwise unreferenced.
231 KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
232 if (entry->refCount == 1) {
233 entry->repeatCount += 1;
234 } else {
235 KeyEntry* newEntry = mAllocator.obtainKeyEntry();
236 newEntry->deviceId = entry->deviceId;
237 newEntry->nature = entry->nature;
238 newEntry->policyFlags = entry->policyFlags;
239 newEntry->action = entry->action;
240 newEntry->flags = entry->flags;
241 newEntry->keyCode = entry->keyCode;
242 newEntry->scanCode = entry->scanCode;
243 newEntry->metaState = entry->metaState;
244 newEntry->repeatCount = entry->repeatCount + 1;
245
246 mKeyRepeatState.lastKeyEntry = newEntry;
247 mAllocator.releaseKeyEntry(entry);
248
249 entry = newEntry;
250 }
251 entry->eventTime = currentTime;
252 entry->downTime = currentTime;
253 entry->policyFlags = 0;
254
255 mKeyRepeatState.nextRepeatTime = currentTime + mPolicy->getKeyRepeatTimeout();
256
257#if DEBUG_OUTBOUND_EVENT_DETAILS
258 LOGD("processKeyRepeat - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, "
259 "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
260 "repeatCount=%d, downTime=%lld",
261 entry->eventTime, entry->deviceId, entry->nature, entry->policyFlags,
262 entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
263 entry->repeatCount, entry->downTime);
264#endif
265
266 identifyInputTargetsAndDispatchKeyLocked(currentTime, entry);
267}
268
269void InputDispatcher::processMotionLocked(nsecs_t currentTime, MotionEntry* entry) {
270#if DEBUG_OUTBOUND_EVENT_DETAILS
271 LOGD("processMotion - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, action=0x%x, "
272 "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
273 entry->eventTime, entry->deviceId, entry->nature, entry->policyFlags, entry->action,
274 entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
275 entry->downTime);
276
277 // Print the most recent sample that we have available, this may change due to batching.
278 size_t sampleCount = 1;
279 MotionSample* sample = & entry->firstSample;
280 for (; sample->next != NULL; sample = sample->next) {
281 sampleCount += 1;
282 }
283 for (uint32_t i = 0; i < entry->pointerCount; i++) {
284 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
285 i, entry->pointerIds[i],
286 sample->pointerCoords[i].x,
287 sample->pointerCoords[i].y,
288 sample->pointerCoords[i].pressure,
289 sample->pointerCoords[i].size);
290 }
291
292 // Keep in mind that due to batching, it is possible for the number of samples actually
293 // dispatched to change before the application finally consumed them.
294 if (entry->action == MOTION_EVENT_ACTION_MOVE) {
295 LOGD(" ... Total movement samples currently batched %d ...", sampleCount);
296 }
297#endif
298
299 identifyInputTargetsAndDispatchMotionLocked(currentTime, entry);
300}
301
302void InputDispatcher::identifyInputTargetsAndDispatchKeyLocked(
303 nsecs_t currentTime, KeyEntry* entry) {
304#if DEBUG_DISPATCH_CYCLE
305 LOGD("identifyInputTargetsAndDispatchKey");
306#endif
307
308 mReusableKeyEvent.initialize(entry->deviceId, entry->nature, entry->action, entry->flags,
309 entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
310 entry->downTime, entry->eventTime);
311
312 mCurrentInputTargets.clear();
313 mPolicy->getKeyEventTargets(& mReusableKeyEvent, entry->policyFlags,
314 mCurrentInputTargets);
315
316 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
317}
318
319void InputDispatcher::identifyInputTargetsAndDispatchMotionLocked(
320 nsecs_t currentTime, MotionEntry* entry) {
321#if DEBUG_DISPATCH_CYCLE
322 LOGD("identifyInputTargetsAndDispatchMotion");
323#endif
324
325 mReusableMotionEvent.initialize(entry->deviceId, entry->nature, entry->action,
326 entry->edgeFlags, entry->metaState,
327 entry->firstSample.pointerCoords[0].x, entry->firstSample.pointerCoords[0].y,
328 entry->xPrecision, entry->yPrecision,
329 entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds,
330 entry->firstSample.pointerCoords);
331
332 mCurrentInputTargets.clear();
333 mPolicy->getMotionEventTargets(& mReusableMotionEvent, entry->policyFlags,
334 mCurrentInputTargets);
335
336 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
337}
338
339void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
340 EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
341#if DEBUG_DISPATCH_CYCLE
342 LOGD("dispatchEventToCurrentInputTargets, "
343 "resumeWithAppendedMotionSample=%s",
344 resumeWithAppendedMotionSample ? "true" : "false");
345#endif
346
347 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
348 const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
349
350 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(
351 inputTarget.inputChannel->getReceivePipeFd());
352 if (connectionIndex >= 0) {
353 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
354 prepareDispatchCycleLocked(currentTime, connection.get(), eventEntry, & inputTarget,
355 resumeWithAppendedMotionSample);
356 } else {
357 LOGW("Framework requested delivery of an input event to channel '%s' but it "
358 "is not registered with the input dispatcher.",
359 inputTarget.inputChannel->getName().string());
360 }
361 }
362}
363
364void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, Connection* connection,
365 EventEntry* eventEntry, const InputTarget* inputTarget,
366 bool resumeWithAppendedMotionSample) {
367#if DEBUG_DISPATCH_CYCLE
368 LOGD("channel '%s' ~ prepareDispatchCycle, flags=%d, timeout=%lldns, "
369 "xOffset=%f, yOffset=%f, resumeWithAppendedMotionSample=%s",
370 connection->getInputChannelName(), inputTarget->flags, inputTarget->timeout,
371 inputTarget->xOffset, inputTarget->yOffset,
372 resumeWithAppendedMotionSample ? "true" : "false");
373#endif
374
375 // Skip this event if the connection status is not normal.
376 // We don't want to queue outbound events at all if the connection is broken or
377 // not responding.
378 if (connection->status != Connection::STATUS_NORMAL) {
379 LOGV("channel '%s' ~ Dropping event because the channel status is %s",
380 connection->status == Connection::STATUS_BROKEN ? "BROKEN" : "NOT RESPONDING");
381 return;
382 }
383
384 // Resume the dispatch cycle with a freshly appended motion sample.
385 // First we check that the last dispatch entry in the outbound queue is for the same
386 // motion event to which we appended the motion sample. If we find such a dispatch
387 // entry, and if it is currently in progress then we try to stream the new sample.
388 bool wasEmpty = connection->outboundQueue.isEmpty();
389
390 if (! wasEmpty && resumeWithAppendedMotionSample) {
391 DispatchEntry* motionEventDispatchEntry =
392 connection->findQueuedDispatchEntryForEvent(eventEntry);
393 if (motionEventDispatchEntry) {
394 // If the dispatch entry is not in progress, then we must be busy dispatching an
395 // earlier event. Not a problem, the motion event is on the outbound queue and will
396 // be dispatched later.
397 if (! motionEventDispatchEntry->inProgress) {
398#if DEBUG_BATCHING
399 LOGD("channel '%s' ~ Not streaming because the motion event has "
400 "not yet been dispatched. "
401 "(Waiting for earlier events to be consumed.)",
402 connection->getInputChannelName());
403#endif
404 return;
405 }
406
407 // If the dispatch entry is in progress but it already has a tail of pending
408 // motion samples, then it must mean that the shared memory buffer filled up.
409 // Not a problem, when this dispatch cycle is finished, we will eventually start
410 // a new dispatch cycle to process the tail and that tail includes the newly
411 // appended motion sample.
412 if (motionEventDispatchEntry->tailMotionSample) {
413#if DEBUG_BATCHING
414 LOGD("channel '%s' ~ Not streaming because no new samples can "
415 "be appended to the motion event in this dispatch cycle. "
416 "(Waiting for next dispatch cycle to start.)",
417 connection->getInputChannelName());
418#endif
419 return;
420 }
421
422 // The dispatch entry is in progress and is still potentially open for streaming.
423 // Try to stream the new motion sample. This might fail if the consumer has already
424 // consumed the motion event (or if the channel is broken).
425 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
426 status_t status = connection->inputPublisher.appendMotionSample(
427 appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
428 if (status == OK) {
429#if DEBUG_BATCHING
430 LOGD("channel '%s' ~ Successfully streamed new motion sample.",
431 connection->getInputChannelName());
432#endif
433 return;
434 }
435
436#if DEBUG_BATCHING
437 if (status == NO_MEMORY) {
438 LOGD("channel '%s' ~ Could not append motion sample to currently "
439 "dispatched move event because the shared memory buffer is full. "
440 "(Waiting for next dispatch cycle to start.)",
441 connection->getInputChannelName());
442 } else if (status == status_t(FAILED_TRANSACTION)) {
443 LOGD("channel '%s' ~ Could not append motion sample to currently "
444 "dispatchedmove event because the event has already been consumed. "
445 "(Waiting for next dispatch cycle to start.)",
446 connection->getInputChannelName());
447 } else {
448 LOGD("channel '%s' ~ Could not append motion sample to currently "
449 "dispatched move event due to an error, status=%d. "
450 "(Waiting for next dispatch cycle to start.)",
451 connection->getInputChannelName(), status);
452 }
453#endif
454 // Failed to stream. Start a new tail of pending motion samples to dispatch
455 // in the next cycle.
456 motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
457 return;
458 }
459 }
460
461 // This is a new event.
462 // Enqueue a new dispatch entry onto the outbound queue for this connection.
463 DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry); // increments ref
464 dispatchEntry->targetFlags = inputTarget->flags;
465 dispatchEntry->xOffset = inputTarget->xOffset;
466 dispatchEntry->yOffset = inputTarget->yOffset;
467 dispatchEntry->timeout = inputTarget->timeout;
468 dispatchEntry->inProgress = false;
469 dispatchEntry->headMotionSample = NULL;
470 dispatchEntry->tailMotionSample = NULL;
471
472 // Handle the case where we could not stream a new motion sample because the consumer has
473 // already consumed the motion event (otherwise the corresponding dispatch entry would
474 // still be in the outbound queue for this connection). We set the head motion sample
475 // to the list starting with the newly appended motion sample.
476 if (resumeWithAppendedMotionSample) {
477#if DEBUG_BATCHING
478 LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
479 "that cannot be streamed because the motion event has already been consumed.",
480 connection->getInputChannelName());
481#endif
482 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
483 dispatchEntry->headMotionSample = appendedMotionSample;
484 }
485
486 // Enqueue the dispatch entry.
487 connection->outboundQueue.enqueueAtTail(dispatchEntry);
488
489 // If the outbound queue was previously empty, start the dispatch cycle going.
490 if (wasEmpty) {
491 activateConnectionLocked(connection);
492 startDispatchCycleLocked(currentTime, connection);
493 }
494}
495
496void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, Connection* connection) {
497#if DEBUG_DISPATCH_CYCLE
498 LOGD("channel '%s' ~ startDispatchCycle",
499 connection->getInputChannelName());
500#endif
501
502 assert(connection->status == Connection::STATUS_NORMAL);
503 assert(! connection->outboundQueue.isEmpty());
504
505 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
506 assert(! dispatchEntry->inProgress);
507
508 // TODO throttle successive ACTION_MOVE motion events for the same device
509 // possible implementation could set a brief poll timeout here and resume starting the
510 // dispatch cycle when elapsed
511
512 // Publish the event.
513 status_t status;
514 switch (dispatchEntry->eventEntry->type) {
515 case EventEntry::TYPE_KEY: {
516 KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
517
518 // Apply target flags.
519 int32_t action = keyEntry->action;
520 int32_t flags = keyEntry->flags;
521 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
522 flags |= KEY_EVENT_FLAG_CANCELED;
523 }
524
525 // Publish the key event.
526 status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->nature,
527 action, flags, keyEntry->keyCode, keyEntry->scanCode,
528 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
529 keyEntry->eventTime);
530
531 if (status) {
532 LOGE("channel '%s' ~ Could not publish key event, "
533 "status=%d", connection->getInputChannelName(), status);
534 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
535 return;
536 }
537 break;
538 }
539
540 case EventEntry::TYPE_MOTION: {
541 MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
542
543 // Apply target flags.
544 int32_t action = motionEntry->action;
545 if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
546 action = MOTION_EVENT_ACTION_OUTSIDE;
547 }
548 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
549 action = MOTION_EVENT_ACTION_CANCEL;
550 }
551
552 // If headMotionSample is non-NULL, then it points to the first new sample that we
553 // were unable to dispatch during the previous cycle so we resume dispatching from
554 // that point in the list of motion samples.
555 // Otherwise, we just start from the first sample of the motion event.
556 MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
557 if (! firstMotionSample) {
558 firstMotionSample = & motionEntry->firstSample;
559 }
560
561 // Publish the motion event and the first motion sample.
562 status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
563 motionEntry->nature, action, motionEntry->edgeFlags, motionEntry->metaState,
564 dispatchEntry->xOffset, dispatchEntry->yOffset,
565 motionEntry->xPrecision, motionEntry->yPrecision,
566 motionEntry->downTime, firstMotionSample->eventTime,
567 motionEntry->pointerCount, motionEntry->pointerIds,
568 firstMotionSample->pointerCoords);
569
570 if (status) {
571 LOGE("channel '%s' ~ Could not publish motion event, "
572 "status=%d", connection->getInputChannelName(), status);
573 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
574 return;
575 }
576
577 // Append additional motion samples.
578 MotionSample* nextMotionSample = firstMotionSample->next;
579 for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
580 status = connection->inputPublisher.appendMotionSample(
581 nextMotionSample->eventTime, nextMotionSample->pointerCoords);
582 if (status == NO_MEMORY) {
583#if DEBUG_DISPATCH_CYCLE
584 LOGD("channel '%s' ~ Shared memory buffer full. Some motion samples will "
585 "be sent in the next dispatch cycle.",
586 connection->getInputChannelName());
587#endif
588 break;
589 }
590 if (status != OK) {
591 LOGE("channel '%s' ~ Could not append motion sample "
592 "for a reason other than out of memory, status=%d",
593 connection->getInputChannelName(), status);
594 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
595 return;
596 }
597 }
598
599 // Remember the next motion sample that we could not dispatch, in case we ran out
600 // of space in the shared memory buffer.
601 dispatchEntry->tailMotionSample = nextMotionSample;
602 break;
603 }
604
605 default: {
606 assert(false);
607 }
608 }
609
610 // Send the dispatch signal.
611 status = connection->inputPublisher.sendDispatchSignal();
612 if (status) {
613 LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
614 connection->getInputChannelName(), status);
615 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
616 return;
617 }
618
619 // Record information about the newly started dispatch cycle.
620 dispatchEntry->inProgress = true;
621
622 connection->lastEventTime = dispatchEntry->eventEntry->eventTime;
623 connection->lastDispatchTime = currentTime;
624
625 nsecs_t timeout = dispatchEntry->timeout;
626 connection->nextTimeoutTime = (timeout >= 0) ? currentTime + timeout : LONG_LONG_MAX;
627
628 // Notify other system components.
629 onDispatchCycleStartedLocked(currentTime, connection);
630}
631
632void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime, Connection* connection) {
633#if DEBUG_DISPATCH_CYCLE
634 LOGD("channel '%s' ~ finishDispatchCycle: %01.1fms since event, "
635 "%01.1fms since dispatch",
636 connection->getInputChannelName(),
637 connection->getEventLatencyMillis(currentTime),
638 connection->getDispatchLatencyMillis(currentTime));
639#endif
640
641 if (connection->status == Connection::STATUS_BROKEN) {
642 return;
643 }
644
645 // Clear the pending timeout.
646 connection->nextTimeoutTime = LONG_LONG_MAX;
647
648 if (connection->status == Connection::STATUS_NOT_RESPONDING) {
649 // Recovering from an ANR.
650 connection->status = Connection::STATUS_NORMAL;
651
652 // Notify other system components.
653 onDispatchCycleFinishedLocked(currentTime, connection, true /*recoveredFromANR*/);
654 } else {
655 // Normal finish. Not much to do here.
656
657 // Notify other system components.
658 onDispatchCycleFinishedLocked(currentTime, connection, false /*recoveredFromANR*/);
659 }
660
661 // Reset the publisher since the event has been consumed.
662 // We do this now so that the publisher can release some of its internal resources
663 // while waiting for the next dispatch cycle to begin.
664 status_t status = connection->inputPublisher.reset();
665 if (status) {
666 LOGE("channel '%s' ~ Could not reset publisher, status=%d",
667 connection->getInputChannelName(), status);
668 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
669 return;
670 }
671
672 // Start the next dispatch cycle for this connection.
673 while (! connection->outboundQueue.isEmpty()) {
674 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
675 if (dispatchEntry->inProgress) {
676 // Finish or resume current event in progress.
677 if (dispatchEntry->tailMotionSample) {
678 // We have a tail of undispatched motion samples.
679 // Reuse the same DispatchEntry and start a new cycle.
680 dispatchEntry->inProgress = false;
681 dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
682 dispatchEntry->tailMotionSample = NULL;
683 startDispatchCycleLocked(currentTime, connection);
684 return;
685 }
686 // Finished.
687 connection->outboundQueue.dequeueAtHead();
688 mAllocator.releaseDispatchEntry(dispatchEntry);
689 } else {
690 // If the head is not in progress, then we must have already dequeued the in
691 // progress event, which means we actually aborted it (due to ANR).
692 // So just start the next event for this connection.
693 startDispatchCycleLocked(currentTime, connection);
694 return;
695 }
696 }
697
698 // Outbound queue is empty, deactivate the connection.
699 deactivateConnectionLocked(connection);
700}
701
702bool InputDispatcher::timeoutDispatchCycleLocked(nsecs_t currentTime, Connection* connection) {
703#if DEBUG_DISPATCH_CYCLE
704 LOGD("channel '%s' ~ timeoutDispatchCycle",
705 connection->getInputChannelName());
706#endif
707
708 if (connection->status != Connection::STATUS_NORMAL) {
709 return false;
710 }
711
712 // Enter the not responding state.
713 connection->status = Connection::STATUS_NOT_RESPONDING;
714 connection->lastANRTime = currentTime;
715 bool deactivated = abortDispatchCycleLocked(currentTime, connection, false /*(not) broken*/);
716
717 // Notify other system components.
718 onDispatchCycleANRLocked(currentTime, connection);
719 return deactivated;
720}
721
722bool InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime, Connection* connection,
723 bool broken) {
724#if DEBUG_DISPATCH_CYCLE
725 LOGD("channel '%s' ~ abortDispatchCycle, broken=%s",
726 connection->getInputChannelName(), broken ? "true" : "false");
727#endif
728
729 if (connection->status == Connection::STATUS_BROKEN) {
730 return false;
731 }
732
733 // Clear the pending timeout.
734 connection->nextTimeoutTime = LONG_LONG_MAX;
735
736 // Clear the outbound queue.
737 while (! connection->outboundQueue.isEmpty()) {
738 DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
739 mAllocator.releaseDispatchEntry(dispatchEntry);
740 }
741
742 // Outbound queue is empty, deactivate the connection.
743 deactivateConnectionLocked(connection);
744
745 // Handle the case where the connection appears to be unrecoverably broken.
746 if (broken) {
747 connection->status = Connection::STATUS_BROKEN;
748
749 // Notify other system components.
750 onDispatchCycleBrokenLocked(currentTime, connection);
751 }
752 return true; /*deactivated*/
753}
754
755bool InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
756 InputDispatcher* d = static_cast<InputDispatcher*>(data);
757
758 { // acquire lock
759 AutoMutex _l(d->mLock);
760
761 ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
762 if (connectionIndex < 0) {
763 LOGE("Received spurious receive callback for unknown input channel. "
764 "fd=%d, events=0x%x", receiveFd, events);
765 return false; // remove the callback
766 }
767
768 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
769
770 sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
771 if (events & (POLLERR | POLLHUP | POLLNVAL)) {
772 LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
773 "events=0x%x", connection->getInputChannelName(), events);
774 d->abortDispatchCycleLocked(currentTime, connection.get(), true /*broken*/);
775 return false; // remove the callback
776 }
777
778 if (! (events & POLLIN)) {
779 LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
780 "events=0x%x", connection->getInputChannelName(), events);
781 return true;
782 }
783
784 status_t status = connection->inputPublisher.receiveFinishedSignal();
785 if (status) {
786 LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
787 connection->getInputChannelName(), status);
788 d->abortDispatchCycleLocked(currentTime, connection.get(), true /*broken*/);
789 return false; // remove the callback
790 }
791
792 d->finishDispatchCycleLocked(currentTime, connection.get());
793 return true;
794 } // release lock
795}
796
797void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime, int32_t touchScreenConfig,
798 int32_t keyboardConfig, int32_t navigationConfig) {
799#if DEBUG_INBOUND_EVENT_DETAILS
800 LOGD("notifyConfigurationChanged - eventTime=%lld, touchScreenConfig=%d, "
801 "keyboardConfig=%d, navigationConfig=%d", eventTime,
802 touchScreenConfig, keyboardConfig, navigationConfig);
803#endif
804
805 bool wasEmpty;
806 { // acquire lock
807 AutoMutex _l(mLock);
808
809 ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry();
810 newEntry->eventTime = eventTime;
811 newEntry->touchScreenConfig = touchScreenConfig;
812 newEntry->keyboardConfig = keyboardConfig;
813 newEntry->navigationConfig = navigationConfig;
814
815 wasEmpty = mInboundQueue.isEmpty();
816 mInboundQueue.enqueueAtTail(newEntry);
817 } // release lock
818
819 if (wasEmpty) {
820 mPollLoop->wake();
821 }
822}
823
824void InputDispatcher::notifyLidSwitchChanged(nsecs_t eventTime, bool lidOpen) {
825#if DEBUG_INBOUND_EVENT_DETAILS
826 LOGD("notifyLidSwitchChanged - eventTime=%lld, open=%s", eventTime,
827 lidOpen ? "true" : "false");
828#endif
829
830 // Send lid switch notification immediately and synchronously.
831 mPolicy->notifyLidSwitchChanged(eventTime, lidOpen);
832}
833
834void InputDispatcher::notifyAppSwitchComing(nsecs_t eventTime) {
835#if DEBUG_INBOUND_EVENT_DETAILS
836 LOGD("notifyAppSwitchComing - eventTime=%lld", eventTime);
837#endif
838
839 // Remove movement keys from the queue from most recent to least recent, stopping at the
840 // first non-movement key.
841 // TODO: Include a detailed description of why we do this...
842
843 { // acquire lock
844 AutoMutex _l(mLock);
845
846 for (EventEntry* entry = mInboundQueue.tail.prev; entry != & mInboundQueue.head; ) {
847 EventEntry* prev = entry->prev;
848
849 if (entry->type == EventEntry::TYPE_KEY) {
850 KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
851 if (isMovementKey(keyEntry->keyCode)) {
852 LOGV("Dropping movement key during app switch: keyCode=%d, action=%d",
853 keyEntry->keyCode, keyEntry->action);
854 mInboundQueue.dequeue(keyEntry);
855 mAllocator.releaseKeyEntry(keyEntry);
856 } else {
857 // stop at last non-movement key
858 break;
859 }
860 }
861
862 entry = prev;
863 }
864 } // release lock
865}
866
867void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
868 uint32_t policyFlags, int32_t action, int32_t flags,
869 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
870#if DEBUG_INBOUND_EVENT_DETAILS
871 LOGD("notifyKey - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, action=0x%x, "
872 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
873 eventTime, deviceId, nature, policyFlags, action, flags,
874 keyCode, scanCode, metaState, downTime);
875#endif
876
877 bool wasEmpty;
878 { // acquire lock
879 AutoMutex _l(mLock);
880
881 KeyEntry* newEntry = mAllocator.obtainKeyEntry();
882 newEntry->eventTime = eventTime;
883 newEntry->deviceId = deviceId;
884 newEntry->nature = nature;
885 newEntry->policyFlags = policyFlags;
886 newEntry->action = action;
887 newEntry->flags = flags;
888 newEntry->keyCode = keyCode;
889 newEntry->scanCode = scanCode;
890 newEntry->metaState = metaState;
891 newEntry->repeatCount = 0;
892 newEntry->downTime = downTime;
893
894 wasEmpty = mInboundQueue.isEmpty();
895 mInboundQueue.enqueueAtTail(newEntry);
896 } // release lock
897
898 if (wasEmpty) {
899 mPollLoop->wake();
900 }
901}
902
903void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t nature,
904 uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
905 uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
906 float xPrecision, float yPrecision, nsecs_t downTime) {
907#if DEBUG_INBOUND_EVENT_DETAILS
908 LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, "
909 "action=0x%x, metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, "
910 "downTime=%lld",
911 eventTime, deviceId, nature, policyFlags, action, metaState, edgeFlags,
912 xPrecision, yPrecision, downTime);
913 for (uint32_t i = 0; i < pointerCount; i++) {
914 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
915 i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
916 pointerCoords[i].pressure, pointerCoords[i].size);
917 }
918#endif
919
920 bool wasEmpty;
921 { // acquire lock
922 AutoMutex _l(mLock);
923
924 // Attempt batching and streaming of move events.
925 if (action == MOTION_EVENT_ACTION_MOVE) {
926 // BATCHING CASE
927 //
928 // Try to append a move sample to the tail of the inbound queue for this device.
929 // Give up if we encounter a non-move motion event for this device since that
930 // means we cannot append any new samples until a new motion event has started.
931 for (EventEntry* entry = mInboundQueue.tail.prev;
932 entry != & mInboundQueue.head; entry = entry->prev) {
933 if (entry->type != EventEntry::TYPE_MOTION) {
934 // Keep looking for motion events.
935 continue;
936 }
937
938 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
939 if (motionEntry->deviceId != deviceId) {
940 // Keep looking for this device.
941 continue;
942 }
943
944 if (motionEntry->action != MOTION_EVENT_ACTION_MOVE
945 || motionEntry->pointerCount != pointerCount) {
946 // Last motion event in the queue for this device is not compatible for
947 // appending new samples. Stop here.
948 goto NoBatchingOrStreaming;
949 }
950
951 // The last motion event is a move and is compatible for appending.
952 // Do the batching magic and exit.
953 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCount, pointerCoords);
954#if DEBUG_BATCHING
955 LOGD("Appended motion sample onto batch for most recent "
956 "motion event for this device in the inbound queue.");
957#endif
958 return; // done
959 }
960
961 // STREAMING CASE
962 //
963 // There is no pending motion event (of any kind) for this device in the inbound queue.
964 // Search the outbound queues for a synchronously dispatched motion event for this
965 // device. If found, then we append the new sample to that event and then try to
966 // push it out to all current targets. It is possible that some targets will already
967 // have consumed the motion event. This case is automatically handled by the
968 // logic in prepareDispatchCycleLocked by tracking where resumption takes place.
969 //
970 // The reason we look for a synchronously dispatched motion event is because we
971 // want to be sure that no other motion events have been dispatched since the move.
972 // It's also convenient because it means that the input targets are still valid.
973 // This code could be improved to support streaming of asynchronously dispatched
974 // motion events (which might be significantly more efficient) but it may become
975 // a little more complicated as a result.
976 //
977 // Note: This code crucially depends on the invariant that an outbound queue always
978 // contains at most one synchronous event and it is always last (but it might
979 // not be first!).
980 for (size_t i = 0; i < mActiveConnections.size(); i++) {
981 Connection* connection = mActiveConnections.itemAt(i);
982 if (! connection->outboundQueue.isEmpty()) {
983 DispatchEntry* dispatchEntry = connection->outboundQueue.tail.prev;
984 if (dispatchEntry->targetFlags & InputTarget::FLAG_SYNC) {
985 if (dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION) {
986 goto NoBatchingOrStreaming;
987 }
988
989 MotionEntry* syncedMotionEntry = static_cast<MotionEntry*>(
990 dispatchEntry->eventEntry);
991 if (syncedMotionEntry->action != MOTION_EVENT_ACTION_MOVE
992 || syncedMotionEntry->deviceId != deviceId
993 || syncedMotionEntry->pointerCount != pointerCount) {
994 goto NoBatchingOrStreaming;
995 }
996
997 // Found synced move entry. Append sample and resume dispatch.
998 mAllocator.appendMotionSample(syncedMotionEntry, eventTime,
999 pointerCount, pointerCoords);
1000#if DEBUG_BATCHING
1001 LOGD("Appended motion sample onto batch for most recent synchronously "
1002 "dispatched motion event for this device in the outbound queues.");
1003#endif
1004 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1005 dispatchEventToCurrentInputTargetsLocked(currentTime, syncedMotionEntry,
1006 true /*resumeWithAppendedMotionSample*/);
1007 return; // done!
1008 }
1009 }
1010 }
1011
1012NoBatchingOrStreaming:;
1013 }
1014
1015 // Just enqueue a new motion event.
1016 MotionEntry* newEntry = mAllocator.obtainMotionEntry();
1017 newEntry->eventTime = eventTime;
1018 newEntry->deviceId = deviceId;
1019 newEntry->nature = nature;
1020 newEntry->policyFlags = policyFlags;
1021 newEntry->action = action;
1022 newEntry->metaState = metaState;
1023 newEntry->edgeFlags = edgeFlags;
1024 newEntry->xPrecision = xPrecision;
1025 newEntry->yPrecision = yPrecision;
1026 newEntry->downTime = downTime;
1027 newEntry->pointerCount = pointerCount;
1028 newEntry->firstSample.eventTime = eventTime;
1029 newEntry->lastSample = & newEntry->firstSample;
1030 for (uint32_t i = 0; i < pointerCount; i++) {
1031 newEntry->pointerIds[i] = pointerIds[i];
1032 newEntry->firstSample.pointerCoords[i] = pointerCoords[i];
1033 }
1034
1035 wasEmpty = mInboundQueue.isEmpty();
1036 mInboundQueue.enqueueAtTail(newEntry);
1037 } // release lock
1038
1039 if (wasEmpty) {
1040 mPollLoop->wake();
1041 }
1042}
1043
1044void InputDispatcher::resetKeyRepeatLocked() {
1045 if (mKeyRepeatState.lastKeyEntry) {
1046 mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
1047 mKeyRepeatState.lastKeyEntry = NULL;
1048 }
1049}
1050
1051status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
1052 int receiveFd;
1053 { // acquire lock
1054 AutoMutex _l(mLock);
1055
1056 receiveFd = inputChannel->getReceivePipeFd();
1057 if (mConnectionsByReceiveFd.indexOfKey(receiveFd) >= 0) {
1058 LOGW("Attempted to register already registered input channel '%s'",
1059 inputChannel->getName().string());
1060 return BAD_VALUE;
1061 }
1062
1063 sp<Connection> connection = new Connection(inputChannel);
1064 status_t status = connection->initialize();
1065 if (status) {
1066 LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
1067 inputChannel->getName().string(), status);
1068 return status;
1069 }
1070
1071 mConnectionsByReceiveFd.add(receiveFd, connection);
1072 } // release lock
1073
1074 mPollLoop->setCallback(receiveFd, POLLIN, handleReceiveCallback, this);
1075 return OK;
1076}
1077
1078status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
1079 int32_t receiveFd;
1080 { // acquire lock
1081 AutoMutex _l(mLock);
1082
1083 receiveFd = inputChannel->getReceivePipeFd();
1084 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(receiveFd);
1085 if (connectionIndex < 0) {
1086 LOGW("Attempted to unregister already unregistered input channel '%s'",
1087 inputChannel->getName().string());
1088 return BAD_VALUE;
1089 }
1090
1091 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1092 mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
1093
1094 connection->status = Connection::STATUS_ZOMBIE;
1095
1096 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1097 abortDispatchCycleLocked(currentTime, connection.get(), true /*broken*/);
1098 } // release lock
1099
1100 mPollLoop->removeCallback(receiveFd);
1101
1102 // Wake the poll loop because removing the connection may have changed the current
1103 // synchronization state.
1104 mPollLoop->wake();
1105 return OK;
1106}
1107
1108void InputDispatcher::activateConnectionLocked(Connection* connection) {
1109 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1110 if (mActiveConnections.itemAt(i) == connection) {
1111 return;
1112 }
1113 }
1114 mActiveConnections.add(connection);
1115}
1116
1117void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
1118 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1119 if (mActiveConnections.itemAt(i) == connection) {
1120 mActiveConnections.removeAt(i);
1121 return;
1122 }
1123 }
1124}
1125
1126void InputDispatcher::onDispatchCycleStartedLocked(nsecs_t currentTime, Connection* connection) {
1127}
1128
1129void InputDispatcher::onDispatchCycleFinishedLocked(nsecs_t currentTime,
1130 Connection* connection, bool recoveredFromANR) {
1131 if (recoveredFromANR) {
1132 LOGI("channel '%s' ~ Recovered from ANR. %01.1fms since event, "
1133 "%01.1fms since dispatch, %01.1fms since ANR",
1134 connection->getInputChannelName(),
1135 connection->getEventLatencyMillis(currentTime),
1136 connection->getDispatchLatencyMillis(currentTime),
1137 connection->getANRLatencyMillis(currentTime));
1138
1139 // TODO tell framework
1140 }
1141}
1142
1143void InputDispatcher::onDispatchCycleANRLocked(nsecs_t currentTime, Connection* connection) {
1144 LOGI("channel '%s' ~ Not responding! %01.1fms since event, %01.1fms since dispatch",
1145 connection->getInputChannelName(),
1146 connection->getEventLatencyMillis(currentTime),
1147 connection->getDispatchLatencyMillis(currentTime));
1148
1149 // TODO tell framework
1150}
1151
1152void InputDispatcher::onDispatchCycleBrokenLocked(nsecs_t currentTime, Connection* connection) {
1153 LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
1154 connection->getInputChannelName());
1155
1156 // TODO tell framework
1157}
1158
1159// --- InputDispatcher::Allocator ---
1160
1161InputDispatcher::Allocator::Allocator() {
1162}
1163
1164InputDispatcher::ConfigurationChangedEntry*
1165InputDispatcher::Allocator::obtainConfigurationChangedEntry() {
1166 ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
1167 entry->refCount = 1;
1168 entry->type = EventEntry::TYPE_CONFIGURATION_CHANGED;
1169 return entry;
1170}
1171
1172InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry() {
1173 KeyEntry* entry = mKeyEntryPool.alloc();
1174 entry->refCount = 1;
1175 entry->type = EventEntry::TYPE_KEY;
1176 return entry;
1177}
1178
1179InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry() {
1180 MotionEntry* entry = mMotionEntryPool.alloc();
1181 entry->refCount = 1;
1182 entry->type = EventEntry::TYPE_MOTION;
1183 entry->firstSample.next = NULL;
1184 return entry;
1185}
1186
1187InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
1188 EventEntry* eventEntry) {
1189 DispatchEntry* entry = mDispatchEntryPool.alloc();
1190 entry->eventEntry = eventEntry;
1191 eventEntry->refCount += 1;
1192 return entry;
1193}
1194
1195void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
1196 switch (entry->type) {
1197 case EventEntry::TYPE_CONFIGURATION_CHANGED:
1198 releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
1199 break;
1200 case EventEntry::TYPE_KEY:
1201 releaseKeyEntry(static_cast<KeyEntry*>(entry));
1202 break;
1203 case EventEntry::TYPE_MOTION:
1204 releaseMotionEntry(static_cast<MotionEntry*>(entry));
1205 break;
1206 default:
1207 assert(false);
1208 break;
1209 }
1210}
1211
1212void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
1213 ConfigurationChangedEntry* entry) {
1214 entry->refCount -= 1;
1215 if (entry->refCount == 0) {
1216 mConfigurationChangeEntryPool.free(entry);
1217 } else {
1218 assert(entry->refCount > 0);
1219 }
1220}
1221
1222void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
1223 entry->refCount -= 1;
1224 if (entry->refCount == 0) {
1225 mKeyEntryPool.free(entry);
1226 } else {
1227 assert(entry->refCount > 0);
1228 }
1229}
1230
1231void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
1232 entry->refCount -= 1;
1233 if (entry->refCount == 0) {
1234 freeMotionSampleList(entry->firstSample.next);
1235 mMotionEntryPool.free(entry);
1236 } else {
1237 assert(entry->refCount > 0);
1238 }
1239}
1240
1241void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
1242 releaseEventEntry(entry->eventEntry);
1243 mDispatchEntryPool.free(entry);
1244}
1245
1246void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
1247 nsecs_t eventTime, int32_t pointerCount, const PointerCoords* pointerCoords) {
1248 MotionSample* sample = mMotionSamplePool.alloc();
1249 sample->eventTime = eventTime;
1250 for (int32_t i = 0; i < pointerCount; i++) {
1251 sample->pointerCoords[i] = pointerCoords[i];
1252 }
1253
1254 sample->next = NULL;
1255 motionEntry->lastSample->next = sample;
1256 motionEntry->lastSample = sample;
1257}
1258
1259void InputDispatcher::Allocator::freeMotionSample(MotionSample* sample) {
1260 mMotionSamplePool.free(sample);
1261}
1262
1263void InputDispatcher::Allocator::freeMotionSampleList(MotionSample* head) {
1264 while (head) {
1265 MotionSample* next = head->next;
1266 mMotionSamplePool.free(head);
1267 head = next;
1268 }
1269}
1270
1271// --- InputDispatcher::Connection ---
1272
1273InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
1274 status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
1275 nextTimeoutTime(LONG_LONG_MAX),
1276 lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX),
1277 lastANRTime(LONG_LONG_MAX) {
1278}
1279
1280InputDispatcher::Connection::~Connection() {
1281}
1282
1283status_t InputDispatcher::Connection::initialize() {
1284 return inputPublisher.initialize();
1285}
1286
1287InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
1288 const EventEntry* eventEntry) const {
1289 for (DispatchEntry* dispatchEntry = outboundQueue.tail.prev;
1290 dispatchEntry != & outboundQueue.head; dispatchEntry = dispatchEntry->prev) {
1291 if (dispatchEntry->eventEntry == eventEntry) {
1292 return dispatchEntry;
1293 }
1294 }
1295 return NULL;
1296}
1297
1298
1299// --- InputDispatcherThread ---
1300
1301InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
1302 Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
1303}
1304
1305InputDispatcherThread::~InputDispatcherThread() {
1306}
1307
1308bool InputDispatcherThread::threadLoop() {
1309 mDispatcher->dispatchOnce();
1310 return true;
1311}
1312
1313} // namespace android