blob: b3103a47c80400091a941dd875be62dc20ccceb5 [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
Jeff Brown9c3cda02010-06-15 01:31:58 -070022// Log debug messages about registrations.
23#define DEBUG_REGISTRATION 1
24
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070025// Log debug messages about performance statistics.
26#define DEBUG_PERFORMANCE_STATISTICS 1
27
Jeff Brown7fbdc842010-06-17 20:52:56 -070028// Log debug messages about input event injection.
29#define DEBUG_INJECTION 1
30
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070031#include <cutils/log.h>
32#include <ui/InputDispatcher.h>
33
34#include <stddef.h>
35#include <unistd.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070036#include <errno.h>
37#include <limits.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070038
39namespace android {
40
41// TODO, this needs to be somewhere else, perhaps in the policy
42static inline bool isMovementKey(int32_t keyCode) {
43 return keyCode == KEYCODE_DPAD_UP
44 || keyCode == KEYCODE_DPAD_DOWN
45 || keyCode == KEYCODE_DPAD_LEFT
46 || keyCode == KEYCODE_DPAD_RIGHT;
47}
48
Jeff Brown7fbdc842010-06-17 20:52:56 -070049static inline nsecs_t now() {
50 return systemTime(SYSTEM_TIME_MONOTONIC);
51}
52
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070053// --- InputDispatcher ---
54
Jeff Brown9c3cda02010-06-15 01:31:58 -070055InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070056 mPolicy(policy) {
57 mPollLoop = new PollLoop();
58
59 mInboundQueue.head.refCount = -1;
60 mInboundQueue.head.type = EventEntry::TYPE_SENTINEL;
61 mInboundQueue.head.eventTime = LONG_LONG_MIN;
62
63 mInboundQueue.tail.refCount = -1;
64 mInboundQueue.tail.type = EventEntry::TYPE_SENTINEL;
65 mInboundQueue.tail.eventTime = LONG_LONG_MAX;
66
67 mKeyRepeatState.lastKeyEntry = NULL;
Jeff Brown9c3cda02010-06-15 01:31:58 -070068
69 mCurrentInputTargetsValid = false;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070070}
71
72InputDispatcher::~InputDispatcher() {
73 resetKeyRepeatLocked();
74
75 while (mConnectionsByReceiveFd.size() != 0) {
76 unregisterInputChannel(mConnectionsByReceiveFd.valueAt(0)->inputChannel);
77 }
78
79 for (EventEntry* entry = mInboundQueue.head.next; entry != & mInboundQueue.tail; ) {
80 EventEntry* next = entry->next;
81 mAllocator.releaseEventEntry(next);
82 entry = next;
83 }
84}
85
86void InputDispatcher::dispatchOnce() {
Jeff Brown9c3cda02010-06-15 01:31:58 -070087 nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070088
Jeff Brown9c3cda02010-06-15 01:31:58 -070089 bool skipPoll = false;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070090 nsecs_t currentTime;
91 nsecs_t nextWakeupTime = LONG_LONG_MAX;
92 { // acquire lock
93 AutoMutex _l(mLock);
Jeff Brown7fbdc842010-06-17 20:52:56 -070094 currentTime = now();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070095
96 // Reset the key repeat timer whenever we disallow key events, even if the next event
97 // is not a key. This is to ensure that we abort a key repeat if the device is just coming
98 // out of sleep.
99 // XXX we should handle resetting input state coming out of sleep more generally elsewhere
Jeff Brown9c3cda02010-06-15 01:31:58 -0700100 if (keyRepeatTimeout < 0) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700101 resetKeyRepeatLocked();
102 }
103
Jeff Brown7fbdc842010-06-17 20:52:56 -0700104 // Detect and process timeouts for all connections and determine if there are any
105 // synchronous event dispatches pending. This step is entirely non-interruptible.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700106 bool hasPendingSyncTarget = false;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700107 size_t activeConnectionCount = mActiveConnections.size();
108 for (size_t i = 0; i < activeConnectionCount; i++) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700109 Connection* connection = mActiveConnections.itemAt(i);
110
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700111 if (connection->hasPendingSyncTarget()) {
112 hasPendingSyncTarget = true;
113 }
114
Jeff Brown7fbdc842010-06-17 20:52:56 -0700115 nsecs_t connectionTimeoutTime = connection->nextTimeoutTime;
116 if (connectionTimeoutTime <= currentTime) {
117 mTimedOutConnections.add(connection);
118 } else if (connectionTimeoutTime < nextWakeupTime) {
119 nextWakeupTime = connectionTimeoutTime;
120 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700121 }
122
Jeff Brown7fbdc842010-06-17 20:52:56 -0700123 size_t timedOutConnectionCount = mTimedOutConnections.size();
124 for (size_t i = 0; i < timedOutConnectionCount; i++) {
125 Connection* connection = mTimedOutConnections.itemAt(i);
126 timeoutDispatchCycleLocked(currentTime, connection);
127 skipPoll = true;
128 }
129 mTimedOutConnections.clear();
130
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700131 // If we don't have a pending sync target, then we can begin delivering a new event.
132 // (Otherwise we wait for dispatch to complete for that target.)
133 if (! hasPendingSyncTarget) {
134 if (mInboundQueue.isEmpty()) {
135 if (mKeyRepeatState.lastKeyEntry) {
136 if (currentTime >= mKeyRepeatState.nextRepeatTime) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700137 processKeyRepeatLockedInterruptible(currentTime, keyRepeatTimeout);
138 skipPoll = true;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700139 } else {
140 if (mKeyRepeatState.nextRepeatTime < nextWakeupTime) {
141 nextWakeupTime = mKeyRepeatState.nextRepeatTime;
142 }
143 }
144 }
145 } else {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700146 // Inbound queue has at least one entry.
147 // Start processing it but leave it on the queue until later so that the
148 // input reader can keep appending samples onto a motion event between the
149 // time we started processing it and the time we finally enqueue dispatch
150 // entries for it.
151 EventEntry* entry = mInboundQueue.head.next;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700152
153 switch (entry->type) {
154 case EventEntry::TYPE_CONFIGURATION_CHANGED: {
155 ConfigurationChangedEntry* typedEntry =
156 static_cast<ConfigurationChangedEntry*>(entry);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700157 processConfigurationChangedLockedInterruptible(currentTime, typedEntry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700158 break;
159 }
160
161 case EventEntry::TYPE_KEY: {
162 KeyEntry* typedEntry = static_cast<KeyEntry*>(entry);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700163 processKeyLockedInterruptible(currentTime, typedEntry, keyRepeatTimeout);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700164 break;
165 }
166
167 case EventEntry::TYPE_MOTION: {
168 MotionEntry* typedEntry = static_cast<MotionEntry*>(entry);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700169 processMotionLockedInterruptible(currentTime, typedEntry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700170 break;
171 }
172
173 default:
174 assert(false);
175 break;
176 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700177
178 // Dequeue and release the event entry that we just processed.
179 mInboundQueue.dequeue(entry);
180 mAllocator.releaseEventEntry(entry);
181 skipPoll = true;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700182 }
183 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700184
185 // Run any deferred commands.
186 skipPoll |= runCommandsLockedInterruptible();
Jeff Brown7fbdc842010-06-17 20:52:56 -0700187
188 // Wake up synchronization waiters, if needed.
189 if (isFullySynchronizedLocked()) {
190 mFullySynchronizedCondition.broadcast();
191 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700192 } // release lock
193
Jeff Brown9c3cda02010-06-15 01:31:58 -0700194 // If we dispatched anything, don't poll just now. Wait for the next iteration.
195 // Contents may have shifted during flight.
196 if (skipPoll) {
197 return;
198 }
199
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700200 // Wait for callback or timeout or wake.
201 nsecs_t timeout = nanoseconds_to_milliseconds(nextWakeupTime - currentTime);
202 int32_t timeoutMillis = timeout > INT_MAX ? -1 : timeout > 0 ? int32_t(timeout) : 0;
203 mPollLoop->pollOnce(timeoutMillis);
204}
205
Jeff Brown9c3cda02010-06-15 01:31:58 -0700206bool InputDispatcher::runCommandsLockedInterruptible() {
207 if (mCommandQueue.isEmpty()) {
208 return false;
209 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700210
Jeff Brown9c3cda02010-06-15 01:31:58 -0700211 do {
212 CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
213
214 Command command = commandEntry->command;
215 (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
216
Jeff Brown7fbdc842010-06-17 20:52:56 -0700217 commandEntry->connection.clear();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700218 mAllocator.releaseCommandEntry(commandEntry);
219 } while (! mCommandQueue.isEmpty());
220 return true;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700221}
222
Jeff Brown9c3cda02010-06-15 01:31:58 -0700223InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
224 CommandEntry* commandEntry = mAllocator.obtainCommandEntry(command);
225 mCommandQueue.enqueueAtTail(commandEntry);
226 return commandEntry;
227}
228
229void InputDispatcher::processConfigurationChangedLockedInterruptible(
230 nsecs_t currentTime, ConfigurationChangedEntry* entry) {
231#if DEBUG_OUTBOUND_EVENT_DETAILS
232 LOGD("processConfigurationChanged - eventTime=%lld", entry->eventTime);
233#endif
234
235 mLock.unlock();
236
237 mPolicy->notifyConfigurationChanged(entry->eventTime);
238
239 mLock.lock();
240}
241
242void InputDispatcher::processKeyLockedInterruptible(
243 nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700244#if DEBUG_OUTBOUND_EVENT_DETAILS
245 LOGD("processKey - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, action=0x%x, "
246 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
247 entry->eventTime, entry->deviceId, entry->nature, entry->policyFlags, entry->action,
248 entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
249 entry->downTime);
250#endif
251
252 // TODO: Poke user activity.
253
254 if (entry->action == KEY_EVENT_ACTION_DOWN) {
255 if (mKeyRepeatState.lastKeyEntry
256 && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
257 // We have seen two identical key downs in a row which indicates that the device
258 // driver is automatically generating key repeats itself. We take note of the
259 // repeat here, but we disable our own next key repeat timer since it is clear that
260 // we will not need to synthesize key repeats ourselves.
261 entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
262 resetKeyRepeatLocked();
263 mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
264 } else {
265 // Not a repeat. Save key down state in case we do see a repeat later.
266 resetKeyRepeatLocked();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700267 mKeyRepeatState.nextRepeatTime = entry->eventTime + keyRepeatTimeout;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700268 }
269 mKeyRepeatState.lastKeyEntry = entry;
270 entry->refCount += 1;
271 } else {
272 resetKeyRepeatLocked();
273 }
274
Jeff Brown9c3cda02010-06-15 01:31:58 -0700275 identifyInputTargetsAndDispatchKeyLockedInterruptible(currentTime, entry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700276}
277
Jeff Brown9c3cda02010-06-15 01:31:58 -0700278void InputDispatcher::processKeyRepeatLockedInterruptible(
279 nsecs_t currentTime, nsecs_t keyRepeatTimeout) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700280 // TODO Old WindowManagerServer code sniffs the input queue for following key up
281 // events and drops the repeat if one is found. We should do something similar.
282 // One good place to do it is in notifyKey as soon as the key up enters the
283 // inbound event queue.
284
285 // Synthesize a key repeat after the repeat timeout expired.
286 // We reuse the previous key entry if otherwise unreferenced.
287 KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700288 uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700289 if (entry->refCount == 1) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700290 entry->eventTime = currentTime;
291 entry->downTime = currentTime;
292 entry->policyFlags = policyFlags;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700293 entry->repeatCount += 1;
294 } else {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700295 KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
296 entry->deviceId, entry->nature, policyFlags,
297 entry->action, entry->flags, entry->keyCode, entry->scanCode,
298 entry->metaState, entry->repeatCount + 1, currentTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700299
300 mKeyRepeatState.lastKeyEntry = newEntry;
301 mAllocator.releaseKeyEntry(entry);
302
303 entry = newEntry;
304 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700305
Jeff Brown9c3cda02010-06-15 01:31:58 -0700306 mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatTimeout;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700307
308#if DEBUG_OUTBOUND_EVENT_DETAILS
309 LOGD("processKeyRepeat - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, "
310 "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
311 "repeatCount=%d, downTime=%lld",
312 entry->eventTime, entry->deviceId, entry->nature, entry->policyFlags,
313 entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
314 entry->repeatCount, entry->downTime);
315#endif
316
Jeff Brown9c3cda02010-06-15 01:31:58 -0700317 identifyInputTargetsAndDispatchKeyLockedInterruptible(currentTime, entry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700318}
319
Jeff Brown9c3cda02010-06-15 01:31:58 -0700320void InputDispatcher::processMotionLockedInterruptible(
321 nsecs_t currentTime, MotionEntry* entry) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700322#if DEBUG_OUTBOUND_EVENT_DETAILS
323 LOGD("processMotion - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, action=0x%x, "
324 "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
325 entry->eventTime, entry->deviceId, entry->nature, entry->policyFlags, entry->action,
326 entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
327 entry->downTime);
328
329 // Print the most recent sample that we have available, this may change due to batching.
330 size_t sampleCount = 1;
331 MotionSample* sample = & entry->firstSample;
332 for (; sample->next != NULL; sample = sample->next) {
333 sampleCount += 1;
334 }
335 for (uint32_t i = 0; i < entry->pointerCount; i++) {
336 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
337 i, entry->pointerIds[i],
338 sample->pointerCoords[i].x,
339 sample->pointerCoords[i].y,
340 sample->pointerCoords[i].pressure,
341 sample->pointerCoords[i].size);
342 }
343
344 // Keep in mind that due to batching, it is possible for the number of samples actually
345 // dispatched to change before the application finally consumed them.
346 if (entry->action == MOTION_EVENT_ACTION_MOVE) {
347 LOGD(" ... Total movement samples currently batched %d ...", sampleCount);
348 }
349#endif
350
Jeff Brown9c3cda02010-06-15 01:31:58 -0700351 identifyInputTargetsAndDispatchMotionLockedInterruptible(currentTime, entry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700352}
353
Jeff Brown9c3cda02010-06-15 01:31:58 -0700354void InputDispatcher::identifyInputTargetsAndDispatchKeyLockedInterruptible(
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700355 nsecs_t currentTime, KeyEntry* entry) {
356#if DEBUG_DISPATCH_CYCLE
357 LOGD("identifyInputTargetsAndDispatchKey");
358#endif
359
Jeff Brown9c3cda02010-06-15 01:31:58 -0700360 entry->dispatchInProgress = true;
361 mCurrentInputTargetsValid = false;
362 mLock.unlock();
363
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700364 mReusableKeyEvent.initialize(entry->deviceId, entry->nature, entry->action, entry->flags,
365 entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
366 entry->downTime, entry->eventTime);
367
368 mCurrentInputTargets.clear();
Jeff Brown7fbdc842010-06-17 20:52:56 -0700369 int32_t injectionResult = mPolicy->getKeyEventTargets(& mReusableKeyEvent,
370 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700371 mCurrentInputTargets);
372
Jeff Brown9c3cda02010-06-15 01:31:58 -0700373 mLock.lock();
374 mCurrentInputTargetsValid = true;
375
Jeff Brown7fbdc842010-06-17 20:52:56 -0700376 setInjectionResultLocked(entry, injectionResult);
377
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700378 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
379}
380
Jeff Brown9c3cda02010-06-15 01:31:58 -0700381void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700382 nsecs_t currentTime, MotionEntry* entry) {
383#if DEBUG_DISPATCH_CYCLE
384 LOGD("identifyInputTargetsAndDispatchMotion");
385#endif
386
Jeff Brown9c3cda02010-06-15 01:31:58 -0700387 entry->dispatchInProgress = true;
388 mCurrentInputTargetsValid = false;
389 mLock.unlock();
390
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700391 mReusableMotionEvent.initialize(entry->deviceId, entry->nature, entry->action,
392 entry->edgeFlags, entry->metaState,
Jeff Brown5c225b12010-06-16 01:53:36 -0700393 0, 0, entry->xPrecision, entry->yPrecision,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700394 entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds,
395 entry->firstSample.pointerCoords);
396
397 mCurrentInputTargets.clear();
Jeff Brown7fbdc842010-06-17 20:52:56 -0700398 int32_t injectionResult = mPolicy->getMotionEventTargets(& mReusableMotionEvent,
399 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700400 mCurrentInputTargets);
401
Jeff Brown9c3cda02010-06-15 01:31:58 -0700402 mLock.lock();
403 mCurrentInputTargetsValid = true;
404
Jeff Brown7fbdc842010-06-17 20:52:56 -0700405 setInjectionResultLocked(entry, injectionResult);
406
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700407 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
408}
409
410void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
411 EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
412#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700413 LOGD("dispatchEventToCurrentInputTargets - "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700414 "resumeWithAppendedMotionSample=%s",
415 resumeWithAppendedMotionSample ? "true" : "false");
416#endif
417
Jeff Brown9c3cda02010-06-15 01:31:58 -0700418 assert(eventEntry->dispatchInProgress); // should already have been set to true
419
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700420 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
421 const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
422
423 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(
424 inputTarget.inputChannel->getReceivePipeFd());
425 if (connectionIndex >= 0) {
426 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700427 prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700428 resumeWithAppendedMotionSample);
429 } else {
430 LOGW("Framework requested delivery of an input event to channel '%s' but it "
431 "is not registered with the input dispatcher.",
432 inputTarget.inputChannel->getName().string());
433 }
434 }
435}
436
Jeff Brown7fbdc842010-06-17 20:52:56 -0700437void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
438 const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700439 bool resumeWithAppendedMotionSample) {
440#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700441 LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, timeout=%lldns, "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700442 "xOffset=%f, yOffset=%f, resumeWithAppendedMotionSample=%s",
443 connection->getInputChannelName(), inputTarget->flags, inputTarget->timeout,
444 inputTarget->xOffset, inputTarget->yOffset,
445 resumeWithAppendedMotionSample ? "true" : "false");
446#endif
447
448 // Skip this event if the connection status is not normal.
449 // We don't want to queue outbound events at all if the connection is broken or
450 // not responding.
451 if (connection->status != Connection::STATUS_NORMAL) {
452 LOGV("channel '%s' ~ Dropping event because the channel status is %s",
Jeff Brown9c3cda02010-06-15 01:31:58 -0700453 connection->getStatusLabel());
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700454 return;
455 }
456
457 // Resume the dispatch cycle with a freshly appended motion sample.
458 // First we check that the last dispatch entry in the outbound queue is for the same
459 // motion event to which we appended the motion sample. If we find such a dispatch
460 // entry, and if it is currently in progress then we try to stream the new sample.
461 bool wasEmpty = connection->outboundQueue.isEmpty();
462
463 if (! wasEmpty && resumeWithAppendedMotionSample) {
464 DispatchEntry* motionEventDispatchEntry =
465 connection->findQueuedDispatchEntryForEvent(eventEntry);
466 if (motionEventDispatchEntry) {
467 // If the dispatch entry is not in progress, then we must be busy dispatching an
468 // earlier event. Not a problem, the motion event is on the outbound queue and will
469 // be dispatched later.
470 if (! motionEventDispatchEntry->inProgress) {
471#if DEBUG_BATCHING
472 LOGD("channel '%s' ~ Not streaming because the motion event has "
473 "not yet been dispatched. "
474 "(Waiting for earlier events to be consumed.)",
475 connection->getInputChannelName());
476#endif
477 return;
478 }
479
480 // If the dispatch entry is in progress but it already has a tail of pending
481 // motion samples, then it must mean that the shared memory buffer filled up.
482 // Not a problem, when this dispatch cycle is finished, we will eventually start
483 // a new dispatch cycle to process the tail and that tail includes the newly
484 // appended motion sample.
485 if (motionEventDispatchEntry->tailMotionSample) {
486#if DEBUG_BATCHING
487 LOGD("channel '%s' ~ Not streaming because no new samples can "
488 "be appended to the motion event in this dispatch cycle. "
489 "(Waiting for next dispatch cycle to start.)",
490 connection->getInputChannelName());
491#endif
492 return;
493 }
494
495 // The dispatch entry is in progress and is still potentially open for streaming.
496 // Try to stream the new motion sample. This might fail if the consumer has already
497 // consumed the motion event (or if the channel is broken).
498 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
499 status_t status = connection->inputPublisher.appendMotionSample(
500 appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
501 if (status == OK) {
502#if DEBUG_BATCHING
503 LOGD("channel '%s' ~ Successfully streamed new motion sample.",
504 connection->getInputChannelName());
505#endif
506 return;
507 }
508
509#if DEBUG_BATCHING
510 if (status == NO_MEMORY) {
511 LOGD("channel '%s' ~ Could not append motion sample to currently "
512 "dispatched move event because the shared memory buffer is full. "
513 "(Waiting for next dispatch cycle to start.)",
514 connection->getInputChannelName());
515 } else if (status == status_t(FAILED_TRANSACTION)) {
516 LOGD("channel '%s' ~ Could not append motion sample to currently "
517 "dispatchedmove event because the event has already been consumed. "
518 "(Waiting for next dispatch cycle to start.)",
519 connection->getInputChannelName());
520 } else {
521 LOGD("channel '%s' ~ Could not append motion sample to currently "
522 "dispatched move event due to an error, status=%d. "
523 "(Waiting for next dispatch cycle to start.)",
524 connection->getInputChannelName(), status);
525 }
526#endif
527 // Failed to stream. Start a new tail of pending motion samples to dispatch
528 // in the next cycle.
529 motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
530 return;
531 }
532 }
533
534 // This is a new event.
535 // Enqueue a new dispatch entry onto the outbound queue for this connection.
536 DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry); // increments ref
537 dispatchEntry->targetFlags = inputTarget->flags;
538 dispatchEntry->xOffset = inputTarget->xOffset;
539 dispatchEntry->yOffset = inputTarget->yOffset;
540 dispatchEntry->timeout = inputTarget->timeout;
541 dispatchEntry->inProgress = false;
542 dispatchEntry->headMotionSample = NULL;
543 dispatchEntry->tailMotionSample = NULL;
544
545 // Handle the case where we could not stream a new motion sample because the consumer has
546 // already consumed the motion event (otherwise the corresponding dispatch entry would
547 // still be in the outbound queue for this connection). We set the head motion sample
548 // to the list starting with the newly appended motion sample.
549 if (resumeWithAppendedMotionSample) {
550#if DEBUG_BATCHING
551 LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
552 "that cannot be streamed because the motion event has already been consumed.",
553 connection->getInputChannelName());
554#endif
555 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
556 dispatchEntry->headMotionSample = appendedMotionSample;
557 }
558
559 // Enqueue the dispatch entry.
560 connection->outboundQueue.enqueueAtTail(dispatchEntry);
561
562 // If the outbound queue was previously empty, start the dispatch cycle going.
563 if (wasEmpty) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700564 activateConnectionLocked(connection.get());
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700565 startDispatchCycleLocked(currentTime, connection);
566 }
567}
568
Jeff Brown7fbdc842010-06-17 20:52:56 -0700569void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
570 const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700571#if DEBUG_DISPATCH_CYCLE
572 LOGD("channel '%s' ~ startDispatchCycle",
573 connection->getInputChannelName());
574#endif
575
576 assert(connection->status == Connection::STATUS_NORMAL);
577 assert(! connection->outboundQueue.isEmpty());
578
579 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
580 assert(! dispatchEntry->inProgress);
581
582 // TODO throttle successive ACTION_MOVE motion events for the same device
583 // possible implementation could set a brief poll timeout here and resume starting the
584 // dispatch cycle when elapsed
585
586 // Publish the event.
587 status_t status;
588 switch (dispatchEntry->eventEntry->type) {
589 case EventEntry::TYPE_KEY: {
590 KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
591
592 // Apply target flags.
593 int32_t action = keyEntry->action;
594 int32_t flags = keyEntry->flags;
595 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
596 flags |= KEY_EVENT_FLAG_CANCELED;
597 }
598
599 // Publish the key event.
600 status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->nature,
601 action, flags, keyEntry->keyCode, keyEntry->scanCode,
602 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
603 keyEntry->eventTime);
604
605 if (status) {
606 LOGE("channel '%s' ~ Could not publish key event, "
607 "status=%d", connection->getInputChannelName(), status);
608 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
609 return;
610 }
611 break;
612 }
613
614 case EventEntry::TYPE_MOTION: {
615 MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
616
617 // Apply target flags.
618 int32_t action = motionEntry->action;
619 if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
620 action = MOTION_EVENT_ACTION_OUTSIDE;
621 }
622 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
623 action = MOTION_EVENT_ACTION_CANCEL;
624 }
625
626 // If headMotionSample is non-NULL, then it points to the first new sample that we
627 // were unable to dispatch during the previous cycle so we resume dispatching from
628 // that point in the list of motion samples.
629 // Otherwise, we just start from the first sample of the motion event.
630 MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
631 if (! firstMotionSample) {
632 firstMotionSample = & motionEntry->firstSample;
633 }
634
635 // Publish the motion event and the first motion sample.
636 status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
637 motionEntry->nature, action, motionEntry->edgeFlags, motionEntry->metaState,
638 dispatchEntry->xOffset, dispatchEntry->yOffset,
639 motionEntry->xPrecision, motionEntry->yPrecision,
640 motionEntry->downTime, firstMotionSample->eventTime,
641 motionEntry->pointerCount, motionEntry->pointerIds,
642 firstMotionSample->pointerCoords);
643
644 if (status) {
645 LOGE("channel '%s' ~ Could not publish motion event, "
646 "status=%d", connection->getInputChannelName(), status);
647 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
648 return;
649 }
650
651 // Append additional motion samples.
652 MotionSample* nextMotionSample = firstMotionSample->next;
653 for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
654 status = connection->inputPublisher.appendMotionSample(
655 nextMotionSample->eventTime, nextMotionSample->pointerCoords);
656 if (status == NO_MEMORY) {
657#if DEBUG_DISPATCH_CYCLE
658 LOGD("channel '%s' ~ Shared memory buffer full. Some motion samples will "
659 "be sent in the next dispatch cycle.",
660 connection->getInputChannelName());
661#endif
662 break;
663 }
664 if (status != OK) {
665 LOGE("channel '%s' ~ Could not append motion sample "
666 "for a reason other than out of memory, status=%d",
667 connection->getInputChannelName(), status);
668 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
669 return;
670 }
671 }
672
673 // Remember the next motion sample that we could not dispatch, in case we ran out
674 // of space in the shared memory buffer.
675 dispatchEntry->tailMotionSample = nextMotionSample;
676 break;
677 }
678
679 default: {
680 assert(false);
681 }
682 }
683
684 // Send the dispatch signal.
685 status = connection->inputPublisher.sendDispatchSignal();
686 if (status) {
687 LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
688 connection->getInputChannelName(), status);
689 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
690 return;
691 }
692
693 // Record information about the newly started dispatch cycle.
694 dispatchEntry->inProgress = true;
695
696 connection->lastEventTime = dispatchEntry->eventEntry->eventTime;
697 connection->lastDispatchTime = currentTime;
698
699 nsecs_t timeout = dispatchEntry->timeout;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700700 connection->setNextTimeoutTime(currentTime, timeout);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700701
702 // Notify other system components.
703 onDispatchCycleStartedLocked(currentTime, connection);
704}
705
Jeff Brown7fbdc842010-06-17 20:52:56 -0700706void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
707 const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700708#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700709 LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700710 "%01.1fms since dispatch",
711 connection->getInputChannelName(),
712 connection->getEventLatencyMillis(currentTime),
713 connection->getDispatchLatencyMillis(currentTime));
714#endif
715
Jeff Brown9c3cda02010-06-15 01:31:58 -0700716 if (connection->status == Connection::STATUS_BROKEN
717 || connection->status == Connection::STATUS_ZOMBIE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700718 return;
719 }
720
721 // Clear the pending timeout.
722 connection->nextTimeoutTime = LONG_LONG_MAX;
723
724 if (connection->status == Connection::STATUS_NOT_RESPONDING) {
725 // Recovering from an ANR.
726 connection->status = Connection::STATUS_NORMAL;
727
728 // Notify other system components.
729 onDispatchCycleFinishedLocked(currentTime, connection, true /*recoveredFromANR*/);
730 } else {
731 // Normal finish. Not much to do here.
732
733 // Notify other system components.
734 onDispatchCycleFinishedLocked(currentTime, connection, false /*recoveredFromANR*/);
735 }
736
737 // Reset the publisher since the event has been consumed.
738 // We do this now so that the publisher can release some of its internal resources
739 // while waiting for the next dispatch cycle to begin.
740 status_t status = connection->inputPublisher.reset();
741 if (status) {
742 LOGE("channel '%s' ~ Could not reset publisher, status=%d",
743 connection->getInputChannelName(), status);
744 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
745 return;
746 }
747
748 // Start the next dispatch cycle for this connection.
749 while (! connection->outboundQueue.isEmpty()) {
750 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
751 if (dispatchEntry->inProgress) {
752 // Finish or resume current event in progress.
753 if (dispatchEntry->tailMotionSample) {
754 // We have a tail of undispatched motion samples.
755 // Reuse the same DispatchEntry and start a new cycle.
756 dispatchEntry->inProgress = false;
757 dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
758 dispatchEntry->tailMotionSample = NULL;
759 startDispatchCycleLocked(currentTime, connection);
760 return;
761 }
762 // Finished.
763 connection->outboundQueue.dequeueAtHead();
764 mAllocator.releaseDispatchEntry(dispatchEntry);
765 } else {
766 // If the head is not in progress, then we must have already dequeued the in
767 // progress event, which means we actually aborted it (due to ANR).
768 // So just start the next event for this connection.
769 startDispatchCycleLocked(currentTime, connection);
770 return;
771 }
772 }
773
774 // Outbound queue is empty, deactivate the connection.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700775 deactivateConnectionLocked(connection.get());
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700776}
777
Jeff Brown7fbdc842010-06-17 20:52:56 -0700778void InputDispatcher::timeoutDispatchCycleLocked(nsecs_t currentTime,
779 const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700780#if DEBUG_DISPATCH_CYCLE
781 LOGD("channel '%s' ~ timeoutDispatchCycle",
782 connection->getInputChannelName());
783#endif
784
785 if (connection->status != Connection::STATUS_NORMAL) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700786 return;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700787 }
788
789 // Enter the not responding state.
790 connection->status = Connection::STATUS_NOT_RESPONDING;
791 connection->lastANRTime = currentTime;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700792
793 // Notify other system components.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700794 // This enqueues a command which will eventually either call
795 // resumeAfterTimeoutDispatchCycleLocked or abortDispatchCycleLocked.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700796 onDispatchCycleANRLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700797}
798
Jeff Brown7fbdc842010-06-17 20:52:56 -0700799void InputDispatcher::resumeAfterTimeoutDispatchCycleLocked(nsecs_t currentTime,
800 const sp<Connection>& connection, nsecs_t newTimeout) {
801#if DEBUG_DISPATCH_CYCLE
802 LOGD("channel '%s' ~ resumeAfterTimeoutDispatchCycleLocked",
803 connection->getInputChannelName());
804#endif
805
806 if (connection->status != Connection::STATUS_NOT_RESPONDING) {
807 return;
808 }
809
810 // Resume normal dispatch.
811 connection->status = Connection::STATUS_NORMAL;
812 connection->setNextTimeoutTime(currentTime, newTimeout);
813}
814
815void InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime,
816 const sp<Connection>& connection, bool broken) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700817#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700818 LOGD("channel '%s' ~ abortDispatchCycle - broken=%s",
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700819 connection->getInputChannelName(), broken ? "true" : "false");
820#endif
821
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700822 // Clear the pending timeout.
823 connection->nextTimeoutTime = LONG_LONG_MAX;
824
825 // Clear the outbound queue.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700826 if (! connection->outboundQueue.isEmpty()) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700827 do {
828 DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
829 mAllocator.releaseDispatchEntry(dispatchEntry);
830 } while (! connection->outboundQueue.isEmpty());
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700831
Jeff Brown7fbdc842010-06-17 20:52:56 -0700832 deactivateConnectionLocked(connection.get());
Jeff Brown9c3cda02010-06-15 01:31:58 -0700833 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700834
835 // Handle the case where the connection appears to be unrecoverably broken.
Jeff Brown9c3cda02010-06-15 01:31:58 -0700836 // Ignore already broken or zombie connections.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700837 if (broken) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700838 if (connection->status == Connection::STATUS_NORMAL
839 || connection->status == Connection::STATUS_NOT_RESPONDING) {
840 connection->status = Connection::STATUS_BROKEN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700841
Jeff Brown9c3cda02010-06-15 01:31:58 -0700842 // Notify other system components.
843 onDispatchCycleBrokenLocked(currentTime, connection);
844 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700845 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700846}
847
848bool InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
849 InputDispatcher* d = static_cast<InputDispatcher*>(data);
850
851 { // acquire lock
852 AutoMutex _l(d->mLock);
853
854 ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
855 if (connectionIndex < 0) {
856 LOGE("Received spurious receive callback for unknown input channel. "
857 "fd=%d, events=0x%x", receiveFd, events);
858 return false; // remove the callback
859 }
860
Jeff Brown7fbdc842010-06-17 20:52:56 -0700861 nsecs_t currentTime = now();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700862
863 sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
864 if (events & (POLLERR | POLLHUP | POLLNVAL)) {
865 LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
866 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700867 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700868 d->runCommandsLockedInterruptible();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700869 return false; // remove the callback
870 }
871
872 if (! (events & POLLIN)) {
873 LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
874 "events=0x%x", connection->getInputChannelName(), events);
875 return true;
876 }
877
878 status_t status = connection->inputPublisher.receiveFinishedSignal();
879 if (status) {
880 LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
881 connection->getInputChannelName(), status);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700882 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700883 d->runCommandsLockedInterruptible();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700884 return false; // remove the callback
885 }
886
Jeff Brown7fbdc842010-06-17 20:52:56 -0700887 d->finishDispatchCycleLocked(currentTime, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700888 d->runCommandsLockedInterruptible();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700889 return true;
890 } // release lock
891}
892
Jeff Brown9c3cda02010-06-15 01:31:58 -0700893void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700894#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown9c3cda02010-06-15 01:31:58 -0700895 LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700896#endif
897
898 bool wasEmpty;
899 { // acquire lock
900 AutoMutex _l(mLock);
901
Jeff Brown7fbdc842010-06-17 20:52:56 -0700902 ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700903
904 wasEmpty = mInboundQueue.isEmpty();
905 mInboundQueue.enqueueAtTail(newEntry);
906 } // release lock
907
908 if (wasEmpty) {
909 mPollLoop->wake();
910 }
911}
912
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700913void InputDispatcher::notifyAppSwitchComing(nsecs_t eventTime) {
914#if DEBUG_INBOUND_EVENT_DETAILS
915 LOGD("notifyAppSwitchComing - eventTime=%lld", eventTime);
916#endif
917
918 // Remove movement keys from the queue from most recent to least recent, stopping at the
919 // first non-movement key.
920 // TODO: Include a detailed description of why we do this...
921
922 { // acquire lock
923 AutoMutex _l(mLock);
924
925 for (EventEntry* entry = mInboundQueue.tail.prev; entry != & mInboundQueue.head; ) {
926 EventEntry* prev = entry->prev;
927
928 if (entry->type == EventEntry::TYPE_KEY) {
929 KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
930 if (isMovementKey(keyEntry->keyCode)) {
931 LOGV("Dropping movement key during app switch: keyCode=%d, action=%d",
932 keyEntry->keyCode, keyEntry->action);
933 mInboundQueue.dequeue(keyEntry);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700934
935 setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
936
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700937 mAllocator.releaseKeyEntry(keyEntry);
938 } else {
939 // stop at last non-movement key
940 break;
941 }
942 }
943
944 entry = prev;
945 }
946 } // release lock
947}
948
949void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
950 uint32_t policyFlags, int32_t action, int32_t flags,
951 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
952#if DEBUG_INBOUND_EVENT_DETAILS
953 LOGD("notifyKey - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, action=0x%x, "
954 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
955 eventTime, deviceId, nature, policyFlags, action, flags,
956 keyCode, scanCode, metaState, downTime);
957#endif
958
959 bool wasEmpty;
960 { // acquire lock
961 AutoMutex _l(mLock);
962
Jeff Brown7fbdc842010-06-17 20:52:56 -0700963 int32_t repeatCount = 0;
964 KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
965 deviceId, nature, policyFlags, action, flags, keyCode, scanCode,
966 metaState, repeatCount, downTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700967
968 wasEmpty = mInboundQueue.isEmpty();
969 mInboundQueue.enqueueAtTail(newEntry);
970 } // release lock
971
972 if (wasEmpty) {
973 mPollLoop->wake();
974 }
975}
976
977void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t nature,
978 uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
979 uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
980 float xPrecision, float yPrecision, nsecs_t downTime) {
981#if DEBUG_INBOUND_EVENT_DETAILS
982 LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, "
983 "action=0x%x, metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, "
984 "downTime=%lld",
985 eventTime, deviceId, nature, policyFlags, action, metaState, edgeFlags,
986 xPrecision, yPrecision, downTime);
987 for (uint32_t i = 0; i < pointerCount; i++) {
988 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
989 i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
990 pointerCoords[i].pressure, pointerCoords[i].size);
991 }
992#endif
993
994 bool wasEmpty;
995 { // acquire lock
996 AutoMutex _l(mLock);
997
998 // Attempt batching and streaming of move events.
999 if (action == MOTION_EVENT_ACTION_MOVE) {
1000 // BATCHING CASE
1001 //
1002 // Try to append a move sample to the tail of the inbound queue for this device.
1003 // Give up if we encounter a non-move motion event for this device since that
1004 // means we cannot append any new samples until a new motion event has started.
1005 for (EventEntry* entry = mInboundQueue.tail.prev;
1006 entry != & mInboundQueue.head; entry = entry->prev) {
1007 if (entry->type != EventEntry::TYPE_MOTION) {
1008 // Keep looking for motion events.
1009 continue;
1010 }
1011
1012 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
1013 if (motionEntry->deviceId != deviceId) {
1014 // Keep looking for this device.
1015 continue;
1016 }
1017
1018 if (motionEntry->action != MOTION_EVENT_ACTION_MOVE
Jeff Brown7fbdc842010-06-17 20:52:56 -07001019 || motionEntry->pointerCount != pointerCount
1020 || motionEntry->isInjected()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001021 // Last motion event in the queue for this device is not compatible for
1022 // appending new samples. Stop here.
1023 goto NoBatchingOrStreaming;
1024 }
1025
1026 // The last motion event is a move and is compatible for appending.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001027 // Do the batching magic.
Jeff Brown7fbdc842010-06-17 20:52:56 -07001028 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001029#if DEBUG_BATCHING
1030 LOGD("Appended motion sample onto batch for most recent "
1031 "motion event for this device in the inbound queue.");
1032#endif
Jeff Brown9c3cda02010-06-15 01:31:58 -07001033
1034 // Sanity check for special case because dispatch is interruptible.
1035 // The dispatch logic is partially interruptible and releases its lock while
1036 // identifying targets. However, as soon as the targets have been identified,
1037 // the dispatcher proceeds to write a dispatch entry into all relevant outbound
1038 // queues and then promptly removes the motion entry from the queue.
1039 //
1040 // Consequently, we should never observe the case where the inbound queue contains
1041 // an in-progress motion entry unless the current input targets are invalid
1042 // (currently being computed). Check for this!
1043 assert(! (motionEntry->dispatchInProgress && mCurrentInputTargetsValid));
1044
1045 return; // done!
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001046 }
1047
1048 // STREAMING CASE
1049 //
1050 // There is no pending motion event (of any kind) for this device in the inbound queue.
1051 // Search the outbound queues for a synchronously dispatched motion event for this
1052 // device. If found, then we append the new sample to that event and then try to
1053 // push it out to all current targets. It is possible that some targets will already
1054 // have consumed the motion event. This case is automatically handled by the
1055 // logic in prepareDispatchCycleLocked by tracking where resumption takes place.
1056 //
1057 // The reason we look for a synchronously dispatched motion event is because we
1058 // want to be sure that no other motion events have been dispatched since the move.
1059 // It's also convenient because it means that the input targets are still valid.
1060 // This code could be improved to support streaming of asynchronously dispatched
1061 // motion events (which might be significantly more efficient) but it may become
1062 // a little more complicated as a result.
1063 //
1064 // Note: This code crucially depends on the invariant that an outbound queue always
1065 // contains at most one synchronous event and it is always last (but it might
1066 // not be first!).
Jeff Brown9c3cda02010-06-15 01:31:58 -07001067 if (mCurrentInputTargetsValid) {
1068 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1069 Connection* connection = mActiveConnections.itemAt(i);
1070 if (! connection->outboundQueue.isEmpty()) {
1071 DispatchEntry* dispatchEntry = connection->outboundQueue.tail.prev;
1072 if (dispatchEntry->targetFlags & InputTarget::FLAG_SYNC) {
1073 if (dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION) {
1074 goto NoBatchingOrStreaming;
1075 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001076
Jeff Brown9c3cda02010-06-15 01:31:58 -07001077 MotionEntry* syncedMotionEntry = static_cast<MotionEntry*>(
1078 dispatchEntry->eventEntry);
1079 if (syncedMotionEntry->action != MOTION_EVENT_ACTION_MOVE
1080 || syncedMotionEntry->deviceId != deviceId
Jeff Brown7fbdc842010-06-17 20:52:56 -07001081 || syncedMotionEntry->pointerCount != pointerCount
1082 || syncedMotionEntry->isInjected()) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001083 goto NoBatchingOrStreaming;
1084 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001085
Jeff Brown9c3cda02010-06-15 01:31:58 -07001086 // Found synced move entry. Append sample and resume dispatch.
1087 mAllocator.appendMotionSample(syncedMotionEntry, eventTime,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001088 pointerCoords);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001089 #if DEBUG_BATCHING
1090 LOGD("Appended motion sample onto batch for most recent synchronously "
1091 "dispatched motion event for this device in the outbound queues.");
1092 #endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001093 nsecs_t currentTime = now();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001094 dispatchEventToCurrentInputTargetsLocked(currentTime, syncedMotionEntry,
1095 true /*resumeWithAppendedMotionSample*/);
1096
1097 runCommandsLockedInterruptible();
1098 return; // done!
1099 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001100 }
1101 }
1102 }
1103
1104NoBatchingOrStreaming:;
1105 }
1106
1107 // Just enqueue a new motion event.
Jeff Brown7fbdc842010-06-17 20:52:56 -07001108 MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
1109 deviceId, nature, policyFlags, action, metaState, edgeFlags,
1110 xPrecision, yPrecision, downTime,
1111 pointerCount, pointerIds, pointerCoords);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001112
1113 wasEmpty = mInboundQueue.isEmpty();
1114 mInboundQueue.enqueueAtTail(newEntry);
1115 } // release lock
1116
1117 if (wasEmpty) {
1118 mPollLoop->wake();
1119 }
1120}
1121
Jeff Brown7fbdc842010-06-17 20:52:56 -07001122int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
1123 int32_t injectorPid, int32_t injectorUid, bool sync, int32_t timeoutMillis) {
1124#if DEBUG_INBOUND_EVENT_DETAILS
1125 LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
1126 "sync=%d, timeoutMillis=%d",
1127 event->getType(), injectorPid, injectorUid, sync, timeoutMillis);
1128#endif
1129
1130 nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
1131
1132 EventEntry* injectedEntry;
1133 bool wasEmpty;
1134 { // acquire lock
1135 AutoMutex _l(mLock);
1136
1137 injectedEntry = createEntryFromInputEventLocked(event);
1138 injectedEntry->refCount += 1;
1139 injectedEntry->injectorPid = injectorPid;
1140 injectedEntry->injectorUid = injectorUid;
1141
1142 wasEmpty = mInboundQueue.isEmpty();
1143 mInboundQueue.enqueueAtTail(injectedEntry);
1144
1145 } // release lock
1146
1147 if (wasEmpty) {
1148 mPollLoop->wake();
1149 }
1150
1151 int32_t injectionResult;
1152 { // acquire lock
1153 AutoMutex _l(mLock);
1154
1155 for (;;) {
1156 injectionResult = injectedEntry->injectionResult;
1157 if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
1158 break;
1159 }
1160
1161 nsecs_t remainingTimeout = endTime - now();
1162 if (remainingTimeout <= 0) {
1163 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1164 sync = false;
1165 break;
1166 }
1167
1168 mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
1169 }
1170
1171 if (sync) {
1172 while (! isFullySynchronizedLocked()) {
1173 nsecs_t remainingTimeout = endTime - now();
1174 if (remainingTimeout <= 0) {
1175 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1176 break;
1177 }
1178
1179 mFullySynchronizedCondition.waitRelative(mLock, remainingTimeout);
1180 }
1181 }
1182
1183 mAllocator.releaseEventEntry(injectedEntry);
1184 } // release lock
1185
1186 return injectionResult;
1187}
1188
1189void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
1190 if (entry->isInjected()) {
1191#if DEBUG_INJECTION
1192 LOGD("Setting input event injection result to %d. "
1193 "injectorPid=%d, injectorUid=%d",
1194 injectionResult, entry->injectorPid, entry->injectorUid);
1195#endif
1196
1197 entry->injectionResult = injectionResult;
1198 mInjectionResultAvailableCondition.broadcast();
1199 }
1200}
1201
1202bool InputDispatcher::isFullySynchronizedLocked() {
1203 return mInboundQueue.isEmpty() && mActiveConnections.isEmpty();
1204}
1205
1206InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked(
1207 const InputEvent* event) {
1208 switch (event->getType()) {
1209 case INPUT_EVENT_TYPE_KEY: {
1210 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
1211 uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
1212
1213 KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
1214 keyEvent->getDeviceId(), keyEvent->getNature(), policyFlags,
1215 keyEvent->getAction(), keyEvent->getFlags(),
1216 keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
1217 keyEvent->getRepeatCount(), keyEvent->getDownTime());
1218 return keyEntry;
1219 }
1220
1221 case INPUT_EVENT_TYPE_MOTION: {
1222 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
1223 uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
1224
1225 const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
1226 const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
1227 size_t pointerCount = motionEvent->getPointerCount();
1228
1229 MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
1230 motionEvent->getDeviceId(), motionEvent->getNature(), policyFlags,
1231 motionEvent->getAction(), motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
1232 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
1233 motionEvent->getDownTime(), uint32_t(pointerCount),
1234 motionEvent->getPointerIds(), samplePointerCoords);
1235 for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
1236 sampleEventTimes += 1;
1237 samplePointerCoords += pointerCount;
1238 mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
1239 }
1240 return motionEntry;
1241 }
1242
1243 default:
1244 assert(false);
1245 return NULL;
1246 }
1247}
1248
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001249void InputDispatcher::resetKeyRepeatLocked() {
1250 if (mKeyRepeatState.lastKeyEntry) {
1251 mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
1252 mKeyRepeatState.lastKeyEntry = NULL;
1253 }
1254}
1255
1256status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001257#if DEBUG_REGISTRATION
1258 LOGD("channel '%s' - Registered", inputChannel->getName().string());
1259#endif
1260
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001261 int receiveFd;
1262 { // acquire lock
1263 AutoMutex _l(mLock);
1264
1265 receiveFd = inputChannel->getReceivePipeFd();
1266 if (mConnectionsByReceiveFd.indexOfKey(receiveFd) >= 0) {
1267 LOGW("Attempted to register already registered input channel '%s'",
1268 inputChannel->getName().string());
1269 return BAD_VALUE;
1270 }
1271
1272 sp<Connection> connection = new Connection(inputChannel);
1273 status_t status = connection->initialize();
1274 if (status) {
1275 LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
1276 inputChannel->getName().string(), status);
1277 return status;
1278 }
1279
1280 mConnectionsByReceiveFd.add(receiveFd, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001281
1282 runCommandsLockedInterruptible();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001283 } // release lock
1284
1285 mPollLoop->setCallback(receiveFd, POLLIN, handleReceiveCallback, this);
1286 return OK;
1287}
1288
1289status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001290#if DEBUG_REGISTRATION
1291 LOGD("channel '%s' - Unregistered", inputChannel->getName().string());
1292#endif
1293
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001294 int32_t receiveFd;
1295 { // acquire lock
1296 AutoMutex _l(mLock);
1297
1298 receiveFd = inputChannel->getReceivePipeFd();
1299 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(receiveFd);
1300 if (connectionIndex < 0) {
1301 LOGW("Attempted to unregister already unregistered input channel '%s'",
1302 inputChannel->getName().string());
1303 return BAD_VALUE;
1304 }
1305
1306 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1307 mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
1308
1309 connection->status = Connection::STATUS_ZOMBIE;
1310
Jeff Brown7fbdc842010-06-17 20:52:56 -07001311 nsecs_t currentTime = now();
1312 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001313
1314 runCommandsLockedInterruptible();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001315 } // release lock
1316
1317 mPollLoop->removeCallback(receiveFd);
1318
1319 // Wake the poll loop because removing the connection may have changed the current
1320 // synchronization state.
1321 mPollLoop->wake();
1322 return OK;
1323}
1324
1325void InputDispatcher::activateConnectionLocked(Connection* connection) {
1326 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1327 if (mActiveConnections.itemAt(i) == connection) {
1328 return;
1329 }
1330 }
1331 mActiveConnections.add(connection);
1332}
1333
1334void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
1335 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1336 if (mActiveConnections.itemAt(i) == connection) {
1337 mActiveConnections.removeAt(i);
1338 return;
1339 }
1340 }
1341}
1342
Jeff Brown9c3cda02010-06-15 01:31:58 -07001343void InputDispatcher::onDispatchCycleStartedLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07001344 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001345}
1346
Jeff Brown9c3cda02010-06-15 01:31:58 -07001347void InputDispatcher::onDispatchCycleFinishedLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07001348 nsecs_t currentTime, const sp<Connection>& connection, bool recoveredFromANR) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001349 if (recoveredFromANR) {
1350 LOGI("channel '%s' ~ Recovered from ANR. %01.1fms since event, "
1351 "%01.1fms since dispatch, %01.1fms since ANR",
1352 connection->getInputChannelName(),
1353 connection->getEventLatencyMillis(currentTime),
1354 connection->getDispatchLatencyMillis(currentTime),
1355 connection->getANRLatencyMillis(currentTime));
1356
Jeff Brown9c3cda02010-06-15 01:31:58 -07001357 CommandEntry* commandEntry = postCommandLocked(
1358 & InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001359 commandEntry->connection = connection;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001360 }
1361}
1362
Jeff Brown9c3cda02010-06-15 01:31:58 -07001363void InputDispatcher::onDispatchCycleANRLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07001364 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001365 LOGI("channel '%s' ~ Not responding! %01.1fms since event, %01.1fms since dispatch",
1366 connection->getInputChannelName(),
1367 connection->getEventLatencyMillis(currentTime),
1368 connection->getDispatchLatencyMillis(currentTime));
1369
Jeff Brown9c3cda02010-06-15 01:31:58 -07001370 CommandEntry* commandEntry = postCommandLocked(
1371 & InputDispatcher::doNotifyInputChannelANRLockedInterruptible);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001372 commandEntry->connection = connection;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001373}
1374
Jeff Brown9c3cda02010-06-15 01:31:58 -07001375void InputDispatcher::onDispatchCycleBrokenLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07001376 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001377 LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
1378 connection->getInputChannelName());
1379
Jeff Brown9c3cda02010-06-15 01:31:58 -07001380 CommandEntry* commandEntry = postCommandLocked(
1381 & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001382 commandEntry->connection = connection;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001383}
1384
Jeff Brown9c3cda02010-06-15 01:31:58 -07001385void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
1386 CommandEntry* commandEntry) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001387 sp<Connection> connection = commandEntry->connection;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001388
Jeff Brown7fbdc842010-06-17 20:52:56 -07001389 if (connection->status != Connection::STATUS_ZOMBIE) {
1390 mLock.unlock();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001391
Jeff Brown7fbdc842010-06-17 20:52:56 -07001392 mPolicy->notifyInputChannelBroken(connection->inputChannel);
1393
1394 mLock.lock();
1395 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001396}
1397
1398void InputDispatcher::doNotifyInputChannelANRLockedInterruptible(
1399 CommandEntry* commandEntry) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001400 sp<Connection> connection = commandEntry->connection;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001401
Jeff Brown7fbdc842010-06-17 20:52:56 -07001402 if (connection->status != Connection::STATUS_ZOMBIE) {
1403 mLock.unlock();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001404
Jeff Brown7fbdc842010-06-17 20:52:56 -07001405 nsecs_t newTimeout;
1406 bool resume = mPolicy->notifyInputChannelANR(connection->inputChannel, newTimeout);
1407
1408 mLock.lock();
1409
1410 nsecs_t currentTime = now();
1411 if (resume) {
1412 resumeAfterTimeoutDispatchCycleLocked(currentTime, connection, newTimeout);
1413 } else {
1414 abortDispatchCycleLocked(currentTime, connection, false /*(not) broken*/);
1415 }
1416 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001417}
1418
1419void InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible(
1420 CommandEntry* commandEntry) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001421 sp<Connection> connection = commandEntry->connection;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001422
Jeff Brown7fbdc842010-06-17 20:52:56 -07001423 if (connection->status != Connection::STATUS_ZOMBIE) {
1424 mLock.unlock();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001425
Jeff Brown7fbdc842010-06-17 20:52:56 -07001426 mPolicy->notifyInputChannelRecoveredFromANR(connection->inputChannel);
1427
1428 mLock.lock();
1429 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001430}
1431
1432
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001433// --- InputDispatcher::Allocator ---
1434
1435InputDispatcher::Allocator::Allocator() {
1436}
1437
Jeff Brown7fbdc842010-06-17 20:52:56 -07001438void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
1439 nsecs_t eventTime) {
1440 entry->type = type;
1441 entry->refCount = 1;
1442 entry->dispatchInProgress = false;
Christopher Tatee91a5db2010-06-23 16:50:30 -07001443 entry->eventTime = eventTime;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001444 entry->injectionResult = INPUT_EVENT_INJECTION_PENDING;
1445 entry->injectorPid = -1;
1446 entry->injectorUid = -1;
1447}
1448
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001449InputDispatcher::ConfigurationChangedEntry*
Jeff Brown7fbdc842010-06-17 20:52:56 -07001450InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001451 ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
Jeff Brown7fbdc842010-06-17 20:52:56 -07001452 initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001453 return entry;
1454}
1455
Jeff Brown7fbdc842010-06-17 20:52:56 -07001456InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
1457 int32_t deviceId, int32_t nature, uint32_t policyFlags, int32_t action,
1458 int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
1459 int32_t repeatCount, nsecs_t downTime) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001460 KeyEntry* entry = mKeyEntryPool.alloc();
Jeff Brown7fbdc842010-06-17 20:52:56 -07001461 initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime);
1462
1463 entry->deviceId = deviceId;
1464 entry->nature = nature;
1465 entry->policyFlags = policyFlags;
1466 entry->action = action;
1467 entry->flags = flags;
1468 entry->keyCode = keyCode;
1469 entry->scanCode = scanCode;
1470 entry->metaState = metaState;
1471 entry->repeatCount = repeatCount;
1472 entry->downTime = downTime;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001473 return entry;
1474}
1475
Jeff Brown7fbdc842010-06-17 20:52:56 -07001476InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
1477 int32_t deviceId, int32_t nature, uint32_t policyFlags, int32_t action,
1478 int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
1479 nsecs_t downTime, uint32_t pointerCount,
1480 const int32_t* pointerIds, const PointerCoords* pointerCoords) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001481 MotionEntry* entry = mMotionEntryPool.alloc();
Jeff Brown7fbdc842010-06-17 20:52:56 -07001482 initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime);
1483
1484 entry->eventTime = eventTime;
1485 entry->deviceId = deviceId;
1486 entry->nature = nature;
1487 entry->policyFlags = policyFlags;
1488 entry->action = action;
1489 entry->metaState = metaState;
1490 entry->edgeFlags = edgeFlags;
1491 entry->xPrecision = xPrecision;
1492 entry->yPrecision = yPrecision;
1493 entry->downTime = downTime;
1494 entry->pointerCount = pointerCount;
1495 entry->firstSample.eventTime = eventTime;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001496 entry->firstSample.next = NULL;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001497 entry->lastSample = & entry->firstSample;
1498 for (uint32_t i = 0; i < pointerCount; i++) {
1499 entry->pointerIds[i] = pointerIds[i];
1500 entry->firstSample.pointerCoords[i] = pointerCoords[i];
1501 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001502 return entry;
1503}
1504
1505InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
1506 EventEntry* eventEntry) {
1507 DispatchEntry* entry = mDispatchEntryPool.alloc();
1508 entry->eventEntry = eventEntry;
1509 eventEntry->refCount += 1;
1510 return entry;
1511}
1512
Jeff Brown9c3cda02010-06-15 01:31:58 -07001513InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
1514 CommandEntry* entry = mCommandEntryPool.alloc();
1515 entry->command = command;
1516 return entry;
1517}
1518
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001519void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
1520 switch (entry->type) {
1521 case EventEntry::TYPE_CONFIGURATION_CHANGED:
1522 releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
1523 break;
1524 case EventEntry::TYPE_KEY:
1525 releaseKeyEntry(static_cast<KeyEntry*>(entry));
1526 break;
1527 case EventEntry::TYPE_MOTION:
1528 releaseMotionEntry(static_cast<MotionEntry*>(entry));
1529 break;
1530 default:
1531 assert(false);
1532 break;
1533 }
1534}
1535
1536void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
1537 ConfigurationChangedEntry* entry) {
1538 entry->refCount -= 1;
1539 if (entry->refCount == 0) {
1540 mConfigurationChangeEntryPool.free(entry);
1541 } else {
1542 assert(entry->refCount > 0);
1543 }
1544}
1545
1546void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
1547 entry->refCount -= 1;
1548 if (entry->refCount == 0) {
1549 mKeyEntryPool.free(entry);
1550 } else {
1551 assert(entry->refCount > 0);
1552 }
1553}
1554
1555void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
1556 entry->refCount -= 1;
1557 if (entry->refCount == 0) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001558 for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
1559 MotionSample* next = sample->next;
1560 mMotionSamplePool.free(sample);
1561 sample = next;
1562 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001563 mMotionEntryPool.free(entry);
1564 } else {
1565 assert(entry->refCount > 0);
1566 }
1567}
1568
1569void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
1570 releaseEventEntry(entry->eventEntry);
1571 mDispatchEntryPool.free(entry);
1572}
1573
Jeff Brown9c3cda02010-06-15 01:31:58 -07001574void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
1575 mCommandEntryPool.free(entry);
1576}
1577
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001578void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001579 nsecs_t eventTime, const PointerCoords* pointerCoords) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001580 MotionSample* sample = mMotionSamplePool.alloc();
1581 sample->eventTime = eventTime;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001582 uint32_t pointerCount = motionEntry->pointerCount;
1583 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001584 sample->pointerCoords[i] = pointerCoords[i];
1585 }
1586
1587 sample->next = NULL;
1588 motionEntry->lastSample->next = sample;
1589 motionEntry->lastSample = sample;
1590}
1591
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001592// --- InputDispatcher::Connection ---
1593
1594InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
1595 status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
1596 nextTimeoutTime(LONG_LONG_MAX),
1597 lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX),
1598 lastANRTime(LONG_LONG_MAX) {
1599}
1600
1601InputDispatcher::Connection::~Connection() {
1602}
1603
1604status_t InputDispatcher::Connection::initialize() {
1605 return inputPublisher.initialize();
1606}
1607
Jeff Brown7fbdc842010-06-17 20:52:56 -07001608void InputDispatcher::Connection::setNextTimeoutTime(nsecs_t currentTime, nsecs_t timeout) {
1609 nextTimeoutTime = (timeout >= 0) ? currentTime + timeout : LONG_LONG_MAX;
1610}
1611
Jeff Brown9c3cda02010-06-15 01:31:58 -07001612const char* InputDispatcher::Connection::getStatusLabel() const {
1613 switch (status) {
1614 case STATUS_NORMAL:
1615 return "NORMAL";
1616
1617 case STATUS_BROKEN:
1618 return "BROKEN";
1619
1620 case STATUS_NOT_RESPONDING:
1621 return "NOT_RESPONDING";
1622
1623 case STATUS_ZOMBIE:
1624 return "ZOMBIE";
1625
1626 default:
1627 return "UNKNOWN";
1628 }
1629}
1630
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001631InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
1632 const EventEntry* eventEntry) const {
1633 for (DispatchEntry* dispatchEntry = outboundQueue.tail.prev;
1634 dispatchEntry != & outboundQueue.head; dispatchEntry = dispatchEntry->prev) {
1635 if (dispatchEntry->eventEntry == eventEntry) {
1636 return dispatchEntry;
1637 }
1638 }
1639 return NULL;
1640}
1641
Jeff Brown9c3cda02010-06-15 01:31:58 -07001642// --- InputDispatcher::CommandEntry ---
1643
1644InputDispatcher::CommandEntry::CommandEntry() {
1645}
1646
1647InputDispatcher::CommandEntry::~CommandEntry() {
1648}
1649
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001650
1651// --- InputDispatcherThread ---
1652
1653InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
1654 Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
1655}
1656
1657InputDispatcherThread::~InputDispatcherThread() {
1658}
1659
1660bool InputDispatcherThread::threadLoop() {
1661 mDispatcher->dispatchOnce();
1662 return true;
1663}
1664
1665} // namespace android