blob: 0fc29b24f78013027d52b2152398e55d3ed827bc [file] [log] [blame]
Jeff Brown46b9ac02010-04-22 18:58:52 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4// The input dispatcher.
5//
6#define LOG_TAG "InputDispatcher"
7
8//#define LOG_NDEBUG 0
9
10// Log detailed debug messages about each inbound event notification to the dispatcher.
Jeff Brown349703e2010-06-22 01:27:15 -070011#define DEBUG_INBOUND_EVENT_DETAILS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070012
13// Log detailed debug messages about each outbound event processed by the dispatcher.
Jeff Brown349703e2010-06-22 01:27:15 -070014#define DEBUG_OUTBOUND_EVENT_DETAILS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070015
16// Log debug messages about batching.
Jeff Brown349703e2010-06-22 01:27:15 -070017#define DEBUG_BATCHING 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070018
19// Log debug messages about the dispatch cycle.
Jeff Brown349703e2010-06-22 01:27:15 -070020#define DEBUG_DISPATCH_CYCLE 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070021
Jeff Brown9c3cda02010-06-15 01:31:58 -070022// Log debug messages about registrations.
Jeff Brown349703e2010-06-22 01:27:15 -070023#define DEBUG_REGISTRATION 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070024
Jeff Brown46b9ac02010-04-22 18:58:52 -070025// Log debug messages about performance statistics.
Jeff Brown349703e2010-06-22 01:27:15 -070026#define DEBUG_PERFORMANCE_STATISTICS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070027
Jeff Brown7fbdc842010-06-17 20:52:56 -070028// Log debug messages about input event injection.
Jeff Brown349703e2010-06-22 01:27:15 -070029#define DEBUG_INJECTION 0
Jeff Brown7fbdc842010-06-17 20:52:56 -070030
Jeff Brown46b9ac02010-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 Brown46b9ac02010-04-22 18:58:52 -070036#include <errno.h>
37#include <limits.h>
Jeff Brown46b9ac02010-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 Brown46b9ac02010-04-22 18:58:52 -070053// --- InputDispatcher ---
54
Jeff Brown9c3cda02010-06-15 01:31:58 -070055InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
Jeff Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-04-22 18:58:52 -070088
Jeff Brown9c3cda02010-06-15 01:31:58 -070089 bool skipPoll = false;
Jeff Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-04-22 18:58:52 -0700109 Connection* connection = mActiveConnections.itemAt(i);
110
Jeff Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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
Jeff Brown349703e2010-06-22 01:27:15 -0700252 if (entry->action == KEY_EVENT_ACTION_DOWN && ! entry->isInjected()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700253 if (mKeyRepeatState.lastKeyEntry
254 && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
255 // We have seen two identical key downs in a row which indicates that the device
256 // driver is automatically generating key repeats itself. We take note of the
257 // repeat here, but we disable our own next key repeat timer since it is clear that
258 // we will not need to synthesize key repeats ourselves.
259 entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
260 resetKeyRepeatLocked();
261 mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
262 } else {
263 // Not a repeat. Save key down state in case we do see a repeat later.
264 resetKeyRepeatLocked();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700265 mKeyRepeatState.nextRepeatTime = entry->eventTime + keyRepeatTimeout;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700266 }
267 mKeyRepeatState.lastKeyEntry = entry;
268 entry->refCount += 1;
269 } else {
270 resetKeyRepeatLocked();
271 }
272
Jeff Brown9c3cda02010-06-15 01:31:58 -0700273 identifyInputTargetsAndDispatchKeyLockedInterruptible(currentTime, entry);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700274}
275
Jeff Brown9c3cda02010-06-15 01:31:58 -0700276void InputDispatcher::processKeyRepeatLockedInterruptible(
277 nsecs_t currentTime, nsecs_t keyRepeatTimeout) {
Jeff Brown349703e2010-06-22 01:27:15 -0700278 KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
279
280 // Search the inbound queue for a key up corresponding to this device.
281 // It doesn't make sense to generate a key repeat event if the key is already up.
282 for (EventEntry* queuedEntry = mInboundQueue.head.next;
283 queuedEntry != & mInboundQueue.tail; queuedEntry = entry->next) {
284 if (queuedEntry->type == EventEntry::TYPE_KEY) {
285 KeyEntry* queuedKeyEntry = static_cast<KeyEntry*>(queuedEntry);
286 if (queuedKeyEntry->deviceId == entry->deviceId
287 && entry->action == KEY_EVENT_ACTION_UP) {
288 resetKeyRepeatLocked();
289 return;
290 }
291 }
292 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700293
294 // Synthesize a key repeat after the repeat timeout expired.
Jeff Brown349703e2010-06-22 01:27:15 -0700295 // Reuse the repeated key entry if it is otherwise unreferenced.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700296 uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700297 if (entry->refCount == 1) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700298 entry->eventTime = currentTime;
299 entry->downTime = currentTime;
300 entry->policyFlags = policyFlags;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700301 entry->repeatCount += 1;
302 } else {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700303 KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
304 entry->deviceId, entry->nature, policyFlags,
305 entry->action, entry->flags, entry->keyCode, entry->scanCode,
306 entry->metaState, entry->repeatCount + 1, currentTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700307
308 mKeyRepeatState.lastKeyEntry = newEntry;
309 mAllocator.releaseKeyEntry(entry);
310
311 entry = newEntry;
312 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700313
Jeff Brown9c3cda02010-06-15 01:31:58 -0700314 mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatTimeout;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700315
316#if DEBUG_OUTBOUND_EVENT_DETAILS
317 LOGD("processKeyRepeat - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, "
318 "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
319 "repeatCount=%d, downTime=%lld",
320 entry->eventTime, entry->deviceId, entry->nature, entry->policyFlags,
321 entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
322 entry->repeatCount, entry->downTime);
323#endif
324
Jeff Brown9c3cda02010-06-15 01:31:58 -0700325 identifyInputTargetsAndDispatchKeyLockedInterruptible(currentTime, entry);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700326}
327
Jeff Brown9c3cda02010-06-15 01:31:58 -0700328void InputDispatcher::processMotionLockedInterruptible(
329 nsecs_t currentTime, MotionEntry* entry) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700330#if DEBUG_OUTBOUND_EVENT_DETAILS
331 LOGD("processMotion - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, action=0x%x, "
332 "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
333 entry->eventTime, entry->deviceId, entry->nature, entry->policyFlags, entry->action,
334 entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
335 entry->downTime);
336
337 // Print the most recent sample that we have available, this may change due to batching.
338 size_t sampleCount = 1;
339 MotionSample* sample = & entry->firstSample;
340 for (; sample->next != NULL; sample = sample->next) {
341 sampleCount += 1;
342 }
343 for (uint32_t i = 0; i < entry->pointerCount; i++) {
344 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
345 i, entry->pointerIds[i],
346 sample->pointerCoords[i].x,
347 sample->pointerCoords[i].y,
348 sample->pointerCoords[i].pressure,
349 sample->pointerCoords[i].size);
350 }
351
352 // Keep in mind that due to batching, it is possible for the number of samples actually
353 // dispatched to change before the application finally consumed them.
354 if (entry->action == MOTION_EVENT_ACTION_MOVE) {
355 LOGD(" ... Total movement samples currently batched %d ...", sampleCount);
356 }
357#endif
358
Jeff Brown9c3cda02010-06-15 01:31:58 -0700359 identifyInputTargetsAndDispatchMotionLockedInterruptible(currentTime, entry);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700360}
361
Jeff Brown9c3cda02010-06-15 01:31:58 -0700362void InputDispatcher::identifyInputTargetsAndDispatchKeyLockedInterruptible(
Jeff Brown46b9ac02010-04-22 18:58:52 -0700363 nsecs_t currentTime, KeyEntry* entry) {
364#if DEBUG_DISPATCH_CYCLE
365 LOGD("identifyInputTargetsAndDispatchKey");
366#endif
367
Jeff Brown9c3cda02010-06-15 01:31:58 -0700368 entry->dispatchInProgress = true;
369 mCurrentInputTargetsValid = false;
370 mLock.unlock();
371
Jeff Brown46b9ac02010-04-22 18:58:52 -0700372 mReusableKeyEvent.initialize(entry->deviceId, entry->nature, entry->action, entry->flags,
373 entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
374 entry->downTime, entry->eventTime);
375
376 mCurrentInputTargets.clear();
Jeff Brown349703e2010-06-22 01:27:15 -0700377 int32_t injectionResult = mPolicy->waitForKeyEventTargets(& mReusableKeyEvent,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700378 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700379 mCurrentInputTargets);
380
Jeff Brown9c3cda02010-06-15 01:31:58 -0700381 mLock.lock();
382 mCurrentInputTargetsValid = true;
383
Jeff Brown7fbdc842010-06-17 20:52:56 -0700384 setInjectionResultLocked(entry, injectionResult);
385
Jeff Brown349703e2010-06-22 01:27:15 -0700386 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
387 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
388 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700389}
390
Jeff Brown9c3cda02010-06-15 01:31:58 -0700391void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(
Jeff Brown46b9ac02010-04-22 18:58:52 -0700392 nsecs_t currentTime, MotionEntry* entry) {
393#if DEBUG_DISPATCH_CYCLE
394 LOGD("identifyInputTargetsAndDispatchMotion");
395#endif
396
Jeff Brown9c3cda02010-06-15 01:31:58 -0700397 entry->dispatchInProgress = true;
398 mCurrentInputTargetsValid = false;
399 mLock.unlock();
400
Jeff Brown46b9ac02010-04-22 18:58:52 -0700401 mReusableMotionEvent.initialize(entry->deviceId, entry->nature, entry->action,
402 entry->edgeFlags, entry->metaState,
Jeff Brown5c225b12010-06-16 01:53:36 -0700403 0, 0, entry->xPrecision, entry->yPrecision,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700404 entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds,
405 entry->firstSample.pointerCoords);
406
407 mCurrentInputTargets.clear();
Jeff Brown349703e2010-06-22 01:27:15 -0700408 int32_t injectionResult = mPolicy->waitForMotionEventTargets(& mReusableMotionEvent,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700409 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700410 mCurrentInputTargets);
411
Jeff Brown9c3cda02010-06-15 01:31:58 -0700412 mLock.lock();
413 mCurrentInputTargetsValid = true;
414
Jeff Brown7fbdc842010-06-17 20:52:56 -0700415 setInjectionResultLocked(entry, injectionResult);
416
Jeff Brown349703e2010-06-22 01:27:15 -0700417 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
418 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
419 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700420}
421
422void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
423 EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
424#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700425 LOGD("dispatchEventToCurrentInputTargets - "
Jeff Brown46b9ac02010-04-22 18:58:52 -0700426 "resumeWithAppendedMotionSample=%s",
427 resumeWithAppendedMotionSample ? "true" : "false");
428#endif
429
Jeff Brown9c3cda02010-06-15 01:31:58 -0700430 assert(eventEntry->dispatchInProgress); // should already have been set to true
431
Jeff Brown46b9ac02010-04-22 18:58:52 -0700432 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
433 const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
434
435 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(
436 inputTarget.inputChannel->getReceivePipeFd());
437 if (connectionIndex >= 0) {
438 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700439 prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700440 resumeWithAppendedMotionSample);
441 } else {
442 LOGW("Framework requested delivery of an input event to channel '%s' but it "
443 "is not registered with the input dispatcher.",
444 inputTarget.inputChannel->getName().string());
445 }
446 }
447}
448
Jeff Brown7fbdc842010-06-17 20:52:56 -0700449void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
450 const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700451 bool resumeWithAppendedMotionSample) {
452#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700453 LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, timeout=%lldns, "
Jeff Brown46b9ac02010-04-22 18:58:52 -0700454 "xOffset=%f, yOffset=%f, resumeWithAppendedMotionSample=%s",
455 connection->getInputChannelName(), inputTarget->flags, inputTarget->timeout,
456 inputTarget->xOffset, inputTarget->yOffset,
457 resumeWithAppendedMotionSample ? "true" : "false");
458#endif
459
460 // Skip this event if the connection status is not normal.
461 // We don't want to queue outbound events at all if the connection is broken or
462 // not responding.
463 if (connection->status != Connection::STATUS_NORMAL) {
464 LOGV("channel '%s' ~ Dropping event because the channel status is %s",
Jeff Brown9c3cda02010-06-15 01:31:58 -0700465 connection->getStatusLabel());
Jeff Brown46b9ac02010-04-22 18:58:52 -0700466 return;
467 }
468
469 // Resume the dispatch cycle with a freshly appended motion sample.
470 // First we check that the last dispatch entry in the outbound queue is for the same
471 // motion event to which we appended the motion sample. If we find such a dispatch
472 // entry, and if it is currently in progress then we try to stream the new sample.
473 bool wasEmpty = connection->outboundQueue.isEmpty();
474
475 if (! wasEmpty && resumeWithAppendedMotionSample) {
476 DispatchEntry* motionEventDispatchEntry =
477 connection->findQueuedDispatchEntryForEvent(eventEntry);
478 if (motionEventDispatchEntry) {
479 // If the dispatch entry is not in progress, then we must be busy dispatching an
480 // earlier event. Not a problem, the motion event is on the outbound queue and will
481 // be dispatched later.
482 if (! motionEventDispatchEntry->inProgress) {
483#if DEBUG_BATCHING
484 LOGD("channel '%s' ~ Not streaming because the motion event has "
485 "not yet been dispatched. "
486 "(Waiting for earlier events to be consumed.)",
487 connection->getInputChannelName());
488#endif
489 return;
490 }
491
492 // If the dispatch entry is in progress but it already has a tail of pending
493 // motion samples, then it must mean that the shared memory buffer filled up.
494 // Not a problem, when this dispatch cycle is finished, we will eventually start
495 // a new dispatch cycle to process the tail and that tail includes the newly
496 // appended motion sample.
497 if (motionEventDispatchEntry->tailMotionSample) {
498#if DEBUG_BATCHING
499 LOGD("channel '%s' ~ Not streaming because no new samples can "
500 "be appended to the motion event in this dispatch cycle. "
501 "(Waiting for next dispatch cycle to start.)",
502 connection->getInputChannelName());
503#endif
504 return;
505 }
506
507 // The dispatch entry is in progress and is still potentially open for streaming.
508 // Try to stream the new motion sample. This might fail if the consumer has already
509 // consumed the motion event (or if the channel is broken).
510 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
511 status_t status = connection->inputPublisher.appendMotionSample(
512 appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
513 if (status == OK) {
514#if DEBUG_BATCHING
515 LOGD("channel '%s' ~ Successfully streamed new motion sample.",
516 connection->getInputChannelName());
517#endif
518 return;
519 }
520
521#if DEBUG_BATCHING
522 if (status == NO_MEMORY) {
523 LOGD("channel '%s' ~ Could not append motion sample to currently "
524 "dispatched move event because the shared memory buffer is full. "
525 "(Waiting for next dispatch cycle to start.)",
526 connection->getInputChannelName());
527 } else if (status == status_t(FAILED_TRANSACTION)) {
528 LOGD("channel '%s' ~ Could not append motion sample to currently "
Jeff Brown349703e2010-06-22 01:27:15 -0700529 "dispatched move event because the event has already been consumed. "
Jeff Brown46b9ac02010-04-22 18:58:52 -0700530 "(Waiting for next dispatch cycle to start.)",
531 connection->getInputChannelName());
532 } else {
533 LOGD("channel '%s' ~ Could not append motion sample to currently "
534 "dispatched move event due to an error, status=%d. "
535 "(Waiting for next dispatch cycle to start.)",
536 connection->getInputChannelName(), status);
537 }
538#endif
539 // Failed to stream. Start a new tail of pending motion samples to dispatch
540 // in the next cycle.
541 motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
542 return;
543 }
544 }
545
546 // This is a new event.
547 // Enqueue a new dispatch entry onto the outbound queue for this connection.
548 DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry); // increments ref
549 dispatchEntry->targetFlags = inputTarget->flags;
550 dispatchEntry->xOffset = inputTarget->xOffset;
551 dispatchEntry->yOffset = inputTarget->yOffset;
552 dispatchEntry->timeout = inputTarget->timeout;
553 dispatchEntry->inProgress = false;
554 dispatchEntry->headMotionSample = NULL;
555 dispatchEntry->tailMotionSample = NULL;
556
557 // Handle the case where we could not stream a new motion sample because the consumer has
558 // already consumed the motion event (otherwise the corresponding dispatch entry would
559 // still be in the outbound queue for this connection). We set the head motion sample
560 // to the list starting with the newly appended motion sample.
561 if (resumeWithAppendedMotionSample) {
562#if DEBUG_BATCHING
563 LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
564 "that cannot be streamed because the motion event has already been consumed.",
565 connection->getInputChannelName());
566#endif
567 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
568 dispatchEntry->headMotionSample = appendedMotionSample;
569 }
570
571 // Enqueue the dispatch entry.
572 connection->outboundQueue.enqueueAtTail(dispatchEntry);
573
574 // If the outbound queue was previously empty, start the dispatch cycle going.
575 if (wasEmpty) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700576 activateConnectionLocked(connection.get());
Jeff Brown46b9ac02010-04-22 18:58:52 -0700577 startDispatchCycleLocked(currentTime, connection);
578 }
579}
580
Jeff Brown7fbdc842010-06-17 20:52:56 -0700581void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
582 const sp<Connection>& connection) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700583#if DEBUG_DISPATCH_CYCLE
584 LOGD("channel '%s' ~ startDispatchCycle",
585 connection->getInputChannelName());
586#endif
587
588 assert(connection->status == Connection::STATUS_NORMAL);
589 assert(! connection->outboundQueue.isEmpty());
590
591 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
592 assert(! dispatchEntry->inProgress);
593
594 // TODO throttle successive ACTION_MOVE motion events for the same device
595 // possible implementation could set a brief poll timeout here and resume starting the
596 // dispatch cycle when elapsed
597
598 // Publish the event.
599 status_t status;
600 switch (dispatchEntry->eventEntry->type) {
601 case EventEntry::TYPE_KEY: {
602 KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
603
604 // Apply target flags.
605 int32_t action = keyEntry->action;
606 int32_t flags = keyEntry->flags;
607 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
608 flags |= KEY_EVENT_FLAG_CANCELED;
609 }
610
611 // Publish the key event.
612 status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->nature,
613 action, flags, keyEntry->keyCode, keyEntry->scanCode,
614 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
615 keyEntry->eventTime);
616
617 if (status) {
618 LOGE("channel '%s' ~ Could not publish key event, "
619 "status=%d", connection->getInputChannelName(), status);
620 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
621 return;
622 }
623 break;
624 }
625
626 case EventEntry::TYPE_MOTION: {
627 MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
628
629 // Apply target flags.
630 int32_t action = motionEntry->action;
631 if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
632 action = MOTION_EVENT_ACTION_OUTSIDE;
633 }
634 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
635 action = MOTION_EVENT_ACTION_CANCEL;
636 }
637
638 // If headMotionSample is non-NULL, then it points to the first new sample that we
639 // were unable to dispatch during the previous cycle so we resume dispatching from
640 // that point in the list of motion samples.
641 // Otherwise, we just start from the first sample of the motion event.
642 MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
643 if (! firstMotionSample) {
644 firstMotionSample = & motionEntry->firstSample;
645 }
646
647 // Publish the motion event and the first motion sample.
648 status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
649 motionEntry->nature, action, motionEntry->edgeFlags, motionEntry->metaState,
650 dispatchEntry->xOffset, dispatchEntry->yOffset,
651 motionEntry->xPrecision, motionEntry->yPrecision,
652 motionEntry->downTime, firstMotionSample->eventTime,
653 motionEntry->pointerCount, motionEntry->pointerIds,
654 firstMotionSample->pointerCoords);
655
656 if (status) {
657 LOGE("channel '%s' ~ Could not publish motion event, "
658 "status=%d", connection->getInputChannelName(), status);
659 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
660 return;
661 }
662
663 // Append additional motion samples.
664 MotionSample* nextMotionSample = firstMotionSample->next;
665 for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
666 status = connection->inputPublisher.appendMotionSample(
667 nextMotionSample->eventTime, nextMotionSample->pointerCoords);
668 if (status == NO_MEMORY) {
669#if DEBUG_DISPATCH_CYCLE
670 LOGD("channel '%s' ~ Shared memory buffer full. Some motion samples will "
671 "be sent in the next dispatch cycle.",
672 connection->getInputChannelName());
673#endif
674 break;
675 }
676 if (status != OK) {
677 LOGE("channel '%s' ~ Could not append motion sample "
678 "for a reason other than out of memory, status=%d",
679 connection->getInputChannelName(), status);
680 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
681 return;
682 }
683 }
684
685 // Remember the next motion sample that we could not dispatch, in case we ran out
686 // of space in the shared memory buffer.
687 dispatchEntry->tailMotionSample = nextMotionSample;
688 break;
689 }
690
691 default: {
692 assert(false);
693 }
694 }
695
696 // Send the dispatch signal.
697 status = connection->inputPublisher.sendDispatchSignal();
698 if (status) {
699 LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
700 connection->getInputChannelName(), status);
701 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
702 return;
703 }
704
705 // Record information about the newly started dispatch cycle.
706 dispatchEntry->inProgress = true;
707
708 connection->lastEventTime = dispatchEntry->eventEntry->eventTime;
709 connection->lastDispatchTime = currentTime;
710
711 nsecs_t timeout = dispatchEntry->timeout;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700712 connection->setNextTimeoutTime(currentTime, timeout);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700713
714 // Notify other system components.
715 onDispatchCycleStartedLocked(currentTime, connection);
716}
717
Jeff Brown7fbdc842010-06-17 20:52:56 -0700718void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
719 const sp<Connection>& connection) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700720#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700721 LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
Jeff Brown46b9ac02010-04-22 18:58:52 -0700722 "%01.1fms since dispatch",
723 connection->getInputChannelName(),
724 connection->getEventLatencyMillis(currentTime),
725 connection->getDispatchLatencyMillis(currentTime));
726#endif
727
Jeff Brown9c3cda02010-06-15 01:31:58 -0700728 if (connection->status == Connection::STATUS_BROKEN
729 || connection->status == Connection::STATUS_ZOMBIE) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700730 return;
731 }
732
733 // Clear the pending timeout.
734 connection->nextTimeoutTime = LONG_LONG_MAX;
735
736 if (connection->status == Connection::STATUS_NOT_RESPONDING) {
737 // Recovering from an ANR.
738 connection->status = Connection::STATUS_NORMAL;
739
740 // Notify other system components.
741 onDispatchCycleFinishedLocked(currentTime, connection, true /*recoveredFromANR*/);
742 } else {
743 // Normal finish. Not much to do here.
744
745 // Notify other system components.
746 onDispatchCycleFinishedLocked(currentTime, connection, false /*recoveredFromANR*/);
747 }
748
749 // Reset the publisher since the event has been consumed.
750 // We do this now so that the publisher can release some of its internal resources
751 // while waiting for the next dispatch cycle to begin.
752 status_t status = connection->inputPublisher.reset();
753 if (status) {
754 LOGE("channel '%s' ~ Could not reset publisher, status=%d",
755 connection->getInputChannelName(), status);
756 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
757 return;
758 }
759
760 // Start the next dispatch cycle for this connection.
761 while (! connection->outboundQueue.isEmpty()) {
762 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
763 if (dispatchEntry->inProgress) {
764 // Finish or resume current event in progress.
765 if (dispatchEntry->tailMotionSample) {
766 // We have a tail of undispatched motion samples.
767 // Reuse the same DispatchEntry and start a new cycle.
768 dispatchEntry->inProgress = false;
769 dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
770 dispatchEntry->tailMotionSample = NULL;
771 startDispatchCycleLocked(currentTime, connection);
772 return;
773 }
774 // Finished.
775 connection->outboundQueue.dequeueAtHead();
776 mAllocator.releaseDispatchEntry(dispatchEntry);
777 } else {
778 // If the head is not in progress, then we must have already dequeued the in
779 // progress event, which means we actually aborted it (due to ANR).
780 // So just start the next event for this connection.
781 startDispatchCycleLocked(currentTime, connection);
782 return;
783 }
784 }
785
786 // Outbound queue is empty, deactivate the connection.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700787 deactivateConnectionLocked(connection.get());
Jeff Brown46b9ac02010-04-22 18:58:52 -0700788}
789
Jeff Brown7fbdc842010-06-17 20:52:56 -0700790void InputDispatcher::timeoutDispatchCycleLocked(nsecs_t currentTime,
791 const sp<Connection>& connection) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700792#if DEBUG_DISPATCH_CYCLE
793 LOGD("channel '%s' ~ timeoutDispatchCycle",
794 connection->getInputChannelName());
795#endif
796
797 if (connection->status != Connection::STATUS_NORMAL) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700798 return;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700799 }
800
801 // Enter the not responding state.
802 connection->status = Connection::STATUS_NOT_RESPONDING;
803 connection->lastANRTime = currentTime;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700804
805 // Notify other system components.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700806 // This enqueues a command which will eventually either call
807 // resumeAfterTimeoutDispatchCycleLocked or abortDispatchCycleLocked.
Jeff Brown46b9ac02010-04-22 18:58:52 -0700808 onDispatchCycleANRLocked(currentTime, connection);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700809}
810
Jeff Brown7fbdc842010-06-17 20:52:56 -0700811void InputDispatcher::resumeAfterTimeoutDispatchCycleLocked(nsecs_t currentTime,
812 const sp<Connection>& connection, nsecs_t newTimeout) {
813#if DEBUG_DISPATCH_CYCLE
814 LOGD("channel '%s' ~ resumeAfterTimeoutDispatchCycleLocked",
815 connection->getInputChannelName());
816#endif
817
818 if (connection->status != Connection::STATUS_NOT_RESPONDING) {
819 return;
820 }
821
822 // Resume normal dispatch.
823 connection->status = Connection::STATUS_NORMAL;
824 connection->setNextTimeoutTime(currentTime, newTimeout);
825}
826
827void InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime,
828 const sp<Connection>& connection, bool broken) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700829#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700830 LOGD("channel '%s' ~ abortDispatchCycle - broken=%s",
Jeff Brown46b9ac02010-04-22 18:58:52 -0700831 connection->getInputChannelName(), broken ? "true" : "false");
832#endif
833
Jeff Brown46b9ac02010-04-22 18:58:52 -0700834 // Clear the pending timeout.
835 connection->nextTimeoutTime = LONG_LONG_MAX;
836
837 // Clear the outbound queue.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700838 if (! connection->outboundQueue.isEmpty()) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700839 do {
840 DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
841 mAllocator.releaseDispatchEntry(dispatchEntry);
842 } while (! connection->outboundQueue.isEmpty());
Jeff Brown46b9ac02010-04-22 18:58:52 -0700843
Jeff Brown7fbdc842010-06-17 20:52:56 -0700844 deactivateConnectionLocked(connection.get());
Jeff Brown9c3cda02010-06-15 01:31:58 -0700845 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700846
847 // Handle the case where the connection appears to be unrecoverably broken.
Jeff Brown9c3cda02010-06-15 01:31:58 -0700848 // Ignore already broken or zombie connections.
Jeff Brown46b9ac02010-04-22 18:58:52 -0700849 if (broken) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700850 if (connection->status == Connection::STATUS_NORMAL
851 || connection->status == Connection::STATUS_NOT_RESPONDING) {
852 connection->status = Connection::STATUS_BROKEN;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700853
Jeff Brown9c3cda02010-06-15 01:31:58 -0700854 // Notify other system components.
855 onDispatchCycleBrokenLocked(currentTime, connection);
856 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700857 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700858}
859
860bool InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
861 InputDispatcher* d = static_cast<InputDispatcher*>(data);
862
863 { // acquire lock
864 AutoMutex _l(d->mLock);
865
866 ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
867 if (connectionIndex < 0) {
868 LOGE("Received spurious receive callback for unknown input channel. "
869 "fd=%d, events=0x%x", receiveFd, events);
870 return false; // remove the callback
871 }
872
Jeff Brown7fbdc842010-06-17 20:52:56 -0700873 nsecs_t currentTime = now();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700874
875 sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
876 if (events & (POLLERR | POLLHUP | POLLNVAL)) {
877 LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
878 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700879 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700880 d->runCommandsLockedInterruptible();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700881 return false; // remove the callback
882 }
883
884 if (! (events & POLLIN)) {
885 LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
886 "events=0x%x", connection->getInputChannelName(), events);
887 return true;
888 }
889
890 status_t status = connection->inputPublisher.receiveFinishedSignal();
891 if (status) {
892 LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
893 connection->getInputChannelName(), status);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700894 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700895 d->runCommandsLockedInterruptible();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700896 return false; // remove the callback
897 }
898
Jeff Brown7fbdc842010-06-17 20:52:56 -0700899 d->finishDispatchCycleLocked(currentTime, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700900 d->runCommandsLockedInterruptible();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700901 return true;
902 } // release lock
903}
904
Jeff Brown9c3cda02010-06-15 01:31:58 -0700905void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700906#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown9c3cda02010-06-15 01:31:58 -0700907 LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700908#endif
909
910 bool wasEmpty;
911 { // acquire lock
912 AutoMutex _l(mLock);
913
Jeff Brown7fbdc842010-06-17 20:52:56 -0700914 ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700915
916 wasEmpty = mInboundQueue.isEmpty();
917 mInboundQueue.enqueueAtTail(newEntry);
918 } // release lock
919
920 if (wasEmpty) {
921 mPollLoop->wake();
922 }
923}
924
Jeff Brown46b9ac02010-04-22 18:58:52 -0700925void InputDispatcher::notifyAppSwitchComing(nsecs_t eventTime) {
926#if DEBUG_INBOUND_EVENT_DETAILS
927 LOGD("notifyAppSwitchComing - eventTime=%lld", eventTime);
928#endif
929
930 // Remove movement keys from the queue from most recent to least recent, stopping at the
931 // first non-movement key.
932 // TODO: Include a detailed description of why we do this...
933
934 { // acquire lock
935 AutoMutex _l(mLock);
936
937 for (EventEntry* entry = mInboundQueue.tail.prev; entry != & mInboundQueue.head; ) {
938 EventEntry* prev = entry->prev;
939
940 if (entry->type == EventEntry::TYPE_KEY) {
941 KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
942 if (isMovementKey(keyEntry->keyCode)) {
943 LOGV("Dropping movement key during app switch: keyCode=%d, action=%d",
944 keyEntry->keyCode, keyEntry->action);
945 mInboundQueue.dequeue(keyEntry);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700946
947 setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
948
Jeff Brown46b9ac02010-04-22 18:58:52 -0700949 mAllocator.releaseKeyEntry(keyEntry);
950 } else {
951 // stop at last non-movement key
952 break;
953 }
954 }
955
956 entry = prev;
957 }
958 } // release lock
959}
960
961void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
962 uint32_t policyFlags, int32_t action, int32_t flags,
963 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
964#if DEBUG_INBOUND_EVENT_DETAILS
965 LOGD("notifyKey - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, action=0x%x, "
966 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
967 eventTime, deviceId, nature, policyFlags, action, flags,
968 keyCode, scanCode, metaState, downTime);
969#endif
970
971 bool wasEmpty;
972 { // acquire lock
973 AutoMutex _l(mLock);
974
Jeff Brown7fbdc842010-06-17 20:52:56 -0700975 int32_t repeatCount = 0;
976 KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
977 deviceId, nature, policyFlags, action, flags, keyCode, scanCode,
978 metaState, repeatCount, downTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700979
980 wasEmpty = mInboundQueue.isEmpty();
981 mInboundQueue.enqueueAtTail(newEntry);
982 } // release lock
983
984 if (wasEmpty) {
985 mPollLoop->wake();
986 }
987}
988
989void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t nature,
990 uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
991 uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
992 float xPrecision, float yPrecision, nsecs_t downTime) {
993#if DEBUG_INBOUND_EVENT_DETAILS
994 LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, "
995 "action=0x%x, metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, "
996 "downTime=%lld",
997 eventTime, deviceId, nature, policyFlags, action, metaState, edgeFlags,
998 xPrecision, yPrecision, downTime);
999 for (uint32_t i = 0; i < pointerCount; i++) {
1000 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
1001 i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
1002 pointerCoords[i].pressure, pointerCoords[i].size);
1003 }
1004#endif
1005
1006 bool wasEmpty;
1007 { // acquire lock
1008 AutoMutex _l(mLock);
1009
1010 // Attempt batching and streaming of move events.
1011 if (action == MOTION_EVENT_ACTION_MOVE) {
1012 // BATCHING CASE
1013 //
1014 // Try to append a move sample to the tail of the inbound queue for this device.
1015 // Give up if we encounter a non-move motion event for this device since that
1016 // means we cannot append any new samples until a new motion event has started.
1017 for (EventEntry* entry = mInboundQueue.tail.prev;
1018 entry != & mInboundQueue.head; entry = entry->prev) {
1019 if (entry->type != EventEntry::TYPE_MOTION) {
1020 // Keep looking for motion events.
1021 continue;
1022 }
1023
1024 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
1025 if (motionEntry->deviceId != deviceId) {
1026 // Keep looking for this device.
1027 continue;
1028 }
1029
1030 if (motionEntry->action != MOTION_EVENT_ACTION_MOVE
Jeff Brown7fbdc842010-06-17 20:52:56 -07001031 || motionEntry->pointerCount != pointerCount
1032 || motionEntry->isInjected()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001033 // Last motion event in the queue for this device is not compatible for
1034 // appending new samples. Stop here.
1035 goto NoBatchingOrStreaming;
1036 }
1037
1038 // The last motion event is a move and is compatible for appending.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001039 // Do the batching magic.
Jeff Brown7fbdc842010-06-17 20:52:56 -07001040 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001041#if DEBUG_BATCHING
1042 LOGD("Appended motion sample onto batch for most recent "
1043 "motion event for this device in the inbound queue.");
1044#endif
Jeff Brown9c3cda02010-06-15 01:31:58 -07001045
1046 // Sanity check for special case because dispatch is interruptible.
1047 // The dispatch logic is partially interruptible and releases its lock while
1048 // identifying targets. However, as soon as the targets have been identified,
1049 // the dispatcher proceeds to write a dispatch entry into all relevant outbound
1050 // queues and then promptly removes the motion entry from the queue.
1051 //
1052 // Consequently, we should never observe the case where the inbound queue contains
1053 // an in-progress motion entry unless the current input targets are invalid
1054 // (currently being computed). Check for this!
1055 assert(! (motionEntry->dispatchInProgress && mCurrentInputTargetsValid));
1056
1057 return; // done!
Jeff Brown46b9ac02010-04-22 18:58:52 -07001058 }
1059
1060 // STREAMING CASE
1061 //
1062 // There is no pending motion event (of any kind) for this device in the inbound queue.
1063 // Search the outbound queues for a synchronously dispatched motion event for this
1064 // device. If found, then we append the new sample to that event and then try to
1065 // push it out to all current targets. It is possible that some targets will already
1066 // have consumed the motion event. This case is automatically handled by the
1067 // logic in prepareDispatchCycleLocked by tracking where resumption takes place.
1068 //
1069 // The reason we look for a synchronously dispatched motion event is because we
1070 // want to be sure that no other motion events have been dispatched since the move.
1071 // It's also convenient because it means that the input targets are still valid.
1072 // This code could be improved to support streaming of asynchronously dispatched
1073 // motion events (which might be significantly more efficient) but it may become
1074 // a little more complicated as a result.
1075 //
1076 // Note: This code crucially depends on the invariant that an outbound queue always
1077 // contains at most one synchronous event and it is always last (but it might
1078 // not be first!).
Jeff Brown9c3cda02010-06-15 01:31:58 -07001079 if (mCurrentInputTargetsValid) {
1080 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1081 Connection* connection = mActiveConnections.itemAt(i);
1082 if (! connection->outboundQueue.isEmpty()) {
1083 DispatchEntry* dispatchEntry = connection->outboundQueue.tail.prev;
1084 if (dispatchEntry->targetFlags & InputTarget::FLAG_SYNC) {
1085 if (dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION) {
1086 goto NoBatchingOrStreaming;
1087 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001088
Jeff Brown9c3cda02010-06-15 01:31:58 -07001089 MotionEntry* syncedMotionEntry = static_cast<MotionEntry*>(
1090 dispatchEntry->eventEntry);
1091 if (syncedMotionEntry->action != MOTION_EVENT_ACTION_MOVE
1092 || syncedMotionEntry->deviceId != deviceId
Jeff Brown7fbdc842010-06-17 20:52:56 -07001093 || syncedMotionEntry->pointerCount != pointerCount
1094 || syncedMotionEntry->isInjected()) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001095 goto NoBatchingOrStreaming;
1096 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001097
Jeff Brown9c3cda02010-06-15 01:31:58 -07001098 // Found synced move entry. Append sample and resume dispatch.
1099 mAllocator.appendMotionSample(syncedMotionEntry, eventTime,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001100 pointerCoords);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001101 #if DEBUG_BATCHING
1102 LOGD("Appended motion sample onto batch for most recent synchronously "
1103 "dispatched motion event for this device in the outbound queues.");
1104 #endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001105 nsecs_t currentTime = now();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001106 dispatchEventToCurrentInputTargetsLocked(currentTime, syncedMotionEntry,
1107 true /*resumeWithAppendedMotionSample*/);
1108
1109 runCommandsLockedInterruptible();
1110 return; // done!
1111 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001112 }
1113 }
1114 }
1115
1116NoBatchingOrStreaming:;
1117 }
1118
1119 // Just enqueue a new motion event.
Jeff Brown7fbdc842010-06-17 20:52:56 -07001120 MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
1121 deviceId, nature, policyFlags, action, metaState, edgeFlags,
1122 xPrecision, yPrecision, downTime,
1123 pointerCount, pointerIds, pointerCoords);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001124
1125 wasEmpty = mInboundQueue.isEmpty();
1126 mInboundQueue.enqueueAtTail(newEntry);
1127 } // release lock
1128
1129 if (wasEmpty) {
1130 mPollLoop->wake();
1131 }
1132}
1133
Jeff Brown7fbdc842010-06-17 20:52:56 -07001134int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
1135 int32_t injectorPid, int32_t injectorUid, bool sync, int32_t timeoutMillis) {
1136#if DEBUG_INBOUND_EVENT_DETAILS
1137 LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
1138 "sync=%d, timeoutMillis=%d",
1139 event->getType(), injectorPid, injectorUid, sync, timeoutMillis);
1140#endif
1141
1142 nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
1143
1144 EventEntry* injectedEntry;
1145 bool wasEmpty;
1146 { // acquire lock
1147 AutoMutex _l(mLock);
1148
1149 injectedEntry = createEntryFromInputEventLocked(event);
1150 injectedEntry->refCount += 1;
1151 injectedEntry->injectorPid = injectorPid;
1152 injectedEntry->injectorUid = injectorUid;
1153
1154 wasEmpty = mInboundQueue.isEmpty();
1155 mInboundQueue.enqueueAtTail(injectedEntry);
1156
1157 } // release lock
1158
1159 if (wasEmpty) {
1160 mPollLoop->wake();
1161 }
1162
1163 int32_t injectionResult;
1164 { // acquire lock
1165 AutoMutex _l(mLock);
1166
1167 for (;;) {
1168 injectionResult = injectedEntry->injectionResult;
1169 if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
1170 break;
1171 }
1172
1173 nsecs_t remainingTimeout = endTime - now();
1174 if (remainingTimeout <= 0) {
1175 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1176 sync = false;
1177 break;
1178 }
1179
1180 mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
1181 }
1182
1183 if (sync) {
1184 while (! isFullySynchronizedLocked()) {
1185 nsecs_t remainingTimeout = endTime - now();
1186 if (remainingTimeout <= 0) {
1187 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1188 break;
1189 }
1190
1191 mFullySynchronizedCondition.waitRelative(mLock, remainingTimeout);
1192 }
1193 }
1194
1195 mAllocator.releaseEventEntry(injectedEntry);
1196 } // release lock
1197
1198 return injectionResult;
1199}
1200
1201void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
1202 if (entry->isInjected()) {
1203#if DEBUG_INJECTION
1204 LOGD("Setting input event injection result to %d. "
1205 "injectorPid=%d, injectorUid=%d",
1206 injectionResult, entry->injectorPid, entry->injectorUid);
1207#endif
1208
1209 entry->injectionResult = injectionResult;
1210 mInjectionResultAvailableCondition.broadcast();
1211 }
1212}
1213
1214bool InputDispatcher::isFullySynchronizedLocked() {
1215 return mInboundQueue.isEmpty() && mActiveConnections.isEmpty();
1216}
1217
1218InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked(
1219 const InputEvent* event) {
1220 switch (event->getType()) {
1221 case INPUT_EVENT_TYPE_KEY: {
1222 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
1223 uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
1224
1225 KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
1226 keyEvent->getDeviceId(), keyEvent->getNature(), policyFlags,
1227 keyEvent->getAction(), keyEvent->getFlags(),
1228 keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
1229 keyEvent->getRepeatCount(), keyEvent->getDownTime());
1230 return keyEntry;
1231 }
1232
1233 case INPUT_EVENT_TYPE_MOTION: {
1234 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
1235 uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
1236
1237 const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
1238 const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
1239 size_t pointerCount = motionEvent->getPointerCount();
1240
1241 MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
1242 motionEvent->getDeviceId(), motionEvent->getNature(), policyFlags,
1243 motionEvent->getAction(), motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
1244 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
1245 motionEvent->getDownTime(), uint32_t(pointerCount),
1246 motionEvent->getPointerIds(), samplePointerCoords);
1247 for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
1248 sampleEventTimes += 1;
1249 samplePointerCoords += pointerCount;
1250 mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
1251 }
1252 return motionEntry;
1253 }
1254
1255 default:
1256 assert(false);
1257 return NULL;
1258 }
1259}
1260
Jeff Brown46b9ac02010-04-22 18:58:52 -07001261void InputDispatcher::resetKeyRepeatLocked() {
1262 if (mKeyRepeatState.lastKeyEntry) {
1263 mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
1264 mKeyRepeatState.lastKeyEntry = NULL;
1265 }
1266}
1267
Jeff Brown349703e2010-06-22 01:27:15 -07001268void InputDispatcher::preemptInputDispatch() {
1269#if DEBUG_DISPATCH_CYCLE
1270 LOGD("preemptInputDispatch");
1271#endif
1272
1273 bool preemptedOne = false;
1274 { // acquire lock
1275 AutoMutex _l(mLock);
1276
1277 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1278 Connection* connection = mActiveConnections[i];
1279 if (connection->hasPendingSyncTarget()) {
1280#if DEBUG_DISPATCH_CYCLE
1281 LOGD("channel '%s' ~ Preempted pending synchronous dispatch",
1282 connection->getInputChannelName());
1283#endif
1284 connection->outboundQueue.tail.prev->targetFlags &= ~ InputTarget::FLAG_SYNC;
1285 preemptedOne = true;
1286 }
1287 }
1288 } // release lock
1289
1290 if (preemptedOne) {
1291 // Wake up the poll loop so it can get a head start dispatching the next event.
1292 mPollLoop->wake();
1293 }
1294}
1295
Jeff Brown46b9ac02010-04-22 18:58:52 -07001296status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001297#if DEBUG_REGISTRATION
Jeff Brown349703e2010-06-22 01:27:15 -07001298 LOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().string());
Jeff Brown9c3cda02010-06-15 01:31:58 -07001299#endif
1300
Jeff Brown46b9ac02010-04-22 18:58:52 -07001301 int receiveFd;
1302 { // acquire lock
1303 AutoMutex _l(mLock);
1304
1305 receiveFd = inputChannel->getReceivePipeFd();
1306 if (mConnectionsByReceiveFd.indexOfKey(receiveFd) >= 0) {
1307 LOGW("Attempted to register already registered input channel '%s'",
1308 inputChannel->getName().string());
1309 return BAD_VALUE;
1310 }
1311
1312 sp<Connection> connection = new Connection(inputChannel);
1313 status_t status = connection->initialize();
1314 if (status) {
1315 LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
1316 inputChannel->getName().string(), status);
1317 return status;
1318 }
1319
1320 mConnectionsByReceiveFd.add(receiveFd, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001321
1322 runCommandsLockedInterruptible();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001323 } // release lock
1324
1325 mPollLoop->setCallback(receiveFd, POLLIN, handleReceiveCallback, this);
1326 return OK;
1327}
1328
1329status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001330#if DEBUG_REGISTRATION
Jeff Brown349703e2010-06-22 01:27:15 -07001331 LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
Jeff Brown9c3cda02010-06-15 01:31:58 -07001332#endif
1333
Jeff Brown46b9ac02010-04-22 18:58:52 -07001334 int32_t receiveFd;
1335 { // acquire lock
1336 AutoMutex _l(mLock);
1337
1338 receiveFd = inputChannel->getReceivePipeFd();
1339 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(receiveFd);
1340 if (connectionIndex < 0) {
1341 LOGW("Attempted to unregister already unregistered input channel '%s'",
1342 inputChannel->getName().string());
1343 return BAD_VALUE;
1344 }
1345
1346 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1347 mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
1348
1349 connection->status = Connection::STATUS_ZOMBIE;
1350
Jeff Brown7fbdc842010-06-17 20:52:56 -07001351 nsecs_t currentTime = now();
1352 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001353
1354 runCommandsLockedInterruptible();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001355 } // release lock
1356
1357 mPollLoop->removeCallback(receiveFd);
1358
1359 // Wake the poll loop because removing the connection may have changed the current
1360 // synchronization state.
1361 mPollLoop->wake();
1362 return OK;
1363}
1364
1365void InputDispatcher::activateConnectionLocked(Connection* connection) {
1366 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1367 if (mActiveConnections.itemAt(i) == connection) {
1368 return;
1369 }
1370 }
1371 mActiveConnections.add(connection);
1372}
1373
1374void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
1375 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1376 if (mActiveConnections.itemAt(i) == connection) {
1377 mActiveConnections.removeAt(i);
1378 return;
1379 }
1380 }
1381}
1382
Jeff Brown9c3cda02010-06-15 01:31:58 -07001383void InputDispatcher::onDispatchCycleStartedLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07001384 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001385}
1386
Jeff Brown9c3cda02010-06-15 01:31:58 -07001387void InputDispatcher::onDispatchCycleFinishedLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07001388 nsecs_t currentTime, const sp<Connection>& connection, bool recoveredFromANR) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001389 if (recoveredFromANR) {
1390 LOGI("channel '%s' ~ Recovered from ANR. %01.1fms since event, "
1391 "%01.1fms since dispatch, %01.1fms since ANR",
1392 connection->getInputChannelName(),
1393 connection->getEventLatencyMillis(currentTime),
1394 connection->getDispatchLatencyMillis(currentTime),
1395 connection->getANRLatencyMillis(currentTime));
1396
Jeff Brown9c3cda02010-06-15 01:31:58 -07001397 CommandEntry* commandEntry = postCommandLocked(
1398 & InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001399 commandEntry->connection = connection;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001400 }
1401}
1402
Jeff Brown9c3cda02010-06-15 01:31:58 -07001403void InputDispatcher::onDispatchCycleANRLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07001404 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001405 LOGI("channel '%s' ~ Not responding! %01.1fms since event, %01.1fms since dispatch",
1406 connection->getInputChannelName(),
1407 connection->getEventLatencyMillis(currentTime),
1408 connection->getDispatchLatencyMillis(currentTime));
1409
Jeff Brown9c3cda02010-06-15 01:31:58 -07001410 CommandEntry* commandEntry = postCommandLocked(
1411 & InputDispatcher::doNotifyInputChannelANRLockedInterruptible);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001412 commandEntry->connection = connection;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001413}
1414
Jeff Brown9c3cda02010-06-15 01:31:58 -07001415void InputDispatcher::onDispatchCycleBrokenLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07001416 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001417 LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
1418 connection->getInputChannelName());
1419
Jeff Brown9c3cda02010-06-15 01:31:58 -07001420 CommandEntry* commandEntry = postCommandLocked(
1421 & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001422 commandEntry->connection = connection;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001423}
1424
Jeff Brown9c3cda02010-06-15 01:31:58 -07001425void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
1426 CommandEntry* commandEntry) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001427 sp<Connection> connection = commandEntry->connection;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001428
Jeff Brown7fbdc842010-06-17 20:52:56 -07001429 if (connection->status != Connection::STATUS_ZOMBIE) {
1430 mLock.unlock();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001431
Jeff Brown7fbdc842010-06-17 20:52:56 -07001432 mPolicy->notifyInputChannelBroken(connection->inputChannel);
1433
1434 mLock.lock();
1435 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001436}
1437
1438void InputDispatcher::doNotifyInputChannelANRLockedInterruptible(
1439 CommandEntry* commandEntry) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001440 sp<Connection> connection = commandEntry->connection;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001441
Jeff Brown7fbdc842010-06-17 20:52:56 -07001442 if (connection->status != Connection::STATUS_ZOMBIE) {
1443 mLock.unlock();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001444
Jeff Brown7fbdc842010-06-17 20:52:56 -07001445 nsecs_t newTimeout;
1446 bool resume = mPolicy->notifyInputChannelANR(connection->inputChannel, newTimeout);
1447
1448 mLock.lock();
1449
1450 nsecs_t currentTime = now();
1451 if (resume) {
1452 resumeAfterTimeoutDispatchCycleLocked(currentTime, connection, newTimeout);
1453 } else {
1454 abortDispatchCycleLocked(currentTime, connection, false /*(not) broken*/);
1455 }
1456 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001457}
1458
1459void InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible(
1460 CommandEntry* commandEntry) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001461 sp<Connection> connection = commandEntry->connection;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001462
Jeff Brown7fbdc842010-06-17 20:52:56 -07001463 if (connection->status != Connection::STATUS_ZOMBIE) {
1464 mLock.unlock();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001465
Jeff Brown7fbdc842010-06-17 20:52:56 -07001466 mPolicy->notifyInputChannelRecoveredFromANR(connection->inputChannel);
1467
1468 mLock.lock();
1469 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001470}
1471
1472
Jeff Brown46b9ac02010-04-22 18:58:52 -07001473// --- InputDispatcher::Allocator ---
1474
1475InputDispatcher::Allocator::Allocator() {
1476}
1477
Jeff Brown7fbdc842010-06-17 20:52:56 -07001478void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
1479 nsecs_t eventTime) {
1480 entry->type = type;
1481 entry->refCount = 1;
1482 entry->dispatchInProgress = false;
Christopher Tatee91a5db2010-06-23 16:50:30 -07001483 entry->eventTime = eventTime;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001484 entry->injectionResult = INPUT_EVENT_INJECTION_PENDING;
1485 entry->injectorPid = -1;
1486 entry->injectorUid = -1;
1487}
1488
Jeff Brown46b9ac02010-04-22 18:58:52 -07001489InputDispatcher::ConfigurationChangedEntry*
Jeff Brown7fbdc842010-06-17 20:52:56 -07001490InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001491 ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
Jeff Brown7fbdc842010-06-17 20:52:56 -07001492 initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001493 return entry;
1494}
1495
Jeff Brown7fbdc842010-06-17 20:52:56 -07001496InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
1497 int32_t deviceId, int32_t nature, uint32_t policyFlags, int32_t action,
1498 int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
1499 int32_t repeatCount, nsecs_t downTime) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001500 KeyEntry* entry = mKeyEntryPool.alloc();
Jeff Brown7fbdc842010-06-17 20:52:56 -07001501 initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime);
1502
1503 entry->deviceId = deviceId;
1504 entry->nature = nature;
1505 entry->policyFlags = policyFlags;
1506 entry->action = action;
1507 entry->flags = flags;
1508 entry->keyCode = keyCode;
1509 entry->scanCode = scanCode;
1510 entry->metaState = metaState;
1511 entry->repeatCount = repeatCount;
1512 entry->downTime = downTime;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001513 return entry;
1514}
1515
Jeff Brown7fbdc842010-06-17 20:52:56 -07001516InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
1517 int32_t deviceId, int32_t nature, uint32_t policyFlags, int32_t action,
1518 int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
1519 nsecs_t downTime, uint32_t pointerCount,
1520 const int32_t* pointerIds, const PointerCoords* pointerCoords) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001521 MotionEntry* entry = mMotionEntryPool.alloc();
Jeff Brown7fbdc842010-06-17 20:52:56 -07001522 initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime);
1523
1524 entry->eventTime = eventTime;
1525 entry->deviceId = deviceId;
1526 entry->nature = nature;
1527 entry->policyFlags = policyFlags;
1528 entry->action = action;
1529 entry->metaState = metaState;
1530 entry->edgeFlags = edgeFlags;
1531 entry->xPrecision = xPrecision;
1532 entry->yPrecision = yPrecision;
1533 entry->downTime = downTime;
1534 entry->pointerCount = pointerCount;
1535 entry->firstSample.eventTime = eventTime;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001536 entry->firstSample.next = NULL;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001537 entry->lastSample = & entry->firstSample;
1538 for (uint32_t i = 0; i < pointerCount; i++) {
1539 entry->pointerIds[i] = pointerIds[i];
1540 entry->firstSample.pointerCoords[i] = pointerCoords[i];
1541 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001542 return entry;
1543}
1544
1545InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
1546 EventEntry* eventEntry) {
1547 DispatchEntry* entry = mDispatchEntryPool.alloc();
1548 entry->eventEntry = eventEntry;
1549 eventEntry->refCount += 1;
1550 return entry;
1551}
1552
Jeff Brown9c3cda02010-06-15 01:31:58 -07001553InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
1554 CommandEntry* entry = mCommandEntryPool.alloc();
1555 entry->command = command;
1556 return entry;
1557}
1558
Jeff Brown46b9ac02010-04-22 18:58:52 -07001559void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
1560 switch (entry->type) {
1561 case EventEntry::TYPE_CONFIGURATION_CHANGED:
1562 releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
1563 break;
1564 case EventEntry::TYPE_KEY:
1565 releaseKeyEntry(static_cast<KeyEntry*>(entry));
1566 break;
1567 case EventEntry::TYPE_MOTION:
1568 releaseMotionEntry(static_cast<MotionEntry*>(entry));
1569 break;
1570 default:
1571 assert(false);
1572 break;
1573 }
1574}
1575
1576void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
1577 ConfigurationChangedEntry* entry) {
1578 entry->refCount -= 1;
1579 if (entry->refCount == 0) {
1580 mConfigurationChangeEntryPool.free(entry);
1581 } else {
1582 assert(entry->refCount > 0);
1583 }
1584}
1585
1586void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
1587 entry->refCount -= 1;
1588 if (entry->refCount == 0) {
1589 mKeyEntryPool.free(entry);
1590 } else {
1591 assert(entry->refCount > 0);
1592 }
1593}
1594
1595void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
1596 entry->refCount -= 1;
1597 if (entry->refCount == 0) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001598 for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
1599 MotionSample* next = sample->next;
1600 mMotionSamplePool.free(sample);
1601 sample = next;
1602 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001603 mMotionEntryPool.free(entry);
1604 } else {
1605 assert(entry->refCount > 0);
1606 }
1607}
1608
1609void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
1610 releaseEventEntry(entry->eventEntry);
1611 mDispatchEntryPool.free(entry);
1612}
1613
Jeff Brown9c3cda02010-06-15 01:31:58 -07001614void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
1615 mCommandEntryPool.free(entry);
1616}
1617
Jeff Brown46b9ac02010-04-22 18:58:52 -07001618void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001619 nsecs_t eventTime, const PointerCoords* pointerCoords) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001620 MotionSample* sample = mMotionSamplePool.alloc();
1621 sample->eventTime = eventTime;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001622 uint32_t pointerCount = motionEntry->pointerCount;
1623 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001624 sample->pointerCoords[i] = pointerCoords[i];
1625 }
1626
1627 sample->next = NULL;
1628 motionEntry->lastSample->next = sample;
1629 motionEntry->lastSample = sample;
1630}
1631
Jeff Brown46b9ac02010-04-22 18:58:52 -07001632// --- InputDispatcher::Connection ---
1633
1634InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
1635 status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
1636 nextTimeoutTime(LONG_LONG_MAX),
1637 lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX),
1638 lastANRTime(LONG_LONG_MAX) {
1639}
1640
1641InputDispatcher::Connection::~Connection() {
1642}
1643
1644status_t InputDispatcher::Connection::initialize() {
1645 return inputPublisher.initialize();
1646}
1647
Jeff Brown7fbdc842010-06-17 20:52:56 -07001648void InputDispatcher::Connection::setNextTimeoutTime(nsecs_t currentTime, nsecs_t timeout) {
1649 nextTimeoutTime = (timeout >= 0) ? currentTime + timeout : LONG_LONG_MAX;
1650}
1651
Jeff Brown9c3cda02010-06-15 01:31:58 -07001652const char* InputDispatcher::Connection::getStatusLabel() const {
1653 switch (status) {
1654 case STATUS_NORMAL:
1655 return "NORMAL";
1656
1657 case STATUS_BROKEN:
1658 return "BROKEN";
1659
1660 case STATUS_NOT_RESPONDING:
1661 return "NOT_RESPONDING";
1662
1663 case STATUS_ZOMBIE:
1664 return "ZOMBIE";
1665
1666 default:
1667 return "UNKNOWN";
1668 }
1669}
1670
Jeff Brown46b9ac02010-04-22 18:58:52 -07001671InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
1672 const EventEntry* eventEntry) const {
1673 for (DispatchEntry* dispatchEntry = outboundQueue.tail.prev;
1674 dispatchEntry != & outboundQueue.head; dispatchEntry = dispatchEntry->prev) {
1675 if (dispatchEntry->eventEntry == eventEntry) {
1676 return dispatchEntry;
1677 }
1678 }
1679 return NULL;
1680}
1681
Jeff Brown9c3cda02010-06-15 01:31:58 -07001682// --- InputDispatcher::CommandEntry ---
1683
1684InputDispatcher::CommandEntry::CommandEntry() {
1685}
1686
1687InputDispatcher::CommandEntry::~CommandEntry() {
1688}
1689
Jeff Brown46b9ac02010-04-22 18:58:52 -07001690
1691// --- InputDispatcherThread ---
1692
1693InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
1694 Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
1695}
1696
1697InputDispatcherThread::~InputDispatcherThread() {
1698}
1699
1700bool InputDispatcherThread::threadLoop() {
1701 mDispatcher->dispatchOnce();
1702 return true;
1703}
1704
1705} // namespace android