blob: 886c7856debb2b18992d88e46a63cf8be62e8521 [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 Brown542412c2010-08-18 15:51:08 -070031// Log debug messages about input event throttling.
32#define DEBUG_THROTTLING 0
33
Jeff Browne839a582010-04-22 18:58:52 -070034#include <cutils/log.h>
35#include <ui/InputDispatcher.h>
36
37#include <stddef.h>
38#include <unistd.h>
Jeff Browne839a582010-04-22 18:58:52 -070039#include <errno.h>
40#include <limits.h>
Jeff Browne839a582010-04-22 18:58:52 -070041
42namespace android {
43
44// TODO, this needs to be somewhere else, perhaps in the policy
45static inline bool isMovementKey(int32_t keyCode) {
Jeff Brown8575a872010-06-30 16:10:35 -070046 return keyCode == AKEYCODE_DPAD_UP
47 || keyCode == AKEYCODE_DPAD_DOWN
48 || keyCode == AKEYCODE_DPAD_LEFT
49 || keyCode == AKEYCODE_DPAD_RIGHT;
Jeff Browne839a582010-04-22 18:58:52 -070050}
51
Jeff Brown51d45a72010-06-17 20:52:56 -070052static inline nsecs_t now() {
53 return systemTime(SYSTEM_TIME_MONOTONIC);
54}
55
Jeff Browne839a582010-04-22 18:58:52 -070056// --- InputDispatcher ---
57
Jeff Brown54bc2812010-06-15 01:31:58 -070058InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
Jeff Browne839a582010-04-22 18:58:52 -070059 mPolicy(policy) {
Dianne Hackborn3c5d1252010-07-07 14:27:31 -070060 mPollLoop = new PollLoop(false);
Jeff Browne839a582010-04-22 18:58:52 -070061
62 mInboundQueue.head.refCount = -1;
63 mInboundQueue.head.type = EventEntry::TYPE_SENTINEL;
64 mInboundQueue.head.eventTime = LONG_LONG_MIN;
65
66 mInboundQueue.tail.refCount = -1;
67 mInboundQueue.tail.type = EventEntry::TYPE_SENTINEL;
68 mInboundQueue.tail.eventTime = LONG_LONG_MAX;
69
70 mKeyRepeatState.lastKeyEntry = NULL;
Jeff Brown54bc2812010-06-15 01:31:58 -070071
Jeff Brown542412c2010-08-18 15:51:08 -070072 int32_t maxEventsPerSecond = policy->getMaxEventsPerSecond();
73 mThrottleState.minTimeBetweenEvents = 1000000000LL / maxEventsPerSecond;
74 mThrottleState.lastDeviceId = -1;
75
76#if DEBUG_THROTTLING
77 mThrottleState.originalSampleCount = 0;
78 LOGD("Throttling - Max events per second = %d", maxEventsPerSecond);
79#endif
80
Jeff Brown54bc2812010-06-15 01:31:58 -070081 mCurrentInputTargetsValid = false;
Jeff Browne839a582010-04-22 18:58:52 -070082}
83
84InputDispatcher::~InputDispatcher() {
85 resetKeyRepeatLocked();
86
87 while (mConnectionsByReceiveFd.size() != 0) {
88 unregisterInputChannel(mConnectionsByReceiveFd.valueAt(0)->inputChannel);
89 }
90
91 for (EventEntry* entry = mInboundQueue.head.next; entry != & mInboundQueue.tail; ) {
92 EventEntry* next = entry->next;
93 mAllocator.releaseEventEntry(next);
94 entry = next;
95 }
96}
97
98void InputDispatcher::dispatchOnce() {
Jeff Brown54bc2812010-06-15 01:31:58 -070099 nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
Jeff Browne839a582010-04-22 18:58:52 -0700100
Jeff Brown54bc2812010-06-15 01:31:58 -0700101 bool skipPoll = false;
Jeff Browne839a582010-04-22 18:58:52 -0700102 nsecs_t currentTime;
103 nsecs_t nextWakeupTime = LONG_LONG_MAX;
104 { // acquire lock
105 AutoMutex _l(mLock);
Jeff Brown51d45a72010-06-17 20:52:56 -0700106 currentTime = now();
Jeff Browne839a582010-04-22 18:58:52 -0700107
108 // Reset the key repeat timer whenever we disallow key events, even if the next event
109 // is not a key. This is to ensure that we abort a key repeat if the device is just coming
110 // out of sleep.
111 // XXX we should handle resetting input state coming out of sleep more generally elsewhere
Jeff Brown54bc2812010-06-15 01:31:58 -0700112 if (keyRepeatTimeout < 0) {
Jeff Browne839a582010-04-22 18:58:52 -0700113 resetKeyRepeatLocked();
114 }
115
Jeff Brown51d45a72010-06-17 20:52:56 -0700116 // Detect and process timeouts for all connections and determine if there are any
117 // synchronous event dispatches pending. This step is entirely non-interruptible.
Jeff Browne839a582010-04-22 18:58:52 -0700118 bool hasPendingSyncTarget = false;
Jeff Brown51d45a72010-06-17 20:52:56 -0700119 size_t activeConnectionCount = mActiveConnections.size();
120 for (size_t i = 0; i < activeConnectionCount; i++) {
Jeff Browne839a582010-04-22 18:58:52 -0700121 Connection* connection = mActiveConnections.itemAt(i);
122
Jeff Browne839a582010-04-22 18:58:52 -0700123 if (connection->hasPendingSyncTarget()) {
124 hasPendingSyncTarget = true;
125 }
126
Jeff Brown51d45a72010-06-17 20:52:56 -0700127 nsecs_t connectionTimeoutTime = connection->nextTimeoutTime;
128 if (connectionTimeoutTime <= currentTime) {
129 mTimedOutConnections.add(connection);
130 } else if (connectionTimeoutTime < nextWakeupTime) {
131 nextWakeupTime = connectionTimeoutTime;
132 }
Jeff Browne839a582010-04-22 18:58:52 -0700133 }
134
Jeff Brown51d45a72010-06-17 20:52:56 -0700135 size_t timedOutConnectionCount = mTimedOutConnections.size();
136 for (size_t i = 0; i < timedOutConnectionCount; i++) {
137 Connection* connection = mTimedOutConnections.itemAt(i);
138 timeoutDispatchCycleLocked(currentTime, connection);
139 skipPoll = true;
140 }
141 mTimedOutConnections.clear();
142
Jeff Browne839a582010-04-22 18:58:52 -0700143 // If we don't have a pending sync target, then we can begin delivering a new event.
144 // (Otherwise we wait for dispatch to complete for that target.)
145 if (! hasPendingSyncTarget) {
146 if (mInboundQueue.isEmpty()) {
147 if (mKeyRepeatState.lastKeyEntry) {
148 if (currentTime >= mKeyRepeatState.nextRepeatTime) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700149 processKeyRepeatLockedInterruptible(currentTime, keyRepeatTimeout);
150 skipPoll = true;
Jeff Browne839a582010-04-22 18:58:52 -0700151 } else {
152 if (mKeyRepeatState.nextRepeatTime < nextWakeupTime) {
153 nextWakeupTime = mKeyRepeatState.nextRepeatTime;
154 }
155 }
156 }
157 } else {
Jeff Brown54bc2812010-06-15 01:31:58 -0700158 // Inbound queue has at least one entry.
Jeff Brown542412c2010-08-18 15:51:08 -0700159 EventEntry* entry = mInboundQueue.head.next;
160
161 // Consider throttling the entry if it is a move event and there are no
162 // other events behind it in the queue. Due to movement batching, additional
163 // samples may be appended to this event by the time the throttling timeout
164 // expires.
165 // TODO Make this smarter and consider throttling per device independently.
166 if (entry->type == EventEntry::TYPE_MOTION) {
167 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
168 int32_t deviceId = motionEntry->deviceId;
169 uint32_t source = motionEntry->source;
170 if (motionEntry->next == & mInboundQueue.tail
171 && motionEntry->action == AMOTION_EVENT_ACTION_MOVE
172 && deviceId == mThrottleState.lastDeviceId
173 && source == mThrottleState.lastSource) {
174 nsecs_t nextTime = mThrottleState.lastEventTime
175 + mThrottleState.minTimeBetweenEvents;
176 if (currentTime < nextTime) {
177 // Throttle it!
178#if DEBUG_THROTTLING
179 LOGD("Throttling - Delaying motion event for "
180 "device 0x%x, source 0x%08x by up to %0.3fms.",
181 deviceId, source, (nextTime - currentTime) * 0.000001);
182#endif
183 if (nextTime < nextWakeupTime) {
184 nextWakeupTime = nextTime;
185 }
186 if (mThrottleState.originalSampleCount == 0) {
187 mThrottleState.originalSampleCount =
188 motionEntry->countSamples();
189 }
190 goto Throttle;
191 }
192 }
193
194#if DEBUG_THROTTLING
195 if (mThrottleState.originalSampleCount != 0) {
196 uint32_t count = motionEntry->countSamples();
197 LOGD("Throttling - Motion event sample count grew by %d from %d to %d.",
198 count - mThrottleState.originalSampleCount,
199 mThrottleState.originalSampleCount, count);
200 mThrottleState.originalSampleCount = 0;
201 }
202#endif
203
Jeff Brown869347f2010-08-19 11:55:13 -0700204 mThrottleState.lastEventTime = entry->eventTime < currentTime
205 ? entry->eventTime : currentTime;
Jeff Brown542412c2010-08-18 15:51:08 -0700206 mThrottleState.lastDeviceId = deviceId;
207 mThrottleState.lastSource = source;
208 }
209
210 // Start processing the entry but leave it on the queue until later so that the
Jeff Brown54bc2812010-06-15 01:31:58 -0700211 // input reader can keep appending samples onto a motion event between the
212 // time we started processing it and the time we finally enqueue dispatch
213 // entries for it.
Jeff Browne839a582010-04-22 18:58:52 -0700214 switch (entry->type) {
215 case EventEntry::TYPE_CONFIGURATION_CHANGED: {
216 ConfigurationChangedEntry* typedEntry =
217 static_cast<ConfigurationChangedEntry*>(entry);
Jeff Brown54bc2812010-06-15 01:31:58 -0700218 processConfigurationChangedLockedInterruptible(currentTime, typedEntry);
Jeff Browne839a582010-04-22 18:58:52 -0700219 break;
220 }
221
222 case EventEntry::TYPE_KEY: {
223 KeyEntry* typedEntry = static_cast<KeyEntry*>(entry);
Jeff Brown54bc2812010-06-15 01:31:58 -0700224 processKeyLockedInterruptible(currentTime, typedEntry, keyRepeatTimeout);
Jeff Browne839a582010-04-22 18:58:52 -0700225 break;
226 }
227
228 case EventEntry::TYPE_MOTION: {
229 MotionEntry* typedEntry = static_cast<MotionEntry*>(entry);
Jeff Brown54bc2812010-06-15 01:31:58 -0700230 processMotionLockedInterruptible(currentTime, typedEntry);
Jeff Browne839a582010-04-22 18:58:52 -0700231 break;
232 }
233
234 default:
235 assert(false);
236 break;
237 }
Jeff Brown54bc2812010-06-15 01:31:58 -0700238
239 // Dequeue and release the event entry that we just processed.
240 mInboundQueue.dequeue(entry);
241 mAllocator.releaseEventEntry(entry);
242 skipPoll = true;
Jeff Brown542412c2010-08-18 15:51:08 -0700243
244 Throttle: ;
Jeff Browne839a582010-04-22 18:58:52 -0700245 }
246 }
Jeff Brown54bc2812010-06-15 01:31:58 -0700247
248 // Run any deferred commands.
249 skipPoll |= runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700250 } // release lock
251
Jeff Brown54bc2812010-06-15 01:31:58 -0700252 // If we dispatched anything, don't poll just now. Wait for the next iteration.
253 // Contents may have shifted during flight.
254 if (skipPoll) {
255 return;
256 }
257
Jeff Brown542412c2010-08-18 15:51:08 -0700258 // Wait for callback or timeout or wake. (make sure we round up, not down)
259 nsecs_t timeout = (nextWakeupTime - currentTime + 999999LL) / 1000000LL;
Jeff Browne839a582010-04-22 18:58:52 -0700260 int32_t timeoutMillis = timeout > INT_MAX ? -1 : timeout > 0 ? int32_t(timeout) : 0;
261 mPollLoop->pollOnce(timeoutMillis);
262}
263
Jeff Brown54bc2812010-06-15 01:31:58 -0700264bool InputDispatcher::runCommandsLockedInterruptible() {
265 if (mCommandQueue.isEmpty()) {
266 return false;
267 }
Jeff Browne839a582010-04-22 18:58:52 -0700268
Jeff Brown54bc2812010-06-15 01:31:58 -0700269 do {
270 CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
271
272 Command command = commandEntry->command;
273 (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
274
Jeff Brown51d45a72010-06-17 20:52:56 -0700275 commandEntry->connection.clear();
Jeff Brown54bc2812010-06-15 01:31:58 -0700276 mAllocator.releaseCommandEntry(commandEntry);
277 } while (! mCommandQueue.isEmpty());
278 return true;
Jeff Browne839a582010-04-22 18:58:52 -0700279}
280
Jeff Brown54bc2812010-06-15 01:31:58 -0700281InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
282 CommandEntry* commandEntry = mAllocator.obtainCommandEntry(command);
283 mCommandQueue.enqueueAtTail(commandEntry);
284 return commandEntry;
285}
286
287void InputDispatcher::processConfigurationChangedLockedInterruptible(
288 nsecs_t currentTime, ConfigurationChangedEntry* entry) {
289#if DEBUG_OUTBOUND_EVENT_DETAILS
290 LOGD("processConfigurationChanged - eventTime=%lld", entry->eventTime);
291#endif
292
Jeff Brown4036f7f2010-06-29 16:52:21 -0700293 // Reset key repeating in case a keyboard device was added or removed or something.
294 resetKeyRepeatLocked();
295
Jeff Brown54bc2812010-06-15 01:31:58 -0700296 mLock.unlock();
297
298 mPolicy->notifyConfigurationChanged(entry->eventTime);
299
300 mLock.lock();
301}
302
303void InputDispatcher::processKeyLockedInterruptible(
304 nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout) {
Jeff Browne839a582010-04-22 18:58:52 -0700305#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -0700306 LOGD("processKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -0700307 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
Jeff Brown5c1ed842010-07-14 18:48:53 -0700308 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, entry->action,
Jeff Browne839a582010-04-22 18:58:52 -0700309 entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
310 entry->downTime);
311#endif
312
Jeff Brown5c1ed842010-07-14 18:48:53 -0700313 if (entry->action == AKEY_EVENT_ACTION_DOWN && ! entry->isInjected()) {
Jeff Browne839a582010-04-22 18:58:52 -0700314 if (mKeyRepeatState.lastKeyEntry
315 && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
316 // We have seen two identical key downs in a row which indicates that the device
317 // driver is automatically generating key repeats itself. We take note of the
318 // repeat here, but we disable our own next key repeat timer since it is clear that
319 // we will not need to synthesize key repeats ourselves.
320 entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
321 resetKeyRepeatLocked();
322 mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
323 } else {
324 // Not a repeat. Save key down state in case we do see a repeat later.
325 resetKeyRepeatLocked();
Jeff Brown54bc2812010-06-15 01:31:58 -0700326 mKeyRepeatState.nextRepeatTime = entry->eventTime + keyRepeatTimeout;
Jeff Browne839a582010-04-22 18:58:52 -0700327 }
328 mKeyRepeatState.lastKeyEntry = entry;
329 entry->refCount += 1;
330 } else {
331 resetKeyRepeatLocked();
332 }
333
Jeff Brown54bc2812010-06-15 01:31:58 -0700334 identifyInputTargetsAndDispatchKeyLockedInterruptible(currentTime, entry);
Jeff Browne839a582010-04-22 18:58:52 -0700335}
336
Jeff Brown54bc2812010-06-15 01:31:58 -0700337void InputDispatcher::processKeyRepeatLockedInterruptible(
338 nsecs_t currentTime, nsecs_t keyRepeatTimeout) {
Jeff Brown50de30a2010-06-22 01:27:15 -0700339 KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
340
341 // Search the inbound queue for a key up corresponding to this device.
342 // It doesn't make sense to generate a key repeat event if the key is already up.
343 for (EventEntry* queuedEntry = mInboundQueue.head.next;
344 queuedEntry != & mInboundQueue.tail; queuedEntry = entry->next) {
345 if (queuedEntry->type == EventEntry::TYPE_KEY) {
346 KeyEntry* queuedKeyEntry = static_cast<KeyEntry*>(queuedEntry);
347 if (queuedKeyEntry->deviceId == entry->deviceId
Jeff Brown5c1ed842010-07-14 18:48:53 -0700348 && entry->action == AKEY_EVENT_ACTION_UP) {
Jeff Brown50de30a2010-06-22 01:27:15 -0700349 resetKeyRepeatLocked();
350 return;
351 }
352 }
353 }
Jeff Browne839a582010-04-22 18:58:52 -0700354
355 // Synthesize a key repeat after the repeat timeout expired.
Jeff Brown50de30a2010-06-22 01:27:15 -0700356 // Reuse the repeated key entry if it is otherwise unreferenced.
Jeff Brown51d45a72010-06-17 20:52:56 -0700357 uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
Jeff Browne839a582010-04-22 18:58:52 -0700358 if (entry->refCount == 1) {
Jeff Brown51d45a72010-06-17 20:52:56 -0700359 entry->eventTime = currentTime;
Jeff Brown51d45a72010-06-17 20:52:56 -0700360 entry->policyFlags = policyFlags;
Jeff Browne839a582010-04-22 18:58:52 -0700361 entry->repeatCount += 1;
362 } else {
Jeff Brown51d45a72010-06-17 20:52:56 -0700363 KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700364 entry->deviceId, entry->source, policyFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -0700365 entry->action, entry->flags, entry->keyCode, entry->scanCode,
Jeff Brownf16c26d2010-07-02 15:37:36 -0700366 entry->metaState, entry->repeatCount + 1, entry->downTime);
Jeff Browne839a582010-04-22 18:58:52 -0700367
368 mKeyRepeatState.lastKeyEntry = newEntry;
369 mAllocator.releaseKeyEntry(entry);
370
371 entry = newEntry;
372 }
Jeff Browne839a582010-04-22 18:58:52 -0700373
Jeff Brownf16c26d2010-07-02 15:37:36 -0700374 if (entry->repeatCount == 1) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700375 entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
Jeff Brownf16c26d2010-07-02 15:37:36 -0700376 }
377
Jeff Brown54bc2812010-06-15 01:31:58 -0700378 mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatTimeout;
Jeff Browne839a582010-04-22 18:58:52 -0700379
380#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -0700381 LOGD("processKeyRepeat - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -0700382 "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
383 "repeatCount=%d, downTime=%lld",
Jeff Brown5c1ed842010-07-14 18:48:53 -0700384 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
Jeff Browne839a582010-04-22 18:58:52 -0700385 entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
386 entry->repeatCount, entry->downTime);
387#endif
388
Jeff Brown54bc2812010-06-15 01:31:58 -0700389 identifyInputTargetsAndDispatchKeyLockedInterruptible(currentTime, entry);
Jeff Browne839a582010-04-22 18:58:52 -0700390}
391
Jeff Brown54bc2812010-06-15 01:31:58 -0700392void InputDispatcher::processMotionLockedInterruptible(
393 nsecs_t currentTime, MotionEntry* entry) {
Jeff Browne839a582010-04-22 18:58:52 -0700394#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -0700395 LOGD("processMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -0700396 "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
Jeff Brown5c1ed842010-07-14 18:48:53 -0700397 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, entry->action,
Jeff Browne839a582010-04-22 18:58:52 -0700398 entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
399 entry->downTime);
400
401 // Print the most recent sample that we have available, this may change due to batching.
402 size_t sampleCount = 1;
403 MotionSample* sample = & entry->firstSample;
404 for (; sample->next != NULL; sample = sample->next) {
405 sampleCount += 1;
406 }
407 for (uint32_t i = 0; i < entry->pointerCount; i++) {
Jeff Brown38a7fab2010-08-30 03:02:23 -0700408 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
409 "touchMajor=%f, touchMinor=%d, toolMajor=%f, toolMinor=%f, "
410 "orientation=%f",
Jeff Browne839a582010-04-22 18:58:52 -0700411 i, entry->pointerIds[i],
Jeff Brown38a7fab2010-08-30 03:02:23 -0700412 sample->pointerCoords[i].x, sample->pointerCoords[i].y,
413 sample->pointerCoords[i].pressure, sample->pointerCoords[i].size,
414 sample->pointerCoords[i].touchMajor, sample->pointerCoords[i].touchMinor,
415 sample->pointerCoords[i].toolMajor, sample->pointerCoords[i].toolMinor,
416 sample->pointerCoords[i].orientation);
Jeff Browne839a582010-04-22 18:58:52 -0700417 }
418
419 // Keep in mind that due to batching, it is possible for the number of samples actually
420 // dispatched to change before the application finally consumed them.
Jeff Brown5c1ed842010-07-14 18:48:53 -0700421 if (entry->action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Browne839a582010-04-22 18:58:52 -0700422 LOGD(" ... Total movement samples currently batched %d ...", sampleCount);
423 }
424#endif
425
Jeff Brown54bc2812010-06-15 01:31:58 -0700426 identifyInputTargetsAndDispatchMotionLockedInterruptible(currentTime, entry);
Jeff Browne839a582010-04-22 18:58:52 -0700427}
428
Jeff Brown54bc2812010-06-15 01:31:58 -0700429void InputDispatcher::identifyInputTargetsAndDispatchKeyLockedInterruptible(
Jeff Browne839a582010-04-22 18:58:52 -0700430 nsecs_t currentTime, KeyEntry* entry) {
431#if DEBUG_DISPATCH_CYCLE
432 LOGD("identifyInputTargetsAndDispatchKey");
433#endif
434
Jeff Brown54bc2812010-06-15 01:31:58 -0700435 entry->dispatchInProgress = true;
436 mCurrentInputTargetsValid = false;
437 mLock.unlock();
438
Jeff Brown5c1ed842010-07-14 18:48:53 -0700439 mReusableKeyEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
Jeff Browne839a582010-04-22 18:58:52 -0700440 entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
441 entry->downTime, entry->eventTime);
442
443 mCurrentInputTargets.clear();
Jeff Brown50de30a2010-06-22 01:27:15 -0700444 int32_t injectionResult = mPolicy->waitForKeyEventTargets(& mReusableKeyEvent,
Jeff Brown51d45a72010-06-17 20:52:56 -0700445 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Browne839a582010-04-22 18:58:52 -0700446 mCurrentInputTargets);
447
Jeff Brown54bc2812010-06-15 01:31:58 -0700448 mLock.lock();
449 mCurrentInputTargetsValid = true;
450
Jeff Brown51d45a72010-06-17 20:52:56 -0700451 setInjectionResultLocked(entry, injectionResult);
452
Jeff Brown50de30a2010-06-22 01:27:15 -0700453 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
454 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
455 }
Jeff Browne839a582010-04-22 18:58:52 -0700456}
457
Jeff Brown54bc2812010-06-15 01:31:58 -0700458void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(
Jeff Browne839a582010-04-22 18:58:52 -0700459 nsecs_t currentTime, MotionEntry* entry) {
460#if DEBUG_DISPATCH_CYCLE
461 LOGD("identifyInputTargetsAndDispatchMotion");
462#endif
463
Jeff Brown54bc2812010-06-15 01:31:58 -0700464 entry->dispatchInProgress = true;
465 mCurrentInputTargetsValid = false;
466 mLock.unlock();
467
Jeff Brown5c1ed842010-07-14 18:48:53 -0700468 mReusableMotionEvent.initialize(entry->deviceId, entry->source, entry->action,
Jeff Browne839a582010-04-22 18:58:52 -0700469 entry->edgeFlags, entry->metaState,
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700470 0, 0, entry->xPrecision, entry->yPrecision,
Jeff Browne839a582010-04-22 18:58:52 -0700471 entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds,
472 entry->firstSample.pointerCoords);
473
474 mCurrentInputTargets.clear();
Jeff Brown50de30a2010-06-22 01:27:15 -0700475 int32_t injectionResult = mPolicy->waitForMotionEventTargets(& mReusableMotionEvent,
Jeff Brown51d45a72010-06-17 20:52:56 -0700476 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Browne839a582010-04-22 18:58:52 -0700477 mCurrentInputTargets);
478
Jeff Brown54bc2812010-06-15 01:31:58 -0700479 mLock.lock();
480 mCurrentInputTargetsValid = true;
481
Jeff Brown51d45a72010-06-17 20:52:56 -0700482 setInjectionResultLocked(entry, injectionResult);
483
Jeff Brown50de30a2010-06-22 01:27:15 -0700484 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
485 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
486 }
Jeff Browne839a582010-04-22 18:58:52 -0700487}
488
489void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
490 EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
491#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700492 LOGD("dispatchEventToCurrentInputTargets - "
Jeff Browne839a582010-04-22 18:58:52 -0700493 "resumeWithAppendedMotionSample=%s",
494 resumeWithAppendedMotionSample ? "true" : "false");
495#endif
496
Jeff Brown54bc2812010-06-15 01:31:58 -0700497 assert(eventEntry->dispatchInProgress); // should already have been set to true
498
Jeff Browne839a582010-04-22 18:58:52 -0700499 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
500 const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
501
Jeff Brown0cacb872010-08-17 15:59:26 -0700502 ssize_t connectionIndex = getConnectionIndex(inputTarget.inputChannel);
Jeff Browne839a582010-04-22 18:58:52 -0700503 if (connectionIndex >= 0) {
504 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown51d45a72010-06-17 20:52:56 -0700505 prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
Jeff Browne839a582010-04-22 18:58:52 -0700506 resumeWithAppendedMotionSample);
507 } else {
508 LOGW("Framework requested delivery of an input event to channel '%s' but it "
509 "is not registered with the input dispatcher.",
510 inputTarget.inputChannel->getName().string());
511 }
512 }
513}
514
Jeff Brown51d45a72010-06-17 20:52:56 -0700515void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
516 const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
Jeff Browne839a582010-04-22 18:58:52 -0700517 bool resumeWithAppendedMotionSample) {
518#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700519 LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, timeout=%lldns, "
Jeff Browne839a582010-04-22 18:58:52 -0700520 "xOffset=%f, yOffset=%f, resumeWithAppendedMotionSample=%s",
521 connection->getInputChannelName(), inputTarget->flags, inputTarget->timeout,
522 inputTarget->xOffset, inputTarget->yOffset,
523 resumeWithAppendedMotionSample ? "true" : "false");
524#endif
525
526 // Skip this event if the connection status is not normal.
527 // We don't want to queue outbound events at all if the connection is broken or
528 // not responding.
529 if (connection->status != Connection::STATUS_NORMAL) {
530 LOGV("channel '%s' ~ Dropping event because the channel status is %s",
Jeff Brown54bc2812010-06-15 01:31:58 -0700531 connection->getStatusLabel());
Jeff Browne839a582010-04-22 18:58:52 -0700532 return;
533 }
534
535 // Resume the dispatch cycle with a freshly appended motion sample.
536 // First we check that the last dispatch entry in the outbound queue is for the same
537 // motion event to which we appended the motion sample. If we find such a dispatch
538 // entry, and if it is currently in progress then we try to stream the new sample.
539 bool wasEmpty = connection->outboundQueue.isEmpty();
540
541 if (! wasEmpty && resumeWithAppendedMotionSample) {
542 DispatchEntry* motionEventDispatchEntry =
543 connection->findQueuedDispatchEntryForEvent(eventEntry);
544 if (motionEventDispatchEntry) {
545 // If the dispatch entry is not in progress, then we must be busy dispatching an
546 // earlier event. Not a problem, the motion event is on the outbound queue and will
547 // be dispatched later.
548 if (! motionEventDispatchEntry->inProgress) {
549#if DEBUG_BATCHING
550 LOGD("channel '%s' ~ Not streaming because the motion event has "
551 "not yet been dispatched. "
552 "(Waiting for earlier events to be consumed.)",
553 connection->getInputChannelName());
554#endif
555 return;
556 }
557
558 // If the dispatch entry is in progress but it already has a tail of pending
559 // motion samples, then it must mean that the shared memory buffer filled up.
560 // Not a problem, when this dispatch cycle is finished, we will eventually start
561 // a new dispatch cycle to process the tail and that tail includes the newly
562 // appended motion sample.
563 if (motionEventDispatchEntry->tailMotionSample) {
564#if DEBUG_BATCHING
565 LOGD("channel '%s' ~ Not streaming because no new samples can "
566 "be appended to the motion event in this dispatch cycle. "
567 "(Waiting for next dispatch cycle to start.)",
568 connection->getInputChannelName());
569#endif
570 return;
571 }
572
573 // The dispatch entry is in progress and is still potentially open for streaming.
574 // Try to stream the new motion sample. This might fail if the consumer has already
575 // consumed the motion event (or if the channel is broken).
576 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
577 status_t status = connection->inputPublisher.appendMotionSample(
578 appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
579 if (status == OK) {
580#if DEBUG_BATCHING
581 LOGD("channel '%s' ~ Successfully streamed new motion sample.",
582 connection->getInputChannelName());
583#endif
584 return;
585 }
586
587#if DEBUG_BATCHING
588 if (status == NO_MEMORY) {
589 LOGD("channel '%s' ~ Could not append motion sample to currently "
590 "dispatched move event because the shared memory buffer is full. "
591 "(Waiting for next dispatch cycle to start.)",
592 connection->getInputChannelName());
593 } else if (status == status_t(FAILED_TRANSACTION)) {
594 LOGD("channel '%s' ~ Could not append motion sample to currently "
Jeff Brown50de30a2010-06-22 01:27:15 -0700595 "dispatched move event because the event has already been consumed. "
Jeff Browne839a582010-04-22 18:58:52 -0700596 "(Waiting for next dispatch cycle to start.)",
597 connection->getInputChannelName());
598 } else {
599 LOGD("channel '%s' ~ Could not append motion sample to currently "
600 "dispatched move event due to an error, status=%d. "
601 "(Waiting for next dispatch cycle to start.)",
602 connection->getInputChannelName(), status);
603 }
604#endif
605 // Failed to stream. Start a new tail of pending motion samples to dispatch
606 // in the next cycle.
607 motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
608 return;
609 }
610 }
611
612 // This is a new event.
613 // Enqueue a new dispatch entry onto the outbound queue for this connection.
614 DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry); // increments ref
615 dispatchEntry->targetFlags = inputTarget->flags;
616 dispatchEntry->xOffset = inputTarget->xOffset;
617 dispatchEntry->yOffset = inputTarget->yOffset;
618 dispatchEntry->timeout = inputTarget->timeout;
619 dispatchEntry->inProgress = false;
620 dispatchEntry->headMotionSample = NULL;
621 dispatchEntry->tailMotionSample = NULL;
622
Jeff Brownf67c53e2010-07-28 15:48:59 -0700623 if (dispatchEntry->isSyncTarget()) {
624 eventEntry->pendingSyncDispatches += 1;
625 }
626
Jeff Browne839a582010-04-22 18:58:52 -0700627 // Handle the case where we could not stream a new motion sample because the consumer has
628 // already consumed the motion event (otherwise the corresponding dispatch entry would
629 // still be in the outbound queue for this connection). We set the head motion sample
630 // to the list starting with the newly appended motion sample.
631 if (resumeWithAppendedMotionSample) {
632#if DEBUG_BATCHING
633 LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
634 "that cannot be streamed because the motion event has already been consumed.",
635 connection->getInputChannelName());
636#endif
637 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
638 dispatchEntry->headMotionSample = appendedMotionSample;
639 }
640
641 // Enqueue the dispatch entry.
642 connection->outboundQueue.enqueueAtTail(dispatchEntry);
643
644 // If the outbound queue was previously empty, start the dispatch cycle going.
645 if (wasEmpty) {
Jeff Brown51d45a72010-06-17 20:52:56 -0700646 activateConnectionLocked(connection.get());
Jeff Browne839a582010-04-22 18:58:52 -0700647 startDispatchCycleLocked(currentTime, connection);
648 }
649}
650
Jeff Brown51d45a72010-06-17 20:52:56 -0700651void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
652 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -0700653#if DEBUG_DISPATCH_CYCLE
654 LOGD("channel '%s' ~ startDispatchCycle",
655 connection->getInputChannelName());
656#endif
657
658 assert(connection->status == Connection::STATUS_NORMAL);
659 assert(! connection->outboundQueue.isEmpty());
660
661 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
662 assert(! dispatchEntry->inProgress);
663
664 // TODO throttle successive ACTION_MOVE motion events for the same device
665 // possible implementation could set a brief poll timeout here and resume starting the
666 // dispatch cycle when elapsed
667
668 // Publish the event.
669 status_t status;
670 switch (dispatchEntry->eventEntry->type) {
671 case EventEntry::TYPE_KEY: {
672 KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
673
674 // Apply target flags.
675 int32_t action = keyEntry->action;
676 int32_t flags = keyEntry->flags;
677 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700678 flags |= AKEY_EVENT_FLAG_CANCELED;
Jeff Browne839a582010-04-22 18:58:52 -0700679 }
680
681 // Publish the key event.
Jeff Brown5c1ed842010-07-14 18:48:53 -0700682 status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
Jeff Browne839a582010-04-22 18:58:52 -0700683 action, flags, keyEntry->keyCode, keyEntry->scanCode,
684 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
685 keyEntry->eventTime);
686
687 if (status) {
688 LOGE("channel '%s' ~ Could not publish key event, "
689 "status=%d", connection->getInputChannelName(), status);
690 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
691 return;
692 }
693 break;
694 }
695
696 case EventEntry::TYPE_MOTION: {
697 MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
698
699 // Apply target flags.
700 int32_t action = motionEntry->action;
701 if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700702 action = AMOTION_EVENT_ACTION_OUTSIDE;
Jeff Browne839a582010-04-22 18:58:52 -0700703 }
704 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700705 action = AMOTION_EVENT_ACTION_CANCEL;
Jeff Browne839a582010-04-22 18:58:52 -0700706 }
707
708 // If headMotionSample is non-NULL, then it points to the first new sample that we
709 // were unable to dispatch during the previous cycle so we resume dispatching from
710 // that point in the list of motion samples.
711 // Otherwise, we just start from the first sample of the motion event.
712 MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
713 if (! firstMotionSample) {
714 firstMotionSample = & motionEntry->firstSample;
715 }
716
Jeff Brownf26db0d2010-07-16 17:21:06 -0700717 // Set the X and Y offset depending on the input source.
718 float xOffset, yOffset;
719 if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
720 xOffset = dispatchEntry->xOffset;
721 yOffset = dispatchEntry->yOffset;
722 } else {
723 xOffset = 0.0f;
724 yOffset = 0.0f;
725 }
726
Jeff Browne839a582010-04-22 18:58:52 -0700727 // Publish the motion event and the first motion sample.
728 status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700729 motionEntry->source, action, motionEntry->edgeFlags, motionEntry->metaState,
Jeff Brownf26db0d2010-07-16 17:21:06 -0700730 xOffset, yOffset,
Jeff Browne839a582010-04-22 18:58:52 -0700731 motionEntry->xPrecision, motionEntry->yPrecision,
732 motionEntry->downTime, firstMotionSample->eventTime,
733 motionEntry->pointerCount, motionEntry->pointerIds,
734 firstMotionSample->pointerCoords);
735
736 if (status) {
737 LOGE("channel '%s' ~ Could not publish motion event, "
738 "status=%d", connection->getInputChannelName(), status);
739 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
740 return;
741 }
742
743 // Append additional motion samples.
744 MotionSample* nextMotionSample = firstMotionSample->next;
745 for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
746 status = connection->inputPublisher.appendMotionSample(
747 nextMotionSample->eventTime, nextMotionSample->pointerCoords);
748 if (status == NO_MEMORY) {
749#if DEBUG_DISPATCH_CYCLE
750 LOGD("channel '%s' ~ Shared memory buffer full. Some motion samples will "
751 "be sent in the next dispatch cycle.",
752 connection->getInputChannelName());
753#endif
754 break;
755 }
756 if (status != OK) {
757 LOGE("channel '%s' ~ Could not append motion sample "
758 "for a reason other than out of memory, status=%d",
759 connection->getInputChannelName(), status);
760 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
761 return;
762 }
763 }
764
765 // Remember the next motion sample that we could not dispatch, in case we ran out
766 // of space in the shared memory buffer.
767 dispatchEntry->tailMotionSample = nextMotionSample;
768 break;
769 }
770
771 default: {
772 assert(false);
773 }
774 }
775
776 // Send the dispatch signal.
777 status = connection->inputPublisher.sendDispatchSignal();
778 if (status) {
779 LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
780 connection->getInputChannelName(), status);
781 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
782 return;
783 }
784
785 // Record information about the newly started dispatch cycle.
786 dispatchEntry->inProgress = true;
787
788 connection->lastEventTime = dispatchEntry->eventEntry->eventTime;
789 connection->lastDispatchTime = currentTime;
790
791 nsecs_t timeout = dispatchEntry->timeout;
Jeff Brown51d45a72010-06-17 20:52:56 -0700792 connection->setNextTimeoutTime(currentTime, timeout);
Jeff Browne839a582010-04-22 18:58:52 -0700793
794 // Notify other system components.
795 onDispatchCycleStartedLocked(currentTime, connection);
796}
797
Jeff Brown51d45a72010-06-17 20:52:56 -0700798void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
799 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -0700800#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700801 LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
Jeff Browne839a582010-04-22 18:58:52 -0700802 "%01.1fms since dispatch",
803 connection->getInputChannelName(),
804 connection->getEventLatencyMillis(currentTime),
805 connection->getDispatchLatencyMillis(currentTime));
806#endif
807
Jeff Brown54bc2812010-06-15 01:31:58 -0700808 if (connection->status == Connection::STATUS_BROKEN
809 || connection->status == Connection::STATUS_ZOMBIE) {
Jeff Browne839a582010-04-22 18:58:52 -0700810 return;
811 }
812
813 // Clear the pending timeout.
814 connection->nextTimeoutTime = LONG_LONG_MAX;
815
816 if (connection->status == Connection::STATUS_NOT_RESPONDING) {
817 // Recovering from an ANR.
818 connection->status = Connection::STATUS_NORMAL;
819
820 // Notify other system components.
821 onDispatchCycleFinishedLocked(currentTime, connection, true /*recoveredFromANR*/);
822 } else {
823 // Normal finish. Not much to do here.
824
825 // Notify other system components.
826 onDispatchCycleFinishedLocked(currentTime, connection, false /*recoveredFromANR*/);
827 }
828
829 // Reset the publisher since the event has been consumed.
830 // We do this now so that the publisher can release some of its internal resources
831 // while waiting for the next dispatch cycle to begin.
832 status_t status = connection->inputPublisher.reset();
833 if (status) {
834 LOGE("channel '%s' ~ Could not reset publisher, status=%d",
835 connection->getInputChannelName(), status);
836 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
837 return;
838 }
839
840 // Start the next dispatch cycle for this connection.
841 while (! connection->outboundQueue.isEmpty()) {
842 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
843 if (dispatchEntry->inProgress) {
844 // Finish or resume current event in progress.
845 if (dispatchEntry->tailMotionSample) {
846 // We have a tail of undispatched motion samples.
847 // Reuse the same DispatchEntry and start a new cycle.
848 dispatchEntry->inProgress = false;
849 dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
850 dispatchEntry->tailMotionSample = NULL;
851 startDispatchCycleLocked(currentTime, connection);
852 return;
853 }
854 // Finished.
855 connection->outboundQueue.dequeueAtHead();
Jeff Brownf67c53e2010-07-28 15:48:59 -0700856 if (dispatchEntry->isSyncTarget()) {
857 decrementPendingSyncDispatchesLocked(dispatchEntry->eventEntry);
858 }
Jeff Browne839a582010-04-22 18:58:52 -0700859 mAllocator.releaseDispatchEntry(dispatchEntry);
860 } else {
861 // If the head is not in progress, then we must have already dequeued the in
862 // progress event, which means we actually aborted it (due to ANR).
863 // So just start the next event for this connection.
864 startDispatchCycleLocked(currentTime, connection);
865 return;
866 }
867 }
868
869 // Outbound queue is empty, deactivate the connection.
Jeff Brown51d45a72010-06-17 20:52:56 -0700870 deactivateConnectionLocked(connection.get());
Jeff Browne839a582010-04-22 18:58:52 -0700871}
872
Jeff Brown51d45a72010-06-17 20:52:56 -0700873void InputDispatcher::timeoutDispatchCycleLocked(nsecs_t currentTime,
874 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -0700875#if DEBUG_DISPATCH_CYCLE
876 LOGD("channel '%s' ~ timeoutDispatchCycle",
877 connection->getInputChannelName());
878#endif
879
880 if (connection->status != Connection::STATUS_NORMAL) {
Jeff Brown51d45a72010-06-17 20:52:56 -0700881 return;
Jeff Browne839a582010-04-22 18:58:52 -0700882 }
883
884 // Enter the not responding state.
885 connection->status = Connection::STATUS_NOT_RESPONDING;
886 connection->lastANRTime = currentTime;
Jeff Browne839a582010-04-22 18:58:52 -0700887
888 // Notify other system components.
Jeff Brown51d45a72010-06-17 20:52:56 -0700889 // This enqueues a command which will eventually either call
890 // resumeAfterTimeoutDispatchCycleLocked or abortDispatchCycleLocked.
Jeff Browne839a582010-04-22 18:58:52 -0700891 onDispatchCycleANRLocked(currentTime, connection);
Jeff Browne839a582010-04-22 18:58:52 -0700892}
893
Jeff Brown51d45a72010-06-17 20:52:56 -0700894void InputDispatcher::resumeAfterTimeoutDispatchCycleLocked(nsecs_t currentTime,
895 const sp<Connection>& connection, nsecs_t newTimeout) {
896#if DEBUG_DISPATCH_CYCLE
897 LOGD("channel '%s' ~ resumeAfterTimeoutDispatchCycleLocked",
898 connection->getInputChannelName());
899#endif
900
901 if (connection->status != Connection::STATUS_NOT_RESPONDING) {
902 return;
903 }
904
905 // Resume normal dispatch.
906 connection->status = Connection::STATUS_NORMAL;
907 connection->setNextTimeoutTime(currentTime, newTimeout);
908}
909
910void InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime,
911 const sp<Connection>& connection, bool broken) {
Jeff Browne839a582010-04-22 18:58:52 -0700912#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700913 LOGD("channel '%s' ~ abortDispatchCycle - broken=%s",
Jeff Browne839a582010-04-22 18:58:52 -0700914 connection->getInputChannelName(), broken ? "true" : "false");
915#endif
916
Jeff Browne839a582010-04-22 18:58:52 -0700917 // Clear the pending timeout.
918 connection->nextTimeoutTime = LONG_LONG_MAX;
919
920 // Clear the outbound queue.
Jeff Brown51d45a72010-06-17 20:52:56 -0700921 if (! connection->outboundQueue.isEmpty()) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700922 do {
923 DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
Jeff Brownf67c53e2010-07-28 15:48:59 -0700924 if (dispatchEntry->isSyncTarget()) {
925 decrementPendingSyncDispatchesLocked(dispatchEntry->eventEntry);
926 }
Jeff Brown54bc2812010-06-15 01:31:58 -0700927 mAllocator.releaseDispatchEntry(dispatchEntry);
928 } while (! connection->outboundQueue.isEmpty());
Jeff Browne839a582010-04-22 18:58:52 -0700929
Jeff Brown51d45a72010-06-17 20:52:56 -0700930 deactivateConnectionLocked(connection.get());
Jeff Brown54bc2812010-06-15 01:31:58 -0700931 }
Jeff Browne839a582010-04-22 18:58:52 -0700932
933 // Handle the case where the connection appears to be unrecoverably broken.
Jeff Brown54bc2812010-06-15 01:31:58 -0700934 // Ignore already broken or zombie connections.
Jeff Browne839a582010-04-22 18:58:52 -0700935 if (broken) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700936 if (connection->status == Connection::STATUS_NORMAL
937 || connection->status == Connection::STATUS_NOT_RESPONDING) {
938 connection->status = Connection::STATUS_BROKEN;
Jeff Browne839a582010-04-22 18:58:52 -0700939
Jeff Brown54bc2812010-06-15 01:31:58 -0700940 // Notify other system components.
941 onDispatchCycleBrokenLocked(currentTime, connection);
942 }
Jeff Browne839a582010-04-22 18:58:52 -0700943 }
Jeff Browne839a582010-04-22 18:58:52 -0700944}
945
946bool InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
947 InputDispatcher* d = static_cast<InputDispatcher*>(data);
948
949 { // acquire lock
950 AutoMutex _l(d->mLock);
951
952 ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
953 if (connectionIndex < 0) {
954 LOGE("Received spurious receive callback for unknown input channel. "
955 "fd=%d, events=0x%x", receiveFd, events);
956 return false; // remove the callback
957 }
958
Jeff Brown51d45a72010-06-17 20:52:56 -0700959 nsecs_t currentTime = now();
Jeff Browne839a582010-04-22 18:58:52 -0700960
961 sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
962 if (events & (POLLERR | POLLHUP | POLLNVAL)) {
963 LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
964 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brown51d45a72010-06-17 20:52:56 -0700965 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -0700966 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700967 return false; // remove the callback
968 }
969
970 if (! (events & POLLIN)) {
971 LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
972 "events=0x%x", connection->getInputChannelName(), events);
973 return true;
974 }
975
976 status_t status = connection->inputPublisher.receiveFinishedSignal();
977 if (status) {
978 LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
979 connection->getInputChannelName(), status);
Jeff Brown51d45a72010-06-17 20:52:56 -0700980 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -0700981 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700982 return false; // remove the callback
983 }
984
Jeff Brown51d45a72010-06-17 20:52:56 -0700985 d->finishDispatchCycleLocked(currentTime, connection);
Jeff Brown54bc2812010-06-15 01:31:58 -0700986 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700987 return true;
988 } // release lock
989}
990
Jeff Brown54bc2812010-06-15 01:31:58 -0700991void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
Jeff Browne839a582010-04-22 18:58:52 -0700992#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown54bc2812010-06-15 01:31:58 -0700993 LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
Jeff Browne839a582010-04-22 18:58:52 -0700994#endif
995
996 bool wasEmpty;
997 { // acquire lock
998 AutoMutex _l(mLock);
999
Jeff Brown51d45a72010-06-17 20:52:56 -07001000 ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
Jeff Browne839a582010-04-22 18:58:52 -07001001
1002 wasEmpty = mInboundQueue.isEmpty();
1003 mInboundQueue.enqueueAtTail(newEntry);
1004 } // release lock
1005
1006 if (wasEmpty) {
1007 mPollLoop->wake();
1008 }
1009}
1010
Jeff Browne839a582010-04-22 18:58:52 -07001011void InputDispatcher::notifyAppSwitchComing(nsecs_t eventTime) {
1012#if DEBUG_INBOUND_EVENT_DETAILS
1013 LOGD("notifyAppSwitchComing - eventTime=%lld", eventTime);
1014#endif
1015
1016 // Remove movement keys from the queue from most recent to least recent, stopping at the
1017 // first non-movement key.
1018 // TODO: Include a detailed description of why we do this...
1019
1020 { // acquire lock
1021 AutoMutex _l(mLock);
1022
1023 for (EventEntry* entry = mInboundQueue.tail.prev; entry != & mInboundQueue.head; ) {
1024 EventEntry* prev = entry->prev;
1025
1026 if (entry->type == EventEntry::TYPE_KEY) {
1027 KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
1028 if (isMovementKey(keyEntry->keyCode)) {
1029 LOGV("Dropping movement key during app switch: keyCode=%d, action=%d",
1030 keyEntry->keyCode, keyEntry->action);
1031 mInboundQueue.dequeue(keyEntry);
Jeff Brown51d45a72010-06-17 20:52:56 -07001032
1033 setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
1034
Jeff Browne839a582010-04-22 18:58:52 -07001035 mAllocator.releaseKeyEntry(keyEntry);
1036 } else {
1037 // stop at last non-movement key
1038 break;
1039 }
1040 }
1041
1042 entry = prev;
1043 }
1044 } // release lock
1045}
1046
Jeff Brown5c1ed842010-07-14 18:48:53 -07001047void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Browne839a582010-04-22 18:58:52 -07001048 uint32_t policyFlags, int32_t action, int32_t flags,
1049 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
1050#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -07001051 LOGD("notifyKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -07001052 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
Jeff Brown5c1ed842010-07-14 18:48:53 -07001053 eventTime, deviceId, source, policyFlags, action, flags,
Jeff Browne839a582010-04-22 18:58:52 -07001054 keyCode, scanCode, metaState, downTime);
1055#endif
1056
1057 bool wasEmpty;
1058 { // acquire lock
1059 AutoMutex _l(mLock);
1060
Jeff Brown51d45a72010-06-17 20:52:56 -07001061 int32_t repeatCount = 0;
1062 KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001063 deviceId, source, policyFlags, action, flags, keyCode, scanCode,
Jeff Brown51d45a72010-06-17 20:52:56 -07001064 metaState, repeatCount, downTime);
Jeff Browne839a582010-04-22 18:58:52 -07001065
1066 wasEmpty = mInboundQueue.isEmpty();
1067 mInboundQueue.enqueueAtTail(newEntry);
1068 } // release lock
1069
1070 if (wasEmpty) {
1071 mPollLoop->wake();
1072 }
1073}
1074
Jeff Brown5c1ed842010-07-14 18:48:53 -07001075void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Browne839a582010-04-22 18:58:52 -07001076 uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
1077 uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
1078 float xPrecision, float yPrecision, nsecs_t downTime) {
1079#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -07001080 LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -07001081 "action=0x%x, metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, "
1082 "downTime=%lld",
Jeff Brown5c1ed842010-07-14 18:48:53 -07001083 eventTime, deviceId, source, policyFlags, action, metaState, edgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07001084 xPrecision, yPrecision, downTime);
1085 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001086 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
1087 "touchMajor=%f, touchMinor=%d, toolMajor=%f, toolMinor=%f, "
1088 "orientation=%f",
Jeff Browne839a582010-04-22 18:58:52 -07001089 i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
Jeff Brown38a7fab2010-08-30 03:02:23 -07001090 pointerCoords[i].pressure, pointerCoords[i].size,
1091 pointerCoords[i].touchMajor, pointerCoords[i].touchMinor,
1092 pointerCoords[i].toolMajor, pointerCoords[i].toolMinor,
1093 pointerCoords[i].orientation);
Jeff Browne839a582010-04-22 18:58:52 -07001094 }
1095#endif
1096
1097 bool wasEmpty;
1098 { // acquire lock
1099 AutoMutex _l(mLock);
1100
1101 // Attempt batching and streaming of move events.
Jeff Brown5c1ed842010-07-14 18:48:53 -07001102 if (action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Browne839a582010-04-22 18:58:52 -07001103 // BATCHING CASE
1104 //
1105 // Try to append a move sample to the tail of the inbound queue for this device.
1106 // Give up if we encounter a non-move motion event for this device since that
1107 // means we cannot append any new samples until a new motion event has started.
1108 for (EventEntry* entry = mInboundQueue.tail.prev;
1109 entry != & mInboundQueue.head; entry = entry->prev) {
1110 if (entry->type != EventEntry::TYPE_MOTION) {
1111 // Keep looking for motion events.
1112 continue;
1113 }
1114
1115 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
1116 if (motionEntry->deviceId != deviceId) {
1117 // Keep looking for this device.
1118 continue;
1119 }
1120
Jeff Brown5c1ed842010-07-14 18:48:53 -07001121 if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown51d45a72010-06-17 20:52:56 -07001122 || motionEntry->pointerCount != pointerCount
1123 || motionEntry->isInjected()) {
Jeff Browne839a582010-04-22 18:58:52 -07001124 // Last motion event in the queue for this device is not compatible for
1125 // appending new samples. Stop here.
1126 goto NoBatchingOrStreaming;
1127 }
1128
1129 // The last motion event is a move and is compatible for appending.
Jeff Brown54bc2812010-06-15 01:31:58 -07001130 // Do the batching magic.
Jeff Brown51d45a72010-06-17 20:52:56 -07001131 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
Jeff Browne839a582010-04-22 18:58:52 -07001132#if DEBUG_BATCHING
1133 LOGD("Appended motion sample onto batch for most recent "
1134 "motion event for this device in the inbound queue.");
1135#endif
Jeff Brown54bc2812010-06-15 01:31:58 -07001136
1137 // Sanity check for special case because dispatch is interruptible.
1138 // The dispatch logic is partially interruptible and releases its lock while
1139 // identifying targets. However, as soon as the targets have been identified,
1140 // the dispatcher proceeds to write a dispatch entry into all relevant outbound
1141 // queues and then promptly removes the motion entry from the queue.
1142 //
1143 // Consequently, we should never observe the case where the inbound queue contains
1144 // an in-progress motion entry unless the current input targets are invalid
1145 // (currently being computed). Check for this!
1146 assert(! (motionEntry->dispatchInProgress && mCurrentInputTargetsValid));
1147
1148 return; // done!
Jeff Browne839a582010-04-22 18:58:52 -07001149 }
1150
1151 // STREAMING CASE
1152 //
1153 // There is no pending motion event (of any kind) for this device in the inbound queue.
1154 // Search the outbound queues for a synchronously dispatched motion event for this
1155 // device. If found, then we append the new sample to that event and then try to
1156 // push it out to all current targets. It is possible that some targets will already
1157 // have consumed the motion event. This case is automatically handled by the
1158 // logic in prepareDispatchCycleLocked by tracking where resumption takes place.
1159 //
1160 // The reason we look for a synchronously dispatched motion event is because we
1161 // want to be sure that no other motion events have been dispatched since the move.
1162 // It's also convenient because it means that the input targets are still valid.
1163 // This code could be improved to support streaming of asynchronously dispatched
1164 // motion events (which might be significantly more efficient) but it may become
1165 // a little more complicated as a result.
1166 //
1167 // Note: This code crucially depends on the invariant that an outbound queue always
1168 // contains at most one synchronous event and it is always last (but it might
1169 // not be first!).
Jeff Brown54bc2812010-06-15 01:31:58 -07001170 if (mCurrentInputTargetsValid) {
1171 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1172 Connection* connection = mActiveConnections.itemAt(i);
1173 if (! connection->outboundQueue.isEmpty()) {
1174 DispatchEntry* dispatchEntry = connection->outboundQueue.tail.prev;
Jeff Brownf67c53e2010-07-28 15:48:59 -07001175 if (dispatchEntry->isSyncTarget()) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001176 if (dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION) {
1177 goto NoBatchingOrStreaming;
1178 }
Jeff Browne839a582010-04-22 18:58:52 -07001179
Jeff Brown54bc2812010-06-15 01:31:58 -07001180 MotionEntry* syncedMotionEntry = static_cast<MotionEntry*>(
1181 dispatchEntry->eventEntry);
Jeff Brown5c1ed842010-07-14 18:48:53 -07001182 if (syncedMotionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown54bc2812010-06-15 01:31:58 -07001183 || syncedMotionEntry->deviceId != deviceId
Jeff Brown51d45a72010-06-17 20:52:56 -07001184 || syncedMotionEntry->pointerCount != pointerCount
1185 || syncedMotionEntry->isInjected()) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001186 goto NoBatchingOrStreaming;
1187 }
Jeff Browne839a582010-04-22 18:58:52 -07001188
Jeff Brown54bc2812010-06-15 01:31:58 -07001189 // Found synced move entry. Append sample and resume dispatch.
1190 mAllocator.appendMotionSample(syncedMotionEntry, eventTime,
Jeff Brown51d45a72010-06-17 20:52:56 -07001191 pointerCoords);
Jeff Brown54bc2812010-06-15 01:31:58 -07001192 #if DEBUG_BATCHING
1193 LOGD("Appended motion sample onto batch for most recent synchronously "
1194 "dispatched motion event for this device in the outbound queues.");
1195 #endif
Jeff Brown51d45a72010-06-17 20:52:56 -07001196 nsecs_t currentTime = now();
Jeff Brown54bc2812010-06-15 01:31:58 -07001197 dispatchEventToCurrentInputTargetsLocked(currentTime, syncedMotionEntry,
1198 true /*resumeWithAppendedMotionSample*/);
1199
1200 runCommandsLockedInterruptible();
1201 return; // done!
1202 }
Jeff Browne839a582010-04-22 18:58:52 -07001203 }
1204 }
1205 }
1206
1207NoBatchingOrStreaming:;
1208 }
1209
1210 // Just enqueue a new motion event.
Jeff Brown51d45a72010-06-17 20:52:56 -07001211 MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001212 deviceId, source, policyFlags, action, metaState, edgeFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -07001213 xPrecision, yPrecision, downTime,
1214 pointerCount, pointerIds, pointerCoords);
Jeff Browne839a582010-04-22 18:58:52 -07001215
1216 wasEmpty = mInboundQueue.isEmpty();
1217 mInboundQueue.enqueueAtTail(newEntry);
1218 } // release lock
1219
1220 if (wasEmpty) {
1221 mPollLoop->wake();
1222 }
1223}
1224
Jeff Brown51d45a72010-06-17 20:52:56 -07001225int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
Jeff Brownf67c53e2010-07-28 15:48:59 -07001226 int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001227#if DEBUG_INBOUND_EVENT_DETAILS
1228 LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
Jeff Brownf67c53e2010-07-28 15:48:59 -07001229 "syncMode=%d, timeoutMillis=%d",
1230 event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis);
Jeff Brown51d45a72010-06-17 20:52:56 -07001231#endif
1232
1233 nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
1234
1235 EventEntry* injectedEntry;
1236 bool wasEmpty;
1237 { // acquire lock
1238 AutoMutex _l(mLock);
1239
1240 injectedEntry = createEntryFromInputEventLocked(event);
1241 injectedEntry->refCount += 1;
1242 injectedEntry->injectorPid = injectorPid;
1243 injectedEntry->injectorUid = injectorUid;
1244
Jeff Brownf67c53e2010-07-28 15:48:59 -07001245 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
1246 injectedEntry->injectionIsAsync = true;
1247 }
1248
Jeff Brown51d45a72010-06-17 20:52:56 -07001249 wasEmpty = mInboundQueue.isEmpty();
1250 mInboundQueue.enqueueAtTail(injectedEntry);
1251
1252 } // release lock
1253
1254 if (wasEmpty) {
1255 mPollLoop->wake();
1256 }
1257
1258 int32_t injectionResult;
1259 { // acquire lock
1260 AutoMutex _l(mLock);
1261
Jeff Brownf67c53e2010-07-28 15:48:59 -07001262 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
1263 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1264 } else {
1265 for (;;) {
1266 injectionResult = injectedEntry->injectionResult;
1267 if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
1268 break;
1269 }
Jeff Brown51d45a72010-06-17 20:52:56 -07001270
Jeff Brown51d45a72010-06-17 20:52:56 -07001271 nsecs_t remainingTimeout = endTime - now();
1272 if (remainingTimeout <= 0) {
Jeff Brownf67c53e2010-07-28 15:48:59 -07001273#if DEBUG_INJECTION
1274 LOGD("injectInputEvent - Timed out waiting for injection result "
1275 "to become available.");
1276#endif
Jeff Brown51d45a72010-06-17 20:52:56 -07001277 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1278 break;
1279 }
1280
Jeff Brownf67c53e2010-07-28 15:48:59 -07001281 mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
1282 }
1283
1284 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
1285 && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
1286 while (injectedEntry->pendingSyncDispatches != 0) {
1287#if DEBUG_INJECTION
1288 LOGD("injectInputEvent - Waiting for %d pending synchronous dispatches.",
1289 injectedEntry->pendingSyncDispatches);
1290#endif
1291 nsecs_t remainingTimeout = endTime - now();
1292 if (remainingTimeout <= 0) {
1293#if DEBUG_INJECTION
1294 LOGD("injectInputEvent - Timed out waiting for pending synchronous "
1295 "dispatches to finish.");
1296#endif
1297 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1298 break;
1299 }
1300
1301 mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
1302 }
Jeff Brown51d45a72010-06-17 20:52:56 -07001303 }
1304 }
1305
1306 mAllocator.releaseEventEntry(injectedEntry);
1307 } // release lock
1308
Jeff Brownf67c53e2010-07-28 15:48:59 -07001309#if DEBUG_INJECTION
1310 LOGD("injectInputEvent - Finished with result %d. "
1311 "injectorPid=%d, injectorUid=%d",
1312 injectionResult, injectorPid, injectorUid);
1313#endif
1314
Jeff Brown51d45a72010-06-17 20:52:56 -07001315 return injectionResult;
1316}
1317
1318void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
1319 if (entry->isInjected()) {
1320#if DEBUG_INJECTION
1321 LOGD("Setting input event injection result to %d. "
1322 "injectorPid=%d, injectorUid=%d",
1323 injectionResult, entry->injectorPid, entry->injectorUid);
1324#endif
1325
Jeff Brownf67c53e2010-07-28 15:48:59 -07001326 if (entry->injectionIsAsync) {
1327 // Log the outcome since the injector did not wait for the injection result.
1328 switch (injectionResult) {
1329 case INPUT_EVENT_INJECTION_SUCCEEDED:
1330 LOGV("Asynchronous input event injection succeeded.");
1331 break;
1332 case INPUT_EVENT_INJECTION_FAILED:
1333 LOGW("Asynchronous input event injection failed.");
1334 break;
1335 case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
1336 LOGW("Asynchronous input event injection permission denied.");
1337 break;
1338 case INPUT_EVENT_INJECTION_TIMED_OUT:
1339 LOGW("Asynchronous input event injection timed out.");
1340 break;
1341 }
1342 }
1343
Jeff Brown51d45a72010-06-17 20:52:56 -07001344 entry->injectionResult = injectionResult;
1345 mInjectionResultAvailableCondition.broadcast();
1346 }
1347}
1348
Jeff Brownf67c53e2010-07-28 15:48:59 -07001349void InputDispatcher::decrementPendingSyncDispatchesLocked(EventEntry* entry) {
1350 entry->pendingSyncDispatches -= 1;
1351
1352 if (entry->isInjected() && entry->pendingSyncDispatches == 0) {
1353 mInjectionSyncFinishedCondition.broadcast();
1354 }
Jeff Brown51d45a72010-06-17 20:52:56 -07001355}
1356
1357InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked(
1358 const InputEvent* event) {
1359 switch (event->getType()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07001360 case AINPUT_EVENT_TYPE_KEY: {
Jeff Brown51d45a72010-06-17 20:52:56 -07001361 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
1362 uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
1363
1364 KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
Jeff Brown5c1ed842010-07-14 18:48:53 -07001365 keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -07001366 keyEvent->getAction(), keyEvent->getFlags(),
1367 keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
1368 keyEvent->getRepeatCount(), keyEvent->getDownTime());
1369 return keyEntry;
1370 }
1371
Jeff Brown5c1ed842010-07-14 18:48:53 -07001372 case AINPUT_EVENT_TYPE_MOTION: {
Jeff Brown51d45a72010-06-17 20:52:56 -07001373 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
1374 uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
1375
1376 const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
1377 const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
1378 size_t pointerCount = motionEvent->getPointerCount();
1379
1380 MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001381 motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -07001382 motionEvent->getAction(), motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
1383 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
1384 motionEvent->getDownTime(), uint32_t(pointerCount),
1385 motionEvent->getPointerIds(), samplePointerCoords);
1386 for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
1387 sampleEventTimes += 1;
1388 samplePointerCoords += pointerCount;
1389 mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
1390 }
1391 return motionEntry;
1392 }
1393
1394 default:
1395 assert(false);
1396 return NULL;
1397 }
1398}
1399
Jeff Browne839a582010-04-22 18:58:52 -07001400void InputDispatcher::resetKeyRepeatLocked() {
1401 if (mKeyRepeatState.lastKeyEntry) {
1402 mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
1403 mKeyRepeatState.lastKeyEntry = NULL;
1404 }
1405}
1406
Jeff Brown50de30a2010-06-22 01:27:15 -07001407void InputDispatcher::preemptInputDispatch() {
1408#if DEBUG_DISPATCH_CYCLE
1409 LOGD("preemptInputDispatch");
1410#endif
1411
1412 bool preemptedOne = false;
1413 { // acquire lock
1414 AutoMutex _l(mLock);
1415
1416 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1417 Connection* connection = mActiveConnections[i];
1418 if (connection->hasPendingSyncTarget()) {
1419#if DEBUG_DISPATCH_CYCLE
1420 LOGD("channel '%s' ~ Preempted pending synchronous dispatch",
1421 connection->getInputChannelName());
1422#endif
1423 connection->outboundQueue.tail.prev->targetFlags &= ~ InputTarget::FLAG_SYNC;
1424 preemptedOne = true;
1425 }
1426 }
1427 } // release lock
1428
1429 if (preemptedOne) {
1430 // Wake up the poll loop so it can get a head start dispatching the next event.
1431 mPollLoop->wake();
1432 }
1433}
1434
Jeff Browne839a582010-04-22 18:58:52 -07001435status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001436#if DEBUG_REGISTRATION
Jeff Brown50de30a2010-06-22 01:27:15 -07001437 LOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().string());
Jeff Brown54bc2812010-06-15 01:31:58 -07001438#endif
1439
Jeff Browne839a582010-04-22 18:58:52 -07001440 { // acquire lock
1441 AutoMutex _l(mLock);
1442
Jeff Brown0cacb872010-08-17 15:59:26 -07001443 if (getConnectionIndex(inputChannel) >= 0) {
Jeff Browne839a582010-04-22 18:58:52 -07001444 LOGW("Attempted to register already registered input channel '%s'",
1445 inputChannel->getName().string());
1446 return BAD_VALUE;
1447 }
1448
1449 sp<Connection> connection = new Connection(inputChannel);
1450 status_t status = connection->initialize();
1451 if (status) {
1452 LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
1453 inputChannel->getName().string(), status);
1454 return status;
1455 }
1456
Jeff Brown0cacb872010-08-17 15:59:26 -07001457 int32_t receiveFd = inputChannel->getReceivePipeFd();
Jeff Browne839a582010-04-22 18:58:52 -07001458 mConnectionsByReceiveFd.add(receiveFd, connection);
Jeff Brown54bc2812010-06-15 01:31:58 -07001459
Jeff Brown0cacb872010-08-17 15:59:26 -07001460 mPollLoop->setCallback(receiveFd, POLLIN, handleReceiveCallback, this);
1461
Jeff Brown54bc2812010-06-15 01:31:58 -07001462 runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07001463 } // release lock
Jeff Browne839a582010-04-22 18:58:52 -07001464 return OK;
1465}
1466
1467status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001468#if DEBUG_REGISTRATION
Jeff Brown50de30a2010-06-22 01:27:15 -07001469 LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
Jeff Brown54bc2812010-06-15 01:31:58 -07001470#endif
1471
Jeff Browne839a582010-04-22 18:58:52 -07001472 { // acquire lock
1473 AutoMutex _l(mLock);
1474
Jeff Brown0cacb872010-08-17 15:59:26 -07001475 ssize_t connectionIndex = getConnectionIndex(inputChannel);
Jeff Browne839a582010-04-22 18:58:52 -07001476 if (connectionIndex < 0) {
1477 LOGW("Attempted to unregister already unregistered input channel '%s'",
1478 inputChannel->getName().string());
1479 return BAD_VALUE;
1480 }
1481
1482 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1483 mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
1484
1485 connection->status = Connection::STATUS_ZOMBIE;
1486
Jeff Brown0cacb872010-08-17 15:59:26 -07001487 mPollLoop->removeCallback(inputChannel->getReceivePipeFd());
1488
Jeff Brown51d45a72010-06-17 20:52:56 -07001489 nsecs_t currentTime = now();
1490 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -07001491
1492 runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07001493 } // release lock
1494
Jeff Browne839a582010-04-22 18:58:52 -07001495 // Wake the poll loop because removing the connection may have changed the current
1496 // synchronization state.
1497 mPollLoop->wake();
1498 return OK;
1499}
1500
Jeff Brown0cacb872010-08-17 15:59:26 -07001501ssize_t InputDispatcher::getConnectionIndex(const sp<InputChannel>& inputChannel) {
1502 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(inputChannel->getReceivePipeFd());
1503 if (connectionIndex >= 0) {
1504 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1505 if (connection->inputChannel.get() == inputChannel.get()) {
1506 return connectionIndex;
1507 }
1508 }
1509
1510 return -1;
1511}
1512
Jeff Browne839a582010-04-22 18:58:52 -07001513void InputDispatcher::activateConnectionLocked(Connection* connection) {
1514 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1515 if (mActiveConnections.itemAt(i) == connection) {
1516 return;
1517 }
1518 }
1519 mActiveConnections.add(connection);
1520}
1521
1522void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
1523 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1524 if (mActiveConnections.itemAt(i) == connection) {
1525 mActiveConnections.removeAt(i);
1526 return;
1527 }
1528 }
1529}
1530
Jeff Brown54bc2812010-06-15 01:31:58 -07001531void InputDispatcher::onDispatchCycleStartedLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001532 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001533}
1534
Jeff Brown54bc2812010-06-15 01:31:58 -07001535void InputDispatcher::onDispatchCycleFinishedLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001536 nsecs_t currentTime, const sp<Connection>& connection, bool recoveredFromANR) {
Jeff Browne839a582010-04-22 18:58:52 -07001537 if (recoveredFromANR) {
1538 LOGI("channel '%s' ~ Recovered from ANR. %01.1fms since event, "
1539 "%01.1fms since dispatch, %01.1fms since ANR",
1540 connection->getInputChannelName(),
1541 connection->getEventLatencyMillis(currentTime),
1542 connection->getDispatchLatencyMillis(currentTime),
1543 connection->getANRLatencyMillis(currentTime));
1544
Jeff Brown54bc2812010-06-15 01:31:58 -07001545 CommandEntry* commandEntry = postCommandLocked(
1546 & InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07001547 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07001548 }
1549}
1550
Jeff Brown54bc2812010-06-15 01:31:58 -07001551void InputDispatcher::onDispatchCycleANRLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001552 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001553 LOGI("channel '%s' ~ Not responding! %01.1fms since event, %01.1fms since dispatch",
1554 connection->getInputChannelName(),
1555 connection->getEventLatencyMillis(currentTime),
1556 connection->getDispatchLatencyMillis(currentTime));
1557
Jeff Brown54bc2812010-06-15 01:31:58 -07001558 CommandEntry* commandEntry = postCommandLocked(
1559 & InputDispatcher::doNotifyInputChannelANRLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07001560 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07001561}
1562
Jeff Brown54bc2812010-06-15 01:31:58 -07001563void InputDispatcher::onDispatchCycleBrokenLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001564 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001565 LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
1566 connection->getInputChannelName());
1567
Jeff Brown54bc2812010-06-15 01:31:58 -07001568 CommandEntry* commandEntry = postCommandLocked(
1569 & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07001570 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07001571}
1572
Jeff Brown54bc2812010-06-15 01:31:58 -07001573void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
1574 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001575 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07001576
Jeff Brown51d45a72010-06-17 20:52:56 -07001577 if (connection->status != Connection::STATUS_ZOMBIE) {
1578 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07001579
Jeff Brown51d45a72010-06-17 20:52:56 -07001580 mPolicy->notifyInputChannelBroken(connection->inputChannel);
1581
1582 mLock.lock();
1583 }
Jeff Brown54bc2812010-06-15 01:31:58 -07001584}
1585
1586void InputDispatcher::doNotifyInputChannelANRLockedInterruptible(
1587 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001588 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07001589
Jeff Brown51d45a72010-06-17 20:52:56 -07001590 if (connection->status != Connection::STATUS_ZOMBIE) {
1591 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07001592
Jeff Brown51d45a72010-06-17 20:52:56 -07001593 nsecs_t newTimeout;
1594 bool resume = mPolicy->notifyInputChannelANR(connection->inputChannel, newTimeout);
1595
1596 mLock.lock();
1597
1598 nsecs_t currentTime = now();
1599 if (resume) {
1600 resumeAfterTimeoutDispatchCycleLocked(currentTime, connection, newTimeout);
1601 } else {
1602 abortDispatchCycleLocked(currentTime, connection, false /*(not) broken*/);
1603 }
1604 }
Jeff Brown54bc2812010-06-15 01:31:58 -07001605}
1606
1607void InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible(
1608 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001609 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07001610
Jeff Brown51d45a72010-06-17 20:52:56 -07001611 if (connection->status != Connection::STATUS_ZOMBIE) {
1612 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07001613
Jeff Brown51d45a72010-06-17 20:52:56 -07001614 mPolicy->notifyInputChannelRecoveredFromANR(connection->inputChannel);
1615
1616 mLock.lock();
1617 }
Jeff Brown54bc2812010-06-15 01:31:58 -07001618}
1619
1620
Jeff Browne839a582010-04-22 18:58:52 -07001621// --- InputDispatcher::Allocator ---
1622
1623InputDispatcher::Allocator::Allocator() {
1624}
1625
Jeff Brown51d45a72010-06-17 20:52:56 -07001626void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
1627 nsecs_t eventTime) {
1628 entry->type = type;
1629 entry->refCount = 1;
1630 entry->dispatchInProgress = false;
Christopher Tated974e002010-06-23 16:50:30 -07001631 entry->eventTime = eventTime;
Jeff Brown51d45a72010-06-17 20:52:56 -07001632 entry->injectionResult = INPUT_EVENT_INJECTION_PENDING;
Jeff Brownf67c53e2010-07-28 15:48:59 -07001633 entry->injectionIsAsync = false;
Jeff Brown51d45a72010-06-17 20:52:56 -07001634 entry->injectorPid = -1;
1635 entry->injectorUid = -1;
Jeff Brownf67c53e2010-07-28 15:48:59 -07001636 entry->pendingSyncDispatches = 0;
Jeff Brown51d45a72010-06-17 20:52:56 -07001637}
1638
Jeff Browne839a582010-04-22 18:58:52 -07001639InputDispatcher::ConfigurationChangedEntry*
Jeff Brown51d45a72010-06-17 20:52:56 -07001640InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
Jeff Browne839a582010-04-22 18:58:52 -07001641 ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07001642 initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime);
Jeff Browne839a582010-04-22 18:58:52 -07001643 return entry;
1644}
1645
Jeff Brown51d45a72010-06-17 20:52:56 -07001646InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001647 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
Jeff Brown51d45a72010-06-17 20:52:56 -07001648 int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
1649 int32_t repeatCount, nsecs_t downTime) {
Jeff Browne839a582010-04-22 18:58:52 -07001650 KeyEntry* entry = mKeyEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07001651 initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime);
1652
1653 entry->deviceId = deviceId;
Jeff Brown5c1ed842010-07-14 18:48:53 -07001654 entry->source = source;
Jeff Brown51d45a72010-06-17 20:52:56 -07001655 entry->policyFlags = policyFlags;
1656 entry->action = action;
1657 entry->flags = flags;
1658 entry->keyCode = keyCode;
1659 entry->scanCode = scanCode;
1660 entry->metaState = metaState;
1661 entry->repeatCount = repeatCount;
1662 entry->downTime = downTime;
Jeff Browne839a582010-04-22 18:58:52 -07001663 return entry;
1664}
1665
Jeff Brown51d45a72010-06-17 20:52:56 -07001666InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001667 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
Jeff Brown51d45a72010-06-17 20:52:56 -07001668 int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
1669 nsecs_t downTime, uint32_t pointerCount,
1670 const int32_t* pointerIds, const PointerCoords* pointerCoords) {
Jeff Browne839a582010-04-22 18:58:52 -07001671 MotionEntry* entry = mMotionEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07001672 initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime);
1673
1674 entry->eventTime = eventTime;
1675 entry->deviceId = deviceId;
Jeff Brown5c1ed842010-07-14 18:48:53 -07001676 entry->source = source;
Jeff Brown51d45a72010-06-17 20:52:56 -07001677 entry->policyFlags = policyFlags;
1678 entry->action = action;
1679 entry->metaState = metaState;
1680 entry->edgeFlags = edgeFlags;
1681 entry->xPrecision = xPrecision;
1682 entry->yPrecision = yPrecision;
1683 entry->downTime = downTime;
1684 entry->pointerCount = pointerCount;
1685 entry->firstSample.eventTime = eventTime;
Jeff Browne839a582010-04-22 18:58:52 -07001686 entry->firstSample.next = NULL;
Jeff Brown51d45a72010-06-17 20:52:56 -07001687 entry->lastSample = & entry->firstSample;
1688 for (uint32_t i = 0; i < pointerCount; i++) {
1689 entry->pointerIds[i] = pointerIds[i];
1690 entry->firstSample.pointerCoords[i] = pointerCoords[i];
1691 }
Jeff Browne839a582010-04-22 18:58:52 -07001692 return entry;
1693}
1694
1695InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
1696 EventEntry* eventEntry) {
1697 DispatchEntry* entry = mDispatchEntryPool.alloc();
1698 entry->eventEntry = eventEntry;
1699 eventEntry->refCount += 1;
1700 return entry;
1701}
1702
Jeff Brown54bc2812010-06-15 01:31:58 -07001703InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
1704 CommandEntry* entry = mCommandEntryPool.alloc();
1705 entry->command = command;
1706 return entry;
1707}
1708
Jeff Browne839a582010-04-22 18:58:52 -07001709void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
1710 switch (entry->type) {
1711 case EventEntry::TYPE_CONFIGURATION_CHANGED:
1712 releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
1713 break;
1714 case EventEntry::TYPE_KEY:
1715 releaseKeyEntry(static_cast<KeyEntry*>(entry));
1716 break;
1717 case EventEntry::TYPE_MOTION:
1718 releaseMotionEntry(static_cast<MotionEntry*>(entry));
1719 break;
1720 default:
1721 assert(false);
1722 break;
1723 }
1724}
1725
1726void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
1727 ConfigurationChangedEntry* entry) {
1728 entry->refCount -= 1;
1729 if (entry->refCount == 0) {
1730 mConfigurationChangeEntryPool.free(entry);
1731 } else {
1732 assert(entry->refCount > 0);
1733 }
1734}
1735
1736void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
1737 entry->refCount -= 1;
1738 if (entry->refCount == 0) {
1739 mKeyEntryPool.free(entry);
1740 } else {
1741 assert(entry->refCount > 0);
1742 }
1743}
1744
1745void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
1746 entry->refCount -= 1;
1747 if (entry->refCount == 0) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001748 for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
1749 MotionSample* next = sample->next;
1750 mMotionSamplePool.free(sample);
1751 sample = next;
1752 }
Jeff Browne839a582010-04-22 18:58:52 -07001753 mMotionEntryPool.free(entry);
1754 } else {
1755 assert(entry->refCount > 0);
1756 }
1757}
1758
1759void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
1760 releaseEventEntry(entry->eventEntry);
1761 mDispatchEntryPool.free(entry);
1762}
1763
Jeff Brown54bc2812010-06-15 01:31:58 -07001764void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
1765 mCommandEntryPool.free(entry);
1766}
1767
Jeff Browne839a582010-04-22 18:58:52 -07001768void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
Jeff Brown51d45a72010-06-17 20:52:56 -07001769 nsecs_t eventTime, const PointerCoords* pointerCoords) {
Jeff Browne839a582010-04-22 18:58:52 -07001770 MotionSample* sample = mMotionSamplePool.alloc();
1771 sample->eventTime = eventTime;
Jeff Brown51d45a72010-06-17 20:52:56 -07001772 uint32_t pointerCount = motionEntry->pointerCount;
1773 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Browne839a582010-04-22 18:58:52 -07001774 sample->pointerCoords[i] = pointerCoords[i];
1775 }
1776
1777 sample->next = NULL;
1778 motionEntry->lastSample->next = sample;
1779 motionEntry->lastSample = sample;
1780}
1781
Jeff Brown542412c2010-08-18 15:51:08 -07001782// --- InputDispatcher::MotionEntry ---
1783
1784uint32_t InputDispatcher::MotionEntry::countSamples() const {
1785 uint32_t count = 1;
1786 for (MotionSample* sample = firstSample.next; sample != NULL; sample = sample->next) {
1787 count += 1;
1788 }
1789 return count;
1790}
1791
Jeff Browne839a582010-04-22 18:58:52 -07001792// --- InputDispatcher::Connection ---
1793
1794InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
1795 status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
1796 nextTimeoutTime(LONG_LONG_MAX),
1797 lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX),
1798 lastANRTime(LONG_LONG_MAX) {
1799}
1800
1801InputDispatcher::Connection::~Connection() {
1802}
1803
1804status_t InputDispatcher::Connection::initialize() {
1805 return inputPublisher.initialize();
1806}
1807
Jeff Brown51d45a72010-06-17 20:52:56 -07001808void InputDispatcher::Connection::setNextTimeoutTime(nsecs_t currentTime, nsecs_t timeout) {
1809 nextTimeoutTime = (timeout >= 0) ? currentTime + timeout : LONG_LONG_MAX;
1810}
1811
Jeff Brown54bc2812010-06-15 01:31:58 -07001812const char* InputDispatcher::Connection::getStatusLabel() const {
1813 switch (status) {
1814 case STATUS_NORMAL:
1815 return "NORMAL";
1816
1817 case STATUS_BROKEN:
1818 return "BROKEN";
1819
1820 case STATUS_NOT_RESPONDING:
1821 return "NOT_RESPONDING";
1822
1823 case STATUS_ZOMBIE:
1824 return "ZOMBIE";
1825
1826 default:
1827 return "UNKNOWN";
1828 }
1829}
1830
Jeff Browne839a582010-04-22 18:58:52 -07001831InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
1832 const EventEntry* eventEntry) const {
1833 for (DispatchEntry* dispatchEntry = outboundQueue.tail.prev;
1834 dispatchEntry != & outboundQueue.head; dispatchEntry = dispatchEntry->prev) {
1835 if (dispatchEntry->eventEntry == eventEntry) {
1836 return dispatchEntry;
1837 }
1838 }
1839 return NULL;
1840}
1841
Jeff Brown54bc2812010-06-15 01:31:58 -07001842// --- InputDispatcher::CommandEntry ---
1843
1844InputDispatcher::CommandEntry::CommandEntry() {
1845}
1846
1847InputDispatcher::CommandEntry::~CommandEntry() {
1848}
1849
Jeff Browne839a582010-04-22 18:58:52 -07001850
1851// --- InputDispatcherThread ---
1852
1853InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
1854 Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
1855}
1856
1857InputDispatcherThread::~InputDispatcherThread() {
1858}
1859
1860bool InputDispatcherThread::threadLoop() {
1861 mDispatcher->dispatchOnce();
1862 return true;
1863}
1864
1865} // namespace android