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