blob: b53f140f63fef787e8ec1393fed5306cffd239db [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) {
Jeff Brown8575a872010-06-30 16:10:35 -070043 return keyCode == AKEYCODE_DPAD_UP
44 || keyCode == AKEYCODE_DPAD_DOWN
45 || keyCode == AKEYCODE_DPAD_LEFT
46 || keyCode == AKEYCODE_DPAD_RIGHT;
Jeff Browne839a582010-04-22 18:58:52 -070047}
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) {
Dianne Hackborn3c5d1252010-07-07 14:27:31 -070057 mPollLoop = new PollLoop(false);
Jeff Browne839a582010-04-22 18:58:52 -070058
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 Browne839a582010-04-22 18:58:52 -0700187 } // release lock
188
Jeff Brown54bc2812010-06-15 01:31:58 -0700189 // If we dispatched anything, don't poll just now. Wait for the next iteration.
190 // Contents may have shifted during flight.
191 if (skipPoll) {
192 return;
193 }
194
Jeff Browne839a582010-04-22 18:58:52 -0700195 // Wait for callback or timeout or wake.
196 nsecs_t timeout = nanoseconds_to_milliseconds(nextWakeupTime - currentTime);
197 int32_t timeoutMillis = timeout > INT_MAX ? -1 : timeout > 0 ? int32_t(timeout) : 0;
198 mPollLoop->pollOnce(timeoutMillis);
199}
200
Jeff Brown54bc2812010-06-15 01:31:58 -0700201bool InputDispatcher::runCommandsLockedInterruptible() {
202 if (mCommandQueue.isEmpty()) {
203 return false;
204 }
Jeff Browne839a582010-04-22 18:58:52 -0700205
Jeff Brown54bc2812010-06-15 01:31:58 -0700206 do {
207 CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
208
209 Command command = commandEntry->command;
210 (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
211
Jeff Brown51d45a72010-06-17 20:52:56 -0700212 commandEntry->connection.clear();
Jeff Brown54bc2812010-06-15 01:31:58 -0700213 mAllocator.releaseCommandEntry(commandEntry);
214 } while (! mCommandQueue.isEmpty());
215 return true;
Jeff Browne839a582010-04-22 18:58:52 -0700216}
217
Jeff Brown54bc2812010-06-15 01:31:58 -0700218InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
219 CommandEntry* commandEntry = mAllocator.obtainCommandEntry(command);
220 mCommandQueue.enqueueAtTail(commandEntry);
221 return commandEntry;
222}
223
224void InputDispatcher::processConfigurationChangedLockedInterruptible(
225 nsecs_t currentTime, ConfigurationChangedEntry* entry) {
226#if DEBUG_OUTBOUND_EVENT_DETAILS
227 LOGD("processConfigurationChanged - eventTime=%lld", entry->eventTime);
228#endif
229
Jeff Brown4036f7f2010-06-29 16:52:21 -0700230 // Reset key repeating in case a keyboard device was added or removed or something.
231 resetKeyRepeatLocked();
232
Jeff Brown54bc2812010-06-15 01:31:58 -0700233 mLock.unlock();
234
235 mPolicy->notifyConfigurationChanged(entry->eventTime);
236
237 mLock.lock();
238}
239
240void InputDispatcher::processKeyLockedInterruptible(
241 nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout) {
Jeff Browne839a582010-04-22 18:58:52 -0700242#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -0700243 LOGD("processKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -0700244 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
Jeff Brown5c1ed842010-07-14 18:48:53 -0700245 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, entry->action,
Jeff Browne839a582010-04-22 18:58:52 -0700246 entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
247 entry->downTime);
248#endif
249
Jeff Brown5c1ed842010-07-14 18:48:53 -0700250 if (entry->action == AKEY_EVENT_ACTION_DOWN && ! entry->isInjected()) {
Jeff Browne839a582010-04-22 18:58:52 -0700251 if (mKeyRepeatState.lastKeyEntry
252 && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
253 // We have seen two identical key downs in a row which indicates that the device
254 // driver is automatically generating key repeats itself. We take note of the
255 // repeat here, but we disable our own next key repeat timer since it is clear that
256 // we will not need to synthesize key repeats ourselves.
257 entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
258 resetKeyRepeatLocked();
259 mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
260 } else {
261 // Not a repeat. Save key down state in case we do see a repeat later.
262 resetKeyRepeatLocked();
Jeff Brown54bc2812010-06-15 01:31:58 -0700263 mKeyRepeatState.nextRepeatTime = entry->eventTime + keyRepeatTimeout;
Jeff Browne839a582010-04-22 18:58:52 -0700264 }
265 mKeyRepeatState.lastKeyEntry = entry;
266 entry->refCount += 1;
267 } else {
268 resetKeyRepeatLocked();
269 }
270
Jeff Brown54bc2812010-06-15 01:31:58 -0700271 identifyInputTargetsAndDispatchKeyLockedInterruptible(currentTime, entry);
Jeff Browne839a582010-04-22 18:58:52 -0700272}
273
Jeff Brown54bc2812010-06-15 01:31:58 -0700274void InputDispatcher::processKeyRepeatLockedInterruptible(
275 nsecs_t currentTime, nsecs_t keyRepeatTimeout) {
Jeff Brown50de30a2010-06-22 01:27:15 -0700276 KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
277
278 // Search the inbound queue for a key up corresponding to this device.
279 // It doesn't make sense to generate a key repeat event if the key is already up.
280 for (EventEntry* queuedEntry = mInboundQueue.head.next;
281 queuedEntry != & mInboundQueue.tail; queuedEntry = entry->next) {
282 if (queuedEntry->type == EventEntry::TYPE_KEY) {
283 KeyEntry* queuedKeyEntry = static_cast<KeyEntry*>(queuedEntry);
284 if (queuedKeyEntry->deviceId == entry->deviceId
Jeff Brown5c1ed842010-07-14 18:48:53 -0700285 && entry->action == AKEY_EVENT_ACTION_UP) {
Jeff Brown50de30a2010-06-22 01:27:15 -0700286 resetKeyRepeatLocked();
287 return;
288 }
289 }
290 }
Jeff Browne839a582010-04-22 18:58:52 -0700291
292 // Synthesize a key repeat after the repeat timeout expired.
Jeff Brown50de30a2010-06-22 01:27:15 -0700293 // Reuse the repeated key entry if it is otherwise unreferenced.
Jeff Brown51d45a72010-06-17 20:52:56 -0700294 uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
Jeff Browne839a582010-04-22 18:58:52 -0700295 if (entry->refCount == 1) {
Jeff Brown51d45a72010-06-17 20:52:56 -0700296 entry->eventTime = currentTime;
Jeff Brown51d45a72010-06-17 20:52:56 -0700297 entry->policyFlags = policyFlags;
Jeff Browne839a582010-04-22 18:58:52 -0700298 entry->repeatCount += 1;
299 } else {
Jeff Brown51d45a72010-06-17 20:52:56 -0700300 KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700301 entry->deviceId, entry->source, policyFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -0700302 entry->action, entry->flags, entry->keyCode, entry->scanCode,
Jeff Brownf16c26d2010-07-02 15:37:36 -0700303 entry->metaState, entry->repeatCount + 1, entry->downTime);
Jeff Browne839a582010-04-22 18:58:52 -0700304
305 mKeyRepeatState.lastKeyEntry = newEntry;
306 mAllocator.releaseKeyEntry(entry);
307
308 entry = newEntry;
309 }
Jeff Browne839a582010-04-22 18:58:52 -0700310
Jeff Brownf16c26d2010-07-02 15:37:36 -0700311 if (entry->repeatCount == 1) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700312 entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
Jeff Brownf16c26d2010-07-02 15:37:36 -0700313 }
314
Jeff Brown54bc2812010-06-15 01:31:58 -0700315 mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatTimeout;
Jeff Browne839a582010-04-22 18:58:52 -0700316
317#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -0700318 LOGD("processKeyRepeat - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -0700319 "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
320 "repeatCount=%d, downTime=%lld",
Jeff Brown5c1ed842010-07-14 18:48:53 -0700321 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
Jeff Browne839a582010-04-22 18:58:52 -0700322 entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
323 entry->repeatCount, entry->downTime);
324#endif
325
Jeff Brown54bc2812010-06-15 01:31:58 -0700326 identifyInputTargetsAndDispatchKeyLockedInterruptible(currentTime, entry);
Jeff Browne839a582010-04-22 18:58:52 -0700327}
328
Jeff Brown54bc2812010-06-15 01:31:58 -0700329void InputDispatcher::processMotionLockedInterruptible(
330 nsecs_t currentTime, MotionEntry* entry) {
Jeff Browne839a582010-04-22 18:58:52 -0700331#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -0700332 LOGD("processMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -0700333 "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
Jeff Brown5c1ed842010-07-14 18:48:53 -0700334 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, entry->action,
Jeff Browne839a582010-04-22 18:58:52 -0700335 entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
336 entry->downTime);
337
338 // Print the most recent sample that we have available, this may change due to batching.
339 size_t sampleCount = 1;
340 MotionSample* sample = & entry->firstSample;
341 for (; sample->next != NULL; sample = sample->next) {
342 sampleCount += 1;
343 }
344 for (uint32_t i = 0; i < entry->pointerCount; i++) {
345 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
346 i, entry->pointerIds[i],
347 sample->pointerCoords[i].x,
348 sample->pointerCoords[i].y,
349 sample->pointerCoords[i].pressure,
350 sample->pointerCoords[i].size);
351 }
352
353 // Keep in mind that due to batching, it is possible for the number of samples actually
354 // dispatched to change before the application finally consumed them.
Jeff Brown5c1ed842010-07-14 18:48:53 -0700355 if (entry->action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Browne839a582010-04-22 18:58:52 -0700356 LOGD(" ... Total movement samples currently batched %d ...", sampleCount);
357 }
358#endif
359
Jeff Brown54bc2812010-06-15 01:31:58 -0700360 identifyInputTargetsAndDispatchMotionLockedInterruptible(currentTime, entry);
Jeff Browne839a582010-04-22 18:58:52 -0700361}
362
Jeff Brown54bc2812010-06-15 01:31:58 -0700363void InputDispatcher::identifyInputTargetsAndDispatchKeyLockedInterruptible(
Jeff Browne839a582010-04-22 18:58:52 -0700364 nsecs_t currentTime, KeyEntry* entry) {
365#if DEBUG_DISPATCH_CYCLE
366 LOGD("identifyInputTargetsAndDispatchKey");
367#endif
368
Jeff Brown54bc2812010-06-15 01:31:58 -0700369 entry->dispatchInProgress = true;
370 mCurrentInputTargetsValid = false;
371 mLock.unlock();
372
Jeff Brown5c1ed842010-07-14 18:48:53 -0700373 mReusableKeyEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
Jeff Browne839a582010-04-22 18:58:52 -0700374 entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
375 entry->downTime, entry->eventTime);
376
377 mCurrentInputTargets.clear();
Jeff Brown50de30a2010-06-22 01:27:15 -0700378 int32_t injectionResult = mPolicy->waitForKeyEventTargets(& mReusableKeyEvent,
Jeff Brown51d45a72010-06-17 20:52:56 -0700379 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Browne839a582010-04-22 18:58:52 -0700380 mCurrentInputTargets);
381
Jeff Brown54bc2812010-06-15 01:31:58 -0700382 mLock.lock();
383 mCurrentInputTargetsValid = true;
384
Jeff Brown51d45a72010-06-17 20:52:56 -0700385 setInjectionResultLocked(entry, injectionResult);
386
Jeff Brown50de30a2010-06-22 01:27:15 -0700387 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
388 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
389 }
Jeff Browne839a582010-04-22 18:58:52 -0700390}
391
Jeff Brown54bc2812010-06-15 01:31:58 -0700392void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(
Jeff Browne839a582010-04-22 18:58:52 -0700393 nsecs_t currentTime, MotionEntry* entry) {
394#if DEBUG_DISPATCH_CYCLE
395 LOGD("identifyInputTargetsAndDispatchMotion");
396#endif
397
Jeff Brown54bc2812010-06-15 01:31:58 -0700398 entry->dispatchInProgress = true;
399 mCurrentInputTargetsValid = false;
400 mLock.unlock();
401
Jeff Brown5c1ed842010-07-14 18:48:53 -0700402 mReusableMotionEvent.initialize(entry->deviceId, entry->source, entry->action,
Jeff Browne839a582010-04-22 18:58:52 -0700403 entry->edgeFlags, entry->metaState,
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700404 0, 0, entry->xPrecision, entry->yPrecision,
Jeff Browne839a582010-04-22 18:58:52 -0700405 entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds,
406 entry->firstSample.pointerCoords);
407
408 mCurrentInputTargets.clear();
Jeff Brown50de30a2010-06-22 01:27:15 -0700409 int32_t injectionResult = mPolicy->waitForMotionEventTargets(& mReusableMotionEvent,
Jeff Brown51d45a72010-06-17 20:52:56 -0700410 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Browne839a582010-04-22 18:58:52 -0700411 mCurrentInputTargets);
412
Jeff Brown54bc2812010-06-15 01:31:58 -0700413 mLock.lock();
414 mCurrentInputTargetsValid = true;
415
Jeff Brown51d45a72010-06-17 20:52:56 -0700416 setInjectionResultLocked(entry, injectionResult);
417
Jeff Brown50de30a2010-06-22 01:27:15 -0700418 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
419 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
420 }
Jeff Browne839a582010-04-22 18:58:52 -0700421}
422
423void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
424 EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
425#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700426 LOGD("dispatchEventToCurrentInputTargets - "
Jeff Browne839a582010-04-22 18:58:52 -0700427 "resumeWithAppendedMotionSample=%s",
428 resumeWithAppendedMotionSample ? "true" : "false");
429#endif
430
Jeff Brown54bc2812010-06-15 01:31:58 -0700431 assert(eventEntry->dispatchInProgress); // should already have been set to true
432
Jeff Browne839a582010-04-22 18:58:52 -0700433 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
434 const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
435
436 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(
437 inputTarget.inputChannel->getReceivePipeFd());
438 if (connectionIndex >= 0) {
439 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown51d45a72010-06-17 20:52:56 -0700440 prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
Jeff Browne839a582010-04-22 18:58:52 -0700441 resumeWithAppendedMotionSample);
442 } else {
443 LOGW("Framework requested delivery of an input event to channel '%s' but it "
444 "is not registered with the input dispatcher.",
445 inputTarget.inputChannel->getName().string());
446 }
447 }
448}
449
Jeff Brown51d45a72010-06-17 20:52:56 -0700450void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
451 const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
Jeff Browne839a582010-04-22 18:58:52 -0700452 bool resumeWithAppendedMotionSample) {
453#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700454 LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, timeout=%lldns, "
Jeff Browne839a582010-04-22 18:58:52 -0700455 "xOffset=%f, yOffset=%f, resumeWithAppendedMotionSample=%s",
456 connection->getInputChannelName(), inputTarget->flags, inputTarget->timeout,
457 inputTarget->xOffset, inputTarget->yOffset,
458 resumeWithAppendedMotionSample ? "true" : "false");
459#endif
460
461 // Skip this event if the connection status is not normal.
462 // We don't want to queue outbound events at all if the connection is broken or
463 // not responding.
464 if (connection->status != Connection::STATUS_NORMAL) {
465 LOGV("channel '%s' ~ Dropping event because the channel status is %s",
Jeff Brown54bc2812010-06-15 01:31:58 -0700466 connection->getStatusLabel());
Jeff Browne839a582010-04-22 18:58:52 -0700467 return;
468 }
469
470 // Resume the dispatch cycle with a freshly appended motion sample.
471 // First we check that the last dispatch entry in the outbound queue is for the same
472 // motion event to which we appended the motion sample. If we find such a dispatch
473 // entry, and if it is currently in progress then we try to stream the new sample.
474 bool wasEmpty = connection->outboundQueue.isEmpty();
475
476 if (! wasEmpty && resumeWithAppendedMotionSample) {
477 DispatchEntry* motionEventDispatchEntry =
478 connection->findQueuedDispatchEntryForEvent(eventEntry);
479 if (motionEventDispatchEntry) {
480 // If the dispatch entry is not in progress, then we must be busy dispatching an
481 // earlier event. Not a problem, the motion event is on the outbound queue and will
482 // be dispatched later.
483 if (! motionEventDispatchEntry->inProgress) {
484#if DEBUG_BATCHING
485 LOGD("channel '%s' ~ Not streaming because the motion event has "
486 "not yet been dispatched. "
487 "(Waiting for earlier events to be consumed.)",
488 connection->getInputChannelName());
489#endif
490 return;
491 }
492
493 // If the dispatch entry is in progress but it already has a tail of pending
494 // motion samples, then it must mean that the shared memory buffer filled up.
495 // Not a problem, when this dispatch cycle is finished, we will eventually start
496 // a new dispatch cycle to process the tail and that tail includes the newly
497 // appended motion sample.
498 if (motionEventDispatchEntry->tailMotionSample) {
499#if DEBUG_BATCHING
500 LOGD("channel '%s' ~ Not streaming because no new samples can "
501 "be appended to the motion event in this dispatch cycle. "
502 "(Waiting for next dispatch cycle to start.)",
503 connection->getInputChannelName());
504#endif
505 return;
506 }
507
508 // The dispatch entry is in progress and is still potentially open for streaming.
509 // Try to stream the new motion sample. This might fail if the consumer has already
510 // consumed the motion event (or if the channel is broken).
511 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
512 status_t status = connection->inputPublisher.appendMotionSample(
513 appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
514 if (status == OK) {
515#if DEBUG_BATCHING
516 LOGD("channel '%s' ~ Successfully streamed new motion sample.",
517 connection->getInputChannelName());
518#endif
519 return;
520 }
521
522#if DEBUG_BATCHING
523 if (status == NO_MEMORY) {
524 LOGD("channel '%s' ~ Could not append motion sample to currently "
525 "dispatched move event because the shared memory buffer is full. "
526 "(Waiting for next dispatch cycle to start.)",
527 connection->getInputChannelName());
528 } else if (status == status_t(FAILED_TRANSACTION)) {
529 LOGD("channel '%s' ~ Could not append motion sample to currently "
Jeff Brown50de30a2010-06-22 01:27:15 -0700530 "dispatched move event because the event has already been consumed. "
Jeff Browne839a582010-04-22 18:58:52 -0700531 "(Waiting for next dispatch cycle to start.)",
532 connection->getInputChannelName());
533 } else {
534 LOGD("channel '%s' ~ Could not append motion sample to currently "
535 "dispatched move event due to an error, status=%d. "
536 "(Waiting for next dispatch cycle to start.)",
537 connection->getInputChannelName(), status);
538 }
539#endif
540 // Failed to stream. Start a new tail of pending motion samples to dispatch
541 // in the next cycle.
542 motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
543 return;
544 }
545 }
546
547 // This is a new event.
548 // Enqueue a new dispatch entry onto the outbound queue for this connection.
549 DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry); // increments ref
550 dispatchEntry->targetFlags = inputTarget->flags;
551 dispatchEntry->xOffset = inputTarget->xOffset;
552 dispatchEntry->yOffset = inputTarget->yOffset;
553 dispatchEntry->timeout = inputTarget->timeout;
554 dispatchEntry->inProgress = false;
555 dispatchEntry->headMotionSample = NULL;
556 dispatchEntry->tailMotionSample = NULL;
557
Jeff Brownf67c53e2010-07-28 15:48:59 -0700558 if (dispatchEntry->isSyncTarget()) {
559 eventEntry->pendingSyncDispatches += 1;
560 }
561
Jeff Browne839a582010-04-22 18:58:52 -0700562 // Handle the case where we could not stream a new motion sample because the consumer has
563 // already consumed the motion event (otherwise the corresponding dispatch entry would
564 // still be in the outbound queue for this connection). We set the head motion sample
565 // to the list starting with the newly appended motion sample.
566 if (resumeWithAppendedMotionSample) {
567#if DEBUG_BATCHING
568 LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
569 "that cannot be streamed because the motion event has already been consumed.",
570 connection->getInputChannelName());
571#endif
572 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
573 dispatchEntry->headMotionSample = appendedMotionSample;
574 }
575
576 // Enqueue the dispatch entry.
577 connection->outboundQueue.enqueueAtTail(dispatchEntry);
578
579 // If the outbound queue was previously empty, start the dispatch cycle going.
580 if (wasEmpty) {
Jeff Brown51d45a72010-06-17 20:52:56 -0700581 activateConnectionLocked(connection.get());
Jeff Browne839a582010-04-22 18:58:52 -0700582 startDispatchCycleLocked(currentTime, connection);
583 }
584}
585
Jeff Brown51d45a72010-06-17 20:52:56 -0700586void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
587 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -0700588#if DEBUG_DISPATCH_CYCLE
589 LOGD("channel '%s' ~ startDispatchCycle",
590 connection->getInputChannelName());
591#endif
592
593 assert(connection->status == Connection::STATUS_NORMAL);
594 assert(! connection->outboundQueue.isEmpty());
595
596 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
597 assert(! dispatchEntry->inProgress);
598
599 // TODO throttle successive ACTION_MOVE motion events for the same device
600 // possible implementation could set a brief poll timeout here and resume starting the
601 // dispatch cycle when elapsed
602
603 // Publish the event.
604 status_t status;
605 switch (dispatchEntry->eventEntry->type) {
606 case EventEntry::TYPE_KEY: {
607 KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
608
609 // Apply target flags.
610 int32_t action = keyEntry->action;
611 int32_t flags = keyEntry->flags;
612 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700613 flags |= AKEY_EVENT_FLAG_CANCELED;
Jeff Browne839a582010-04-22 18:58:52 -0700614 }
615
616 // Publish the key event.
Jeff Brown5c1ed842010-07-14 18:48:53 -0700617 status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
Jeff Browne839a582010-04-22 18:58:52 -0700618 action, flags, keyEntry->keyCode, keyEntry->scanCode,
619 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
620 keyEntry->eventTime);
621
622 if (status) {
623 LOGE("channel '%s' ~ Could not publish key event, "
624 "status=%d", connection->getInputChannelName(), status);
625 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
626 return;
627 }
628 break;
629 }
630
631 case EventEntry::TYPE_MOTION: {
632 MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
633
634 // Apply target flags.
635 int32_t action = motionEntry->action;
636 if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700637 action = AMOTION_EVENT_ACTION_OUTSIDE;
Jeff Browne839a582010-04-22 18:58:52 -0700638 }
639 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700640 action = AMOTION_EVENT_ACTION_CANCEL;
Jeff Browne839a582010-04-22 18:58:52 -0700641 }
642
643 // If headMotionSample is non-NULL, then it points to the first new sample that we
644 // were unable to dispatch during the previous cycle so we resume dispatching from
645 // that point in the list of motion samples.
646 // Otherwise, we just start from the first sample of the motion event.
647 MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
648 if (! firstMotionSample) {
649 firstMotionSample = & motionEntry->firstSample;
650 }
651
Jeff Brownf26db0d2010-07-16 17:21:06 -0700652 // Set the X and Y offset depending on the input source.
653 float xOffset, yOffset;
654 if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
655 xOffset = dispatchEntry->xOffset;
656 yOffset = dispatchEntry->yOffset;
657 } else {
658 xOffset = 0.0f;
659 yOffset = 0.0f;
660 }
661
Jeff Browne839a582010-04-22 18:58:52 -0700662 // Publish the motion event and the first motion sample.
663 status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700664 motionEntry->source, action, motionEntry->edgeFlags, motionEntry->metaState,
Jeff Brownf26db0d2010-07-16 17:21:06 -0700665 xOffset, yOffset,
Jeff Browne839a582010-04-22 18:58:52 -0700666 motionEntry->xPrecision, motionEntry->yPrecision,
667 motionEntry->downTime, firstMotionSample->eventTime,
668 motionEntry->pointerCount, motionEntry->pointerIds,
669 firstMotionSample->pointerCoords);
670
671 if (status) {
672 LOGE("channel '%s' ~ Could not publish motion event, "
673 "status=%d", connection->getInputChannelName(), status);
674 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
675 return;
676 }
677
678 // Append additional motion samples.
679 MotionSample* nextMotionSample = firstMotionSample->next;
680 for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
681 status = connection->inputPublisher.appendMotionSample(
682 nextMotionSample->eventTime, nextMotionSample->pointerCoords);
683 if (status == NO_MEMORY) {
684#if DEBUG_DISPATCH_CYCLE
685 LOGD("channel '%s' ~ Shared memory buffer full. Some motion samples will "
686 "be sent in the next dispatch cycle.",
687 connection->getInputChannelName());
688#endif
689 break;
690 }
691 if (status != OK) {
692 LOGE("channel '%s' ~ Could not append motion sample "
693 "for a reason other than out of memory, status=%d",
694 connection->getInputChannelName(), status);
695 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
696 return;
697 }
698 }
699
700 // Remember the next motion sample that we could not dispatch, in case we ran out
701 // of space in the shared memory buffer.
702 dispatchEntry->tailMotionSample = nextMotionSample;
703 break;
704 }
705
706 default: {
707 assert(false);
708 }
709 }
710
711 // Send the dispatch signal.
712 status = connection->inputPublisher.sendDispatchSignal();
713 if (status) {
714 LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
715 connection->getInputChannelName(), status);
716 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
717 return;
718 }
719
720 // Record information about the newly started dispatch cycle.
721 dispatchEntry->inProgress = true;
722
723 connection->lastEventTime = dispatchEntry->eventEntry->eventTime;
724 connection->lastDispatchTime = currentTime;
725
726 nsecs_t timeout = dispatchEntry->timeout;
Jeff Brown51d45a72010-06-17 20:52:56 -0700727 connection->setNextTimeoutTime(currentTime, timeout);
Jeff Browne839a582010-04-22 18:58:52 -0700728
729 // Notify other system components.
730 onDispatchCycleStartedLocked(currentTime, connection);
731}
732
Jeff Brown51d45a72010-06-17 20:52:56 -0700733void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
734 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -0700735#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700736 LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
Jeff Browne839a582010-04-22 18:58:52 -0700737 "%01.1fms since dispatch",
738 connection->getInputChannelName(),
739 connection->getEventLatencyMillis(currentTime),
740 connection->getDispatchLatencyMillis(currentTime));
741#endif
742
Jeff Brown54bc2812010-06-15 01:31:58 -0700743 if (connection->status == Connection::STATUS_BROKEN
744 || connection->status == Connection::STATUS_ZOMBIE) {
Jeff Browne839a582010-04-22 18:58:52 -0700745 return;
746 }
747
748 // Clear the pending timeout.
749 connection->nextTimeoutTime = LONG_LONG_MAX;
750
751 if (connection->status == Connection::STATUS_NOT_RESPONDING) {
752 // Recovering from an ANR.
753 connection->status = Connection::STATUS_NORMAL;
754
755 // Notify other system components.
756 onDispatchCycleFinishedLocked(currentTime, connection, true /*recoveredFromANR*/);
757 } else {
758 // Normal finish. Not much to do here.
759
760 // Notify other system components.
761 onDispatchCycleFinishedLocked(currentTime, connection, false /*recoveredFromANR*/);
762 }
763
764 // Reset the publisher since the event has been consumed.
765 // We do this now so that the publisher can release some of its internal resources
766 // while waiting for the next dispatch cycle to begin.
767 status_t status = connection->inputPublisher.reset();
768 if (status) {
769 LOGE("channel '%s' ~ Could not reset publisher, status=%d",
770 connection->getInputChannelName(), status);
771 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
772 return;
773 }
774
775 // Start the next dispatch cycle for this connection.
776 while (! connection->outboundQueue.isEmpty()) {
777 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
778 if (dispatchEntry->inProgress) {
779 // Finish or resume current event in progress.
780 if (dispatchEntry->tailMotionSample) {
781 // We have a tail of undispatched motion samples.
782 // Reuse the same DispatchEntry and start a new cycle.
783 dispatchEntry->inProgress = false;
784 dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
785 dispatchEntry->tailMotionSample = NULL;
786 startDispatchCycleLocked(currentTime, connection);
787 return;
788 }
789 // Finished.
790 connection->outboundQueue.dequeueAtHead();
Jeff Brownf67c53e2010-07-28 15:48:59 -0700791 if (dispatchEntry->isSyncTarget()) {
792 decrementPendingSyncDispatchesLocked(dispatchEntry->eventEntry);
793 }
Jeff Browne839a582010-04-22 18:58:52 -0700794 mAllocator.releaseDispatchEntry(dispatchEntry);
795 } else {
796 // If the head is not in progress, then we must have already dequeued the in
797 // progress event, which means we actually aborted it (due to ANR).
798 // So just start the next event for this connection.
799 startDispatchCycleLocked(currentTime, connection);
800 return;
801 }
802 }
803
804 // Outbound queue is empty, deactivate the connection.
Jeff Brown51d45a72010-06-17 20:52:56 -0700805 deactivateConnectionLocked(connection.get());
Jeff Browne839a582010-04-22 18:58:52 -0700806}
807
Jeff Brown51d45a72010-06-17 20:52:56 -0700808void InputDispatcher::timeoutDispatchCycleLocked(nsecs_t currentTime,
809 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -0700810#if DEBUG_DISPATCH_CYCLE
811 LOGD("channel '%s' ~ timeoutDispatchCycle",
812 connection->getInputChannelName());
813#endif
814
815 if (connection->status != Connection::STATUS_NORMAL) {
Jeff Brown51d45a72010-06-17 20:52:56 -0700816 return;
Jeff Browne839a582010-04-22 18:58:52 -0700817 }
818
819 // Enter the not responding state.
820 connection->status = Connection::STATUS_NOT_RESPONDING;
821 connection->lastANRTime = currentTime;
Jeff Browne839a582010-04-22 18:58:52 -0700822
823 // Notify other system components.
Jeff Brown51d45a72010-06-17 20:52:56 -0700824 // This enqueues a command which will eventually either call
825 // resumeAfterTimeoutDispatchCycleLocked or abortDispatchCycleLocked.
Jeff Browne839a582010-04-22 18:58:52 -0700826 onDispatchCycleANRLocked(currentTime, connection);
Jeff Browne839a582010-04-22 18:58:52 -0700827}
828
Jeff Brown51d45a72010-06-17 20:52:56 -0700829void InputDispatcher::resumeAfterTimeoutDispatchCycleLocked(nsecs_t currentTime,
830 const sp<Connection>& connection, nsecs_t newTimeout) {
831#if DEBUG_DISPATCH_CYCLE
832 LOGD("channel '%s' ~ resumeAfterTimeoutDispatchCycleLocked",
833 connection->getInputChannelName());
834#endif
835
836 if (connection->status != Connection::STATUS_NOT_RESPONDING) {
837 return;
838 }
839
840 // Resume normal dispatch.
841 connection->status = Connection::STATUS_NORMAL;
842 connection->setNextTimeoutTime(currentTime, newTimeout);
843}
844
845void InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime,
846 const sp<Connection>& connection, bool broken) {
Jeff Browne839a582010-04-22 18:58:52 -0700847#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700848 LOGD("channel '%s' ~ abortDispatchCycle - broken=%s",
Jeff Browne839a582010-04-22 18:58:52 -0700849 connection->getInputChannelName(), broken ? "true" : "false");
850#endif
851
Jeff Browne839a582010-04-22 18:58:52 -0700852 // Clear the pending timeout.
853 connection->nextTimeoutTime = LONG_LONG_MAX;
854
855 // Clear the outbound queue.
Jeff Brown51d45a72010-06-17 20:52:56 -0700856 if (! connection->outboundQueue.isEmpty()) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700857 do {
858 DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
Jeff Brownf67c53e2010-07-28 15:48:59 -0700859 if (dispatchEntry->isSyncTarget()) {
860 decrementPendingSyncDispatchesLocked(dispatchEntry->eventEntry);
861 }
Jeff Brown54bc2812010-06-15 01:31:58 -0700862 mAllocator.releaseDispatchEntry(dispatchEntry);
863 } while (! connection->outboundQueue.isEmpty());
Jeff Browne839a582010-04-22 18:58:52 -0700864
Jeff Brown51d45a72010-06-17 20:52:56 -0700865 deactivateConnectionLocked(connection.get());
Jeff Brown54bc2812010-06-15 01:31:58 -0700866 }
Jeff Browne839a582010-04-22 18:58:52 -0700867
868 // Handle the case where the connection appears to be unrecoverably broken.
Jeff Brown54bc2812010-06-15 01:31:58 -0700869 // Ignore already broken or zombie connections.
Jeff Browne839a582010-04-22 18:58:52 -0700870 if (broken) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700871 if (connection->status == Connection::STATUS_NORMAL
872 || connection->status == Connection::STATUS_NOT_RESPONDING) {
873 connection->status = Connection::STATUS_BROKEN;
Jeff Browne839a582010-04-22 18:58:52 -0700874
Jeff Brown54bc2812010-06-15 01:31:58 -0700875 // Notify other system components.
876 onDispatchCycleBrokenLocked(currentTime, connection);
877 }
Jeff Browne839a582010-04-22 18:58:52 -0700878 }
Jeff Browne839a582010-04-22 18:58:52 -0700879}
880
881bool InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
882 InputDispatcher* d = static_cast<InputDispatcher*>(data);
883
884 { // acquire lock
885 AutoMutex _l(d->mLock);
886
887 ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
888 if (connectionIndex < 0) {
889 LOGE("Received spurious receive callback for unknown input channel. "
890 "fd=%d, events=0x%x", receiveFd, events);
891 return false; // remove the callback
892 }
893
Jeff Brown51d45a72010-06-17 20:52:56 -0700894 nsecs_t currentTime = now();
Jeff Browne839a582010-04-22 18:58:52 -0700895
896 sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
897 if (events & (POLLERR | POLLHUP | POLLNVAL)) {
898 LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
899 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brown51d45a72010-06-17 20:52:56 -0700900 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -0700901 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700902 return false; // remove the callback
903 }
904
905 if (! (events & POLLIN)) {
906 LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
907 "events=0x%x", connection->getInputChannelName(), events);
908 return true;
909 }
910
911 status_t status = connection->inputPublisher.receiveFinishedSignal();
912 if (status) {
913 LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
914 connection->getInputChannelName(), status);
Jeff Brown51d45a72010-06-17 20:52:56 -0700915 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -0700916 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700917 return false; // remove the callback
918 }
919
Jeff Brown51d45a72010-06-17 20:52:56 -0700920 d->finishDispatchCycleLocked(currentTime, connection);
Jeff Brown54bc2812010-06-15 01:31:58 -0700921 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700922 return true;
923 } // release lock
924}
925
Jeff Brown54bc2812010-06-15 01:31:58 -0700926void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
Jeff Browne839a582010-04-22 18:58:52 -0700927#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown54bc2812010-06-15 01:31:58 -0700928 LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
Jeff Browne839a582010-04-22 18:58:52 -0700929#endif
930
931 bool wasEmpty;
932 { // acquire lock
933 AutoMutex _l(mLock);
934
Jeff Brown51d45a72010-06-17 20:52:56 -0700935 ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
Jeff Browne839a582010-04-22 18:58:52 -0700936
937 wasEmpty = mInboundQueue.isEmpty();
938 mInboundQueue.enqueueAtTail(newEntry);
939 } // release lock
940
941 if (wasEmpty) {
942 mPollLoop->wake();
943 }
944}
945
Jeff Browne839a582010-04-22 18:58:52 -0700946void InputDispatcher::notifyAppSwitchComing(nsecs_t eventTime) {
947#if DEBUG_INBOUND_EVENT_DETAILS
948 LOGD("notifyAppSwitchComing - eventTime=%lld", eventTime);
949#endif
950
951 // Remove movement keys from the queue from most recent to least recent, stopping at the
952 // first non-movement key.
953 // TODO: Include a detailed description of why we do this...
954
955 { // acquire lock
956 AutoMutex _l(mLock);
957
958 for (EventEntry* entry = mInboundQueue.tail.prev; entry != & mInboundQueue.head; ) {
959 EventEntry* prev = entry->prev;
960
961 if (entry->type == EventEntry::TYPE_KEY) {
962 KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
963 if (isMovementKey(keyEntry->keyCode)) {
964 LOGV("Dropping movement key during app switch: keyCode=%d, action=%d",
965 keyEntry->keyCode, keyEntry->action);
966 mInboundQueue.dequeue(keyEntry);
Jeff Brown51d45a72010-06-17 20:52:56 -0700967
968 setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
969
Jeff Browne839a582010-04-22 18:58:52 -0700970 mAllocator.releaseKeyEntry(keyEntry);
971 } else {
972 // stop at last non-movement key
973 break;
974 }
975 }
976
977 entry = prev;
978 }
979 } // release lock
980}
981
Jeff Brown5c1ed842010-07-14 18:48:53 -0700982void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Browne839a582010-04-22 18:58:52 -0700983 uint32_t policyFlags, int32_t action, int32_t flags,
984 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
985#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -0700986 LOGD("notifyKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -0700987 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
Jeff Brown5c1ed842010-07-14 18:48:53 -0700988 eventTime, deviceId, source, policyFlags, action, flags,
Jeff Browne839a582010-04-22 18:58:52 -0700989 keyCode, scanCode, metaState, downTime);
990#endif
991
992 bool wasEmpty;
993 { // acquire lock
994 AutoMutex _l(mLock);
995
Jeff Brown51d45a72010-06-17 20:52:56 -0700996 int32_t repeatCount = 0;
997 KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700998 deviceId, source, policyFlags, action, flags, keyCode, scanCode,
Jeff Brown51d45a72010-06-17 20:52:56 -0700999 metaState, repeatCount, downTime);
Jeff Browne839a582010-04-22 18:58:52 -07001000
1001 wasEmpty = mInboundQueue.isEmpty();
1002 mInboundQueue.enqueueAtTail(newEntry);
1003 } // release lock
1004
1005 if (wasEmpty) {
1006 mPollLoop->wake();
1007 }
1008}
1009
Jeff Brown5c1ed842010-07-14 18:48:53 -07001010void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Browne839a582010-04-22 18:58:52 -07001011 uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
1012 uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
1013 float xPrecision, float yPrecision, nsecs_t downTime) {
1014#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -07001015 LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -07001016 "action=0x%x, metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, "
1017 "downTime=%lld",
Jeff Brown5c1ed842010-07-14 18:48:53 -07001018 eventTime, deviceId, source, policyFlags, action, metaState, edgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07001019 xPrecision, yPrecision, downTime);
1020 for (uint32_t i = 0; i < pointerCount; i++) {
1021 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
1022 i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
1023 pointerCoords[i].pressure, pointerCoords[i].size);
1024 }
1025#endif
1026
1027 bool wasEmpty;
1028 { // acquire lock
1029 AutoMutex _l(mLock);
1030
1031 // Attempt batching and streaming of move events.
Jeff Brown5c1ed842010-07-14 18:48:53 -07001032 if (action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Browne839a582010-04-22 18:58:52 -07001033 // BATCHING CASE
1034 //
1035 // Try to append a move sample to the tail of the inbound queue for this device.
1036 // Give up if we encounter a non-move motion event for this device since that
1037 // means we cannot append any new samples until a new motion event has started.
1038 for (EventEntry* entry = mInboundQueue.tail.prev;
1039 entry != & mInboundQueue.head; entry = entry->prev) {
1040 if (entry->type != EventEntry::TYPE_MOTION) {
1041 // Keep looking for motion events.
1042 continue;
1043 }
1044
1045 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
1046 if (motionEntry->deviceId != deviceId) {
1047 // Keep looking for this device.
1048 continue;
1049 }
1050
Jeff Brown5c1ed842010-07-14 18:48:53 -07001051 if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown51d45a72010-06-17 20:52:56 -07001052 || motionEntry->pointerCount != pointerCount
1053 || motionEntry->isInjected()) {
Jeff Browne839a582010-04-22 18:58:52 -07001054 // Last motion event in the queue for this device is not compatible for
1055 // appending new samples. Stop here.
1056 goto NoBatchingOrStreaming;
1057 }
1058
1059 // The last motion event is a move and is compatible for appending.
Jeff Brown54bc2812010-06-15 01:31:58 -07001060 // Do the batching magic.
Jeff Brown51d45a72010-06-17 20:52:56 -07001061 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
Jeff Browne839a582010-04-22 18:58:52 -07001062#if DEBUG_BATCHING
1063 LOGD("Appended motion sample onto batch for most recent "
1064 "motion event for this device in the inbound queue.");
1065#endif
Jeff Brown54bc2812010-06-15 01:31:58 -07001066
1067 // Sanity check for special case because dispatch is interruptible.
1068 // The dispatch logic is partially interruptible and releases its lock while
1069 // identifying targets. However, as soon as the targets have been identified,
1070 // the dispatcher proceeds to write a dispatch entry into all relevant outbound
1071 // queues and then promptly removes the motion entry from the queue.
1072 //
1073 // Consequently, we should never observe the case where the inbound queue contains
1074 // an in-progress motion entry unless the current input targets are invalid
1075 // (currently being computed). Check for this!
1076 assert(! (motionEntry->dispatchInProgress && mCurrentInputTargetsValid));
1077
1078 return; // done!
Jeff Browne839a582010-04-22 18:58:52 -07001079 }
1080
1081 // STREAMING CASE
1082 //
1083 // There is no pending motion event (of any kind) for this device in the inbound queue.
1084 // Search the outbound queues for a synchronously dispatched motion event for this
1085 // device. If found, then we append the new sample to that event and then try to
1086 // push it out to all current targets. It is possible that some targets will already
1087 // have consumed the motion event. This case is automatically handled by the
1088 // logic in prepareDispatchCycleLocked by tracking where resumption takes place.
1089 //
1090 // The reason we look for a synchronously dispatched motion event is because we
1091 // want to be sure that no other motion events have been dispatched since the move.
1092 // It's also convenient because it means that the input targets are still valid.
1093 // This code could be improved to support streaming of asynchronously dispatched
1094 // motion events (which might be significantly more efficient) but it may become
1095 // a little more complicated as a result.
1096 //
1097 // Note: This code crucially depends on the invariant that an outbound queue always
1098 // contains at most one synchronous event and it is always last (but it might
1099 // not be first!).
Jeff Brown54bc2812010-06-15 01:31:58 -07001100 if (mCurrentInputTargetsValid) {
1101 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1102 Connection* connection = mActiveConnections.itemAt(i);
1103 if (! connection->outboundQueue.isEmpty()) {
1104 DispatchEntry* dispatchEntry = connection->outboundQueue.tail.prev;
Jeff Brownf67c53e2010-07-28 15:48:59 -07001105 if (dispatchEntry->isSyncTarget()) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001106 if (dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION) {
1107 goto NoBatchingOrStreaming;
1108 }
Jeff Browne839a582010-04-22 18:58:52 -07001109
Jeff Brown54bc2812010-06-15 01:31:58 -07001110 MotionEntry* syncedMotionEntry = static_cast<MotionEntry*>(
1111 dispatchEntry->eventEntry);
Jeff Brown5c1ed842010-07-14 18:48:53 -07001112 if (syncedMotionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown54bc2812010-06-15 01:31:58 -07001113 || syncedMotionEntry->deviceId != deviceId
Jeff Brown51d45a72010-06-17 20:52:56 -07001114 || syncedMotionEntry->pointerCount != pointerCount
1115 || syncedMotionEntry->isInjected()) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001116 goto NoBatchingOrStreaming;
1117 }
Jeff Browne839a582010-04-22 18:58:52 -07001118
Jeff Brown54bc2812010-06-15 01:31:58 -07001119 // Found synced move entry. Append sample and resume dispatch.
1120 mAllocator.appendMotionSample(syncedMotionEntry, eventTime,
Jeff Brown51d45a72010-06-17 20:52:56 -07001121 pointerCoords);
Jeff Brown54bc2812010-06-15 01:31:58 -07001122 #if DEBUG_BATCHING
1123 LOGD("Appended motion sample onto batch for most recent synchronously "
1124 "dispatched motion event for this device in the outbound queues.");
1125 #endif
Jeff Brown51d45a72010-06-17 20:52:56 -07001126 nsecs_t currentTime = now();
Jeff Brown54bc2812010-06-15 01:31:58 -07001127 dispatchEventToCurrentInputTargetsLocked(currentTime, syncedMotionEntry,
1128 true /*resumeWithAppendedMotionSample*/);
1129
1130 runCommandsLockedInterruptible();
1131 return; // done!
1132 }
Jeff Browne839a582010-04-22 18:58:52 -07001133 }
1134 }
1135 }
1136
1137NoBatchingOrStreaming:;
1138 }
1139
1140 // Just enqueue a new motion event.
Jeff Brown51d45a72010-06-17 20:52:56 -07001141 MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001142 deviceId, source, policyFlags, action, metaState, edgeFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -07001143 xPrecision, yPrecision, downTime,
1144 pointerCount, pointerIds, pointerCoords);
Jeff Browne839a582010-04-22 18:58:52 -07001145
1146 wasEmpty = mInboundQueue.isEmpty();
1147 mInboundQueue.enqueueAtTail(newEntry);
1148 } // release lock
1149
1150 if (wasEmpty) {
1151 mPollLoop->wake();
1152 }
1153}
1154
Jeff Brown51d45a72010-06-17 20:52:56 -07001155int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
Jeff Brownf67c53e2010-07-28 15:48:59 -07001156 int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001157#if DEBUG_INBOUND_EVENT_DETAILS
1158 LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
Jeff Brownf67c53e2010-07-28 15:48:59 -07001159 "syncMode=%d, timeoutMillis=%d",
1160 event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis);
Jeff Brown51d45a72010-06-17 20:52:56 -07001161#endif
1162
1163 nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
1164
1165 EventEntry* injectedEntry;
1166 bool wasEmpty;
1167 { // acquire lock
1168 AutoMutex _l(mLock);
1169
1170 injectedEntry = createEntryFromInputEventLocked(event);
1171 injectedEntry->refCount += 1;
1172 injectedEntry->injectorPid = injectorPid;
1173 injectedEntry->injectorUid = injectorUid;
1174
Jeff Brownf67c53e2010-07-28 15:48:59 -07001175 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
1176 injectedEntry->injectionIsAsync = true;
1177 }
1178
Jeff Brown51d45a72010-06-17 20:52:56 -07001179 wasEmpty = mInboundQueue.isEmpty();
1180 mInboundQueue.enqueueAtTail(injectedEntry);
1181
1182 } // release lock
1183
1184 if (wasEmpty) {
1185 mPollLoop->wake();
1186 }
1187
1188 int32_t injectionResult;
1189 { // acquire lock
1190 AutoMutex _l(mLock);
1191
Jeff Brownf67c53e2010-07-28 15:48:59 -07001192 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
1193 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1194 } else {
1195 for (;;) {
1196 injectionResult = injectedEntry->injectionResult;
1197 if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
1198 break;
1199 }
Jeff Brown51d45a72010-06-17 20:52:56 -07001200
Jeff Brown51d45a72010-06-17 20:52:56 -07001201 nsecs_t remainingTimeout = endTime - now();
1202 if (remainingTimeout <= 0) {
Jeff Brownf67c53e2010-07-28 15:48:59 -07001203#if DEBUG_INJECTION
1204 LOGD("injectInputEvent - Timed out waiting for injection result "
1205 "to become available.");
1206#endif
Jeff Brown51d45a72010-06-17 20:52:56 -07001207 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1208 break;
1209 }
1210
Jeff Brownf67c53e2010-07-28 15:48:59 -07001211 mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
1212 }
1213
1214 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
1215 && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
1216 while (injectedEntry->pendingSyncDispatches != 0) {
1217#if DEBUG_INJECTION
1218 LOGD("injectInputEvent - Waiting for %d pending synchronous dispatches.",
1219 injectedEntry->pendingSyncDispatches);
1220#endif
1221 nsecs_t remainingTimeout = endTime - now();
1222 if (remainingTimeout <= 0) {
1223#if DEBUG_INJECTION
1224 LOGD("injectInputEvent - Timed out waiting for pending synchronous "
1225 "dispatches to finish.");
1226#endif
1227 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1228 break;
1229 }
1230
1231 mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
1232 }
Jeff Brown51d45a72010-06-17 20:52:56 -07001233 }
1234 }
1235
1236 mAllocator.releaseEventEntry(injectedEntry);
1237 } // release lock
1238
Jeff Brownf67c53e2010-07-28 15:48:59 -07001239#if DEBUG_INJECTION
1240 LOGD("injectInputEvent - Finished with result %d. "
1241 "injectorPid=%d, injectorUid=%d",
1242 injectionResult, injectorPid, injectorUid);
1243#endif
1244
Jeff Brown51d45a72010-06-17 20:52:56 -07001245 return injectionResult;
1246}
1247
1248void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
1249 if (entry->isInjected()) {
1250#if DEBUG_INJECTION
1251 LOGD("Setting input event injection result to %d. "
1252 "injectorPid=%d, injectorUid=%d",
1253 injectionResult, entry->injectorPid, entry->injectorUid);
1254#endif
1255
Jeff Brownf67c53e2010-07-28 15:48:59 -07001256 if (entry->injectionIsAsync) {
1257 // Log the outcome since the injector did not wait for the injection result.
1258 switch (injectionResult) {
1259 case INPUT_EVENT_INJECTION_SUCCEEDED:
1260 LOGV("Asynchronous input event injection succeeded.");
1261 break;
1262 case INPUT_EVENT_INJECTION_FAILED:
1263 LOGW("Asynchronous input event injection failed.");
1264 break;
1265 case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
1266 LOGW("Asynchronous input event injection permission denied.");
1267 break;
1268 case INPUT_EVENT_INJECTION_TIMED_OUT:
1269 LOGW("Asynchronous input event injection timed out.");
1270 break;
1271 }
1272 }
1273
Jeff Brown51d45a72010-06-17 20:52:56 -07001274 entry->injectionResult = injectionResult;
1275 mInjectionResultAvailableCondition.broadcast();
1276 }
1277}
1278
Jeff Brownf67c53e2010-07-28 15:48:59 -07001279void InputDispatcher::decrementPendingSyncDispatchesLocked(EventEntry* entry) {
1280 entry->pendingSyncDispatches -= 1;
1281
1282 if (entry->isInjected() && entry->pendingSyncDispatches == 0) {
1283 mInjectionSyncFinishedCondition.broadcast();
1284 }
Jeff Brown51d45a72010-06-17 20:52:56 -07001285}
1286
1287InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked(
1288 const InputEvent* event) {
1289 switch (event->getType()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07001290 case AINPUT_EVENT_TYPE_KEY: {
Jeff Brown51d45a72010-06-17 20:52:56 -07001291 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
1292 uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
1293
1294 KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
Jeff Brown5c1ed842010-07-14 18:48:53 -07001295 keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -07001296 keyEvent->getAction(), keyEvent->getFlags(),
1297 keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
1298 keyEvent->getRepeatCount(), keyEvent->getDownTime());
1299 return keyEntry;
1300 }
1301
Jeff Brown5c1ed842010-07-14 18:48:53 -07001302 case AINPUT_EVENT_TYPE_MOTION: {
Jeff Brown51d45a72010-06-17 20:52:56 -07001303 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
1304 uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
1305
1306 const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
1307 const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
1308 size_t pointerCount = motionEvent->getPointerCount();
1309
1310 MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001311 motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -07001312 motionEvent->getAction(), motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
1313 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
1314 motionEvent->getDownTime(), uint32_t(pointerCount),
1315 motionEvent->getPointerIds(), samplePointerCoords);
1316 for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
1317 sampleEventTimes += 1;
1318 samplePointerCoords += pointerCount;
1319 mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
1320 }
1321 return motionEntry;
1322 }
1323
1324 default:
1325 assert(false);
1326 return NULL;
1327 }
1328}
1329
Jeff Browne839a582010-04-22 18:58:52 -07001330void InputDispatcher::resetKeyRepeatLocked() {
1331 if (mKeyRepeatState.lastKeyEntry) {
1332 mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
1333 mKeyRepeatState.lastKeyEntry = NULL;
1334 }
1335}
1336
Jeff Brown50de30a2010-06-22 01:27:15 -07001337void InputDispatcher::preemptInputDispatch() {
1338#if DEBUG_DISPATCH_CYCLE
1339 LOGD("preemptInputDispatch");
1340#endif
1341
1342 bool preemptedOne = false;
1343 { // acquire lock
1344 AutoMutex _l(mLock);
1345
1346 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1347 Connection* connection = mActiveConnections[i];
1348 if (connection->hasPendingSyncTarget()) {
1349#if DEBUG_DISPATCH_CYCLE
1350 LOGD("channel '%s' ~ Preempted pending synchronous dispatch",
1351 connection->getInputChannelName());
1352#endif
1353 connection->outboundQueue.tail.prev->targetFlags &= ~ InputTarget::FLAG_SYNC;
1354 preemptedOne = true;
1355 }
1356 }
1357 } // release lock
1358
1359 if (preemptedOne) {
1360 // Wake up the poll loop so it can get a head start dispatching the next event.
1361 mPollLoop->wake();
1362 }
1363}
1364
Jeff Browne839a582010-04-22 18:58:52 -07001365status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001366#if DEBUG_REGISTRATION
Jeff Brown50de30a2010-06-22 01:27:15 -07001367 LOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().string());
Jeff Brown54bc2812010-06-15 01:31:58 -07001368#endif
1369
Jeff Browne839a582010-04-22 18:58:52 -07001370 int receiveFd;
1371 { // acquire lock
1372 AutoMutex _l(mLock);
1373
1374 receiveFd = inputChannel->getReceivePipeFd();
1375 if (mConnectionsByReceiveFd.indexOfKey(receiveFd) >= 0) {
1376 LOGW("Attempted to register already registered input channel '%s'",
1377 inputChannel->getName().string());
1378 return BAD_VALUE;
1379 }
1380
1381 sp<Connection> connection = new Connection(inputChannel);
1382 status_t status = connection->initialize();
1383 if (status) {
1384 LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
1385 inputChannel->getName().string(), status);
1386 return status;
1387 }
1388
1389 mConnectionsByReceiveFd.add(receiveFd, connection);
Jeff Brown54bc2812010-06-15 01:31:58 -07001390
1391 runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07001392 } // release lock
1393
1394 mPollLoop->setCallback(receiveFd, POLLIN, handleReceiveCallback, this);
1395 return OK;
1396}
1397
1398status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001399#if DEBUG_REGISTRATION
Jeff Brown50de30a2010-06-22 01:27:15 -07001400 LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
Jeff Brown54bc2812010-06-15 01:31:58 -07001401#endif
1402
Jeff Browne839a582010-04-22 18:58:52 -07001403 int32_t receiveFd;
1404 { // acquire lock
1405 AutoMutex _l(mLock);
1406
1407 receiveFd = inputChannel->getReceivePipeFd();
1408 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(receiveFd);
1409 if (connectionIndex < 0) {
1410 LOGW("Attempted to unregister already unregistered input channel '%s'",
1411 inputChannel->getName().string());
1412 return BAD_VALUE;
1413 }
1414
1415 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1416 mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
1417
1418 connection->status = Connection::STATUS_ZOMBIE;
1419
Jeff Brown51d45a72010-06-17 20:52:56 -07001420 nsecs_t currentTime = now();
1421 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -07001422
1423 runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07001424 } // release lock
1425
1426 mPollLoop->removeCallback(receiveFd);
1427
1428 // Wake the poll loop because removing the connection may have changed the current
1429 // synchronization state.
1430 mPollLoop->wake();
1431 return OK;
1432}
1433
1434void InputDispatcher::activateConnectionLocked(Connection* connection) {
1435 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1436 if (mActiveConnections.itemAt(i) == connection) {
1437 return;
1438 }
1439 }
1440 mActiveConnections.add(connection);
1441}
1442
1443void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
1444 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1445 if (mActiveConnections.itemAt(i) == connection) {
1446 mActiveConnections.removeAt(i);
1447 return;
1448 }
1449 }
1450}
1451
Jeff Brown54bc2812010-06-15 01:31:58 -07001452void InputDispatcher::onDispatchCycleStartedLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001453 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001454}
1455
Jeff Brown54bc2812010-06-15 01:31:58 -07001456void InputDispatcher::onDispatchCycleFinishedLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001457 nsecs_t currentTime, const sp<Connection>& connection, bool recoveredFromANR) {
Jeff Browne839a582010-04-22 18:58:52 -07001458 if (recoveredFromANR) {
1459 LOGI("channel '%s' ~ Recovered from ANR. %01.1fms since event, "
1460 "%01.1fms since dispatch, %01.1fms since ANR",
1461 connection->getInputChannelName(),
1462 connection->getEventLatencyMillis(currentTime),
1463 connection->getDispatchLatencyMillis(currentTime),
1464 connection->getANRLatencyMillis(currentTime));
1465
Jeff Brown54bc2812010-06-15 01:31:58 -07001466 CommandEntry* commandEntry = postCommandLocked(
1467 & InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07001468 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07001469 }
1470}
1471
Jeff Brown54bc2812010-06-15 01:31:58 -07001472void InputDispatcher::onDispatchCycleANRLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001473 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001474 LOGI("channel '%s' ~ Not responding! %01.1fms since event, %01.1fms since dispatch",
1475 connection->getInputChannelName(),
1476 connection->getEventLatencyMillis(currentTime),
1477 connection->getDispatchLatencyMillis(currentTime));
1478
Jeff Brown54bc2812010-06-15 01:31:58 -07001479 CommandEntry* commandEntry = postCommandLocked(
1480 & InputDispatcher::doNotifyInputChannelANRLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07001481 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07001482}
1483
Jeff Brown54bc2812010-06-15 01:31:58 -07001484void InputDispatcher::onDispatchCycleBrokenLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001485 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001486 LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
1487 connection->getInputChannelName());
1488
Jeff Brown54bc2812010-06-15 01:31:58 -07001489 CommandEntry* commandEntry = postCommandLocked(
1490 & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07001491 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07001492}
1493
Jeff Brown54bc2812010-06-15 01:31:58 -07001494void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
1495 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001496 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07001497
Jeff Brown51d45a72010-06-17 20:52:56 -07001498 if (connection->status != Connection::STATUS_ZOMBIE) {
1499 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07001500
Jeff Brown51d45a72010-06-17 20:52:56 -07001501 mPolicy->notifyInputChannelBroken(connection->inputChannel);
1502
1503 mLock.lock();
1504 }
Jeff Brown54bc2812010-06-15 01:31:58 -07001505}
1506
1507void InputDispatcher::doNotifyInputChannelANRLockedInterruptible(
1508 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001509 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07001510
Jeff Brown51d45a72010-06-17 20:52:56 -07001511 if (connection->status != Connection::STATUS_ZOMBIE) {
1512 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07001513
Jeff Brown51d45a72010-06-17 20:52:56 -07001514 nsecs_t newTimeout;
1515 bool resume = mPolicy->notifyInputChannelANR(connection->inputChannel, newTimeout);
1516
1517 mLock.lock();
1518
1519 nsecs_t currentTime = now();
1520 if (resume) {
1521 resumeAfterTimeoutDispatchCycleLocked(currentTime, connection, newTimeout);
1522 } else {
1523 abortDispatchCycleLocked(currentTime, connection, false /*(not) broken*/);
1524 }
1525 }
Jeff Brown54bc2812010-06-15 01:31:58 -07001526}
1527
1528void InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible(
1529 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001530 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07001531
Jeff Brown51d45a72010-06-17 20:52:56 -07001532 if (connection->status != Connection::STATUS_ZOMBIE) {
1533 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07001534
Jeff Brown51d45a72010-06-17 20:52:56 -07001535 mPolicy->notifyInputChannelRecoveredFromANR(connection->inputChannel);
1536
1537 mLock.lock();
1538 }
Jeff Brown54bc2812010-06-15 01:31:58 -07001539}
1540
1541
Jeff Browne839a582010-04-22 18:58:52 -07001542// --- InputDispatcher::Allocator ---
1543
1544InputDispatcher::Allocator::Allocator() {
1545}
1546
Jeff Brown51d45a72010-06-17 20:52:56 -07001547void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
1548 nsecs_t eventTime) {
1549 entry->type = type;
1550 entry->refCount = 1;
1551 entry->dispatchInProgress = false;
Christopher Tated974e002010-06-23 16:50:30 -07001552 entry->eventTime = eventTime;
Jeff Brown51d45a72010-06-17 20:52:56 -07001553 entry->injectionResult = INPUT_EVENT_INJECTION_PENDING;
Jeff Brownf67c53e2010-07-28 15:48:59 -07001554 entry->injectionIsAsync = false;
Jeff Brown51d45a72010-06-17 20:52:56 -07001555 entry->injectorPid = -1;
1556 entry->injectorUid = -1;
Jeff Brownf67c53e2010-07-28 15:48:59 -07001557 entry->pendingSyncDispatches = 0;
Jeff Brown51d45a72010-06-17 20:52:56 -07001558}
1559
Jeff Browne839a582010-04-22 18:58:52 -07001560InputDispatcher::ConfigurationChangedEntry*
Jeff Brown51d45a72010-06-17 20:52:56 -07001561InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
Jeff Browne839a582010-04-22 18:58:52 -07001562 ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07001563 initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime);
Jeff Browne839a582010-04-22 18:58:52 -07001564 return entry;
1565}
1566
Jeff Brown51d45a72010-06-17 20:52:56 -07001567InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001568 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
Jeff Brown51d45a72010-06-17 20:52:56 -07001569 int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
1570 int32_t repeatCount, nsecs_t downTime) {
Jeff Browne839a582010-04-22 18:58:52 -07001571 KeyEntry* entry = mKeyEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07001572 initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime);
1573
1574 entry->deviceId = deviceId;
Jeff Brown5c1ed842010-07-14 18:48:53 -07001575 entry->source = source;
Jeff Brown51d45a72010-06-17 20:52:56 -07001576 entry->policyFlags = policyFlags;
1577 entry->action = action;
1578 entry->flags = flags;
1579 entry->keyCode = keyCode;
1580 entry->scanCode = scanCode;
1581 entry->metaState = metaState;
1582 entry->repeatCount = repeatCount;
1583 entry->downTime = downTime;
Jeff Browne839a582010-04-22 18:58:52 -07001584 return entry;
1585}
1586
Jeff Brown51d45a72010-06-17 20:52:56 -07001587InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001588 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
Jeff Brown51d45a72010-06-17 20:52:56 -07001589 int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
1590 nsecs_t downTime, uint32_t pointerCount,
1591 const int32_t* pointerIds, const PointerCoords* pointerCoords) {
Jeff Browne839a582010-04-22 18:58:52 -07001592 MotionEntry* entry = mMotionEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07001593 initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime);
1594
1595 entry->eventTime = eventTime;
1596 entry->deviceId = deviceId;
Jeff Brown5c1ed842010-07-14 18:48:53 -07001597 entry->source = source;
Jeff Brown51d45a72010-06-17 20:52:56 -07001598 entry->policyFlags = policyFlags;
1599 entry->action = action;
1600 entry->metaState = metaState;
1601 entry->edgeFlags = edgeFlags;
1602 entry->xPrecision = xPrecision;
1603 entry->yPrecision = yPrecision;
1604 entry->downTime = downTime;
1605 entry->pointerCount = pointerCount;
1606 entry->firstSample.eventTime = eventTime;
Jeff Browne839a582010-04-22 18:58:52 -07001607 entry->firstSample.next = NULL;
Jeff Brown51d45a72010-06-17 20:52:56 -07001608 entry->lastSample = & entry->firstSample;
1609 for (uint32_t i = 0; i < pointerCount; i++) {
1610 entry->pointerIds[i] = pointerIds[i];
1611 entry->firstSample.pointerCoords[i] = pointerCoords[i];
1612 }
Jeff Browne839a582010-04-22 18:58:52 -07001613 return entry;
1614}
1615
1616InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
1617 EventEntry* eventEntry) {
1618 DispatchEntry* entry = mDispatchEntryPool.alloc();
1619 entry->eventEntry = eventEntry;
1620 eventEntry->refCount += 1;
1621 return entry;
1622}
1623
Jeff Brown54bc2812010-06-15 01:31:58 -07001624InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
1625 CommandEntry* entry = mCommandEntryPool.alloc();
1626 entry->command = command;
1627 return entry;
1628}
1629
Jeff Browne839a582010-04-22 18:58:52 -07001630void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
1631 switch (entry->type) {
1632 case EventEntry::TYPE_CONFIGURATION_CHANGED:
1633 releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
1634 break;
1635 case EventEntry::TYPE_KEY:
1636 releaseKeyEntry(static_cast<KeyEntry*>(entry));
1637 break;
1638 case EventEntry::TYPE_MOTION:
1639 releaseMotionEntry(static_cast<MotionEntry*>(entry));
1640 break;
1641 default:
1642 assert(false);
1643 break;
1644 }
1645}
1646
1647void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
1648 ConfigurationChangedEntry* entry) {
1649 entry->refCount -= 1;
1650 if (entry->refCount == 0) {
1651 mConfigurationChangeEntryPool.free(entry);
1652 } else {
1653 assert(entry->refCount > 0);
1654 }
1655}
1656
1657void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
1658 entry->refCount -= 1;
1659 if (entry->refCount == 0) {
1660 mKeyEntryPool.free(entry);
1661 } else {
1662 assert(entry->refCount > 0);
1663 }
1664}
1665
1666void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
1667 entry->refCount -= 1;
1668 if (entry->refCount == 0) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001669 for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
1670 MotionSample* next = sample->next;
1671 mMotionSamplePool.free(sample);
1672 sample = next;
1673 }
Jeff Browne839a582010-04-22 18:58:52 -07001674 mMotionEntryPool.free(entry);
1675 } else {
1676 assert(entry->refCount > 0);
1677 }
1678}
1679
1680void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
1681 releaseEventEntry(entry->eventEntry);
1682 mDispatchEntryPool.free(entry);
1683}
1684
Jeff Brown54bc2812010-06-15 01:31:58 -07001685void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
1686 mCommandEntryPool.free(entry);
1687}
1688
Jeff Browne839a582010-04-22 18:58:52 -07001689void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
Jeff Brown51d45a72010-06-17 20:52:56 -07001690 nsecs_t eventTime, const PointerCoords* pointerCoords) {
Jeff Browne839a582010-04-22 18:58:52 -07001691 MotionSample* sample = mMotionSamplePool.alloc();
1692 sample->eventTime = eventTime;
Jeff Brown51d45a72010-06-17 20:52:56 -07001693 uint32_t pointerCount = motionEntry->pointerCount;
1694 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Browne839a582010-04-22 18:58:52 -07001695 sample->pointerCoords[i] = pointerCoords[i];
1696 }
1697
1698 sample->next = NULL;
1699 motionEntry->lastSample->next = sample;
1700 motionEntry->lastSample = sample;
1701}
1702
Jeff Browne839a582010-04-22 18:58:52 -07001703// --- InputDispatcher::Connection ---
1704
1705InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
1706 status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
1707 nextTimeoutTime(LONG_LONG_MAX),
1708 lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX),
1709 lastANRTime(LONG_LONG_MAX) {
1710}
1711
1712InputDispatcher::Connection::~Connection() {
1713}
1714
1715status_t InputDispatcher::Connection::initialize() {
1716 return inputPublisher.initialize();
1717}
1718
Jeff Brown51d45a72010-06-17 20:52:56 -07001719void InputDispatcher::Connection::setNextTimeoutTime(nsecs_t currentTime, nsecs_t timeout) {
1720 nextTimeoutTime = (timeout >= 0) ? currentTime + timeout : LONG_LONG_MAX;
1721}
1722
Jeff Brown54bc2812010-06-15 01:31:58 -07001723const char* InputDispatcher::Connection::getStatusLabel() const {
1724 switch (status) {
1725 case STATUS_NORMAL:
1726 return "NORMAL";
1727
1728 case STATUS_BROKEN:
1729 return "BROKEN";
1730
1731 case STATUS_NOT_RESPONDING:
1732 return "NOT_RESPONDING";
1733
1734 case STATUS_ZOMBIE:
1735 return "ZOMBIE";
1736
1737 default:
1738 return "UNKNOWN";
1739 }
1740}
1741
Jeff Browne839a582010-04-22 18:58:52 -07001742InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
1743 const EventEntry* eventEntry) const {
1744 for (DispatchEntry* dispatchEntry = outboundQueue.tail.prev;
1745 dispatchEntry != & outboundQueue.head; dispatchEntry = dispatchEntry->prev) {
1746 if (dispatchEntry->eventEntry == eventEntry) {
1747 return dispatchEntry;
1748 }
1749 }
1750 return NULL;
1751}
1752
Jeff Brown54bc2812010-06-15 01:31:58 -07001753// --- InputDispatcher::CommandEntry ---
1754
1755InputDispatcher::CommandEntry::CommandEntry() {
1756}
1757
1758InputDispatcher::CommandEntry::~CommandEntry() {
1759}
1760
Jeff Browne839a582010-04-22 18:58:52 -07001761
1762// --- InputDispatcherThread ---
1763
1764InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
1765 Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
1766}
1767
1768InputDispatcherThread::~InputDispatcherThread() {
1769}
1770
1771bool InputDispatcherThread::threadLoop() {
1772 mDispatcher->dispatchOnce();
1773 return true;
1774}
1775
1776} // namespace android