blob: df232d425bd31950bc7db53cf789768be0e58736 [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 Brown61ce3982010-09-07 10:44:57 -0700100 nsecs_t keyRepeatDelay = mPolicy->getKeyRepeatDelay();
Jeff Browne839a582010-04-22 18:58:52 -0700101
Jeff Brown54bc2812010-06-15 01:31:58 -0700102 bool skipPoll = false;
Jeff Browne839a582010-04-22 18:58:52 -0700103 nsecs_t currentTime;
104 nsecs_t nextWakeupTime = LONG_LONG_MAX;
105 { // acquire lock
106 AutoMutex _l(mLock);
Jeff Brown51d45a72010-06-17 20:52:56 -0700107 currentTime = now();
Jeff Browne839a582010-04-22 18:58:52 -0700108
109 // Reset the key repeat timer whenever we disallow key events, even if the next event
110 // is not a key. This is to ensure that we abort a key repeat if the device is just coming
111 // out of sleep.
112 // XXX we should handle resetting input state coming out of sleep more generally elsewhere
Jeff Brown54bc2812010-06-15 01:31:58 -0700113 if (keyRepeatTimeout < 0) {
Jeff Browne839a582010-04-22 18:58:52 -0700114 resetKeyRepeatLocked();
115 }
116
Jeff Brown51d45a72010-06-17 20:52:56 -0700117 // Detect and process timeouts for all connections and determine if there are any
118 // synchronous event dispatches pending. This step is entirely non-interruptible.
Jeff Browne839a582010-04-22 18:58:52 -0700119 bool hasPendingSyncTarget = false;
Jeff Brown51d45a72010-06-17 20:52:56 -0700120 size_t activeConnectionCount = mActiveConnections.size();
121 for (size_t i = 0; i < activeConnectionCount; i++) {
Jeff Browne839a582010-04-22 18:58:52 -0700122 Connection* connection = mActiveConnections.itemAt(i);
123
Jeff Browne839a582010-04-22 18:58:52 -0700124 if (connection->hasPendingSyncTarget()) {
125 hasPendingSyncTarget = true;
126 }
127
Jeff Brown51d45a72010-06-17 20:52:56 -0700128 nsecs_t connectionTimeoutTime = connection->nextTimeoutTime;
129 if (connectionTimeoutTime <= currentTime) {
130 mTimedOutConnections.add(connection);
131 } else if (connectionTimeoutTime < nextWakeupTime) {
132 nextWakeupTime = connectionTimeoutTime;
133 }
Jeff Browne839a582010-04-22 18:58:52 -0700134 }
135
Jeff Brown51d45a72010-06-17 20:52:56 -0700136 size_t timedOutConnectionCount = mTimedOutConnections.size();
137 for (size_t i = 0; i < timedOutConnectionCount; i++) {
138 Connection* connection = mTimedOutConnections.itemAt(i);
139 timeoutDispatchCycleLocked(currentTime, connection);
140 skipPoll = true;
141 }
142 mTimedOutConnections.clear();
143
Jeff Browne839a582010-04-22 18:58:52 -0700144 // If we don't have a pending sync target, then we can begin delivering a new event.
145 // (Otherwise we wait for dispatch to complete for that target.)
146 if (! hasPendingSyncTarget) {
147 if (mInboundQueue.isEmpty()) {
148 if (mKeyRepeatState.lastKeyEntry) {
149 if (currentTime >= mKeyRepeatState.nextRepeatTime) {
Jeff Brown61ce3982010-09-07 10:44:57 -0700150 processKeyRepeatLockedInterruptible(currentTime, keyRepeatDelay);
Jeff Brown54bc2812010-06-15 01:31:58 -0700151 skipPoll = true;
Jeff Browne839a582010-04-22 18:58:52 -0700152 } else {
153 if (mKeyRepeatState.nextRepeatTime < nextWakeupTime) {
154 nextWakeupTime = mKeyRepeatState.nextRepeatTime;
155 }
156 }
157 }
158 } else {
Jeff Brown54bc2812010-06-15 01:31:58 -0700159 // Inbound queue has at least one entry.
Jeff Brown542412c2010-08-18 15:51:08 -0700160 EventEntry* entry = mInboundQueue.head.next;
161
162 // Consider throttling the entry if it is a move event and there are no
163 // other events behind it in the queue. Due to movement batching, additional
164 // samples may be appended to this event by the time the throttling timeout
165 // expires.
166 // TODO Make this smarter and consider throttling per device independently.
167 if (entry->type == EventEntry::TYPE_MOTION) {
168 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
169 int32_t deviceId = motionEntry->deviceId;
170 uint32_t source = motionEntry->source;
171 if (motionEntry->next == & mInboundQueue.tail
172 && motionEntry->action == AMOTION_EVENT_ACTION_MOVE
173 && deviceId == mThrottleState.lastDeviceId
174 && source == mThrottleState.lastSource) {
175 nsecs_t nextTime = mThrottleState.lastEventTime
176 + mThrottleState.minTimeBetweenEvents;
177 if (currentTime < nextTime) {
178 // Throttle it!
179#if DEBUG_THROTTLING
180 LOGD("Throttling - Delaying motion event for "
181 "device 0x%x, source 0x%08x by up to %0.3fms.",
182 deviceId, source, (nextTime - currentTime) * 0.000001);
183#endif
184 if (nextTime < nextWakeupTime) {
185 nextWakeupTime = nextTime;
186 }
187 if (mThrottleState.originalSampleCount == 0) {
188 mThrottleState.originalSampleCount =
189 motionEntry->countSamples();
190 }
191 goto Throttle;
192 }
193 }
194
195#if DEBUG_THROTTLING
196 if (mThrottleState.originalSampleCount != 0) {
197 uint32_t count = motionEntry->countSamples();
198 LOGD("Throttling - Motion event sample count grew by %d from %d to %d.",
199 count - mThrottleState.originalSampleCount,
200 mThrottleState.originalSampleCount, count);
201 mThrottleState.originalSampleCount = 0;
202 }
203#endif
204
Jeff Brown869347f2010-08-19 11:55:13 -0700205 mThrottleState.lastEventTime = entry->eventTime < currentTime
206 ? entry->eventTime : currentTime;
Jeff Brown542412c2010-08-18 15:51:08 -0700207 mThrottleState.lastDeviceId = deviceId;
208 mThrottleState.lastSource = source;
209 }
210
211 // Start processing the entry but leave it on the queue until later so that the
Jeff Brown54bc2812010-06-15 01:31:58 -0700212 // input reader can keep appending samples onto a motion event between the
213 // time we started processing it and the time we finally enqueue dispatch
214 // entries for it.
Jeff Browne839a582010-04-22 18:58:52 -0700215 switch (entry->type) {
216 case EventEntry::TYPE_CONFIGURATION_CHANGED: {
217 ConfigurationChangedEntry* typedEntry =
218 static_cast<ConfigurationChangedEntry*>(entry);
Jeff Brown54bc2812010-06-15 01:31:58 -0700219 processConfigurationChangedLockedInterruptible(currentTime, typedEntry);
Jeff Browne839a582010-04-22 18:58:52 -0700220 break;
221 }
222
223 case EventEntry::TYPE_KEY: {
224 KeyEntry* typedEntry = static_cast<KeyEntry*>(entry);
Jeff Brown54bc2812010-06-15 01:31:58 -0700225 processKeyLockedInterruptible(currentTime, typedEntry, keyRepeatTimeout);
Jeff Browne839a582010-04-22 18:58:52 -0700226 break;
227 }
228
229 case EventEntry::TYPE_MOTION: {
230 MotionEntry* typedEntry = static_cast<MotionEntry*>(entry);
Jeff Brown54bc2812010-06-15 01:31:58 -0700231 processMotionLockedInterruptible(currentTime, typedEntry);
Jeff Browne839a582010-04-22 18:58:52 -0700232 break;
233 }
234
235 default:
236 assert(false);
237 break;
238 }
Jeff Brown54bc2812010-06-15 01:31:58 -0700239
240 // Dequeue and release the event entry that we just processed.
241 mInboundQueue.dequeue(entry);
242 mAllocator.releaseEventEntry(entry);
243 skipPoll = true;
Jeff Brown542412c2010-08-18 15:51:08 -0700244
245 Throttle: ;
Jeff Browne839a582010-04-22 18:58:52 -0700246 }
247 }
Jeff Brown54bc2812010-06-15 01:31:58 -0700248
249 // Run any deferred commands.
250 skipPoll |= runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700251 } // release lock
252
Jeff Brown54bc2812010-06-15 01:31:58 -0700253 // If we dispatched anything, don't poll just now. Wait for the next iteration.
254 // Contents may have shifted during flight.
255 if (skipPoll) {
256 return;
257 }
258
Jeff Brown542412c2010-08-18 15:51:08 -0700259 // Wait for callback or timeout or wake. (make sure we round up, not down)
260 nsecs_t timeout = (nextWakeupTime - currentTime + 999999LL) / 1000000LL;
Jeff Browne839a582010-04-22 18:58:52 -0700261 int32_t timeoutMillis = timeout > INT_MAX ? -1 : timeout > 0 ? int32_t(timeout) : 0;
262 mPollLoop->pollOnce(timeoutMillis);
263}
264
Jeff Brown54bc2812010-06-15 01:31:58 -0700265bool InputDispatcher::runCommandsLockedInterruptible() {
266 if (mCommandQueue.isEmpty()) {
267 return false;
268 }
Jeff Browne839a582010-04-22 18:58:52 -0700269
Jeff Brown54bc2812010-06-15 01:31:58 -0700270 do {
271 CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
272
273 Command command = commandEntry->command;
274 (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
275
Jeff Brown51d45a72010-06-17 20:52:56 -0700276 commandEntry->connection.clear();
Jeff Brown54bc2812010-06-15 01:31:58 -0700277 mAllocator.releaseCommandEntry(commandEntry);
278 } while (! mCommandQueue.isEmpty());
279 return true;
Jeff Browne839a582010-04-22 18:58:52 -0700280}
281
Jeff Brown54bc2812010-06-15 01:31:58 -0700282InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
283 CommandEntry* commandEntry = mAllocator.obtainCommandEntry(command);
284 mCommandQueue.enqueueAtTail(commandEntry);
285 return commandEntry;
286}
287
288void InputDispatcher::processConfigurationChangedLockedInterruptible(
289 nsecs_t currentTime, ConfigurationChangedEntry* entry) {
290#if DEBUG_OUTBOUND_EVENT_DETAILS
291 LOGD("processConfigurationChanged - eventTime=%lld", entry->eventTime);
292#endif
293
Jeff Brown4036f7f2010-06-29 16:52:21 -0700294 // Reset key repeating in case a keyboard device was added or removed or something.
295 resetKeyRepeatLocked();
296
Jeff Brown54bc2812010-06-15 01:31:58 -0700297 mLock.unlock();
298
299 mPolicy->notifyConfigurationChanged(entry->eventTime);
300
301 mLock.lock();
302}
303
304void InputDispatcher::processKeyLockedInterruptible(
305 nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout) {
Jeff Browne839a582010-04-22 18:58:52 -0700306#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -0700307 LOGD("processKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -0700308 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
Jeff Brown5c1ed842010-07-14 18:48:53 -0700309 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, entry->action,
Jeff Browne839a582010-04-22 18:58:52 -0700310 entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
311 entry->downTime);
312#endif
313
Jeff Brown5c1ed842010-07-14 18:48:53 -0700314 if (entry->action == AKEY_EVENT_ACTION_DOWN && ! entry->isInjected()) {
Jeff Browne839a582010-04-22 18:58:52 -0700315 if (mKeyRepeatState.lastKeyEntry
316 && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
317 // We have seen two identical key downs in a row which indicates that the device
318 // driver is automatically generating key repeats itself. We take note of the
319 // repeat here, but we disable our own next key repeat timer since it is clear that
320 // we will not need to synthesize key repeats ourselves.
321 entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
322 resetKeyRepeatLocked();
323 mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
324 } else {
325 // Not a repeat. Save key down state in case we do see a repeat later.
326 resetKeyRepeatLocked();
Jeff Brown54bc2812010-06-15 01:31:58 -0700327 mKeyRepeatState.nextRepeatTime = entry->eventTime + keyRepeatTimeout;
Jeff Browne839a582010-04-22 18:58:52 -0700328 }
329 mKeyRepeatState.lastKeyEntry = entry;
330 entry->refCount += 1;
331 } else {
332 resetKeyRepeatLocked();
333 }
334
Jeff Brown54bc2812010-06-15 01:31:58 -0700335 identifyInputTargetsAndDispatchKeyLockedInterruptible(currentTime, entry);
Jeff Browne839a582010-04-22 18:58:52 -0700336}
337
Jeff Brown54bc2812010-06-15 01:31:58 -0700338void InputDispatcher::processKeyRepeatLockedInterruptible(
Jeff Brown61ce3982010-09-07 10:44:57 -0700339 nsecs_t currentTime, nsecs_t keyRepeatDelay) {
Jeff Brown50de30a2010-06-22 01:27:15 -0700340 KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
341
342 // Search the inbound queue for a key up corresponding to this device.
343 // It doesn't make sense to generate a key repeat event if the key is already up.
344 for (EventEntry* queuedEntry = mInboundQueue.head.next;
345 queuedEntry != & mInboundQueue.tail; queuedEntry = entry->next) {
346 if (queuedEntry->type == EventEntry::TYPE_KEY) {
347 KeyEntry* queuedKeyEntry = static_cast<KeyEntry*>(queuedEntry);
348 if (queuedKeyEntry->deviceId == entry->deviceId
Jeff Brown5c1ed842010-07-14 18:48:53 -0700349 && entry->action == AKEY_EVENT_ACTION_UP) {
Jeff Brown50de30a2010-06-22 01:27:15 -0700350 resetKeyRepeatLocked();
351 return;
352 }
353 }
354 }
Jeff Browne839a582010-04-22 18:58:52 -0700355
Jeff Brown61ce3982010-09-07 10:44:57 -0700356 // Synthesize a key repeat.
Jeff Brown50de30a2010-06-22 01:27:15 -0700357 // Reuse the repeated key entry if it is otherwise unreferenced.
Jeff Brown51d45a72010-06-17 20:52:56 -0700358 uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
Jeff Browne839a582010-04-22 18:58:52 -0700359 if (entry->refCount == 1) {
Jeff Brown51d45a72010-06-17 20:52:56 -0700360 entry->eventTime = currentTime;
Jeff Brown51d45a72010-06-17 20:52:56 -0700361 entry->policyFlags = policyFlags;
Jeff Browne839a582010-04-22 18:58:52 -0700362 entry->repeatCount += 1;
363 } else {
Jeff Brown51d45a72010-06-17 20:52:56 -0700364 KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700365 entry->deviceId, entry->source, policyFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -0700366 entry->action, entry->flags, entry->keyCode, entry->scanCode,
Jeff Brownf16c26d2010-07-02 15:37:36 -0700367 entry->metaState, entry->repeatCount + 1, entry->downTime);
Jeff Browne839a582010-04-22 18:58:52 -0700368
369 mKeyRepeatState.lastKeyEntry = newEntry;
370 mAllocator.releaseKeyEntry(entry);
371
372 entry = newEntry;
373 }
Jeff Browne839a582010-04-22 18:58:52 -0700374
Jeff Brownf16c26d2010-07-02 15:37:36 -0700375 if (entry->repeatCount == 1) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700376 entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
Jeff Brownf16c26d2010-07-02 15:37:36 -0700377 }
378
Jeff Brown61ce3982010-09-07 10:44:57 -0700379 mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatDelay;
Jeff Browne839a582010-04-22 18:58:52 -0700380
381#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -0700382 LOGD("processKeyRepeat - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -0700383 "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
384 "repeatCount=%d, downTime=%lld",
Jeff Brown5c1ed842010-07-14 18:48:53 -0700385 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
Jeff Browne839a582010-04-22 18:58:52 -0700386 entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
387 entry->repeatCount, entry->downTime);
388#endif
389
Jeff Brown54bc2812010-06-15 01:31:58 -0700390 identifyInputTargetsAndDispatchKeyLockedInterruptible(currentTime, entry);
Jeff Browne839a582010-04-22 18:58:52 -0700391}
392
Jeff Brown54bc2812010-06-15 01:31:58 -0700393void InputDispatcher::processMotionLockedInterruptible(
394 nsecs_t currentTime, MotionEntry* entry) {
Jeff Browne839a582010-04-22 18:58:52 -0700395#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brownaf30ff62010-09-01 17:01:00 -0700396 LOGD("processMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
397 "action=0x%x, flags=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -0700398 "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
Jeff Brownaf30ff62010-09-01 17:01:00 -0700399 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
400 entry->action, entry->flags,
Jeff Browne839a582010-04-22 18:58:52 -0700401 entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
402 entry->downTime);
403
404 // Print the most recent sample that we have available, this may change due to batching.
405 size_t sampleCount = 1;
406 MotionSample* sample = & entry->firstSample;
407 for (; sample->next != NULL; sample = sample->next) {
408 sampleCount += 1;
409 }
410 for (uint32_t i = 0; i < entry->pointerCount; i++) {
Jeff Brown38a7fab2010-08-30 03:02:23 -0700411 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
Jeff Brownaf30ff62010-09-01 17:01:00 -0700412 "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
Jeff Brown38a7fab2010-08-30 03:02:23 -0700413 "orientation=%f",
Jeff Browne839a582010-04-22 18:58:52 -0700414 i, entry->pointerIds[i],
Jeff Brown38a7fab2010-08-30 03:02:23 -0700415 sample->pointerCoords[i].x, sample->pointerCoords[i].y,
416 sample->pointerCoords[i].pressure, sample->pointerCoords[i].size,
417 sample->pointerCoords[i].touchMajor, sample->pointerCoords[i].touchMinor,
418 sample->pointerCoords[i].toolMajor, sample->pointerCoords[i].toolMinor,
419 sample->pointerCoords[i].orientation);
Jeff Browne839a582010-04-22 18:58:52 -0700420 }
421
422 // Keep in mind that due to batching, it is possible for the number of samples actually
423 // dispatched to change before the application finally consumed them.
Jeff Brown5c1ed842010-07-14 18:48:53 -0700424 if (entry->action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Browne839a582010-04-22 18:58:52 -0700425 LOGD(" ... Total movement samples currently batched %d ...", sampleCount);
426 }
427#endif
428
Jeff Brown54bc2812010-06-15 01:31:58 -0700429 identifyInputTargetsAndDispatchMotionLockedInterruptible(currentTime, entry);
Jeff Browne839a582010-04-22 18:58:52 -0700430}
431
Jeff Brown54bc2812010-06-15 01:31:58 -0700432void InputDispatcher::identifyInputTargetsAndDispatchKeyLockedInterruptible(
Jeff Browne839a582010-04-22 18:58:52 -0700433 nsecs_t currentTime, KeyEntry* entry) {
434#if DEBUG_DISPATCH_CYCLE
435 LOGD("identifyInputTargetsAndDispatchKey");
436#endif
437
Jeff Brown54bc2812010-06-15 01:31:58 -0700438 entry->dispatchInProgress = true;
439 mCurrentInputTargetsValid = false;
440 mLock.unlock();
441
Jeff Brown5c1ed842010-07-14 18:48:53 -0700442 mReusableKeyEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
Jeff Browne839a582010-04-22 18:58:52 -0700443 entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
444 entry->downTime, entry->eventTime);
445
446 mCurrentInputTargets.clear();
Jeff Brown50de30a2010-06-22 01:27:15 -0700447 int32_t injectionResult = mPolicy->waitForKeyEventTargets(& mReusableKeyEvent,
Jeff Brown51d45a72010-06-17 20:52:56 -0700448 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Browne839a582010-04-22 18:58:52 -0700449 mCurrentInputTargets);
450
Jeff Brown54bc2812010-06-15 01:31:58 -0700451 mLock.lock();
452 mCurrentInputTargetsValid = true;
453
Jeff Brown51d45a72010-06-17 20:52:56 -0700454 setInjectionResultLocked(entry, injectionResult);
455
Jeff Brown50de30a2010-06-22 01:27:15 -0700456 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
457 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
458 }
Jeff Browne839a582010-04-22 18:58:52 -0700459}
460
Jeff Brown54bc2812010-06-15 01:31:58 -0700461void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(
Jeff Browne839a582010-04-22 18:58:52 -0700462 nsecs_t currentTime, MotionEntry* entry) {
463#if DEBUG_DISPATCH_CYCLE
464 LOGD("identifyInputTargetsAndDispatchMotion");
465#endif
466
Jeff Brown54bc2812010-06-15 01:31:58 -0700467 entry->dispatchInProgress = true;
468 mCurrentInputTargetsValid = false;
469 mLock.unlock();
470
Jeff Brownaf30ff62010-09-01 17:01:00 -0700471 mReusableMotionEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
Jeff Browne839a582010-04-22 18:58:52 -0700472 entry->edgeFlags, entry->metaState,
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700473 0, 0, entry->xPrecision, entry->yPrecision,
Jeff Browne839a582010-04-22 18:58:52 -0700474 entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds,
475 entry->firstSample.pointerCoords);
476
477 mCurrentInputTargets.clear();
Jeff Brown50de30a2010-06-22 01:27:15 -0700478 int32_t injectionResult = mPolicy->waitForMotionEventTargets(& mReusableMotionEvent,
Jeff Brown51d45a72010-06-17 20:52:56 -0700479 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Browne839a582010-04-22 18:58:52 -0700480 mCurrentInputTargets);
481
Jeff Brown54bc2812010-06-15 01:31:58 -0700482 mLock.lock();
483 mCurrentInputTargetsValid = true;
484
Jeff Brown51d45a72010-06-17 20:52:56 -0700485 setInjectionResultLocked(entry, injectionResult);
486
Jeff Brown50de30a2010-06-22 01:27:15 -0700487 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
488 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
489 }
Jeff Browne839a582010-04-22 18:58:52 -0700490}
491
492void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
493 EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
494#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700495 LOGD("dispatchEventToCurrentInputTargets - "
Jeff Browne839a582010-04-22 18:58:52 -0700496 "resumeWithAppendedMotionSample=%s",
497 resumeWithAppendedMotionSample ? "true" : "false");
498#endif
499
Jeff Brown54bc2812010-06-15 01:31:58 -0700500 assert(eventEntry->dispatchInProgress); // should already have been set to true
501
Jeff Browne839a582010-04-22 18:58:52 -0700502 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
503 const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
504
Jeff Brown0cacb872010-08-17 15:59:26 -0700505 ssize_t connectionIndex = getConnectionIndex(inputTarget.inputChannel);
Jeff Browne839a582010-04-22 18:58:52 -0700506 if (connectionIndex >= 0) {
507 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown51d45a72010-06-17 20:52:56 -0700508 prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
Jeff Browne839a582010-04-22 18:58:52 -0700509 resumeWithAppendedMotionSample);
510 } else {
511 LOGW("Framework requested delivery of an input event to channel '%s' but it "
512 "is not registered with the input dispatcher.",
513 inputTarget.inputChannel->getName().string());
514 }
515 }
516}
517
Jeff Brown51d45a72010-06-17 20:52:56 -0700518void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
519 const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
Jeff Browne839a582010-04-22 18:58:52 -0700520 bool resumeWithAppendedMotionSample) {
521#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700522 LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, timeout=%lldns, "
Jeff Browne839a582010-04-22 18:58:52 -0700523 "xOffset=%f, yOffset=%f, resumeWithAppendedMotionSample=%s",
524 connection->getInputChannelName(), inputTarget->flags, inputTarget->timeout,
525 inputTarget->xOffset, inputTarget->yOffset,
526 resumeWithAppendedMotionSample ? "true" : "false");
527#endif
528
529 // Skip this event if the connection status is not normal.
530 // We don't want to queue outbound events at all if the connection is broken or
531 // not responding.
532 if (connection->status != Connection::STATUS_NORMAL) {
533 LOGV("channel '%s' ~ Dropping event because the channel status is %s",
Jeff Brown54bc2812010-06-15 01:31:58 -0700534 connection->getStatusLabel());
Jeff Browne839a582010-04-22 18:58:52 -0700535 return;
536 }
537
538 // Resume the dispatch cycle with a freshly appended motion sample.
539 // First we check that the last dispatch entry in the outbound queue is for the same
540 // motion event to which we appended the motion sample. If we find such a dispatch
541 // entry, and if it is currently in progress then we try to stream the new sample.
542 bool wasEmpty = connection->outboundQueue.isEmpty();
543
544 if (! wasEmpty && resumeWithAppendedMotionSample) {
545 DispatchEntry* motionEventDispatchEntry =
546 connection->findQueuedDispatchEntryForEvent(eventEntry);
547 if (motionEventDispatchEntry) {
548 // If the dispatch entry is not in progress, then we must be busy dispatching an
549 // earlier event. Not a problem, the motion event is on the outbound queue and will
550 // be dispatched later.
551 if (! motionEventDispatchEntry->inProgress) {
552#if DEBUG_BATCHING
553 LOGD("channel '%s' ~ Not streaming because the motion event has "
554 "not yet been dispatched. "
555 "(Waiting for earlier events to be consumed.)",
556 connection->getInputChannelName());
557#endif
558 return;
559 }
560
561 // If the dispatch entry is in progress but it already has a tail of pending
562 // motion samples, then it must mean that the shared memory buffer filled up.
563 // Not a problem, when this dispatch cycle is finished, we will eventually start
564 // a new dispatch cycle to process the tail and that tail includes the newly
565 // appended motion sample.
566 if (motionEventDispatchEntry->tailMotionSample) {
567#if DEBUG_BATCHING
568 LOGD("channel '%s' ~ Not streaming because no new samples can "
569 "be appended to the motion event in this dispatch cycle. "
570 "(Waiting for next dispatch cycle to start.)",
571 connection->getInputChannelName());
572#endif
573 return;
574 }
575
576 // The dispatch entry is in progress and is still potentially open for streaming.
577 // Try to stream the new motion sample. This might fail if the consumer has already
578 // consumed the motion event (or if the channel is broken).
579 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
580 status_t status = connection->inputPublisher.appendMotionSample(
581 appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
582 if (status == OK) {
583#if DEBUG_BATCHING
584 LOGD("channel '%s' ~ Successfully streamed new motion sample.",
585 connection->getInputChannelName());
586#endif
587 return;
588 }
589
590#if DEBUG_BATCHING
591 if (status == NO_MEMORY) {
592 LOGD("channel '%s' ~ Could not append motion sample to currently "
593 "dispatched move event because the shared memory buffer is full. "
594 "(Waiting for next dispatch cycle to start.)",
595 connection->getInputChannelName());
596 } else if (status == status_t(FAILED_TRANSACTION)) {
597 LOGD("channel '%s' ~ Could not append motion sample to currently "
Jeff Brown50de30a2010-06-22 01:27:15 -0700598 "dispatched move event because the event has already been consumed. "
Jeff Browne839a582010-04-22 18:58:52 -0700599 "(Waiting for next dispatch cycle to start.)",
600 connection->getInputChannelName());
601 } else {
602 LOGD("channel '%s' ~ Could not append motion sample to currently "
603 "dispatched move event due to an error, status=%d. "
604 "(Waiting for next dispatch cycle to start.)",
605 connection->getInputChannelName(), status);
606 }
607#endif
608 // Failed to stream. Start a new tail of pending motion samples to dispatch
609 // in the next cycle.
610 motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
611 return;
612 }
613 }
614
615 // This is a new event.
616 // Enqueue a new dispatch entry onto the outbound queue for this connection.
617 DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry); // increments ref
618 dispatchEntry->targetFlags = inputTarget->flags;
619 dispatchEntry->xOffset = inputTarget->xOffset;
620 dispatchEntry->yOffset = inputTarget->yOffset;
621 dispatchEntry->timeout = inputTarget->timeout;
622 dispatchEntry->inProgress = false;
623 dispatchEntry->headMotionSample = NULL;
624 dispatchEntry->tailMotionSample = NULL;
625
Jeff Brownf67c53e2010-07-28 15:48:59 -0700626 if (dispatchEntry->isSyncTarget()) {
627 eventEntry->pendingSyncDispatches += 1;
628 }
629
Jeff Browne839a582010-04-22 18:58:52 -0700630 // Handle the case where we could not stream a new motion sample because the consumer has
631 // already consumed the motion event (otherwise the corresponding dispatch entry would
632 // still be in the outbound queue for this connection). We set the head motion sample
633 // to the list starting with the newly appended motion sample.
634 if (resumeWithAppendedMotionSample) {
635#if DEBUG_BATCHING
636 LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
637 "that cannot be streamed because the motion event has already been consumed.",
638 connection->getInputChannelName());
639#endif
640 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
641 dispatchEntry->headMotionSample = appendedMotionSample;
642 }
643
644 // Enqueue the dispatch entry.
645 connection->outboundQueue.enqueueAtTail(dispatchEntry);
646
647 // If the outbound queue was previously empty, start the dispatch cycle going.
648 if (wasEmpty) {
Jeff Brown51d45a72010-06-17 20:52:56 -0700649 activateConnectionLocked(connection.get());
Jeff Browne839a582010-04-22 18:58:52 -0700650 startDispatchCycleLocked(currentTime, connection);
651 }
652}
653
Jeff Brown51d45a72010-06-17 20:52:56 -0700654void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
655 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -0700656#if DEBUG_DISPATCH_CYCLE
657 LOGD("channel '%s' ~ startDispatchCycle",
658 connection->getInputChannelName());
659#endif
660
661 assert(connection->status == Connection::STATUS_NORMAL);
662 assert(! connection->outboundQueue.isEmpty());
663
664 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
665 assert(! dispatchEntry->inProgress);
666
667 // TODO throttle successive ACTION_MOVE motion events for the same device
668 // possible implementation could set a brief poll timeout here and resume starting the
669 // dispatch cycle when elapsed
670
671 // Publish the event.
672 status_t status;
673 switch (dispatchEntry->eventEntry->type) {
674 case EventEntry::TYPE_KEY: {
675 KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
676
677 // Apply target flags.
678 int32_t action = keyEntry->action;
679 int32_t flags = keyEntry->flags;
680 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700681 flags |= AKEY_EVENT_FLAG_CANCELED;
Jeff Browne839a582010-04-22 18:58:52 -0700682 }
683
684 // Publish the key event.
Jeff Brown5c1ed842010-07-14 18:48:53 -0700685 status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
Jeff Browne839a582010-04-22 18:58:52 -0700686 action, flags, keyEntry->keyCode, keyEntry->scanCode,
687 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
688 keyEntry->eventTime);
689
690 if (status) {
691 LOGE("channel '%s' ~ Could not publish key event, "
692 "status=%d", connection->getInputChannelName(), status);
693 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
694 return;
695 }
696 break;
697 }
698
699 case EventEntry::TYPE_MOTION: {
700 MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
701
702 // Apply target flags.
703 int32_t action = motionEntry->action;
Jeff Brownaf30ff62010-09-01 17:01:00 -0700704 int32_t flags = motionEntry->flags;
Jeff Browne839a582010-04-22 18:58:52 -0700705 if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700706 action = AMOTION_EVENT_ACTION_OUTSIDE;
Jeff Browne839a582010-04-22 18:58:52 -0700707 }
708 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700709 action = AMOTION_EVENT_ACTION_CANCEL;
Jeff Browne839a582010-04-22 18:58:52 -0700710 }
Jeff Brownaf30ff62010-09-01 17:01:00 -0700711 if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
712 flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
713 }
Jeff Browne839a582010-04-22 18:58:52 -0700714
715 // If headMotionSample is non-NULL, then it points to the first new sample that we
716 // were unable to dispatch during the previous cycle so we resume dispatching from
717 // that point in the list of motion samples.
718 // Otherwise, we just start from the first sample of the motion event.
719 MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
720 if (! firstMotionSample) {
721 firstMotionSample = & motionEntry->firstSample;
722 }
723
Jeff Brownf26db0d2010-07-16 17:21:06 -0700724 // Set the X and Y offset depending on the input source.
725 float xOffset, yOffset;
726 if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
727 xOffset = dispatchEntry->xOffset;
728 yOffset = dispatchEntry->yOffset;
729 } else {
730 xOffset = 0.0f;
731 yOffset = 0.0f;
732 }
733
Jeff Browne839a582010-04-22 18:58:52 -0700734 // Publish the motion event and the first motion sample.
735 status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
Jeff Brownaf30ff62010-09-01 17:01:00 -0700736 motionEntry->source, action, flags, motionEntry->edgeFlags, motionEntry->metaState,
Jeff Brownf26db0d2010-07-16 17:21:06 -0700737 xOffset, yOffset,
Jeff Browne839a582010-04-22 18:58:52 -0700738 motionEntry->xPrecision, motionEntry->yPrecision,
739 motionEntry->downTime, firstMotionSample->eventTime,
740 motionEntry->pointerCount, motionEntry->pointerIds,
741 firstMotionSample->pointerCoords);
742
743 if (status) {
744 LOGE("channel '%s' ~ Could not publish motion event, "
745 "status=%d", connection->getInputChannelName(), status);
746 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
747 return;
748 }
749
750 // Append additional motion samples.
751 MotionSample* nextMotionSample = firstMotionSample->next;
752 for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
753 status = connection->inputPublisher.appendMotionSample(
754 nextMotionSample->eventTime, nextMotionSample->pointerCoords);
755 if (status == NO_MEMORY) {
756#if DEBUG_DISPATCH_CYCLE
757 LOGD("channel '%s' ~ Shared memory buffer full. Some motion samples will "
758 "be sent in the next dispatch cycle.",
759 connection->getInputChannelName());
760#endif
761 break;
762 }
763 if (status != OK) {
764 LOGE("channel '%s' ~ Could not append motion sample "
765 "for a reason other than out of memory, status=%d",
766 connection->getInputChannelName(), status);
767 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
768 return;
769 }
770 }
771
772 // Remember the next motion sample that we could not dispatch, in case we ran out
773 // of space in the shared memory buffer.
774 dispatchEntry->tailMotionSample = nextMotionSample;
775 break;
776 }
777
778 default: {
779 assert(false);
780 }
781 }
782
783 // Send the dispatch signal.
784 status = connection->inputPublisher.sendDispatchSignal();
785 if (status) {
786 LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
787 connection->getInputChannelName(), status);
788 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
789 return;
790 }
791
792 // Record information about the newly started dispatch cycle.
793 dispatchEntry->inProgress = true;
794
795 connection->lastEventTime = dispatchEntry->eventEntry->eventTime;
796 connection->lastDispatchTime = currentTime;
797
798 nsecs_t timeout = dispatchEntry->timeout;
Jeff Brown51d45a72010-06-17 20:52:56 -0700799 connection->setNextTimeoutTime(currentTime, timeout);
Jeff Browne839a582010-04-22 18:58:52 -0700800
801 // Notify other system components.
802 onDispatchCycleStartedLocked(currentTime, connection);
803}
804
Jeff Brown51d45a72010-06-17 20:52:56 -0700805void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
806 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -0700807#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700808 LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
Jeff Browne839a582010-04-22 18:58:52 -0700809 "%01.1fms since dispatch",
810 connection->getInputChannelName(),
811 connection->getEventLatencyMillis(currentTime),
812 connection->getDispatchLatencyMillis(currentTime));
813#endif
814
Jeff Brown54bc2812010-06-15 01:31:58 -0700815 if (connection->status == Connection::STATUS_BROKEN
816 || connection->status == Connection::STATUS_ZOMBIE) {
Jeff Browne839a582010-04-22 18:58:52 -0700817 return;
818 }
819
820 // Clear the pending timeout.
821 connection->nextTimeoutTime = LONG_LONG_MAX;
822
823 if (connection->status == Connection::STATUS_NOT_RESPONDING) {
824 // Recovering from an ANR.
825 connection->status = Connection::STATUS_NORMAL;
826
827 // Notify other system components.
828 onDispatchCycleFinishedLocked(currentTime, connection, true /*recoveredFromANR*/);
829 } else {
830 // Normal finish. Not much to do here.
831
832 // Notify other system components.
833 onDispatchCycleFinishedLocked(currentTime, connection, false /*recoveredFromANR*/);
834 }
835
836 // Reset the publisher since the event has been consumed.
837 // We do this now so that the publisher can release some of its internal resources
838 // while waiting for the next dispatch cycle to begin.
839 status_t status = connection->inputPublisher.reset();
840 if (status) {
841 LOGE("channel '%s' ~ Could not reset publisher, status=%d",
842 connection->getInputChannelName(), status);
843 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
844 return;
845 }
846
847 // Start the next dispatch cycle for this connection.
848 while (! connection->outboundQueue.isEmpty()) {
849 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
850 if (dispatchEntry->inProgress) {
851 // Finish or resume current event in progress.
852 if (dispatchEntry->tailMotionSample) {
853 // We have a tail of undispatched motion samples.
854 // Reuse the same DispatchEntry and start a new cycle.
855 dispatchEntry->inProgress = false;
856 dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
857 dispatchEntry->tailMotionSample = NULL;
858 startDispatchCycleLocked(currentTime, connection);
859 return;
860 }
861 // Finished.
862 connection->outboundQueue.dequeueAtHead();
Jeff Brownf67c53e2010-07-28 15:48:59 -0700863 if (dispatchEntry->isSyncTarget()) {
864 decrementPendingSyncDispatchesLocked(dispatchEntry->eventEntry);
865 }
Jeff Browne839a582010-04-22 18:58:52 -0700866 mAllocator.releaseDispatchEntry(dispatchEntry);
867 } else {
868 // If the head is not in progress, then we must have already dequeued the in
869 // progress event, which means we actually aborted it (due to ANR).
870 // So just start the next event for this connection.
871 startDispatchCycleLocked(currentTime, connection);
872 return;
873 }
874 }
875
876 // Outbound queue is empty, deactivate the connection.
Jeff Brown51d45a72010-06-17 20:52:56 -0700877 deactivateConnectionLocked(connection.get());
Jeff Browne839a582010-04-22 18:58:52 -0700878}
879
Jeff Brown51d45a72010-06-17 20:52:56 -0700880void InputDispatcher::timeoutDispatchCycleLocked(nsecs_t currentTime,
881 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -0700882#if DEBUG_DISPATCH_CYCLE
883 LOGD("channel '%s' ~ timeoutDispatchCycle",
884 connection->getInputChannelName());
885#endif
886
887 if (connection->status != Connection::STATUS_NORMAL) {
Jeff Brown51d45a72010-06-17 20:52:56 -0700888 return;
Jeff Browne839a582010-04-22 18:58:52 -0700889 }
890
891 // Enter the not responding state.
892 connection->status = Connection::STATUS_NOT_RESPONDING;
893 connection->lastANRTime = currentTime;
Jeff Browne839a582010-04-22 18:58:52 -0700894
895 // Notify other system components.
Jeff Brown51d45a72010-06-17 20:52:56 -0700896 // This enqueues a command which will eventually either call
897 // resumeAfterTimeoutDispatchCycleLocked or abortDispatchCycleLocked.
Jeff Browne839a582010-04-22 18:58:52 -0700898 onDispatchCycleANRLocked(currentTime, connection);
Jeff Browne839a582010-04-22 18:58:52 -0700899}
900
Jeff Brown51d45a72010-06-17 20:52:56 -0700901void InputDispatcher::resumeAfterTimeoutDispatchCycleLocked(nsecs_t currentTime,
902 const sp<Connection>& connection, nsecs_t newTimeout) {
903#if DEBUG_DISPATCH_CYCLE
904 LOGD("channel '%s' ~ resumeAfterTimeoutDispatchCycleLocked",
905 connection->getInputChannelName());
906#endif
907
908 if (connection->status != Connection::STATUS_NOT_RESPONDING) {
909 return;
910 }
911
912 // Resume normal dispatch.
913 connection->status = Connection::STATUS_NORMAL;
914 connection->setNextTimeoutTime(currentTime, newTimeout);
915}
916
917void InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime,
918 const sp<Connection>& connection, bool broken) {
Jeff Browne839a582010-04-22 18:58:52 -0700919#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700920 LOGD("channel '%s' ~ abortDispatchCycle - broken=%s",
Jeff Browne839a582010-04-22 18:58:52 -0700921 connection->getInputChannelName(), broken ? "true" : "false");
922#endif
923
Jeff Browne839a582010-04-22 18:58:52 -0700924 // Clear the pending timeout.
925 connection->nextTimeoutTime = LONG_LONG_MAX;
926
927 // Clear the outbound queue.
Jeff Brown51d45a72010-06-17 20:52:56 -0700928 if (! connection->outboundQueue.isEmpty()) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700929 do {
930 DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
Jeff Brownf67c53e2010-07-28 15:48:59 -0700931 if (dispatchEntry->isSyncTarget()) {
932 decrementPendingSyncDispatchesLocked(dispatchEntry->eventEntry);
933 }
Jeff Brown54bc2812010-06-15 01:31:58 -0700934 mAllocator.releaseDispatchEntry(dispatchEntry);
935 } while (! connection->outboundQueue.isEmpty());
Jeff Browne839a582010-04-22 18:58:52 -0700936
Jeff Brown51d45a72010-06-17 20:52:56 -0700937 deactivateConnectionLocked(connection.get());
Jeff Brown54bc2812010-06-15 01:31:58 -0700938 }
Jeff Browne839a582010-04-22 18:58:52 -0700939
940 // Handle the case where the connection appears to be unrecoverably broken.
Jeff Brown54bc2812010-06-15 01:31:58 -0700941 // Ignore already broken or zombie connections.
Jeff Browne839a582010-04-22 18:58:52 -0700942 if (broken) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700943 if (connection->status == Connection::STATUS_NORMAL
944 || connection->status == Connection::STATUS_NOT_RESPONDING) {
945 connection->status = Connection::STATUS_BROKEN;
Jeff Browne839a582010-04-22 18:58:52 -0700946
Jeff Brown54bc2812010-06-15 01:31:58 -0700947 // Notify other system components.
948 onDispatchCycleBrokenLocked(currentTime, connection);
949 }
Jeff Browne839a582010-04-22 18:58:52 -0700950 }
Jeff Browne839a582010-04-22 18:58:52 -0700951}
952
953bool InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
954 InputDispatcher* d = static_cast<InputDispatcher*>(data);
955
956 { // acquire lock
957 AutoMutex _l(d->mLock);
958
959 ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
960 if (connectionIndex < 0) {
961 LOGE("Received spurious receive callback for unknown input channel. "
962 "fd=%d, events=0x%x", receiveFd, events);
963 return false; // remove the callback
964 }
965
Jeff Brown51d45a72010-06-17 20:52:56 -0700966 nsecs_t currentTime = now();
Jeff Browne839a582010-04-22 18:58:52 -0700967
968 sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
969 if (events & (POLLERR | POLLHUP | POLLNVAL)) {
970 LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
971 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brown51d45a72010-06-17 20:52:56 -0700972 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -0700973 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700974 return false; // remove the callback
975 }
976
977 if (! (events & POLLIN)) {
978 LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
979 "events=0x%x", connection->getInputChannelName(), events);
980 return true;
981 }
982
983 status_t status = connection->inputPublisher.receiveFinishedSignal();
984 if (status) {
985 LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
986 connection->getInputChannelName(), status);
Jeff Brown51d45a72010-06-17 20:52:56 -0700987 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -0700988 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700989 return false; // remove the callback
990 }
991
Jeff Brown51d45a72010-06-17 20:52:56 -0700992 d->finishDispatchCycleLocked(currentTime, connection);
Jeff Brown54bc2812010-06-15 01:31:58 -0700993 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -0700994 return true;
995 } // release lock
996}
997
Jeff Brown54bc2812010-06-15 01:31:58 -0700998void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
Jeff Browne839a582010-04-22 18:58:52 -0700999#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown54bc2812010-06-15 01:31:58 -07001000 LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
Jeff Browne839a582010-04-22 18:58:52 -07001001#endif
1002
1003 bool wasEmpty;
1004 { // acquire lock
1005 AutoMutex _l(mLock);
1006
Jeff Brown51d45a72010-06-17 20:52:56 -07001007 ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
Jeff Browne839a582010-04-22 18:58:52 -07001008
1009 wasEmpty = mInboundQueue.isEmpty();
1010 mInboundQueue.enqueueAtTail(newEntry);
1011 } // release lock
1012
1013 if (wasEmpty) {
1014 mPollLoop->wake();
1015 }
1016}
1017
Jeff Browne839a582010-04-22 18:58:52 -07001018void InputDispatcher::notifyAppSwitchComing(nsecs_t eventTime) {
1019#if DEBUG_INBOUND_EVENT_DETAILS
1020 LOGD("notifyAppSwitchComing - eventTime=%lld", eventTime);
1021#endif
1022
1023 // Remove movement keys from the queue from most recent to least recent, stopping at the
1024 // first non-movement key.
1025 // TODO: Include a detailed description of why we do this...
1026
1027 { // acquire lock
1028 AutoMutex _l(mLock);
1029
1030 for (EventEntry* entry = mInboundQueue.tail.prev; entry != & mInboundQueue.head; ) {
1031 EventEntry* prev = entry->prev;
1032
1033 if (entry->type == EventEntry::TYPE_KEY) {
1034 KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
1035 if (isMovementKey(keyEntry->keyCode)) {
1036 LOGV("Dropping movement key during app switch: keyCode=%d, action=%d",
1037 keyEntry->keyCode, keyEntry->action);
1038 mInboundQueue.dequeue(keyEntry);
Jeff Brown51d45a72010-06-17 20:52:56 -07001039
1040 setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
1041
Jeff Browne839a582010-04-22 18:58:52 -07001042 mAllocator.releaseKeyEntry(keyEntry);
1043 } else {
1044 // stop at last non-movement key
1045 break;
1046 }
1047 }
1048
1049 entry = prev;
1050 }
1051 } // release lock
1052}
1053
Jeff Brown5c1ed842010-07-14 18:48:53 -07001054void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Browne839a582010-04-22 18:58:52 -07001055 uint32_t policyFlags, int32_t action, int32_t flags,
1056 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
1057#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -07001058 LOGD("notifyKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -07001059 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
Jeff Brown5c1ed842010-07-14 18:48:53 -07001060 eventTime, deviceId, source, policyFlags, action, flags,
Jeff Browne839a582010-04-22 18:58:52 -07001061 keyCode, scanCode, metaState, downTime);
1062#endif
1063
1064 bool wasEmpty;
1065 { // acquire lock
1066 AutoMutex _l(mLock);
1067
Jeff Brown51d45a72010-06-17 20:52:56 -07001068 int32_t repeatCount = 0;
1069 KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001070 deviceId, source, policyFlags, action, flags, keyCode, scanCode,
Jeff Brown51d45a72010-06-17 20:52:56 -07001071 metaState, repeatCount, downTime);
Jeff Browne839a582010-04-22 18:58:52 -07001072
1073 wasEmpty = mInboundQueue.isEmpty();
1074 mInboundQueue.enqueueAtTail(newEntry);
1075 } // release lock
1076
1077 if (wasEmpty) {
1078 mPollLoop->wake();
1079 }
1080}
1081
Jeff Brown5c1ed842010-07-14 18:48:53 -07001082void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001083 uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t edgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07001084 uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
1085 float xPrecision, float yPrecision, nsecs_t downTime) {
1086#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -07001087 LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Brownaf30ff62010-09-01 17:01:00 -07001088 "action=0x%x, flags=0x%x, metaState=0x%x, edgeFlags=0x%x, "
1089 "xPrecision=%f, yPrecision=%f, downTime=%lld",
1090 eventTime, deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07001091 xPrecision, yPrecision, downTime);
1092 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001093 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
Jeff Brownaf30ff62010-09-01 17:01:00 -07001094 "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
Jeff Brown38a7fab2010-08-30 03:02:23 -07001095 "orientation=%f",
Jeff Browne839a582010-04-22 18:58:52 -07001096 i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
Jeff Brown38a7fab2010-08-30 03:02:23 -07001097 pointerCoords[i].pressure, pointerCoords[i].size,
1098 pointerCoords[i].touchMajor, pointerCoords[i].touchMinor,
1099 pointerCoords[i].toolMajor, pointerCoords[i].toolMinor,
1100 pointerCoords[i].orientation);
Jeff Browne839a582010-04-22 18:58:52 -07001101 }
1102#endif
1103
1104 bool wasEmpty;
1105 { // acquire lock
1106 AutoMutex _l(mLock);
1107
1108 // Attempt batching and streaming of move events.
Jeff Brown5c1ed842010-07-14 18:48:53 -07001109 if (action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Browne839a582010-04-22 18:58:52 -07001110 // BATCHING CASE
1111 //
1112 // Try to append a move sample to the tail of the inbound queue for this device.
1113 // Give up if we encounter a non-move motion event for this device since that
1114 // means we cannot append any new samples until a new motion event has started.
1115 for (EventEntry* entry = mInboundQueue.tail.prev;
1116 entry != & mInboundQueue.head; entry = entry->prev) {
1117 if (entry->type != EventEntry::TYPE_MOTION) {
1118 // Keep looking for motion events.
1119 continue;
1120 }
1121
1122 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
1123 if (motionEntry->deviceId != deviceId) {
1124 // Keep looking for this device.
1125 continue;
1126 }
1127
Jeff Brown5c1ed842010-07-14 18:48:53 -07001128 if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown51d45a72010-06-17 20:52:56 -07001129 || motionEntry->pointerCount != pointerCount
1130 || motionEntry->isInjected()) {
Jeff Browne839a582010-04-22 18:58:52 -07001131 // Last motion event in the queue for this device is not compatible for
1132 // appending new samples. Stop here.
1133 goto NoBatchingOrStreaming;
1134 }
1135
1136 // The last motion event is a move and is compatible for appending.
Jeff Brown54bc2812010-06-15 01:31:58 -07001137 // Do the batching magic.
Jeff Brown51d45a72010-06-17 20:52:56 -07001138 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
Jeff Browne839a582010-04-22 18:58:52 -07001139#if DEBUG_BATCHING
1140 LOGD("Appended motion sample onto batch for most recent "
1141 "motion event for this device in the inbound queue.");
1142#endif
Jeff Brown54bc2812010-06-15 01:31:58 -07001143
1144 // Sanity check for special case because dispatch is interruptible.
1145 // The dispatch logic is partially interruptible and releases its lock while
1146 // identifying targets. However, as soon as the targets have been identified,
1147 // the dispatcher proceeds to write a dispatch entry into all relevant outbound
1148 // queues and then promptly removes the motion entry from the queue.
1149 //
1150 // Consequently, we should never observe the case where the inbound queue contains
1151 // an in-progress motion entry unless the current input targets are invalid
1152 // (currently being computed). Check for this!
1153 assert(! (motionEntry->dispatchInProgress && mCurrentInputTargetsValid));
1154
1155 return; // done!
Jeff Browne839a582010-04-22 18:58:52 -07001156 }
1157
1158 // STREAMING CASE
1159 //
1160 // There is no pending motion event (of any kind) for this device in the inbound queue.
1161 // Search the outbound queues for a synchronously dispatched motion event for this
1162 // device. If found, then we append the new sample to that event and then try to
1163 // push it out to all current targets. It is possible that some targets will already
1164 // have consumed the motion event. This case is automatically handled by the
1165 // logic in prepareDispatchCycleLocked by tracking where resumption takes place.
1166 //
1167 // The reason we look for a synchronously dispatched motion event is because we
1168 // want to be sure that no other motion events have been dispatched since the move.
1169 // It's also convenient because it means that the input targets are still valid.
1170 // This code could be improved to support streaming of asynchronously dispatched
1171 // motion events (which might be significantly more efficient) but it may become
1172 // a little more complicated as a result.
1173 //
1174 // Note: This code crucially depends on the invariant that an outbound queue always
1175 // contains at most one synchronous event and it is always last (but it might
1176 // not be first!).
Jeff Brown54bc2812010-06-15 01:31:58 -07001177 if (mCurrentInputTargetsValid) {
1178 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1179 Connection* connection = mActiveConnections.itemAt(i);
1180 if (! connection->outboundQueue.isEmpty()) {
1181 DispatchEntry* dispatchEntry = connection->outboundQueue.tail.prev;
Jeff Brownf67c53e2010-07-28 15:48:59 -07001182 if (dispatchEntry->isSyncTarget()) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001183 if (dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION) {
1184 goto NoBatchingOrStreaming;
1185 }
Jeff Browne839a582010-04-22 18:58:52 -07001186
Jeff Brown54bc2812010-06-15 01:31:58 -07001187 MotionEntry* syncedMotionEntry = static_cast<MotionEntry*>(
1188 dispatchEntry->eventEntry);
Jeff Brown5c1ed842010-07-14 18:48:53 -07001189 if (syncedMotionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown54bc2812010-06-15 01:31:58 -07001190 || syncedMotionEntry->deviceId != deviceId
Jeff Brown51d45a72010-06-17 20:52:56 -07001191 || syncedMotionEntry->pointerCount != pointerCount
1192 || syncedMotionEntry->isInjected()) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001193 goto NoBatchingOrStreaming;
1194 }
Jeff Browne839a582010-04-22 18:58:52 -07001195
Jeff Brown54bc2812010-06-15 01:31:58 -07001196 // Found synced move entry. Append sample and resume dispatch.
1197 mAllocator.appendMotionSample(syncedMotionEntry, eventTime,
Jeff Brown51d45a72010-06-17 20:52:56 -07001198 pointerCoords);
Jeff Brown54bc2812010-06-15 01:31:58 -07001199 #if DEBUG_BATCHING
1200 LOGD("Appended motion sample onto batch for most recent synchronously "
1201 "dispatched motion event for this device in the outbound queues.");
1202 #endif
Jeff Brown51d45a72010-06-17 20:52:56 -07001203 nsecs_t currentTime = now();
Jeff Brown54bc2812010-06-15 01:31:58 -07001204 dispatchEventToCurrentInputTargetsLocked(currentTime, syncedMotionEntry,
1205 true /*resumeWithAppendedMotionSample*/);
1206
1207 runCommandsLockedInterruptible();
1208 return; // done!
1209 }
Jeff Browne839a582010-04-22 18:58:52 -07001210 }
1211 }
1212 }
1213
1214NoBatchingOrStreaming:;
1215 }
1216
1217 // Just enqueue a new motion event.
Jeff Brown51d45a72010-06-17 20:52:56 -07001218 MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001219 deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -07001220 xPrecision, yPrecision, downTime,
1221 pointerCount, pointerIds, pointerCoords);
Jeff Browne839a582010-04-22 18:58:52 -07001222
1223 wasEmpty = mInboundQueue.isEmpty();
1224 mInboundQueue.enqueueAtTail(newEntry);
1225 } // release lock
1226
1227 if (wasEmpty) {
1228 mPollLoop->wake();
1229 }
1230}
1231
Jeff Brown51d45a72010-06-17 20:52:56 -07001232int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
Jeff Brownf67c53e2010-07-28 15:48:59 -07001233 int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001234#if DEBUG_INBOUND_EVENT_DETAILS
1235 LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
Jeff Brownf67c53e2010-07-28 15:48:59 -07001236 "syncMode=%d, timeoutMillis=%d",
1237 event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis);
Jeff Brown51d45a72010-06-17 20:52:56 -07001238#endif
1239
1240 nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
1241
1242 EventEntry* injectedEntry;
1243 bool wasEmpty;
1244 { // acquire lock
1245 AutoMutex _l(mLock);
1246
1247 injectedEntry = createEntryFromInputEventLocked(event);
1248 injectedEntry->refCount += 1;
1249 injectedEntry->injectorPid = injectorPid;
1250 injectedEntry->injectorUid = injectorUid;
1251
Jeff Brownf67c53e2010-07-28 15:48:59 -07001252 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
1253 injectedEntry->injectionIsAsync = true;
1254 }
1255
Jeff Brown51d45a72010-06-17 20:52:56 -07001256 wasEmpty = mInboundQueue.isEmpty();
1257 mInboundQueue.enqueueAtTail(injectedEntry);
1258
1259 } // release lock
1260
1261 if (wasEmpty) {
1262 mPollLoop->wake();
1263 }
1264
1265 int32_t injectionResult;
1266 { // acquire lock
1267 AutoMutex _l(mLock);
1268
Jeff Brownf67c53e2010-07-28 15:48:59 -07001269 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
1270 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1271 } else {
1272 for (;;) {
1273 injectionResult = injectedEntry->injectionResult;
1274 if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
1275 break;
1276 }
Jeff Brown51d45a72010-06-17 20:52:56 -07001277
Jeff Brown51d45a72010-06-17 20:52:56 -07001278 nsecs_t remainingTimeout = endTime - now();
1279 if (remainingTimeout <= 0) {
Jeff Brownf67c53e2010-07-28 15:48:59 -07001280#if DEBUG_INJECTION
1281 LOGD("injectInputEvent - Timed out waiting for injection result "
1282 "to become available.");
1283#endif
Jeff Brown51d45a72010-06-17 20:52:56 -07001284 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1285 break;
1286 }
1287
Jeff Brownf67c53e2010-07-28 15:48:59 -07001288 mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
1289 }
1290
1291 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
1292 && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
1293 while (injectedEntry->pendingSyncDispatches != 0) {
1294#if DEBUG_INJECTION
1295 LOGD("injectInputEvent - Waiting for %d pending synchronous dispatches.",
1296 injectedEntry->pendingSyncDispatches);
1297#endif
1298 nsecs_t remainingTimeout = endTime - now();
1299 if (remainingTimeout <= 0) {
1300#if DEBUG_INJECTION
1301 LOGD("injectInputEvent - Timed out waiting for pending synchronous "
1302 "dispatches to finish.");
1303#endif
1304 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1305 break;
1306 }
1307
1308 mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
1309 }
Jeff Brown51d45a72010-06-17 20:52:56 -07001310 }
1311 }
1312
1313 mAllocator.releaseEventEntry(injectedEntry);
1314 } // release lock
1315
Jeff Brownf67c53e2010-07-28 15:48:59 -07001316#if DEBUG_INJECTION
1317 LOGD("injectInputEvent - Finished with result %d. "
1318 "injectorPid=%d, injectorUid=%d",
1319 injectionResult, injectorPid, injectorUid);
1320#endif
1321
Jeff Brown51d45a72010-06-17 20:52:56 -07001322 return injectionResult;
1323}
1324
1325void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
1326 if (entry->isInjected()) {
1327#if DEBUG_INJECTION
1328 LOGD("Setting input event injection result to %d. "
1329 "injectorPid=%d, injectorUid=%d",
1330 injectionResult, entry->injectorPid, entry->injectorUid);
1331#endif
1332
Jeff Brownf67c53e2010-07-28 15:48:59 -07001333 if (entry->injectionIsAsync) {
1334 // Log the outcome since the injector did not wait for the injection result.
1335 switch (injectionResult) {
1336 case INPUT_EVENT_INJECTION_SUCCEEDED:
1337 LOGV("Asynchronous input event injection succeeded.");
1338 break;
1339 case INPUT_EVENT_INJECTION_FAILED:
1340 LOGW("Asynchronous input event injection failed.");
1341 break;
1342 case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
1343 LOGW("Asynchronous input event injection permission denied.");
1344 break;
1345 case INPUT_EVENT_INJECTION_TIMED_OUT:
1346 LOGW("Asynchronous input event injection timed out.");
1347 break;
1348 }
1349 }
1350
Jeff Brown51d45a72010-06-17 20:52:56 -07001351 entry->injectionResult = injectionResult;
1352 mInjectionResultAvailableCondition.broadcast();
1353 }
1354}
1355
Jeff Brownf67c53e2010-07-28 15:48:59 -07001356void InputDispatcher::decrementPendingSyncDispatchesLocked(EventEntry* entry) {
1357 entry->pendingSyncDispatches -= 1;
1358
1359 if (entry->isInjected() && entry->pendingSyncDispatches == 0) {
1360 mInjectionSyncFinishedCondition.broadcast();
1361 }
Jeff Brown51d45a72010-06-17 20:52:56 -07001362}
1363
1364InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked(
1365 const InputEvent* event) {
1366 switch (event->getType()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07001367 case AINPUT_EVENT_TYPE_KEY: {
Jeff Brown51d45a72010-06-17 20:52:56 -07001368 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
Jeff Brownaf30ff62010-09-01 17:01:00 -07001369 uint32_t policyFlags = POLICY_FLAG_INJECTED;
Jeff Brown51d45a72010-06-17 20:52:56 -07001370
1371 KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
Jeff Brown5c1ed842010-07-14 18:48:53 -07001372 keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -07001373 keyEvent->getAction(), keyEvent->getFlags(),
1374 keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
1375 keyEvent->getRepeatCount(), keyEvent->getDownTime());
1376 return keyEntry;
1377 }
1378
Jeff Brown5c1ed842010-07-14 18:48:53 -07001379 case AINPUT_EVENT_TYPE_MOTION: {
Jeff Brown51d45a72010-06-17 20:52:56 -07001380 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
Jeff Brownaf30ff62010-09-01 17:01:00 -07001381 uint32_t policyFlags = POLICY_FLAG_INJECTED;
Jeff Brown51d45a72010-06-17 20:52:56 -07001382
1383 const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
1384 const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
1385 size_t pointerCount = motionEvent->getPointerCount();
1386
1387 MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001388 motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001389 motionEvent->getAction(), motionEvent->getFlags(),
1390 motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
Jeff Brown51d45a72010-06-17 20:52:56 -07001391 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
1392 motionEvent->getDownTime(), uint32_t(pointerCount),
1393 motionEvent->getPointerIds(), samplePointerCoords);
1394 for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
1395 sampleEventTimes += 1;
1396 samplePointerCoords += pointerCount;
1397 mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
1398 }
1399 return motionEntry;
1400 }
1401
1402 default:
1403 assert(false);
1404 return NULL;
1405 }
1406}
1407
Jeff Browne839a582010-04-22 18:58:52 -07001408void InputDispatcher::resetKeyRepeatLocked() {
1409 if (mKeyRepeatState.lastKeyEntry) {
1410 mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
1411 mKeyRepeatState.lastKeyEntry = NULL;
1412 }
1413}
1414
Jeff Brown50de30a2010-06-22 01:27:15 -07001415void InputDispatcher::preemptInputDispatch() {
1416#if DEBUG_DISPATCH_CYCLE
1417 LOGD("preemptInputDispatch");
1418#endif
1419
1420 bool preemptedOne = false;
1421 { // acquire lock
1422 AutoMutex _l(mLock);
1423
1424 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1425 Connection* connection = mActiveConnections[i];
1426 if (connection->hasPendingSyncTarget()) {
1427#if DEBUG_DISPATCH_CYCLE
1428 LOGD("channel '%s' ~ Preempted pending synchronous dispatch",
1429 connection->getInputChannelName());
1430#endif
1431 connection->outboundQueue.tail.prev->targetFlags &= ~ InputTarget::FLAG_SYNC;
1432 preemptedOne = true;
1433 }
1434 }
1435 } // release lock
1436
1437 if (preemptedOne) {
1438 // Wake up the poll loop so it can get a head start dispatching the next event.
1439 mPollLoop->wake();
1440 }
1441}
1442
Jeff Browne839a582010-04-22 18:58:52 -07001443status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001444#if DEBUG_REGISTRATION
Jeff Brown50de30a2010-06-22 01:27:15 -07001445 LOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().string());
Jeff Brown54bc2812010-06-15 01:31:58 -07001446#endif
1447
Jeff Browne839a582010-04-22 18:58:52 -07001448 { // acquire lock
1449 AutoMutex _l(mLock);
1450
Jeff Brown0cacb872010-08-17 15:59:26 -07001451 if (getConnectionIndex(inputChannel) >= 0) {
Jeff Browne839a582010-04-22 18:58:52 -07001452 LOGW("Attempted to register already registered input channel '%s'",
1453 inputChannel->getName().string());
1454 return BAD_VALUE;
1455 }
1456
1457 sp<Connection> connection = new Connection(inputChannel);
1458 status_t status = connection->initialize();
1459 if (status) {
1460 LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
1461 inputChannel->getName().string(), status);
1462 return status;
1463 }
1464
Jeff Brown0cacb872010-08-17 15:59:26 -07001465 int32_t receiveFd = inputChannel->getReceivePipeFd();
Jeff Browne839a582010-04-22 18:58:52 -07001466 mConnectionsByReceiveFd.add(receiveFd, connection);
Jeff Brown54bc2812010-06-15 01:31:58 -07001467
Jeff Brown0cacb872010-08-17 15:59:26 -07001468 mPollLoop->setCallback(receiveFd, POLLIN, handleReceiveCallback, this);
1469
Jeff Brown54bc2812010-06-15 01:31:58 -07001470 runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07001471 } // release lock
Jeff Browne839a582010-04-22 18:58:52 -07001472 return OK;
1473}
1474
1475status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001476#if DEBUG_REGISTRATION
Jeff Brown50de30a2010-06-22 01:27:15 -07001477 LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
Jeff Brown54bc2812010-06-15 01:31:58 -07001478#endif
1479
Jeff Browne839a582010-04-22 18:58:52 -07001480 { // acquire lock
1481 AutoMutex _l(mLock);
1482
Jeff Brown0cacb872010-08-17 15:59:26 -07001483 ssize_t connectionIndex = getConnectionIndex(inputChannel);
Jeff Browne839a582010-04-22 18:58:52 -07001484 if (connectionIndex < 0) {
1485 LOGW("Attempted to unregister already unregistered input channel '%s'",
1486 inputChannel->getName().string());
1487 return BAD_VALUE;
1488 }
1489
1490 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1491 mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
1492
1493 connection->status = Connection::STATUS_ZOMBIE;
1494
Jeff Brown0cacb872010-08-17 15:59:26 -07001495 mPollLoop->removeCallback(inputChannel->getReceivePipeFd());
1496
Jeff Brown51d45a72010-06-17 20:52:56 -07001497 nsecs_t currentTime = now();
1498 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -07001499
1500 runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07001501 } // release lock
1502
Jeff Browne839a582010-04-22 18:58:52 -07001503 // Wake the poll loop because removing the connection may have changed the current
1504 // synchronization state.
1505 mPollLoop->wake();
1506 return OK;
1507}
1508
Jeff Brown0cacb872010-08-17 15:59:26 -07001509ssize_t InputDispatcher::getConnectionIndex(const sp<InputChannel>& inputChannel) {
1510 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(inputChannel->getReceivePipeFd());
1511 if (connectionIndex >= 0) {
1512 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1513 if (connection->inputChannel.get() == inputChannel.get()) {
1514 return connectionIndex;
1515 }
1516 }
1517
1518 return -1;
1519}
1520
Jeff Browne839a582010-04-22 18:58:52 -07001521void InputDispatcher::activateConnectionLocked(Connection* connection) {
1522 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1523 if (mActiveConnections.itemAt(i) == connection) {
1524 return;
1525 }
1526 }
1527 mActiveConnections.add(connection);
1528}
1529
1530void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
1531 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1532 if (mActiveConnections.itemAt(i) == connection) {
1533 mActiveConnections.removeAt(i);
1534 return;
1535 }
1536 }
1537}
1538
Jeff Brown54bc2812010-06-15 01:31:58 -07001539void InputDispatcher::onDispatchCycleStartedLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001540 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001541}
1542
Jeff Brown54bc2812010-06-15 01:31:58 -07001543void InputDispatcher::onDispatchCycleFinishedLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001544 nsecs_t currentTime, const sp<Connection>& connection, bool recoveredFromANR) {
Jeff Browne839a582010-04-22 18:58:52 -07001545 if (recoveredFromANR) {
1546 LOGI("channel '%s' ~ Recovered from ANR. %01.1fms since event, "
1547 "%01.1fms since dispatch, %01.1fms since ANR",
1548 connection->getInputChannelName(),
1549 connection->getEventLatencyMillis(currentTime),
1550 connection->getDispatchLatencyMillis(currentTime),
1551 connection->getANRLatencyMillis(currentTime));
1552
Jeff Brown54bc2812010-06-15 01:31:58 -07001553 CommandEntry* commandEntry = postCommandLocked(
1554 & InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07001555 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07001556 }
1557}
1558
Jeff Brown54bc2812010-06-15 01:31:58 -07001559void InputDispatcher::onDispatchCycleANRLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001560 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001561 LOGI("channel '%s' ~ Not responding! %01.1fms since event, %01.1fms since dispatch",
1562 connection->getInputChannelName(),
1563 connection->getEventLatencyMillis(currentTime),
1564 connection->getDispatchLatencyMillis(currentTime));
1565
Jeff Brown54bc2812010-06-15 01:31:58 -07001566 CommandEntry* commandEntry = postCommandLocked(
1567 & InputDispatcher::doNotifyInputChannelANRLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07001568 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07001569}
1570
Jeff Brown54bc2812010-06-15 01:31:58 -07001571void InputDispatcher::onDispatchCycleBrokenLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07001572 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001573 LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
1574 connection->getInputChannelName());
1575
Jeff Brown54bc2812010-06-15 01:31:58 -07001576 CommandEntry* commandEntry = postCommandLocked(
1577 & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07001578 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07001579}
1580
Jeff Brown54bc2812010-06-15 01:31:58 -07001581void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
1582 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001583 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07001584
Jeff Brown51d45a72010-06-17 20:52:56 -07001585 if (connection->status != Connection::STATUS_ZOMBIE) {
1586 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07001587
Jeff Brown51d45a72010-06-17 20:52:56 -07001588 mPolicy->notifyInputChannelBroken(connection->inputChannel);
1589
1590 mLock.lock();
1591 }
Jeff Brown54bc2812010-06-15 01:31:58 -07001592}
1593
1594void InputDispatcher::doNotifyInputChannelANRLockedInterruptible(
1595 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001596 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07001597
Jeff Brown51d45a72010-06-17 20:52:56 -07001598 if (connection->status != Connection::STATUS_ZOMBIE) {
1599 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07001600
Jeff Brown51d45a72010-06-17 20:52:56 -07001601 nsecs_t newTimeout;
1602 bool resume = mPolicy->notifyInputChannelANR(connection->inputChannel, newTimeout);
1603
1604 mLock.lock();
1605
1606 nsecs_t currentTime = now();
1607 if (resume) {
1608 resumeAfterTimeoutDispatchCycleLocked(currentTime, connection, newTimeout);
1609 } else {
1610 abortDispatchCycleLocked(currentTime, connection, false /*(not) broken*/);
1611 }
1612 }
Jeff Brown54bc2812010-06-15 01:31:58 -07001613}
1614
1615void InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible(
1616 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001617 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07001618
Jeff Brown51d45a72010-06-17 20:52:56 -07001619 if (connection->status != Connection::STATUS_ZOMBIE) {
1620 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07001621
Jeff Brown51d45a72010-06-17 20:52:56 -07001622 mPolicy->notifyInputChannelRecoveredFromANR(connection->inputChannel);
1623
1624 mLock.lock();
1625 }
Jeff Brown54bc2812010-06-15 01:31:58 -07001626}
1627
1628
Jeff Browne839a582010-04-22 18:58:52 -07001629// --- InputDispatcher::Allocator ---
1630
1631InputDispatcher::Allocator::Allocator() {
1632}
1633
Jeff Brown51d45a72010-06-17 20:52:56 -07001634void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
1635 nsecs_t eventTime) {
1636 entry->type = type;
1637 entry->refCount = 1;
1638 entry->dispatchInProgress = false;
Christopher Tated974e002010-06-23 16:50:30 -07001639 entry->eventTime = eventTime;
Jeff Brown51d45a72010-06-17 20:52:56 -07001640 entry->injectionResult = INPUT_EVENT_INJECTION_PENDING;
Jeff Brownf67c53e2010-07-28 15:48:59 -07001641 entry->injectionIsAsync = false;
Jeff Brown51d45a72010-06-17 20:52:56 -07001642 entry->injectorPid = -1;
1643 entry->injectorUid = -1;
Jeff Brownf67c53e2010-07-28 15:48:59 -07001644 entry->pendingSyncDispatches = 0;
Jeff Brown51d45a72010-06-17 20:52:56 -07001645}
1646
Jeff Browne839a582010-04-22 18:58:52 -07001647InputDispatcher::ConfigurationChangedEntry*
Jeff Brown51d45a72010-06-17 20:52:56 -07001648InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
Jeff Browne839a582010-04-22 18:58:52 -07001649 ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07001650 initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime);
Jeff Browne839a582010-04-22 18:58:52 -07001651 return entry;
1652}
1653
Jeff Brown51d45a72010-06-17 20:52:56 -07001654InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001655 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
Jeff Brown51d45a72010-06-17 20:52:56 -07001656 int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
1657 int32_t repeatCount, nsecs_t downTime) {
Jeff Browne839a582010-04-22 18:58:52 -07001658 KeyEntry* entry = mKeyEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07001659 initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime);
1660
1661 entry->deviceId = deviceId;
Jeff Brown5c1ed842010-07-14 18:48:53 -07001662 entry->source = source;
Jeff Brown51d45a72010-06-17 20:52:56 -07001663 entry->policyFlags = policyFlags;
1664 entry->action = action;
1665 entry->flags = flags;
1666 entry->keyCode = keyCode;
1667 entry->scanCode = scanCode;
1668 entry->metaState = metaState;
1669 entry->repeatCount = repeatCount;
1670 entry->downTime = downTime;
Jeff Browne839a582010-04-22 18:58:52 -07001671 return entry;
1672}
1673
Jeff Brown51d45a72010-06-17 20:52:56 -07001674InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001675 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
Jeff Brown51d45a72010-06-17 20:52:56 -07001676 int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
1677 nsecs_t downTime, uint32_t pointerCount,
1678 const int32_t* pointerIds, const PointerCoords* pointerCoords) {
Jeff Browne839a582010-04-22 18:58:52 -07001679 MotionEntry* entry = mMotionEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07001680 initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime);
1681
1682 entry->eventTime = eventTime;
1683 entry->deviceId = deviceId;
Jeff Brown5c1ed842010-07-14 18:48:53 -07001684 entry->source = source;
Jeff Brown51d45a72010-06-17 20:52:56 -07001685 entry->policyFlags = policyFlags;
1686 entry->action = action;
Jeff Brownaf30ff62010-09-01 17:01:00 -07001687 entry->flags = flags;
Jeff Brown51d45a72010-06-17 20:52:56 -07001688 entry->metaState = metaState;
1689 entry->edgeFlags = edgeFlags;
1690 entry->xPrecision = xPrecision;
1691 entry->yPrecision = yPrecision;
1692 entry->downTime = downTime;
1693 entry->pointerCount = pointerCount;
1694 entry->firstSample.eventTime = eventTime;
Jeff Browne839a582010-04-22 18:58:52 -07001695 entry->firstSample.next = NULL;
Jeff Brown51d45a72010-06-17 20:52:56 -07001696 entry->lastSample = & entry->firstSample;
1697 for (uint32_t i = 0; i < pointerCount; i++) {
1698 entry->pointerIds[i] = pointerIds[i];
1699 entry->firstSample.pointerCoords[i] = pointerCoords[i];
1700 }
Jeff Browne839a582010-04-22 18:58:52 -07001701 return entry;
1702}
1703
1704InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
1705 EventEntry* eventEntry) {
1706 DispatchEntry* entry = mDispatchEntryPool.alloc();
1707 entry->eventEntry = eventEntry;
1708 eventEntry->refCount += 1;
1709 return entry;
1710}
1711
Jeff Brown54bc2812010-06-15 01:31:58 -07001712InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
1713 CommandEntry* entry = mCommandEntryPool.alloc();
1714 entry->command = command;
1715 return entry;
1716}
1717
Jeff Browne839a582010-04-22 18:58:52 -07001718void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
1719 switch (entry->type) {
1720 case EventEntry::TYPE_CONFIGURATION_CHANGED:
1721 releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
1722 break;
1723 case EventEntry::TYPE_KEY:
1724 releaseKeyEntry(static_cast<KeyEntry*>(entry));
1725 break;
1726 case EventEntry::TYPE_MOTION:
1727 releaseMotionEntry(static_cast<MotionEntry*>(entry));
1728 break;
1729 default:
1730 assert(false);
1731 break;
1732 }
1733}
1734
1735void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
1736 ConfigurationChangedEntry* entry) {
1737 entry->refCount -= 1;
1738 if (entry->refCount == 0) {
1739 mConfigurationChangeEntryPool.free(entry);
1740 } else {
1741 assert(entry->refCount > 0);
1742 }
1743}
1744
1745void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
1746 entry->refCount -= 1;
1747 if (entry->refCount == 0) {
1748 mKeyEntryPool.free(entry);
1749 } else {
1750 assert(entry->refCount > 0);
1751 }
1752}
1753
1754void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
1755 entry->refCount -= 1;
1756 if (entry->refCount == 0) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001757 for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
1758 MotionSample* next = sample->next;
1759 mMotionSamplePool.free(sample);
1760 sample = next;
1761 }
Jeff Browne839a582010-04-22 18:58:52 -07001762 mMotionEntryPool.free(entry);
1763 } else {
1764 assert(entry->refCount > 0);
1765 }
1766}
1767
1768void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
1769 releaseEventEntry(entry->eventEntry);
1770 mDispatchEntryPool.free(entry);
1771}
1772
Jeff Brown54bc2812010-06-15 01:31:58 -07001773void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
1774 mCommandEntryPool.free(entry);
1775}
1776
Jeff Browne839a582010-04-22 18:58:52 -07001777void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
Jeff Brown51d45a72010-06-17 20:52:56 -07001778 nsecs_t eventTime, const PointerCoords* pointerCoords) {
Jeff Browne839a582010-04-22 18:58:52 -07001779 MotionSample* sample = mMotionSamplePool.alloc();
1780 sample->eventTime = eventTime;
Jeff Brown51d45a72010-06-17 20:52:56 -07001781 uint32_t pointerCount = motionEntry->pointerCount;
1782 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Browne839a582010-04-22 18:58:52 -07001783 sample->pointerCoords[i] = pointerCoords[i];
1784 }
1785
1786 sample->next = NULL;
1787 motionEntry->lastSample->next = sample;
1788 motionEntry->lastSample = sample;
1789}
1790
Jeff Brown542412c2010-08-18 15:51:08 -07001791// --- InputDispatcher::MotionEntry ---
1792
1793uint32_t InputDispatcher::MotionEntry::countSamples() const {
1794 uint32_t count = 1;
1795 for (MotionSample* sample = firstSample.next; sample != NULL; sample = sample->next) {
1796 count += 1;
1797 }
1798 return count;
1799}
1800
Jeff Browne839a582010-04-22 18:58:52 -07001801// --- InputDispatcher::Connection ---
1802
1803InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
1804 status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
1805 nextTimeoutTime(LONG_LONG_MAX),
1806 lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX),
1807 lastANRTime(LONG_LONG_MAX) {
1808}
1809
1810InputDispatcher::Connection::~Connection() {
1811}
1812
1813status_t InputDispatcher::Connection::initialize() {
1814 return inputPublisher.initialize();
1815}
1816
Jeff Brown51d45a72010-06-17 20:52:56 -07001817void InputDispatcher::Connection::setNextTimeoutTime(nsecs_t currentTime, nsecs_t timeout) {
1818 nextTimeoutTime = (timeout >= 0) ? currentTime + timeout : LONG_LONG_MAX;
1819}
1820
Jeff Brown54bc2812010-06-15 01:31:58 -07001821const char* InputDispatcher::Connection::getStatusLabel() const {
1822 switch (status) {
1823 case STATUS_NORMAL:
1824 return "NORMAL";
1825
1826 case STATUS_BROKEN:
1827 return "BROKEN";
1828
1829 case STATUS_NOT_RESPONDING:
1830 return "NOT_RESPONDING";
1831
1832 case STATUS_ZOMBIE:
1833 return "ZOMBIE";
1834
1835 default:
1836 return "UNKNOWN";
1837 }
1838}
1839
Jeff Browne839a582010-04-22 18:58:52 -07001840InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
1841 const EventEntry* eventEntry) const {
1842 for (DispatchEntry* dispatchEntry = outboundQueue.tail.prev;
1843 dispatchEntry != & outboundQueue.head; dispatchEntry = dispatchEntry->prev) {
1844 if (dispatchEntry->eventEntry == eventEntry) {
1845 return dispatchEntry;
1846 }
1847 }
1848 return NULL;
1849}
1850
Jeff Brown54bc2812010-06-15 01:31:58 -07001851// --- InputDispatcher::CommandEntry ---
1852
1853InputDispatcher::CommandEntry::CommandEntry() {
1854}
1855
1856InputDispatcher::CommandEntry::~CommandEntry() {
1857}
1858
Jeff Browne839a582010-04-22 18:58:52 -07001859
1860// --- InputDispatcherThread ---
1861
1862InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
1863 Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
1864}
1865
1866InputDispatcherThread::~InputDispatcherThread() {
1867}
1868
1869bool InputDispatcherThread::threadLoop() {
1870 mDispatcher->dispatchOnce();
1871 return true;
1872}
1873
1874} // namespace android