blob: 8f6d1fe0c0cb9144f1b14fc46408f69c6e1c400e [file] [log] [blame]
Jeff Browne839a582010-04-22 18:58:52 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4// The input dispatcher.
5//
6#define LOG_TAG "InputDispatcher"
7
8//#define LOG_NDEBUG 0
9
10// Log detailed debug messages about each inbound event notification to the dispatcher.
Jeff Brown50de30a2010-06-22 01:27:15 -070011#define DEBUG_INBOUND_EVENT_DETAILS 0
Jeff Browne839a582010-04-22 18:58:52 -070012
13// Log detailed debug messages about each outbound event processed by the dispatcher.
Jeff Brown50de30a2010-06-22 01:27:15 -070014#define DEBUG_OUTBOUND_EVENT_DETAILS 0
Jeff Browne839a582010-04-22 18:58:52 -070015
16// Log debug messages about batching.
Jeff Brown50de30a2010-06-22 01:27:15 -070017#define DEBUG_BATCHING 0
Jeff Browne839a582010-04-22 18:58:52 -070018
19// Log debug messages about the dispatch cycle.
Jeff Brown50de30a2010-06-22 01:27:15 -070020#define DEBUG_DISPATCH_CYCLE 0
Jeff Browne839a582010-04-22 18:58:52 -070021
Jeff Brown54bc2812010-06-15 01:31:58 -070022// Log debug messages about registrations.
Jeff Brown50de30a2010-06-22 01:27:15 -070023#define DEBUG_REGISTRATION 0
Jeff Brown54bc2812010-06-15 01:31:58 -070024
Jeff Browne839a582010-04-22 18:58:52 -070025// Log debug messages about performance statistics.
Jeff Brown50de30a2010-06-22 01:27:15 -070026#define DEBUG_PERFORMANCE_STATISTICS 0
Jeff Browne839a582010-04-22 18:58:52 -070027
Jeff Brown51d45a72010-06-17 20:52:56 -070028// Log debug messages about input event injection.
Jeff Brown50de30a2010-06-22 01:27:15 -070029#define DEBUG_INJECTION 0
Jeff Brown51d45a72010-06-17 20:52:56 -070030
Jeff Browne839a582010-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 Browne839a582010-04-22 18:58:52 -070036#include <errno.h>
37#include <limits.h>
Jeff Browne839a582010-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 Brown51d45a72010-06-17 20:52:56 -070049static inline nsecs_t now() {
50 return systemTime(SYSTEM_TIME_MONOTONIC);
51}
52
Jeff Browne839a582010-04-22 18:58:52 -070053// --- InputDispatcher ---
54
Jeff Brown54bc2812010-06-15 01:31:58 -070055InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
Jeff Browne839a582010-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 Brown54bc2812010-06-15 01:31:58 -070068
69 mCurrentInputTargetsValid = false;
Jeff Browne839a582010-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 Brown54bc2812010-06-15 01:31:58 -070087 nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
Jeff Browne839a582010-04-22 18:58:52 -070088
Jeff Brown54bc2812010-06-15 01:31:58 -070089 bool skipPoll = false;
Jeff Browne839a582010-04-22 18:58:52 -070090 nsecs_t currentTime;
91 nsecs_t nextWakeupTime = LONG_LONG_MAX;
92 { // acquire lock
93 AutoMutex _l(mLock);
Jeff Brown51d45a72010-06-17 20:52:56 -070094 currentTime = now();
Jeff Browne839a582010-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 Brown54bc2812010-06-15 01:31:58 -0700100 if (keyRepeatTimeout < 0) {
Jeff Browne839a582010-04-22 18:58:52 -0700101 resetKeyRepeatLocked();
102 }
103
Jeff Brown51d45a72010-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 Browne839a582010-04-22 18:58:52 -0700106 bool hasPendingSyncTarget = false;
Jeff Brown51d45a72010-06-17 20:52:56 -0700107 size_t activeConnectionCount = mActiveConnections.size();
108 for (size_t i = 0; i < activeConnectionCount; i++) {
Jeff Browne839a582010-04-22 18:58:52 -0700109 Connection* connection = mActiveConnections.itemAt(i);
110
Jeff Browne839a582010-04-22 18:58:52 -0700111 if (connection->hasPendingSyncTarget()) {
112 hasPendingSyncTarget = true;
113 }
114
Jeff Brown51d45a72010-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 Browne839a582010-04-22 18:58:52 -0700121 }
122
Jeff Brown51d45a72010-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 Browne839a582010-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 Brown54bc2812010-06-15 01:31:58 -0700137 processKeyRepeatLockedInterruptible(currentTime, keyRepeatTimeout);
138 skipPoll = true;
Jeff Browne839a582010-04-22 18:58:52 -0700139 } else {
140 if (mKeyRepeatState.nextRepeatTime < nextWakeupTime) {
141 nextWakeupTime = mKeyRepeatState.nextRepeatTime;
142 }
143 }
144 }
145 } else {
Jeff Brown54bc2812010-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 Browne839a582010-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 Brown54bc2812010-06-15 01:31:58 -0700157 processConfigurationChangedLockedInterruptible(currentTime, typedEntry);
Jeff Browne839a582010-04-22 18:58:52 -0700158 break;
159 }
160
161 case EventEntry::TYPE_KEY: {
162 KeyEntry* typedEntry = static_cast<KeyEntry*>(entry);
Jeff Brown54bc2812010-06-15 01:31:58 -0700163 processKeyLockedInterruptible(currentTime, typedEntry, keyRepeatTimeout);
Jeff Browne839a582010-04-22 18:58:52 -0700164 break;
165 }
166
167 case EventEntry::TYPE_MOTION: {
168 MotionEntry* typedEntry = static_cast<MotionEntry*>(entry);
Jeff Brown54bc2812010-06-15 01:31:58 -0700169 processMotionLockedInterruptible(currentTime, typedEntry);
Jeff Browne839a582010-04-22 18:58:52 -0700170 break;
171 }
172
173 default:
174 assert(false);
175 break;
176 }
Jeff Brown54bc2812010-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 Browne839a582010-04-22 18:58:52 -0700182 }
183 }
Jeff Brown54bc2812010-06-15 01:31:58 -0700184
185 // Run any deferred commands.
186 skipPoll |= runCommandsLockedInterruptible();
Jeff Brown51d45a72010-06-17 20:52:56 -0700187
188 // Wake up synchronization waiters, if needed.
189 if (isFullySynchronizedLocked()) {
190 mFullySynchronizedCondition.broadcast();
191 }
Jeff Browne839a582010-04-22 18:58:52 -0700192 } // release lock
193
Jeff Brown54bc2812010-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 Browne839a582010-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 Brown54bc2812010-06-15 01:31:58 -0700206bool InputDispatcher::runCommandsLockedInterruptible() {
207 if (mCommandQueue.isEmpty()) {
208 return false;
209 }
Jeff Browne839a582010-04-22 18:58:52 -0700210
Jeff Brown54bc2812010-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 Brown51d45a72010-06-17 20:52:56 -0700217 commandEntry->connection.clear();
Jeff Brown54bc2812010-06-15 01:31:58 -0700218 mAllocator.releaseCommandEntry(commandEntry);
219 } while (! mCommandQueue.isEmpty());
220 return true;
Jeff Browne839a582010-04-22 18:58:52 -0700221}
222
Jeff Brown54bc2812010-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
Jeff Brown4036f7f2010-06-29 16:52:21 -0700235 // Reset key repeating in case a keyboard device was added or removed or something.
236 resetKeyRepeatLocked();
237
Jeff Brown54bc2812010-06-15 01:31:58 -0700238 mLock.unlock();
239
240 mPolicy->notifyConfigurationChanged(entry->eventTime);
241
242 mLock.lock();
243}
244
245void InputDispatcher::processKeyLockedInterruptible(
246 nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout) {
Jeff Browne839a582010-04-22 18:58:52 -0700247#if DEBUG_OUTBOUND_EVENT_DETAILS
248 LOGD("processKey - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, action=0x%x, "
249 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
250 entry->eventTime, entry->deviceId, entry->nature, entry->policyFlags, entry->action,
251 entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
252 entry->downTime);
253#endif
254
Jeff Brown50de30a2010-06-22 01:27:15 -0700255 if (entry->action == KEY_EVENT_ACTION_DOWN && ! entry->isInjected()) {
Jeff Browne839a582010-04-22 18:58:52 -0700256 if (mKeyRepeatState.lastKeyEntry
257 && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
258 // We have seen two identical key downs in a row which indicates that the device
259 // driver is automatically generating key repeats itself. We take note of the
260 // repeat here, but we disable our own next key repeat timer since it is clear that
261 // we will not need to synthesize key repeats ourselves.
262 entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
263 resetKeyRepeatLocked();
264 mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
265 } else {
266 // Not a repeat. Save key down state in case we do see a repeat later.
267 resetKeyRepeatLocked();
Jeff Brown54bc2812010-06-15 01:31:58 -0700268 mKeyRepeatState.nextRepeatTime = entry->eventTime + keyRepeatTimeout;
Jeff Browne839a582010-04-22 18:58:52 -0700269 }
270 mKeyRepeatState.lastKeyEntry = entry;
271 entry->refCount += 1;
272 } else {
273 resetKeyRepeatLocked();
274 }
275
Jeff Brown54bc2812010-06-15 01:31:58 -0700276 identifyInputTargetsAndDispatchKeyLockedInterruptible(currentTime, entry);
Jeff Browne839a582010-04-22 18:58:52 -0700277}
278
Jeff Brown54bc2812010-06-15 01:31:58 -0700279void InputDispatcher::processKeyRepeatLockedInterruptible(
280 nsecs_t currentTime, nsecs_t keyRepeatTimeout) {
Jeff Brown50de30a2010-06-22 01:27:15 -0700281 KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
282
283 // Search the inbound queue for a key up corresponding to this device.
284 // It doesn't make sense to generate a key repeat event if the key is already up.
285 for (EventEntry* queuedEntry = mInboundQueue.head.next;
286 queuedEntry != & mInboundQueue.tail; queuedEntry = entry->next) {
287 if (queuedEntry->type == EventEntry::TYPE_KEY) {
288 KeyEntry* queuedKeyEntry = static_cast<KeyEntry*>(queuedEntry);
289 if (queuedKeyEntry->deviceId == entry->deviceId
290 && entry->action == KEY_EVENT_ACTION_UP) {
291 resetKeyRepeatLocked();
292 return;
293 }
294 }
295 }
Jeff Browne839a582010-04-22 18:58:52 -0700296
297 // Synthesize a key repeat after the repeat timeout expired.
Jeff Brown50de30a2010-06-22 01:27:15 -0700298 // Reuse the repeated key entry if it is otherwise unreferenced.
Jeff Brown51d45a72010-06-17 20:52:56 -0700299 uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
Jeff Browne839a582010-04-22 18:58:52 -0700300 if (entry->refCount == 1) {
Jeff Brown51d45a72010-06-17 20:52:56 -0700301 entry->eventTime = currentTime;
302 entry->downTime = currentTime;
303 entry->policyFlags = policyFlags;
Jeff Browne839a582010-04-22 18:58:52 -0700304 entry->repeatCount += 1;
305 } else {
Jeff Brown51d45a72010-06-17 20:52:56 -0700306 KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
307 entry->deviceId, entry->nature, policyFlags,
308 entry->action, entry->flags, entry->keyCode, entry->scanCode,
309 entry->metaState, entry->repeatCount + 1, currentTime);
Jeff Browne839a582010-04-22 18:58:52 -0700310
311 mKeyRepeatState.lastKeyEntry = newEntry;
312 mAllocator.releaseKeyEntry(entry);
313
314 entry = newEntry;
315 }
Jeff Browne839a582010-04-22 18:58:52 -0700316
Jeff Brown54bc2812010-06-15 01:31:58 -0700317 mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatTimeout;
Jeff Browne839a582010-04-22 18:58:52 -0700318
319#if DEBUG_OUTBOUND_EVENT_DETAILS
320 LOGD("processKeyRepeat - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, "
321 "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
322 "repeatCount=%d, downTime=%lld",
323 entry->eventTime, entry->deviceId, entry->nature, entry->policyFlags,
324 entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
325 entry->repeatCount, entry->downTime);
326#endif
327
Jeff Brown54bc2812010-06-15 01:31:58 -0700328 identifyInputTargetsAndDispatchKeyLockedInterruptible(currentTime, entry);
Jeff Browne839a582010-04-22 18:58:52 -0700329}
330
Jeff Brown54bc2812010-06-15 01:31:58 -0700331void InputDispatcher::processMotionLockedInterruptible(
332 nsecs_t currentTime, MotionEntry* entry) {
Jeff Browne839a582010-04-22 18:58:52 -0700333#if DEBUG_OUTBOUND_EVENT_DETAILS
334 LOGD("processMotion - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, action=0x%x, "
335 "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
336 entry->eventTime, entry->deviceId, entry->nature, entry->policyFlags, entry->action,
337 entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
338 entry->downTime);
339
340 // Print the most recent sample that we have available, this may change due to batching.
341 size_t sampleCount = 1;
342 MotionSample* sample = & entry->firstSample;
343 for (; sample->next != NULL; sample = sample->next) {
344 sampleCount += 1;
345 }
346 for (uint32_t i = 0; i < entry->pointerCount; i++) {
347 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
348 i, entry->pointerIds[i],
349 sample->pointerCoords[i].x,
350 sample->pointerCoords[i].y,
351 sample->pointerCoords[i].pressure,
352 sample->pointerCoords[i].size);
353 }
354
355 // Keep in mind that due to batching, it is possible for the number of samples actually
356 // dispatched to change before the application finally consumed them.
357 if (entry->action == MOTION_EVENT_ACTION_MOVE) {
358 LOGD(" ... Total movement samples currently batched %d ...", sampleCount);
359 }
360#endif
361
Jeff Brown54bc2812010-06-15 01:31:58 -0700362 identifyInputTargetsAndDispatchMotionLockedInterruptible(currentTime, entry);
Jeff Browne839a582010-04-22 18:58:52 -0700363}
364
Jeff Brown54bc2812010-06-15 01:31:58 -0700365void InputDispatcher::identifyInputTargetsAndDispatchKeyLockedInterruptible(
Jeff Browne839a582010-04-22 18:58:52 -0700366 nsecs_t currentTime, KeyEntry* entry) {
367#if DEBUG_DISPATCH_CYCLE
368 LOGD("identifyInputTargetsAndDispatchKey");
369#endif
370
Jeff Brown54bc2812010-06-15 01:31:58 -0700371 entry->dispatchInProgress = true;
372 mCurrentInputTargetsValid = false;
373 mLock.unlock();
374
Jeff Browne839a582010-04-22 18:58:52 -0700375 mReusableKeyEvent.initialize(entry->deviceId, entry->nature, entry->action, entry->flags,
376 entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
377 entry->downTime, entry->eventTime);
378
379 mCurrentInputTargets.clear();
Jeff Brown50de30a2010-06-22 01:27:15 -0700380 int32_t injectionResult = mPolicy->waitForKeyEventTargets(& mReusableKeyEvent,
Jeff Brown51d45a72010-06-17 20:52:56 -0700381 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Browne839a582010-04-22 18:58:52 -0700382 mCurrentInputTargets);
383
Jeff Brown54bc2812010-06-15 01:31:58 -0700384 mLock.lock();
385 mCurrentInputTargetsValid = true;
386
Jeff Brown51d45a72010-06-17 20:52:56 -0700387 setInjectionResultLocked(entry, injectionResult);
388
Jeff Brown50de30a2010-06-22 01:27:15 -0700389 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
390 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
391 }
Jeff Browne839a582010-04-22 18:58:52 -0700392}
393
Jeff Brown54bc2812010-06-15 01:31:58 -0700394void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(
Jeff Browne839a582010-04-22 18:58:52 -0700395 nsecs_t currentTime, MotionEntry* entry) {
396#if DEBUG_DISPATCH_CYCLE
397 LOGD("identifyInputTargetsAndDispatchMotion");
398#endif
399
Jeff Brown54bc2812010-06-15 01:31:58 -0700400 entry->dispatchInProgress = true;
401 mCurrentInputTargetsValid = false;
402 mLock.unlock();
403
Jeff Browne839a582010-04-22 18:58:52 -0700404 mReusableMotionEvent.initialize(entry->deviceId, entry->nature, entry->action,
405 entry->edgeFlags, entry->metaState,
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700406 0, 0, entry->xPrecision, entry->yPrecision,
Jeff Browne839a582010-04-22 18:58:52 -0700407 entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds,
408 entry->firstSample.pointerCoords);
409
410 mCurrentInputTargets.clear();
Jeff Brown50de30a2010-06-22 01:27:15 -0700411 int32_t injectionResult = mPolicy->waitForMotionEventTargets(& mReusableMotionEvent,
Jeff Brown51d45a72010-06-17 20:52:56 -0700412 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Browne839a582010-04-22 18:58:52 -0700413 mCurrentInputTargets);
414
Jeff Brown54bc2812010-06-15 01:31:58 -0700415 mLock.lock();
416 mCurrentInputTargetsValid = true;
417
Jeff Brown51d45a72010-06-17 20:52:56 -0700418 setInjectionResultLocked(entry, injectionResult);
419
Jeff Brown50de30a2010-06-22 01:27:15 -0700420 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
421 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
422 }
Jeff Browne839a582010-04-22 18:58:52 -0700423}
424
425void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
426 EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
427#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700428 LOGD("dispatchEventToCurrentInputTargets - "
Jeff Browne839a582010-04-22 18:58:52 -0700429 "resumeWithAppendedMotionSample=%s",
430 resumeWithAppendedMotionSample ? "true" : "false");
431#endif
432
Jeff Brown54bc2812010-06-15 01:31:58 -0700433 assert(eventEntry->dispatchInProgress); // should already have been set to true
434
Jeff Browne839a582010-04-22 18:58:52 -0700435 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
436 const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
437
438 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(
439 inputTarget.inputChannel->getReceivePipeFd());
440 if (connectionIndex >= 0) {
441 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown51d45a72010-06-17 20:52:56 -0700442 prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
Jeff Browne839a582010-04-22 18:58:52 -0700443 resumeWithAppendedMotionSample);
444 } else {
445 LOGW("Framework requested delivery of an input event to channel '%s' but it "
446 "is not registered with the input dispatcher.",
447 inputTarget.inputChannel->getName().string());
448 }
449 }
450}
451
Jeff Brown51d45a72010-06-17 20:52:56 -0700452void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
453 const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
Jeff Browne839a582010-04-22 18:58:52 -0700454 bool resumeWithAppendedMotionSample) {
455#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700456 LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, timeout=%lldns, "
Jeff Browne839a582010-04-22 18:58:52 -0700457 "xOffset=%f, yOffset=%f, resumeWithAppendedMotionSample=%s",
458 connection->getInputChannelName(), inputTarget->flags, inputTarget->timeout,
459 inputTarget->xOffset, inputTarget->yOffset,
460 resumeWithAppendedMotionSample ? "true" : "false");
461#endif
462
463 // Skip this event if the connection status is not normal.
464 // We don't want to queue outbound events at all if the connection is broken or
465 // not responding.
466 if (connection->status != Connection::STATUS_NORMAL) {
467 LOGV("channel '%s' ~ Dropping event because the channel status is %s",
Jeff Brown54bc2812010-06-15 01:31:58 -0700468 connection->getStatusLabel());
Jeff Browne839a582010-04-22 18:58:52 -0700469 return;
470 }
471
472 // Resume the dispatch cycle with a freshly appended motion sample.
473 // First we check that the last dispatch entry in the outbound queue is for the same
474 // motion event to which we appended the motion sample. If we find such a dispatch
475 // entry, and if it is currently in progress then we try to stream the new sample.
476 bool wasEmpty = connection->outboundQueue.isEmpty();
477
478 if (! wasEmpty && resumeWithAppendedMotionSample) {
479 DispatchEntry* motionEventDispatchEntry =
480 connection->findQueuedDispatchEntryForEvent(eventEntry);
481 if (motionEventDispatchEntry) {
482 // If the dispatch entry is not in progress, then we must be busy dispatching an
483 // earlier event. Not a problem, the motion event is on the outbound queue and will
484 // be dispatched later.
485 if (! motionEventDispatchEntry->inProgress) {
486#if DEBUG_BATCHING
487 LOGD("channel '%s' ~ Not streaming because the motion event has "
488 "not yet been dispatched. "
489 "(Waiting for earlier events to be consumed.)",
490 connection->getInputChannelName());
491#endif
492 return;
493 }
494
495 // If the dispatch entry is in progress but it already has a tail of pending
496 // motion samples, then it must mean that the shared memory buffer filled up.
497 // Not a problem, when this dispatch cycle is finished, we will eventually start
498 // a new dispatch cycle to process the tail and that tail includes the newly
499 // appended motion sample.
500 if (motionEventDispatchEntry->tailMotionSample) {
501#if DEBUG_BATCHING
502 LOGD("channel '%s' ~ Not streaming because no new samples can "
503 "be appended to the motion event in this dispatch cycle. "
504 "(Waiting for next dispatch cycle to start.)",
505 connection->getInputChannelName());
506#endif
507 return;
508 }
509
510 // The dispatch entry is in progress and is still potentially open for streaming.
511 // Try to stream the new motion sample. This might fail if the consumer has already
512 // consumed the motion event (or if the channel is broken).
513 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
514 status_t status = connection->inputPublisher.appendMotionSample(
515 appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
516 if (status == OK) {
517#if DEBUG_BATCHING
518 LOGD("channel '%s' ~ Successfully streamed new motion sample.",
519 connection->getInputChannelName());
520#endif
521 return;
522 }
523
524#if DEBUG_BATCHING
525 if (status == NO_MEMORY) {
526 LOGD("channel '%s' ~ Could not append motion sample to currently "
527 "dispatched move event because the shared memory buffer is full. "
528 "(Waiting for next dispatch cycle to start.)",
529 connection->getInputChannelName());
530 } else if (status == status_t(FAILED_TRANSACTION)) {
531 LOGD("channel '%s' ~ Could not append motion sample to currently "
Jeff Brown50de30a2010-06-22 01:27:15 -0700532 "dispatched move event because the event has already been consumed. "
Jeff Browne839a582010-04-22 18:58:52 -0700533 "(Waiting for next dispatch cycle to start.)",
534 connection->getInputChannelName());
535 } else {
536 LOGD("channel '%s' ~ Could not append motion sample to currently "
537 "dispatched move event due to an error, status=%d. "
538 "(Waiting for next dispatch cycle to start.)",
539 connection->getInputChannelName(), status);
540 }
541#endif
542 // Failed to stream. Start a new tail of pending motion samples to dispatch
543 // in the next cycle.
544 motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
545 return;
546 }
547 }
548
549 // This is a new event.
550 // Enqueue a new dispatch entry onto the outbound queue for this connection.
551 DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry); // increments ref
552 dispatchEntry->targetFlags = inputTarget->flags;
553 dispatchEntry->xOffset = inputTarget->xOffset;
554 dispatchEntry->yOffset = inputTarget->yOffset;
555 dispatchEntry->timeout = inputTarget->timeout;
556 dispatchEntry->inProgress = false;
557 dispatchEntry->headMotionSample = NULL;
558 dispatchEntry->tailMotionSample = NULL;
559
560 // Handle the case where we could not stream a new motion sample because the consumer has
561 // already consumed the motion event (otherwise the corresponding dispatch entry would
562 // still be in the outbound queue for this connection). We set the head motion sample
563 // to the list starting with the newly appended motion sample.
564 if (resumeWithAppendedMotionSample) {
565#if DEBUG_BATCHING
566 LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
567 "that cannot be streamed because the motion event has already been consumed.",
568 connection->getInputChannelName());
569#endif
570 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
571 dispatchEntry->headMotionSample = appendedMotionSample;
572 }
573
574 // Enqueue the dispatch entry.
575 connection->outboundQueue.enqueueAtTail(dispatchEntry);
576
577 // If the outbound queue was previously empty, start the dispatch cycle going.
578 if (wasEmpty) {
Jeff Brown51d45a72010-06-17 20:52:56 -0700579 activateConnectionLocked(connection.get());
Jeff Browne839a582010-04-22 18:58:52 -0700580 startDispatchCycleLocked(currentTime, connection);
581 }
582}
583
Jeff Brown51d45a72010-06-17 20:52:56 -0700584void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
585 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -0700586#if DEBUG_DISPATCH_CYCLE
587 LOGD("channel '%s' ~ startDispatchCycle",
588 connection->getInputChannelName());
589#endif
590
591 assert(connection->status == Connection::STATUS_NORMAL);
592 assert(! connection->outboundQueue.isEmpty());
593
594 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
595 assert(! dispatchEntry->inProgress);
596
597 // TODO throttle successive ACTION_MOVE motion events for the same device
598 // possible implementation could set a brief poll timeout here and resume starting the
599 // dispatch cycle when elapsed
600
601 // Publish the event.
602 status_t status;
603 switch (dispatchEntry->eventEntry->type) {
604 case EventEntry::TYPE_KEY: {
605 KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
606
607 // Apply target flags.
608 int32_t action = keyEntry->action;
609 int32_t flags = keyEntry->flags;
610 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
611 flags |= KEY_EVENT_FLAG_CANCELED;
612 }
613
614 // Publish the key event.
615 status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->nature,
616 action, flags, keyEntry->keyCode, keyEntry->scanCode,
617 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
618 keyEntry->eventTime);
619
620 if (status) {
621 LOGE("channel '%s' ~ Could not publish key event, "
622 "status=%d", connection->getInputChannelName(), status);
623 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
624 return;
625 }
626 break;
627 }
628
629 case EventEntry::TYPE_MOTION: {
630 MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
631
632 // Apply target flags.
633 int32_t action = motionEntry->action;
634 if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
635 action = MOTION_EVENT_ACTION_OUTSIDE;
636 }
637 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
638 action = MOTION_EVENT_ACTION_CANCEL;
639 }
640
641 // If headMotionSample is non-NULL, then it points to the first new sample that we
642 // were unable to dispatch during the previous cycle so we resume dispatching from
643 // that point in the list of motion samples.
644 // Otherwise, we just start from the first sample of the motion event.
645 MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
646 if (! firstMotionSample) {
647 firstMotionSample = & motionEntry->firstSample;
648 }
649
650 // Publish the motion event and the first motion sample.
651 status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
652 motionEntry->nature, action, motionEntry->edgeFlags, motionEntry->metaState,
653 dispatchEntry->xOffset, dispatchEntry->yOffset,
654 motionEntry->xPrecision, motionEntry->yPrecision,
655 motionEntry->downTime, firstMotionSample->eventTime,
656 motionEntry->pointerCount, motionEntry->pointerIds,
657 firstMotionSample->pointerCoords);
658
659 if (status) {
660 LOGE("channel '%s' ~ Could not publish motion event, "
661 "status=%d", connection->getInputChannelName(), status);
662 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
663 return;
664 }
665
666 // Append additional motion samples.
667 MotionSample* nextMotionSample = firstMotionSample->next;
668 for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
669 status = connection->inputPublisher.appendMotionSample(
670 nextMotionSample->eventTime, nextMotionSample->pointerCoords);
671 if (status == NO_MEMORY) {
672#if DEBUG_DISPATCH_CYCLE
673 LOGD("channel '%s' ~ Shared memory buffer full. Some motion samples will "
674 "be sent in the next dispatch cycle.",
675 connection->getInputChannelName());
676#endif
677 break;
678 }
679 if (status != OK) {
680 LOGE("channel '%s' ~ Could not append motion sample "
681 "for a reason other than out of memory, status=%d",
682 connection->getInputChannelName(), status);
683 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
684 return;
685 }
686 }
687
688 // Remember the next motion sample that we could not dispatch, in case we ran out
689 // of space in the shared memory buffer.
690 dispatchEntry->tailMotionSample = nextMotionSample;
691 break;
692 }
693
694 default: {
695 assert(false);
696 }
697 }
698
699 // Send the dispatch signal.
700 status = connection->inputPublisher.sendDispatchSignal();
701 if (status) {
702 LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
703 connection->getInputChannelName(), status);
704 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
705 return;
706 }
707
708 // Record information about the newly started dispatch cycle.
709 dispatchEntry->inProgress = true;
710
711 connection->lastEventTime = dispatchEntry->eventEntry->eventTime;
712 connection->lastDispatchTime = currentTime;
713
714 nsecs_t timeout = dispatchEntry->timeout;
Jeff Brown51d45a72010-06-17 20:52:56 -0700715 connection->setNextTimeoutTime(currentTime, timeout);
Jeff Browne839a582010-04-22 18:58:52 -0700716
717 // Notify other system components.
718 onDispatchCycleStartedLocked(currentTime, connection);
719}
720
Jeff Brown51d45a72010-06-17 20:52:56 -0700721void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
722 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -0700723#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700724 LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
Jeff Browne839a582010-04-22 18:58:52 -0700725 "%01.1fms since dispatch",
726 connection->getInputChannelName(),
727 connection->getEventLatencyMillis(currentTime),
728 connection->getDispatchLatencyMillis(currentTime));
729#endif
730
Jeff Brown54bc2812010-06-15 01:31:58 -0700731 if (connection->status == Connection::STATUS_BROKEN
732 || connection->status == Connection::STATUS_ZOMBIE) {
Jeff Browne839a582010-04-22 18:58:52 -0700733 return;
734 }
735
736 // Clear the pending timeout.
737 connection->nextTimeoutTime = LONG_LONG_MAX;
738
739 if (connection->status == Connection::STATUS_NOT_RESPONDING) {
740 // Recovering from an ANR.
741 connection->status = Connection::STATUS_NORMAL;
742
743 // Notify other system components.
744 onDispatchCycleFinishedLocked(currentTime, connection, true /*recoveredFromANR*/);
745 } else {
746 // Normal finish. Not much to do here.
747
748 // Notify other system components.
749 onDispatchCycleFinishedLocked(currentTime, connection, false /*recoveredFromANR*/);
750 }
751
752 // Reset the publisher since the event has been consumed.
753 // We do this now so that the publisher can release some of its internal resources
754 // while waiting for the next dispatch cycle to begin.
755 status_t status = connection->inputPublisher.reset();
756 if (status) {
757 LOGE("channel '%s' ~ Could not reset publisher, status=%d",
758 connection->getInputChannelName(), status);
759 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
760 return;
761 }
762
763 // Start the next dispatch cycle for this connection.
764 while (! connection->outboundQueue.isEmpty()) {
765 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
766 if (dispatchEntry->inProgress) {
767 // Finish or resume current event in progress.
768 if (dispatchEntry->tailMotionSample) {
769 // We have a tail of undispatched motion samples.
770 // Reuse the same DispatchEntry and start a new cycle.
771 dispatchEntry->inProgress = false;
772 dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
773 dispatchEntry->tailMotionSample = NULL;
774 startDispatchCycleLocked(currentTime, connection);
775 return;
776 }
777 // Finished.
778 connection->outboundQueue.dequeueAtHead();
779 mAllocator.releaseDispatchEntry(dispatchEntry);
780 } else {
781 // If the head is not in progress, then we must have already dequeued the in
782 // progress event, which means we actually aborted it (due to ANR).
783 // So just start the next event for this connection.
784 startDispatchCycleLocked(currentTime, connection);
785 return;
786 }
787 }
788
789 // Outbound queue is empty, deactivate the connection.
Jeff Brown51d45a72010-06-17 20:52:56 -0700790 deactivateConnectionLocked(connection.get());
Jeff Browne839a582010-04-22 18:58:52 -0700791}
792
Jeff Brown51d45a72010-06-17 20:52:56 -0700793void InputDispatcher::timeoutDispatchCycleLocked(nsecs_t currentTime,
794 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -0700795#if DEBUG_DISPATCH_CYCLE
796 LOGD("channel '%s' ~ timeoutDispatchCycle",
797 connection->getInputChannelName());
798#endif
799
800 if (connection->status != Connection::STATUS_NORMAL) {
Jeff Brown51d45a72010-06-17 20:52:56 -0700801 return;
Jeff Browne839a582010-04-22 18:58:52 -0700802 }
803
804 // Enter the not responding state.
805 connection->status = Connection::STATUS_NOT_RESPONDING;
806 connection->lastANRTime = currentTime;
Jeff Browne839a582010-04-22 18:58:52 -0700807
808 // Notify other system components.
Jeff Brown51d45a72010-06-17 20:52:56 -0700809 // This enqueues a command which will eventually either call
810 // resumeAfterTimeoutDispatchCycleLocked or abortDispatchCycleLocked.
Jeff Browne839a582010-04-22 18:58:52 -0700811 onDispatchCycleANRLocked(currentTime, connection);
Jeff Browne839a582010-04-22 18:58:52 -0700812}
813
Jeff Brown51d45a72010-06-17 20:52:56 -0700814void InputDispatcher::resumeAfterTimeoutDispatchCycleLocked(nsecs_t currentTime,
815 const sp<Connection>& connection, nsecs_t newTimeout) {
816#if DEBUG_DISPATCH_CYCLE
817 LOGD("channel '%s' ~ resumeAfterTimeoutDispatchCycleLocked",
818 connection->getInputChannelName());
819#endif
820
821 if (connection->status != Connection::STATUS_NOT_RESPONDING) {
822 return;
823 }
824
825 // Resume normal dispatch.
826 connection->status = Connection::STATUS_NORMAL;
827 connection->setNextTimeoutTime(currentTime, newTimeout);
828}
829
830void InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime,
831 const sp<Connection>& connection, bool broken) {
Jeff Browne839a582010-04-22 18:58:52 -0700832#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700833 LOGD("channel '%s' ~ abortDispatchCycle - broken=%s",
Jeff Browne839a582010-04-22 18:58:52 -0700834 connection->getInputChannelName(), broken ? "true" : "false");
835#endif
836
Jeff Browne839a582010-04-22 18:58:52 -0700837 // Clear the pending timeout.
838 connection->nextTimeoutTime = LONG_LONG_MAX;
839
840 // Clear the outbound queue.
Jeff Brown51d45a72010-06-17 20:52:56 -0700841 if (! connection->outboundQueue.isEmpty()) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700842 do {
843 DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
844 mAllocator.releaseDispatchEntry(dispatchEntry);
845 } while (! connection->outboundQueue.isEmpty());
Jeff Browne839a582010-04-22 18:58:52 -0700846
Jeff Brown51d45a72010-06-17 20:52:56 -0700847 deactivateConnectionLocked(connection.get());
Jeff Brown54bc2812010-06-15 01:31:58 -0700848 }
Jeff Browne839a582010-04-22 18:58:52 -0700849
850 // Handle the case where the connection appears to be unrecoverably broken.
Jeff Brown54bc2812010-06-15 01:31:58 -0700851 // Ignore already broken or zombie connections.
Jeff Browne839a582010-04-22 18:58:52 -0700852 if (broken) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700853 if (connection->status == Connection::STATUS_NORMAL
854 || connection->status == Connection::STATUS_NOT_RESPONDING) {
855 connection->status = Connection::STATUS_BROKEN;
Jeff Browne839a582010-04-22 18:58:52 -0700856
Jeff Brown54bc2812010-06-15 01:31:58 -0700857 // Notify other system components.
858 onDispatchCycleBrokenLocked(currentTime, connection);
859 }
Jeff Browne839a582010-04-22 18:58:52 -0700860 }
Jeff Browne839a582010-04-22 18:58:52 -0700861}
862
863bool InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
864 InputDispatcher* d = static_cast<InputDispatcher*>(data);
865
866 { // acquire lock
867 AutoMutex _l(d->mLock);
868
869 ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
870 if (connectionIndex < 0) {
871 LOGE("Received spurious receive callback for unknown input channel. "
872 "fd=%d, events=0x%x", receiveFd, events);
873 return false; // remove the callback
874 }
875
Jeff Brown51d45a72010-06-17 20:52:56 -0700876 nsecs_t currentTime = now();
Jeff Browne839a582010-04-22 18:58:52 -0700877
878 sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
879 if (events & (POLLERR | POLLHUP | POLLNVAL)) {
880 LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
881 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brown51d45a72010-06-17 20:52:56 -0700882 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -0700883 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700884 return false; // remove the callback
885 }
886
887 if (! (events & POLLIN)) {
888 LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
889 "events=0x%x", connection->getInputChannelName(), events);
890 return true;
891 }
892
893 status_t status = connection->inputPublisher.receiveFinishedSignal();
894 if (status) {
895 LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
896 connection->getInputChannelName(), status);
Jeff Brown51d45a72010-06-17 20:52:56 -0700897 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -0700898 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700899 return false; // remove the callback
900 }
901
Jeff Brown51d45a72010-06-17 20:52:56 -0700902 d->finishDispatchCycleLocked(currentTime, connection);
Jeff Brown54bc2812010-06-15 01:31:58 -0700903 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700904 return true;
905 } // release lock
906}
907
Jeff Brown54bc2812010-06-15 01:31:58 -0700908void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
Jeff Browne839a582010-04-22 18:58:52 -0700909#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown54bc2812010-06-15 01:31:58 -0700910 LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
Jeff Browne839a582010-04-22 18:58:52 -0700911#endif
912
913 bool wasEmpty;
914 { // acquire lock
915 AutoMutex _l(mLock);
916
Jeff Brown51d45a72010-06-17 20:52:56 -0700917 ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
Jeff Browne839a582010-04-22 18:58:52 -0700918
919 wasEmpty = mInboundQueue.isEmpty();
920 mInboundQueue.enqueueAtTail(newEntry);
921 } // release lock
922
923 if (wasEmpty) {
924 mPollLoop->wake();
925 }
926}
927
Jeff Browne839a582010-04-22 18:58:52 -0700928void InputDispatcher::notifyAppSwitchComing(nsecs_t eventTime) {
929#if DEBUG_INBOUND_EVENT_DETAILS
930 LOGD("notifyAppSwitchComing - eventTime=%lld", eventTime);
931#endif
932
933 // Remove movement keys from the queue from most recent to least recent, stopping at the
934 // first non-movement key.
935 // TODO: Include a detailed description of why we do this...
936
937 { // acquire lock
938 AutoMutex _l(mLock);
939
940 for (EventEntry* entry = mInboundQueue.tail.prev; entry != & mInboundQueue.head; ) {
941 EventEntry* prev = entry->prev;
942
943 if (entry->type == EventEntry::TYPE_KEY) {
944 KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
945 if (isMovementKey(keyEntry->keyCode)) {
946 LOGV("Dropping movement key during app switch: keyCode=%d, action=%d",
947 keyEntry->keyCode, keyEntry->action);
948 mInboundQueue.dequeue(keyEntry);
Jeff Brown51d45a72010-06-17 20:52:56 -0700949
950 setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
951
Jeff Browne839a582010-04-22 18:58:52 -0700952 mAllocator.releaseKeyEntry(keyEntry);
953 } else {
954 // stop at last non-movement key
955 break;
956 }
957 }
958
959 entry = prev;
960 }
961 } // release lock
962}
963
964void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
965 uint32_t policyFlags, int32_t action, int32_t flags,
966 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
967#if DEBUG_INBOUND_EVENT_DETAILS
968 LOGD("notifyKey - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, action=0x%x, "
969 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
970 eventTime, deviceId, nature, policyFlags, action, flags,
971 keyCode, scanCode, metaState, downTime);
972#endif
973
974 bool wasEmpty;
975 { // acquire lock
976 AutoMutex _l(mLock);
977
Jeff Brown51d45a72010-06-17 20:52:56 -0700978 int32_t repeatCount = 0;
979 KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
980 deviceId, nature, policyFlags, action, flags, keyCode, scanCode,
981 metaState, repeatCount, downTime);
Jeff Browne839a582010-04-22 18:58:52 -0700982
983 wasEmpty = mInboundQueue.isEmpty();
984 mInboundQueue.enqueueAtTail(newEntry);
985 } // release lock
986
987 if (wasEmpty) {
988 mPollLoop->wake();
989 }
990}
991
992void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t nature,
993 uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
994 uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
995 float xPrecision, float yPrecision, nsecs_t downTime) {
996#if DEBUG_INBOUND_EVENT_DETAILS
997 LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, "
998 "action=0x%x, metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, "
999 "downTime=%lld",
1000 eventTime, deviceId, nature, policyFlags, action, metaState, edgeFlags,
1001 xPrecision, yPrecision, downTime);
1002 for (uint32_t i = 0; i < pointerCount; i++) {
1003 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
1004 i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
1005 pointerCoords[i].pressure, pointerCoords[i].size);
1006 }
1007#endif
1008
1009 bool wasEmpty;
1010 { // acquire lock
1011 AutoMutex _l(mLock);
1012
1013 // Attempt batching and streaming of move events.
1014 if (action == MOTION_EVENT_ACTION_MOVE) {
1015 // BATCHING CASE
1016 //
1017 // Try to append a move sample to the tail of the inbound queue for this device.
1018 // Give up if we encounter a non-move motion event for this device since that
1019 // means we cannot append any new samples until a new motion event has started.
1020 for (EventEntry* entry = mInboundQueue.tail.prev;
1021 entry != & mInboundQueue.head; entry = entry->prev) {
1022 if (entry->type != EventEntry::TYPE_MOTION) {
1023 // Keep looking for motion events.
1024 continue;
1025 }
1026
1027 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
1028 if (motionEntry->deviceId != deviceId) {
1029 // Keep looking for this device.
1030 continue;
1031 }
1032
1033 if (motionEntry->action != MOTION_EVENT_ACTION_MOVE
Jeff Brown51d45a72010-06-17 20:52:56 -07001034 || motionEntry->pointerCount != pointerCount
1035 || motionEntry->isInjected()) {
Jeff Browne839a582010-04-22 18:58:52 -07001036 // Last motion event in the queue for this device is not compatible for
1037 // appending new samples. Stop here.
1038 goto NoBatchingOrStreaming;
1039 }
1040
1041 // The last motion event is a move and is compatible for appending.
Jeff Brown54bc2812010-06-15 01:31:58 -07001042 // Do the batching magic.
Jeff Brown51d45a72010-06-17 20:52:56 -07001043 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
Jeff Browne839a582010-04-22 18:58:52 -07001044#if DEBUG_BATCHING
1045 LOGD("Appended motion sample onto batch for most recent "
1046 "motion event for this device in the inbound queue.");
1047#endif
Jeff Brown54bc2812010-06-15 01:31:58 -07001048
1049 // Sanity check for special case because dispatch is interruptible.
1050 // The dispatch logic is partially interruptible and releases its lock while
1051 // identifying targets. However, as soon as the targets have been identified,
1052 // the dispatcher proceeds to write a dispatch entry into all relevant outbound
1053 // queues and then promptly removes the motion entry from the queue.
1054 //
1055 // Consequently, we should never observe the case where the inbound queue contains
1056 // an in-progress motion entry unless the current input targets are invalid
1057 // (currently being computed). Check for this!
1058 assert(! (motionEntry->dispatchInProgress && mCurrentInputTargetsValid));
1059
1060 return; // done!
Jeff Browne839a582010-04-22 18:58:52 -07001061 }
1062
1063 // STREAMING CASE
1064 //
1065 // There is no pending motion event (of any kind) for this device in the inbound queue.
1066 // Search the outbound queues for a synchronously dispatched motion event for this
1067 // device. If found, then we append the new sample to that event and then try to
1068 // push it out to all current targets. It is possible that some targets will already
1069 // have consumed the motion event. This case is automatically handled by the
1070 // logic in prepareDispatchCycleLocked by tracking where resumption takes place.
1071 //
1072 // The reason we look for a synchronously dispatched motion event is because we
1073 // want to be sure that no other motion events have been dispatched since the move.
1074 // It's also convenient because it means that the input targets are still valid.
1075 // This code could be improved to support streaming of asynchronously dispatched
1076 // motion events (which might be significantly more efficient) but it may become
1077 // a little more complicated as a result.
1078 //
1079 // Note: This code crucially depends on the invariant that an outbound queue always
1080 // contains at most one synchronous event and it is always last (but it might
1081 // not be first!).
Jeff Brown54bc2812010-06-15 01:31:58 -07001082 if (mCurrentInputTargetsValid) {
1083 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1084 Connection* connection = mActiveConnections.itemAt(i);
1085 if (! connection->outboundQueue.isEmpty()) {
1086 DispatchEntry* dispatchEntry = connection->outboundQueue.tail.prev;
1087 if (dispatchEntry->targetFlags & InputTarget::FLAG_SYNC) {
1088 if (dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION) {
1089 goto NoBatchingOrStreaming;
1090 }
Jeff Browne839a582010-04-22 18:58:52 -07001091
Jeff Brown54bc2812010-06-15 01:31:58 -07001092 MotionEntry* syncedMotionEntry = static_cast<MotionEntry*>(
1093 dispatchEntry->eventEntry);
1094 if (syncedMotionEntry->action != MOTION_EVENT_ACTION_MOVE
1095 || syncedMotionEntry->deviceId != deviceId
Jeff Brown51d45a72010-06-17 20:52:56 -07001096 || syncedMotionEntry->pointerCount != pointerCount
1097 || syncedMotionEntry->isInjected()) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001098 goto NoBatchingOrStreaming;
1099 }
Jeff Browne839a582010-04-22 18:58:52 -07001100
Jeff Brown54bc2812010-06-15 01:31:58 -07001101 // Found synced move entry. Append sample and resume dispatch.
1102 mAllocator.appendMotionSample(syncedMotionEntry, eventTime,
Jeff Brown51d45a72010-06-17 20:52:56 -07001103 pointerCoords);
Jeff Brown54bc2812010-06-15 01:31:58 -07001104 #if DEBUG_BATCHING
1105 LOGD("Appended motion sample onto batch for most recent synchronously "
1106 "dispatched motion event for this device in the outbound queues.");
1107 #endif
Jeff Brown51d45a72010-06-17 20:52:56 -07001108 nsecs_t currentTime = now();
Jeff Brown54bc2812010-06-15 01:31:58 -07001109 dispatchEventToCurrentInputTargetsLocked(currentTime, syncedMotionEntry,
1110 true /*resumeWithAppendedMotionSample*/);
1111
1112 runCommandsLockedInterruptible();
1113 return; // done!
1114 }
Jeff Browne839a582010-04-22 18:58:52 -07001115 }
1116 }
1117 }
1118
1119NoBatchingOrStreaming:;
1120 }
1121
1122 // Just enqueue a new motion event.
Jeff Brown51d45a72010-06-17 20:52:56 -07001123 MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
1124 deviceId, nature, policyFlags, action, metaState, edgeFlags,
1125 xPrecision, yPrecision, downTime,
1126 pointerCount, pointerIds, pointerCoords);
Jeff Browne839a582010-04-22 18:58:52 -07001127
1128 wasEmpty = mInboundQueue.isEmpty();
1129 mInboundQueue.enqueueAtTail(newEntry);
1130 } // release lock
1131
1132 if (wasEmpty) {
1133 mPollLoop->wake();
1134 }
1135}
1136
Jeff Brown51d45a72010-06-17 20:52:56 -07001137int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
1138 int32_t injectorPid, int32_t injectorUid, bool sync, int32_t timeoutMillis) {
1139#if DEBUG_INBOUND_EVENT_DETAILS
1140 LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
1141 "sync=%d, timeoutMillis=%d",
1142 event->getType(), injectorPid, injectorUid, sync, timeoutMillis);
1143#endif
1144
1145 nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
1146
1147 EventEntry* injectedEntry;
1148 bool wasEmpty;
1149 { // acquire lock
1150 AutoMutex _l(mLock);
1151
1152 injectedEntry = createEntryFromInputEventLocked(event);
1153 injectedEntry->refCount += 1;
1154 injectedEntry->injectorPid = injectorPid;
1155 injectedEntry->injectorUid = injectorUid;
1156
1157 wasEmpty = mInboundQueue.isEmpty();
1158 mInboundQueue.enqueueAtTail(injectedEntry);
1159
1160 } // release lock
1161
1162 if (wasEmpty) {
1163 mPollLoop->wake();
1164 }
1165
1166 int32_t injectionResult;
1167 { // acquire lock
1168 AutoMutex _l(mLock);
1169
1170 for (;;) {
1171 injectionResult = injectedEntry->injectionResult;
1172 if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
1173 break;
1174 }
1175
1176 nsecs_t remainingTimeout = endTime - now();
1177 if (remainingTimeout <= 0) {
1178 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1179 sync = false;
1180 break;
1181 }
1182
1183 mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
1184 }
1185
1186 if (sync) {
1187 while (! isFullySynchronizedLocked()) {
1188 nsecs_t remainingTimeout = endTime - now();
1189 if (remainingTimeout <= 0) {
1190 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1191 break;
1192 }
1193
1194 mFullySynchronizedCondition.waitRelative(mLock, remainingTimeout);
1195 }
1196 }
1197
1198 mAllocator.releaseEventEntry(injectedEntry);
1199 } // release lock
1200
1201 return injectionResult;
1202}
1203
1204void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
1205 if (entry->isInjected()) {
1206#if DEBUG_INJECTION
1207 LOGD("Setting input event injection result to %d. "
1208 "injectorPid=%d, injectorUid=%d",
1209 injectionResult, entry->injectorPid, entry->injectorUid);
1210#endif
1211
1212 entry->injectionResult = injectionResult;
1213 mInjectionResultAvailableCondition.broadcast();
1214 }
1215}
1216
1217bool InputDispatcher::isFullySynchronizedLocked() {
1218 return mInboundQueue.isEmpty() && mActiveConnections.isEmpty();
1219}
1220
1221InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked(
1222 const InputEvent* event) {
1223 switch (event->getType()) {
1224 case INPUT_EVENT_TYPE_KEY: {
1225 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
1226 uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
1227
1228 KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
1229 keyEvent->getDeviceId(), keyEvent->getNature(), policyFlags,
1230 keyEvent->getAction(), keyEvent->getFlags(),
1231 keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
1232 keyEvent->getRepeatCount(), keyEvent->getDownTime());
1233 return keyEntry;
1234 }
1235
1236 case INPUT_EVENT_TYPE_MOTION: {
1237 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
1238 uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
1239
1240 const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
1241 const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
1242 size_t pointerCount = motionEvent->getPointerCount();
1243
1244 MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
1245 motionEvent->getDeviceId(), motionEvent->getNature(), policyFlags,
1246 motionEvent->getAction(), motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
1247 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
1248 motionEvent->getDownTime(), uint32_t(pointerCount),
1249 motionEvent->getPointerIds(), samplePointerCoords);
1250 for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
1251 sampleEventTimes += 1;
1252 samplePointerCoords += pointerCount;
1253 mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
1254 }
1255 return motionEntry;
1256 }
1257
1258 default:
1259 assert(false);
1260 return NULL;
1261 }
1262}
1263
Jeff Browne839a582010-04-22 18:58:52 -07001264void InputDispatcher::resetKeyRepeatLocked() {
1265 if (mKeyRepeatState.lastKeyEntry) {
1266 mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
1267 mKeyRepeatState.lastKeyEntry = NULL;
1268 }
1269}
1270
Jeff Brown50de30a2010-06-22 01:27:15 -07001271void InputDispatcher::preemptInputDispatch() {
1272#if DEBUG_DISPATCH_CYCLE
1273 LOGD("preemptInputDispatch");
1274#endif
1275
1276 bool preemptedOne = false;
1277 { // acquire lock
1278 AutoMutex _l(mLock);
1279
1280 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1281 Connection* connection = mActiveConnections[i];
1282 if (connection->hasPendingSyncTarget()) {
1283#if DEBUG_DISPATCH_CYCLE
1284 LOGD("channel '%s' ~ Preempted pending synchronous dispatch",
1285 connection->getInputChannelName());
1286#endif
1287 connection->outboundQueue.tail.prev->targetFlags &= ~ InputTarget::FLAG_SYNC;
1288 preemptedOne = true;
1289 }
1290 }
1291 } // release lock
1292
1293 if (preemptedOne) {
1294 // Wake up the poll loop so it can get a head start dispatching the next event.
1295 mPollLoop->wake();
1296 }
1297}
1298
Jeff Browne839a582010-04-22 18:58:52 -07001299status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001300#if DEBUG_REGISTRATION
Jeff Brown50de30a2010-06-22 01:27:15 -07001301 LOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().string());
Jeff Brown54bc2812010-06-15 01:31:58 -07001302#endif
1303
Jeff Browne839a582010-04-22 18:58:52 -07001304 int receiveFd;
1305 { // acquire lock
1306 AutoMutex _l(mLock);
1307
1308 receiveFd = inputChannel->getReceivePipeFd();
1309 if (mConnectionsByReceiveFd.indexOfKey(receiveFd) >= 0) {
1310 LOGW("Attempted to register already registered input channel '%s'",
1311 inputChannel->getName().string());
1312 return BAD_VALUE;
1313 }
1314
1315 sp<Connection> connection = new Connection(inputChannel);
1316 status_t status = connection->initialize();
1317 if (status) {
1318 LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
1319 inputChannel->getName().string(), status);
1320 return status;
1321 }
1322
1323 mConnectionsByReceiveFd.add(receiveFd, connection);
Jeff Brown54bc2812010-06-15 01:31:58 -07001324
1325 runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07001326 } // release lock
1327
1328 mPollLoop->setCallback(receiveFd, POLLIN, handleReceiveCallback, this);
1329 return OK;
1330}
1331
1332status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001333#if DEBUG_REGISTRATION
Jeff Brown50de30a2010-06-22 01:27:15 -07001334 LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
Jeff Brown54bc2812010-06-15 01:31:58 -07001335#endif
1336
Jeff Browne839a582010-04-22 18:58:52 -07001337 int32_t receiveFd;
1338 { // acquire lock
1339 AutoMutex _l(mLock);
1340
1341 receiveFd = inputChannel->getReceivePipeFd();
1342 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(receiveFd);
1343 if (connectionIndex < 0) {
1344 LOGW("Attempted to unregister already unregistered input channel '%s'",
1345 inputChannel->getName().string());
1346 return BAD_VALUE;
1347 }
1348
1349 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1350 mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
1351
1352 connection->status = Connection::STATUS_ZOMBIE;
1353
Jeff Brown51d45a72010-06-17 20:52:56 -07001354 nsecs_t currentTime = now();
1355 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -07001356
1357 runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07001358 } // release lock
1359
1360 mPollLoop->removeCallback(receiveFd);
1361
1362 // Wake the poll loop because removing the connection may have changed the current
1363 // synchronization state.
1364 mPollLoop->wake();
1365 return OK;
1366}
1367
1368void InputDispatcher::activateConnectionLocked(Connection* connection) {
1369 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1370 if (mActiveConnections.itemAt(i) == connection) {
1371 return;
1372 }
1373 }
1374 mActiveConnections.add(connection);
1375}
1376
1377void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
1378 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1379 if (mActiveConnections.itemAt(i) == connection) {
1380 mActiveConnections.removeAt(i);
1381 return;
1382 }
1383 }
1384}
1385
Jeff Brown54bc2812010-06-15 01:31:58 -07001386void InputDispatcher::onDispatchCycleStartedLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001387 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001388}
1389
Jeff Brown54bc2812010-06-15 01:31:58 -07001390void InputDispatcher::onDispatchCycleFinishedLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001391 nsecs_t currentTime, const sp<Connection>& connection, bool recoveredFromANR) {
Jeff Browne839a582010-04-22 18:58:52 -07001392 if (recoveredFromANR) {
1393 LOGI("channel '%s' ~ Recovered from ANR. %01.1fms since event, "
1394 "%01.1fms since dispatch, %01.1fms since ANR",
1395 connection->getInputChannelName(),
1396 connection->getEventLatencyMillis(currentTime),
1397 connection->getDispatchLatencyMillis(currentTime),
1398 connection->getANRLatencyMillis(currentTime));
1399
Jeff Brown54bc2812010-06-15 01:31:58 -07001400 CommandEntry* commandEntry = postCommandLocked(
1401 & InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07001402 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07001403 }
1404}
1405
Jeff Brown54bc2812010-06-15 01:31:58 -07001406void InputDispatcher::onDispatchCycleANRLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001407 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001408 LOGI("channel '%s' ~ Not responding! %01.1fms since event, %01.1fms since dispatch",
1409 connection->getInputChannelName(),
1410 connection->getEventLatencyMillis(currentTime),
1411 connection->getDispatchLatencyMillis(currentTime));
1412
Jeff Brown54bc2812010-06-15 01:31:58 -07001413 CommandEntry* commandEntry = postCommandLocked(
1414 & InputDispatcher::doNotifyInputChannelANRLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07001415 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07001416}
1417
Jeff Brown54bc2812010-06-15 01:31:58 -07001418void InputDispatcher::onDispatchCycleBrokenLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001419 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001420 LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
1421 connection->getInputChannelName());
1422
Jeff Brown54bc2812010-06-15 01:31:58 -07001423 CommandEntry* commandEntry = postCommandLocked(
1424 & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07001425 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07001426}
1427
Jeff Brown54bc2812010-06-15 01:31:58 -07001428void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
1429 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001430 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07001431
Jeff Brown51d45a72010-06-17 20:52:56 -07001432 if (connection->status != Connection::STATUS_ZOMBIE) {
1433 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07001434
Jeff Brown51d45a72010-06-17 20:52:56 -07001435 mPolicy->notifyInputChannelBroken(connection->inputChannel);
1436
1437 mLock.lock();
1438 }
Jeff Brown54bc2812010-06-15 01:31:58 -07001439}
1440
1441void InputDispatcher::doNotifyInputChannelANRLockedInterruptible(
1442 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001443 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07001444
Jeff Brown51d45a72010-06-17 20:52:56 -07001445 if (connection->status != Connection::STATUS_ZOMBIE) {
1446 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07001447
Jeff Brown51d45a72010-06-17 20:52:56 -07001448 nsecs_t newTimeout;
1449 bool resume = mPolicy->notifyInputChannelANR(connection->inputChannel, newTimeout);
1450
1451 mLock.lock();
1452
1453 nsecs_t currentTime = now();
1454 if (resume) {
1455 resumeAfterTimeoutDispatchCycleLocked(currentTime, connection, newTimeout);
1456 } else {
1457 abortDispatchCycleLocked(currentTime, connection, false /*(not) broken*/);
1458 }
1459 }
Jeff Brown54bc2812010-06-15 01:31:58 -07001460}
1461
1462void InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible(
1463 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001464 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07001465
Jeff Brown51d45a72010-06-17 20:52:56 -07001466 if (connection->status != Connection::STATUS_ZOMBIE) {
1467 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07001468
Jeff Brown51d45a72010-06-17 20:52:56 -07001469 mPolicy->notifyInputChannelRecoveredFromANR(connection->inputChannel);
1470
1471 mLock.lock();
1472 }
Jeff Brown54bc2812010-06-15 01:31:58 -07001473}
1474
1475
Jeff Browne839a582010-04-22 18:58:52 -07001476// --- InputDispatcher::Allocator ---
1477
1478InputDispatcher::Allocator::Allocator() {
1479}
1480
Jeff Brown51d45a72010-06-17 20:52:56 -07001481void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
1482 nsecs_t eventTime) {
1483 entry->type = type;
1484 entry->refCount = 1;
1485 entry->dispatchInProgress = false;
Christopher Tated974e002010-06-23 16:50:30 -07001486 entry->eventTime = eventTime;
Jeff Brown51d45a72010-06-17 20:52:56 -07001487 entry->injectionResult = INPUT_EVENT_INJECTION_PENDING;
1488 entry->injectorPid = -1;
1489 entry->injectorUid = -1;
1490}
1491
Jeff Browne839a582010-04-22 18:58:52 -07001492InputDispatcher::ConfigurationChangedEntry*
Jeff Brown51d45a72010-06-17 20:52:56 -07001493InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
Jeff Browne839a582010-04-22 18:58:52 -07001494 ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07001495 initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime);
Jeff Browne839a582010-04-22 18:58:52 -07001496 return entry;
1497}
1498
Jeff Brown51d45a72010-06-17 20:52:56 -07001499InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
1500 int32_t deviceId, int32_t nature, uint32_t policyFlags, int32_t action,
1501 int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
1502 int32_t repeatCount, nsecs_t downTime) {
Jeff Browne839a582010-04-22 18:58:52 -07001503 KeyEntry* entry = mKeyEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07001504 initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime);
1505
1506 entry->deviceId = deviceId;
1507 entry->nature = nature;
1508 entry->policyFlags = policyFlags;
1509 entry->action = action;
1510 entry->flags = flags;
1511 entry->keyCode = keyCode;
1512 entry->scanCode = scanCode;
1513 entry->metaState = metaState;
1514 entry->repeatCount = repeatCount;
1515 entry->downTime = downTime;
Jeff Browne839a582010-04-22 18:58:52 -07001516 return entry;
1517}
1518
Jeff Brown51d45a72010-06-17 20:52:56 -07001519InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
1520 int32_t deviceId, int32_t nature, uint32_t policyFlags, int32_t action,
1521 int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
1522 nsecs_t downTime, uint32_t pointerCount,
1523 const int32_t* pointerIds, const PointerCoords* pointerCoords) {
Jeff Browne839a582010-04-22 18:58:52 -07001524 MotionEntry* entry = mMotionEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07001525 initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime);
1526
1527 entry->eventTime = eventTime;
1528 entry->deviceId = deviceId;
1529 entry->nature = nature;
1530 entry->policyFlags = policyFlags;
1531 entry->action = action;
1532 entry->metaState = metaState;
1533 entry->edgeFlags = edgeFlags;
1534 entry->xPrecision = xPrecision;
1535 entry->yPrecision = yPrecision;
1536 entry->downTime = downTime;
1537 entry->pointerCount = pointerCount;
1538 entry->firstSample.eventTime = eventTime;
Jeff Browne839a582010-04-22 18:58:52 -07001539 entry->firstSample.next = NULL;
Jeff Brown51d45a72010-06-17 20:52:56 -07001540 entry->lastSample = & entry->firstSample;
1541 for (uint32_t i = 0; i < pointerCount; i++) {
1542 entry->pointerIds[i] = pointerIds[i];
1543 entry->firstSample.pointerCoords[i] = pointerCoords[i];
1544 }
Jeff Browne839a582010-04-22 18:58:52 -07001545 return entry;
1546}
1547
1548InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
1549 EventEntry* eventEntry) {
1550 DispatchEntry* entry = mDispatchEntryPool.alloc();
1551 entry->eventEntry = eventEntry;
1552 eventEntry->refCount += 1;
1553 return entry;
1554}
1555
Jeff Brown54bc2812010-06-15 01:31:58 -07001556InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
1557 CommandEntry* entry = mCommandEntryPool.alloc();
1558 entry->command = command;
1559 return entry;
1560}
1561
Jeff Browne839a582010-04-22 18:58:52 -07001562void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
1563 switch (entry->type) {
1564 case EventEntry::TYPE_CONFIGURATION_CHANGED:
1565 releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
1566 break;
1567 case EventEntry::TYPE_KEY:
1568 releaseKeyEntry(static_cast<KeyEntry*>(entry));
1569 break;
1570 case EventEntry::TYPE_MOTION:
1571 releaseMotionEntry(static_cast<MotionEntry*>(entry));
1572 break;
1573 default:
1574 assert(false);
1575 break;
1576 }
1577}
1578
1579void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
1580 ConfigurationChangedEntry* entry) {
1581 entry->refCount -= 1;
1582 if (entry->refCount == 0) {
1583 mConfigurationChangeEntryPool.free(entry);
1584 } else {
1585 assert(entry->refCount > 0);
1586 }
1587}
1588
1589void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
1590 entry->refCount -= 1;
1591 if (entry->refCount == 0) {
1592 mKeyEntryPool.free(entry);
1593 } else {
1594 assert(entry->refCount > 0);
1595 }
1596}
1597
1598void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
1599 entry->refCount -= 1;
1600 if (entry->refCount == 0) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001601 for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
1602 MotionSample* next = sample->next;
1603 mMotionSamplePool.free(sample);
1604 sample = next;
1605 }
Jeff Browne839a582010-04-22 18:58:52 -07001606 mMotionEntryPool.free(entry);
1607 } else {
1608 assert(entry->refCount > 0);
1609 }
1610}
1611
1612void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
1613 releaseEventEntry(entry->eventEntry);
1614 mDispatchEntryPool.free(entry);
1615}
1616
Jeff Brown54bc2812010-06-15 01:31:58 -07001617void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
1618 mCommandEntryPool.free(entry);
1619}
1620
Jeff Browne839a582010-04-22 18:58:52 -07001621void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
Jeff Brown51d45a72010-06-17 20:52:56 -07001622 nsecs_t eventTime, const PointerCoords* pointerCoords) {
Jeff Browne839a582010-04-22 18:58:52 -07001623 MotionSample* sample = mMotionSamplePool.alloc();
1624 sample->eventTime = eventTime;
Jeff Brown51d45a72010-06-17 20:52:56 -07001625 uint32_t pointerCount = motionEntry->pointerCount;
1626 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Browne839a582010-04-22 18:58:52 -07001627 sample->pointerCoords[i] = pointerCoords[i];
1628 }
1629
1630 sample->next = NULL;
1631 motionEntry->lastSample->next = sample;
1632 motionEntry->lastSample = sample;
1633}
1634
Jeff Browne839a582010-04-22 18:58:52 -07001635// --- InputDispatcher::Connection ---
1636
1637InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
1638 status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
1639 nextTimeoutTime(LONG_LONG_MAX),
1640 lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX),
1641 lastANRTime(LONG_LONG_MAX) {
1642}
1643
1644InputDispatcher::Connection::~Connection() {
1645}
1646
1647status_t InputDispatcher::Connection::initialize() {
1648 return inputPublisher.initialize();
1649}
1650
Jeff Brown51d45a72010-06-17 20:52:56 -07001651void InputDispatcher::Connection::setNextTimeoutTime(nsecs_t currentTime, nsecs_t timeout) {
1652 nextTimeoutTime = (timeout >= 0) ? currentTime + timeout : LONG_LONG_MAX;
1653}
1654
Jeff Brown54bc2812010-06-15 01:31:58 -07001655const char* InputDispatcher::Connection::getStatusLabel() const {
1656 switch (status) {
1657 case STATUS_NORMAL:
1658 return "NORMAL";
1659
1660 case STATUS_BROKEN:
1661 return "BROKEN";
1662
1663 case STATUS_NOT_RESPONDING:
1664 return "NOT_RESPONDING";
1665
1666 case STATUS_ZOMBIE:
1667 return "ZOMBIE";
1668
1669 default:
1670 return "UNKNOWN";
1671 }
1672}
1673
Jeff Browne839a582010-04-22 18:58:52 -07001674InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
1675 const EventEntry* eventEntry) const {
1676 for (DispatchEntry* dispatchEntry = outboundQueue.tail.prev;
1677 dispatchEntry != & outboundQueue.head; dispatchEntry = dispatchEntry->prev) {
1678 if (dispatchEntry->eventEntry == eventEntry) {
1679 return dispatchEntry;
1680 }
1681 }
1682 return NULL;
1683}
1684
Jeff Brown54bc2812010-06-15 01:31:58 -07001685// --- InputDispatcher::CommandEntry ---
1686
1687InputDispatcher::CommandEntry::CommandEntry() {
1688}
1689
1690InputDispatcher::CommandEntry::~CommandEntry() {
1691}
1692
Jeff Browne839a582010-04-22 18:58:52 -07001693
1694// --- InputDispatcherThread ---
1695
1696InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
1697 Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
1698}
1699
1700InputDispatcherThread::~InputDispatcherThread() {
1701}
1702
1703bool InputDispatcherThread::threadLoop() {
1704 mDispatcher->dispatchOnce();
1705 return true;
1706}
1707
1708} // namespace android