blob: 67138174cafebd572c984e220c242c104b27f56b [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 Browna665ca82010-09-08 11:49:43 -070034// Log debug messages about input focus tracking.
35#define DEBUG_FOCUS 0
36
37// Log debug messages about the app switch latency optimization.
38#define DEBUG_APP_SWITCH 0
39
Jeff Browne839a582010-04-22 18:58:52 -070040#include <cutils/log.h>
41#include <ui/InputDispatcher.h>
Jeff Browna665ca82010-09-08 11:49:43 -070042#include <ui/PowerManager.h>
Jeff Browne839a582010-04-22 18:58:52 -070043
44#include <stddef.h>
45#include <unistd.h>
Jeff Browne839a582010-04-22 18:58:52 -070046#include <errno.h>
47#include <limits.h>
Jeff Browne839a582010-04-22 18:58:52 -070048
49namespace android {
50
Jeff Browna665ca82010-09-08 11:49:43 -070051// Delay between reporting long touch events to the power manager.
52const nsecs_t EVENT_IGNORE_DURATION = 300 * 1000000LL; // 300 ms
53
54// Default input dispatching timeout if there is no focused application or paused window
55// from which to determine an appropriate dispatching timeout.
56const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
57
58// Amount of time to allow for all pending events to be processed when an app switch
59// key is on the way. This is used to preempt input dispatch and drop input events
60// when an application takes too long to respond and the user has pressed an app switch key.
61const nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
62
Jeff Browne839a582010-04-22 18:58:52 -070063
Jeff Brown51d45a72010-06-17 20:52:56 -070064static inline nsecs_t now() {
65 return systemTime(SYSTEM_TIME_MONOTONIC);
66}
67
Jeff Browna665ca82010-09-08 11:49:43 -070068static inline const char* toString(bool value) {
69 return value ? "true" : "false";
70}
71
72
73// --- InputWindow ---
74
75bool InputWindow::visibleFrameIntersects(const InputWindow* other) const {
76 return visibleFrameRight > other->visibleFrameLeft
77 && visibleFrameLeft < other->visibleFrameRight
78 && visibleFrameBottom > other->visibleFrameTop
79 && visibleFrameTop < other->visibleFrameBottom;
80}
81
82bool InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
83 return x >= touchableAreaLeft && x <= touchableAreaRight
84 && y >= touchableAreaTop && y <= touchableAreaBottom;
85}
86
87
Jeff Browne839a582010-04-22 18:58:52 -070088// --- InputDispatcher ---
89
Jeff Brown54bc2812010-06-15 01:31:58 -070090InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
Jeff Browna665ca82010-09-08 11:49:43 -070091 mPolicy(policy),
92 mPendingEvent(NULL), mAppSwitchDueTime(LONG_LONG_MAX),
93 mDispatchEnabled(true), mDispatchFrozen(false),
94 mFocusedWindow(NULL), mTouchDown(false), mTouchedWindow(NULL),
95 mFocusedApplication(NULL),
96 mCurrentInputTargetsValid(false),
97 mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
Jeff Brown59abe7e2010-09-13 23:17:30 -070098 mLooper = new Looper(false);
Jeff Browne839a582010-04-22 18:58:52 -070099
Jeff Browna665ca82010-09-08 11:49:43 -0700100 mInboundQueue.headSentinel.refCount = -1;
101 mInboundQueue.headSentinel.type = EventEntry::TYPE_SENTINEL;
102 mInboundQueue.headSentinel.eventTime = LONG_LONG_MIN;
Jeff Browne839a582010-04-22 18:58:52 -0700103
Jeff Browna665ca82010-09-08 11:49:43 -0700104 mInboundQueue.tailSentinel.refCount = -1;
105 mInboundQueue.tailSentinel.type = EventEntry::TYPE_SENTINEL;
106 mInboundQueue.tailSentinel.eventTime = LONG_LONG_MAX;
Jeff Browne839a582010-04-22 18:58:52 -0700107
108 mKeyRepeatState.lastKeyEntry = NULL;
Jeff Brown54bc2812010-06-15 01:31:58 -0700109
Jeff Brown542412c2010-08-18 15:51:08 -0700110 int32_t maxEventsPerSecond = policy->getMaxEventsPerSecond();
111 mThrottleState.minTimeBetweenEvents = 1000000000LL / maxEventsPerSecond;
112 mThrottleState.lastDeviceId = -1;
113
114#if DEBUG_THROTTLING
115 mThrottleState.originalSampleCount = 0;
116 LOGD("Throttling - Max events per second = %d", maxEventsPerSecond);
117#endif
Jeff Browne839a582010-04-22 18:58:52 -0700118}
119
120InputDispatcher::~InputDispatcher() {
Jeff Browna665ca82010-09-08 11:49:43 -0700121 { // acquire lock
122 AutoMutex _l(mLock);
123
124 resetKeyRepeatLocked();
125 releasePendingEventLocked(true);
126 drainInboundQueueLocked();
127 }
Jeff Browne839a582010-04-22 18:58:52 -0700128
129 while (mConnectionsByReceiveFd.size() != 0) {
130 unregisterInputChannel(mConnectionsByReceiveFd.valueAt(0)->inputChannel);
131 }
Jeff Browne839a582010-04-22 18:58:52 -0700132}
133
134void InputDispatcher::dispatchOnce() {
Jeff Brown54bc2812010-06-15 01:31:58 -0700135 nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
Jeff Brown61ce3982010-09-07 10:44:57 -0700136 nsecs_t keyRepeatDelay = mPolicy->getKeyRepeatDelay();
Jeff Browne839a582010-04-22 18:58:52 -0700137
Jeff Browne839a582010-04-22 18:58:52 -0700138 nsecs_t nextWakeupTime = LONG_LONG_MAX;
139 { // acquire lock
140 AutoMutex _l(mLock);
Jeff Browna665ca82010-09-08 11:49:43 -0700141 dispatchOnceInnerLocked(keyRepeatTimeout, keyRepeatDelay, & nextWakeupTime);
Jeff Browne839a582010-04-22 18:58:52 -0700142
Jeff Browna665ca82010-09-08 11:49:43 -0700143 if (runCommandsLockedInterruptible()) {
144 nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
Jeff Browne839a582010-04-22 18:58:52 -0700145 }
Jeff Browne839a582010-04-22 18:58:52 -0700146 } // release lock
147
Jeff Browna665ca82010-09-08 11:49:43 -0700148 // Wait for callback or timeout or wake. (make sure we round up, not down)
149 nsecs_t currentTime = now();
150 int32_t timeoutMillis;
151 if (nextWakeupTime > currentTime) {
152 uint64_t timeout = uint64_t(nextWakeupTime - currentTime);
153 timeout = (timeout + 999999LL) / 1000000LL;
154 timeoutMillis = timeout > INT_MAX ? -1 : int32_t(timeout);
155 } else {
156 timeoutMillis = 0;
157 }
158
Jeff Brown59abe7e2010-09-13 23:17:30 -0700159 mLooper->pollOnce(timeoutMillis);
Jeff Browna665ca82010-09-08 11:49:43 -0700160}
161
162void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
163 nsecs_t keyRepeatDelay, nsecs_t* nextWakeupTime) {
164 nsecs_t currentTime = now();
165
166 // Reset the key repeat timer whenever we disallow key events, even if the next event
167 // is not a key. This is to ensure that we abort a key repeat if the device is just coming
168 // out of sleep.
169 if (keyRepeatTimeout < 0) {
170 resetKeyRepeatLocked();
171 }
172
173 // If dispatching is disabled, drop all events in the queue.
174 if (! mDispatchEnabled) {
175 if (mPendingEvent || ! mInboundQueue.isEmpty()) {
176 LOGI("Dropping pending events because input dispatch is disabled.");
177 releasePendingEventLocked(true);
178 drainInboundQueueLocked();
179 }
Jeff Brown54bc2812010-06-15 01:31:58 -0700180 return;
181 }
182
Jeff Browna665ca82010-09-08 11:49:43 -0700183 // If dispatching is frozen, do not process timeouts or try to deliver any new events.
184 if (mDispatchFrozen) {
185#if DEBUG_FOCUS
186 LOGD("Dispatch frozen. Waiting some more.");
187#endif
188 return;
189 }
190
191 // Optimize latency of app switches.
192 // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
193 // been pressed. When it expires, we preempt dispatch and drop all other pending events.
194 bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
195 if (mAppSwitchDueTime < *nextWakeupTime) {
196 *nextWakeupTime = mAppSwitchDueTime;
197 }
198
Jeff Browna665ca82010-09-08 11:49:43 -0700199 // Ready to start a new event.
200 // If we don't already have a pending event, go grab one.
201 if (! mPendingEvent) {
202 if (mInboundQueue.isEmpty()) {
203 if (isAppSwitchDue) {
204 // The inbound queue is empty so the app switch key we were waiting
205 // for will never arrive. Stop waiting for it.
206 resetPendingAppSwitchLocked(false);
207 isAppSwitchDue = false;
208 }
209
210 // Synthesize a key repeat if appropriate.
211 if (mKeyRepeatState.lastKeyEntry) {
212 if (currentTime >= mKeyRepeatState.nextRepeatTime) {
213 mPendingEvent = synthesizeKeyRepeatLocked(currentTime, keyRepeatDelay);
214 } else {
215 if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
216 *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
217 }
218 }
219 }
220 if (! mPendingEvent) {
221 return;
222 }
223 } else {
224 // Inbound queue has at least one entry.
225 EventEntry* entry = mInboundQueue.headSentinel.next;
226
227 // Throttle the entry if it is a move event and there are no
228 // other events behind it in the queue. Due to movement batching, additional
229 // samples may be appended to this event by the time the throttling timeout
230 // expires.
231 // TODO Make this smarter and consider throttling per device independently.
232 if (entry->type == EventEntry::TYPE_MOTION) {
233 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
234 int32_t deviceId = motionEntry->deviceId;
235 uint32_t source = motionEntry->source;
236 if (! isAppSwitchDue
237 && motionEntry->next == & mInboundQueue.tailSentinel // exactly one event
238 && motionEntry->action == AMOTION_EVENT_ACTION_MOVE
239 && deviceId == mThrottleState.lastDeviceId
240 && source == mThrottleState.lastSource) {
241 nsecs_t nextTime = mThrottleState.lastEventTime
242 + mThrottleState.minTimeBetweenEvents;
243 if (currentTime < nextTime) {
244 // Throttle it!
245#if DEBUG_THROTTLING
246 LOGD("Throttling - Delaying motion event for "
247 "device 0x%x, source 0x%08x by up to %0.3fms.",
248 deviceId, source, (nextTime - currentTime) * 0.000001);
249#endif
250 if (nextTime < *nextWakeupTime) {
251 *nextWakeupTime = nextTime;
252 }
253 if (mThrottleState.originalSampleCount == 0) {
254 mThrottleState.originalSampleCount =
255 motionEntry->countSamples();
256 }
257 return;
258 }
259 }
260
261#if DEBUG_THROTTLING
262 if (mThrottleState.originalSampleCount != 0) {
263 uint32_t count = motionEntry->countSamples();
264 LOGD("Throttling - Motion event sample count grew by %d from %d to %d.",
265 count - mThrottleState.originalSampleCount,
266 mThrottleState.originalSampleCount, count);
267 mThrottleState.originalSampleCount = 0;
268 }
269#endif
270
271 mThrottleState.lastEventTime = entry->eventTime < currentTime
272 ? entry->eventTime : currentTime;
273 mThrottleState.lastDeviceId = deviceId;
274 mThrottleState.lastSource = source;
275 }
276
277 mInboundQueue.dequeue(entry);
278 mPendingEvent = entry;
279 }
280 }
281
282 // Now we have an event to dispatch.
283 assert(mPendingEvent != NULL);
284 bool wasDispatched = false;
285 bool wasDropped = false;
286 switch (mPendingEvent->type) {
287 case EventEntry::TYPE_CONFIGURATION_CHANGED: {
288 ConfigurationChangedEntry* typedEntry =
289 static_cast<ConfigurationChangedEntry*>(mPendingEvent);
290 wasDispatched = dispatchConfigurationChangedLocked(currentTime, typedEntry);
291 break;
292 }
293
294 case EventEntry::TYPE_KEY: {
295 KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
296 if (isAppSwitchPendingLocked()) {
297 if (isAppSwitchKey(typedEntry->keyCode)) {
298 resetPendingAppSwitchLocked(true);
299 } else if (isAppSwitchDue) {
300 LOGI("Dropping key because of pending overdue app switch.");
301 wasDropped = true;
302 break;
303 }
304 }
305 wasDispatched = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
306 nextWakeupTime);
307 break;
308 }
309
310 case EventEntry::TYPE_MOTION: {
311 MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
312 if (isAppSwitchDue) {
313 LOGI("Dropping motion because of pending overdue app switch.");
314 wasDropped = true;
315 break;
316 }
317 wasDispatched = dispatchMotionLocked(currentTime, typedEntry, nextWakeupTime);
318 break;
319 }
320
321 default:
322 assert(false);
323 wasDropped = true;
324 break;
325 }
326
327 if (wasDispatched || wasDropped) {
328 releasePendingEventLocked(wasDropped);
329 *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
330 }
331}
332
333bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
334 bool needWake = mInboundQueue.isEmpty();
335 mInboundQueue.enqueueAtTail(entry);
336
337 switch (entry->type) {
338 case EventEntry::TYPE_KEY:
339 needWake |= detectPendingAppSwitchLocked(static_cast<KeyEntry*>(entry));
340 break;
341 }
342
343 return needWake;
344}
345
346bool InputDispatcher::isAppSwitchKey(int32_t keyCode) {
347 return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
348}
349
350bool InputDispatcher::isAppSwitchPendingLocked() {
351 return mAppSwitchDueTime != LONG_LONG_MAX;
352}
353
354bool InputDispatcher::detectPendingAppSwitchLocked(KeyEntry* inboundKeyEntry) {
355 if (inboundKeyEntry->action == AKEY_EVENT_ACTION_UP
356 && ! (inboundKeyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
357 && isAppSwitchKey(inboundKeyEntry->keyCode)
358 && isEventFromReliableSourceLocked(inboundKeyEntry)) {
359#if DEBUG_APP_SWITCH
360 LOGD("App switch is pending!");
361#endif
362 mAppSwitchDueTime = inboundKeyEntry->eventTime + APP_SWITCH_TIMEOUT;
363 return true; // need wake
364 }
365 return false;
366}
367
368void InputDispatcher::resetPendingAppSwitchLocked(bool handled) {
369 mAppSwitchDueTime = LONG_LONG_MAX;
370
371#if DEBUG_APP_SWITCH
372 if (handled) {
373 LOGD("App switch has arrived.");
374 } else {
375 LOGD("App switch was abandoned.");
376 }
377#endif
Jeff Browne839a582010-04-22 18:58:52 -0700378}
379
Jeff Brown54bc2812010-06-15 01:31:58 -0700380bool InputDispatcher::runCommandsLockedInterruptible() {
381 if (mCommandQueue.isEmpty()) {
382 return false;
383 }
Jeff Browne839a582010-04-22 18:58:52 -0700384
Jeff Brown54bc2812010-06-15 01:31:58 -0700385 do {
386 CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
387
388 Command command = commandEntry->command;
389 (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
390
Jeff Brown51d45a72010-06-17 20:52:56 -0700391 commandEntry->connection.clear();
Jeff Brown54bc2812010-06-15 01:31:58 -0700392 mAllocator.releaseCommandEntry(commandEntry);
393 } while (! mCommandQueue.isEmpty());
394 return true;
Jeff Browne839a582010-04-22 18:58:52 -0700395}
396
Jeff Brown54bc2812010-06-15 01:31:58 -0700397InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
398 CommandEntry* commandEntry = mAllocator.obtainCommandEntry(command);
399 mCommandQueue.enqueueAtTail(commandEntry);
400 return commandEntry;
401}
402
Jeff Browna665ca82010-09-08 11:49:43 -0700403void InputDispatcher::drainInboundQueueLocked() {
404 while (! mInboundQueue.isEmpty()) {
405 EventEntry* entry = mInboundQueue.dequeueAtHead();
406 releaseInboundEventLocked(entry, true /*wasDropped*/);
Jeff Browne839a582010-04-22 18:58:52 -0700407 }
Jeff Browne839a582010-04-22 18:58:52 -0700408}
409
Jeff Browna665ca82010-09-08 11:49:43 -0700410void InputDispatcher::releasePendingEventLocked(bool wasDropped) {
411 if (mPendingEvent) {
412 releaseInboundEventLocked(mPendingEvent, wasDropped);
413 mPendingEvent = NULL;
414 }
415}
416
417void InputDispatcher::releaseInboundEventLocked(EventEntry* entry, bool wasDropped) {
418 if (wasDropped) {
419#if DEBUG_DISPATCH_CYCLE
420 LOGD("Pending event was dropped.");
421#endif
422 setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
423 }
424 mAllocator.releaseEventEntry(entry);
425}
426
427bool InputDispatcher::isEventFromReliableSourceLocked(EventEntry* entry) {
428 return ! entry->isInjected()
429 || entry->injectorUid == 0
430 || mPolicy->checkInjectEventsPermissionNonReentrant(
431 entry->injectorPid, entry->injectorUid);
432}
433
434void InputDispatcher::resetKeyRepeatLocked() {
435 if (mKeyRepeatState.lastKeyEntry) {
436 mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
437 mKeyRepeatState.lastKeyEntry = NULL;
438 }
439}
440
441InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(
Jeff Brown61ce3982010-09-07 10:44:57 -0700442 nsecs_t currentTime, nsecs_t keyRepeatDelay) {
Jeff Brown50de30a2010-06-22 01:27:15 -0700443 KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
444
Jeff Brown50de30a2010-06-22 01:27:15 -0700445 // Reuse the repeated key entry if it is otherwise unreferenced.
Jeff Brown51d45a72010-06-17 20:52:56 -0700446 uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
Jeff Browne839a582010-04-22 18:58:52 -0700447 if (entry->refCount == 1) {
Jeff Browna665ca82010-09-08 11:49:43 -0700448 entry->recycle();
Jeff Brown51d45a72010-06-17 20:52:56 -0700449 entry->eventTime = currentTime;
Jeff Brown51d45a72010-06-17 20:52:56 -0700450 entry->policyFlags = policyFlags;
Jeff Browne839a582010-04-22 18:58:52 -0700451 entry->repeatCount += 1;
452 } else {
Jeff Brown51d45a72010-06-17 20:52:56 -0700453 KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700454 entry->deviceId, entry->source, policyFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -0700455 entry->action, entry->flags, entry->keyCode, entry->scanCode,
Jeff Brownf16c26d2010-07-02 15:37:36 -0700456 entry->metaState, entry->repeatCount + 1, entry->downTime);
Jeff Browne839a582010-04-22 18:58:52 -0700457
458 mKeyRepeatState.lastKeyEntry = newEntry;
459 mAllocator.releaseKeyEntry(entry);
460
461 entry = newEntry;
462 }
Jeff Browna665ca82010-09-08 11:49:43 -0700463 entry->syntheticRepeat = true;
464
465 // Increment reference count since we keep a reference to the event in
466 // mKeyRepeatState.lastKeyEntry in addition to the one we return.
467 entry->refCount += 1;
Jeff Browne839a582010-04-22 18:58:52 -0700468
Jeff Brownf16c26d2010-07-02 15:37:36 -0700469 if (entry->repeatCount == 1) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700470 entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
Jeff Brownf16c26d2010-07-02 15:37:36 -0700471 }
472
Jeff Brown61ce3982010-09-07 10:44:57 -0700473 mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatDelay;
Jeff Browna665ca82010-09-08 11:49:43 -0700474 return entry;
Jeff Browne839a582010-04-22 18:58:52 -0700475}
476
Jeff Browna665ca82010-09-08 11:49:43 -0700477bool InputDispatcher::dispatchConfigurationChangedLocked(
478 nsecs_t currentTime, ConfigurationChangedEntry* entry) {
Jeff Browne839a582010-04-22 18:58:52 -0700479#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Browna665ca82010-09-08 11:49:43 -0700480 LOGD("dispatchConfigurationChanged - eventTime=%lld", entry->eventTime);
481#endif
482
483 // Reset key repeating in case a keyboard device was added or removed or something.
484 resetKeyRepeatLocked();
485
486 // Enqueue a command to run outside the lock to tell the policy that the configuration changed.
487 CommandEntry* commandEntry = postCommandLocked(
488 & InputDispatcher::doNotifyConfigurationChangedInterruptible);
489 commandEntry->eventTime = entry->eventTime;
490 return true;
491}
492
493bool InputDispatcher::dispatchKeyLocked(
494 nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
495 nsecs_t* nextWakeupTime) {
496 // Preprocessing.
497 if (! entry->dispatchInProgress) {
498 logOutboundKeyDetailsLocked("dispatchKey - ", entry);
499
500 if (entry->repeatCount == 0
501 && entry->action == AKEY_EVENT_ACTION_DOWN
502 && ! entry->isInjected()) {
503 if (mKeyRepeatState.lastKeyEntry
504 && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
505 // We have seen two identical key downs in a row which indicates that the device
506 // driver is automatically generating key repeats itself. We take note of the
507 // repeat here, but we disable our own next key repeat timer since it is clear that
508 // we will not need to synthesize key repeats ourselves.
509 entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
510 resetKeyRepeatLocked();
511 mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
512 } else {
513 // Not a repeat. Save key down state in case we do see a repeat later.
514 resetKeyRepeatLocked();
515 mKeyRepeatState.nextRepeatTime = entry->eventTime + keyRepeatTimeout;
516 }
517 mKeyRepeatState.lastKeyEntry = entry;
518 entry->refCount += 1;
519 } else if (! entry->syntheticRepeat) {
520 resetKeyRepeatLocked();
521 }
522
523 entry->dispatchInProgress = true;
Jeff Brown53a415e2010-09-15 15:18:56 -0700524 startFindingTargetsLocked(); // resets mCurrentInputTargetsValid
Jeff Browna665ca82010-09-08 11:49:43 -0700525 }
526
527 // Identify targets.
528 if (! mCurrentInputTargetsValid) {
529 InputWindow* window = NULL;
530 int32_t injectionResult = findFocusedWindowLocked(currentTime,
531 entry, nextWakeupTime, & window);
532 if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
533 return false;
534 }
535
536 setInjectionResultLocked(entry, injectionResult);
537 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
538 return true;
539 }
540
541 addMonitoringTargetsLocked();
542 finishFindingTargetsLocked(window);
543 }
544
545 // Give the policy a chance to intercept the key.
546 if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
547 CommandEntry* commandEntry = postCommandLocked(
548 & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
549 commandEntry->inputChannel = mCurrentInputChannel;
550 commandEntry->keyEntry = entry;
551 entry->refCount += 1;
552 return false; // wait for the command to run
553 }
554 if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
555 return true;
556 }
557
558 // Dispatch the key.
559 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
560
561 // Poke user activity.
562 pokeUserActivityLocked(entry->eventTime, mCurrentInputWindowType, POWER_MANAGER_BUTTON_EVENT);
563 return true;
564}
565
566void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry) {
567#if DEBUG_OUTBOUND_EVENT_DETAILS
568 LOGD("%seventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
569 "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
570 "downTime=%lld",
571 prefix,
572 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
573 entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
574 entry->downTime);
575#endif
576}
577
578bool InputDispatcher::dispatchMotionLocked(
579 nsecs_t currentTime, MotionEntry* entry, nsecs_t* nextWakeupTime) {
580 // Preprocessing.
581 if (! entry->dispatchInProgress) {
582 logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
583
584 entry->dispatchInProgress = true;
Jeff Brown53a415e2010-09-15 15:18:56 -0700585 startFindingTargetsLocked(); // resets mCurrentInputTargetsValid
Jeff Browna665ca82010-09-08 11:49:43 -0700586 }
587
588 bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
589
590 // Identify targets.
591 if (! mCurrentInputTargetsValid) {
592 InputWindow* window = NULL;
593 int32_t injectionResult;
594 if (isPointerEvent) {
595 // Pointer event. (eg. touchscreen)
596 injectionResult = findTouchedWindowLocked(currentTime,
597 entry, nextWakeupTime, & window);
598 } else {
599 // Non touch event. (eg. trackball)
600 injectionResult = findFocusedWindowLocked(currentTime,
601 entry, nextWakeupTime, & window);
602 }
603 if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
604 return false;
605 }
606
607 setInjectionResultLocked(entry, injectionResult);
608 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
609 return true;
610 }
611
612 addMonitoringTargetsLocked();
613 finishFindingTargetsLocked(window);
614 }
615
616 // Dispatch the motion.
617 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
618
619 // Poke user activity.
620 int32_t eventType;
621 if (isPointerEvent) {
622 switch (entry->action) {
623 case AMOTION_EVENT_ACTION_DOWN:
624 eventType = POWER_MANAGER_TOUCH_EVENT;
625 break;
626 case AMOTION_EVENT_ACTION_UP:
627 eventType = POWER_MANAGER_TOUCH_UP_EVENT;
628 break;
629 default:
630 if (entry->eventTime - entry->downTime >= EVENT_IGNORE_DURATION) {
631 eventType = POWER_MANAGER_TOUCH_EVENT;
632 } else {
633 eventType = POWER_MANAGER_LONG_TOUCH_EVENT;
634 }
635 break;
636 }
637 } else {
638 eventType = POWER_MANAGER_BUTTON_EVENT;
639 }
640 pokeUserActivityLocked(entry->eventTime, mCurrentInputWindowType, eventType);
641 return true;
642}
643
644
645void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) {
646#if DEBUG_OUTBOUND_EVENT_DETAILS
647 LOGD("%seventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Brownaf30ff62010-09-01 17:01:00 -0700648 "action=0x%x, flags=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -0700649 "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
Jeff Browna665ca82010-09-08 11:49:43 -0700650 prefix,
Jeff Brownaf30ff62010-09-01 17:01:00 -0700651 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
652 entry->action, entry->flags,
Jeff Browne839a582010-04-22 18:58:52 -0700653 entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
654 entry->downTime);
655
656 // Print the most recent sample that we have available, this may change due to batching.
657 size_t sampleCount = 1;
Jeff Browna665ca82010-09-08 11:49:43 -0700658 const MotionSample* sample = & entry->firstSample;
Jeff Browne839a582010-04-22 18:58:52 -0700659 for (; sample->next != NULL; sample = sample->next) {
660 sampleCount += 1;
661 }
662 for (uint32_t i = 0; i < entry->pointerCount; i++) {
Jeff Brown38a7fab2010-08-30 03:02:23 -0700663 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
Jeff Brownaf30ff62010-09-01 17:01:00 -0700664 "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
Jeff Brown38a7fab2010-08-30 03:02:23 -0700665 "orientation=%f",
Jeff Browne839a582010-04-22 18:58:52 -0700666 i, entry->pointerIds[i],
Jeff Brown38a7fab2010-08-30 03:02:23 -0700667 sample->pointerCoords[i].x, sample->pointerCoords[i].y,
668 sample->pointerCoords[i].pressure, sample->pointerCoords[i].size,
669 sample->pointerCoords[i].touchMajor, sample->pointerCoords[i].touchMinor,
670 sample->pointerCoords[i].toolMajor, sample->pointerCoords[i].toolMinor,
671 sample->pointerCoords[i].orientation);
Jeff Browne839a582010-04-22 18:58:52 -0700672 }
673
674 // Keep in mind that due to batching, it is possible for the number of samples actually
675 // dispatched to change before the application finally consumed them.
Jeff Brown5c1ed842010-07-14 18:48:53 -0700676 if (entry->action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Browne839a582010-04-22 18:58:52 -0700677 LOGD(" ... Total movement samples currently batched %d ...", sampleCount);
678 }
679#endif
Jeff Browne839a582010-04-22 18:58:52 -0700680}
681
682void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
683 EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
684#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700685 LOGD("dispatchEventToCurrentInputTargets - "
Jeff Browne839a582010-04-22 18:58:52 -0700686 "resumeWithAppendedMotionSample=%s",
Jeff Browna665ca82010-09-08 11:49:43 -0700687 toString(resumeWithAppendedMotionSample));
Jeff Browne839a582010-04-22 18:58:52 -0700688#endif
689
Jeff Brown54bc2812010-06-15 01:31:58 -0700690 assert(eventEntry->dispatchInProgress); // should already have been set to true
691
Jeff Browne839a582010-04-22 18:58:52 -0700692 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
693 const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
694
Jeff Brown53a415e2010-09-15 15:18:56 -0700695 ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
Jeff Browne839a582010-04-22 18:58:52 -0700696 if (connectionIndex >= 0) {
697 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown51d45a72010-06-17 20:52:56 -0700698 prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
Jeff Browne839a582010-04-22 18:58:52 -0700699 resumeWithAppendedMotionSample);
700 } else {
701 LOGW("Framework requested delivery of an input event to channel '%s' but it "
702 "is not registered with the input dispatcher.",
703 inputTarget.inputChannel->getName().string());
704 }
705 }
706}
707
Jeff Browna665ca82010-09-08 11:49:43 -0700708void InputDispatcher::startFindingTargetsLocked() {
709 mCurrentInputTargetsValid = false;
710 mCurrentInputTargets.clear();
711 mCurrentInputChannel.clear();
712 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
713}
714
715void InputDispatcher::finishFindingTargetsLocked(const InputWindow* window) {
716 mCurrentInputWindowType = window->layoutParamsType;
717 mCurrentInputChannel = window->inputChannel;
718 mCurrentInputTargetsValid = true;
719}
720
721int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
722 const EventEntry* entry, const InputApplication* application, const InputWindow* window,
723 nsecs_t* nextWakeupTime) {
724 if (application == NULL && window == NULL) {
725 if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
726#if DEBUG_FOCUS
727 LOGD("Waiting for system to become ready for input.");
728#endif
729 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
730 mInputTargetWaitStartTime = currentTime;
731 mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
732 mInputTargetWaitTimeoutExpired = false;
733 }
734 } else {
735 if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
736#if DEBUG_FOCUS
Jeff Brown53a415e2010-09-15 15:18:56 -0700737 LOGD("Waiting for application to become ready for input: %s",
738 getApplicationWindowLabelLocked(application, window).string());
Jeff Browna665ca82010-09-08 11:49:43 -0700739#endif
740 nsecs_t timeout = window ? window->dispatchingTimeout :
741 application ? application->dispatchingTimeout : DEFAULT_INPUT_DISPATCHING_TIMEOUT;
742
743 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
744 mInputTargetWaitStartTime = currentTime;
745 mInputTargetWaitTimeoutTime = currentTime + timeout;
746 mInputTargetWaitTimeoutExpired = false;
747 }
748 }
749
750 if (mInputTargetWaitTimeoutExpired) {
751 return INPUT_EVENT_INJECTION_TIMED_OUT;
752 }
753
754 if (currentTime >= mInputTargetWaitTimeoutTime) {
Jeff Brown53a415e2010-09-15 15:18:56 -0700755 onANRLocked(currentTime, application, window, entry->eventTime, mInputTargetWaitStartTime);
Jeff Browna665ca82010-09-08 11:49:43 -0700756
757 // Force poll loop to wake up immediately on next iteration once we get the
758 // ANR response back from the policy.
759 *nextWakeupTime = LONG_LONG_MIN;
760 return INPUT_EVENT_INJECTION_PENDING;
761 } else {
762 // Force poll loop to wake up when timeout is due.
763 if (mInputTargetWaitTimeoutTime < *nextWakeupTime) {
764 *nextWakeupTime = mInputTargetWaitTimeoutTime;
765 }
766 return INPUT_EVENT_INJECTION_PENDING;
767 }
768}
769
Jeff Brown53a415e2010-09-15 15:18:56 -0700770void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
771 const sp<InputChannel>& inputChannel) {
Jeff Browna665ca82010-09-08 11:49:43 -0700772 if (newTimeout > 0) {
773 // Extend the timeout.
774 mInputTargetWaitTimeoutTime = now() + newTimeout;
775 } else {
776 // Give up.
777 mInputTargetWaitTimeoutExpired = true;
Jeff Brown53a415e2010-09-15 15:18:56 -0700778
Jeff Brown405a1d32010-09-16 12:31:46 -0700779 // Release the touch target.
780 releaseTouchedWindowLocked();
781
Jeff Brown53a415e2010-09-15 15:18:56 -0700782 // Input state will not be realistic. Mark it out of sync.
Jeff Brown40ad4702010-09-16 11:02:16 -0700783 if (inputChannel.get()) {
784 ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
785 if (connectionIndex >= 0) {
786 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
787 connection->inputState.setOutOfSync();
788 }
Jeff Brown53a415e2010-09-15 15:18:56 -0700789 }
Jeff Browna665ca82010-09-08 11:49:43 -0700790 }
791}
792
Jeff Brown53a415e2010-09-15 15:18:56 -0700793nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(
Jeff Browna665ca82010-09-08 11:49:43 -0700794 nsecs_t currentTime) {
795 if (mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
796 return currentTime - mInputTargetWaitStartTime;
797 }
798 return 0;
799}
800
801void InputDispatcher::resetANRTimeoutsLocked() {
802#if DEBUG_FOCUS
803 LOGD("Resetting ANR timeouts.");
804#endif
805
Jeff Browna665ca82010-09-08 11:49:43 -0700806 // Reset input target wait timeout.
807 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
808}
809
810int32_t InputDispatcher::findFocusedWindowLocked(nsecs_t currentTime, const EventEntry* entry,
811 nsecs_t* nextWakeupTime, InputWindow** outWindow) {
812 *outWindow = NULL;
813 mCurrentInputTargets.clear();
814
815 int32_t injectionResult;
816
817 // If there is no currently focused window and no focused application
818 // then drop the event.
819 if (! mFocusedWindow) {
820 if (mFocusedApplication) {
821#if DEBUG_FOCUS
822 LOGD("Waiting because there is no focused window but there is a "
Jeff Brown53a415e2010-09-15 15:18:56 -0700823 "focused application that may eventually add a window: %s.",
824 getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
Jeff Browna665ca82010-09-08 11:49:43 -0700825#endif
826 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
827 mFocusedApplication, NULL, nextWakeupTime);
828 goto Unresponsive;
829 }
830
831 LOGI("Dropping event because there is no focused window or focused application.");
832 injectionResult = INPUT_EVENT_INJECTION_FAILED;
833 goto Failed;
834 }
835
836 // Check permissions.
837 if (! checkInjectionPermission(mFocusedWindow, entry->injectorPid, entry->injectorUid)) {
838 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
839 goto Failed;
840 }
841
842 // If the currently focused window is paused then keep waiting.
843 if (mFocusedWindow->paused) {
844#if DEBUG_FOCUS
845 LOGD("Waiting because focused window is paused.");
846#endif
847 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
848 mFocusedApplication, mFocusedWindow, nextWakeupTime);
849 goto Unresponsive;
850 }
851
Jeff Brown53a415e2010-09-15 15:18:56 -0700852 // If the currently focused window is still working on previous events then keep waiting.
853 if (! isWindowFinishedWithPreviousInputLocked(mFocusedWindow)) {
854#if DEBUG_FOCUS
855 LOGD("Waiting because focused window still processing previous input.");
856#endif
857 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
858 mFocusedApplication, mFocusedWindow, nextWakeupTime);
859 goto Unresponsive;
860 }
861
Jeff Browna665ca82010-09-08 11:49:43 -0700862 // Success! Output targets.
863 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
864 *outWindow = mFocusedWindow;
Jeff Brown53a415e2010-09-15 15:18:56 -0700865 addWindowTargetLocked(mFocusedWindow, InputTarget::FLAG_FOREGROUND);
Jeff Browna665ca82010-09-08 11:49:43 -0700866
867 // Done.
868Failed:
869Unresponsive:
Jeff Brown53a415e2010-09-15 15:18:56 -0700870 nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
871 updateDispatchStatisticsLocked(currentTime, entry,
872 injectionResult, timeSpentWaitingForApplication);
Jeff Browna665ca82010-09-08 11:49:43 -0700873#if DEBUG_FOCUS
Jeff Brown53a415e2010-09-15 15:18:56 -0700874 LOGD("findFocusedWindow finished: injectionResult=%d, "
875 "timeSpendWaitingForApplication=%0.1fms",
876 injectionResult, timeSpentWaitingForApplication / 1000000.0);
Jeff Browna665ca82010-09-08 11:49:43 -0700877#endif
878 return injectionResult;
879}
880
881int32_t InputDispatcher::findTouchedWindowLocked(nsecs_t currentTime, const MotionEntry* entry,
882 nsecs_t* nextWakeupTime, InputWindow** outWindow) {
883 enum InjectionPermission {
884 INJECTION_PERMISSION_UNKNOWN,
885 INJECTION_PERMISSION_GRANTED,
886 INJECTION_PERMISSION_DENIED
887 };
888
889 *outWindow = NULL;
890 mCurrentInputTargets.clear();
891
892 nsecs_t startTime = now();
893
894 // For security reasons, we defer updating the touch state until we are sure that
895 // event injection will be allowed.
896 //
897 // FIXME In the original code, screenWasOff could never be set to true.
898 // The reason is that the POLICY_FLAG_WOKE_HERE
899 // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
900 // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
901 // actually enqueued using the policyFlags that appeared in the final EV_SYN
902 // events upon which no preprocessing took place. So policyFlags was always 0.
903 // In the new native input dispatcher we're a bit more careful about event
904 // preprocessing so the touches we receive can actually have non-zero policyFlags.
905 // Unfortunately we obtain undesirable behavior.
906 //
907 // Here's what happens:
908 //
909 // When the device dims in anticipation of going to sleep, touches
910 // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
911 // the device to brighten and reset the user activity timer.
912 // Touches on other windows (such as the launcher window)
913 // are dropped. Then after a moment, the device goes to sleep. Oops.
914 //
915 // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
916 // instead of POLICY_FLAG_WOKE_HERE...
917 //
918 bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
919
920 int32_t action = entry->action;
921
922 // Update the touch state as needed based on the properties of the touch event.
923 int32_t injectionResult;
924 InjectionPermission injectionPermission;
925 if (action == AMOTION_EVENT_ACTION_DOWN) {
926 /* Case 1: ACTION_DOWN */
927
928 InputWindow* newTouchedWindow = NULL;
929 mTempTouchedOutsideTargets.clear();
930
931 int32_t x = int32_t(entry->firstSample.pointerCoords[0].x);
932 int32_t y = int32_t(entry->firstSample.pointerCoords[0].y);
933 InputWindow* topErrorWindow = NULL;
934 bool obscured = false;
935
936 // Traverse windows from front to back to find touched window and outside targets.
937 size_t numWindows = mWindows.size();
938 for (size_t i = 0; i < numWindows; i++) {
939 InputWindow* window = & mWindows.editItemAt(i);
940 int32_t flags = window->layoutParamsFlags;
941
942 if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
943 if (! topErrorWindow) {
944 topErrorWindow = window;
945 }
946 }
947
948 if (window->visible) {
949 if (! (flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
950 bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
951 | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
952 if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
953 if (! screenWasOff || flags & InputWindow::FLAG_TOUCHABLE_WHEN_WAKING) {
954 newTouchedWindow = window;
955 obscured = isWindowObscuredLocked(window);
956 }
957 break; // found touched window, exit window loop
958 }
959 }
960
961 if (flags & InputWindow::FLAG_WATCH_OUTSIDE_TOUCH) {
962 OutsideTarget outsideTarget;
963 outsideTarget.window = window;
964 outsideTarget.obscured = isWindowObscuredLocked(window);
965 mTempTouchedOutsideTargets.push(outsideTarget);
966 }
967 }
968 }
969
970 // If there is an error window but it is not taking focus (typically because
971 // it is invisible) then wait for it. Any other focused window may in
972 // fact be in ANR state.
973 if (topErrorWindow && newTouchedWindow != topErrorWindow) {
974#if DEBUG_FOCUS
975 LOGD("Waiting because system error window is pending.");
976#endif
977 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
978 NULL, NULL, nextWakeupTime);
979 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
980 goto Unresponsive;
981 }
982
983 // If we did not find a touched window then fail.
984 if (! newTouchedWindow) {
985 if (mFocusedApplication) {
986#if DEBUG_FOCUS
987 LOGD("Waiting because there is no touched window but there is a "
Jeff Brown53a415e2010-09-15 15:18:56 -0700988 "focused application that may eventually add a new window: %s.",
989 getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
Jeff Browna665ca82010-09-08 11:49:43 -0700990#endif
991 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
992 mFocusedApplication, NULL, nextWakeupTime);
993 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
994 goto Unresponsive;
995 }
996
997 LOGI("Dropping event because there is no touched window or focused application.");
998 injectionResult = INPUT_EVENT_INJECTION_FAILED;
999 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
1000 goto Failed;
1001 }
1002
1003 // Check permissions.
1004 if (! checkInjectionPermission(newTouchedWindow, entry->injectorPid, entry->injectorUid)) {
1005 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1006 injectionPermission = INJECTION_PERMISSION_DENIED;
1007 goto Failed;
1008 }
1009
1010 // If the touched window is paused then keep waiting.
1011 if (newTouchedWindow->paused) {
1012#if DEBUG_INPUT_DISPATCHER_POLICY
1013 LOGD("Waiting because touched window is paused.");
1014#endif
1015 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1016 NULL, newTouchedWindow, nextWakeupTime);
1017 injectionPermission = INJECTION_PERMISSION_GRANTED;
1018 goto Unresponsive;
1019 }
1020
Jeff Brown53a415e2010-09-15 15:18:56 -07001021 // If the touched window is still working on previous events then keep waiting.
1022 if (! isWindowFinishedWithPreviousInputLocked(newTouchedWindow)) {
1023#if DEBUG_FOCUS
1024 LOGD("Waiting because touched window still processing previous input.");
1025#endif
1026 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1027 NULL, newTouchedWindow, nextWakeupTime);
1028 injectionPermission = INJECTION_PERMISSION_GRANTED;
1029 goto Unresponsive;
1030 }
1031
Jeff Browna665ca82010-09-08 11:49:43 -07001032 // Success! Update the touch dispatch state for real.
1033 releaseTouchedWindowLocked();
1034
1035 mTouchedWindow = newTouchedWindow;
1036 mTouchedWindowIsObscured = obscured;
1037
1038 if (newTouchedWindow->hasWallpaper) {
1039 mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
1040 }
1041 } else {
1042 /* Case 2: Everything but ACTION_DOWN */
1043
1044 // Check permissions.
1045 if (! checkInjectionPermission(mTouchedWindow, entry->injectorPid, entry->injectorUid)) {
1046 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1047 injectionPermission = INJECTION_PERMISSION_DENIED;
1048 goto Failed;
1049 }
1050
1051 // If the pointer is not currently down, then ignore the event.
1052 if (! mTouchDown) {
1053 LOGI("Dropping event because the pointer is not down.");
1054 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1055 injectionPermission = INJECTION_PERMISSION_GRANTED;
1056 goto Failed;
1057 }
1058
1059 // If there is no currently touched window then fail.
1060 if (! mTouchedWindow) {
1061#if DEBUG_INPUT_DISPATCHER_POLICY
1062 LOGD("Dropping event because there is no touched window to receive it.");
1063#endif
1064 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1065 injectionPermission = INJECTION_PERMISSION_GRANTED;
1066 goto Failed;
1067 }
1068
1069 // If the touched window is paused then keep waiting.
1070 if (mTouchedWindow->paused) {
1071#if DEBUG_INPUT_DISPATCHER_POLICY
1072 LOGD("Waiting because touched window is paused.");
1073#endif
1074 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1075 NULL, mTouchedWindow, nextWakeupTime);
1076 injectionPermission = INJECTION_PERMISSION_GRANTED;
1077 goto Unresponsive;
1078 }
Jeff Brown53a415e2010-09-15 15:18:56 -07001079
1080 // If the touched window is still working on previous events then keep waiting.
1081 if (! isWindowFinishedWithPreviousInputLocked(mTouchedWindow)) {
1082#if DEBUG_FOCUS
1083 LOGD("Waiting because touched window still processing previous input.");
1084#endif
1085 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1086 NULL, mTouchedWindow, nextWakeupTime);
1087 injectionPermission = INJECTION_PERMISSION_GRANTED;
1088 goto Unresponsive;
1089 }
Jeff Browna665ca82010-09-08 11:49:43 -07001090 }
1091
1092 // Success! Output targets.
1093 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1094 injectionPermission = INJECTION_PERMISSION_GRANTED;
1095
1096 {
1097 size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
1098 for (size_t i = 0; i < numWallpaperWindows; i++) {
1099 addWindowTargetLocked(mTouchedWallpaperWindows[i],
Jeff Brown53a415e2010-09-15 15:18:56 -07001100 InputTarget::FLAG_WINDOW_IS_OBSCURED);
Jeff Browna665ca82010-09-08 11:49:43 -07001101 }
1102
1103 size_t numOutsideTargets = mTempTouchedOutsideTargets.size();
1104 for (size_t i = 0; i < numOutsideTargets; i++) {
1105 const OutsideTarget& outsideTarget = mTempTouchedOutsideTargets[i];
1106 int32_t outsideTargetFlags = InputTarget::FLAG_OUTSIDE;
1107 if (outsideTarget.obscured) {
1108 outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
1109 }
Jeff Brown53a415e2010-09-15 15:18:56 -07001110 addWindowTargetLocked(outsideTarget.window, outsideTargetFlags);
Jeff Browna665ca82010-09-08 11:49:43 -07001111 }
1112 mTempTouchedOutsideTargets.clear();
1113
Jeff Brown53a415e2010-09-15 15:18:56 -07001114 int32_t targetFlags = InputTarget::FLAG_FOREGROUND;
Jeff Browna665ca82010-09-08 11:49:43 -07001115 if (mTouchedWindowIsObscured) {
1116 targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
1117 }
Jeff Brown53a415e2010-09-15 15:18:56 -07001118 addWindowTargetLocked(mTouchedWindow, targetFlags);
Jeff Browna665ca82010-09-08 11:49:43 -07001119 *outWindow = mTouchedWindow;
1120 }
1121
1122Failed:
1123 // Check injection permission once and for all.
1124 if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
1125 if (checkInjectionPermission(action == AMOTION_EVENT_ACTION_DOWN ? NULL : mTouchedWindow,
1126 entry->injectorPid, entry->injectorUid)) {
1127 injectionPermission = INJECTION_PERMISSION_GRANTED;
1128 } else {
1129 injectionPermission = INJECTION_PERMISSION_DENIED;
1130 }
1131 }
1132
1133 // Update final pieces of touch state if the injector had permission.
1134 if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
1135 if (action == AMOTION_EVENT_ACTION_DOWN) {
1136 if (mTouchDown) {
1137 // This is weird. We got a down but we thought it was already down!
1138 LOGW("Pointer down received while already down.");
1139 } else {
1140 mTouchDown = true;
1141 }
1142
1143 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1144 // Since we failed to identify a target for this touch down, we may still
1145 // be holding on to an earlier target from a previous touch down. Release it.
1146 releaseTouchedWindowLocked();
1147 }
1148 } else if (action == AMOTION_EVENT_ACTION_UP) {
1149 mTouchDown = false;
1150 releaseTouchedWindowLocked();
1151 }
1152 } else {
1153 LOGW("Not updating touch focus because injection was denied.");
1154 }
1155
1156Unresponsive:
Jeff Brown53a415e2010-09-15 15:18:56 -07001157 nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
1158 updateDispatchStatisticsLocked(currentTime, entry,
1159 injectionResult, timeSpentWaitingForApplication);
Jeff Browna665ca82010-09-08 11:49:43 -07001160#if DEBUG_FOCUS
Jeff Brown53a415e2010-09-15 15:18:56 -07001161 LOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d,"
1162 "timeSpendWaitingForApplication=%0.1fms",
1163 injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0);
Jeff Browna665ca82010-09-08 11:49:43 -07001164#endif
1165 return injectionResult;
1166}
1167
1168void InputDispatcher::releaseTouchedWindowLocked() {
1169 mTouchedWindow = NULL;
1170 mTouchedWindowIsObscured = false;
1171 mTouchedWallpaperWindows.clear();
1172}
1173
Jeff Brown53a415e2010-09-15 15:18:56 -07001174void InputDispatcher::addWindowTargetLocked(const InputWindow* window, int32_t targetFlags) {
Jeff Browna665ca82010-09-08 11:49:43 -07001175 mCurrentInputTargets.push();
1176
1177 InputTarget& target = mCurrentInputTargets.editTop();
1178 target.inputChannel = window->inputChannel;
1179 target.flags = targetFlags;
Jeff Browna665ca82010-09-08 11:49:43 -07001180 target.xOffset = - window->frameLeft;
1181 target.yOffset = - window->frameTop;
1182}
1183
1184void InputDispatcher::addMonitoringTargetsLocked() {
1185 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
1186 mCurrentInputTargets.push();
1187
1188 InputTarget& target = mCurrentInputTargets.editTop();
1189 target.inputChannel = mMonitoringChannels[i];
1190 target.flags = 0;
Jeff Browna665ca82010-09-08 11:49:43 -07001191 target.xOffset = 0;
1192 target.yOffset = 0;
1193 }
1194}
1195
1196bool InputDispatcher::checkInjectionPermission(const InputWindow* window,
1197 int32_t injectorPid, int32_t injectorUid) {
1198 if (injectorUid > 0 && (window == NULL || window->ownerUid != injectorUid)) {
1199 bool result = mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
1200 if (! result) {
1201 if (window) {
1202 LOGW("Permission denied: injecting event from pid %d uid %d to window "
1203 "with input channel %s owned by uid %d",
1204 injectorPid, injectorUid, window->inputChannel->getName().string(),
1205 window->ownerUid);
1206 } else {
1207 LOGW("Permission denied: injecting event from pid %d uid %d",
1208 injectorPid, injectorUid);
1209 }
1210 return false;
1211 }
1212 }
1213 return true;
1214}
1215
1216bool InputDispatcher::isWindowObscuredLocked(const InputWindow* window) {
1217 size_t numWindows = mWindows.size();
1218 for (size_t i = 0; i < numWindows; i++) {
1219 const InputWindow* other = & mWindows.itemAt(i);
1220 if (other == window) {
1221 break;
1222 }
1223 if (other->visible && window->visibleFrameIntersects(other)) {
1224 return true;
1225 }
1226 }
1227 return false;
1228}
1229
Jeff Brown53a415e2010-09-15 15:18:56 -07001230bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(const InputWindow* window) {
1231 ssize_t connectionIndex = getConnectionIndexLocked(window->inputChannel);
1232 if (connectionIndex >= 0) {
1233 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1234 return connection->outboundQueue.isEmpty();
1235 } else {
1236 return true;
1237 }
1238}
1239
1240String8 InputDispatcher::getApplicationWindowLabelLocked(const InputApplication* application,
1241 const InputWindow* window) {
1242 if (application) {
1243 if (window) {
1244 String8 label(application->name);
1245 label.append(" - ");
1246 label.append(window->name);
1247 return label;
1248 } else {
1249 return application->name;
1250 }
1251 } else if (window) {
1252 return window->name;
1253 } else {
1254 return String8("<unknown application or window>");
1255 }
1256}
1257
Jeff Browna665ca82010-09-08 11:49:43 -07001258void InputDispatcher::pokeUserActivityLocked(nsecs_t eventTime,
1259 int32_t windowType, int32_t eventType) {
1260 CommandEntry* commandEntry = postCommandLocked(
1261 & InputDispatcher::doPokeUserActivityLockedInterruptible);
1262 commandEntry->eventTime = eventTime;
1263 commandEntry->windowType = windowType;
1264 commandEntry->userActivityEventType = eventType;
1265}
1266
Jeff Brown51d45a72010-06-17 20:52:56 -07001267void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
1268 const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
Jeff Browne839a582010-04-22 18:58:52 -07001269 bool resumeWithAppendedMotionSample) {
1270#if DEBUG_DISPATCH_CYCLE
Jeff Brown53a415e2010-09-15 15:18:56 -07001271 LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, "
Jeff Browne839a582010-04-22 18:58:52 -07001272 "xOffset=%f, yOffset=%f, resumeWithAppendedMotionSample=%s",
Jeff Brown53a415e2010-09-15 15:18:56 -07001273 connection->getInputChannelName(), inputTarget->flags,
Jeff Browne839a582010-04-22 18:58:52 -07001274 inputTarget->xOffset, inputTarget->yOffset,
Jeff Browna665ca82010-09-08 11:49:43 -07001275 toString(resumeWithAppendedMotionSample));
Jeff Browne839a582010-04-22 18:58:52 -07001276#endif
1277
1278 // Skip this event if the connection status is not normal.
Jeff Brown53a415e2010-09-15 15:18:56 -07001279 // We don't want to enqueue additional outbound events if the connection is broken.
Jeff Browne839a582010-04-22 18:58:52 -07001280 if (connection->status != Connection::STATUS_NORMAL) {
Jeff Browna665ca82010-09-08 11:49:43 -07001281 LOGW("channel '%s' ~ Dropping event because the channel status is %s",
1282 connection->getInputChannelName(), connection->getStatusLabel());
Jeff Browne839a582010-04-22 18:58:52 -07001283 return;
1284 }
1285
1286 // Resume the dispatch cycle with a freshly appended motion sample.
1287 // First we check that the last dispatch entry in the outbound queue is for the same
1288 // motion event to which we appended the motion sample. If we find such a dispatch
1289 // entry, and if it is currently in progress then we try to stream the new sample.
1290 bool wasEmpty = connection->outboundQueue.isEmpty();
1291
1292 if (! wasEmpty && resumeWithAppendedMotionSample) {
1293 DispatchEntry* motionEventDispatchEntry =
1294 connection->findQueuedDispatchEntryForEvent(eventEntry);
1295 if (motionEventDispatchEntry) {
1296 // If the dispatch entry is not in progress, then we must be busy dispatching an
1297 // earlier event. Not a problem, the motion event is on the outbound queue and will
1298 // be dispatched later.
1299 if (! motionEventDispatchEntry->inProgress) {
1300#if DEBUG_BATCHING
1301 LOGD("channel '%s' ~ Not streaming because the motion event has "
1302 "not yet been dispatched. "
1303 "(Waiting for earlier events to be consumed.)",
1304 connection->getInputChannelName());
1305#endif
1306 return;
1307 }
1308
1309 // If the dispatch entry is in progress but it already has a tail of pending
1310 // motion samples, then it must mean that the shared memory buffer filled up.
1311 // Not a problem, when this dispatch cycle is finished, we will eventually start
1312 // a new dispatch cycle to process the tail and that tail includes the newly
1313 // appended motion sample.
1314 if (motionEventDispatchEntry->tailMotionSample) {
1315#if DEBUG_BATCHING
1316 LOGD("channel '%s' ~ Not streaming because no new samples can "
1317 "be appended to the motion event in this dispatch cycle. "
1318 "(Waiting for next dispatch cycle to start.)",
1319 connection->getInputChannelName());
1320#endif
1321 return;
1322 }
1323
1324 // The dispatch entry is in progress and is still potentially open for streaming.
1325 // Try to stream the new motion sample. This might fail if the consumer has already
1326 // consumed the motion event (or if the channel is broken).
1327 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
1328 status_t status = connection->inputPublisher.appendMotionSample(
1329 appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
1330 if (status == OK) {
1331#if DEBUG_BATCHING
1332 LOGD("channel '%s' ~ Successfully streamed new motion sample.",
1333 connection->getInputChannelName());
1334#endif
1335 return;
1336 }
1337
1338#if DEBUG_BATCHING
1339 if (status == NO_MEMORY) {
1340 LOGD("channel '%s' ~ Could not append motion sample to currently "
1341 "dispatched move event because the shared memory buffer is full. "
1342 "(Waiting for next dispatch cycle to start.)",
1343 connection->getInputChannelName());
1344 } else if (status == status_t(FAILED_TRANSACTION)) {
1345 LOGD("channel '%s' ~ Could not append motion sample to currently "
Jeff Brown50de30a2010-06-22 01:27:15 -07001346 "dispatched move event because the event has already been consumed. "
Jeff Browne839a582010-04-22 18:58:52 -07001347 "(Waiting for next dispatch cycle to start.)",
1348 connection->getInputChannelName());
1349 } else {
1350 LOGD("channel '%s' ~ Could not append motion sample to currently "
1351 "dispatched move event due to an error, status=%d. "
1352 "(Waiting for next dispatch cycle to start.)",
1353 connection->getInputChannelName(), status);
1354 }
1355#endif
1356 // Failed to stream. Start a new tail of pending motion samples to dispatch
1357 // in the next cycle.
1358 motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
1359 return;
1360 }
1361 }
1362
Jeff Browna665ca82010-09-08 11:49:43 -07001363 // Bring the input state back in line with reality in case it drifted off during an ANR.
1364 if (connection->inputState.isOutOfSync()) {
1365 mTempCancelationEvents.clear();
1366 connection->inputState.synthesizeCancelationEvents(& mAllocator, mTempCancelationEvents);
1367 connection->inputState.resetOutOfSync();
1368
1369 if (! mTempCancelationEvents.isEmpty()) {
1370 LOGI("channel '%s' ~ Generated %d cancelation events to bring channel back in sync "
1371 "with reality.",
1372 connection->getInputChannelName(), mTempCancelationEvents.size());
1373
1374 for (size_t i = 0; i < mTempCancelationEvents.size(); i++) {
1375 EventEntry* cancelationEventEntry = mTempCancelationEvents.itemAt(i);
1376 switch (cancelationEventEntry->type) {
1377 case EventEntry::TYPE_KEY:
1378 logOutboundKeyDetailsLocked(" ",
1379 static_cast<KeyEntry*>(cancelationEventEntry));
1380 break;
1381 case EventEntry::TYPE_MOTION:
1382 logOutboundMotionDetailsLocked(" ",
1383 static_cast<MotionEntry*>(cancelationEventEntry));
1384 break;
1385 }
1386
1387 DispatchEntry* cancelationDispatchEntry =
1388 mAllocator.obtainDispatchEntry(cancelationEventEntry,
Jeff Brown53a415e2010-09-15 15:18:56 -07001389 0, inputTarget->xOffset, inputTarget->yOffset); // increments ref
Jeff Browna665ca82010-09-08 11:49:43 -07001390 connection->outboundQueue.enqueueAtTail(cancelationDispatchEntry);
1391
1392 mAllocator.releaseEventEntry(cancelationEventEntry);
1393 }
1394 }
1395 }
1396
Jeff Browne839a582010-04-22 18:58:52 -07001397 // This is a new event.
1398 // Enqueue a new dispatch entry onto the outbound queue for this connection.
Jeff Browna665ca82010-09-08 11:49:43 -07001399 DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry, // increments ref
Jeff Brown53a415e2010-09-15 15:18:56 -07001400 inputTarget->flags, inputTarget->xOffset, inputTarget->yOffset);
1401 if (dispatchEntry->hasForegroundTarget()) {
1402 eventEntry->pendingForegroundDispatches += 1;
Jeff Brownf67c53e2010-07-28 15:48:59 -07001403 }
1404
Jeff Browne839a582010-04-22 18:58:52 -07001405 // Handle the case where we could not stream a new motion sample because the consumer has
1406 // already consumed the motion event (otherwise the corresponding dispatch entry would
1407 // still be in the outbound queue for this connection). We set the head motion sample
1408 // to the list starting with the newly appended motion sample.
1409 if (resumeWithAppendedMotionSample) {
1410#if DEBUG_BATCHING
1411 LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
1412 "that cannot be streamed because the motion event has already been consumed.",
1413 connection->getInputChannelName());
1414#endif
1415 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
1416 dispatchEntry->headMotionSample = appendedMotionSample;
1417 }
1418
1419 // Enqueue the dispatch entry.
1420 connection->outboundQueue.enqueueAtTail(dispatchEntry);
1421
1422 // If the outbound queue was previously empty, start the dispatch cycle going.
1423 if (wasEmpty) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001424 activateConnectionLocked(connection.get());
Jeff Brown53a415e2010-09-15 15:18:56 -07001425 startDispatchCycleLocked(currentTime, connection);
Jeff Browne839a582010-04-22 18:58:52 -07001426 }
1427}
1428
Jeff Brown51d45a72010-06-17 20:52:56 -07001429void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
Jeff Brown53a415e2010-09-15 15:18:56 -07001430 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001431#if DEBUG_DISPATCH_CYCLE
1432 LOGD("channel '%s' ~ startDispatchCycle",
1433 connection->getInputChannelName());
1434#endif
1435
1436 assert(connection->status == Connection::STATUS_NORMAL);
1437 assert(! connection->outboundQueue.isEmpty());
1438
Jeff Browna665ca82010-09-08 11:49:43 -07001439 DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
Jeff Browne839a582010-04-22 18:58:52 -07001440 assert(! dispatchEntry->inProgress);
1441
Jeff Browna665ca82010-09-08 11:49:43 -07001442 // Mark the dispatch entry as in progress.
1443 dispatchEntry->inProgress = true;
1444
1445 // Update the connection's input state.
1446 InputState::Consistency consistency = connection->inputState.trackEvent(
1447 dispatchEntry->eventEntry);
1448
1449#if FILTER_INPUT_EVENTS
1450 // Filter out inconsistent sequences of input events.
1451 // The input system may drop or inject events in a way that could violate implicit
1452 // invariants on input state and potentially cause an application to crash
1453 // or think that a key or pointer is stuck down. Technically we make no guarantees
1454 // of consistency but it would be nice to improve on this where possible.
1455 // XXX: This code is a proof of concept only. Not ready for prime time.
1456 if (consistency == InputState::TOLERABLE) {
1457#if DEBUG_DISPATCH_CYCLE
1458 LOGD("channel '%s' ~ Sending an event that is inconsistent with the connection's "
1459 "current input state but that is likely to be tolerated by the application.",
1460 connection->getInputChannelName());
1461#endif
1462 } else if (consistency == InputState::BROKEN) {
1463 LOGI("channel '%s' ~ Dropping an event that is inconsistent with the connection's "
1464 "current input state and that is likely to cause the application to crash.",
1465 connection->getInputChannelName());
1466 startNextDispatchCycleLocked(currentTime, connection);
1467 return;
1468 }
1469#endif
Jeff Browne839a582010-04-22 18:58:52 -07001470
1471 // Publish the event.
1472 status_t status;
1473 switch (dispatchEntry->eventEntry->type) {
1474 case EventEntry::TYPE_KEY: {
1475 KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
1476
1477 // Apply target flags.
1478 int32_t action = keyEntry->action;
1479 int32_t flags = keyEntry->flags;
1480 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07001481 flags |= AKEY_EVENT_FLAG_CANCELED;
Jeff Browne839a582010-04-22 18:58:52 -07001482 }
1483
1484 // Publish the key event.
Jeff Brown5c1ed842010-07-14 18:48:53 -07001485 status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
Jeff Browne839a582010-04-22 18:58:52 -07001486 action, flags, keyEntry->keyCode, keyEntry->scanCode,
1487 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
1488 keyEntry->eventTime);
1489
1490 if (status) {
1491 LOGE("channel '%s' ~ Could not publish key event, "
1492 "status=%d", connection->getInputChannelName(), status);
1493 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
1494 return;
1495 }
1496 break;
1497 }
1498
1499 case EventEntry::TYPE_MOTION: {
1500 MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
1501
1502 // Apply target flags.
1503 int32_t action = motionEntry->action;
Jeff Brownaf30ff62010-09-01 17:01:00 -07001504 int32_t flags = motionEntry->flags;
Jeff Browne839a582010-04-22 18:58:52 -07001505 if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07001506 action = AMOTION_EVENT_ACTION_OUTSIDE;
Jeff Browne839a582010-04-22 18:58:52 -07001507 }
1508 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07001509 action = AMOTION_EVENT_ACTION_CANCEL;
Jeff Browne839a582010-04-22 18:58:52 -07001510 }
Jeff Brownaf30ff62010-09-01 17:01:00 -07001511 if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
1512 flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
1513 }
Jeff Browne839a582010-04-22 18:58:52 -07001514
1515 // If headMotionSample is non-NULL, then it points to the first new sample that we
1516 // were unable to dispatch during the previous cycle so we resume dispatching from
1517 // that point in the list of motion samples.
1518 // Otherwise, we just start from the first sample of the motion event.
1519 MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
1520 if (! firstMotionSample) {
1521 firstMotionSample = & motionEntry->firstSample;
1522 }
1523
Jeff Brownf26db0d2010-07-16 17:21:06 -07001524 // Set the X and Y offset depending on the input source.
1525 float xOffset, yOffset;
1526 if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
1527 xOffset = dispatchEntry->xOffset;
1528 yOffset = dispatchEntry->yOffset;
1529 } else {
1530 xOffset = 0.0f;
1531 yOffset = 0.0f;
1532 }
1533
Jeff Browne839a582010-04-22 18:58:52 -07001534 // Publish the motion event and the first motion sample.
1535 status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001536 motionEntry->source, action, flags, motionEntry->edgeFlags, motionEntry->metaState,
Jeff Brownf26db0d2010-07-16 17:21:06 -07001537 xOffset, yOffset,
Jeff Browne839a582010-04-22 18:58:52 -07001538 motionEntry->xPrecision, motionEntry->yPrecision,
1539 motionEntry->downTime, firstMotionSample->eventTime,
1540 motionEntry->pointerCount, motionEntry->pointerIds,
1541 firstMotionSample->pointerCoords);
1542
1543 if (status) {
1544 LOGE("channel '%s' ~ Could not publish motion event, "
1545 "status=%d", connection->getInputChannelName(), status);
1546 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
1547 return;
1548 }
1549
1550 // Append additional motion samples.
1551 MotionSample* nextMotionSample = firstMotionSample->next;
1552 for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
1553 status = connection->inputPublisher.appendMotionSample(
1554 nextMotionSample->eventTime, nextMotionSample->pointerCoords);
1555 if (status == NO_MEMORY) {
1556#if DEBUG_DISPATCH_CYCLE
1557 LOGD("channel '%s' ~ Shared memory buffer full. Some motion samples will "
1558 "be sent in the next dispatch cycle.",
1559 connection->getInputChannelName());
1560#endif
1561 break;
1562 }
1563 if (status != OK) {
1564 LOGE("channel '%s' ~ Could not append motion sample "
1565 "for a reason other than out of memory, status=%d",
1566 connection->getInputChannelName(), status);
1567 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
1568 return;
1569 }
1570 }
1571
1572 // Remember the next motion sample that we could not dispatch, in case we ran out
1573 // of space in the shared memory buffer.
1574 dispatchEntry->tailMotionSample = nextMotionSample;
1575 break;
1576 }
1577
1578 default: {
1579 assert(false);
1580 }
1581 }
1582
1583 // Send the dispatch signal.
1584 status = connection->inputPublisher.sendDispatchSignal();
1585 if (status) {
1586 LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
1587 connection->getInputChannelName(), status);
1588 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
1589 return;
1590 }
1591
1592 // Record information about the newly started dispatch cycle.
Jeff Browne839a582010-04-22 18:58:52 -07001593 connection->lastEventTime = dispatchEntry->eventEntry->eventTime;
1594 connection->lastDispatchTime = currentTime;
1595
Jeff Browne839a582010-04-22 18:58:52 -07001596 // Notify other system components.
1597 onDispatchCycleStartedLocked(currentTime, connection);
1598}
1599
Jeff Brown51d45a72010-06-17 20:52:56 -07001600void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
1601 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001602#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -07001603 LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
Jeff Browne839a582010-04-22 18:58:52 -07001604 "%01.1fms since dispatch",
1605 connection->getInputChannelName(),
1606 connection->getEventLatencyMillis(currentTime),
1607 connection->getDispatchLatencyMillis(currentTime));
1608#endif
1609
Jeff Brown54bc2812010-06-15 01:31:58 -07001610 if (connection->status == Connection::STATUS_BROKEN
1611 || connection->status == Connection::STATUS_ZOMBIE) {
Jeff Browne839a582010-04-22 18:58:52 -07001612 return;
1613 }
1614
Jeff Brown53a415e2010-09-15 15:18:56 -07001615 // Notify other system components.
1616 onDispatchCycleFinishedLocked(currentTime, connection);
Jeff Browne839a582010-04-22 18:58:52 -07001617
1618 // Reset the publisher since the event has been consumed.
1619 // We do this now so that the publisher can release some of its internal resources
1620 // while waiting for the next dispatch cycle to begin.
1621 status_t status = connection->inputPublisher.reset();
1622 if (status) {
1623 LOGE("channel '%s' ~ Could not reset publisher, status=%d",
1624 connection->getInputChannelName(), status);
1625 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
1626 return;
1627 }
1628
Jeff Browna665ca82010-09-08 11:49:43 -07001629 startNextDispatchCycleLocked(currentTime, connection);
1630}
1631
1632void InputDispatcher::startNextDispatchCycleLocked(nsecs_t currentTime,
1633 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001634 // Start the next dispatch cycle for this connection.
1635 while (! connection->outboundQueue.isEmpty()) {
Jeff Browna665ca82010-09-08 11:49:43 -07001636 DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
Jeff Browne839a582010-04-22 18:58:52 -07001637 if (dispatchEntry->inProgress) {
1638 // Finish or resume current event in progress.
1639 if (dispatchEntry->tailMotionSample) {
1640 // We have a tail of undispatched motion samples.
1641 // Reuse the same DispatchEntry and start a new cycle.
1642 dispatchEntry->inProgress = false;
1643 dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
1644 dispatchEntry->tailMotionSample = NULL;
Jeff Brown53a415e2010-09-15 15:18:56 -07001645 startDispatchCycleLocked(currentTime, connection);
Jeff Browne839a582010-04-22 18:58:52 -07001646 return;
1647 }
1648 // Finished.
1649 connection->outboundQueue.dequeueAtHead();
Jeff Brown53a415e2010-09-15 15:18:56 -07001650 if (dispatchEntry->hasForegroundTarget()) {
1651 decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
Jeff Brownf67c53e2010-07-28 15:48:59 -07001652 }
Jeff Browne839a582010-04-22 18:58:52 -07001653 mAllocator.releaseDispatchEntry(dispatchEntry);
1654 } else {
1655 // If the head is not in progress, then we must have already dequeued the in
Jeff Brown53a415e2010-09-15 15:18:56 -07001656 // progress event, which means we actually aborted it.
Jeff Browne839a582010-04-22 18:58:52 -07001657 // So just start the next event for this connection.
Jeff Brown53a415e2010-09-15 15:18:56 -07001658 startDispatchCycleLocked(currentTime, connection);
Jeff Browne839a582010-04-22 18:58:52 -07001659 return;
1660 }
1661 }
1662
1663 // Outbound queue is empty, deactivate the connection.
Jeff Brown51d45a72010-06-17 20:52:56 -07001664 deactivateConnectionLocked(connection.get());
Jeff Browne839a582010-04-22 18:58:52 -07001665}
1666
Jeff Brown51d45a72010-06-17 20:52:56 -07001667void InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime,
1668 const sp<Connection>& connection, bool broken) {
Jeff Browne839a582010-04-22 18:58:52 -07001669#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -07001670 LOGD("channel '%s' ~ abortDispatchCycle - broken=%s",
Jeff Browna665ca82010-09-08 11:49:43 -07001671 connection->getInputChannelName(), toString(broken));
Jeff Browne839a582010-04-22 18:58:52 -07001672#endif
1673
Jeff Browna665ca82010-09-08 11:49:43 -07001674 // Input state will no longer be realistic.
1675 connection->inputState.setOutOfSync();
Jeff Browne839a582010-04-22 18:58:52 -07001676
Jeff Browna665ca82010-09-08 11:49:43 -07001677 // Clear the outbound queue.
Jeff Brown53a415e2010-09-15 15:18:56 -07001678 drainOutboundQueueLocked(connection.get());
Jeff Browne839a582010-04-22 18:58:52 -07001679
1680 // Handle the case where the connection appears to be unrecoverably broken.
Jeff Brown54bc2812010-06-15 01:31:58 -07001681 // Ignore already broken or zombie connections.
Jeff Browne839a582010-04-22 18:58:52 -07001682 if (broken) {
Jeff Brown53a415e2010-09-15 15:18:56 -07001683 if (connection->status == Connection::STATUS_NORMAL) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001684 connection->status = Connection::STATUS_BROKEN;
Jeff Browne839a582010-04-22 18:58:52 -07001685
Jeff Brown54bc2812010-06-15 01:31:58 -07001686 // Notify other system components.
1687 onDispatchCycleBrokenLocked(currentTime, connection);
1688 }
Jeff Browne839a582010-04-22 18:58:52 -07001689 }
Jeff Browne839a582010-04-22 18:58:52 -07001690}
1691
Jeff Brown53a415e2010-09-15 15:18:56 -07001692void InputDispatcher::drainOutboundQueueLocked(Connection* connection) {
1693 while (! connection->outboundQueue.isEmpty()) {
1694 DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
1695 if (dispatchEntry->hasForegroundTarget()) {
1696 decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
Jeff Browna665ca82010-09-08 11:49:43 -07001697 }
1698 mAllocator.releaseDispatchEntry(dispatchEntry);
Jeff Browna665ca82010-09-08 11:49:43 -07001699 }
1700
Jeff Brown53a415e2010-09-15 15:18:56 -07001701 deactivateConnectionLocked(connection);
Jeff Browna665ca82010-09-08 11:49:43 -07001702}
1703
Jeff Brown59abe7e2010-09-13 23:17:30 -07001704int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
Jeff Browne839a582010-04-22 18:58:52 -07001705 InputDispatcher* d = static_cast<InputDispatcher*>(data);
1706
1707 { // acquire lock
1708 AutoMutex _l(d->mLock);
1709
1710 ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
1711 if (connectionIndex < 0) {
1712 LOGE("Received spurious receive callback for unknown input channel. "
1713 "fd=%d, events=0x%x", receiveFd, events);
Jeff Brown59abe7e2010-09-13 23:17:30 -07001714 return 0; // remove the callback
Jeff Browne839a582010-04-22 18:58:52 -07001715 }
1716
Jeff Brown51d45a72010-06-17 20:52:56 -07001717 nsecs_t currentTime = now();
Jeff Browne839a582010-04-22 18:58:52 -07001718
1719 sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown59abe7e2010-09-13 23:17:30 -07001720 if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
Jeff Browne839a582010-04-22 18:58:52 -07001721 LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
1722 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brown51d45a72010-06-17 20:52:56 -07001723 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -07001724 d->runCommandsLockedInterruptible();
Jeff Brown59abe7e2010-09-13 23:17:30 -07001725 return 0; // remove the callback
Jeff Browne839a582010-04-22 18:58:52 -07001726 }
1727
Jeff Brown59abe7e2010-09-13 23:17:30 -07001728 if (! (events & ALOOPER_EVENT_INPUT)) {
Jeff Browne839a582010-04-22 18:58:52 -07001729 LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
1730 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brown59abe7e2010-09-13 23:17:30 -07001731 return 1;
Jeff Browne839a582010-04-22 18:58:52 -07001732 }
1733
1734 status_t status = connection->inputPublisher.receiveFinishedSignal();
1735 if (status) {
1736 LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
1737 connection->getInputChannelName(), status);
Jeff Brown51d45a72010-06-17 20:52:56 -07001738 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -07001739 d->runCommandsLockedInterruptible();
Jeff Brown59abe7e2010-09-13 23:17:30 -07001740 return 0; // remove the callback
Jeff Browne839a582010-04-22 18:58:52 -07001741 }
1742
Jeff Brown51d45a72010-06-17 20:52:56 -07001743 d->finishDispatchCycleLocked(currentTime, connection);
Jeff Brown54bc2812010-06-15 01:31:58 -07001744 d->runCommandsLockedInterruptible();
Jeff Brown59abe7e2010-09-13 23:17:30 -07001745 return 1;
Jeff Browne839a582010-04-22 18:58:52 -07001746 } // release lock
1747}
1748
Jeff Brown54bc2812010-06-15 01:31:58 -07001749void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
Jeff Browne839a582010-04-22 18:58:52 -07001750#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown54bc2812010-06-15 01:31:58 -07001751 LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
Jeff Browne839a582010-04-22 18:58:52 -07001752#endif
1753
Jeff Browna665ca82010-09-08 11:49:43 -07001754 bool needWake;
Jeff Browne839a582010-04-22 18:58:52 -07001755 { // acquire lock
1756 AutoMutex _l(mLock);
1757
Jeff Brown51d45a72010-06-17 20:52:56 -07001758 ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
Jeff Browna665ca82010-09-08 11:49:43 -07001759 needWake = enqueueInboundEventLocked(newEntry);
Jeff Browne839a582010-04-22 18:58:52 -07001760 } // release lock
1761
Jeff Browna665ca82010-09-08 11:49:43 -07001762 if (needWake) {
Jeff Brown59abe7e2010-09-13 23:17:30 -07001763 mLooper->wake();
Jeff Browne839a582010-04-22 18:58:52 -07001764 }
1765}
1766
Jeff Brown5c1ed842010-07-14 18:48:53 -07001767void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Browne839a582010-04-22 18:58:52 -07001768 uint32_t policyFlags, int32_t action, int32_t flags,
1769 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
1770#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -07001771 LOGD("notifyKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -07001772 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
Jeff Brown5c1ed842010-07-14 18:48:53 -07001773 eventTime, deviceId, source, policyFlags, action, flags,
Jeff Browne839a582010-04-22 18:58:52 -07001774 keyCode, scanCode, metaState, downTime);
1775#endif
1776
Jeff Browna665ca82010-09-08 11:49:43 -07001777 bool needWake;
Jeff Browne839a582010-04-22 18:58:52 -07001778 { // acquire lock
1779 AutoMutex _l(mLock);
1780
Jeff Brown51d45a72010-06-17 20:52:56 -07001781 int32_t repeatCount = 0;
1782 KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001783 deviceId, source, policyFlags, action, flags, keyCode, scanCode,
Jeff Brown51d45a72010-06-17 20:52:56 -07001784 metaState, repeatCount, downTime);
Jeff Browne839a582010-04-22 18:58:52 -07001785
Jeff Browna665ca82010-09-08 11:49:43 -07001786 needWake = enqueueInboundEventLocked(newEntry);
Jeff Browne839a582010-04-22 18:58:52 -07001787 } // release lock
1788
Jeff Browna665ca82010-09-08 11:49:43 -07001789 if (needWake) {
Jeff Brown59abe7e2010-09-13 23:17:30 -07001790 mLooper->wake();
Jeff Browne839a582010-04-22 18:58:52 -07001791 }
1792}
1793
Jeff Brown5c1ed842010-07-14 18:48:53 -07001794void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001795 uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t edgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07001796 uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
1797 float xPrecision, float yPrecision, nsecs_t downTime) {
1798#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -07001799 LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Brownaf30ff62010-09-01 17:01:00 -07001800 "action=0x%x, flags=0x%x, metaState=0x%x, edgeFlags=0x%x, "
1801 "xPrecision=%f, yPrecision=%f, downTime=%lld",
1802 eventTime, deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07001803 xPrecision, yPrecision, downTime);
1804 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001805 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
Jeff Brownaf30ff62010-09-01 17:01:00 -07001806 "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
Jeff Brown38a7fab2010-08-30 03:02:23 -07001807 "orientation=%f",
Jeff Browne839a582010-04-22 18:58:52 -07001808 i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
Jeff Brown38a7fab2010-08-30 03:02:23 -07001809 pointerCoords[i].pressure, pointerCoords[i].size,
1810 pointerCoords[i].touchMajor, pointerCoords[i].touchMinor,
1811 pointerCoords[i].toolMajor, pointerCoords[i].toolMinor,
1812 pointerCoords[i].orientation);
Jeff Browne839a582010-04-22 18:58:52 -07001813 }
1814#endif
1815
Jeff Browna665ca82010-09-08 11:49:43 -07001816 bool needWake;
Jeff Browne839a582010-04-22 18:58:52 -07001817 { // acquire lock
1818 AutoMutex _l(mLock);
1819
1820 // Attempt batching and streaming of move events.
Jeff Brown5c1ed842010-07-14 18:48:53 -07001821 if (action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Browne839a582010-04-22 18:58:52 -07001822 // BATCHING CASE
1823 //
1824 // Try to append a move sample to the tail of the inbound queue for this device.
1825 // Give up if we encounter a non-move motion event for this device since that
1826 // means we cannot append any new samples until a new motion event has started.
Jeff Browna665ca82010-09-08 11:49:43 -07001827 for (EventEntry* entry = mInboundQueue.tailSentinel.prev;
1828 entry != & mInboundQueue.headSentinel; entry = entry->prev) {
Jeff Browne839a582010-04-22 18:58:52 -07001829 if (entry->type != EventEntry::TYPE_MOTION) {
1830 // Keep looking for motion events.
1831 continue;
1832 }
1833
1834 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
1835 if (motionEntry->deviceId != deviceId) {
1836 // Keep looking for this device.
1837 continue;
1838 }
1839
Jeff Brown5c1ed842010-07-14 18:48:53 -07001840 if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown51d45a72010-06-17 20:52:56 -07001841 || motionEntry->pointerCount != pointerCount
1842 || motionEntry->isInjected()) {
Jeff Browne839a582010-04-22 18:58:52 -07001843 // Last motion event in the queue for this device is not compatible for
1844 // appending new samples. Stop here.
1845 goto NoBatchingOrStreaming;
1846 }
1847
1848 // The last motion event is a move and is compatible for appending.
Jeff Brown54bc2812010-06-15 01:31:58 -07001849 // Do the batching magic.
Jeff Brown51d45a72010-06-17 20:52:56 -07001850 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
Jeff Browne839a582010-04-22 18:58:52 -07001851#if DEBUG_BATCHING
1852 LOGD("Appended motion sample onto batch for most recent "
1853 "motion event for this device in the inbound queue.");
1854#endif
Jeff Brown54bc2812010-06-15 01:31:58 -07001855 return; // done!
Jeff Browne839a582010-04-22 18:58:52 -07001856 }
1857
1858 // STREAMING CASE
1859 //
1860 // There is no pending motion event (of any kind) for this device in the inbound queue.
Jeff Brown53a415e2010-09-15 15:18:56 -07001861 // Search the outbound queue for the current foreground targets to find a dispatched
1862 // motion event that is still in progress. If found, then, appen the new sample to
1863 // that event and push it out to all current targets. The logic in
1864 // prepareDispatchCycleLocked takes care of the case where some targets may
1865 // already have consumed the motion event by starting a new dispatch cycle if needed.
Jeff Brown54bc2812010-06-15 01:31:58 -07001866 if (mCurrentInputTargetsValid) {
Jeff Brown53a415e2010-09-15 15:18:56 -07001867 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
1868 const InputTarget& inputTarget = mCurrentInputTargets[i];
1869 if ((inputTarget.flags & InputTarget::FLAG_FOREGROUND) == 0) {
1870 // Skip non-foreground targets. We only want to stream if there is at
1871 // least one foreground target whose dispatch is still in progress.
1872 continue;
Jeff Browne839a582010-04-22 18:58:52 -07001873 }
Jeff Brown53a415e2010-09-15 15:18:56 -07001874
1875 ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
1876 if (connectionIndex < 0) {
1877 // Connection must no longer be valid.
1878 continue;
1879 }
1880
1881 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1882 if (connection->outboundQueue.isEmpty()) {
1883 // This foreground target has an empty outbound queue.
1884 continue;
1885 }
1886
1887 DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
1888 if (! dispatchEntry->inProgress
1889 || dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION) {
1890 // No motion event is being dispatched.
1891 continue;
1892 }
1893
1894 MotionEntry* motionEntry = static_cast<MotionEntry*>(
1895 dispatchEntry->eventEntry);
1896 if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
1897 || motionEntry->deviceId != deviceId
1898 || motionEntry->pointerCount != pointerCount
1899 || motionEntry->isInjected()) {
1900 // The motion event is not compatible with this move.
1901 continue;
1902 }
1903
1904 // Hurray! This foreground target is currently dispatching a move event
1905 // that we can stream onto. Append the motion sample and resume dispatch.
1906 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
1907#if DEBUG_BATCHING
1908 LOGD("Appended motion sample onto batch for most recently dispatched "
1909 "motion event for this device in the outbound queues. "
1910 "Attempting to stream the motion sample.");
1911#endif
1912 nsecs_t currentTime = now();
1913 dispatchEventToCurrentInputTargetsLocked(currentTime, motionEntry,
1914 true /*resumeWithAppendedMotionSample*/);
1915
1916 runCommandsLockedInterruptible();
1917 return; // done!
Jeff Browne839a582010-04-22 18:58:52 -07001918 }
1919 }
1920
1921NoBatchingOrStreaming:;
1922 }
1923
1924 // Just enqueue a new motion event.
Jeff Brown51d45a72010-06-17 20:52:56 -07001925 MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001926 deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -07001927 xPrecision, yPrecision, downTime,
1928 pointerCount, pointerIds, pointerCoords);
Jeff Browne839a582010-04-22 18:58:52 -07001929
Jeff Browna665ca82010-09-08 11:49:43 -07001930 needWake = enqueueInboundEventLocked(newEntry);
Jeff Browne839a582010-04-22 18:58:52 -07001931 } // release lock
1932
Jeff Browna665ca82010-09-08 11:49:43 -07001933 if (needWake) {
Jeff Brown59abe7e2010-09-13 23:17:30 -07001934 mLooper->wake();
Jeff Browne839a582010-04-22 18:58:52 -07001935 }
1936}
1937
Jeff Brown51d45a72010-06-17 20:52:56 -07001938int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
Jeff Brownf67c53e2010-07-28 15:48:59 -07001939 int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001940#if DEBUG_INBOUND_EVENT_DETAILS
1941 LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
Jeff Brownf67c53e2010-07-28 15:48:59 -07001942 "syncMode=%d, timeoutMillis=%d",
1943 event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis);
Jeff Brown51d45a72010-06-17 20:52:56 -07001944#endif
1945
1946 nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
1947
1948 EventEntry* injectedEntry;
Jeff Browna665ca82010-09-08 11:49:43 -07001949 bool needWake;
Jeff Brown51d45a72010-06-17 20:52:56 -07001950 { // acquire lock
1951 AutoMutex _l(mLock);
1952
Jeff Browna665ca82010-09-08 11:49:43 -07001953 injectedEntry = createEntryFromInjectedInputEventLocked(event);
1954 if (! injectedEntry) {
1955 return INPUT_EVENT_INJECTION_FAILED;
1956 }
1957
Jeff Brown51d45a72010-06-17 20:52:56 -07001958 injectedEntry->refCount += 1;
1959 injectedEntry->injectorPid = injectorPid;
1960 injectedEntry->injectorUid = injectorUid;
1961
Jeff Brownf67c53e2010-07-28 15:48:59 -07001962 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
1963 injectedEntry->injectionIsAsync = true;
1964 }
1965
Jeff Browna665ca82010-09-08 11:49:43 -07001966 needWake = enqueueInboundEventLocked(injectedEntry);
Jeff Brown51d45a72010-06-17 20:52:56 -07001967 } // release lock
1968
Jeff Browna665ca82010-09-08 11:49:43 -07001969 if (needWake) {
Jeff Brown59abe7e2010-09-13 23:17:30 -07001970 mLooper->wake();
Jeff Brown51d45a72010-06-17 20:52:56 -07001971 }
1972
1973 int32_t injectionResult;
1974 { // acquire lock
1975 AutoMutex _l(mLock);
1976
Jeff Brownf67c53e2010-07-28 15:48:59 -07001977 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
1978 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1979 } else {
1980 for (;;) {
1981 injectionResult = injectedEntry->injectionResult;
1982 if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
1983 break;
1984 }
Jeff Brown51d45a72010-06-17 20:52:56 -07001985
Jeff Brown51d45a72010-06-17 20:52:56 -07001986 nsecs_t remainingTimeout = endTime - now();
1987 if (remainingTimeout <= 0) {
Jeff Brownf67c53e2010-07-28 15:48:59 -07001988#if DEBUG_INJECTION
1989 LOGD("injectInputEvent - Timed out waiting for injection result "
1990 "to become available.");
1991#endif
Jeff Brown51d45a72010-06-17 20:52:56 -07001992 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1993 break;
1994 }
1995
Jeff Brownf67c53e2010-07-28 15:48:59 -07001996 mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
1997 }
1998
1999 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
2000 && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
Jeff Brown53a415e2010-09-15 15:18:56 -07002001 while (injectedEntry->pendingForegroundDispatches != 0) {
Jeff Brownf67c53e2010-07-28 15:48:59 -07002002#if DEBUG_INJECTION
Jeff Brown53a415e2010-09-15 15:18:56 -07002003 LOGD("injectInputEvent - Waiting for %d pending foreground dispatches.",
2004 injectedEntry->pendingForegroundDispatches);
Jeff Brownf67c53e2010-07-28 15:48:59 -07002005#endif
2006 nsecs_t remainingTimeout = endTime - now();
2007 if (remainingTimeout <= 0) {
2008#if DEBUG_INJECTION
Jeff Brown53a415e2010-09-15 15:18:56 -07002009 LOGD("injectInputEvent - Timed out waiting for pending foreground "
Jeff Brownf67c53e2010-07-28 15:48:59 -07002010 "dispatches to finish.");
2011#endif
2012 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
2013 break;
2014 }
2015
2016 mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
2017 }
Jeff Brown51d45a72010-06-17 20:52:56 -07002018 }
2019 }
2020
2021 mAllocator.releaseEventEntry(injectedEntry);
2022 } // release lock
2023
Jeff Brownf67c53e2010-07-28 15:48:59 -07002024#if DEBUG_INJECTION
2025 LOGD("injectInputEvent - Finished with result %d. "
2026 "injectorPid=%d, injectorUid=%d",
2027 injectionResult, injectorPid, injectorUid);
2028#endif
2029
Jeff Brown51d45a72010-06-17 20:52:56 -07002030 return injectionResult;
2031}
2032
2033void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
2034 if (entry->isInjected()) {
2035#if DEBUG_INJECTION
2036 LOGD("Setting input event injection result to %d. "
2037 "injectorPid=%d, injectorUid=%d",
2038 injectionResult, entry->injectorPid, entry->injectorUid);
2039#endif
2040
Jeff Brownf67c53e2010-07-28 15:48:59 -07002041 if (entry->injectionIsAsync) {
2042 // Log the outcome since the injector did not wait for the injection result.
2043 switch (injectionResult) {
2044 case INPUT_EVENT_INJECTION_SUCCEEDED:
2045 LOGV("Asynchronous input event injection succeeded.");
2046 break;
2047 case INPUT_EVENT_INJECTION_FAILED:
2048 LOGW("Asynchronous input event injection failed.");
2049 break;
2050 case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
2051 LOGW("Asynchronous input event injection permission denied.");
2052 break;
2053 case INPUT_EVENT_INJECTION_TIMED_OUT:
2054 LOGW("Asynchronous input event injection timed out.");
2055 break;
2056 }
2057 }
2058
Jeff Brown51d45a72010-06-17 20:52:56 -07002059 entry->injectionResult = injectionResult;
2060 mInjectionResultAvailableCondition.broadcast();
2061 }
2062}
2063
Jeff Brown53a415e2010-09-15 15:18:56 -07002064void InputDispatcher::decrementPendingForegroundDispatchesLocked(EventEntry* entry) {
2065 entry->pendingForegroundDispatches -= 1;
Jeff Brownf67c53e2010-07-28 15:48:59 -07002066
Jeff Brown53a415e2010-09-15 15:18:56 -07002067 if (entry->isInjected() && entry->pendingForegroundDispatches == 0) {
Jeff Brownf67c53e2010-07-28 15:48:59 -07002068 mInjectionSyncFinishedCondition.broadcast();
2069 }
Jeff Brown51d45a72010-06-17 20:52:56 -07002070}
2071
Jeff Browna665ca82010-09-08 11:49:43 -07002072static bool isValidKeyAction(int32_t action) {
2073 switch (action) {
2074 case AKEY_EVENT_ACTION_DOWN:
2075 case AKEY_EVENT_ACTION_UP:
2076 return true;
2077 default:
2078 return false;
2079 }
2080}
2081
2082static bool isValidMotionAction(int32_t action) {
2083 switch (action & AMOTION_EVENT_ACTION_MASK) {
2084 case AMOTION_EVENT_ACTION_DOWN:
2085 case AMOTION_EVENT_ACTION_UP:
2086 case AMOTION_EVENT_ACTION_CANCEL:
2087 case AMOTION_EVENT_ACTION_MOVE:
2088 case AMOTION_EVENT_ACTION_POINTER_DOWN:
2089 case AMOTION_EVENT_ACTION_POINTER_UP:
2090 case AMOTION_EVENT_ACTION_OUTSIDE:
2091 return true;
2092 default:
2093 return false;
2094 }
2095}
2096
2097InputDispatcher::EventEntry* InputDispatcher::createEntryFromInjectedInputEventLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07002098 const InputEvent* event) {
2099 switch (event->getType()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07002100 case AINPUT_EVENT_TYPE_KEY: {
Jeff Brown51d45a72010-06-17 20:52:56 -07002101 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
Jeff Browna665ca82010-09-08 11:49:43 -07002102 if (! isValidKeyAction(keyEvent->getAction())) {
2103 LOGE("Dropping injected key event since it has invalid action code 0x%x",
2104 keyEvent->getAction());
2105 return NULL;
2106 }
2107
Jeff Brownaf30ff62010-09-01 17:01:00 -07002108 uint32_t policyFlags = POLICY_FLAG_INJECTED;
Jeff Brown51d45a72010-06-17 20:52:56 -07002109
2110 KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
Jeff Brown5c1ed842010-07-14 18:48:53 -07002111 keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -07002112 keyEvent->getAction(), keyEvent->getFlags(),
2113 keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
2114 keyEvent->getRepeatCount(), keyEvent->getDownTime());
2115 return keyEntry;
2116 }
2117
Jeff Brown5c1ed842010-07-14 18:48:53 -07002118 case AINPUT_EVENT_TYPE_MOTION: {
Jeff Brown51d45a72010-06-17 20:52:56 -07002119 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
Jeff Browna665ca82010-09-08 11:49:43 -07002120 if (! isValidMotionAction(motionEvent->getAction())) {
2121 LOGE("Dropping injected motion event since it has invalid action code 0x%x.",
2122 motionEvent->getAction());
2123 return NULL;
2124 }
2125 if (motionEvent->getPointerCount() == 0
2126 || motionEvent->getPointerCount() > MAX_POINTERS) {
2127 LOGE("Dropping injected motion event since it has an invalid pointer count %d.",
2128 motionEvent->getPointerCount());
2129 }
2130
Jeff Brownaf30ff62010-09-01 17:01:00 -07002131 uint32_t policyFlags = POLICY_FLAG_INJECTED;
Jeff Brown51d45a72010-06-17 20:52:56 -07002132
2133 const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
2134 const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
2135 size_t pointerCount = motionEvent->getPointerCount();
2136
2137 MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
Jeff Brown5c1ed842010-07-14 18:48:53 -07002138 motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
Jeff Brownaf30ff62010-09-01 17:01:00 -07002139 motionEvent->getAction(), motionEvent->getFlags(),
2140 motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
Jeff Brown51d45a72010-06-17 20:52:56 -07002141 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
2142 motionEvent->getDownTime(), uint32_t(pointerCount),
2143 motionEvent->getPointerIds(), samplePointerCoords);
2144 for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
2145 sampleEventTimes += 1;
2146 samplePointerCoords += pointerCount;
2147 mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
2148 }
2149 return motionEntry;
2150 }
2151
2152 default:
2153 assert(false);
2154 return NULL;
2155 }
2156}
2157
Jeff Browna665ca82010-09-08 11:49:43 -07002158void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
2159#if DEBUG_FOCUS
2160 LOGD("setInputWindows");
2161#endif
2162 { // acquire lock
2163 AutoMutex _l(mLock);
2164
Jeff Brown405a1d32010-09-16 12:31:46 -07002165 // Clear old window pointers but remember their associated channels.
2166 mFocusedWindow = NULL;
Jeff Brown53a415e2010-09-15 15:18:56 -07002167
Jeff Browna665ca82010-09-08 11:49:43 -07002168 sp<InputChannel> touchedWindowChannel;
2169 if (mTouchedWindow) {
2170 touchedWindowChannel = mTouchedWindow->inputChannel;
2171 mTouchedWindow = NULL;
2172 }
2173 size_t numTouchedWallpapers = mTouchedWallpaperWindows.size();
2174 if (numTouchedWallpapers != 0) {
2175 for (size_t i = 0; i < numTouchedWallpapers; i++) {
2176 mTempTouchedWallpaperChannels.push(mTouchedWallpaperWindows[i]->inputChannel);
2177 }
2178 mTouchedWallpaperWindows.clear();
2179 }
Jeff Browna665ca82010-09-08 11:49:43 -07002180 mWallpaperWindows.clear();
Jeff Browna665ca82010-09-08 11:49:43 -07002181 mWindows.clear();
Jeff Brown405a1d32010-09-16 12:31:46 -07002182
2183 // Loop over new windows and rebuild the necessary window pointers for
2184 // tracking focus and touch.
Jeff Browna665ca82010-09-08 11:49:43 -07002185 mWindows.appendVector(inputWindows);
2186
2187 size_t numWindows = mWindows.size();
2188 for (size_t i = 0; i < numWindows; i++) {
2189 InputWindow* window = & mWindows.editItemAt(i);
2190 if (window->hasFocus) {
2191 mFocusedWindow = window;
2192 }
2193
2194 if (window->layoutParamsType == InputWindow::TYPE_WALLPAPER) {
2195 mWallpaperWindows.push(window);
2196
2197 for (size_t j = 0; j < numTouchedWallpapers; j++) {
2198 if (window->inputChannel == mTempTouchedWallpaperChannels[i]) {
2199 mTouchedWallpaperWindows.push(window);
2200 }
2201 }
2202 }
2203
2204 if (window->inputChannel == touchedWindowChannel) {
2205 mTouchedWindow = window;
2206 }
2207 }
Jeff Browna665ca82010-09-08 11:49:43 -07002208 mTempTouchedWallpaperChannels.clear();
2209
Jeff Browna665ca82010-09-08 11:49:43 -07002210#if DEBUG_FOCUS
2211 logDispatchStateLocked();
2212#endif
2213 } // release lock
2214
2215 // Wake up poll loop since it may need to make new input dispatching choices.
Jeff Brown59abe7e2010-09-13 23:17:30 -07002216 mLooper->wake();
Jeff Browna665ca82010-09-08 11:49:43 -07002217}
2218
2219void InputDispatcher::setFocusedApplication(const InputApplication* inputApplication) {
2220#if DEBUG_FOCUS
2221 LOGD("setFocusedApplication");
2222#endif
2223 { // acquire lock
2224 AutoMutex _l(mLock);
2225
2226 releaseFocusedApplicationLocked();
2227
2228 if (inputApplication) {
2229 mFocusedApplicationStorage = *inputApplication;
2230 mFocusedApplication = & mFocusedApplicationStorage;
2231 }
2232
2233#if DEBUG_FOCUS
2234 logDispatchStateLocked();
2235#endif
2236 } // release lock
2237
2238 // Wake up poll loop since it may need to make new input dispatching choices.
Jeff Brown59abe7e2010-09-13 23:17:30 -07002239 mLooper->wake();
Jeff Browna665ca82010-09-08 11:49:43 -07002240}
2241
2242void InputDispatcher::releaseFocusedApplicationLocked() {
2243 if (mFocusedApplication) {
2244 mFocusedApplication = NULL;
2245 mFocusedApplicationStorage.handle.clear();
2246 }
2247}
2248
2249void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
2250#if DEBUG_FOCUS
2251 LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
2252#endif
2253
2254 bool changed;
2255 { // acquire lock
2256 AutoMutex _l(mLock);
2257
2258 if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
2259 if (mDispatchFrozen && ! frozen) {
2260 resetANRTimeoutsLocked();
2261 }
2262
2263 mDispatchEnabled = enabled;
2264 mDispatchFrozen = frozen;
2265 changed = true;
2266 } else {
2267 changed = false;
2268 }
2269
2270#if DEBUG_FOCUS
2271 logDispatchStateLocked();
2272#endif
2273 } // release lock
2274
2275 if (changed) {
2276 // Wake up poll loop since it may need to make new input dispatching choices.
Jeff Brown59abe7e2010-09-13 23:17:30 -07002277 mLooper->wake();
Jeff Browne839a582010-04-22 18:58:52 -07002278 }
2279}
2280
Jeff Browna665ca82010-09-08 11:49:43 -07002281void InputDispatcher::logDispatchStateLocked() {
2282 String8 dump;
2283 dumpDispatchStateLocked(dump);
Jeff Brown405a1d32010-09-16 12:31:46 -07002284
2285 char* text = dump.lockBuffer(dump.size());
2286 char* start = text;
2287 while (*start != '\0') {
2288 char* end = strchr(start, '\n');
2289 if (*end == '\n') {
2290 *(end++) = '\0';
2291 }
2292 LOGD("%s", start);
2293 start = end;
2294 }
Jeff Browna665ca82010-09-08 11:49:43 -07002295}
2296
2297void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
2298 dump.appendFormat(" dispatchEnabled: %d\n", mDispatchEnabled);
2299 dump.appendFormat(" dispatchFrozen: %d\n", mDispatchFrozen);
2300
2301 if (mFocusedApplication) {
2302 dump.appendFormat(" focusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
2303 mFocusedApplication->name.string(),
2304 mFocusedApplication->dispatchingTimeout / 1000000.0);
2305 } else {
2306 dump.append(" focusedApplication: <null>\n");
2307 }
Jeff Brown405a1d32010-09-16 12:31:46 -07002308 dump.appendFormat(" focusedWindow: name='%s'\n",
2309 mFocusedWindow != NULL ? mFocusedWindow->name.string() : "<null>");
2310 dump.appendFormat(" touchedWindow: name='%s', touchDown=%d\n",
2311 mTouchedWindow != NULL ? mTouchedWindow->name.string() : "<null>",
Jeff Browna665ca82010-09-08 11:49:43 -07002312 mTouchDown);
2313 for (size_t i = 0; i < mTouchedWallpaperWindows.size(); i++) {
Jeff Brown405a1d32010-09-16 12:31:46 -07002314 dump.appendFormat(" touchedWallpaperWindows[%d]: name='%s'\n",
2315 i, mTouchedWallpaperWindows[i]->name.string());
Jeff Browna665ca82010-09-08 11:49:43 -07002316 }
2317 for (size_t i = 0; i < mWindows.size(); i++) {
Jeff Brown405a1d32010-09-16 12:31:46 -07002318 dump.appendFormat(" windows[%d]: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
2319 "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
Jeff Browna665ca82010-09-08 11:49:43 -07002320 "frame=[%d,%d][%d,%d], "
2321 "visibleFrame=[%d,%d][%d,%d], "
2322 "touchableArea=[%d,%d][%d,%d], "
2323 "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
Jeff Brown405a1d32010-09-16 12:31:46 -07002324 i, mWindows[i].name.string(),
Jeff Browna665ca82010-09-08 11:49:43 -07002325 toString(mWindows[i].paused),
2326 toString(mWindows[i].hasFocus),
2327 toString(mWindows[i].hasWallpaper),
2328 toString(mWindows[i].visible),
Jeff Brown405a1d32010-09-16 12:31:46 -07002329 toString(mWindows[i].canReceiveKeys),
Jeff Browna665ca82010-09-08 11:49:43 -07002330 mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
Jeff Brown405a1d32010-09-16 12:31:46 -07002331 mWindows[i].layer,
Jeff Browna665ca82010-09-08 11:49:43 -07002332 mWindows[i].frameLeft, mWindows[i].frameTop,
2333 mWindows[i].frameRight, mWindows[i].frameBottom,
2334 mWindows[i].visibleFrameLeft, mWindows[i].visibleFrameTop,
2335 mWindows[i].visibleFrameRight, mWindows[i].visibleFrameBottom,
2336 mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop,
2337 mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom,
2338 mWindows[i].ownerPid, mWindows[i].ownerUid,
2339 mWindows[i].dispatchingTimeout / 1000000.0);
2340 }
2341
2342 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
2343 const sp<InputChannel>& channel = mMonitoringChannels[i];
2344 dump.appendFormat(" monitoringChannel[%d]: '%s'\n",
2345 i, channel->getName().string());
2346 }
2347
Jeff Brown53a415e2010-09-15 15:18:56 -07002348 dump.appendFormat(" inboundQueue: length=%u", mInboundQueue.count());
2349
Jeff Browna665ca82010-09-08 11:49:43 -07002350 for (size_t i = 0; i < mActiveConnections.size(); i++) {
2351 const Connection* connection = mActiveConnections[i];
Jeff Brown53a415e2010-09-15 15:18:56 -07002352 dump.appendFormat(" activeConnection[%d]: '%s', status=%s, outboundQueueLength=%u"
Jeff Browna665ca82010-09-08 11:49:43 -07002353 "inputState.isNeutral=%s, inputState.isOutOfSync=%s\n",
2354 i, connection->getInputChannelName(), connection->getStatusLabel(),
Jeff Brown53a415e2010-09-15 15:18:56 -07002355 connection->outboundQueue.count(),
Jeff Browna665ca82010-09-08 11:49:43 -07002356 toString(connection->inputState.isNeutral()),
2357 toString(connection->inputState.isOutOfSync()));
2358 }
2359
2360 if (isAppSwitchPendingLocked()) {
2361 dump.appendFormat(" appSwitch: pending, due in %01.1fms\n",
2362 (mAppSwitchDueTime - now()) / 1000000.0);
2363 } else {
2364 dump.append(" appSwitch: not pending\n");
2365 }
2366}
2367
2368status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
Jeff Brown54bc2812010-06-15 01:31:58 -07002369#if DEBUG_REGISTRATION
Jeff Browna665ca82010-09-08 11:49:43 -07002370 LOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().string(),
2371 toString(monitor));
Jeff Brown54bc2812010-06-15 01:31:58 -07002372#endif
2373
Jeff Browne839a582010-04-22 18:58:52 -07002374 { // acquire lock
2375 AutoMutex _l(mLock);
2376
Jeff Brown53a415e2010-09-15 15:18:56 -07002377 if (getConnectionIndexLocked(inputChannel) >= 0) {
Jeff Browne839a582010-04-22 18:58:52 -07002378 LOGW("Attempted to register already registered input channel '%s'",
2379 inputChannel->getName().string());
2380 return BAD_VALUE;
2381 }
2382
2383 sp<Connection> connection = new Connection(inputChannel);
2384 status_t status = connection->initialize();
2385 if (status) {
2386 LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
2387 inputChannel->getName().string(), status);
2388 return status;
2389 }
2390
Jeff Brown0cacb872010-08-17 15:59:26 -07002391 int32_t receiveFd = inputChannel->getReceivePipeFd();
Jeff Browne839a582010-04-22 18:58:52 -07002392 mConnectionsByReceiveFd.add(receiveFd, connection);
Jeff Brown54bc2812010-06-15 01:31:58 -07002393
Jeff Browna665ca82010-09-08 11:49:43 -07002394 if (monitor) {
2395 mMonitoringChannels.push(inputChannel);
2396 }
2397
Jeff Brown59abe7e2010-09-13 23:17:30 -07002398 mLooper->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
Jeff Brown0cacb872010-08-17 15:59:26 -07002399
Jeff Brown54bc2812010-06-15 01:31:58 -07002400 runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07002401 } // release lock
Jeff Browne839a582010-04-22 18:58:52 -07002402 return OK;
2403}
2404
2405status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown54bc2812010-06-15 01:31:58 -07002406#if DEBUG_REGISTRATION
Jeff Brown50de30a2010-06-22 01:27:15 -07002407 LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
Jeff Brown54bc2812010-06-15 01:31:58 -07002408#endif
2409
Jeff Browne839a582010-04-22 18:58:52 -07002410 { // acquire lock
2411 AutoMutex _l(mLock);
2412
Jeff Brown53a415e2010-09-15 15:18:56 -07002413 ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
Jeff Browne839a582010-04-22 18:58:52 -07002414 if (connectionIndex < 0) {
2415 LOGW("Attempted to unregister already unregistered input channel '%s'",
2416 inputChannel->getName().string());
2417 return BAD_VALUE;
2418 }
2419
2420 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
2421 mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
2422
2423 connection->status = Connection::STATUS_ZOMBIE;
2424
Jeff Browna665ca82010-09-08 11:49:43 -07002425 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
2426 if (mMonitoringChannels[i] == inputChannel) {
2427 mMonitoringChannels.removeAt(i);
2428 break;
2429 }
2430 }
2431
Jeff Brown59abe7e2010-09-13 23:17:30 -07002432 mLooper->removeFd(inputChannel->getReceivePipeFd());
Jeff Brown0cacb872010-08-17 15:59:26 -07002433
Jeff Brown51d45a72010-06-17 20:52:56 -07002434 nsecs_t currentTime = now();
2435 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -07002436
2437 runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07002438 } // release lock
2439
Jeff Browne839a582010-04-22 18:58:52 -07002440 // Wake the poll loop because removing the connection may have changed the current
2441 // synchronization state.
Jeff Brown59abe7e2010-09-13 23:17:30 -07002442 mLooper->wake();
Jeff Browne839a582010-04-22 18:58:52 -07002443 return OK;
2444}
2445
Jeff Brown53a415e2010-09-15 15:18:56 -07002446ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
Jeff Brown0cacb872010-08-17 15:59:26 -07002447 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(inputChannel->getReceivePipeFd());
2448 if (connectionIndex >= 0) {
2449 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
2450 if (connection->inputChannel.get() == inputChannel.get()) {
2451 return connectionIndex;
2452 }
2453 }
2454
2455 return -1;
2456}
2457
Jeff Browne839a582010-04-22 18:58:52 -07002458void InputDispatcher::activateConnectionLocked(Connection* connection) {
2459 for (size_t i = 0; i < mActiveConnections.size(); i++) {
2460 if (mActiveConnections.itemAt(i) == connection) {
2461 return;
2462 }
2463 }
2464 mActiveConnections.add(connection);
2465}
2466
2467void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
2468 for (size_t i = 0; i < mActiveConnections.size(); i++) {
2469 if (mActiveConnections.itemAt(i) == connection) {
2470 mActiveConnections.removeAt(i);
2471 return;
2472 }
2473 }
2474}
2475
Jeff Brown54bc2812010-06-15 01:31:58 -07002476void InputDispatcher::onDispatchCycleStartedLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07002477 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07002478}
2479
Jeff Brown54bc2812010-06-15 01:31:58 -07002480void InputDispatcher::onDispatchCycleFinishedLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07002481 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07002482}
2483
Jeff Brown54bc2812010-06-15 01:31:58 -07002484void InputDispatcher::onDispatchCycleBrokenLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07002485 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07002486 LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
2487 connection->getInputChannelName());
2488
Jeff Brown54bc2812010-06-15 01:31:58 -07002489 CommandEntry* commandEntry = postCommandLocked(
2490 & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07002491 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07002492}
2493
Jeff Brown53a415e2010-09-15 15:18:56 -07002494void InputDispatcher::onANRLocked(
2495 nsecs_t currentTime, const InputApplication* application, const InputWindow* window,
2496 nsecs_t eventTime, nsecs_t waitStartTime) {
2497 LOGI("Application is not responding: %s. "
2498 "%01.1fms since event, %01.1fms since wait started",
2499 getApplicationWindowLabelLocked(application, window).string(),
2500 (currentTime - eventTime) / 1000000.0,
2501 (currentTime - waitStartTime) / 1000000.0);
2502
2503 CommandEntry* commandEntry = postCommandLocked(
2504 & InputDispatcher::doNotifyANRLockedInterruptible);
2505 if (application) {
2506 commandEntry->inputApplicationHandle = application->handle;
2507 }
2508 if (window) {
2509 commandEntry->inputChannel = window->inputChannel;
2510 }
2511}
2512
Jeff Browna665ca82010-09-08 11:49:43 -07002513void InputDispatcher::doNotifyConfigurationChangedInterruptible(
2514 CommandEntry* commandEntry) {
2515 mLock.unlock();
2516
2517 mPolicy->notifyConfigurationChanged(commandEntry->eventTime);
2518
2519 mLock.lock();
2520}
2521
Jeff Brown54bc2812010-06-15 01:31:58 -07002522void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
2523 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07002524 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07002525
Jeff Brown51d45a72010-06-17 20:52:56 -07002526 if (connection->status != Connection::STATUS_ZOMBIE) {
2527 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07002528
Jeff Brown51d45a72010-06-17 20:52:56 -07002529 mPolicy->notifyInputChannelBroken(connection->inputChannel);
2530
2531 mLock.lock();
2532 }
Jeff Brown54bc2812010-06-15 01:31:58 -07002533}
2534
Jeff Brown53a415e2010-09-15 15:18:56 -07002535void InputDispatcher::doNotifyANRLockedInterruptible(
Jeff Brown54bc2812010-06-15 01:31:58 -07002536 CommandEntry* commandEntry) {
Jeff Brown53a415e2010-09-15 15:18:56 -07002537 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07002538
Jeff Brown53a415e2010-09-15 15:18:56 -07002539 nsecs_t newTimeout = mPolicy->notifyANR(
2540 commandEntry->inputApplicationHandle, commandEntry->inputChannel);
Jeff Brown54bc2812010-06-15 01:31:58 -07002541
Jeff Brown53a415e2010-09-15 15:18:56 -07002542 mLock.lock();
Jeff Brown51d45a72010-06-17 20:52:56 -07002543
Jeff Brown53a415e2010-09-15 15:18:56 -07002544 resumeAfterTargetsNotReadyTimeoutLocked(newTimeout, commandEntry->inputChannel);
Jeff Brown54bc2812010-06-15 01:31:58 -07002545}
2546
Jeff Browna665ca82010-09-08 11:49:43 -07002547void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
2548 CommandEntry* commandEntry) {
2549 KeyEntry* entry = commandEntry->keyEntry;
2550 mReusableKeyEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
2551 entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
2552 entry->downTime, entry->eventTime);
2553
2554 mLock.unlock();
2555
2556 bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputChannel,
2557 & mReusableKeyEvent, entry->policyFlags);
2558
2559 mLock.lock();
2560
2561 entry->interceptKeyResult = consumed
2562 ? KeyEntry::INTERCEPT_KEY_RESULT_SKIP
2563 : KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
2564 mAllocator.releaseKeyEntry(entry);
2565}
2566
2567void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
2568 mLock.unlock();
2569
2570 mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->windowType,
2571 commandEntry->userActivityEventType);
2572
2573 mLock.lock();
2574}
2575
Jeff Brown53a415e2010-09-15 15:18:56 -07002576void InputDispatcher::updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
2577 int32_t injectionResult, nsecs_t timeSpentWaitingForApplication) {
2578 // TODO Write some statistics about how long we spend waiting.
Jeff Browna665ca82010-09-08 11:49:43 -07002579}
2580
2581void InputDispatcher::dump(String8& dump) {
2582 dumpDispatchStateLocked(dump);
2583}
2584
Jeff Brown54bc2812010-06-15 01:31:58 -07002585
Jeff Brown53a415e2010-09-15 15:18:56 -07002586// --- InputDispatcher::Queue ---
2587
2588template <typename T>
2589uint32_t InputDispatcher::Queue<T>::count() const {
2590 uint32_t result = 0;
2591 for (const T* entry = headSentinel.next; entry != & tailSentinel; entry = entry->next) {
2592 result += 1;
2593 }
2594 return result;
2595}
2596
2597
Jeff Browne839a582010-04-22 18:58:52 -07002598// --- InputDispatcher::Allocator ---
2599
2600InputDispatcher::Allocator::Allocator() {
2601}
2602
Jeff Brown51d45a72010-06-17 20:52:56 -07002603void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
2604 nsecs_t eventTime) {
2605 entry->type = type;
2606 entry->refCount = 1;
2607 entry->dispatchInProgress = false;
Christopher Tated974e002010-06-23 16:50:30 -07002608 entry->eventTime = eventTime;
Jeff Brown51d45a72010-06-17 20:52:56 -07002609 entry->injectionResult = INPUT_EVENT_INJECTION_PENDING;
Jeff Brownf67c53e2010-07-28 15:48:59 -07002610 entry->injectionIsAsync = false;
Jeff Brown51d45a72010-06-17 20:52:56 -07002611 entry->injectorPid = -1;
2612 entry->injectorUid = -1;
Jeff Brown53a415e2010-09-15 15:18:56 -07002613 entry->pendingForegroundDispatches = 0;
Jeff Brown51d45a72010-06-17 20:52:56 -07002614}
2615
Jeff Browne839a582010-04-22 18:58:52 -07002616InputDispatcher::ConfigurationChangedEntry*
Jeff Brown51d45a72010-06-17 20:52:56 -07002617InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
Jeff Browne839a582010-04-22 18:58:52 -07002618 ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07002619 initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime);
Jeff Browne839a582010-04-22 18:58:52 -07002620 return entry;
2621}
2622
Jeff Brown51d45a72010-06-17 20:52:56 -07002623InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07002624 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
Jeff Brown51d45a72010-06-17 20:52:56 -07002625 int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
2626 int32_t repeatCount, nsecs_t downTime) {
Jeff Browne839a582010-04-22 18:58:52 -07002627 KeyEntry* entry = mKeyEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07002628 initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime);
2629
2630 entry->deviceId = deviceId;
Jeff Brown5c1ed842010-07-14 18:48:53 -07002631 entry->source = source;
Jeff Brown51d45a72010-06-17 20:52:56 -07002632 entry->policyFlags = policyFlags;
2633 entry->action = action;
2634 entry->flags = flags;
2635 entry->keyCode = keyCode;
2636 entry->scanCode = scanCode;
2637 entry->metaState = metaState;
2638 entry->repeatCount = repeatCount;
2639 entry->downTime = downTime;
Jeff Browna665ca82010-09-08 11:49:43 -07002640 entry->syntheticRepeat = false;
2641 entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
Jeff Browne839a582010-04-22 18:58:52 -07002642 return entry;
2643}
2644
Jeff Brown51d45a72010-06-17 20:52:56 -07002645InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
Jeff Brownaf30ff62010-09-01 17:01:00 -07002646 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
Jeff Brown51d45a72010-06-17 20:52:56 -07002647 int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
2648 nsecs_t downTime, uint32_t pointerCount,
2649 const int32_t* pointerIds, const PointerCoords* pointerCoords) {
Jeff Browne839a582010-04-22 18:58:52 -07002650 MotionEntry* entry = mMotionEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07002651 initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime);
2652
2653 entry->eventTime = eventTime;
2654 entry->deviceId = deviceId;
Jeff Brown5c1ed842010-07-14 18:48:53 -07002655 entry->source = source;
Jeff Brown51d45a72010-06-17 20:52:56 -07002656 entry->policyFlags = policyFlags;
2657 entry->action = action;
Jeff Brownaf30ff62010-09-01 17:01:00 -07002658 entry->flags = flags;
Jeff Brown51d45a72010-06-17 20:52:56 -07002659 entry->metaState = metaState;
2660 entry->edgeFlags = edgeFlags;
2661 entry->xPrecision = xPrecision;
2662 entry->yPrecision = yPrecision;
2663 entry->downTime = downTime;
2664 entry->pointerCount = pointerCount;
2665 entry->firstSample.eventTime = eventTime;
Jeff Browne839a582010-04-22 18:58:52 -07002666 entry->firstSample.next = NULL;
Jeff Brown51d45a72010-06-17 20:52:56 -07002667 entry->lastSample = & entry->firstSample;
2668 for (uint32_t i = 0; i < pointerCount; i++) {
2669 entry->pointerIds[i] = pointerIds[i];
2670 entry->firstSample.pointerCoords[i] = pointerCoords[i];
2671 }
Jeff Browne839a582010-04-22 18:58:52 -07002672 return entry;
2673}
2674
2675InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
Jeff Browna665ca82010-09-08 11:49:43 -07002676 EventEntry* eventEntry,
Jeff Brown53a415e2010-09-15 15:18:56 -07002677 int32_t targetFlags, float xOffset, float yOffset) {
Jeff Browne839a582010-04-22 18:58:52 -07002678 DispatchEntry* entry = mDispatchEntryPool.alloc();
2679 entry->eventEntry = eventEntry;
2680 eventEntry->refCount += 1;
Jeff Browna665ca82010-09-08 11:49:43 -07002681 entry->targetFlags = targetFlags;
2682 entry->xOffset = xOffset;
2683 entry->yOffset = yOffset;
Jeff Browna665ca82010-09-08 11:49:43 -07002684 entry->inProgress = false;
2685 entry->headMotionSample = NULL;
2686 entry->tailMotionSample = NULL;
Jeff Browne839a582010-04-22 18:58:52 -07002687 return entry;
2688}
2689
Jeff Brown54bc2812010-06-15 01:31:58 -07002690InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
2691 CommandEntry* entry = mCommandEntryPool.alloc();
2692 entry->command = command;
2693 return entry;
2694}
2695
Jeff Browne839a582010-04-22 18:58:52 -07002696void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
2697 switch (entry->type) {
2698 case EventEntry::TYPE_CONFIGURATION_CHANGED:
2699 releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
2700 break;
2701 case EventEntry::TYPE_KEY:
2702 releaseKeyEntry(static_cast<KeyEntry*>(entry));
2703 break;
2704 case EventEntry::TYPE_MOTION:
2705 releaseMotionEntry(static_cast<MotionEntry*>(entry));
2706 break;
2707 default:
2708 assert(false);
2709 break;
2710 }
2711}
2712
2713void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
2714 ConfigurationChangedEntry* entry) {
2715 entry->refCount -= 1;
2716 if (entry->refCount == 0) {
2717 mConfigurationChangeEntryPool.free(entry);
2718 } else {
2719 assert(entry->refCount > 0);
2720 }
2721}
2722
2723void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
2724 entry->refCount -= 1;
2725 if (entry->refCount == 0) {
2726 mKeyEntryPool.free(entry);
2727 } else {
2728 assert(entry->refCount > 0);
2729 }
2730}
2731
2732void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
2733 entry->refCount -= 1;
2734 if (entry->refCount == 0) {
Jeff Brown54bc2812010-06-15 01:31:58 -07002735 for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
2736 MotionSample* next = sample->next;
2737 mMotionSamplePool.free(sample);
2738 sample = next;
2739 }
Jeff Browne839a582010-04-22 18:58:52 -07002740 mMotionEntryPool.free(entry);
2741 } else {
2742 assert(entry->refCount > 0);
2743 }
2744}
2745
2746void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
2747 releaseEventEntry(entry->eventEntry);
2748 mDispatchEntryPool.free(entry);
2749}
2750
Jeff Brown54bc2812010-06-15 01:31:58 -07002751void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
2752 mCommandEntryPool.free(entry);
2753}
2754
Jeff Browne839a582010-04-22 18:58:52 -07002755void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
Jeff Brown51d45a72010-06-17 20:52:56 -07002756 nsecs_t eventTime, const PointerCoords* pointerCoords) {
Jeff Browne839a582010-04-22 18:58:52 -07002757 MotionSample* sample = mMotionSamplePool.alloc();
2758 sample->eventTime = eventTime;
Jeff Brown51d45a72010-06-17 20:52:56 -07002759 uint32_t pointerCount = motionEntry->pointerCount;
2760 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Browne839a582010-04-22 18:58:52 -07002761 sample->pointerCoords[i] = pointerCoords[i];
2762 }
2763
2764 sample->next = NULL;
2765 motionEntry->lastSample->next = sample;
2766 motionEntry->lastSample = sample;
2767}
2768
Jeff Browna665ca82010-09-08 11:49:43 -07002769
2770// --- InputDispatcher::EventEntry ---
2771
2772void InputDispatcher::EventEntry::recycle() {
2773 injectionResult = INPUT_EVENT_INJECTION_PENDING;
2774 dispatchInProgress = false;
Jeff Brown53a415e2010-09-15 15:18:56 -07002775 pendingForegroundDispatches = 0;
Jeff Browna665ca82010-09-08 11:49:43 -07002776}
2777
2778
2779// --- InputDispatcher::KeyEntry ---
2780
2781void InputDispatcher::KeyEntry::recycle() {
2782 EventEntry::recycle();
2783 syntheticRepeat = false;
2784 interceptKeyResult = INTERCEPT_KEY_RESULT_UNKNOWN;
2785}
2786
2787
Jeff Brown542412c2010-08-18 15:51:08 -07002788// --- InputDispatcher::MotionEntry ---
2789
2790uint32_t InputDispatcher::MotionEntry::countSamples() const {
2791 uint32_t count = 1;
2792 for (MotionSample* sample = firstSample.next; sample != NULL; sample = sample->next) {
2793 count += 1;
2794 }
2795 return count;
2796}
2797
Jeff Browna665ca82010-09-08 11:49:43 -07002798
2799// --- InputDispatcher::InputState ---
2800
2801InputDispatcher::InputState::InputState() :
2802 mIsOutOfSync(false) {
2803}
2804
2805InputDispatcher::InputState::~InputState() {
2806}
2807
2808bool InputDispatcher::InputState::isNeutral() const {
2809 return mKeyMementos.isEmpty() && mMotionMementos.isEmpty();
2810}
2811
2812bool InputDispatcher::InputState::isOutOfSync() const {
2813 return mIsOutOfSync;
2814}
2815
2816void InputDispatcher::InputState::setOutOfSync() {
2817 if (! isNeutral()) {
2818 mIsOutOfSync = true;
2819 }
2820}
2821
2822void InputDispatcher::InputState::resetOutOfSync() {
2823 mIsOutOfSync = false;
2824}
2825
2826InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackEvent(
2827 const EventEntry* entry) {
2828 switch (entry->type) {
2829 case EventEntry::TYPE_KEY:
2830 return trackKey(static_cast<const KeyEntry*>(entry));
2831
2832 case EventEntry::TYPE_MOTION:
2833 return trackMotion(static_cast<const MotionEntry*>(entry));
2834
2835 default:
2836 return CONSISTENT;
2837 }
2838}
2839
2840InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackKey(
2841 const KeyEntry* entry) {
2842 int32_t action = entry->action;
2843 for (size_t i = 0; i < mKeyMementos.size(); i++) {
2844 KeyMemento& memento = mKeyMementos.editItemAt(i);
2845 if (memento.deviceId == entry->deviceId
2846 && memento.source == entry->source
2847 && memento.keyCode == entry->keyCode
2848 && memento.scanCode == entry->scanCode) {
2849 switch (action) {
2850 case AKEY_EVENT_ACTION_UP:
2851 mKeyMementos.removeAt(i);
2852 if (isNeutral()) {
2853 mIsOutOfSync = false;
2854 }
2855 return CONSISTENT;
2856
2857 case AKEY_EVENT_ACTION_DOWN:
2858 return TOLERABLE;
2859
2860 default:
2861 return BROKEN;
2862 }
2863 }
2864 }
2865
2866 switch (action) {
2867 case AKEY_EVENT_ACTION_DOWN: {
2868 mKeyMementos.push();
2869 KeyMemento& memento = mKeyMementos.editTop();
2870 memento.deviceId = entry->deviceId;
2871 memento.source = entry->source;
2872 memento.keyCode = entry->keyCode;
2873 memento.scanCode = entry->scanCode;
2874 memento.downTime = entry->downTime;
2875 return CONSISTENT;
2876 }
2877
2878 default:
2879 return BROKEN;
2880 }
2881}
2882
2883InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackMotion(
2884 const MotionEntry* entry) {
2885 int32_t action = entry->action & AMOTION_EVENT_ACTION_MASK;
2886 for (size_t i = 0; i < mMotionMementos.size(); i++) {
2887 MotionMemento& memento = mMotionMementos.editItemAt(i);
2888 if (memento.deviceId == entry->deviceId
2889 && memento.source == entry->source) {
2890 switch (action) {
2891 case AMOTION_EVENT_ACTION_UP:
2892 case AMOTION_EVENT_ACTION_CANCEL:
2893 mMotionMementos.removeAt(i);
2894 if (isNeutral()) {
2895 mIsOutOfSync = false;
2896 }
2897 return CONSISTENT;
2898
2899 case AMOTION_EVENT_ACTION_DOWN:
2900 return TOLERABLE;
2901
2902 case AMOTION_EVENT_ACTION_POINTER_DOWN:
2903 if (entry->pointerCount == memento.pointerCount + 1) {
2904 memento.setPointers(entry);
2905 return CONSISTENT;
2906 }
2907 return BROKEN;
2908
2909 case AMOTION_EVENT_ACTION_POINTER_UP:
2910 if (entry->pointerCount == memento.pointerCount - 1) {
2911 memento.setPointers(entry);
2912 return CONSISTENT;
2913 }
2914 return BROKEN;
2915
2916 case AMOTION_EVENT_ACTION_MOVE:
2917 if (entry->pointerCount == memento.pointerCount) {
2918 return CONSISTENT;
2919 }
2920 return BROKEN;
2921
2922 default:
2923 return BROKEN;
2924 }
2925 }
2926 }
2927
2928 switch (action) {
2929 case AMOTION_EVENT_ACTION_DOWN: {
2930 mMotionMementos.push();
2931 MotionMemento& memento = mMotionMementos.editTop();
2932 memento.deviceId = entry->deviceId;
2933 memento.source = entry->source;
2934 memento.xPrecision = entry->xPrecision;
2935 memento.yPrecision = entry->yPrecision;
2936 memento.downTime = entry->downTime;
2937 memento.setPointers(entry);
2938 return CONSISTENT;
2939 }
2940
2941 default:
2942 return BROKEN;
2943 }
2944}
2945
2946void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) {
2947 pointerCount = entry->pointerCount;
2948 for (uint32_t i = 0; i < entry->pointerCount; i++) {
2949 pointerIds[i] = entry->pointerIds[i];
2950 pointerCoords[i] = entry->lastSample->pointerCoords[i];
2951 }
2952}
2953
2954void InputDispatcher::InputState::synthesizeCancelationEvents(
2955 Allocator* allocator, Vector<EventEntry*>& outEvents) const {
2956 for (size_t i = 0; i < mKeyMementos.size(); i++) {
2957 const KeyMemento& memento = mKeyMementos.itemAt(i);
2958 outEvents.push(allocator->obtainKeyEntry(now(),
2959 memento.deviceId, memento.source, 0,
2960 AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_CANCELED,
2961 memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
2962 }
2963
2964 for (size_t i = 0; i < mMotionMementos.size(); i++) {
2965 const MotionMemento& memento = mMotionMementos.itemAt(i);
2966 outEvents.push(allocator->obtainMotionEntry(now(),
2967 memento.deviceId, memento.source, 0,
2968 AMOTION_EVENT_ACTION_CANCEL, 0, 0, 0,
2969 memento.xPrecision, memento.yPrecision, memento.downTime,
2970 memento.pointerCount, memento.pointerIds, memento.pointerCoords));
2971 }
2972}
2973
2974void InputDispatcher::InputState::clear() {
2975 mKeyMementos.clear();
2976 mMotionMementos.clear();
2977 mIsOutOfSync = false;
2978}
2979
2980
Jeff Browne839a582010-04-22 18:58:52 -07002981// --- InputDispatcher::Connection ---
2982
2983InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
2984 status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
Jeff Brown53a415e2010-09-15 15:18:56 -07002985 lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX) {
Jeff Browne839a582010-04-22 18:58:52 -07002986}
2987
2988InputDispatcher::Connection::~Connection() {
2989}
2990
2991status_t InputDispatcher::Connection::initialize() {
2992 return inputPublisher.initialize();
2993}
2994
Jeff Brown54bc2812010-06-15 01:31:58 -07002995const char* InputDispatcher::Connection::getStatusLabel() const {
2996 switch (status) {
2997 case STATUS_NORMAL:
2998 return "NORMAL";
2999
3000 case STATUS_BROKEN:
3001 return "BROKEN";
3002
Jeff Brown54bc2812010-06-15 01:31:58 -07003003 case STATUS_ZOMBIE:
3004 return "ZOMBIE";
3005
3006 default:
3007 return "UNKNOWN";
3008 }
3009}
3010
Jeff Browne839a582010-04-22 18:58:52 -07003011InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
3012 const EventEntry* eventEntry) const {
Jeff Browna665ca82010-09-08 11:49:43 -07003013 for (DispatchEntry* dispatchEntry = outboundQueue.tailSentinel.prev;
3014 dispatchEntry != & outboundQueue.headSentinel; dispatchEntry = dispatchEntry->prev) {
Jeff Browne839a582010-04-22 18:58:52 -07003015 if (dispatchEntry->eventEntry == eventEntry) {
3016 return dispatchEntry;
3017 }
3018 }
3019 return NULL;
3020}
3021
Jeff Browna665ca82010-09-08 11:49:43 -07003022
Jeff Brown54bc2812010-06-15 01:31:58 -07003023// --- InputDispatcher::CommandEntry ---
3024
Jeff Browna665ca82010-09-08 11:49:43 -07003025InputDispatcher::CommandEntry::CommandEntry() :
3026 keyEntry(NULL) {
Jeff Brown54bc2812010-06-15 01:31:58 -07003027}
3028
3029InputDispatcher::CommandEntry::~CommandEntry() {
3030}
3031
Jeff Browne839a582010-04-22 18:58:52 -07003032
3033// --- InputDispatcherThread ---
3034
3035InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
3036 Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
3037}
3038
3039InputDispatcherThread::~InputDispatcherThread() {
3040}
3041
3042bool InputDispatcherThread::threadLoop() {
3043 mDispatcher->dispatchOnce();
3044 return true;
3045}
3046
3047} // namespace android