blob: e5b7f280befc5adbeb1b3255f51b15dd2d8e77fb [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 Brownaf30ff62010-09-01 17:01:00 -0700395 LOGD("processMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
396 "action=0x%x, flags=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -0700397 "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
Jeff Brownaf30ff62010-09-01 17:01:00 -0700398 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
399 entry->action, entry->flags,
Jeff Browne839a582010-04-22 18:58:52 -0700400 entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
401 entry->downTime);
402
403 // Print the most recent sample that we have available, this may change due to batching.
404 size_t sampleCount = 1;
405 MotionSample* sample = & entry->firstSample;
406 for (; sample->next != NULL; sample = sample->next) {
407 sampleCount += 1;
408 }
409 for (uint32_t i = 0; i < entry->pointerCount; i++) {
Jeff Brown38a7fab2010-08-30 03:02:23 -0700410 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
Jeff Brownaf30ff62010-09-01 17:01:00 -0700411 "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
Jeff Brown38a7fab2010-08-30 03:02:23 -0700412 "orientation=%f",
Jeff Browne839a582010-04-22 18:58:52 -0700413 i, entry->pointerIds[i],
Jeff Brown38a7fab2010-08-30 03:02:23 -0700414 sample->pointerCoords[i].x, sample->pointerCoords[i].y,
415 sample->pointerCoords[i].pressure, sample->pointerCoords[i].size,
416 sample->pointerCoords[i].touchMajor, sample->pointerCoords[i].touchMinor,
417 sample->pointerCoords[i].toolMajor, sample->pointerCoords[i].toolMinor,
418 sample->pointerCoords[i].orientation);
Jeff Browne839a582010-04-22 18:58:52 -0700419 }
420
421 // Keep in mind that due to batching, it is possible for the number of samples actually
422 // dispatched to change before the application finally consumed them.
Jeff Brown5c1ed842010-07-14 18:48:53 -0700423 if (entry->action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Browne839a582010-04-22 18:58:52 -0700424 LOGD(" ... Total movement samples currently batched %d ...", sampleCount);
425 }
426#endif
427
Jeff Brown54bc2812010-06-15 01:31:58 -0700428 identifyInputTargetsAndDispatchMotionLockedInterruptible(currentTime, entry);
Jeff Browne839a582010-04-22 18:58:52 -0700429}
430
Jeff Brown54bc2812010-06-15 01:31:58 -0700431void InputDispatcher::identifyInputTargetsAndDispatchKeyLockedInterruptible(
Jeff Browne839a582010-04-22 18:58:52 -0700432 nsecs_t currentTime, KeyEntry* entry) {
433#if DEBUG_DISPATCH_CYCLE
434 LOGD("identifyInputTargetsAndDispatchKey");
435#endif
436
Jeff Brown54bc2812010-06-15 01:31:58 -0700437 entry->dispatchInProgress = true;
438 mCurrentInputTargetsValid = false;
439 mLock.unlock();
440
Jeff Brown5c1ed842010-07-14 18:48:53 -0700441 mReusableKeyEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
Jeff Browne839a582010-04-22 18:58:52 -0700442 entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
443 entry->downTime, entry->eventTime);
444
445 mCurrentInputTargets.clear();
Jeff Brown50de30a2010-06-22 01:27:15 -0700446 int32_t injectionResult = mPolicy->waitForKeyEventTargets(& mReusableKeyEvent,
Jeff Brown51d45a72010-06-17 20:52:56 -0700447 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Browne839a582010-04-22 18:58:52 -0700448 mCurrentInputTargets);
449
Jeff Brown54bc2812010-06-15 01:31:58 -0700450 mLock.lock();
451 mCurrentInputTargetsValid = true;
452
Jeff Brown51d45a72010-06-17 20:52:56 -0700453 setInjectionResultLocked(entry, injectionResult);
454
Jeff Brown50de30a2010-06-22 01:27:15 -0700455 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
456 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
457 }
Jeff Browne839a582010-04-22 18:58:52 -0700458}
459
Jeff Brown54bc2812010-06-15 01:31:58 -0700460void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(
Jeff Browne839a582010-04-22 18:58:52 -0700461 nsecs_t currentTime, MotionEntry* entry) {
462#if DEBUG_DISPATCH_CYCLE
463 LOGD("identifyInputTargetsAndDispatchMotion");
464#endif
465
Jeff Brown54bc2812010-06-15 01:31:58 -0700466 entry->dispatchInProgress = true;
467 mCurrentInputTargetsValid = false;
468 mLock.unlock();
469
Jeff Brownaf30ff62010-09-01 17:01:00 -0700470 mReusableMotionEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
Jeff Browne839a582010-04-22 18:58:52 -0700471 entry->edgeFlags, entry->metaState,
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700472 0, 0, entry->xPrecision, entry->yPrecision,
Jeff Browne839a582010-04-22 18:58:52 -0700473 entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds,
474 entry->firstSample.pointerCoords);
475
476 mCurrentInputTargets.clear();
Jeff Brown50de30a2010-06-22 01:27:15 -0700477 int32_t injectionResult = mPolicy->waitForMotionEventTargets(& mReusableMotionEvent,
Jeff Brown51d45a72010-06-17 20:52:56 -0700478 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Browne839a582010-04-22 18:58:52 -0700479 mCurrentInputTargets);
480
Jeff Brown54bc2812010-06-15 01:31:58 -0700481 mLock.lock();
482 mCurrentInputTargetsValid = true;
483
Jeff Brown51d45a72010-06-17 20:52:56 -0700484 setInjectionResultLocked(entry, injectionResult);
485
Jeff Brown50de30a2010-06-22 01:27:15 -0700486 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
487 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
488 }
Jeff Browne839a582010-04-22 18:58:52 -0700489}
490
491void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
492 EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
493#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700494 LOGD("dispatchEventToCurrentInputTargets - "
Jeff Browne839a582010-04-22 18:58:52 -0700495 "resumeWithAppendedMotionSample=%s",
496 resumeWithAppendedMotionSample ? "true" : "false");
497#endif
498
Jeff Brown54bc2812010-06-15 01:31:58 -0700499 assert(eventEntry->dispatchInProgress); // should already have been set to true
500
Jeff Browne839a582010-04-22 18:58:52 -0700501 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
502 const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
503
Jeff Brown0cacb872010-08-17 15:59:26 -0700504 ssize_t connectionIndex = getConnectionIndex(inputTarget.inputChannel);
Jeff Browne839a582010-04-22 18:58:52 -0700505 if (connectionIndex >= 0) {
506 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown51d45a72010-06-17 20:52:56 -0700507 prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
Jeff Browne839a582010-04-22 18:58:52 -0700508 resumeWithAppendedMotionSample);
509 } else {
510 LOGW("Framework requested delivery of an input event to channel '%s' but it "
511 "is not registered with the input dispatcher.",
512 inputTarget.inputChannel->getName().string());
513 }
514 }
515}
516
Jeff Brown51d45a72010-06-17 20:52:56 -0700517void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
518 const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
Jeff Browne839a582010-04-22 18:58:52 -0700519 bool resumeWithAppendedMotionSample) {
520#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700521 LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, timeout=%lldns, "
Jeff Browne839a582010-04-22 18:58:52 -0700522 "xOffset=%f, yOffset=%f, resumeWithAppendedMotionSample=%s",
523 connection->getInputChannelName(), inputTarget->flags, inputTarget->timeout,
524 inputTarget->xOffset, inputTarget->yOffset,
525 resumeWithAppendedMotionSample ? "true" : "false");
526#endif
527
528 // Skip this event if the connection status is not normal.
529 // We don't want to queue outbound events at all if the connection is broken or
530 // not responding.
531 if (connection->status != Connection::STATUS_NORMAL) {
532 LOGV("channel '%s' ~ Dropping event because the channel status is %s",
Jeff Brown54bc2812010-06-15 01:31:58 -0700533 connection->getStatusLabel());
Jeff Browne839a582010-04-22 18:58:52 -0700534 return;
535 }
536
537 // Resume the dispatch cycle with a freshly appended motion sample.
538 // First we check that the last dispatch entry in the outbound queue is for the same
539 // motion event to which we appended the motion sample. If we find such a dispatch
540 // entry, and if it is currently in progress then we try to stream the new sample.
541 bool wasEmpty = connection->outboundQueue.isEmpty();
542
543 if (! wasEmpty && resumeWithAppendedMotionSample) {
544 DispatchEntry* motionEventDispatchEntry =
545 connection->findQueuedDispatchEntryForEvent(eventEntry);
546 if (motionEventDispatchEntry) {
547 // If the dispatch entry is not in progress, then we must be busy dispatching an
548 // earlier event. Not a problem, the motion event is on the outbound queue and will
549 // be dispatched later.
550 if (! motionEventDispatchEntry->inProgress) {
551#if DEBUG_BATCHING
552 LOGD("channel '%s' ~ Not streaming because the motion event has "
553 "not yet been dispatched. "
554 "(Waiting for earlier events to be consumed.)",
555 connection->getInputChannelName());
556#endif
557 return;
558 }
559
560 // If the dispatch entry is in progress but it already has a tail of pending
561 // motion samples, then it must mean that the shared memory buffer filled up.
562 // Not a problem, when this dispatch cycle is finished, we will eventually start
563 // a new dispatch cycle to process the tail and that tail includes the newly
564 // appended motion sample.
565 if (motionEventDispatchEntry->tailMotionSample) {
566#if DEBUG_BATCHING
567 LOGD("channel '%s' ~ Not streaming because no new samples can "
568 "be appended to the motion event in this dispatch cycle. "
569 "(Waiting for next dispatch cycle to start.)",
570 connection->getInputChannelName());
571#endif
572 return;
573 }
574
575 // The dispatch entry is in progress and is still potentially open for streaming.
576 // Try to stream the new motion sample. This might fail if the consumer has already
577 // consumed the motion event (or if the channel is broken).
578 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
579 status_t status = connection->inputPublisher.appendMotionSample(
580 appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
581 if (status == OK) {
582#if DEBUG_BATCHING
583 LOGD("channel '%s' ~ Successfully streamed new motion sample.",
584 connection->getInputChannelName());
585#endif
586 return;
587 }
588
589#if DEBUG_BATCHING
590 if (status == NO_MEMORY) {
591 LOGD("channel '%s' ~ Could not append motion sample to currently "
592 "dispatched move event because the shared memory buffer is full. "
593 "(Waiting for next dispatch cycle to start.)",
594 connection->getInputChannelName());
595 } else if (status == status_t(FAILED_TRANSACTION)) {
596 LOGD("channel '%s' ~ Could not append motion sample to currently "
Jeff Brown50de30a2010-06-22 01:27:15 -0700597 "dispatched move event because the event has already been consumed. "
Jeff Browne839a582010-04-22 18:58:52 -0700598 "(Waiting for next dispatch cycle to start.)",
599 connection->getInputChannelName());
600 } else {
601 LOGD("channel '%s' ~ Could not append motion sample to currently "
602 "dispatched move event due to an error, status=%d. "
603 "(Waiting for next dispatch cycle to start.)",
604 connection->getInputChannelName(), status);
605 }
606#endif
607 // Failed to stream. Start a new tail of pending motion samples to dispatch
608 // in the next cycle.
609 motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
610 return;
611 }
612 }
613
614 // This is a new event.
615 // Enqueue a new dispatch entry onto the outbound queue for this connection.
616 DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry); // increments ref
617 dispatchEntry->targetFlags = inputTarget->flags;
618 dispatchEntry->xOffset = inputTarget->xOffset;
619 dispatchEntry->yOffset = inputTarget->yOffset;
620 dispatchEntry->timeout = inputTarget->timeout;
621 dispatchEntry->inProgress = false;
622 dispatchEntry->headMotionSample = NULL;
623 dispatchEntry->tailMotionSample = NULL;
624
Jeff Brownf67c53e2010-07-28 15:48:59 -0700625 if (dispatchEntry->isSyncTarget()) {
626 eventEntry->pendingSyncDispatches += 1;
627 }
628
Jeff Browne839a582010-04-22 18:58:52 -0700629 // Handle the case where we could not stream a new motion sample because the consumer has
630 // already consumed the motion event (otherwise the corresponding dispatch entry would
631 // still be in the outbound queue for this connection). We set the head motion sample
632 // to the list starting with the newly appended motion sample.
633 if (resumeWithAppendedMotionSample) {
634#if DEBUG_BATCHING
635 LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
636 "that cannot be streamed because the motion event has already been consumed.",
637 connection->getInputChannelName());
638#endif
639 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
640 dispatchEntry->headMotionSample = appendedMotionSample;
641 }
642
643 // Enqueue the dispatch entry.
644 connection->outboundQueue.enqueueAtTail(dispatchEntry);
645
646 // If the outbound queue was previously empty, start the dispatch cycle going.
647 if (wasEmpty) {
Jeff Brown51d45a72010-06-17 20:52:56 -0700648 activateConnectionLocked(connection.get());
Jeff Browne839a582010-04-22 18:58:52 -0700649 startDispatchCycleLocked(currentTime, connection);
650 }
651}
652
Jeff Brown51d45a72010-06-17 20:52:56 -0700653void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
654 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -0700655#if DEBUG_DISPATCH_CYCLE
656 LOGD("channel '%s' ~ startDispatchCycle",
657 connection->getInputChannelName());
658#endif
659
660 assert(connection->status == Connection::STATUS_NORMAL);
661 assert(! connection->outboundQueue.isEmpty());
662
663 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
664 assert(! dispatchEntry->inProgress);
665
666 // TODO throttle successive ACTION_MOVE motion events for the same device
667 // possible implementation could set a brief poll timeout here and resume starting the
668 // dispatch cycle when elapsed
669
670 // Publish the event.
671 status_t status;
672 switch (dispatchEntry->eventEntry->type) {
673 case EventEntry::TYPE_KEY: {
674 KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
675
676 // Apply target flags.
677 int32_t action = keyEntry->action;
678 int32_t flags = keyEntry->flags;
679 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700680 flags |= AKEY_EVENT_FLAG_CANCELED;
Jeff Browne839a582010-04-22 18:58:52 -0700681 }
682
683 // Publish the key event.
Jeff Brown5c1ed842010-07-14 18:48:53 -0700684 status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
Jeff Browne839a582010-04-22 18:58:52 -0700685 action, flags, keyEntry->keyCode, keyEntry->scanCode,
686 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
687 keyEntry->eventTime);
688
689 if (status) {
690 LOGE("channel '%s' ~ Could not publish key event, "
691 "status=%d", connection->getInputChannelName(), status);
692 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
693 return;
694 }
695 break;
696 }
697
698 case EventEntry::TYPE_MOTION: {
699 MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
700
701 // Apply target flags.
702 int32_t action = motionEntry->action;
Jeff Brownaf30ff62010-09-01 17:01:00 -0700703 int32_t flags = motionEntry->flags;
Jeff Browne839a582010-04-22 18:58:52 -0700704 if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700705 action = AMOTION_EVENT_ACTION_OUTSIDE;
Jeff Browne839a582010-04-22 18:58:52 -0700706 }
707 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700708 action = AMOTION_EVENT_ACTION_CANCEL;
Jeff Browne839a582010-04-22 18:58:52 -0700709 }
Jeff Brownaf30ff62010-09-01 17:01:00 -0700710 if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
711 flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
712 }
Jeff Browne839a582010-04-22 18:58:52 -0700713
714 // If headMotionSample is non-NULL, then it points to the first new sample that we
715 // were unable to dispatch during the previous cycle so we resume dispatching from
716 // that point in the list of motion samples.
717 // Otherwise, we just start from the first sample of the motion event.
718 MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
719 if (! firstMotionSample) {
720 firstMotionSample = & motionEntry->firstSample;
721 }
722
Jeff Brownf26db0d2010-07-16 17:21:06 -0700723 // Set the X and Y offset depending on the input source.
724 float xOffset, yOffset;
725 if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
726 xOffset = dispatchEntry->xOffset;
727 yOffset = dispatchEntry->yOffset;
728 } else {
729 xOffset = 0.0f;
730 yOffset = 0.0f;
731 }
732
Jeff Browne839a582010-04-22 18:58:52 -0700733 // Publish the motion event and the first motion sample.
734 status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
Jeff Brownaf30ff62010-09-01 17:01:00 -0700735 motionEntry->source, action, flags, motionEntry->edgeFlags, motionEntry->metaState,
Jeff Brownf26db0d2010-07-16 17:21:06 -0700736 xOffset, yOffset,
Jeff Browne839a582010-04-22 18:58:52 -0700737 motionEntry->xPrecision, motionEntry->yPrecision,
738 motionEntry->downTime, firstMotionSample->eventTime,
739 motionEntry->pointerCount, motionEntry->pointerIds,
740 firstMotionSample->pointerCoords);
741
742 if (status) {
743 LOGE("channel '%s' ~ Could not publish motion event, "
744 "status=%d", connection->getInputChannelName(), status);
745 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
746 return;
747 }
748
749 // Append additional motion samples.
750 MotionSample* nextMotionSample = firstMotionSample->next;
751 for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
752 status = connection->inputPublisher.appendMotionSample(
753 nextMotionSample->eventTime, nextMotionSample->pointerCoords);
754 if (status == NO_MEMORY) {
755#if DEBUG_DISPATCH_CYCLE
756 LOGD("channel '%s' ~ Shared memory buffer full. Some motion samples will "
757 "be sent in the next dispatch cycle.",
758 connection->getInputChannelName());
759#endif
760 break;
761 }
762 if (status != OK) {
763 LOGE("channel '%s' ~ Could not append motion sample "
764 "for a reason other than out of memory, status=%d",
765 connection->getInputChannelName(), status);
766 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
767 return;
768 }
769 }
770
771 // Remember the next motion sample that we could not dispatch, in case we ran out
772 // of space in the shared memory buffer.
773 dispatchEntry->tailMotionSample = nextMotionSample;
774 break;
775 }
776
777 default: {
778 assert(false);
779 }
780 }
781
782 // Send the dispatch signal.
783 status = connection->inputPublisher.sendDispatchSignal();
784 if (status) {
785 LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
786 connection->getInputChannelName(), status);
787 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
788 return;
789 }
790
791 // Record information about the newly started dispatch cycle.
792 dispatchEntry->inProgress = true;
793
794 connection->lastEventTime = dispatchEntry->eventEntry->eventTime;
795 connection->lastDispatchTime = currentTime;
796
797 nsecs_t timeout = dispatchEntry->timeout;
Jeff Brown51d45a72010-06-17 20:52:56 -0700798 connection->setNextTimeoutTime(currentTime, timeout);
Jeff Browne839a582010-04-22 18:58:52 -0700799
800 // Notify other system components.
801 onDispatchCycleStartedLocked(currentTime, connection);
802}
803
Jeff Brown51d45a72010-06-17 20:52:56 -0700804void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
805 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -0700806#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700807 LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
Jeff Browne839a582010-04-22 18:58:52 -0700808 "%01.1fms since dispatch",
809 connection->getInputChannelName(),
810 connection->getEventLatencyMillis(currentTime),
811 connection->getDispatchLatencyMillis(currentTime));
812#endif
813
Jeff Brown54bc2812010-06-15 01:31:58 -0700814 if (connection->status == Connection::STATUS_BROKEN
815 || connection->status == Connection::STATUS_ZOMBIE) {
Jeff Browne839a582010-04-22 18:58:52 -0700816 return;
817 }
818
819 // Clear the pending timeout.
820 connection->nextTimeoutTime = LONG_LONG_MAX;
821
822 if (connection->status == Connection::STATUS_NOT_RESPONDING) {
823 // Recovering from an ANR.
824 connection->status = Connection::STATUS_NORMAL;
825
826 // Notify other system components.
827 onDispatchCycleFinishedLocked(currentTime, connection, true /*recoveredFromANR*/);
828 } else {
829 // Normal finish. Not much to do here.
830
831 // Notify other system components.
832 onDispatchCycleFinishedLocked(currentTime, connection, false /*recoveredFromANR*/);
833 }
834
835 // Reset the publisher since the event has been consumed.
836 // We do this now so that the publisher can release some of its internal resources
837 // while waiting for the next dispatch cycle to begin.
838 status_t status = connection->inputPublisher.reset();
839 if (status) {
840 LOGE("channel '%s' ~ Could not reset publisher, status=%d",
841 connection->getInputChannelName(), status);
842 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
843 return;
844 }
845
846 // Start the next dispatch cycle for this connection.
847 while (! connection->outboundQueue.isEmpty()) {
848 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
849 if (dispatchEntry->inProgress) {
850 // Finish or resume current event in progress.
851 if (dispatchEntry->tailMotionSample) {
852 // We have a tail of undispatched motion samples.
853 // Reuse the same DispatchEntry and start a new cycle.
854 dispatchEntry->inProgress = false;
855 dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
856 dispatchEntry->tailMotionSample = NULL;
857 startDispatchCycleLocked(currentTime, connection);
858 return;
859 }
860 // Finished.
861 connection->outboundQueue.dequeueAtHead();
Jeff Brownf67c53e2010-07-28 15:48:59 -0700862 if (dispatchEntry->isSyncTarget()) {
863 decrementPendingSyncDispatchesLocked(dispatchEntry->eventEntry);
864 }
Jeff Browne839a582010-04-22 18:58:52 -0700865 mAllocator.releaseDispatchEntry(dispatchEntry);
866 } else {
867 // If the head is not in progress, then we must have already dequeued the in
868 // progress event, which means we actually aborted it (due to ANR).
869 // So just start the next event for this connection.
870 startDispatchCycleLocked(currentTime, connection);
871 return;
872 }
873 }
874
875 // Outbound queue is empty, deactivate the connection.
Jeff Brown51d45a72010-06-17 20:52:56 -0700876 deactivateConnectionLocked(connection.get());
Jeff Browne839a582010-04-22 18:58:52 -0700877}
878
Jeff Brown51d45a72010-06-17 20:52:56 -0700879void InputDispatcher::timeoutDispatchCycleLocked(nsecs_t currentTime,
880 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -0700881#if DEBUG_DISPATCH_CYCLE
882 LOGD("channel '%s' ~ timeoutDispatchCycle",
883 connection->getInputChannelName());
884#endif
885
886 if (connection->status != Connection::STATUS_NORMAL) {
Jeff Brown51d45a72010-06-17 20:52:56 -0700887 return;
Jeff Browne839a582010-04-22 18:58:52 -0700888 }
889
890 // Enter the not responding state.
891 connection->status = Connection::STATUS_NOT_RESPONDING;
892 connection->lastANRTime = currentTime;
Jeff Browne839a582010-04-22 18:58:52 -0700893
894 // Notify other system components.
Jeff Brown51d45a72010-06-17 20:52:56 -0700895 // This enqueues a command which will eventually either call
896 // resumeAfterTimeoutDispatchCycleLocked or abortDispatchCycleLocked.
Jeff Browne839a582010-04-22 18:58:52 -0700897 onDispatchCycleANRLocked(currentTime, connection);
Jeff Browne839a582010-04-22 18:58:52 -0700898}
899
Jeff Brown51d45a72010-06-17 20:52:56 -0700900void InputDispatcher::resumeAfterTimeoutDispatchCycleLocked(nsecs_t currentTime,
901 const sp<Connection>& connection, nsecs_t newTimeout) {
902#if DEBUG_DISPATCH_CYCLE
903 LOGD("channel '%s' ~ resumeAfterTimeoutDispatchCycleLocked",
904 connection->getInputChannelName());
905#endif
906
907 if (connection->status != Connection::STATUS_NOT_RESPONDING) {
908 return;
909 }
910
911 // Resume normal dispatch.
912 connection->status = Connection::STATUS_NORMAL;
913 connection->setNextTimeoutTime(currentTime, newTimeout);
914}
915
916void InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime,
917 const sp<Connection>& connection, bool broken) {
Jeff Browne839a582010-04-22 18:58:52 -0700918#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700919 LOGD("channel '%s' ~ abortDispatchCycle - broken=%s",
Jeff Browne839a582010-04-22 18:58:52 -0700920 connection->getInputChannelName(), broken ? "true" : "false");
921#endif
922
Jeff Browne839a582010-04-22 18:58:52 -0700923 // Clear the pending timeout.
924 connection->nextTimeoutTime = LONG_LONG_MAX;
925
926 // Clear the outbound queue.
Jeff Brown51d45a72010-06-17 20:52:56 -0700927 if (! connection->outboundQueue.isEmpty()) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700928 do {
929 DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
Jeff Brownf67c53e2010-07-28 15:48:59 -0700930 if (dispatchEntry->isSyncTarget()) {
931 decrementPendingSyncDispatchesLocked(dispatchEntry->eventEntry);
932 }
Jeff Brown54bc2812010-06-15 01:31:58 -0700933 mAllocator.releaseDispatchEntry(dispatchEntry);
934 } while (! connection->outboundQueue.isEmpty());
Jeff Browne839a582010-04-22 18:58:52 -0700935
Jeff Brown51d45a72010-06-17 20:52:56 -0700936 deactivateConnectionLocked(connection.get());
Jeff Brown54bc2812010-06-15 01:31:58 -0700937 }
Jeff Browne839a582010-04-22 18:58:52 -0700938
939 // Handle the case where the connection appears to be unrecoverably broken.
Jeff Brown54bc2812010-06-15 01:31:58 -0700940 // Ignore already broken or zombie connections.
Jeff Browne839a582010-04-22 18:58:52 -0700941 if (broken) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700942 if (connection->status == Connection::STATUS_NORMAL
943 || connection->status == Connection::STATUS_NOT_RESPONDING) {
944 connection->status = Connection::STATUS_BROKEN;
Jeff Browne839a582010-04-22 18:58:52 -0700945
Jeff Brown54bc2812010-06-15 01:31:58 -0700946 // Notify other system components.
947 onDispatchCycleBrokenLocked(currentTime, connection);
948 }
Jeff Browne839a582010-04-22 18:58:52 -0700949 }
Jeff Browne839a582010-04-22 18:58:52 -0700950}
951
952bool InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
953 InputDispatcher* d = static_cast<InputDispatcher*>(data);
954
955 { // acquire lock
956 AutoMutex _l(d->mLock);
957
958 ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
959 if (connectionIndex < 0) {
960 LOGE("Received spurious receive callback for unknown input channel. "
961 "fd=%d, events=0x%x", receiveFd, events);
962 return false; // remove the callback
963 }
964
Jeff Brown51d45a72010-06-17 20:52:56 -0700965 nsecs_t currentTime = now();
Jeff Browne839a582010-04-22 18:58:52 -0700966
967 sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
968 if (events & (POLLERR | POLLHUP | POLLNVAL)) {
969 LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
970 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brown51d45a72010-06-17 20:52:56 -0700971 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -0700972 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700973 return false; // remove the callback
974 }
975
976 if (! (events & POLLIN)) {
977 LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
978 "events=0x%x", connection->getInputChannelName(), events);
979 return true;
980 }
981
982 status_t status = connection->inputPublisher.receiveFinishedSignal();
983 if (status) {
984 LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
985 connection->getInputChannelName(), status);
Jeff Brown51d45a72010-06-17 20:52:56 -0700986 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -0700987 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700988 return false; // remove the callback
989 }
990
Jeff Brown51d45a72010-06-17 20:52:56 -0700991 d->finishDispatchCycleLocked(currentTime, connection);
Jeff Brown54bc2812010-06-15 01:31:58 -0700992 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700993 return true;
994 } // release lock
995}
996
Jeff Brown54bc2812010-06-15 01:31:58 -0700997void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
Jeff Browne839a582010-04-22 18:58:52 -0700998#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown54bc2812010-06-15 01:31:58 -0700999 LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
Jeff Browne839a582010-04-22 18:58:52 -07001000#endif
1001
1002 bool wasEmpty;
1003 { // acquire lock
1004 AutoMutex _l(mLock);
1005
Jeff Brown51d45a72010-06-17 20:52:56 -07001006 ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
Jeff Browne839a582010-04-22 18:58:52 -07001007
1008 wasEmpty = mInboundQueue.isEmpty();
1009 mInboundQueue.enqueueAtTail(newEntry);
1010 } // release lock
1011
1012 if (wasEmpty) {
1013 mPollLoop->wake();
1014 }
1015}
1016
Jeff Browne839a582010-04-22 18:58:52 -07001017void InputDispatcher::notifyAppSwitchComing(nsecs_t eventTime) {
1018#if DEBUG_INBOUND_EVENT_DETAILS
1019 LOGD("notifyAppSwitchComing - eventTime=%lld", eventTime);
1020#endif
1021
1022 // Remove movement keys from the queue from most recent to least recent, stopping at the
1023 // first non-movement key.
1024 // TODO: Include a detailed description of why we do this...
1025
1026 { // acquire lock
1027 AutoMutex _l(mLock);
1028
1029 for (EventEntry* entry = mInboundQueue.tail.prev; entry != & mInboundQueue.head; ) {
1030 EventEntry* prev = entry->prev;
1031
1032 if (entry->type == EventEntry::TYPE_KEY) {
1033 KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
1034 if (isMovementKey(keyEntry->keyCode)) {
1035 LOGV("Dropping movement key during app switch: keyCode=%d, action=%d",
1036 keyEntry->keyCode, keyEntry->action);
1037 mInboundQueue.dequeue(keyEntry);
Jeff Brown51d45a72010-06-17 20:52:56 -07001038
1039 setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
1040
Jeff Browne839a582010-04-22 18:58:52 -07001041 mAllocator.releaseKeyEntry(keyEntry);
1042 } else {
1043 // stop at last non-movement key
1044 break;
1045 }
1046 }
1047
1048 entry = prev;
1049 }
1050 } // release lock
1051}
1052
Jeff Brown5c1ed842010-07-14 18:48:53 -07001053void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Browne839a582010-04-22 18:58:52 -07001054 uint32_t policyFlags, int32_t action, int32_t flags,
1055 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
1056#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -07001057 LOGD("notifyKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -07001058 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
Jeff Brown5c1ed842010-07-14 18:48:53 -07001059 eventTime, deviceId, source, policyFlags, action, flags,
Jeff Browne839a582010-04-22 18:58:52 -07001060 keyCode, scanCode, metaState, downTime);
1061#endif
1062
1063 bool wasEmpty;
1064 { // acquire lock
1065 AutoMutex _l(mLock);
1066
Jeff Brown51d45a72010-06-17 20:52:56 -07001067 int32_t repeatCount = 0;
1068 KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001069 deviceId, source, policyFlags, action, flags, keyCode, scanCode,
Jeff Brown51d45a72010-06-17 20:52:56 -07001070 metaState, repeatCount, downTime);
Jeff Browne839a582010-04-22 18:58:52 -07001071
1072 wasEmpty = mInboundQueue.isEmpty();
1073 mInboundQueue.enqueueAtTail(newEntry);
1074 } // release lock
1075
1076 if (wasEmpty) {
1077 mPollLoop->wake();
1078 }
1079}
1080
Jeff Brown5c1ed842010-07-14 18:48:53 -07001081void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001082 uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t edgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07001083 uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
1084 float xPrecision, float yPrecision, nsecs_t downTime) {
1085#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -07001086 LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Brownaf30ff62010-09-01 17:01:00 -07001087 "action=0x%x, flags=0x%x, metaState=0x%x, edgeFlags=0x%x, "
1088 "xPrecision=%f, yPrecision=%f, downTime=%lld",
1089 eventTime, deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07001090 xPrecision, yPrecision, downTime);
1091 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001092 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
Jeff Brownaf30ff62010-09-01 17:01:00 -07001093 "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
Jeff Brown38a7fab2010-08-30 03:02:23 -07001094 "orientation=%f",
Jeff Browne839a582010-04-22 18:58:52 -07001095 i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
Jeff Brown38a7fab2010-08-30 03:02:23 -07001096 pointerCoords[i].pressure, pointerCoords[i].size,
1097 pointerCoords[i].touchMajor, pointerCoords[i].touchMinor,
1098 pointerCoords[i].toolMajor, pointerCoords[i].toolMinor,
1099 pointerCoords[i].orientation);
Jeff Browne839a582010-04-22 18:58:52 -07001100 }
1101#endif
1102
1103 bool wasEmpty;
1104 { // acquire lock
1105 AutoMutex _l(mLock);
1106
1107 // Attempt batching and streaming of move events.
Jeff Brown5c1ed842010-07-14 18:48:53 -07001108 if (action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Browne839a582010-04-22 18:58:52 -07001109 // BATCHING CASE
1110 //
1111 // Try to append a move sample to the tail of the inbound queue for this device.
1112 // Give up if we encounter a non-move motion event for this device since that
1113 // means we cannot append any new samples until a new motion event has started.
1114 for (EventEntry* entry = mInboundQueue.tail.prev;
1115 entry != & mInboundQueue.head; entry = entry->prev) {
1116 if (entry->type != EventEntry::TYPE_MOTION) {
1117 // Keep looking for motion events.
1118 continue;
1119 }
1120
1121 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
1122 if (motionEntry->deviceId != deviceId) {
1123 // Keep looking for this device.
1124 continue;
1125 }
1126
Jeff Brown5c1ed842010-07-14 18:48:53 -07001127 if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown51d45a72010-06-17 20:52:56 -07001128 || motionEntry->pointerCount != pointerCount
1129 || motionEntry->isInjected()) {
Jeff Browne839a582010-04-22 18:58:52 -07001130 // Last motion event in the queue for this device is not compatible for
1131 // appending new samples. Stop here.
1132 goto NoBatchingOrStreaming;
1133 }
1134
1135 // The last motion event is a move and is compatible for appending.
Jeff Brown54bc2812010-06-15 01:31:58 -07001136 // Do the batching magic.
Jeff Brown51d45a72010-06-17 20:52:56 -07001137 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
Jeff Browne839a582010-04-22 18:58:52 -07001138#if DEBUG_BATCHING
1139 LOGD("Appended motion sample onto batch for most recent "
1140 "motion event for this device in the inbound queue.");
1141#endif
Jeff Brown54bc2812010-06-15 01:31:58 -07001142
1143 // Sanity check for special case because dispatch is interruptible.
1144 // The dispatch logic is partially interruptible and releases its lock while
1145 // identifying targets. However, as soon as the targets have been identified,
1146 // the dispatcher proceeds to write a dispatch entry into all relevant outbound
1147 // queues and then promptly removes the motion entry from the queue.
1148 //
1149 // Consequently, we should never observe the case where the inbound queue contains
1150 // an in-progress motion entry unless the current input targets are invalid
1151 // (currently being computed). Check for this!
1152 assert(! (motionEntry->dispatchInProgress && mCurrentInputTargetsValid));
1153
1154 return; // done!
Jeff Browne839a582010-04-22 18:58:52 -07001155 }
1156
1157 // STREAMING CASE
1158 //
1159 // There is no pending motion event (of any kind) for this device in the inbound queue.
1160 // Search the outbound queues for a synchronously dispatched motion event for this
1161 // device. If found, then we append the new sample to that event and then try to
1162 // push it out to all current targets. It is possible that some targets will already
1163 // have consumed the motion event. This case is automatically handled by the
1164 // logic in prepareDispatchCycleLocked by tracking where resumption takes place.
1165 //
1166 // The reason we look for a synchronously dispatched motion event is because we
1167 // want to be sure that no other motion events have been dispatched since the move.
1168 // It's also convenient because it means that the input targets are still valid.
1169 // This code could be improved to support streaming of asynchronously dispatched
1170 // motion events (which might be significantly more efficient) but it may become
1171 // a little more complicated as a result.
1172 //
1173 // Note: This code crucially depends on the invariant that an outbound queue always
1174 // contains at most one synchronous event and it is always last (but it might
1175 // not be first!).
Jeff Brown54bc2812010-06-15 01:31:58 -07001176 if (mCurrentInputTargetsValid) {
1177 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1178 Connection* connection = mActiveConnections.itemAt(i);
1179 if (! connection->outboundQueue.isEmpty()) {
1180 DispatchEntry* dispatchEntry = connection->outboundQueue.tail.prev;
Jeff Brownf67c53e2010-07-28 15:48:59 -07001181 if (dispatchEntry->isSyncTarget()) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001182 if (dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION) {
1183 goto NoBatchingOrStreaming;
1184 }
Jeff Browne839a582010-04-22 18:58:52 -07001185
Jeff Brown54bc2812010-06-15 01:31:58 -07001186 MotionEntry* syncedMotionEntry = static_cast<MotionEntry*>(
1187 dispatchEntry->eventEntry);
Jeff Brown5c1ed842010-07-14 18:48:53 -07001188 if (syncedMotionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown54bc2812010-06-15 01:31:58 -07001189 || syncedMotionEntry->deviceId != deviceId
Jeff Brown51d45a72010-06-17 20:52:56 -07001190 || syncedMotionEntry->pointerCount != pointerCount
1191 || syncedMotionEntry->isInjected()) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001192 goto NoBatchingOrStreaming;
1193 }
Jeff Browne839a582010-04-22 18:58:52 -07001194
Jeff Brown54bc2812010-06-15 01:31:58 -07001195 // Found synced move entry. Append sample and resume dispatch.
1196 mAllocator.appendMotionSample(syncedMotionEntry, eventTime,
Jeff Brown51d45a72010-06-17 20:52:56 -07001197 pointerCoords);
Jeff Brown54bc2812010-06-15 01:31:58 -07001198 #if DEBUG_BATCHING
1199 LOGD("Appended motion sample onto batch for most recent synchronously "
1200 "dispatched motion event for this device in the outbound queues.");
1201 #endif
Jeff Brown51d45a72010-06-17 20:52:56 -07001202 nsecs_t currentTime = now();
Jeff Brown54bc2812010-06-15 01:31:58 -07001203 dispatchEventToCurrentInputTargetsLocked(currentTime, syncedMotionEntry,
1204 true /*resumeWithAppendedMotionSample*/);
1205
1206 runCommandsLockedInterruptible();
1207 return; // done!
1208 }
Jeff Browne839a582010-04-22 18:58:52 -07001209 }
1210 }
1211 }
1212
1213NoBatchingOrStreaming:;
1214 }
1215
1216 // Just enqueue a new motion event.
Jeff Brown51d45a72010-06-17 20:52:56 -07001217 MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001218 deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -07001219 xPrecision, yPrecision, downTime,
1220 pointerCount, pointerIds, pointerCoords);
Jeff Browne839a582010-04-22 18:58:52 -07001221
1222 wasEmpty = mInboundQueue.isEmpty();
1223 mInboundQueue.enqueueAtTail(newEntry);
1224 } // release lock
1225
1226 if (wasEmpty) {
1227 mPollLoop->wake();
1228 }
1229}
1230
Jeff Brown51d45a72010-06-17 20:52:56 -07001231int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
Jeff Brownf67c53e2010-07-28 15:48:59 -07001232 int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001233#if DEBUG_INBOUND_EVENT_DETAILS
1234 LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
Jeff Brownf67c53e2010-07-28 15:48:59 -07001235 "syncMode=%d, timeoutMillis=%d",
1236 event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis);
Jeff Brown51d45a72010-06-17 20:52:56 -07001237#endif
1238
1239 nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
1240
1241 EventEntry* injectedEntry;
1242 bool wasEmpty;
1243 { // acquire lock
1244 AutoMutex _l(mLock);
1245
1246 injectedEntry = createEntryFromInputEventLocked(event);
1247 injectedEntry->refCount += 1;
1248 injectedEntry->injectorPid = injectorPid;
1249 injectedEntry->injectorUid = injectorUid;
1250
Jeff Brownf67c53e2010-07-28 15:48:59 -07001251 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
1252 injectedEntry->injectionIsAsync = true;
1253 }
1254
Jeff Brown51d45a72010-06-17 20:52:56 -07001255 wasEmpty = mInboundQueue.isEmpty();
1256 mInboundQueue.enqueueAtTail(injectedEntry);
1257
1258 } // release lock
1259
1260 if (wasEmpty) {
1261 mPollLoop->wake();
1262 }
1263
1264 int32_t injectionResult;
1265 { // acquire lock
1266 AutoMutex _l(mLock);
1267
Jeff Brownf67c53e2010-07-28 15:48:59 -07001268 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
1269 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1270 } else {
1271 for (;;) {
1272 injectionResult = injectedEntry->injectionResult;
1273 if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
1274 break;
1275 }
Jeff Brown51d45a72010-06-17 20:52:56 -07001276
Jeff Brown51d45a72010-06-17 20:52:56 -07001277 nsecs_t remainingTimeout = endTime - now();
1278 if (remainingTimeout <= 0) {
Jeff Brownf67c53e2010-07-28 15:48:59 -07001279#if DEBUG_INJECTION
1280 LOGD("injectInputEvent - Timed out waiting for injection result "
1281 "to become available.");
1282#endif
Jeff Brown51d45a72010-06-17 20:52:56 -07001283 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1284 break;
1285 }
1286
Jeff Brownf67c53e2010-07-28 15:48:59 -07001287 mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
1288 }
1289
1290 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
1291 && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
1292 while (injectedEntry->pendingSyncDispatches != 0) {
1293#if DEBUG_INJECTION
1294 LOGD("injectInputEvent - Waiting for %d pending synchronous dispatches.",
1295 injectedEntry->pendingSyncDispatches);
1296#endif
1297 nsecs_t remainingTimeout = endTime - now();
1298 if (remainingTimeout <= 0) {
1299#if DEBUG_INJECTION
1300 LOGD("injectInputEvent - Timed out waiting for pending synchronous "
1301 "dispatches to finish.");
1302#endif
1303 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1304 break;
1305 }
1306
1307 mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
1308 }
Jeff Brown51d45a72010-06-17 20:52:56 -07001309 }
1310 }
1311
1312 mAllocator.releaseEventEntry(injectedEntry);
1313 } // release lock
1314
Jeff Brownf67c53e2010-07-28 15:48:59 -07001315#if DEBUG_INJECTION
1316 LOGD("injectInputEvent - Finished with result %d. "
1317 "injectorPid=%d, injectorUid=%d",
1318 injectionResult, injectorPid, injectorUid);
1319#endif
1320
Jeff Brown51d45a72010-06-17 20:52:56 -07001321 return injectionResult;
1322}
1323
1324void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
1325 if (entry->isInjected()) {
1326#if DEBUG_INJECTION
1327 LOGD("Setting input event injection result to %d. "
1328 "injectorPid=%d, injectorUid=%d",
1329 injectionResult, entry->injectorPid, entry->injectorUid);
1330#endif
1331
Jeff Brownf67c53e2010-07-28 15:48:59 -07001332 if (entry->injectionIsAsync) {
1333 // Log the outcome since the injector did not wait for the injection result.
1334 switch (injectionResult) {
1335 case INPUT_EVENT_INJECTION_SUCCEEDED:
1336 LOGV("Asynchronous input event injection succeeded.");
1337 break;
1338 case INPUT_EVENT_INJECTION_FAILED:
1339 LOGW("Asynchronous input event injection failed.");
1340 break;
1341 case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
1342 LOGW("Asynchronous input event injection permission denied.");
1343 break;
1344 case INPUT_EVENT_INJECTION_TIMED_OUT:
1345 LOGW("Asynchronous input event injection timed out.");
1346 break;
1347 }
1348 }
1349
Jeff Brown51d45a72010-06-17 20:52:56 -07001350 entry->injectionResult = injectionResult;
1351 mInjectionResultAvailableCondition.broadcast();
1352 }
1353}
1354
Jeff Brownf67c53e2010-07-28 15:48:59 -07001355void InputDispatcher::decrementPendingSyncDispatchesLocked(EventEntry* entry) {
1356 entry->pendingSyncDispatches -= 1;
1357
1358 if (entry->isInjected() && entry->pendingSyncDispatches == 0) {
1359 mInjectionSyncFinishedCondition.broadcast();
1360 }
Jeff Brown51d45a72010-06-17 20:52:56 -07001361}
1362
1363InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked(
1364 const InputEvent* event) {
1365 switch (event->getType()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07001366 case AINPUT_EVENT_TYPE_KEY: {
Jeff Brown51d45a72010-06-17 20:52:56 -07001367 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
Jeff Brownaf30ff62010-09-01 17:01:00 -07001368 uint32_t policyFlags = POLICY_FLAG_INJECTED;
Jeff Brown51d45a72010-06-17 20:52:56 -07001369
1370 KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
Jeff Brown5c1ed842010-07-14 18:48:53 -07001371 keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -07001372 keyEvent->getAction(), keyEvent->getFlags(),
1373 keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
1374 keyEvent->getRepeatCount(), keyEvent->getDownTime());
1375 return keyEntry;
1376 }
1377
Jeff Brown5c1ed842010-07-14 18:48:53 -07001378 case AINPUT_EVENT_TYPE_MOTION: {
Jeff Brown51d45a72010-06-17 20:52:56 -07001379 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
Jeff Brownaf30ff62010-09-01 17:01:00 -07001380 uint32_t policyFlags = POLICY_FLAG_INJECTED;
Jeff Brown51d45a72010-06-17 20:52:56 -07001381
1382 const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
1383 const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
1384 size_t pointerCount = motionEvent->getPointerCount();
1385
1386 MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001387 motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001388 motionEvent->getAction(), motionEvent->getFlags(),
1389 motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
Jeff Brown51d45a72010-06-17 20:52:56 -07001390 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
1391 motionEvent->getDownTime(), uint32_t(pointerCount),
1392 motionEvent->getPointerIds(), samplePointerCoords);
1393 for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
1394 sampleEventTimes += 1;
1395 samplePointerCoords += pointerCount;
1396 mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
1397 }
1398 return motionEntry;
1399 }
1400
1401 default:
1402 assert(false);
1403 return NULL;
1404 }
1405}
1406
Jeff Browne839a582010-04-22 18:58:52 -07001407void InputDispatcher::resetKeyRepeatLocked() {
1408 if (mKeyRepeatState.lastKeyEntry) {
1409 mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
1410 mKeyRepeatState.lastKeyEntry = NULL;
1411 }
1412}
1413
Jeff Brown50de30a2010-06-22 01:27:15 -07001414void InputDispatcher::preemptInputDispatch() {
1415#if DEBUG_DISPATCH_CYCLE
1416 LOGD("preemptInputDispatch");
1417#endif
1418
1419 bool preemptedOne = false;
1420 { // acquire lock
1421 AutoMutex _l(mLock);
1422
1423 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1424 Connection* connection = mActiveConnections[i];
1425 if (connection->hasPendingSyncTarget()) {
1426#if DEBUG_DISPATCH_CYCLE
1427 LOGD("channel '%s' ~ Preempted pending synchronous dispatch",
1428 connection->getInputChannelName());
1429#endif
1430 connection->outboundQueue.tail.prev->targetFlags &= ~ InputTarget::FLAG_SYNC;
1431 preemptedOne = true;
1432 }
1433 }
1434 } // release lock
1435
1436 if (preemptedOne) {
1437 // Wake up the poll loop so it can get a head start dispatching the next event.
1438 mPollLoop->wake();
1439 }
1440}
1441
Jeff Browne839a582010-04-22 18:58:52 -07001442status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001443#if DEBUG_REGISTRATION
Jeff Brown50de30a2010-06-22 01:27:15 -07001444 LOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().string());
Jeff Brown54bc2812010-06-15 01:31:58 -07001445#endif
1446
Jeff Browne839a582010-04-22 18:58:52 -07001447 { // acquire lock
1448 AutoMutex _l(mLock);
1449
Jeff Brown0cacb872010-08-17 15:59:26 -07001450 if (getConnectionIndex(inputChannel) >= 0) {
Jeff Browne839a582010-04-22 18:58:52 -07001451 LOGW("Attempted to register already registered input channel '%s'",
1452 inputChannel->getName().string());
1453 return BAD_VALUE;
1454 }
1455
1456 sp<Connection> connection = new Connection(inputChannel);
1457 status_t status = connection->initialize();
1458 if (status) {
1459 LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
1460 inputChannel->getName().string(), status);
1461 return status;
1462 }
1463
Jeff Brown0cacb872010-08-17 15:59:26 -07001464 int32_t receiveFd = inputChannel->getReceivePipeFd();
Jeff Browne839a582010-04-22 18:58:52 -07001465 mConnectionsByReceiveFd.add(receiveFd, connection);
Jeff Brown54bc2812010-06-15 01:31:58 -07001466
Jeff Brown0cacb872010-08-17 15:59:26 -07001467 mPollLoop->setCallback(receiveFd, POLLIN, handleReceiveCallback, this);
1468
Jeff Brown54bc2812010-06-15 01:31:58 -07001469 runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07001470 } // release lock
Jeff Browne839a582010-04-22 18:58:52 -07001471 return OK;
1472}
1473
1474status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001475#if DEBUG_REGISTRATION
Jeff Brown50de30a2010-06-22 01:27:15 -07001476 LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
Jeff Brown54bc2812010-06-15 01:31:58 -07001477#endif
1478
Jeff Browne839a582010-04-22 18:58:52 -07001479 { // acquire lock
1480 AutoMutex _l(mLock);
1481
Jeff Brown0cacb872010-08-17 15:59:26 -07001482 ssize_t connectionIndex = getConnectionIndex(inputChannel);
Jeff Browne839a582010-04-22 18:58:52 -07001483 if (connectionIndex < 0) {
1484 LOGW("Attempted to unregister already unregistered input channel '%s'",
1485 inputChannel->getName().string());
1486 return BAD_VALUE;
1487 }
1488
1489 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1490 mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
1491
1492 connection->status = Connection::STATUS_ZOMBIE;
1493
Jeff Brown0cacb872010-08-17 15:59:26 -07001494 mPollLoop->removeCallback(inputChannel->getReceivePipeFd());
1495
Jeff Brown51d45a72010-06-17 20:52:56 -07001496 nsecs_t currentTime = now();
1497 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -07001498
1499 runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07001500 } // release lock
1501
Jeff Browne839a582010-04-22 18:58:52 -07001502 // Wake the poll loop because removing the connection may have changed the current
1503 // synchronization state.
1504 mPollLoop->wake();
1505 return OK;
1506}
1507
Jeff Brown0cacb872010-08-17 15:59:26 -07001508ssize_t InputDispatcher::getConnectionIndex(const sp<InputChannel>& inputChannel) {
1509 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(inputChannel->getReceivePipeFd());
1510 if (connectionIndex >= 0) {
1511 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1512 if (connection->inputChannel.get() == inputChannel.get()) {
1513 return connectionIndex;
1514 }
1515 }
1516
1517 return -1;
1518}
1519
Jeff Browne839a582010-04-22 18:58:52 -07001520void InputDispatcher::activateConnectionLocked(Connection* connection) {
1521 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1522 if (mActiveConnections.itemAt(i) == connection) {
1523 return;
1524 }
1525 }
1526 mActiveConnections.add(connection);
1527}
1528
1529void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
1530 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1531 if (mActiveConnections.itemAt(i) == connection) {
1532 mActiveConnections.removeAt(i);
1533 return;
1534 }
1535 }
1536}
1537
Jeff Brown54bc2812010-06-15 01:31:58 -07001538void InputDispatcher::onDispatchCycleStartedLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001539 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001540}
1541
Jeff Brown54bc2812010-06-15 01:31:58 -07001542void InputDispatcher::onDispatchCycleFinishedLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001543 nsecs_t currentTime, const sp<Connection>& connection, bool recoveredFromANR) {
Jeff Browne839a582010-04-22 18:58:52 -07001544 if (recoveredFromANR) {
1545 LOGI("channel '%s' ~ Recovered from ANR. %01.1fms since event, "
1546 "%01.1fms since dispatch, %01.1fms since ANR",
1547 connection->getInputChannelName(),
1548 connection->getEventLatencyMillis(currentTime),
1549 connection->getDispatchLatencyMillis(currentTime),
1550 connection->getANRLatencyMillis(currentTime));
1551
Jeff Brown54bc2812010-06-15 01:31:58 -07001552 CommandEntry* commandEntry = postCommandLocked(
1553 & InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07001554 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07001555 }
1556}
1557
Jeff Brown54bc2812010-06-15 01:31:58 -07001558void InputDispatcher::onDispatchCycleANRLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001559 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001560 LOGI("channel '%s' ~ Not responding! %01.1fms since event, %01.1fms since dispatch",
1561 connection->getInputChannelName(),
1562 connection->getEventLatencyMillis(currentTime),
1563 connection->getDispatchLatencyMillis(currentTime));
1564
Jeff Brown54bc2812010-06-15 01:31:58 -07001565 CommandEntry* commandEntry = postCommandLocked(
1566 & InputDispatcher::doNotifyInputChannelANRLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07001567 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07001568}
1569
Jeff Brown54bc2812010-06-15 01:31:58 -07001570void InputDispatcher::onDispatchCycleBrokenLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001571 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001572 LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
1573 connection->getInputChannelName());
1574
Jeff Brown54bc2812010-06-15 01:31:58 -07001575 CommandEntry* commandEntry = postCommandLocked(
1576 & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07001577 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07001578}
1579
Jeff Brown54bc2812010-06-15 01:31:58 -07001580void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
1581 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001582 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07001583
Jeff Brown51d45a72010-06-17 20:52:56 -07001584 if (connection->status != Connection::STATUS_ZOMBIE) {
1585 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07001586
Jeff Brown51d45a72010-06-17 20:52:56 -07001587 mPolicy->notifyInputChannelBroken(connection->inputChannel);
1588
1589 mLock.lock();
1590 }
Jeff Brown54bc2812010-06-15 01:31:58 -07001591}
1592
1593void InputDispatcher::doNotifyInputChannelANRLockedInterruptible(
1594 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001595 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07001596
Jeff Brown51d45a72010-06-17 20:52:56 -07001597 if (connection->status != Connection::STATUS_ZOMBIE) {
1598 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07001599
Jeff Brown51d45a72010-06-17 20:52:56 -07001600 nsecs_t newTimeout;
1601 bool resume = mPolicy->notifyInputChannelANR(connection->inputChannel, newTimeout);
1602
1603 mLock.lock();
1604
1605 nsecs_t currentTime = now();
1606 if (resume) {
1607 resumeAfterTimeoutDispatchCycleLocked(currentTime, connection, newTimeout);
1608 } else {
1609 abortDispatchCycleLocked(currentTime, connection, false /*(not) broken*/);
1610 }
1611 }
Jeff Brown54bc2812010-06-15 01:31:58 -07001612}
1613
1614void InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible(
1615 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001616 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07001617
Jeff Brown51d45a72010-06-17 20:52:56 -07001618 if (connection->status != Connection::STATUS_ZOMBIE) {
1619 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07001620
Jeff Brown51d45a72010-06-17 20:52:56 -07001621 mPolicy->notifyInputChannelRecoveredFromANR(connection->inputChannel);
1622
1623 mLock.lock();
1624 }
Jeff Brown54bc2812010-06-15 01:31:58 -07001625}
1626
1627
Jeff Browne839a582010-04-22 18:58:52 -07001628// --- InputDispatcher::Allocator ---
1629
1630InputDispatcher::Allocator::Allocator() {
1631}
1632
Jeff Brown51d45a72010-06-17 20:52:56 -07001633void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
1634 nsecs_t eventTime) {
1635 entry->type = type;
1636 entry->refCount = 1;
1637 entry->dispatchInProgress = false;
Christopher Tated974e002010-06-23 16:50:30 -07001638 entry->eventTime = eventTime;
Jeff Brown51d45a72010-06-17 20:52:56 -07001639 entry->injectionResult = INPUT_EVENT_INJECTION_PENDING;
Jeff Brownf67c53e2010-07-28 15:48:59 -07001640 entry->injectionIsAsync = false;
Jeff Brown51d45a72010-06-17 20:52:56 -07001641 entry->injectorPid = -1;
1642 entry->injectorUid = -1;
Jeff Brownf67c53e2010-07-28 15:48:59 -07001643 entry->pendingSyncDispatches = 0;
Jeff Brown51d45a72010-06-17 20:52:56 -07001644}
1645
Jeff Browne839a582010-04-22 18:58:52 -07001646InputDispatcher::ConfigurationChangedEntry*
Jeff Brown51d45a72010-06-17 20:52:56 -07001647InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
Jeff Browne839a582010-04-22 18:58:52 -07001648 ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07001649 initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime);
Jeff Browne839a582010-04-22 18:58:52 -07001650 return entry;
1651}
1652
Jeff Brown51d45a72010-06-17 20:52:56 -07001653InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001654 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
Jeff Brown51d45a72010-06-17 20:52:56 -07001655 int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
1656 int32_t repeatCount, nsecs_t downTime) {
Jeff Browne839a582010-04-22 18:58:52 -07001657 KeyEntry* entry = mKeyEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07001658 initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime);
1659
1660 entry->deviceId = deviceId;
Jeff Brown5c1ed842010-07-14 18:48:53 -07001661 entry->source = source;
Jeff Brown51d45a72010-06-17 20:52:56 -07001662 entry->policyFlags = policyFlags;
1663 entry->action = action;
1664 entry->flags = flags;
1665 entry->keyCode = keyCode;
1666 entry->scanCode = scanCode;
1667 entry->metaState = metaState;
1668 entry->repeatCount = repeatCount;
1669 entry->downTime = downTime;
Jeff Browne839a582010-04-22 18:58:52 -07001670 return entry;
1671}
1672
Jeff Brown51d45a72010-06-17 20:52:56 -07001673InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001674 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
Jeff Brown51d45a72010-06-17 20:52:56 -07001675 int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
1676 nsecs_t downTime, uint32_t pointerCount,
1677 const int32_t* pointerIds, const PointerCoords* pointerCoords) {
Jeff Browne839a582010-04-22 18:58:52 -07001678 MotionEntry* entry = mMotionEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07001679 initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime);
1680
1681 entry->eventTime = eventTime;
1682 entry->deviceId = deviceId;
Jeff Brown5c1ed842010-07-14 18:48:53 -07001683 entry->source = source;
Jeff Brown51d45a72010-06-17 20:52:56 -07001684 entry->policyFlags = policyFlags;
1685 entry->action = action;
Jeff Brownaf30ff62010-09-01 17:01:00 -07001686 entry->flags = flags;
Jeff Brown51d45a72010-06-17 20:52:56 -07001687 entry->metaState = metaState;
1688 entry->edgeFlags = edgeFlags;
1689 entry->xPrecision = xPrecision;
1690 entry->yPrecision = yPrecision;
1691 entry->downTime = downTime;
1692 entry->pointerCount = pointerCount;
1693 entry->firstSample.eventTime = eventTime;
Jeff Browne839a582010-04-22 18:58:52 -07001694 entry->firstSample.next = NULL;
Jeff Brown51d45a72010-06-17 20:52:56 -07001695 entry->lastSample = & entry->firstSample;
1696 for (uint32_t i = 0; i < pointerCount; i++) {
1697 entry->pointerIds[i] = pointerIds[i];
1698 entry->firstSample.pointerCoords[i] = pointerCoords[i];
1699 }
Jeff Browne839a582010-04-22 18:58:52 -07001700 return entry;
1701}
1702
1703InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
1704 EventEntry* eventEntry) {
1705 DispatchEntry* entry = mDispatchEntryPool.alloc();
1706 entry->eventEntry = eventEntry;
1707 eventEntry->refCount += 1;
1708 return entry;
1709}
1710
Jeff Brown54bc2812010-06-15 01:31:58 -07001711InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
1712 CommandEntry* entry = mCommandEntryPool.alloc();
1713 entry->command = command;
1714 return entry;
1715}
1716
Jeff Browne839a582010-04-22 18:58:52 -07001717void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
1718 switch (entry->type) {
1719 case EventEntry::TYPE_CONFIGURATION_CHANGED:
1720 releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
1721 break;
1722 case EventEntry::TYPE_KEY:
1723 releaseKeyEntry(static_cast<KeyEntry*>(entry));
1724 break;
1725 case EventEntry::TYPE_MOTION:
1726 releaseMotionEntry(static_cast<MotionEntry*>(entry));
1727 break;
1728 default:
1729 assert(false);
1730 break;
1731 }
1732}
1733
1734void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
1735 ConfigurationChangedEntry* entry) {
1736 entry->refCount -= 1;
1737 if (entry->refCount == 0) {
1738 mConfigurationChangeEntryPool.free(entry);
1739 } else {
1740 assert(entry->refCount > 0);
1741 }
1742}
1743
1744void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
1745 entry->refCount -= 1;
1746 if (entry->refCount == 0) {
1747 mKeyEntryPool.free(entry);
1748 } else {
1749 assert(entry->refCount > 0);
1750 }
1751}
1752
1753void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
1754 entry->refCount -= 1;
1755 if (entry->refCount == 0) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001756 for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
1757 MotionSample* next = sample->next;
1758 mMotionSamplePool.free(sample);
1759 sample = next;
1760 }
Jeff Browne839a582010-04-22 18:58:52 -07001761 mMotionEntryPool.free(entry);
1762 } else {
1763 assert(entry->refCount > 0);
1764 }
1765}
1766
1767void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
1768 releaseEventEntry(entry->eventEntry);
1769 mDispatchEntryPool.free(entry);
1770}
1771
Jeff Brown54bc2812010-06-15 01:31:58 -07001772void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
1773 mCommandEntryPool.free(entry);
1774}
1775
Jeff Browne839a582010-04-22 18:58:52 -07001776void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
Jeff Brown51d45a72010-06-17 20:52:56 -07001777 nsecs_t eventTime, const PointerCoords* pointerCoords) {
Jeff Browne839a582010-04-22 18:58:52 -07001778 MotionSample* sample = mMotionSamplePool.alloc();
1779 sample->eventTime = eventTime;
Jeff Brown51d45a72010-06-17 20:52:56 -07001780 uint32_t pointerCount = motionEntry->pointerCount;
1781 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Browne839a582010-04-22 18:58:52 -07001782 sample->pointerCoords[i] = pointerCoords[i];
1783 }
1784
1785 sample->next = NULL;
1786 motionEntry->lastSample->next = sample;
1787 motionEntry->lastSample = sample;
1788}
1789
Jeff Brown542412c2010-08-18 15:51:08 -07001790// --- InputDispatcher::MotionEntry ---
1791
1792uint32_t InputDispatcher::MotionEntry::countSamples() const {
1793 uint32_t count = 1;
1794 for (MotionSample* sample = firstSample.next; sample != NULL; sample = sample->next) {
1795 count += 1;
1796 }
1797 return count;
1798}
1799
Jeff Browne839a582010-04-22 18:58:52 -07001800// --- InputDispatcher::Connection ---
1801
1802InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
1803 status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
1804 nextTimeoutTime(LONG_LONG_MAX),
1805 lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX),
1806 lastANRTime(LONG_LONG_MAX) {
1807}
1808
1809InputDispatcher::Connection::~Connection() {
1810}
1811
1812status_t InputDispatcher::Connection::initialize() {
1813 return inputPublisher.initialize();
1814}
1815
Jeff Brown51d45a72010-06-17 20:52:56 -07001816void InputDispatcher::Connection::setNextTimeoutTime(nsecs_t currentTime, nsecs_t timeout) {
1817 nextTimeoutTime = (timeout >= 0) ? currentTime + timeout : LONG_LONG_MAX;
1818}
1819
Jeff Brown54bc2812010-06-15 01:31:58 -07001820const char* InputDispatcher::Connection::getStatusLabel() const {
1821 switch (status) {
1822 case STATUS_NORMAL:
1823 return "NORMAL";
1824
1825 case STATUS_BROKEN:
1826 return "BROKEN";
1827
1828 case STATUS_NOT_RESPONDING:
1829 return "NOT_RESPONDING";
1830
1831 case STATUS_ZOMBIE:
1832 return "ZOMBIE";
1833
1834 default:
1835 return "UNKNOWN";
1836 }
1837}
1838
Jeff Browne839a582010-04-22 18:58:52 -07001839InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
1840 const EventEntry* eventEntry) const {
1841 for (DispatchEntry* dispatchEntry = outboundQueue.tail.prev;
1842 dispatchEntry != & outboundQueue.head; dispatchEntry = dispatchEntry->prev) {
1843 if (dispatchEntry->eventEntry == eventEntry) {
1844 return dispatchEntry;
1845 }
1846 }
1847 return NULL;
1848}
1849
Jeff Brown54bc2812010-06-15 01:31:58 -07001850// --- InputDispatcher::CommandEntry ---
1851
1852InputDispatcher::CommandEntry::CommandEntry() {
1853}
1854
1855InputDispatcher::CommandEntry::~CommandEntry() {
1856}
1857
Jeff Browne839a582010-04-22 18:58:52 -07001858
1859// --- InputDispatcherThread ---
1860
1861InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
1862 Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
1863}
1864
1865InputDispatcherThread::~InputDispatcherThread() {
1866}
1867
1868bool InputDispatcherThread::threadLoop() {
1869 mDispatcher->dispatchOnce();
1870 return true;
1871}
1872
1873} // namespace android