blob: e35050cb6e4cfd8eca077fe61c30ee0514e4845b [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++) {
408 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
409 i, entry->pointerIds[i],
410 sample->pointerCoords[i].x,
411 sample->pointerCoords[i].y,
412 sample->pointerCoords[i].pressure,
413 sample->pointerCoords[i].size);
414 }
415
416 // Keep in mind that due to batching, it is possible for the number of samples actually
417 // dispatched to change before the application finally consumed them.
Jeff Brown5c1ed842010-07-14 18:48:53 -0700418 if (entry->action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Browne839a582010-04-22 18:58:52 -0700419 LOGD(" ... Total movement samples currently batched %d ...", sampleCount);
420 }
421#endif
422
Jeff Brown54bc2812010-06-15 01:31:58 -0700423 identifyInputTargetsAndDispatchMotionLockedInterruptible(currentTime, entry);
Jeff Browne839a582010-04-22 18:58:52 -0700424}
425
Jeff Brown54bc2812010-06-15 01:31:58 -0700426void InputDispatcher::identifyInputTargetsAndDispatchKeyLockedInterruptible(
Jeff Browne839a582010-04-22 18:58:52 -0700427 nsecs_t currentTime, KeyEntry* entry) {
428#if DEBUG_DISPATCH_CYCLE
429 LOGD("identifyInputTargetsAndDispatchKey");
430#endif
431
Jeff Brown54bc2812010-06-15 01:31:58 -0700432 entry->dispatchInProgress = true;
433 mCurrentInputTargetsValid = false;
434 mLock.unlock();
435
Jeff Brown5c1ed842010-07-14 18:48:53 -0700436 mReusableKeyEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
Jeff Browne839a582010-04-22 18:58:52 -0700437 entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
438 entry->downTime, entry->eventTime);
439
440 mCurrentInputTargets.clear();
Jeff Brown50de30a2010-06-22 01:27:15 -0700441 int32_t injectionResult = mPolicy->waitForKeyEventTargets(& mReusableKeyEvent,
Jeff Brown51d45a72010-06-17 20:52:56 -0700442 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Browne839a582010-04-22 18:58:52 -0700443 mCurrentInputTargets);
444
Jeff Brown54bc2812010-06-15 01:31:58 -0700445 mLock.lock();
446 mCurrentInputTargetsValid = true;
447
Jeff Brown51d45a72010-06-17 20:52:56 -0700448 setInjectionResultLocked(entry, injectionResult);
449
Jeff Brown50de30a2010-06-22 01:27:15 -0700450 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
451 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
452 }
Jeff Browne839a582010-04-22 18:58:52 -0700453}
454
Jeff Brown54bc2812010-06-15 01:31:58 -0700455void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(
Jeff Browne839a582010-04-22 18:58:52 -0700456 nsecs_t currentTime, MotionEntry* entry) {
457#if DEBUG_DISPATCH_CYCLE
458 LOGD("identifyInputTargetsAndDispatchMotion");
459#endif
460
Jeff Brown54bc2812010-06-15 01:31:58 -0700461 entry->dispatchInProgress = true;
462 mCurrentInputTargetsValid = false;
463 mLock.unlock();
464
Jeff Brown5c1ed842010-07-14 18:48:53 -0700465 mReusableMotionEvent.initialize(entry->deviceId, entry->source, entry->action,
Jeff Browne839a582010-04-22 18:58:52 -0700466 entry->edgeFlags, entry->metaState,
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700467 0, 0, entry->xPrecision, entry->yPrecision,
Jeff Browne839a582010-04-22 18:58:52 -0700468 entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds,
469 entry->firstSample.pointerCoords);
470
471 mCurrentInputTargets.clear();
Jeff Brown50de30a2010-06-22 01:27:15 -0700472 int32_t injectionResult = mPolicy->waitForMotionEventTargets(& mReusableMotionEvent,
Jeff Brown51d45a72010-06-17 20:52:56 -0700473 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Browne839a582010-04-22 18:58:52 -0700474 mCurrentInputTargets);
475
Jeff Brown54bc2812010-06-15 01:31:58 -0700476 mLock.lock();
477 mCurrentInputTargetsValid = true;
478
Jeff Brown51d45a72010-06-17 20:52:56 -0700479 setInjectionResultLocked(entry, injectionResult);
480
Jeff Brown50de30a2010-06-22 01:27:15 -0700481 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
482 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
483 }
Jeff Browne839a582010-04-22 18:58:52 -0700484}
485
486void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
487 EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
488#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700489 LOGD("dispatchEventToCurrentInputTargets - "
Jeff Browne839a582010-04-22 18:58:52 -0700490 "resumeWithAppendedMotionSample=%s",
491 resumeWithAppendedMotionSample ? "true" : "false");
492#endif
493
Jeff Brown54bc2812010-06-15 01:31:58 -0700494 assert(eventEntry->dispatchInProgress); // should already have been set to true
495
Jeff Browne839a582010-04-22 18:58:52 -0700496 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
497 const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
498
Jeff Brown0cacb872010-08-17 15:59:26 -0700499 ssize_t connectionIndex = getConnectionIndex(inputTarget.inputChannel);
Jeff Browne839a582010-04-22 18:58:52 -0700500 if (connectionIndex >= 0) {
501 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown51d45a72010-06-17 20:52:56 -0700502 prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
Jeff Browne839a582010-04-22 18:58:52 -0700503 resumeWithAppendedMotionSample);
504 } else {
505 LOGW("Framework requested delivery of an input event to channel '%s' but it "
506 "is not registered with the input dispatcher.",
507 inputTarget.inputChannel->getName().string());
508 }
509 }
510}
511
Jeff Brown51d45a72010-06-17 20:52:56 -0700512void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
513 const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
Jeff Browne839a582010-04-22 18:58:52 -0700514 bool resumeWithAppendedMotionSample) {
515#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700516 LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, timeout=%lldns, "
Jeff Browne839a582010-04-22 18:58:52 -0700517 "xOffset=%f, yOffset=%f, resumeWithAppendedMotionSample=%s",
518 connection->getInputChannelName(), inputTarget->flags, inputTarget->timeout,
519 inputTarget->xOffset, inputTarget->yOffset,
520 resumeWithAppendedMotionSample ? "true" : "false");
521#endif
522
523 // Skip this event if the connection status is not normal.
524 // We don't want to queue outbound events at all if the connection is broken or
525 // not responding.
526 if (connection->status != Connection::STATUS_NORMAL) {
527 LOGV("channel '%s' ~ Dropping event because the channel status is %s",
Jeff Brown54bc2812010-06-15 01:31:58 -0700528 connection->getStatusLabel());
Jeff Browne839a582010-04-22 18:58:52 -0700529 return;
530 }
531
532 // Resume the dispatch cycle with a freshly appended motion sample.
533 // First we check that the last dispatch entry in the outbound queue is for the same
534 // motion event to which we appended the motion sample. If we find such a dispatch
535 // entry, and if it is currently in progress then we try to stream the new sample.
536 bool wasEmpty = connection->outboundQueue.isEmpty();
537
538 if (! wasEmpty && resumeWithAppendedMotionSample) {
539 DispatchEntry* motionEventDispatchEntry =
540 connection->findQueuedDispatchEntryForEvent(eventEntry);
541 if (motionEventDispatchEntry) {
542 // If the dispatch entry is not in progress, then we must be busy dispatching an
543 // earlier event. Not a problem, the motion event is on the outbound queue and will
544 // be dispatched later.
545 if (! motionEventDispatchEntry->inProgress) {
546#if DEBUG_BATCHING
547 LOGD("channel '%s' ~ Not streaming because the motion event has "
548 "not yet been dispatched. "
549 "(Waiting for earlier events to be consumed.)",
550 connection->getInputChannelName());
551#endif
552 return;
553 }
554
555 // If the dispatch entry is in progress but it already has a tail of pending
556 // motion samples, then it must mean that the shared memory buffer filled up.
557 // Not a problem, when this dispatch cycle is finished, we will eventually start
558 // a new dispatch cycle to process the tail and that tail includes the newly
559 // appended motion sample.
560 if (motionEventDispatchEntry->tailMotionSample) {
561#if DEBUG_BATCHING
562 LOGD("channel '%s' ~ Not streaming because no new samples can "
563 "be appended to the motion event in this dispatch cycle. "
564 "(Waiting for next dispatch cycle to start.)",
565 connection->getInputChannelName());
566#endif
567 return;
568 }
569
570 // The dispatch entry is in progress and is still potentially open for streaming.
571 // Try to stream the new motion sample. This might fail if the consumer has already
572 // consumed the motion event (or if the channel is broken).
573 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
574 status_t status = connection->inputPublisher.appendMotionSample(
575 appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
576 if (status == OK) {
577#if DEBUG_BATCHING
578 LOGD("channel '%s' ~ Successfully streamed new motion sample.",
579 connection->getInputChannelName());
580#endif
581 return;
582 }
583
584#if DEBUG_BATCHING
585 if (status == NO_MEMORY) {
586 LOGD("channel '%s' ~ Could not append motion sample to currently "
587 "dispatched move event because the shared memory buffer is full. "
588 "(Waiting for next dispatch cycle to start.)",
589 connection->getInputChannelName());
590 } else if (status == status_t(FAILED_TRANSACTION)) {
591 LOGD("channel '%s' ~ Could not append motion sample to currently "
Jeff Brown50de30a2010-06-22 01:27:15 -0700592 "dispatched move event because the event has already been consumed. "
Jeff Browne839a582010-04-22 18:58:52 -0700593 "(Waiting for next dispatch cycle to start.)",
594 connection->getInputChannelName());
595 } else {
596 LOGD("channel '%s' ~ Could not append motion sample to currently "
597 "dispatched move event due to an error, status=%d. "
598 "(Waiting for next dispatch cycle to start.)",
599 connection->getInputChannelName(), status);
600 }
601#endif
602 // Failed to stream. Start a new tail of pending motion samples to dispatch
603 // in the next cycle.
604 motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
605 return;
606 }
607 }
608
609 // This is a new event.
610 // Enqueue a new dispatch entry onto the outbound queue for this connection.
611 DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry); // increments ref
612 dispatchEntry->targetFlags = inputTarget->flags;
613 dispatchEntry->xOffset = inputTarget->xOffset;
614 dispatchEntry->yOffset = inputTarget->yOffset;
615 dispatchEntry->timeout = inputTarget->timeout;
616 dispatchEntry->inProgress = false;
617 dispatchEntry->headMotionSample = NULL;
618 dispatchEntry->tailMotionSample = NULL;
619
Jeff Brownf67c53e2010-07-28 15:48:59 -0700620 if (dispatchEntry->isSyncTarget()) {
621 eventEntry->pendingSyncDispatches += 1;
622 }
623
Jeff Browne839a582010-04-22 18:58:52 -0700624 // Handle the case where we could not stream a new motion sample because the consumer has
625 // already consumed the motion event (otherwise the corresponding dispatch entry would
626 // still be in the outbound queue for this connection). We set the head motion sample
627 // to the list starting with the newly appended motion sample.
628 if (resumeWithAppendedMotionSample) {
629#if DEBUG_BATCHING
630 LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
631 "that cannot be streamed because the motion event has already been consumed.",
632 connection->getInputChannelName());
633#endif
634 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
635 dispatchEntry->headMotionSample = appendedMotionSample;
636 }
637
638 // Enqueue the dispatch entry.
639 connection->outboundQueue.enqueueAtTail(dispatchEntry);
640
641 // If the outbound queue was previously empty, start the dispatch cycle going.
642 if (wasEmpty) {
Jeff Brown51d45a72010-06-17 20:52:56 -0700643 activateConnectionLocked(connection.get());
Jeff Browne839a582010-04-22 18:58:52 -0700644 startDispatchCycleLocked(currentTime, connection);
645 }
646}
647
Jeff Brown51d45a72010-06-17 20:52:56 -0700648void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
649 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -0700650#if DEBUG_DISPATCH_CYCLE
651 LOGD("channel '%s' ~ startDispatchCycle",
652 connection->getInputChannelName());
653#endif
654
655 assert(connection->status == Connection::STATUS_NORMAL);
656 assert(! connection->outboundQueue.isEmpty());
657
658 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
659 assert(! dispatchEntry->inProgress);
660
661 // TODO throttle successive ACTION_MOVE motion events for the same device
662 // possible implementation could set a brief poll timeout here and resume starting the
663 // dispatch cycle when elapsed
664
665 // Publish the event.
666 status_t status;
667 switch (dispatchEntry->eventEntry->type) {
668 case EventEntry::TYPE_KEY: {
669 KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
670
671 // Apply target flags.
672 int32_t action = keyEntry->action;
673 int32_t flags = keyEntry->flags;
674 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700675 flags |= AKEY_EVENT_FLAG_CANCELED;
Jeff Browne839a582010-04-22 18:58:52 -0700676 }
677
678 // Publish the key event.
Jeff Brown5c1ed842010-07-14 18:48:53 -0700679 status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
Jeff Browne839a582010-04-22 18:58:52 -0700680 action, flags, keyEntry->keyCode, keyEntry->scanCode,
681 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
682 keyEntry->eventTime);
683
684 if (status) {
685 LOGE("channel '%s' ~ Could not publish key event, "
686 "status=%d", connection->getInputChannelName(), status);
687 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
688 return;
689 }
690 break;
691 }
692
693 case EventEntry::TYPE_MOTION: {
694 MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
695
696 // Apply target flags.
697 int32_t action = motionEntry->action;
698 if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700699 action = AMOTION_EVENT_ACTION_OUTSIDE;
Jeff Browne839a582010-04-22 18:58:52 -0700700 }
701 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700702 action = AMOTION_EVENT_ACTION_CANCEL;
Jeff Browne839a582010-04-22 18:58:52 -0700703 }
704
705 // If headMotionSample is non-NULL, then it points to the first new sample that we
706 // were unable to dispatch during the previous cycle so we resume dispatching from
707 // that point in the list of motion samples.
708 // Otherwise, we just start from the first sample of the motion event.
709 MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
710 if (! firstMotionSample) {
711 firstMotionSample = & motionEntry->firstSample;
712 }
713
Jeff Brownf26db0d2010-07-16 17:21:06 -0700714 // Set the X and Y offset depending on the input source.
715 float xOffset, yOffset;
716 if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
717 xOffset = dispatchEntry->xOffset;
718 yOffset = dispatchEntry->yOffset;
719 } else {
720 xOffset = 0.0f;
721 yOffset = 0.0f;
722 }
723
Jeff Browne839a582010-04-22 18:58:52 -0700724 // Publish the motion event and the first motion sample.
725 status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700726 motionEntry->source, action, motionEntry->edgeFlags, motionEntry->metaState,
Jeff Brownf26db0d2010-07-16 17:21:06 -0700727 xOffset, yOffset,
Jeff Browne839a582010-04-22 18:58:52 -0700728 motionEntry->xPrecision, motionEntry->yPrecision,
729 motionEntry->downTime, firstMotionSample->eventTime,
730 motionEntry->pointerCount, motionEntry->pointerIds,
731 firstMotionSample->pointerCoords);
732
733 if (status) {
734 LOGE("channel '%s' ~ Could not publish motion event, "
735 "status=%d", connection->getInputChannelName(), status);
736 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
737 return;
738 }
739
740 // Append additional motion samples.
741 MotionSample* nextMotionSample = firstMotionSample->next;
742 for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
743 status = connection->inputPublisher.appendMotionSample(
744 nextMotionSample->eventTime, nextMotionSample->pointerCoords);
745 if (status == NO_MEMORY) {
746#if DEBUG_DISPATCH_CYCLE
747 LOGD("channel '%s' ~ Shared memory buffer full. Some motion samples will "
748 "be sent in the next dispatch cycle.",
749 connection->getInputChannelName());
750#endif
751 break;
752 }
753 if (status != OK) {
754 LOGE("channel '%s' ~ Could not append motion sample "
755 "for a reason other than out of memory, status=%d",
756 connection->getInputChannelName(), status);
757 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
758 return;
759 }
760 }
761
762 // Remember the next motion sample that we could not dispatch, in case we ran out
763 // of space in the shared memory buffer.
764 dispatchEntry->tailMotionSample = nextMotionSample;
765 break;
766 }
767
768 default: {
769 assert(false);
770 }
771 }
772
773 // Send the dispatch signal.
774 status = connection->inputPublisher.sendDispatchSignal();
775 if (status) {
776 LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
777 connection->getInputChannelName(), status);
778 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
779 return;
780 }
781
782 // Record information about the newly started dispatch cycle.
783 dispatchEntry->inProgress = true;
784
785 connection->lastEventTime = dispatchEntry->eventEntry->eventTime;
786 connection->lastDispatchTime = currentTime;
787
788 nsecs_t timeout = dispatchEntry->timeout;
Jeff Brown51d45a72010-06-17 20:52:56 -0700789 connection->setNextTimeoutTime(currentTime, timeout);
Jeff Browne839a582010-04-22 18:58:52 -0700790
791 // Notify other system components.
792 onDispatchCycleStartedLocked(currentTime, connection);
793}
794
Jeff Brown51d45a72010-06-17 20:52:56 -0700795void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
796 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -0700797#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700798 LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
Jeff Browne839a582010-04-22 18:58:52 -0700799 "%01.1fms since dispatch",
800 connection->getInputChannelName(),
801 connection->getEventLatencyMillis(currentTime),
802 connection->getDispatchLatencyMillis(currentTime));
803#endif
804
Jeff Brown54bc2812010-06-15 01:31:58 -0700805 if (connection->status == Connection::STATUS_BROKEN
806 || connection->status == Connection::STATUS_ZOMBIE) {
Jeff Browne839a582010-04-22 18:58:52 -0700807 return;
808 }
809
810 // Clear the pending timeout.
811 connection->nextTimeoutTime = LONG_LONG_MAX;
812
813 if (connection->status == Connection::STATUS_NOT_RESPONDING) {
814 // Recovering from an ANR.
815 connection->status = Connection::STATUS_NORMAL;
816
817 // Notify other system components.
818 onDispatchCycleFinishedLocked(currentTime, connection, true /*recoveredFromANR*/);
819 } else {
820 // Normal finish. Not much to do here.
821
822 // Notify other system components.
823 onDispatchCycleFinishedLocked(currentTime, connection, false /*recoveredFromANR*/);
824 }
825
826 // Reset the publisher since the event has been consumed.
827 // We do this now so that the publisher can release some of its internal resources
828 // while waiting for the next dispatch cycle to begin.
829 status_t status = connection->inputPublisher.reset();
830 if (status) {
831 LOGE("channel '%s' ~ Could not reset publisher, status=%d",
832 connection->getInputChannelName(), status);
833 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
834 return;
835 }
836
837 // Start the next dispatch cycle for this connection.
838 while (! connection->outboundQueue.isEmpty()) {
839 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
840 if (dispatchEntry->inProgress) {
841 // Finish or resume current event in progress.
842 if (dispatchEntry->tailMotionSample) {
843 // We have a tail of undispatched motion samples.
844 // Reuse the same DispatchEntry and start a new cycle.
845 dispatchEntry->inProgress = false;
846 dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
847 dispatchEntry->tailMotionSample = NULL;
848 startDispatchCycleLocked(currentTime, connection);
849 return;
850 }
851 // Finished.
852 connection->outboundQueue.dequeueAtHead();
Jeff Brownf67c53e2010-07-28 15:48:59 -0700853 if (dispatchEntry->isSyncTarget()) {
854 decrementPendingSyncDispatchesLocked(dispatchEntry->eventEntry);
855 }
Jeff Browne839a582010-04-22 18:58:52 -0700856 mAllocator.releaseDispatchEntry(dispatchEntry);
857 } else {
858 // If the head is not in progress, then we must have already dequeued the in
859 // progress event, which means we actually aborted it (due to ANR).
860 // So just start the next event for this connection.
861 startDispatchCycleLocked(currentTime, connection);
862 return;
863 }
864 }
865
866 // Outbound queue is empty, deactivate the connection.
Jeff Brown51d45a72010-06-17 20:52:56 -0700867 deactivateConnectionLocked(connection.get());
Jeff Browne839a582010-04-22 18:58:52 -0700868}
869
Jeff Brown51d45a72010-06-17 20:52:56 -0700870void InputDispatcher::timeoutDispatchCycleLocked(nsecs_t currentTime,
871 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -0700872#if DEBUG_DISPATCH_CYCLE
873 LOGD("channel '%s' ~ timeoutDispatchCycle",
874 connection->getInputChannelName());
875#endif
876
877 if (connection->status != Connection::STATUS_NORMAL) {
Jeff Brown51d45a72010-06-17 20:52:56 -0700878 return;
Jeff Browne839a582010-04-22 18:58:52 -0700879 }
880
881 // Enter the not responding state.
882 connection->status = Connection::STATUS_NOT_RESPONDING;
883 connection->lastANRTime = currentTime;
Jeff Browne839a582010-04-22 18:58:52 -0700884
885 // Notify other system components.
Jeff Brown51d45a72010-06-17 20:52:56 -0700886 // This enqueues a command which will eventually either call
887 // resumeAfterTimeoutDispatchCycleLocked or abortDispatchCycleLocked.
Jeff Browne839a582010-04-22 18:58:52 -0700888 onDispatchCycleANRLocked(currentTime, connection);
Jeff Browne839a582010-04-22 18:58:52 -0700889}
890
Jeff Brown51d45a72010-06-17 20:52:56 -0700891void InputDispatcher::resumeAfterTimeoutDispatchCycleLocked(nsecs_t currentTime,
892 const sp<Connection>& connection, nsecs_t newTimeout) {
893#if DEBUG_DISPATCH_CYCLE
894 LOGD("channel '%s' ~ resumeAfterTimeoutDispatchCycleLocked",
895 connection->getInputChannelName());
896#endif
897
898 if (connection->status != Connection::STATUS_NOT_RESPONDING) {
899 return;
900 }
901
902 // Resume normal dispatch.
903 connection->status = Connection::STATUS_NORMAL;
904 connection->setNextTimeoutTime(currentTime, newTimeout);
905}
906
907void InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime,
908 const sp<Connection>& connection, bool broken) {
Jeff Browne839a582010-04-22 18:58:52 -0700909#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700910 LOGD("channel '%s' ~ abortDispatchCycle - broken=%s",
Jeff Browne839a582010-04-22 18:58:52 -0700911 connection->getInputChannelName(), broken ? "true" : "false");
912#endif
913
Jeff Browne839a582010-04-22 18:58:52 -0700914 // Clear the pending timeout.
915 connection->nextTimeoutTime = LONG_LONG_MAX;
916
917 // Clear the outbound queue.
Jeff Brown51d45a72010-06-17 20:52:56 -0700918 if (! connection->outboundQueue.isEmpty()) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700919 do {
920 DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
Jeff Brownf67c53e2010-07-28 15:48:59 -0700921 if (dispatchEntry->isSyncTarget()) {
922 decrementPendingSyncDispatchesLocked(dispatchEntry->eventEntry);
923 }
Jeff Brown54bc2812010-06-15 01:31:58 -0700924 mAllocator.releaseDispatchEntry(dispatchEntry);
925 } while (! connection->outboundQueue.isEmpty());
Jeff Browne839a582010-04-22 18:58:52 -0700926
Jeff Brown51d45a72010-06-17 20:52:56 -0700927 deactivateConnectionLocked(connection.get());
Jeff Brown54bc2812010-06-15 01:31:58 -0700928 }
Jeff Browne839a582010-04-22 18:58:52 -0700929
930 // Handle the case where the connection appears to be unrecoverably broken.
Jeff Brown54bc2812010-06-15 01:31:58 -0700931 // Ignore already broken or zombie connections.
Jeff Browne839a582010-04-22 18:58:52 -0700932 if (broken) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700933 if (connection->status == Connection::STATUS_NORMAL
934 || connection->status == Connection::STATUS_NOT_RESPONDING) {
935 connection->status = Connection::STATUS_BROKEN;
Jeff Browne839a582010-04-22 18:58:52 -0700936
Jeff Brown54bc2812010-06-15 01:31:58 -0700937 // Notify other system components.
938 onDispatchCycleBrokenLocked(currentTime, connection);
939 }
Jeff Browne839a582010-04-22 18:58:52 -0700940 }
Jeff Browne839a582010-04-22 18:58:52 -0700941}
942
943bool InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
944 InputDispatcher* d = static_cast<InputDispatcher*>(data);
945
946 { // acquire lock
947 AutoMutex _l(d->mLock);
948
949 ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
950 if (connectionIndex < 0) {
951 LOGE("Received spurious receive callback for unknown input channel. "
952 "fd=%d, events=0x%x", receiveFd, events);
953 return false; // remove the callback
954 }
955
Jeff Brown51d45a72010-06-17 20:52:56 -0700956 nsecs_t currentTime = now();
Jeff Browne839a582010-04-22 18:58:52 -0700957
958 sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
959 if (events & (POLLERR | POLLHUP | POLLNVAL)) {
960 LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
961 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brown51d45a72010-06-17 20:52:56 -0700962 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -0700963 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700964 return false; // remove the callback
965 }
966
967 if (! (events & POLLIN)) {
968 LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
969 "events=0x%x", connection->getInputChannelName(), events);
970 return true;
971 }
972
973 status_t status = connection->inputPublisher.receiveFinishedSignal();
974 if (status) {
975 LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
976 connection->getInputChannelName(), status);
Jeff Brown51d45a72010-06-17 20:52:56 -0700977 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -0700978 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700979 return false; // remove the callback
980 }
981
Jeff Brown51d45a72010-06-17 20:52:56 -0700982 d->finishDispatchCycleLocked(currentTime, connection);
Jeff Brown54bc2812010-06-15 01:31:58 -0700983 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700984 return true;
985 } // release lock
986}
987
Jeff Brown54bc2812010-06-15 01:31:58 -0700988void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
Jeff Browne839a582010-04-22 18:58:52 -0700989#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown54bc2812010-06-15 01:31:58 -0700990 LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
Jeff Browne839a582010-04-22 18:58:52 -0700991#endif
992
993 bool wasEmpty;
994 { // acquire lock
995 AutoMutex _l(mLock);
996
Jeff Brown51d45a72010-06-17 20:52:56 -0700997 ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
Jeff Browne839a582010-04-22 18:58:52 -0700998
999 wasEmpty = mInboundQueue.isEmpty();
1000 mInboundQueue.enqueueAtTail(newEntry);
1001 } // release lock
1002
1003 if (wasEmpty) {
1004 mPollLoop->wake();
1005 }
1006}
1007
Jeff Browne839a582010-04-22 18:58:52 -07001008void InputDispatcher::notifyAppSwitchComing(nsecs_t eventTime) {
1009#if DEBUG_INBOUND_EVENT_DETAILS
1010 LOGD("notifyAppSwitchComing - eventTime=%lld", eventTime);
1011#endif
1012
1013 // Remove movement keys from the queue from most recent to least recent, stopping at the
1014 // first non-movement key.
1015 // TODO: Include a detailed description of why we do this...
1016
1017 { // acquire lock
1018 AutoMutex _l(mLock);
1019
1020 for (EventEntry* entry = mInboundQueue.tail.prev; entry != & mInboundQueue.head; ) {
1021 EventEntry* prev = entry->prev;
1022
1023 if (entry->type == EventEntry::TYPE_KEY) {
1024 KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
1025 if (isMovementKey(keyEntry->keyCode)) {
1026 LOGV("Dropping movement key during app switch: keyCode=%d, action=%d",
1027 keyEntry->keyCode, keyEntry->action);
1028 mInboundQueue.dequeue(keyEntry);
Jeff Brown51d45a72010-06-17 20:52:56 -07001029
1030 setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
1031
Jeff Browne839a582010-04-22 18:58:52 -07001032 mAllocator.releaseKeyEntry(keyEntry);
1033 } else {
1034 // stop at last non-movement key
1035 break;
1036 }
1037 }
1038
1039 entry = prev;
1040 }
1041 } // release lock
1042}
1043
Jeff Brown5c1ed842010-07-14 18:48:53 -07001044void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Browne839a582010-04-22 18:58:52 -07001045 uint32_t policyFlags, int32_t action, int32_t flags,
1046 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
1047#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -07001048 LOGD("notifyKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -07001049 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
Jeff Brown5c1ed842010-07-14 18:48:53 -07001050 eventTime, deviceId, source, policyFlags, action, flags,
Jeff Browne839a582010-04-22 18:58:52 -07001051 keyCode, scanCode, metaState, downTime);
1052#endif
1053
1054 bool wasEmpty;
1055 { // acquire lock
1056 AutoMutex _l(mLock);
1057
Jeff Brown51d45a72010-06-17 20:52:56 -07001058 int32_t repeatCount = 0;
1059 KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001060 deviceId, source, policyFlags, action, flags, keyCode, scanCode,
Jeff Brown51d45a72010-06-17 20:52:56 -07001061 metaState, repeatCount, downTime);
Jeff Browne839a582010-04-22 18:58:52 -07001062
1063 wasEmpty = mInboundQueue.isEmpty();
1064 mInboundQueue.enqueueAtTail(newEntry);
1065 } // release lock
1066
1067 if (wasEmpty) {
1068 mPollLoop->wake();
1069 }
1070}
1071
Jeff Brown5c1ed842010-07-14 18:48:53 -07001072void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Browne839a582010-04-22 18:58:52 -07001073 uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
1074 uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
1075 float xPrecision, float yPrecision, nsecs_t downTime) {
1076#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -07001077 LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -07001078 "action=0x%x, metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, "
1079 "downTime=%lld",
Jeff Brown5c1ed842010-07-14 18:48:53 -07001080 eventTime, deviceId, source, policyFlags, action, metaState, edgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07001081 xPrecision, yPrecision, downTime);
1082 for (uint32_t i = 0; i < pointerCount; i++) {
1083 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
1084 i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
1085 pointerCoords[i].pressure, pointerCoords[i].size);
1086 }
1087#endif
1088
1089 bool wasEmpty;
1090 { // acquire lock
1091 AutoMutex _l(mLock);
1092
1093 // Attempt batching and streaming of move events.
Jeff Brown5c1ed842010-07-14 18:48:53 -07001094 if (action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Browne839a582010-04-22 18:58:52 -07001095 // BATCHING CASE
1096 //
1097 // Try to append a move sample to the tail of the inbound queue for this device.
1098 // Give up if we encounter a non-move motion event for this device since that
1099 // means we cannot append any new samples until a new motion event has started.
1100 for (EventEntry* entry = mInboundQueue.tail.prev;
1101 entry != & mInboundQueue.head; entry = entry->prev) {
1102 if (entry->type != EventEntry::TYPE_MOTION) {
1103 // Keep looking for motion events.
1104 continue;
1105 }
1106
1107 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
1108 if (motionEntry->deviceId != deviceId) {
1109 // Keep looking for this device.
1110 continue;
1111 }
1112
Jeff Brown5c1ed842010-07-14 18:48:53 -07001113 if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown51d45a72010-06-17 20:52:56 -07001114 || motionEntry->pointerCount != pointerCount
1115 || motionEntry->isInjected()) {
Jeff Browne839a582010-04-22 18:58:52 -07001116 // Last motion event in the queue for this device is not compatible for
1117 // appending new samples. Stop here.
1118 goto NoBatchingOrStreaming;
1119 }
1120
1121 // The last motion event is a move and is compatible for appending.
Jeff Brown54bc2812010-06-15 01:31:58 -07001122 // Do the batching magic.
Jeff Brown51d45a72010-06-17 20:52:56 -07001123 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
Jeff Browne839a582010-04-22 18:58:52 -07001124#if DEBUG_BATCHING
1125 LOGD("Appended motion sample onto batch for most recent "
1126 "motion event for this device in the inbound queue.");
1127#endif
Jeff Brown54bc2812010-06-15 01:31:58 -07001128
1129 // Sanity check for special case because dispatch is interruptible.
1130 // The dispatch logic is partially interruptible and releases its lock while
1131 // identifying targets. However, as soon as the targets have been identified,
1132 // the dispatcher proceeds to write a dispatch entry into all relevant outbound
1133 // queues and then promptly removes the motion entry from the queue.
1134 //
1135 // Consequently, we should never observe the case where the inbound queue contains
1136 // an in-progress motion entry unless the current input targets are invalid
1137 // (currently being computed). Check for this!
1138 assert(! (motionEntry->dispatchInProgress && mCurrentInputTargetsValid));
1139
1140 return; // done!
Jeff Browne839a582010-04-22 18:58:52 -07001141 }
1142
1143 // STREAMING CASE
1144 //
1145 // There is no pending motion event (of any kind) for this device in the inbound queue.
1146 // Search the outbound queues for a synchronously dispatched motion event for this
1147 // device. If found, then we append the new sample to that event and then try to
1148 // push it out to all current targets. It is possible that some targets will already
1149 // have consumed the motion event. This case is automatically handled by the
1150 // logic in prepareDispatchCycleLocked by tracking where resumption takes place.
1151 //
1152 // The reason we look for a synchronously dispatched motion event is because we
1153 // want to be sure that no other motion events have been dispatched since the move.
1154 // It's also convenient because it means that the input targets are still valid.
1155 // This code could be improved to support streaming of asynchronously dispatched
1156 // motion events (which might be significantly more efficient) but it may become
1157 // a little more complicated as a result.
1158 //
1159 // Note: This code crucially depends on the invariant that an outbound queue always
1160 // contains at most one synchronous event and it is always last (but it might
1161 // not be first!).
Jeff Brown54bc2812010-06-15 01:31:58 -07001162 if (mCurrentInputTargetsValid) {
1163 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1164 Connection* connection = mActiveConnections.itemAt(i);
1165 if (! connection->outboundQueue.isEmpty()) {
1166 DispatchEntry* dispatchEntry = connection->outboundQueue.tail.prev;
Jeff Brownf67c53e2010-07-28 15:48:59 -07001167 if (dispatchEntry->isSyncTarget()) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001168 if (dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION) {
1169 goto NoBatchingOrStreaming;
1170 }
Jeff Browne839a582010-04-22 18:58:52 -07001171
Jeff Brown54bc2812010-06-15 01:31:58 -07001172 MotionEntry* syncedMotionEntry = static_cast<MotionEntry*>(
1173 dispatchEntry->eventEntry);
Jeff Brown5c1ed842010-07-14 18:48:53 -07001174 if (syncedMotionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown54bc2812010-06-15 01:31:58 -07001175 || syncedMotionEntry->deviceId != deviceId
Jeff Brown51d45a72010-06-17 20:52:56 -07001176 || syncedMotionEntry->pointerCount != pointerCount
1177 || syncedMotionEntry->isInjected()) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001178 goto NoBatchingOrStreaming;
1179 }
Jeff Browne839a582010-04-22 18:58:52 -07001180
Jeff Brown54bc2812010-06-15 01:31:58 -07001181 // Found synced move entry. Append sample and resume dispatch.
1182 mAllocator.appendMotionSample(syncedMotionEntry, eventTime,
Jeff Brown51d45a72010-06-17 20:52:56 -07001183 pointerCoords);
Jeff Brown54bc2812010-06-15 01:31:58 -07001184 #if DEBUG_BATCHING
1185 LOGD("Appended motion sample onto batch for most recent synchronously "
1186 "dispatched motion event for this device in the outbound queues.");
1187 #endif
Jeff Brown51d45a72010-06-17 20:52:56 -07001188 nsecs_t currentTime = now();
Jeff Brown54bc2812010-06-15 01:31:58 -07001189 dispatchEventToCurrentInputTargetsLocked(currentTime, syncedMotionEntry,
1190 true /*resumeWithAppendedMotionSample*/);
1191
1192 runCommandsLockedInterruptible();
1193 return; // done!
1194 }
Jeff Browne839a582010-04-22 18:58:52 -07001195 }
1196 }
1197 }
1198
1199NoBatchingOrStreaming:;
1200 }
1201
1202 // Just enqueue a new motion event.
Jeff Brown51d45a72010-06-17 20:52:56 -07001203 MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001204 deviceId, source, policyFlags, action, metaState, edgeFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -07001205 xPrecision, yPrecision, downTime,
1206 pointerCount, pointerIds, pointerCoords);
Jeff Browne839a582010-04-22 18:58:52 -07001207
1208 wasEmpty = mInboundQueue.isEmpty();
1209 mInboundQueue.enqueueAtTail(newEntry);
1210 } // release lock
1211
1212 if (wasEmpty) {
1213 mPollLoop->wake();
1214 }
1215}
1216
Jeff Brown51d45a72010-06-17 20:52:56 -07001217int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
Jeff Brownf67c53e2010-07-28 15:48:59 -07001218 int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001219#if DEBUG_INBOUND_EVENT_DETAILS
1220 LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
Jeff Brownf67c53e2010-07-28 15:48:59 -07001221 "syncMode=%d, timeoutMillis=%d",
1222 event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis);
Jeff Brown51d45a72010-06-17 20:52:56 -07001223#endif
1224
1225 nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
1226
1227 EventEntry* injectedEntry;
1228 bool wasEmpty;
1229 { // acquire lock
1230 AutoMutex _l(mLock);
1231
1232 injectedEntry = createEntryFromInputEventLocked(event);
1233 injectedEntry->refCount += 1;
1234 injectedEntry->injectorPid = injectorPid;
1235 injectedEntry->injectorUid = injectorUid;
1236
Jeff Brownf67c53e2010-07-28 15:48:59 -07001237 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
1238 injectedEntry->injectionIsAsync = true;
1239 }
1240
Jeff Brown51d45a72010-06-17 20:52:56 -07001241 wasEmpty = mInboundQueue.isEmpty();
1242 mInboundQueue.enqueueAtTail(injectedEntry);
1243
1244 } // release lock
1245
1246 if (wasEmpty) {
1247 mPollLoop->wake();
1248 }
1249
1250 int32_t injectionResult;
1251 { // acquire lock
1252 AutoMutex _l(mLock);
1253
Jeff Brownf67c53e2010-07-28 15:48:59 -07001254 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
1255 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1256 } else {
1257 for (;;) {
1258 injectionResult = injectedEntry->injectionResult;
1259 if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
1260 break;
1261 }
Jeff Brown51d45a72010-06-17 20:52:56 -07001262
Jeff Brown51d45a72010-06-17 20:52:56 -07001263 nsecs_t remainingTimeout = endTime - now();
1264 if (remainingTimeout <= 0) {
Jeff Brownf67c53e2010-07-28 15:48:59 -07001265#if DEBUG_INJECTION
1266 LOGD("injectInputEvent - Timed out waiting for injection result "
1267 "to become available.");
1268#endif
Jeff Brown51d45a72010-06-17 20:52:56 -07001269 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1270 break;
1271 }
1272
Jeff Brownf67c53e2010-07-28 15:48:59 -07001273 mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
1274 }
1275
1276 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
1277 && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
1278 while (injectedEntry->pendingSyncDispatches != 0) {
1279#if DEBUG_INJECTION
1280 LOGD("injectInputEvent - Waiting for %d pending synchronous dispatches.",
1281 injectedEntry->pendingSyncDispatches);
1282#endif
1283 nsecs_t remainingTimeout = endTime - now();
1284 if (remainingTimeout <= 0) {
1285#if DEBUG_INJECTION
1286 LOGD("injectInputEvent - Timed out waiting for pending synchronous "
1287 "dispatches to finish.");
1288#endif
1289 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1290 break;
1291 }
1292
1293 mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
1294 }
Jeff Brown51d45a72010-06-17 20:52:56 -07001295 }
1296 }
1297
1298 mAllocator.releaseEventEntry(injectedEntry);
1299 } // release lock
1300
Jeff Brownf67c53e2010-07-28 15:48:59 -07001301#if DEBUG_INJECTION
1302 LOGD("injectInputEvent - Finished with result %d. "
1303 "injectorPid=%d, injectorUid=%d",
1304 injectionResult, injectorPid, injectorUid);
1305#endif
1306
Jeff Brown51d45a72010-06-17 20:52:56 -07001307 return injectionResult;
1308}
1309
1310void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
1311 if (entry->isInjected()) {
1312#if DEBUG_INJECTION
1313 LOGD("Setting input event injection result to %d. "
1314 "injectorPid=%d, injectorUid=%d",
1315 injectionResult, entry->injectorPid, entry->injectorUid);
1316#endif
1317
Jeff Brownf67c53e2010-07-28 15:48:59 -07001318 if (entry->injectionIsAsync) {
1319 // Log the outcome since the injector did not wait for the injection result.
1320 switch (injectionResult) {
1321 case INPUT_EVENT_INJECTION_SUCCEEDED:
1322 LOGV("Asynchronous input event injection succeeded.");
1323 break;
1324 case INPUT_EVENT_INJECTION_FAILED:
1325 LOGW("Asynchronous input event injection failed.");
1326 break;
1327 case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
1328 LOGW("Asynchronous input event injection permission denied.");
1329 break;
1330 case INPUT_EVENT_INJECTION_TIMED_OUT:
1331 LOGW("Asynchronous input event injection timed out.");
1332 break;
1333 }
1334 }
1335
Jeff Brown51d45a72010-06-17 20:52:56 -07001336 entry->injectionResult = injectionResult;
1337 mInjectionResultAvailableCondition.broadcast();
1338 }
1339}
1340
Jeff Brownf67c53e2010-07-28 15:48:59 -07001341void InputDispatcher::decrementPendingSyncDispatchesLocked(EventEntry* entry) {
1342 entry->pendingSyncDispatches -= 1;
1343
1344 if (entry->isInjected() && entry->pendingSyncDispatches == 0) {
1345 mInjectionSyncFinishedCondition.broadcast();
1346 }
Jeff Brown51d45a72010-06-17 20:52:56 -07001347}
1348
1349InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked(
1350 const InputEvent* event) {
1351 switch (event->getType()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07001352 case AINPUT_EVENT_TYPE_KEY: {
Jeff Brown51d45a72010-06-17 20:52:56 -07001353 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
1354 uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
1355
1356 KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
Jeff Brown5c1ed842010-07-14 18:48:53 -07001357 keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -07001358 keyEvent->getAction(), keyEvent->getFlags(),
1359 keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
1360 keyEvent->getRepeatCount(), keyEvent->getDownTime());
1361 return keyEntry;
1362 }
1363
Jeff Brown5c1ed842010-07-14 18:48:53 -07001364 case AINPUT_EVENT_TYPE_MOTION: {
Jeff Brown51d45a72010-06-17 20:52:56 -07001365 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
1366 uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
1367
1368 const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
1369 const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
1370 size_t pointerCount = motionEvent->getPointerCount();
1371
1372 MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001373 motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -07001374 motionEvent->getAction(), motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
1375 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
1376 motionEvent->getDownTime(), uint32_t(pointerCount),
1377 motionEvent->getPointerIds(), samplePointerCoords);
1378 for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
1379 sampleEventTimes += 1;
1380 samplePointerCoords += pointerCount;
1381 mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
1382 }
1383 return motionEntry;
1384 }
1385
1386 default:
1387 assert(false);
1388 return NULL;
1389 }
1390}
1391
Jeff Browne839a582010-04-22 18:58:52 -07001392void InputDispatcher::resetKeyRepeatLocked() {
1393 if (mKeyRepeatState.lastKeyEntry) {
1394 mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
1395 mKeyRepeatState.lastKeyEntry = NULL;
1396 }
1397}
1398
Jeff Brown50de30a2010-06-22 01:27:15 -07001399void InputDispatcher::preemptInputDispatch() {
1400#if DEBUG_DISPATCH_CYCLE
1401 LOGD("preemptInputDispatch");
1402#endif
1403
1404 bool preemptedOne = false;
1405 { // acquire lock
1406 AutoMutex _l(mLock);
1407
1408 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1409 Connection* connection = mActiveConnections[i];
1410 if (connection->hasPendingSyncTarget()) {
1411#if DEBUG_DISPATCH_CYCLE
1412 LOGD("channel '%s' ~ Preempted pending synchronous dispatch",
1413 connection->getInputChannelName());
1414#endif
1415 connection->outboundQueue.tail.prev->targetFlags &= ~ InputTarget::FLAG_SYNC;
1416 preemptedOne = true;
1417 }
1418 }
1419 } // release lock
1420
1421 if (preemptedOne) {
1422 // Wake up the poll loop so it can get a head start dispatching the next event.
1423 mPollLoop->wake();
1424 }
1425}
1426
Jeff Browne839a582010-04-22 18:58:52 -07001427status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001428#if DEBUG_REGISTRATION
Jeff Brown50de30a2010-06-22 01:27:15 -07001429 LOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().string());
Jeff Brown54bc2812010-06-15 01:31:58 -07001430#endif
1431
Jeff Browne839a582010-04-22 18:58:52 -07001432 { // acquire lock
1433 AutoMutex _l(mLock);
1434
Jeff Brown0cacb872010-08-17 15:59:26 -07001435 if (getConnectionIndex(inputChannel) >= 0) {
Jeff Browne839a582010-04-22 18:58:52 -07001436 LOGW("Attempted to register already registered input channel '%s'",
1437 inputChannel->getName().string());
1438 return BAD_VALUE;
1439 }
1440
1441 sp<Connection> connection = new Connection(inputChannel);
1442 status_t status = connection->initialize();
1443 if (status) {
1444 LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
1445 inputChannel->getName().string(), status);
1446 return status;
1447 }
1448
Jeff Brown0cacb872010-08-17 15:59:26 -07001449 int32_t receiveFd = inputChannel->getReceivePipeFd();
Jeff Browne839a582010-04-22 18:58:52 -07001450 mConnectionsByReceiveFd.add(receiveFd, connection);
Jeff Brown54bc2812010-06-15 01:31:58 -07001451
Jeff Brown0cacb872010-08-17 15:59:26 -07001452 mPollLoop->setCallback(receiveFd, POLLIN, handleReceiveCallback, this);
1453
Jeff Brown54bc2812010-06-15 01:31:58 -07001454 runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07001455 } // release lock
Jeff Browne839a582010-04-22 18:58:52 -07001456 return OK;
1457}
1458
1459status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001460#if DEBUG_REGISTRATION
Jeff Brown50de30a2010-06-22 01:27:15 -07001461 LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
Jeff Brown54bc2812010-06-15 01:31:58 -07001462#endif
1463
Jeff Browne839a582010-04-22 18:58:52 -07001464 { // acquire lock
1465 AutoMutex _l(mLock);
1466
Jeff Brown0cacb872010-08-17 15:59:26 -07001467 ssize_t connectionIndex = getConnectionIndex(inputChannel);
Jeff Browne839a582010-04-22 18:58:52 -07001468 if (connectionIndex < 0) {
1469 LOGW("Attempted to unregister already unregistered input channel '%s'",
1470 inputChannel->getName().string());
1471 return BAD_VALUE;
1472 }
1473
1474 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1475 mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
1476
1477 connection->status = Connection::STATUS_ZOMBIE;
1478
Jeff Brown0cacb872010-08-17 15:59:26 -07001479 mPollLoop->removeCallback(inputChannel->getReceivePipeFd());
1480
Jeff Brown51d45a72010-06-17 20:52:56 -07001481 nsecs_t currentTime = now();
1482 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -07001483
1484 runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07001485 } // release lock
1486
Jeff Browne839a582010-04-22 18:58:52 -07001487 // Wake the poll loop because removing the connection may have changed the current
1488 // synchronization state.
1489 mPollLoop->wake();
1490 return OK;
1491}
1492
Jeff Brown0cacb872010-08-17 15:59:26 -07001493ssize_t InputDispatcher::getConnectionIndex(const sp<InputChannel>& inputChannel) {
1494 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(inputChannel->getReceivePipeFd());
1495 if (connectionIndex >= 0) {
1496 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1497 if (connection->inputChannel.get() == inputChannel.get()) {
1498 return connectionIndex;
1499 }
1500 }
1501
1502 return -1;
1503}
1504
Jeff Browne839a582010-04-22 18:58:52 -07001505void InputDispatcher::activateConnectionLocked(Connection* connection) {
1506 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1507 if (mActiveConnections.itemAt(i) == connection) {
1508 return;
1509 }
1510 }
1511 mActiveConnections.add(connection);
1512}
1513
1514void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
1515 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1516 if (mActiveConnections.itemAt(i) == connection) {
1517 mActiveConnections.removeAt(i);
1518 return;
1519 }
1520 }
1521}
1522
Jeff Brown54bc2812010-06-15 01:31:58 -07001523void InputDispatcher::onDispatchCycleStartedLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001524 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001525}
1526
Jeff Brown54bc2812010-06-15 01:31:58 -07001527void InputDispatcher::onDispatchCycleFinishedLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001528 nsecs_t currentTime, const sp<Connection>& connection, bool recoveredFromANR) {
Jeff Browne839a582010-04-22 18:58:52 -07001529 if (recoveredFromANR) {
1530 LOGI("channel '%s' ~ Recovered from ANR. %01.1fms since event, "
1531 "%01.1fms since dispatch, %01.1fms since ANR",
1532 connection->getInputChannelName(),
1533 connection->getEventLatencyMillis(currentTime),
1534 connection->getDispatchLatencyMillis(currentTime),
1535 connection->getANRLatencyMillis(currentTime));
1536
Jeff Brown54bc2812010-06-15 01:31:58 -07001537 CommandEntry* commandEntry = postCommandLocked(
1538 & InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07001539 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07001540 }
1541}
1542
Jeff Brown54bc2812010-06-15 01:31:58 -07001543void InputDispatcher::onDispatchCycleANRLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001544 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001545 LOGI("channel '%s' ~ Not responding! %01.1fms since event, %01.1fms since dispatch",
1546 connection->getInputChannelName(),
1547 connection->getEventLatencyMillis(currentTime),
1548 connection->getDispatchLatencyMillis(currentTime));
1549
Jeff Brown54bc2812010-06-15 01:31:58 -07001550 CommandEntry* commandEntry = postCommandLocked(
1551 & InputDispatcher::doNotifyInputChannelANRLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07001552 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07001553}
1554
Jeff Brown54bc2812010-06-15 01:31:58 -07001555void InputDispatcher::onDispatchCycleBrokenLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001556 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001557 LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
1558 connection->getInputChannelName());
1559
Jeff Brown54bc2812010-06-15 01:31:58 -07001560 CommandEntry* commandEntry = postCommandLocked(
1561 & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07001562 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07001563}
1564
Jeff Brown54bc2812010-06-15 01:31:58 -07001565void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
1566 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001567 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07001568
Jeff Brown51d45a72010-06-17 20:52:56 -07001569 if (connection->status != Connection::STATUS_ZOMBIE) {
1570 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07001571
Jeff Brown51d45a72010-06-17 20:52:56 -07001572 mPolicy->notifyInputChannelBroken(connection->inputChannel);
1573
1574 mLock.lock();
1575 }
Jeff Brown54bc2812010-06-15 01:31:58 -07001576}
1577
1578void InputDispatcher::doNotifyInputChannelANRLockedInterruptible(
1579 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001580 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07001581
Jeff Brown51d45a72010-06-17 20:52:56 -07001582 if (connection->status != Connection::STATUS_ZOMBIE) {
1583 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07001584
Jeff Brown51d45a72010-06-17 20:52:56 -07001585 nsecs_t newTimeout;
1586 bool resume = mPolicy->notifyInputChannelANR(connection->inputChannel, newTimeout);
1587
1588 mLock.lock();
1589
1590 nsecs_t currentTime = now();
1591 if (resume) {
1592 resumeAfterTimeoutDispatchCycleLocked(currentTime, connection, newTimeout);
1593 } else {
1594 abortDispatchCycleLocked(currentTime, connection, false /*(not) broken*/);
1595 }
1596 }
Jeff Brown54bc2812010-06-15 01:31:58 -07001597}
1598
1599void InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible(
1600 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001601 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07001602
Jeff Brown51d45a72010-06-17 20:52:56 -07001603 if (connection->status != Connection::STATUS_ZOMBIE) {
1604 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07001605
Jeff Brown51d45a72010-06-17 20:52:56 -07001606 mPolicy->notifyInputChannelRecoveredFromANR(connection->inputChannel);
1607
1608 mLock.lock();
1609 }
Jeff Brown54bc2812010-06-15 01:31:58 -07001610}
1611
1612
Jeff Browne839a582010-04-22 18:58:52 -07001613// --- InputDispatcher::Allocator ---
1614
1615InputDispatcher::Allocator::Allocator() {
1616}
1617
Jeff Brown51d45a72010-06-17 20:52:56 -07001618void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
1619 nsecs_t eventTime) {
1620 entry->type = type;
1621 entry->refCount = 1;
1622 entry->dispatchInProgress = false;
Christopher Tated974e002010-06-23 16:50:30 -07001623 entry->eventTime = eventTime;
Jeff Brown51d45a72010-06-17 20:52:56 -07001624 entry->injectionResult = INPUT_EVENT_INJECTION_PENDING;
Jeff Brownf67c53e2010-07-28 15:48:59 -07001625 entry->injectionIsAsync = false;
Jeff Brown51d45a72010-06-17 20:52:56 -07001626 entry->injectorPid = -1;
1627 entry->injectorUid = -1;
Jeff Brownf67c53e2010-07-28 15:48:59 -07001628 entry->pendingSyncDispatches = 0;
Jeff Brown51d45a72010-06-17 20:52:56 -07001629}
1630
Jeff Browne839a582010-04-22 18:58:52 -07001631InputDispatcher::ConfigurationChangedEntry*
Jeff Brown51d45a72010-06-17 20:52:56 -07001632InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
Jeff Browne839a582010-04-22 18:58:52 -07001633 ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07001634 initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime);
Jeff Browne839a582010-04-22 18:58:52 -07001635 return entry;
1636}
1637
Jeff Brown51d45a72010-06-17 20:52:56 -07001638InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001639 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
Jeff Brown51d45a72010-06-17 20:52:56 -07001640 int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
1641 int32_t repeatCount, nsecs_t downTime) {
Jeff Browne839a582010-04-22 18:58:52 -07001642 KeyEntry* entry = mKeyEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07001643 initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime);
1644
1645 entry->deviceId = deviceId;
Jeff Brown5c1ed842010-07-14 18:48:53 -07001646 entry->source = source;
Jeff Brown51d45a72010-06-17 20:52:56 -07001647 entry->policyFlags = policyFlags;
1648 entry->action = action;
1649 entry->flags = flags;
1650 entry->keyCode = keyCode;
1651 entry->scanCode = scanCode;
1652 entry->metaState = metaState;
1653 entry->repeatCount = repeatCount;
1654 entry->downTime = downTime;
Jeff Browne839a582010-04-22 18:58:52 -07001655 return entry;
1656}
1657
Jeff Brown51d45a72010-06-17 20:52:56 -07001658InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001659 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
Jeff Brown51d45a72010-06-17 20:52:56 -07001660 int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
1661 nsecs_t downTime, uint32_t pointerCount,
1662 const int32_t* pointerIds, const PointerCoords* pointerCoords) {
Jeff Browne839a582010-04-22 18:58:52 -07001663 MotionEntry* entry = mMotionEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07001664 initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime);
1665
1666 entry->eventTime = eventTime;
1667 entry->deviceId = deviceId;
Jeff Brown5c1ed842010-07-14 18:48:53 -07001668 entry->source = source;
Jeff Brown51d45a72010-06-17 20:52:56 -07001669 entry->policyFlags = policyFlags;
1670 entry->action = action;
1671 entry->metaState = metaState;
1672 entry->edgeFlags = edgeFlags;
1673 entry->xPrecision = xPrecision;
1674 entry->yPrecision = yPrecision;
1675 entry->downTime = downTime;
1676 entry->pointerCount = pointerCount;
1677 entry->firstSample.eventTime = eventTime;
Jeff Browne839a582010-04-22 18:58:52 -07001678 entry->firstSample.next = NULL;
Jeff Brown51d45a72010-06-17 20:52:56 -07001679 entry->lastSample = & entry->firstSample;
1680 for (uint32_t i = 0; i < pointerCount; i++) {
1681 entry->pointerIds[i] = pointerIds[i];
1682 entry->firstSample.pointerCoords[i] = pointerCoords[i];
1683 }
Jeff Browne839a582010-04-22 18:58:52 -07001684 return entry;
1685}
1686
1687InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
1688 EventEntry* eventEntry) {
1689 DispatchEntry* entry = mDispatchEntryPool.alloc();
1690 entry->eventEntry = eventEntry;
1691 eventEntry->refCount += 1;
1692 return entry;
1693}
1694
Jeff Brown54bc2812010-06-15 01:31:58 -07001695InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
1696 CommandEntry* entry = mCommandEntryPool.alloc();
1697 entry->command = command;
1698 return entry;
1699}
1700
Jeff Browne839a582010-04-22 18:58:52 -07001701void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
1702 switch (entry->type) {
1703 case EventEntry::TYPE_CONFIGURATION_CHANGED:
1704 releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
1705 break;
1706 case EventEntry::TYPE_KEY:
1707 releaseKeyEntry(static_cast<KeyEntry*>(entry));
1708 break;
1709 case EventEntry::TYPE_MOTION:
1710 releaseMotionEntry(static_cast<MotionEntry*>(entry));
1711 break;
1712 default:
1713 assert(false);
1714 break;
1715 }
1716}
1717
1718void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
1719 ConfigurationChangedEntry* entry) {
1720 entry->refCount -= 1;
1721 if (entry->refCount == 0) {
1722 mConfigurationChangeEntryPool.free(entry);
1723 } else {
1724 assert(entry->refCount > 0);
1725 }
1726}
1727
1728void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
1729 entry->refCount -= 1;
1730 if (entry->refCount == 0) {
1731 mKeyEntryPool.free(entry);
1732 } else {
1733 assert(entry->refCount > 0);
1734 }
1735}
1736
1737void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
1738 entry->refCount -= 1;
1739 if (entry->refCount == 0) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001740 for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
1741 MotionSample* next = sample->next;
1742 mMotionSamplePool.free(sample);
1743 sample = next;
1744 }
Jeff Browne839a582010-04-22 18:58:52 -07001745 mMotionEntryPool.free(entry);
1746 } else {
1747 assert(entry->refCount > 0);
1748 }
1749}
1750
1751void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
1752 releaseEventEntry(entry->eventEntry);
1753 mDispatchEntryPool.free(entry);
1754}
1755
Jeff Brown54bc2812010-06-15 01:31:58 -07001756void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
1757 mCommandEntryPool.free(entry);
1758}
1759
Jeff Browne839a582010-04-22 18:58:52 -07001760void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
Jeff Brown51d45a72010-06-17 20:52:56 -07001761 nsecs_t eventTime, const PointerCoords* pointerCoords) {
Jeff Browne839a582010-04-22 18:58:52 -07001762 MotionSample* sample = mMotionSamplePool.alloc();
1763 sample->eventTime = eventTime;
Jeff Brown51d45a72010-06-17 20:52:56 -07001764 uint32_t pointerCount = motionEntry->pointerCount;
1765 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Browne839a582010-04-22 18:58:52 -07001766 sample->pointerCoords[i] = pointerCoords[i];
1767 }
1768
1769 sample->next = NULL;
1770 motionEntry->lastSample->next = sample;
1771 motionEntry->lastSample = sample;
1772}
1773
Jeff Brown542412c2010-08-18 15:51:08 -07001774// --- InputDispatcher::MotionEntry ---
1775
1776uint32_t InputDispatcher::MotionEntry::countSamples() const {
1777 uint32_t count = 1;
1778 for (MotionSample* sample = firstSample.next; sample != NULL; sample = sample->next) {
1779 count += 1;
1780 }
1781 return count;
1782}
1783
Jeff Browne839a582010-04-22 18:58:52 -07001784// --- InputDispatcher::Connection ---
1785
1786InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
1787 status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
1788 nextTimeoutTime(LONG_LONG_MAX),
1789 lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX),
1790 lastANRTime(LONG_LONG_MAX) {
1791}
1792
1793InputDispatcher::Connection::~Connection() {
1794}
1795
1796status_t InputDispatcher::Connection::initialize() {
1797 return inputPublisher.initialize();
1798}
1799
Jeff Brown51d45a72010-06-17 20:52:56 -07001800void InputDispatcher::Connection::setNextTimeoutTime(nsecs_t currentTime, nsecs_t timeout) {
1801 nextTimeoutTime = (timeout >= 0) ? currentTime + timeout : LONG_LONG_MAX;
1802}
1803
Jeff Brown54bc2812010-06-15 01:31:58 -07001804const char* InputDispatcher::Connection::getStatusLabel() const {
1805 switch (status) {
1806 case STATUS_NORMAL:
1807 return "NORMAL";
1808
1809 case STATUS_BROKEN:
1810 return "BROKEN";
1811
1812 case STATUS_NOT_RESPONDING:
1813 return "NOT_RESPONDING";
1814
1815 case STATUS_ZOMBIE:
1816 return "ZOMBIE";
1817
1818 default:
1819 return "UNKNOWN";
1820 }
1821}
1822
Jeff Browne839a582010-04-22 18:58:52 -07001823InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
1824 const EventEntry* eventEntry) const {
1825 for (DispatchEntry* dispatchEntry = outboundQueue.tail.prev;
1826 dispatchEntry != & outboundQueue.head; dispatchEntry = dispatchEntry->prev) {
1827 if (dispatchEntry->eventEntry == eventEntry) {
1828 return dispatchEntry;
1829 }
1830 }
1831 return NULL;
1832}
1833
Jeff Brown54bc2812010-06-15 01:31:58 -07001834// --- InputDispatcher::CommandEntry ---
1835
1836InputDispatcher::CommandEntry::CommandEntry() {
1837}
1838
1839InputDispatcher::CommandEntry::~CommandEntry() {
1840}
1841
Jeff Browne839a582010-04-22 18:58:52 -07001842
1843// --- InputDispatcherThread ---
1844
1845InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
1846 Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
1847}
1848
1849InputDispatcherThread::~InputDispatcherThread() {
1850}
1851
1852bool InputDispatcherThread::threadLoop() {
1853 mDispatcher->dispatchOnce();
1854 return true;
1855}
1856
1857} // namespace android