blob: ce616a475c42bf26c285a48baacade40211c282a [file] [log] [blame]
Jeff Brown46b9ac02010-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 Brown349703e2010-06-22 01:27:15 -070011#define DEBUG_INBOUND_EVENT_DETAILS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070012
13// Log detailed debug messages about each outbound event processed by the dispatcher.
Jeff Brown349703e2010-06-22 01:27:15 -070014#define DEBUG_OUTBOUND_EVENT_DETAILS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070015
16// Log debug messages about batching.
Jeff Brown349703e2010-06-22 01:27:15 -070017#define DEBUG_BATCHING 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070018
19// Log debug messages about the dispatch cycle.
Jeff Brown349703e2010-06-22 01:27:15 -070020#define DEBUG_DISPATCH_CYCLE 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070021
Jeff Brown9c3cda02010-06-15 01:31:58 -070022// Log debug messages about registrations.
Jeff Brown349703e2010-06-22 01:27:15 -070023#define DEBUG_REGISTRATION 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070024
Jeff Brown46b9ac02010-04-22 18:58:52 -070025// Log debug messages about performance statistics.
Jeff Brown349703e2010-06-22 01:27:15 -070026#define DEBUG_PERFORMANCE_STATISTICS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070027
Jeff Brown7fbdc842010-06-17 20:52:56 -070028// Log debug messages about input event injection.
Jeff Brown349703e2010-06-22 01:27:15 -070029#define DEBUG_INJECTION 0
Jeff Brown7fbdc842010-06-17 20:52:56 -070030
Jeff Brownae9fc032010-08-18 15:51:08 -070031// Log debug messages about input event throttling.
32#define DEBUG_THROTTLING 0
33
Jeff Brown46b9ac02010-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 Brown46b9ac02010-04-22 18:58:52 -070039#include <errno.h>
40#include <limits.h>
Jeff Brown46b9ac02010-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 Brownfd035822010-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 Brown46b9ac02010-04-22 18:58:52 -070050}
51
Jeff Brown7fbdc842010-06-17 20:52:56 -070052static inline nsecs_t now() {
53 return systemTime(SYSTEM_TIME_MONOTONIC);
54}
55
Jeff Brown46b9ac02010-04-22 18:58:52 -070056// --- InputDispatcher ---
57
Jeff Brown9c3cda02010-06-15 01:31:58 -070058InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
Jeff Brown46b9ac02010-04-22 18:58:52 -070059 mPolicy(policy) {
Dianne Hackborn85448bb2010-07-07 14:27:31 -070060 mPollLoop = new PollLoop(false);
Jeff Brown46b9ac02010-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 Brown9c3cda02010-06-15 01:31:58 -070071
Jeff Brownae9fc032010-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 Brown9c3cda02010-06-15 01:31:58 -070081 mCurrentInputTargetsValid = false;
Jeff Brown46b9ac02010-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 Brown9c3cda02010-06-15 01:31:58 -070099 nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700100
Jeff Brown9c3cda02010-06-15 01:31:58 -0700101 bool skipPoll = false;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700102 nsecs_t currentTime;
103 nsecs_t nextWakeupTime = LONG_LONG_MAX;
104 { // acquire lock
105 AutoMutex _l(mLock);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700106 currentTime = now();
Jeff Brown46b9ac02010-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 Brown9c3cda02010-06-15 01:31:58 -0700112 if (keyRepeatTimeout < 0) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700113 resetKeyRepeatLocked();
114 }
115
Jeff Brown7fbdc842010-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 Brown46b9ac02010-04-22 18:58:52 -0700118 bool hasPendingSyncTarget = false;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700119 size_t activeConnectionCount = mActiveConnections.size();
120 for (size_t i = 0; i < activeConnectionCount; i++) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700121 Connection* connection = mActiveConnections.itemAt(i);
122
Jeff Brown46b9ac02010-04-22 18:58:52 -0700123 if (connection->hasPendingSyncTarget()) {
124 hasPendingSyncTarget = true;
125 }
126
Jeff Brown7fbdc842010-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 Brown46b9ac02010-04-22 18:58:52 -0700133 }
134
Jeff Brown7fbdc842010-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 Brown46b9ac02010-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 Brown9c3cda02010-06-15 01:31:58 -0700149 processKeyRepeatLockedInterruptible(currentTime, keyRepeatTimeout);
150 skipPoll = true;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700151 } else {
152 if (mKeyRepeatState.nextRepeatTime < nextWakeupTime) {
153 nextWakeupTime = mKeyRepeatState.nextRepeatTime;
154 }
155 }
156 }
157 } else {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700158 // Inbound queue has at least one entry.
Jeff Brownae9fc032010-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
204 mThrottleState.lastEventTime = currentTime;
205 mThrottleState.lastDeviceId = deviceId;
206 mThrottleState.lastSource = source;
207 }
208
209 // Start processing the entry but leave it on the queue until later so that the
Jeff Brown9c3cda02010-06-15 01:31:58 -0700210 // input reader can keep appending samples onto a motion event between the
211 // time we started processing it and the time we finally enqueue dispatch
212 // entries for it.
Jeff Brown46b9ac02010-04-22 18:58:52 -0700213 switch (entry->type) {
214 case EventEntry::TYPE_CONFIGURATION_CHANGED: {
215 ConfigurationChangedEntry* typedEntry =
216 static_cast<ConfigurationChangedEntry*>(entry);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700217 processConfigurationChangedLockedInterruptible(currentTime, typedEntry);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700218 break;
219 }
220
221 case EventEntry::TYPE_KEY: {
222 KeyEntry* typedEntry = static_cast<KeyEntry*>(entry);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700223 processKeyLockedInterruptible(currentTime, typedEntry, keyRepeatTimeout);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700224 break;
225 }
226
227 case EventEntry::TYPE_MOTION: {
228 MotionEntry* typedEntry = static_cast<MotionEntry*>(entry);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700229 processMotionLockedInterruptible(currentTime, typedEntry);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700230 break;
231 }
232
233 default:
234 assert(false);
235 break;
236 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700237
238 // Dequeue and release the event entry that we just processed.
239 mInboundQueue.dequeue(entry);
240 mAllocator.releaseEventEntry(entry);
241 skipPoll = true;
Jeff Brownae9fc032010-08-18 15:51:08 -0700242
243 Throttle: ;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700244 }
245 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700246
247 // Run any deferred commands.
248 skipPoll |= runCommandsLockedInterruptible();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700249 } // release lock
250
Jeff Brown9c3cda02010-06-15 01:31:58 -0700251 // If we dispatched anything, don't poll just now. Wait for the next iteration.
252 // Contents may have shifted during flight.
253 if (skipPoll) {
254 return;
255 }
256
Jeff Brownae9fc032010-08-18 15:51:08 -0700257 // Wait for callback or timeout or wake. (make sure we round up, not down)
258 nsecs_t timeout = (nextWakeupTime - currentTime + 999999LL) / 1000000LL;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700259 int32_t timeoutMillis = timeout > INT_MAX ? -1 : timeout > 0 ? int32_t(timeout) : 0;
260 mPollLoop->pollOnce(timeoutMillis);
261}
262
Jeff Brown9c3cda02010-06-15 01:31:58 -0700263bool InputDispatcher::runCommandsLockedInterruptible() {
264 if (mCommandQueue.isEmpty()) {
265 return false;
266 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700267
Jeff Brown9c3cda02010-06-15 01:31:58 -0700268 do {
269 CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
270
271 Command command = commandEntry->command;
272 (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
273
Jeff Brown7fbdc842010-06-17 20:52:56 -0700274 commandEntry->connection.clear();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700275 mAllocator.releaseCommandEntry(commandEntry);
276 } while (! mCommandQueue.isEmpty());
277 return true;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700278}
279
Jeff Brown9c3cda02010-06-15 01:31:58 -0700280InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
281 CommandEntry* commandEntry = mAllocator.obtainCommandEntry(command);
282 mCommandQueue.enqueueAtTail(commandEntry);
283 return commandEntry;
284}
285
286void InputDispatcher::processConfigurationChangedLockedInterruptible(
287 nsecs_t currentTime, ConfigurationChangedEntry* entry) {
288#if DEBUG_OUTBOUND_EVENT_DETAILS
289 LOGD("processConfigurationChanged - eventTime=%lld", entry->eventTime);
290#endif
291
Jeff Brown0b72e822010-06-29 16:52:21 -0700292 // Reset key repeating in case a keyboard device was added or removed or something.
293 resetKeyRepeatLocked();
294
Jeff Brown9c3cda02010-06-15 01:31:58 -0700295 mLock.unlock();
296
297 mPolicy->notifyConfigurationChanged(entry->eventTime);
298
299 mLock.lock();
300}
301
302void InputDispatcher::processKeyLockedInterruptible(
303 nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700304#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brownc5ed5912010-07-14 18:48:53 -0700305 LOGD("processKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Brown46b9ac02010-04-22 18:58:52 -0700306 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
Jeff Brownc5ed5912010-07-14 18:48:53 -0700307 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, entry->action,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700308 entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
309 entry->downTime);
310#endif
311
Jeff Brownc5ed5912010-07-14 18:48:53 -0700312 if (entry->action == AKEY_EVENT_ACTION_DOWN && ! entry->isInjected()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700313 if (mKeyRepeatState.lastKeyEntry
314 && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
315 // We have seen two identical key downs in a row which indicates that the device
316 // driver is automatically generating key repeats itself. We take note of the
317 // repeat here, but we disable our own next key repeat timer since it is clear that
318 // we will not need to synthesize key repeats ourselves.
319 entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
320 resetKeyRepeatLocked();
321 mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
322 } else {
323 // Not a repeat. Save key down state in case we do see a repeat later.
324 resetKeyRepeatLocked();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700325 mKeyRepeatState.nextRepeatTime = entry->eventTime + keyRepeatTimeout;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700326 }
327 mKeyRepeatState.lastKeyEntry = entry;
328 entry->refCount += 1;
329 } else {
330 resetKeyRepeatLocked();
331 }
332
Jeff Brown9c3cda02010-06-15 01:31:58 -0700333 identifyInputTargetsAndDispatchKeyLockedInterruptible(currentTime, entry);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700334}
335
Jeff Brown9c3cda02010-06-15 01:31:58 -0700336void InputDispatcher::processKeyRepeatLockedInterruptible(
337 nsecs_t currentTime, nsecs_t keyRepeatTimeout) {
Jeff Brown349703e2010-06-22 01:27:15 -0700338 KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
339
340 // Search the inbound queue for a key up corresponding to this device.
341 // It doesn't make sense to generate a key repeat event if the key is already up.
342 for (EventEntry* queuedEntry = mInboundQueue.head.next;
343 queuedEntry != & mInboundQueue.tail; queuedEntry = entry->next) {
344 if (queuedEntry->type == EventEntry::TYPE_KEY) {
345 KeyEntry* queuedKeyEntry = static_cast<KeyEntry*>(queuedEntry);
346 if (queuedKeyEntry->deviceId == entry->deviceId
Jeff Brownc5ed5912010-07-14 18:48:53 -0700347 && entry->action == AKEY_EVENT_ACTION_UP) {
Jeff Brown349703e2010-06-22 01:27:15 -0700348 resetKeyRepeatLocked();
349 return;
350 }
351 }
352 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700353
354 // Synthesize a key repeat after the repeat timeout expired.
Jeff Brown349703e2010-06-22 01:27:15 -0700355 // Reuse the repeated key entry if it is otherwise unreferenced.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700356 uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700357 if (entry->refCount == 1) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700358 entry->eventTime = currentTime;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700359 entry->policyFlags = policyFlags;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700360 entry->repeatCount += 1;
361 } else {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700362 KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700363 entry->deviceId, entry->source, policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700364 entry->action, entry->flags, entry->keyCode, entry->scanCode,
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700365 entry->metaState, entry->repeatCount + 1, entry->downTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700366
367 mKeyRepeatState.lastKeyEntry = newEntry;
368 mAllocator.releaseKeyEntry(entry);
369
370 entry = newEntry;
371 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700372
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700373 if (entry->repeatCount == 1) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700374 entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700375 }
376
Jeff Brown9c3cda02010-06-15 01:31:58 -0700377 mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatTimeout;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700378
379#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brownc5ed5912010-07-14 18:48:53 -0700380 LOGD("processKeyRepeat - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Brown46b9ac02010-04-22 18:58:52 -0700381 "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
382 "repeatCount=%d, downTime=%lld",
Jeff Brownc5ed5912010-07-14 18:48:53 -0700383 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700384 entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
385 entry->repeatCount, entry->downTime);
386#endif
387
Jeff Brown9c3cda02010-06-15 01:31:58 -0700388 identifyInputTargetsAndDispatchKeyLockedInterruptible(currentTime, entry);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700389}
390
Jeff Brown9c3cda02010-06-15 01:31:58 -0700391void InputDispatcher::processMotionLockedInterruptible(
392 nsecs_t currentTime, MotionEntry* entry) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700393#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brownc5ed5912010-07-14 18:48:53 -0700394 LOGD("processMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Brown46b9ac02010-04-22 18:58:52 -0700395 "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
Jeff Brownc5ed5912010-07-14 18:48:53 -0700396 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, entry->action,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700397 entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
398 entry->downTime);
399
400 // Print the most recent sample that we have available, this may change due to batching.
401 size_t sampleCount = 1;
402 MotionSample* sample = & entry->firstSample;
403 for (; sample->next != NULL; sample = sample->next) {
404 sampleCount += 1;
405 }
406 for (uint32_t i = 0; i < entry->pointerCount; i++) {
407 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
408 i, entry->pointerIds[i],
409 sample->pointerCoords[i].x,
410 sample->pointerCoords[i].y,
411 sample->pointerCoords[i].pressure,
412 sample->pointerCoords[i].size);
413 }
414
415 // Keep in mind that due to batching, it is possible for the number of samples actually
416 // dispatched to change before the application finally consumed them.
Jeff Brownc5ed5912010-07-14 18:48:53 -0700417 if (entry->action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700418 LOGD(" ... Total movement samples currently batched %d ...", sampleCount);
419 }
420#endif
421
Jeff Brown9c3cda02010-06-15 01:31:58 -0700422 identifyInputTargetsAndDispatchMotionLockedInterruptible(currentTime, entry);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700423}
424
Jeff Brown9c3cda02010-06-15 01:31:58 -0700425void InputDispatcher::identifyInputTargetsAndDispatchKeyLockedInterruptible(
Jeff Brown46b9ac02010-04-22 18:58:52 -0700426 nsecs_t currentTime, KeyEntry* entry) {
427#if DEBUG_DISPATCH_CYCLE
428 LOGD("identifyInputTargetsAndDispatchKey");
429#endif
430
Jeff Brown9c3cda02010-06-15 01:31:58 -0700431 entry->dispatchInProgress = true;
432 mCurrentInputTargetsValid = false;
433 mLock.unlock();
434
Jeff Brownc5ed5912010-07-14 18:48:53 -0700435 mReusableKeyEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700436 entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
437 entry->downTime, entry->eventTime);
438
439 mCurrentInputTargets.clear();
Jeff Brown349703e2010-06-22 01:27:15 -0700440 int32_t injectionResult = mPolicy->waitForKeyEventTargets(& mReusableKeyEvent,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700441 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700442 mCurrentInputTargets);
443
Jeff Brown9c3cda02010-06-15 01:31:58 -0700444 mLock.lock();
445 mCurrentInputTargetsValid = true;
446
Jeff Brown7fbdc842010-06-17 20:52:56 -0700447 setInjectionResultLocked(entry, injectionResult);
448
Jeff Brown349703e2010-06-22 01:27:15 -0700449 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
450 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
451 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700452}
453
Jeff Brown9c3cda02010-06-15 01:31:58 -0700454void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(
Jeff Brown46b9ac02010-04-22 18:58:52 -0700455 nsecs_t currentTime, MotionEntry* entry) {
456#if DEBUG_DISPATCH_CYCLE
457 LOGD("identifyInputTargetsAndDispatchMotion");
458#endif
459
Jeff Brown9c3cda02010-06-15 01:31:58 -0700460 entry->dispatchInProgress = true;
461 mCurrentInputTargetsValid = false;
462 mLock.unlock();
463
Jeff Brownc5ed5912010-07-14 18:48:53 -0700464 mReusableMotionEvent.initialize(entry->deviceId, entry->source, entry->action,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700465 entry->edgeFlags, entry->metaState,
Jeff Brown5c225b12010-06-16 01:53:36 -0700466 0, 0, entry->xPrecision, entry->yPrecision,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700467 entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds,
468 entry->firstSample.pointerCoords);
469
470 mCurrentInputTargets.clear();
Jeff Brown349703e2010-06-22 01:27:15 -0700471 int32_t injectionResult = mPolicy->waitForMotionEventTargets(& mReusableMotionEvent,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700472 entry->policyFlags, entry->injectorPid, entry->injectorUid,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700473 mCurrentInputTargets);
474
Jeff Brown9c3cda02010-06-15 01:31:58 -0700475 mLock.lock();
476 mCurrentInputTargetsValid = true;
477
Jeff Brown7fbdc842010-06-17 20:52:56 -0700478 setInjectionResultLocked(entry, injectionResult);
479
Jeff Brown349703e2010-06-22 01:27:15 -0700480 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
481 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
482 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700483}
484
485void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
486 EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
487#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700488 LOGD("dispatchEventToCurrentInputTargets - "
Jeff Brown46b9ac02010-04-22 18:58:52 -0700489 "resumeWithAppendedMotionSample=%s",
490 resumeWithAppendedMotionSample ? "true" : "false");
491#endif
492
Jeff Brown9c3cda02010-06-15 01:31:58 -0700493 assert(eventEntry->dispatchInProgress); // should already have been set to true
494
Jeff Brown46b9ac02010-04-22 18:58:52 -0700495 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
496 const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
497
Jeff Brown2cbecea2010-08-17 15:59:26 -0700498 ssize_t connectionIndex = getConnectionIndex(inputTarget.inputChannel);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700499 if (connectionIndex >= 0) {
500 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700501 prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700502 resumeWithAppendedMotionSample);
503 } else {
504 LOGW("Framework requested delivery of an input event to channel '%s' but it "
505 "is not registered with the input dispatcher.",
506 inputTarget.inputChannel->getName().string());
507 }
508 }
509}
510
Jeff Brown7fbdc842010-06-17 20:52:56 -0700511void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
512 const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700513 bool resumeWithAppendedMotionSample) {
514#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700515 LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, timeout=%lldns, "
Jeff Brown46b9ac02010-04-22 18:58:52 -0700516 "xOffset=%f, yOffset=%f, resumeWithAppendedMotionSample=%s",
517 connection->getInputChannelName(), inputTarget->flags, inputTarget->timeout,
518 inputTarget->xOffset, inputTarget->yOffset,
519 resumeWithAppendedMotionSample ? "true" : "false");
520#endif
521
522 // Skip this event if the connection status is not normal.
523 // We don't want to queue outbound events at all if the connection is broken or
524 // not responding.
525 if (connection->status != Connection::STATUS_NORMAL) {
526 LOGV("channel '%s' ~ Dropping event because the channel status is %s",
Jeff Brown9c3cda02010-06-15 01:31:58 -0700527 connection->getStatusLabel());
Jeff Brown46b9ac02010-04-22 18:58:52 -0700528 return;
529 }
530
531 // Resume the dispatch cycle with a freshly appended motion sample.
532 // First we check that the last dispatch entry in the outbound queue is for the same
533 // motion event to which we appended the motion sample. If we find such a dispatch
534 // entry, and if it is currently in progress then we try to stream the new sample.
535 bool wasEmpty = connection->outboundQueue.isEmpty();
536
537 if (! wasEmpty && resumeWithAppendedMotionSample) {
538 DispatchEntry* motionEventDispatchEntry =
539 connection->findQueuedDispatchEntryForEvent(eventEntry);
540 if (motionEventDispatchEntry) {
541 // If the dispatch entry is not in progress, then we must be busy dispatching an
542 // earlier event. Not a problem, the motion event is on the outbound queue and will
543 // be dispatched later.
544 if (! motionEventDispatchEntry->inProgress) {
545#if DEBUG_BATCHING
546 LOGD("channel '%s' ~ Not streaming because the motion event has "
547 "not yet been dispatched. "
548 "(Waiting for earlier events to be consumed.)",
549 connection->getInputChannelName());
550#endif
551 return;
552 }
553
554 // If the dispatch entry is in progress but it already has a tail of pending
555 // motion samples, then it must mean that the shared memory buffer filled up.
556 // Not a problem, when this dispatch cycle is finished, we will eventually start
557 // a new dispatch cycle to process the tail and that tail includes the newly
558 // appended motion sample.
559 if (motionEventDispatchEntry->tailMotionSample) {
560#if DEBUG_BATCHING
561 LOGD("channel '%s' ~ Not streaming because no new samples can "
562 "be appended to the motion event in this dispatch cycle. "
563 "(Waiting for next dispatch cycle to start.)",
564 connection->getInputChannelName());
565#endif
566 return;
567 }
568
569 // The dispatch entry is in progress and is still potentially open for streaming.
570 // Try to stream the new motion sample. This might fail if the consumer has already
571 // consumed the motion event (or if the channel is broken).
572 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
573 status_t status = connection->inputPublisher.appendMotionSample(
574 appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
575 if (status == OK) {
576#if DEBUG_BATCHING
577 LOGD("channel '%s' ~ Successfully streamed new motion sample.",
578 connection->getInputChannelName());
579#endif
580 return;
581 }
582
583#if DEBUG_BATCHING
584 if (status == NO_MEMORY) {
585 LOGD("channel '%s' ~ Could not append motion sample to currently "
586 "dispatched move event because the shared memory buffer is full. "
587 "(Waiting for next dispatch cycle to start.)",
588 connection->getInputChannelName());
589 } else if (status == status_t(FAILED_TRANSACTION)) {
590 LOGD("channel '%s' ~ Could not append motion sample to currently "
Jeff Brown349703e2010-06-22 01:27:15 -0700591 "dispatched move event because the event has already been consumed. "
Jeff Brown46b9ac02010-04-22 18:58:52 -0700592 "(Waiting for next dispatch cycle to start.)",
593 connection->getInputChannelName());
594 } else {
595 LOGD("channel '%s' ~ Could not append motion sample to currently "
596 "dispatched move event due to an error, status=%d. "
597 "(Waiting for next dispatch cycle to start.)",
598 connection->getInputChannelName(), status);
599 }
600#endif
601 // Failed to stream. Start a new tail of pending motion samples to dispatch
602 // in the next cycle.
603 motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
604 return;
605 }
606 }
607
608 // This is a new event.
609 // Enqueue a new dispatch entry onto the outbound queue for this connection.
610 DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry); // increments ref
611 dispatchEntry->targetFlags = inputTarget->flags;
612 dispatchEntry->xOffset = inputTarget->xOffset;
613 dispatchEntry->yOffset = inputTarget->yOffset;
614 dispatchEntry->timeout = inputTarget->timeout;
615 dispatchEntry->inProgress = false;
616 dispatchEntry->headMotionSample = NULL;
617 dispatchEntry->tailMotionSample = NULL;
618
Jeff Brown6ec402b2010-07-28 15:48:59 -0700619 if (dispatchEntry->isSyncTarget()) {
620 eventEntry->pendingSyncDispatches += 1;
621 }
622
Jeff Brown46b9ac02010-04-22 18:58:52 -0700623 // Handle the case where we could not stream a new motion sample because the consumer has
624 // already consumed the motion event (otherwise the corresponding dispatch entry would
625 // still be in the outbound queue for this connection). We set the head motion sample
626 // to the list starting with the newly appended motion sample.
627 if (resumeWithAppendedMotionSample) {
628#if DEBUG_BATCHING
629 LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
630 "that cannot be streamed because the motion event has already been consumed.",
631 connection->getInputChannelName());
632#endif
633 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
634 dispatchEntry->headMotionSample = appendedMotionSample;
635 }
636
637 // Enqueue the dispatch entry.
638 connection->outboundQueue.enqueueAtTail(dispatchEntry);
639
640 // If the outbound queue was previously empty, start the dispatch cycle going.
641 if (wasEmpty) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700642 activateConnectionLocked(connection.get());
Jeff Brown46b9ac02010-04-22 18:58:52 -0700643 startDispatchCycleLocked(currentTime, connection);
644 }
645}
646
Jeff Brown7fbdc842010-06-17 20:52:56 -0700647void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
648 const sp<Connection>& connection) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700649#if DEBUG_DISPATCH_CYCLE
650 LOGD("channel '%s' ~ startDispatchCycle",
651 connection->getInputChannelName());
652#endif
653
654 assert(connection->status == Connection::STATUS_NORMAL);
655 assert(! connection->outboundQueue.isEmpty());
656
657 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
658 assert(! dispatchEntry->inProgress);
659
660 // TODO throttle successive ACTION_MOVE motion events for the same device
661 // possible implementation could set a brief poll timeout here and resume starting the
662 // dispatch cycle when elapsed
663
664 // Publish the event.
665 status_t status;
666 switch (dispatchEntry->eventEntry->type) {
667 case EventEntry::TYPE_KEY: {
668 KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
669
670 // Apply target flags.
671 int32_t action = keyEntry->action;
672 int32_t flags = keyEntry->flags;
673 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700674 flags |= AKEY_EVENT_FLAG_CANCELED;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700675 }
676
677 // Publish the key event.
Jeff Brownc5ed5912010-07-14 18:48:53 -0700678 status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700679 action, flags, keyEntry->keyCode, keyEntry->scanCode,
680 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
681 keyEntry->eventTime);
682
683 if (status) {
684 LOGE("channel '%s' ~ Could not publish key event, "
685 "status=%d", connection->getInputChannelName(), status);
686 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
687 return;
688 }
689 break;
690 }
691
692 case EventEntry::TYPE_MOTION: {
693 MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
694
695 // Apply target flags.
696 int32_t action = motionEntry->action;
697 if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700698 action = AMOTION_EVENT_ACTION_OUTSIDE;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700699 }
700 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700701 action = AMOTION_EVENT_ACTION_CANCEL;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700702 }
703
704 // If headMotionSample is non-NULL, then it points to the first new sample that we
705 // were unable to dispatch during the previous cycle so we resume dispatching from
706 // that point in the list of motion samples.
707 // Otherwise, we just start from the first sample of the motion event.
708 MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
709 if (! firstMotionSample) {
710 firstMotionSample = & motionEntry->firstSample;
711 }
712
Jeff Brownd3616592010-07-16 17:21:06 -0700713 // Set the X and Y offset depending on the input source.
714 float xOffset, yOffset;
715 if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
716 xOffset = dispatchEntry->xOffset;
717 yOffset = dispatchEntry->yOffset;
718 } else {
719 xOffset = 0.0f;
720 yOffset = 0.0f;
721 }
722
Jeff Brown46b9ac02010-04-22 18:58:52 -0700723 // Publish the motion event and the first motion sample.
724 status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700725 motionEntry->source, action, motionEntry->edgeFlags, motionEntry->metaState,
Jeff Brownd3616592010-07-16 17:21:06 -0700726 xOffset, yOffset,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700727 motionEntry->xPrecision, motionEntry->yPrecision,
728 motionEntry->downTime, firstMotionSample->eventTime,
729 motionEntry->pointerCount, motionEntry->pointerIds,
730 firstMotionSample->pointerCoords);
731
732 if (status) {
733 LOGE("channel '%s' ~ Could not publish motion event, "
734 "status=%d", connection->getInputChannelName(), status);
735 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
736 return;
737 }
738
739 // Append additional motion samples.
740 MotionSample* nextMotionSample = firstMotionSample->next;
741 for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
742 status = connection->inputPublisher.appendMotionSample(
743 nextMotionSample->eventTime, nextMotionSample->pointerCoords);
744 if (status == NO_MEMORY) {
745#if DEBUG_DISPATCH_CYCLE
746 LOGD("channel '%s' ~ Shared memory buffer full. Some motion samples will "
747 "be sent in the next dispatch cycle.",
748 connection->getInputChannelName());
749#endif
750 break;
751 }
752 if (status != OK) {
753 LOGE("channel '%s' ~ Could not append motion sample "
754 "for a reason other than out of memory, status=%d",
755 connection->getInputChannelName(), status);
756 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
757 return;
758 }
759 }
760
761 // Remember the next motion sample that we could not dispatch, in case we ran out
762 // of space in the shared memory buffer.
763 dispatchEntry->tailMotionSample = nextMotionSample;
764 break;
765 }
766
767 default: {
768 assert(false);
769 }
770 }
771
772 // Send the dispatch signal.
773 status = connection->inputPublisher.sendDispatchSignal();
774 if (status) {
775 LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
776 connection->getInputChannelName(), status);
777 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
778 return;
779 }
780
781 // Record information about the newly started dispatch cycle.
782 dispatchEntry->inProgress = true;
783
784 connection->lastEventTime = dispatchEntry->eventEntry->eventTime;
785 connection->lastDispatchTime = currentTime;
786
787 nsecs_t timeout = dispatchEntry->timeout;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700788 connection->setNextTimeoutTime(currentTime, timeout);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700789
790 // Notify other system components.
791 onDispatchCycleStartedLocked(currentTime, connection);
792}
793
Jeff Brown7fbdc842010-06-17 20:52:56 -0700794void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
795 const sp<Connection>& connection) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700796#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700797 LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
Jeff Brown46b9ac02010-04-22 18:58:52 -0700798 "%01.1fms since dispatch",
799 connection->getInputChannelName(),
800 connection->getEventLatencyMillis(currentTime),
801 connection->getDispatchLatencyMillis(currentTime));
802#endif
803
Jeff Brown9c3cda02010-06-15 01:31:58 -0700804 if (connection->status == Connection::STATUS_BROKEN
805 || connection->status == Connection::STATUS_ZOMBIE) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700806 return;
807 }
808
809 // Clear the pending timeout.
810 connection->nextTimeoutTime = LONG_LONG_MAX;
811
812 if (connection->status == Connection::STATUS_NOT_RESPONDING) {
813 // Recovering from an ANR.
814 connection->status = Connection::STATUS_NORMAL;
815
816 // Notify other system components.
817 onDispatchCycleFinishedLocked(currentTime, connection, true /*recoveredFromANR*/);
818 } else {
819 // Normal finish. Not much to do here.
820
821 // Notify other system components.
822 onDispatchCycleFinishedLocked(currentTime, connection, false /*recoveredFromANR*/);
823 }
824
825 // Reset the publisher since the event has been consumed.
826 // We do this now so that the publisher can release some of its internal resources
827 // while waiting for the next dispatch cycle to begin.
828 status_t status = connection->inputPublisher.reset();
829 if (status) {
830 LOGE("channel '%s' ~ Could not reset publisher, status=%d",
831 connection->getInputChannelName(), status);
832 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
833 return;
834 }
835
836 // Start the next dispatch cycle for this connection.
837 while (! connection->outboundQueue.isEmpty()) {
838 DispatchEntry* dispatchEntry = connection->outboundQueue.head.next;
839 if (dispatchEntry->inProgress) {
840 // Finish or resume current event in progress.
841 if (dispatchEntry->tailMotionSample) {
842 // We have a tail of undispatched motion samples.
843 // Reuse the same DispatchEntry and start a new cycle.
844 dispatchEntry->inProgress = false;
845 dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
846 dispatchEntry->tailMotionSample = NULL;
847 startDispatchCycleLocked(currentTime, connection);
848 return;
849 }
850 // Finished.
851 connection->outboundQueue.dequeueAtHead();
Jeff Brown6ec402b2010-07-28 15:48:59 -0700852 if (dispatchEntry->isSyncTarget()) {
853 decrementPendingSyncDispatchesLocked(dispatchEntry->eventEntry);
854 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700855 mAllocator.releaseDispatchEntry(dispatchEntry);
856 } else {
857 // If the head is not in progress, then we must have already dequeued the in
858 // progress event, which means we actually aborted it (due to ANR).
859 // So just start the next event for this connection.
860 startDispatchCycleLocked(currentTime, connection);
861 return;
862 }
863 }
864
865 // Outbound queue is empty, deactivate the connection.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700866 deactivateConnectionLocked(connection.get());
Jeff Brown46b9ac02010-04-22 18:58:52 -0700867}
868
Jeff Brown7fbdc842010-06-17 20:52:56 -0700869void InputDispatcher::timeoutDispatchCycleLocked(nsecs_t currentTime,
870 const sp<Connection>& connection) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700871#if DEBUG_DISPATCH_CYCLE
872 LOGD("channel '%s' ~ timeoutDispatchCycle",
873 connection->getInputChannelName());
874#endif
875
876 if (connection->status != Connection::STATUS_NORMAL) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700877 return;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700878 }
879
880 // Enter the not responding state.
881 connection->status = Connection::STATUS_NOT_RESPONDING;
882 connection->lastANRTime = currentTime;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700883
884 // Notify other system components.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700885 // This enqueues a command which will eventually either call
886 // resumeAfterTimeoutDispatchCycleLocked or abortDispatchCycleLocked.
Jeff Brown46b9ac02010-04-22 18:58:52 -0700887 onDispatchCycleANRLocked(currentTime, connection);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700888}
889
Jeff Brown7fbdc842010-06-17 20:52:56 -0700890void InputDispatcher::resumeAfterTimeoutDispatchCycleLocked(nsecs_t currentTime,
891 const sp<Connection>& connection, nsecs_t newTimeout) {
892#if DEBUG_DISPATCH_CYCLE
893 LOGD("channel '%s' ~ resumeAfterTimeoutDispatchCycleLocked",
894 connection->getInputChannelName());
895#endif
896
897 if (connection->status != Connection::STATUS_NOT_RESPONDING) {
898 return;
899 }
900
901 // Resume normal dispatch.
902 connection->status = Connection::STATUS_NORMAL;
903 connection->setNextTimeoutTime(currentTime, newTimeout);
904}
905
906void InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime,
907 const sp<Connection>& connection, bool broken) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700908#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700909 LOGD("channel '%s' ~ abortDispatchCycle - broken=%s",
Jeff Brown46b9ac02010-04-22 18:58:52 -0700910 connection->getInputChannelName(), broken ? "true" : "false");
911#endif
912
Jeff Brown46b9ac02010-04-22 18:58:52 -0700913 // Clear the pending timeout.
914 connection->nextTimeoutTime = LONG_LONG_MAX;
915
916 // Clear the outbound queue.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700917 if (! connection->outboundQueue.isEmpty()) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700918 do {
919 DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
Jeff Brown6ec402b2010-07-28 15:48:59 -0700920 if (dispatchEntry->isSyncTarget()) {
921 decrementPendingSyncDispatchesLocked(dispatchEntry->eventEntry);
922 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700923 mAllocator.releaseDispatchEntry(dispatchEntry);
924 } while (! connection->outboundQueue.isEmpty());
Jeff Brown46b9ac02010-04-22 18:58:52 -0700925
Jeff Brown7fbdc842010-06-17 20:52:56 -0700926 deactivateConnectionLocked(connection.get());
Jeff Brown9c3cda02010-06-15 01:31:58 -0700927 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700928
929 // Handle the case where the connection appears to be unrecoverably broken.
Jeff Brown9c3cda02010-06-15 01:31:58 -0700930 // Ignore already broken or zombie connections.
Jeff Brown46b9ac02010-04-22 18:58:52 -0700931 if (broken) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700932 if (connection->status == Connection::STATUS_NORMAL
933 || connection->status == Connection::STATUS_NOT_RESPONDING) {
934 connection->status = Connection::STATUS_BROKEN;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700935
Jeff Brown9c3cda02010-06-15 01:31:58 -0700936 // Notify other system components.
937 onDispatchCycleBrokenLocked(currentTime, connection);
938 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700939 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700940}
941
942bool InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
943 InputDispatcher* d = static_cast<InputDispatcher*>(data);
944
945 { // acquire lock
946 AutoMutex _l(d->mLock);
947
948 ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
949 if (connectionIndex < 0) {
950 LOGE("Received spurious receive callback for unknown input channel. "
951 "fd=%d, events=0x%x", receiveFd, events);
952 return false; // remove the callback
953 }
954
Jeff Brown7fbdc842010-06-17 20:52:56 -0700955 nsecs_t currentTime = now();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700956
957 sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
958 if (events & (POLLERR | POLLHUP | POLLNVAL)) {
959 LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
960 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700961 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700962 d->runCommandsLockedInterruptible();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700963 return false; // remove the callback
964 }
965
966 if (! (events & POLLIN)) {
967 LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
968 "events=0x%x", connection->getInputChannelName(), events);
969 return true;
970 }
971
972 status_t status = connection->inputPublisher.receiveFinishedSignal();
973 if (status) {
974 LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
975 connection->getInputChannelName(), status);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700976 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700977 d->runCommandsLockedInterruptible();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700978 return false; // remove the callback
979 }
980
Jeff Brown7fbdc842010-06-17 20:52:56 -0700981 d->finishDispatchCycleLocked(currentTime, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700982 d->runCommandsLockedInterruptible();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700983 return true;
984 } // release lock
985}
986
Jeff Brown9c3cda02010-06-15 01:31:58 -0700987void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700988#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown9c3cda02010-06-15 01:31:58 -0700989 LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700990#endif
991
992 bool wasEmpty;
993 { // acquire lock
994 AutoMutex _l(mLock);
995
Jeff Brown7fbdc842010-06-17 20:52:56 -0700996 ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700997
998 wasEmpty = mInboundQueue.isEmpty();
999 mInboundQueue.enqueueAtTail(newEntry);
1000 } // release lock
1001
1002 if (wasEmpty) {
1003 mPollLoop->wake();
1004 }
1005}
1006
Jeff Brown46b9ac02010-04-22 18:58:52 -07001007void InputDispatcher::notifyAppSwitchComing(nsecs_t eventTime) {
1008#if DEBUG_INBOUND_EVENT_DETAILS
1009 LOGD("notifyAppSwitchComing - eventTime=%lld", eventTime);
1010#endif
1011
1012 // Remove movement keys from the queue from most recent to least recent, stopping at the
1013 // first non-movement key.
1014 // TODO: Include a detailed description of why we do this...
1015
1016 { // acquire lock
1017 AutoMutex _l(mLock);
1018
1019 for (EventEntry* entry = mInboundQueue.tail.prev; entry != & mInboundQueue.head; ) {
1020 EventEntry* prev = entry->prev;
1021
1022 if (entry->type == EventEntry::TYPE_KEY) {
1023 KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
1024 if (isMovementKey(keyEntry->keyCode)) {
1025 LOGV("Dropping movement key during app switch: keyCode=%d, action=%d",
1026 keyEntry->keyCode, keyEntry->action);
1027 mInboundQueue.dequeue(keyEntry);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001028
1029 setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
1030
Jeff Brown46b9ac02010-04-22 18:58:52 -07001031 mAllocator.releaseKeyEntry(keyEntry);
1032 } else {
1033 // stop at last non-movement key
1034 break;
1035 }
1036 }
1037
1038 entry = prev;
1039 }
1040 } // release lock
1041}
1042
Jeff Brownc5ed5912010-07-14 18:48:53 -07001043void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Brown46b9ac02010-04-22 18:58:52 -07001044 uint32_t policyFlags, int32_t action, int32_t flags,
1045 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
1046#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brownc5ed5912010-07-14 18:48:53 -07001047 LOGD("notifyKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Brown46b9ac02010-04-22 18:58:52 -07001048 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
Jeff Brownc5ed5912010-07-14 18:48:53 -07001049 eventTime, deviceId, source, policyFlags, action, flags,
Jeff Brown46b9ac02010-04-22 18:58:52 -07001050 keyCode, scanCode, metaState, downTime);
1051#endif
1052
1053 bool wasEmpty;
1054 { // acquire lock
1055 AutoMutex _l(mLock);
1056
Jeff Brown7fbdc842010-06-17 20:52:56 -07001057 int32_t repeatCount = 0;
1058 KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -07001059 deviceId, source, policyFlags, action, flags, keyCode, scanCode,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001060 metaState, repeatCount, downTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001061
1062 wasEmpty = mInboundQueue.isEmpty();
1063 mInboundQueue.enqueueAtTail(newEntry);
1064 } // release lock
1065
1066 if (wasEmpty) {
1067 mPollLoop->wake();
1068 }
1069}
1070
Jeff Brownc5ed5912010-07-14 18:48:53 -07001071void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Brown46b9ac02010-04-22 18:58:52 -07001072 uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
1073 uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
1074 float xPrecision, float yPrecision, nsecs_t downTime) {
1075#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brownc5ed5912010-07-14 18:48:53 -07001076 LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Brown46b9ac02010-04-22 18:58:52 -07001077 "action=0x%x, metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, "
1078 "downTime=%lld",
Jeff Brownc5ed5912010-07-14 18:48:53 -07001079 eventTime, deviceId, source, policyFlags, action, metaState, edgeFlags,
Jeff Brown46b9ac02010-04-22 18:58:52 -07001080 xPrecision, yPrecision, downTime);
1081 for (uint32_t i = 0; i < pointerCount; i++) {
1082 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
1083 i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
1084 pointerCoords[i].pressure, pointerCoords[i].size);
1085 }
1086#endif
1087
1088 bool wasEmpty;
1089 { // acquire lock
1090 AutoMutex _l(mLock);
1091
1092 // Attempt batching and streaming of move events.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001093 if (action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001094 // BATCHING CASE
1095 //
1096 // Try to append a move sample to the tail of the inbound queue for this device.
1097 // Give up if we encounter a non-move motion event for this device since that
1098 // means we cannot append any new samples until a new motion event has started.
1099 for (EventEntry* entry = mInboundQueue.tail.prev;
1100 entry != & mInboundQueue.head; entry = entry->prev) {
1101 if (entry->type != EventEntry::TYPE_MOTION) {
1102 // Keep looking for motion events.
1103 continue;
1104 }
1105
1106 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
1107 if (motionEntry->deviceId != deviceId) {
1108 // Keep looking for this device.
1109 continue;
1110 }
1111
Jeff Brownc5ed5912010-07-14 18:48:53 -07001112 if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown7fbdc842010-06-17 20:52:56 -07001113 || motionEntry->pointerCount != pointerCount
1114 || motionEntry->isInjected()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001115 // Last motion event in the queue for this device is not compatible for
1116 // appending new samples. Stop here.
1117 goto NoBatchingOrStreaming;
1118 }
1119
1120 // The last motion event is a move and is compatible for appending.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001121 // Do the batching magic.
Jeff Brown7fbdc842010-06-17 20:52:56 -07001122 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001123#if DEBUG_BATCHING
1124 LOGD("Appended motion sample onto batch for most recent "
1125 "motion event for this device in the inbound queue.");
1126#endif
Jeff Brown9c3cda02010-06-15 01:31:58 -07001127
1128 // Sanity check for special case because dispatch is interruptible.
1129 // The dispatch logic is partially interruptible and releases its lock while
1130 // identifying targets. However, as soon as the targets have been identified,
1131 // the dispatcher proceeds to write a dispatch entry into all relevant outbound
1132 // queues and then promptly removes the motion entry from the queue.
1133 //
1134 // Consequently, we should never observe the case where the inbound queue contains
1135 // an in-progress motion entry unless the current input targets are invalid
1136 // (currently being computed). Check for this!
1137 assert(! (motionEntry->dispatchInProgress && mCurrentInputTargetsValid));
1138
1139 return; // done!
Jeff Brown46b9ac02010-04-22 18:58:52 -07001140 }
1141
1142 // STREAMING CASE
1143 //
1144 // There is no pending motion event (of any kind) for this device in the inbound queue.
1145 // Search the outbound queues for a synchronously dispatched motion event for this
1146 // device. If found, then we append the new sample to that event and then try to
1147 // push it out to all current targets. It is possible that some targets will already
1148 // have consumed the motion event. This case is automatically handled by the
1149 // logic in prepareDispatchCycleLocked by tracking where resumption takes place.
1150 //
1151 // The reason we look for a synchronously dispatched motion event is because we
1152 // want to be sure that no other motion events have been dispatched since the move.
1153 // It's also convenient because it means that the input targets are still valid.
1154 // This code could be improved to support streaming of asynchronously dispatched
1155 // motion events (which might be significantly more efficient) but it may become
1156 // a little more complicated as a result.
1157 //
1158 // Note: This code crucially depends on the invariant that an outbound queue always
1159 // contains at most one synchronous event and it is always last (but it might
1160 // not be first!).
Jeff Brown9c3cda02010-06-15 01:31:58 -07001161 if (mCurrentInputTargetsValid) {
1162 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1163 Connection* connection = mActiveConnections.itemAt(i);
1164 if (! connection->outboundQueue.isEmpty()) {
1165 DispatchEntry* dispatchEntry = connection->outboundQueue.tail.prev;
Jeff Brown6ec402b2010-07-28 15:48:59 -07001166 if (dispatchEntry->isSyncTarget()) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001167 if (dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION) {
1168 goto NoBatchingOrStreaming;
1169 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001170
Jeff Brown9c3cda02010-06-15 01:31:58 -07001171 MotionEntry* syncedMotionEntry = static_cast<MotionEntry*>(
1172 dispatchEntry->eventEntry);
Jeff Brownc5ed5912010-07-14 18:48:53 -07001173 if (syncedMotionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown9c3cda02010-06-15 01:31:58 -07001174 || syncedMotionEntry->deviceId != deviceId
Jeff Brown7fbdc842010-06-17 20:52:56 -07001175 || syncedMotionEntry->pointerCount != pointerCount
1176 || syncedMotionEntry->isInjected()) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001177 goto NoBatchingOrStreaming;
1178 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001179
Jeff Brown9c3cda02010-06-15 01:31:58 -07001180 // Found synced move entry. Append sample and resume dispatch.
1181 mAllocator.appendMotionSample(syncedMotionEntry, eventTime,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001182 pointerCoords);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001183 #if DEBUG_BATCHING
1184 LOGD("Appended motion sample onto batch for most recent synchronously "
1185 "dispatched motion event for this device in the outbound queues.");
1186 #endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001187 nsecs_t currentTime = now();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001188 dispatchEventToCurrentInputTargetsLocked(currentTime, syncedMotionEntry,
1189 true /*resumeWithAppendedMotionSample*/);
1190
1191 runCommandsLockedInterruptible();
1192 return; // done!
1193 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001194 }
1195 }
1196 }
1197
1198NoBatchingOrStreaming:;
1199 }
1200
1201 // Just enqueue a new motion event.
Jeff Brown7fbdc842010-06-17 20:52:56 -07001202 MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -07001203 deviceId, source, policyFlags, action, metaState, edgeFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001204 xPrecision, yPrecision, downTime,
1205 pointerCount, pointerIds, pointerCoords);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001206
1207 wasEmpty = mInboundQueue.isEmpty();
1208 mInboundQueue.enqueueAtTail(newEntry);
1209 } // release lock
1210
1211 if (wasEmpty) {
1212 mPollLoop->wake();
1213 }
1214}
1215
Jeff Brown7fbdc842010-06-17 20:52:56 -07001216int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
Jeff Brown6ec402b2010-07-28 15:48:59 -07001217 int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001218#if DEBUG_INBOUND_EVENT_DETAILS
1219 LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
Jeff Brown6ec402b2010-07-28 15:48:59 -07001220 "syncMode=%d, timeoutMillis=%d",
1221 event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001222#endif
1223
1224 nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
1225
1226 EventEntry* injectedEntry;
1227 bool wasEmpty;
1228 { // acquire lock
1229 AutoMutex _l(mLock);
1230
1231 injectedEntry = createEntryFromInputEventLocked(event);
1232 injectedEntry->refCount += 1;
1233 injectedEntry->injectorPid = injectorPid;
1234 injectedEntry->injectorUid = injectorUid;
1235
Jeff Brown6ec402b2010-07-28 15:48:59 -07001236 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
1237 injectedEntry->injectionIsAsync = true;
1238 }
1239
Jeff Brown7fbdc842010-06-17 20:52:56 -07001240 wasEmpty = mInboundQueue.isEmpty();
1241 mInboundQueue.enqueueAtTail(injectedEntry);
1242
1243 } // release lock
1244
1245 if (wasEmpty) {
1246 mPollLoop->wake();
1247 }
1248
1249 int32_t injectionResult;
1250 { // acquire lock
1251 AutoMutex _l(mLock);
1252
Jeff Brown6ec402b2010-07-28 15:48:59 -07001253 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
1254 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1255 } else {
1256 for (;;) {
1257 injectionResult = injectedEntry->injectionResult;
1258 if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
1259 break;
1260 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07001261
Jeff Brown7fbdc842010-06-17 20:52:56 -07001262 nsecs_t remainingTimeout = endTime - now();
1263 if (remainingTimeout <= 0) {
Jeff Brown6ec402b2010-07-28 15:48:59 -07001264#if DEBUG_INJECTION
1265 LOGD("injectInputEvent - Timed out waiting for injection result "
1266 "to become available.");
1267#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001268 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1269 break;
1270 }
1271
Jeff Brown6ec402b2010-07-28 15:48:59 -07001272 mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
1273 }
1274
1275 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
1276 && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
1277 while (injectedEntry->pendingSyncDispatches != 0) {
1278#if DEBUG_INJECTION
1279 LOGD("injectInputEvent - Waiting for %d pending synchronous dispatches.",
1280 injectedEntry->pendingSyncDispatches);
1281#endif
1282 nsecs_t remainingTimeout = endTime - now();
1283 if (remainingTimeout <= 0) {
1284#if DEBUG_INJECTION
1285 LOGD("injectInputEvent - Timed out waiting for pending synchronous "
1286 "dispatches to finish.");
1287#endif
1288 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1289 break;
1290 }
1291
1292 mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
1293 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07001294 }
1295 }
1296
1297 mAllocator.releaseEventEntry(injectedEntry);
1298 } // release lock
1299
Jeff Brown6ec402b2010-07-28 15:48:59 -07001300#if DEBUG_INJECTION
1301 LOGD("injectInputEvent - Finished with result %d. "
1302 "injectorPid=%d, injectorUid=%d",
1303 injectionResult, injectorPid, injectorUid);
1304#endif
1305
Jeff Brown7fbdc842010-06-17 20:52:56 -07001306 return injectionResult;
1307}
1308
1309void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
1310 if (entry->isInjected()) {
1311#if DEBUG_INJECTION
1312 LOGD("Setting input event injection result to %d. "
1313 "injectorPid=%d, injectorUid=%d",
1314 injectionResult, entry->injectorPid, entry->injectorUid);
1315#endif
1316
Jeff Brown6ec402b2010-07-28 15:48:59 -07001317 if (entry->injectionIsAsync) {
1318 // Log the outcome since the injector did not wait for the injection result.
1319 switch (injectionResult) {
1320 case INPUT_EVENT_INJECTION_SUCCEEDED:
1321 LOGV("Asynchronous input event injection succeeded.");
1322 break;
1323 case INPUT_EVENT_INJECTION_FAILED:
1324 LOGW("Asynchronous input event injection failed.");
1325 break;
1326 case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
1327 LOGW("Asynchronous input event injection permission denied.");
1328 break;
1329 case INPUT_EVENT_INJECTION_TIMED_OUT:
1330 LOGW("Asynchronous input event injection timed out.");
1331 break;
1332 }
1333 }
1334
Jeff Brown7fbdc842010-06-17 20:52:56 -07001335 entry->injectionResult = injectionResult;
1336 mInjectionResultAvailableCondition.broadcast();
1337 }
1338}
1339
Jeff Brown6ec402b2010-07-28 15:48:59 -07001340void InputDispatcher::decrementPendingSyncDispatchesLocked(EventEntry* entry) {
1341 entry->pendingSyncDispatches -= 1;
1342
1343 if (entry->isInjected() && entry->pendingSyncDispatches == 0) {
1344 mInjectionSyncFinishedCondition.broadcast();
1345 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07001346}
1347
1348InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked(
1349 const InputEvent* event) {
1350 switch (event->getType()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001351 case AINPUT_EVENT_TYPE_KEY: {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001352 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
1353 uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
1354
1355 KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
Jeff Brownc5ed5912010-07-14 18:48:53 -07001356 keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001357 keyEvent->getAction(), keyEvent->getFlags(),
1358 keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
1359 keyEvent->getRepeatCount(), keyEvent->getDownTime());
1360 return keyEntry;
1361 }
1362
Jeff Brownc5ed5912010-07-14 18:48:53 -07001363 case AINPUT_EVENT_TYPE_MOTION: {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001364 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
1365 uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
1366
1367 const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
1368 const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
1369 size_t pointerCount = motionEvent->getPointerCount();
1370
1371 MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
Jeff Brownc5ed5912010-07-14 18:48:53 -07001372 motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001373 motionEvent->getAction(), motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
1374 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
1375 motionEvent->getDownTime(), uint32_t(pointerCount),
1376 motionEvent->getPointerIds(), samplePointerCoords);
1377 for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
1378 sampleEventTimes += 1;
1379 samplePointerCoords += pointerCount;
1380 mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
1381 }
1382 return motionEntry;
1383 }
1384
1385 default:
1386 assert(false);
1387 return NULL;
1388 }
1389}
1390
Jeff Brown46b9ac02010-04-22 18:58:52 -07001391void InputDispatcher::resetKeyRepeatLocked() {
1392 if (mKeyRepeatState.lastKeyEntry) {
1393 mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
1394 mKeyRepeatState.lastKeyEntry = NULL;
1395 }
1396}
1397
Jeff Brown349703e2010-06-22 01:27:15 -07001398void InputDispatcher::preemptInputDispatch() {
1399#if DEBUG_DISPATCH_CYCLE
1400 LOGD("preemptInputDispatch");
1401#endif
1402
1403 bool preemptedOne = false;
1404 { // acquire lock
1405 AutoMutex _l(mLock);
1406
1407 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1408 Connection* connection = mActiveConnections[i];
1409 if (connection->hasPendingSyncTarget()) {
1410#if DEBUG_DISPATCH_CYCLE
1411 LOGD("channel '%s' ~ Preempted pending synchronous dispatch",
1412 connection->getInputChannelName());
1413#endif
1414 connection->outboundQueue.tail.prev->targetFlags &= ~ InputTarget::FLAG_SYNC;
1415 preemptedOne = true;
1416 }
1417 }
1418 } // release lock
1419
1420 if (preemptedOne) {
1421 // Wake up the poll loop so it can get a head start dispatching the next event.
1422 mPollLoop->wake();
1423 }
1424}
1425
Jeff Brown46b9ac02010-04-22 18:58:52 -07001426status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001427#if DEBUG_REGISTRATION
Jeff Brown349703e2010-06-22 01:27:15 -07001428 LOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().string());
Jeff Brown9c3cda02010-06-15 01:31:58 -07001429#endif
1430
Jeff Brown46b9ac02010-04-22 18:58:52 -07001431 { // acquire lock
1432 AutoMutex _l(mLock);
1433
Jeff Brown2cbecea2010-08-17 15:59:26 -07001434 if (getConnectionIndex(inputChannel) >= 0) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001435 LOGW("Attempted to register already registered input channel '%s'",
1436 inputChannel->getName().string());
1437 return BAD_VALUE;
1438 }
1439
1440 sp<Connection> connection = new Connection(inputChannel);
1441 status_t status = connection->initialize();
1442 if (status) {
1443 LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
1444 inputChannel->getName().string(), status);
1445 return status;
1446 }
1447
Jeff Brown2cbecea2010-08-17 15:59:26 -07001448 int32_t receiveFd = inputChannel->getReceivePipeFd();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001449 mConnectionsByReceiveFd.add(receiveFd, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001450
Jeff Brown2cbecea2010-08-17 15:59:26 -07001451 mPollLoop->setCallback(receiveFd, POLLIN, handleReceiveCallback, this);
1452
Jeff Brown9c3cda02010-06-15 01:31:58 -07001453 runCommandsLockedInterruptible();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001454 } // release lock
Jeff Brown46b9ac02010-04-22 18:58:52 -07001455 return OK;
1456}
1457
1458status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001459#if DEBUG_REGISTRATION
Jeff Brown349703e2010-06-22 01:27:15 -07001460 LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
Jeff Brown9c3cda02010-06-15 01:31:58 -07001461#endif
1462
Jeff Brown46b9ac02010-04-22 18:58:52 -07001463 { // acquire lock
1464 AutoMutex _l(mLock);
1465
Jeff Brown2cbecea2010-08-17 15:59:26 -07001466 ssize_t connectionIndex = getConnectionIndex(inputChannel);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001467 if (connectionIndex < 0) {
1468 LOGW("Attempted to unregister already unregistered input channel '%s'",
1469 inputChannel->getName().string());
1470 return BAD_VALUE;
1471 }
1472
1473 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1474 mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
1475
1476 connection->status = Connection::STATUS_ZOMBIE;
1477
Jeff Brown2cbecea2010-08-17 15:59:26 -07001478 mPollLoop->removeCallback(inputChannel->getReceivePipeFd());
1479
Jeff Brown7fbdc842010-06-17 20:52:56 -07001480 nsecs_t currentTime = now();
1481 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001482
1483 runCommandsLockedInterruptible();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001484 } // release lock
1485
Jeff Brown46b9ac02010-04-22 18:58:52 -07001486 // Wake the poll loop because removing the connection may have changed the current
1487 // synchronization state.
1488 mPollLoop->wake();
1489 return OK;
1490}
1491
Jeff Brown2cbecea2010-08-17 15:59:26 -07001492ssize_t InputDispatcher::getConnectionIndex(const sp<InputChannel>& inputChannel) {
1493 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(inputChannel->getReceivePipeFd());
1494 if (connectionIndex >= 0) {
1495 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1496 if (connection->inputChannel.get() == inputChannel.get()) {
1497 return connectionIndex;
1498 }
1499 }
1500
1501 return -1;
1502}
1503
Jeff Brown46b9ac02010-04-22 18:58:52 -07001504void InputDispatcher::activateConnectionLocked(Connection* connection) {
1505 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1506 if (mActiveConnections.itemAt(i) == connection) {
1507 return;
1508 }
1509 }
1510 mActiveConnections.add(connection);
1511}
1512
1513void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
1514 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1515 if (mActiveConnections.itemAt(i) == connection) {
1516 mActiveConnections.removeAt(i);
1517 return;
1518 }
1519 }
1520}
1521
Jeff Brown9c3cda02010-06-15 01:31:58 -07001522void InputDispatcher::onDispatchCycleStartedLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07001523 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001524}
1525
Jeff Brown9c3cda02010-06-15 01:31:58 -07001526void InputDispatcher::onDispatchCycleFinishedLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07001527 nsecs_t currentTime, const sp<Connection>& connection, bool recoveredFromANR) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001528 if (recoveredFromANR) {
1529 LOGI("channel '%s' ~ Recovered from ANR. %01.1fms since event, "
1530 "%01.1fms since dispatch, %01.1fms since ANR",
1531 connection->getInputChannelName(),
1532 connection->getEventLatencyMillis(currentTime),
1533 connection->getDispatchLatencyMillis(currentTime),
1534 connection->getANRLatencyMillis(currentTime));
1535
Jeff Brown9c3cda02010-06-15 01:31:58 -07001536 CommandEntry* commandEntry = postCommandLocked(
1537 & InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001538 commandEntry->connection = connection;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001539 }
1540}
1541
Jeff Brown9c3cda02010-06-15 01:31:58 -07001542void InputDispatcher::onDispatchCycleANRLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07001543 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001544 LOGI("channel '%s' ~ Not responding! %01.1fms since event, %01.1fms since dispatch",
1545 connection->getInputChannelName(),
1546 connection->getEventLatencyMillis(currentTime),
1547 connection->getDispatchLatencyMillis(currentTime));
1548
Jeff Brown9c3cda02010-06-15 01:31:58 -07001549 CommandEntry* commandEntry = postCommandLocked(
1550 & InputDispatcher::doNotifyInputChannelANRLockedInterruptible);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001551 commandEntry->connection = connection;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001552}
1553
Jeff Brown9c3cda02010-06-15 01:31:58 -07001554void InputDispatcher::onDispatchCycleBrokenLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07001555 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001556 LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
1557 connection->getInputChannelName());
1558
Jeff Brown9c3cda02010-06-15 01:31:58 -07001559 CommandEntry* commandEntry = postCommandLocked(
1560 & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001561 commandEntry->connection = connection;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001562}
1563
Jeff Brown9c3cda02010-06-15 01:31:58 -07001564void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
1565 CommandEntry* commandEntry) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001566 sp<Connection> connection = commandEntry->connection;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001567
Jeff Brown7fbdc842010-06-17 20:52:56 -07001568 if (connection->status != Connection::STATUS_ZOMBIE) {
1569 mLock.unlock();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001570
Jeff Brown7fbdc842010-06-17 20:52:56 -07001571 mPolicy->notifyInputChannelBroken(connection->inputChannel);
1572
1573 mLock.lock();
1574 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001575}
1576
1577void InputDispatcher::doNotifyInputChannelANRLockedInterruptible(
1578 CommandEntry* commandEntry) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001579 sp<Connection> connection = commandEntry->connection;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001580
Jeff Brown7fbdc842010-06-17 20:52:56 -07001581 if (connection->status != Connection::STATUS_ZOMBIE) {
1582 mLock.unlock();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001583
Jeff Brown7fbdc842010-06-17 20:52:56 -07001584 nsecs_t newTimeout;
1585 bool resume = mPolicy->notifyInputChannelANR(connection->inputChannel, newTimeout);
1586
1587 mLock.lock();
1588
1589 nsecs_t currentTime = now();
1590 if (resume) {
1591 resumeAfterTimeoutDispatchCycleLocked(currentTime, connection, newTimeout);
1592 } else {
1593 abortDispatchCycleLocked(currentTime, connection, false /*(not) broken*/);
1594 }
1595 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001596}
1597
1598void InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible(
1599 CommandEntry* commandEntry) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001600 sp<Connection> connection = commandEntry->connection;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001601
Jeff Brown7fbdc842010-06-17 20:52:56 -07001602 if (connection->status != Connection::STATUS_ZOMBIE) {
1603 mLock.unlock();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001604
Jeff Brown7fbdc842010-06-17 20:52:56 -07001605 mPolicy->notifyInputChannelRecoveredFromANR(connection->inputChannel);
1606
1607 mLock.lock();
1608 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001609}
1610
1611
Jeff Brown46b9ac02010-04-22 18:58:52 -07001612// --- InputDispatcher::Allocator ---
1613
1614InputDispatcher::Allocator::Allocator() {
1615}
1616
Jeff Brown7fbdc842010-06-17 20:52:56 -07001617void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
1618 nsecs_t eventTime) {
1619 entry->type = type;
1620 entry->refCount = 1;
1621 entry->dispatchInProgress = false;
Christopher Tatee91a5db2010-06-23 16:50:30 -07001622 entry->eventTime = eventTime;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001623 entry->injectionResult = INPUT_EVENT_INJECTION_PENDING;
Jeff Brown6ec402b2010-07-28 15:48:59 -07001624 entry->injectionIsAsync = false;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001625 entry->injectorPid = -1;
1626 entry->injectorUid = -1;
Jeff Brown6ec402b2010-07-28 15:48:59 -07001627 entry->pendingSyncDispatches = 0;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001628}
1629
Jeff Brown46b9ac02010-04-22 18:58:52 -07001630InputDispatcher::ConfigurationChangedEntry*
Jeff Brown7fbdc842010-06-17 20:52:56 -07001631InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001632 ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
Jeff Brown7fbdc842010-06-17 20:52:56 -07001633 initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001634 return entry;
1635}
1636
Jeff Brown7fbdc842010-06-17 20:52:56 -07001637InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -07001638 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001639 int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
1640 int32_t repeatCount, nsecs_t downTime) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001641 KeyEntry* entry = mKeyEntryPool.alloc();
Jeff Brown7fbdc842010-06-17 20:52:56 -07001642 initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime);
1643
1644 entry->deviceId = deviceId;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001645 entry->source = source;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001646 entry->policyFlags = policyFlags;
1647 entry->action = action;
1648 entry->flags = flags;
1649 entry->keyCode = keyCode;
1650 entry->scanCode = scanCode;
1651 entry->metaState = metaState;
1652 entry->repeatCount = repeatCount;
1653 entry->downTime = downTime;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001654 return entry;
1655}
1656
Jeff Brown7fbdc842010-06-17 20:52:56 -07001657InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -07001658 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001659 int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
1660 nsecs_t downTime, uint32_t pointerCount,
1661 const int32_t* pointerIds, const PointerCoords* pointerCoords) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001662 MotionEntry* entry = mMotionEntryPool.alloc();
Jeff Brown7fbdc842010-06-17 20:52:56 -07001663 initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime);
1664
1665 entry->eventTime = eventTime;
1666 entry->deviceId = deviceId;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001667 entry->source = source;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001668 entry->policyFlags = policyFlags;
1669 entry->action = action;
1670 entry->metaState = metaState;
1671 entry->edgeFlags = edgeFlags;
1672 entry->xPrecision = xPrecision;
1673 entry->yPrecision = yPrecision;
1674 entry->downTime = downTime;
1675 entry->pointerCount = pointerCount;
1676 entry->firstSample.eventTime = eventTime;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001677 entry->firstSample.next = NULL;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001678 entry->lastSample = & entry->firstSample;
1679 for (uint32_t i = 0; i < pointerCount; i++) {
1680 entry->pointerIds[i] = pointerIds[i];
1681 entry->firstSample.pointerCoords[i] = pointerCoords[i];
1682 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001683 return entry;
1684}
1685
1686InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
1687 EventEntry* eventEntry) {
1688 DispatchEntry* entry = mDispatchEntryPool.alloc();
1689 entry->eventEntry = eventEntry;
1690 eventEntry->refCount += 1;
1691 return entry;
1692}
1693
Jeff Brown9c3cda02010-06-15 01:31:58 -07001694InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
1695 CommandEntry* entry = mCommandEntryPool.alloc();
1696 entry->command = command;
1697 return entry;
1698}
1699
Jeff Brown46b9ac02010-04-22 18:58:52 -07001700void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
1701 switch (entry->type) {
1702 case EventEntry::TYPE_CONFIGURATION_CHANGED:
1703 releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
1704 break;
1705 case EventEntry::TYPE_KEY:
1706 releaseKeyEntry(static_cast<KeyEntry*>(entry));
1707 break;
1708 case EventEntry::TYPE_MOTION:
1709 releaseMotionEntry(static_cast<MotionEntry*>(entry));
1710 break;
1711 default:
1712 assert(false);
1713 break;
1714 }
1715}
1716
1717void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
1718 ConfigurationChangedEntry* entry) {
1719 entry->refCount -= 1;
1720 if (entry->refCount == 0) {
1721 mConfigurationChangeEntryPool.free(entry);
1722 } else {
1723 assert(entry->refCount > 0);
1724 }
1725}
1726
1727void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
1728 entry->refCount -= 1;
1729 if (entry->refCount == 0) {
1730 mKeyEntryPool.free(entry);
1731 } else {
1732 assert(entry->refCount > 0);
1733 }
1734}
1735
1736void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
1737 entry->refCount -= 1;
1738 if (entry->refCount == 0) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001739 for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
1740 MotionSample* next = sample->next;
1741 mMotionSamplePool.free(sample);
1742 sample = next;
1743 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001744 mMotionEntryPool.free(entry);
1745 } else {
1746 assert(entry->refCount > 0);
1747 }
1748}
1749
1750void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
1751 releaseEventEntry(entry->eventEntry);
1752 mDispatchEntryPool.free(entry);
1753}
1754
Jeff Brown9c3cda02010-06-15 01:31:58 -07001755void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
1756 mCommandEntryPool.free(entry);
1757}
1758
Jeff Brown46b9ac02010-04-22 18:58:52 -07001759void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001760 nsecs_t eventTime, const PointerCoords* pointerCoords) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001761 MotionSample* sample = mMotionSamplePool.alloc();
1762 sample->eventTime = eventTime;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001763 uint32_t pointerCount = motionEntry->pointerCount;
1764 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001765 sample->pointerCoords[i] = pointerCoords[i];
1766 }
1767
1768 sample->next = NULL;
1769 motionEntry->lastSample->next = sample;
1770 motionEntry->lastSample = sample;
1771}
1772
Jeff Brownae9fc032010-08-18 15:51:08 -07001773// --- InputDispatcher::MotionEntry ---
1774
1775uint32_t InputDispatcher::MotionEntry::countSamples() const {
1776 uint32_t count = 1;
1777 for (MotionSample* sample = firstSample.next; sample != NULL; sample = sample->next) {
1778 count += 1;
1779 }
1780 return count;
1781}
1782
Jeff Brown46b9ac02010-04-22 18:58:52 -07001783// --- InputDispatcher::Connection ---
1784
1785InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
1786 status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
1787 nextTimeoutTime(LONG_LONG_MAX),
1788 lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX),
1789 lastANRTime(LONG_LONG_MAX) {
1790}
1791
1792InputDispatcher::Connection::~Connection() {
1793}
1794
1795status_t InputDispatcher::Connection::initialize() {
1796 return inputPublisher.initialize();
1797}
1798
Jeff Brown7fbdc842010-06-17 20:52:56 -07001799void InputDispatcher::Connection::setNextTimeoutTime(nsecs_t currentTime, nsecs_t timeout) {
1800 nextTimeoutTime = (timeout >= 0) ? currentTime + timeout : LONG_LONG_MAX;
1801}
1802
Jeff Brown9c3cda02010-06-15 01:31:58 -07001803const char* InputDispatcher::Connection::getStatusLabel() const {
1804 switch (status) {
1805 case STATUS_NORMAL:
1806 return "NORMAL";
1807
1808 case STATUS_BROKEN:
1809 return "BROKEN";
1810
1811 case STATUS_NOT_RESPONDING:
1812 return "NOT_RESPONDING";
1813
1814 case STATUS_ZOMBIE:
1815 return "ZOMBIE";
1816
1817 default:
1818 return "UNKNOWN";
1819 }
1820}
1821
Jeff Brown46b9ac02010-04-22 18:58:52 -07001822InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
1823 const EventEntry* eventEntry) const {
1824 for (DispatchEntry* dispatchEntry = outboundQueue.tail.prev;
1825 dispatchEntry != & outboundQueue.head; dispatchEntry = dispatchEntry->prev) {
1826 if (dispatchEntry->eventEntry == eventEntry) {
1827 return dispatchEntry;
1828 }
1829 }
1830 return NULL;
1831}
1832
Jeff Brown9c3cda02010-06-15 01:31:58 -07001833// --- InputDispatcher::CommandEntry ---
1834
1835InputDispatcher::CommandEntry::CommandEntry() {
1836}
1837
1838InputDispatcher::CommandEntry::~CommandEntry() {
1839}
1840
Jeff Brown46b9ac02010-04-22 18:58:52 -07001841
1842// --- InputDispatcherThread ---
1843
1844InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
1845 Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
1846}
1847
1848InputDispatcherThread::~InputDispatcherThread() {
1849}
1850
1851bool InputDispatcherThread::threadLoop() {
1852 mDispatcher->dispatchOnce();
1853 return true;
1854}
1855
1856} // namespace android