blob: 3b3c4831798e210d6cf341312769621018e2ed01 [file] [log] [blame]
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4// The input dispatcher.
5//
6#define LOG_TAG "InputDispatcher"
7
8//#define LOG_NDEBUG 0
9
10// Log detailed debug messages about each inbound event notification to the dispatcher.
Jeff Brown349703e2010-06-22 01:27:15 -070011#define DEBUG_INBOUND_EVENT_DETAILS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070012
13// Log detailed debug messages about each outbound event processed by the dispatcher.
Jeff Brown349703e2010-06-22 01:27:15 -070014#define DEBUG_OUTBOUND_EVENT_DETAILS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070015
16// Log debug messages about batching.
Jeff Brown349703e2010-06-22 01:27:15 -070017#define DEBUG_BATCHING 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070018
19// Log debug messages about the dispatch cycle.
Jeff Brown349703e2010-06-22 01:27:15 -070020#define DEBUG_DISPATCH_CYCLE 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070021
Jeff Brown9c3cda02010-06-15 01:31:58 -070022// Log debug messages about registrations.
Jeff Brown349703e2010-06-22 01:27:15 -070023#define DEBUG_REGISTRATION 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070024
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070025// Log debug messages about performance statistics.
Jeff Brown349703e2010-06-22 01:27:15 -070026#define DEBUG_PERFORMANCE_STATISTICS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070027
Jeff Brown7fbdc842010-06-17 20:52:56 -070028// Log debug messages about input event injection.
Jeff Brown349703e2010-06-22 01:27:15 -070029#define DEBUG_INJECTION 0
Jeff Brown7fbdc842010-06-17 20:52:56 -070030
Jeff Brownae9fc032010-08-18 15:51:08 -070031// Log debug messages about input event throttling.
32#define DEBUG_THROTTLING 0
33
Jeff Brownb88102f2010-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 Brown46b9ac0a2010-04-22 18:58:52 -070040#include <cutils/log.h>
41#include <ui/InputDispatcher.h>
Jeff Brownb88102f2010-09-08 11:49:43 -070042#include <ui/PowerManager.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070043
44#include <stddef.h>
45#include <unistd.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070046#include <errno.h>
47#include <limits.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070048
49namespace android {
50
Jeff Brownb88102f2010-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 Brown46b9ac0a2010-04-22 18:58:52 -070063
Jeff Brown7fbdc842010-06-17 20:52:56 -070064static inline nsecs_t now() {
65 return systemTime(SYSTEM_TIME_MONOTONIC);
66}
67
Jeff Brownb88102f2010-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 Brown46b9ac0a2010-04-22 18:58:52 -070088// --- InputDispatcher ---
89
Jeff Brown9c3cda02010-06-15 01:31:58 -070090InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
Jeff Brownb88102f2010-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 Brown4fe6c3e2010-09-13 23:17:30 -070098 mLooper = new Looper(false);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070099
Jeff Brownb88102f2010-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 Brown46b9ac0a2010-04-22 18:58:52 -0700103
Jeff Brownb88102f2010-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 Brown46b9ac0a2010-04-22 18:58:52 -0700107
108 mKeyRepeatState.lastKeyEntry = NULL;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700109
Jeff Brownae9fc032010-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 Brown46b9ac0a2010-04-22 18:58:52 -0700118}
119
120InputDispatcher::~InputDispatcher() {
Jeff Brownb88102f2010-09-08 11:49:43 -0700121 { // acquire lock
122 AutoMutex _l(mLock);
123
124 resetKeyRepeatLocked();
125 releasePendingEventLocked(true);
126 drainInboundQueueLocked();
127 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700128
129 while (mConnectionsByReceiveFd.size() != 0) {
130 unregisterInputChannel(mConnectionsByReceiveFd.valueAt(0)->inputChannel);
131 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700132}
133
134void InputDispatcher::dispatchOnce() {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700135 nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
Jeff Brownb21fb102010-09-07 10:44:57 -0700136 nsecs_t keyRepeatDelay = mPolicy->getKeyRepeatDelay();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700137
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700138 nsecs_t nextWakeupTime = LONG_LONG_MAX;
139 { // acquire lock
140 AutoMutex _l(mLock);
Jeff Brownb88102f2010-09-08 11:49:43 -0700141 dispatchOnceInnerLocked(keyRepeatTimeout, keyRepeatDelay, & nextWakeupTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700142
Jeff Brownb88102f2010-09-08 11:49:43 -0700143 if (runCommandsLockedInterruptible()) {
144 nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700145 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700146 } // release lock
147
Jeff Brownb88102f2010-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 Brown4fe6c3e2010-09-13 23:17:30 -0700159 mLooper->pollOnce(timeoutMillis);
Jeff Brownb88102f2010-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 Brown9c3cda02010-06-15 01:31:58 -0700180 return;
181 }
182
Jeff Brownb88102f2010-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 Brownb88102f2010-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 Brown46b9ac0a2010-04-22 18:58:52 -0700378}
379
Jeff Brown9c3cda02010-06-15 01:31:58 -0700380bool InputDispatcher::runCommandsLockedInterruptible() {
381 if (mCommandQueue.isEmpty()) {
382 return false;
383 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700384
Jeff Brown9c3cda02010-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 Brown7fbdc842010-06-17 20:52:56 -0700391 commandEntry->connection.clear();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700392 mAllocator.releaseCommandEntry(commandEntry);
393 } while (! mCommandQueue.isEmpty());
394 return true;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700395}
396
Jeff Brown9c3cda02010-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 Brownb88102f2010-09-08 11:49:43 -0700403void InputDispatcher::drainInboundQueueLocked() {
404 while (! mInboundQueue.isEmpty()) {
405 EventEntry* entry = mInboundQueue.dequeueAtHead();
406 releaseInboundEventLocked(entry, true /*wasDropped*/);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700407 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700408}
409
Jeff Brownb88102f2010-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 Brownb21fb102010-09-07 10:44:57 -0700442 nsecs_t currentTime, nsecs_t keyRepeatDelay) {
Jeff Brown349703e2010-06-22 01:27:15 -0700443 KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
444
Jeff Brown349703e2010-06-22 01:27:15 -0700445 // Reuse the repeated key entry if it is otherwise unreferenced.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700446 uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700447 if (entry->refCount == 1) {
Jeff Brownb88102f2010-09-08 11:49:43 -0700448 entry->recycle();
Jeff Brown7fbdc842010-06-17 20:52:56 -0700449 entry->eventTime = currentTime;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700450 entry->policyFlags = policyFlags;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700451 entry->repeatCount += 1;
452 } else {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700453 KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700454 entry->deviceId, entry->source, policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700455 entry->action, entry->flags, entry->keyCode, entry->scanCode,
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700456 entry->metaState, entry->repeatCount + 1, entry->downTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700457
458 mKeyRepeatState.lastKeyEntry = newEntry;
459 mAllocator.releaseKeyEntry(entry);
460
461 entry = newEntry;
462 }
Jeff Brownb88102f2010-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 Brown46b9ac0a2010-04-22 18:58:52 -0700468
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700469 if (entry->repeatCount == 1) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700470 entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700471 }
472
Jeff Brownb21fb102010-09-07 10:44:57 -0700473 mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatDelay;
Jeff Brownb88102f2010-09-08 11:49:43 -0700474 return entry;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700475}
476
Jeff Brownb88102f2010-09-08 11:49:43 -0700477bool InputDispatcher::dispatchConfigurationChangedLocked(
478 nsecs_t currentTime, ConfigurationChangedEntry* entry) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700479#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brownb88102f2010-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 Brown519e0242010-09-15 15:18:56 -0700524 startFindingTargetsLocked(); // resets mCurrentInputTargetsValid
Jeff Brownb88102f2010-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 Brown519e0242010-09-15 15:18:56 -0700585 startFindingTargetsLocked(); // resets mCurrentInputTargetsValid
Jeff Brownb88102f2010-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 Brown85a31762010-09-01 17:01:00 -0700648 "action=0x%x, flags=0x%x, "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700649 "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
Jeff Brownb88102f2010-09-08 11:49:43 -0700650 prefix,
Jeff Brown85a31762010-09-01 17:01:00 -0700651 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
652 entry->action, entry->flags,
Jeff Brown46b9ac0a2010-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 Brownb88102f2010-09-08 11:49:43 -0700658 const MotionSample* sample = & entry->firstSample;
Jeff Brown46b9ac0a2010-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 Brown8d608662010-08-30 03:02:23 -0700663 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
Jeff Brown85a31762010-09-01 17:01:00 -0700664 "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
Jeff Brown8d608662010-08-30 03:02:23 -0700665 "orientation=%f",
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700666 i, entry->pointerIds[i],
Jeff Brown8d608662010-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 Brown46b9ac0a2010-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 Brownc5ed5912010-07-14 18:48:53 -0700676 if (entry->action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700677 LOGD(" ... Total movement samples currently batched %d ...", sampleCount);
678 }
679#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700680}
681
682void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
683 EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
684#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700685 LOGD("dispatchEventToCurrentInputTargets - "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700686 "resumeWithAppendedMotionSample=%s",
Jeff Brownb88102f2010-09-08 11:49:43 -0700687 toString(resumeWithAppendedMotionSample));
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700688#endif
689
Jeff Brown9c3cda02010-06-15 01:31:58 -0700690 assert(eventEntry->dispatchInProgress); // should already have been set to true
691
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700692 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
693 const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
694
Jeff Brown519e0242010-09-15 15:18:56 -0700695 ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700696 if (connectionIndex >= 0) {
697 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700698 prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
Jeff Brown46b9ac0a2010-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 Brownb88102f2010-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 Brown519e0242010-09-15 15:18:56 -0700737 LOGD("Waiting for application to become ready for input: %s",
738 getApplicationWindowLabelLocked(application, window).string());
Jeff Brownb88102f2010-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 Brown519e0242010-09-15 15:18:56 -0700755 onANRLocked(currentTime, application, window, entry->eventTime, mInputTargetWaitStartTime);
Jeff Brownb88102f2010-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 Brown519e0242010-09-15 15:18:56 -0700770void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
771 const sp<InputChannel>& inputChannel) {
Jeff Brownb88102f2010-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 Brown519e0242010-09-15 15:18:56 -0700778
779 // Input state will not be realistic. Mark it out of sync.
780 ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
781 if (connectionIndex >= 0) {
782 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
783 connection->inputState.setOutOfSync();
784 }
Jeff Brownb88102f2010-09-08 11:49:43 -0700785 }
786}
787
Jeff Brown519e0242010-09-15 15:18:56 -0700788nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(
Jeff Brownb88102f2010-09-08 11:49:43 -0700789 nsecs_t currentTime) {
790 if (mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
791 return currentTime - mInputTargetWaitStartTime;
792 }
793 return 0;
794}
795
796void InputDispatcher::resetANRTimeoutsLocked() {
797#if DEBUG_FOCUS
798 LOGD("Resetting ANR timeouts.");
799#endif
800
Jeff Brownb88102f2010-09-08 11:49:43 -0700801 // Reset input target wait timeout.
802 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
803}
804
805int32_t InputDispatcher::findFocusedWindowLocked(nsecs_t currentTime, const EventEntry* entry,
806 nsecs_t* nextWakeupTime, InputWindow** outWindow) {
807 *outWindow = NULL;
808 mCurrentInputTargets.clear();
809
810 int32_t injectionResult;
811
812 // If there is no currently focused window and no focused application
813 // then drop the event.
814 if (! mFocusedWindow) {
815 if (mFocusedApplication) {
816#if DEBUG_FOCUS
817 LOGD("Waiting because there is no focused window but there is a "
Jeff Brown519e0242010-09-15 15:18:56 -0700818 "focused application that may eventually add a window: %s.",
819 getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
Jeff Brownb88102f2010-09-08 11:49:43 -0700820#endif
821 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
822 mFocusedApplication, NULL, nextWakeupTime);
823 goto Unresponsive;
824 }
825
826 LOGI("Dropping event because there is no focused window or focused application.");
827 injectionResult = INPUT_EVENT_INJECTION_FAILED;
828 goto Failed;
829 }
830
831 // Check permissions.
832 if (! checkInjectionPermission(mFocusedWindow, entry->injectorPid, entry->injectorUid)) {
833 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
834 goto Failed;
835 }
836
837 // If the currently focused window is paused then keep waiting.
838 if (mFocusedWindow->paused) {
839#if DEBUG_FOCUS
840 LOGD("Waiting because focused window is paused.");
841#endif
842 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
843 mFocusedApplication, mFocusedWindow, nextWakeupTime);
844 goto Unresponsive;
845 }
846
Jeff Brown519e0242010-09-15 15:18:56 -0700847 // If the currently focused window is still working on previous events then keep waiting.
848 if (! isWindowFinishedWithPreviousInputLocked(mFocusedWindow)) {
849#if DEBUG_FOCUS
850 LOGD("Waiting because focused window still processing previous input.");
851#endif
852 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
853 mFocusedApplication, mFocusedWindow, nextWakeupTime);
854 goto Unresponsive;
855 }
856
Jeff Brownb88102f2010-09-08 11:49:43 -0700857 // Success! Output targets.
858 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
859 *outWindow = mFocusedWindow;
Jeff Brown519e0242010-09-15 15:18:56 -0700860 addWindowTargetLocked(mFocusedWindow, InputTarget::FLAG_FOREGROUND);
Jeff Brownb88102f2010-09-08 11:49:43 -0700861
862 // Done.
863Failed:
864Unresponsive:
Jeff Brown519e0242010-09-15 15:18:56 -0700865 nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
866 updateDispatchStatisticsLocked(currentTime, entry,
867 injectionResult, timeSpentWaitingForApplication);
Jeff Brownb88102f2010-09-08 11:49:43 -0700868#if DEBUG_FOCUS
Jeff Brown519e0242010-09-15 15:18:56 -0700869 LOGD("findFocusedWindow finished: injectionResult=%d, "
870 "timeSpendWaitingForApplication=%0.1fms",
871 injectionResult, timeSpentWaitingForApplication / 1000000.0);
Jeff Brownb88102f2010-09-08 11:49:43 -0700872#endif
873 return injectionResult;
874}
875
876int32_t InputDispatcher::findTouchedWindowLocked(nsecs_t currentTime, const MotionEntry* entry,
877 nsecs_t* nextWakeupTime, InputWindow** outWindow) {
878 enum InjectionPermission {
879 INJECTION_PERMISSION_UNKNOWN,
880 INJECTION_PERMISSION_GRANTED,
881 INJECTION_PERMISSION_DENIED
882 };
883
884 *outWindow = NULL;
885 mCurrentInputTargets.clear();
886
887 nsecs_t startTime = now();
888
889 // For security reasons, we defer updating the touch state until we are sure that
890 // event injection will be allowed.
891 //
892 // FIXME In the original code, screenWasOff could never be set to true.
893 // The reason is that the POLICY_FLAG_WOKE_HERE
894 // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
895 // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
896 // actually enqueued using the policyFlags that appeared in the final EV_SYN
897 // events upon which no preprocessing took place. So policyFlags was always 0.
898 // In the new native input dispatcher we're a bit more careful about event
899 // preprocessing so the touches we receive can actually have non-zero policyFlags.
900 // Unfortunately we obtain undesirable behavior.
901 //
902 // Here's what happens:
903 //
904 // When the device dims in anticipation of going to sleep, touches
905 // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
906 // the device to brighten and reset the user activity timer.
907 // Touches on other windows (such as the launcher window)
908 // are dropped. Then after a moment, the device goes to sleep. Oops.
909 //
910 // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
911 // instead of POLICY_FLAG_WOKE_HERE...
912 //
913 bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
914
915 int32_t action = entry->action;
916
917 // Update the touch state as needed based on the properties of the touch event.
918 int32_t injectionResult;
919 InjectionPermission injectionPermission;
920 if (action == AMOTION_EVENT_ACTION_DOWN) {
921 /* Case 1: ACTION_DOWN */
922
923 InputWindow* newTouchedWindow = NULL;
924 mTempTouchedOutsideTargets.clear();
925
926 int32_t x = int32_t(entry->firstSample.pointerCoords[0].x);
927 int32_t y = int32_t(entry->firstSample.pointerCoords[0].y);
928 InputWindow* topErrorWindow = NULL;
929 bool obscured = false;
930
931 // Traverse windows from front to back to find touched window and outside targets.
932 size_t numWindows = mWindows.size();
933 for (size_t i = 0; i < numWindows; i++) {
934 InputWindow* window = & mWindows.editItemAt(i);
935 int32_t flags = window->layoutParamsFlags;
936
937 if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
938 if (! topErrorWindow) {
939 topErrorWindow = window;
940 }
941 }
942
943 if (window->visible) {
944 if (! (flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
945 bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
946 | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
947 if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
948 if (! screenWasOff || flags & InputWindow::FLAG_TOUCHABLE_WHEN_WAKING) {
949 newTouchedWindow = window;
950 obscured = isWindowObscuredLocked(window);
951 }
952 break; // found touched window, exit window loop
953 }
954 }
955
956 if (flags & InputWindow::FLAG_WATCH_OUTSIDE_TOUCH) {
957 OutsideTarget outsideTarget;
958 outsideTarget.window = window;
959 outsideTarget.obscured = isWindowObscuredLocked(window);
960 mTempTouchedOutsideTargets.push(outsideTarget);
961 }
962 }
963 }
964
965 // If there is an error window but it is not taking focus (typically because
966 // it is invisible) then wait for it. Any other focused window may in
967 // fact be in ANR state.
968 if (topErrorWindow && newTouchedWindow != topErrorWindow) {
969#if DEBUG_FOCUS
970 LOGD("Waiting because system error window is pending.");
971#endif
972 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
973 NULL, NULL, nextWakeupTime);
974 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
975 goto Unresponsive;
976 }
977
978 // If we did not find a touched window then fail.
979 if (! newTouchedWindow) {
980 if (mFocusedApplication) {
981#if DEBUG_FOCUS
982 LOGD("Waiting because there is no touched window but there is a "
Jeff Brown519e0242010-09-15 15:18:56 -0700983 "focused application that may eventually add a new window: %s.",
984 getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
Jeff Brownb88102f2010-09-08 11:49:43 -0700985#endif
986 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
987 mFocusedApplication, NULL, nextWakeupTime);
988 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
989 goto Unresponsive;
990 }
991
992 LOGI("Dropping event because there is no touched window or focused application.");
993 injectionResult = INPUT_EVENT_INJECTION_FAILED;
994 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
995 goto Failed;
996 }
997
998 // Check permissions.
999 if (! checkInjectionPermission(newTouchedWindow, entry->injectorPid, entry->injectorUid)) {
1000 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1001 injectionPermission = INJECTION_PERMISSION_DENIED;
1002 goto Failed;
1003 }
1004
1005 // If the touched window is paused then keep waiting.
1006 if (newTouchedWindow->paused) {
1007#if DEBUG_INPUT_DISPATCHER_POLICY
1008 LOGD("Waiting because touched window is paused.");
1009#endif
1010 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1011 NULL, newTouchedWindow, nextWakeupTime);
1012 injectionPermission = INJECTION_PERMISSION_GRANTED;
1013 goto Unresponsive;
1014 }
1015
Jeff Brown519e0242010-09-15 15:18:56 -07001016 // If the touched window is still working on previous events then keep waiting.
1017 if (! isWindowFinishedWithPreviousInputLocked(newTouchedWindow)) {
1018#if DEBUG_FOCUS
1019 LOGD("Waiting because touched window still processing previous input.");
1020#endif
1021 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1022 NULL, newTouchedWindow, nextWakeupTime);
1023 injectionPermission = INJECTION_PERMISSION_GRANTED;
1024 goto Unresponsive;
1025 }
1026
Jeff Brownb88102f2010-09-08 11:49:43 -07001027 // Success! Update the touch dispatch state for real.
1028 releaseTouchedWindowLocked();
1029
1030 mTouchedWindow = newTouchedWindow;
1031 mTouchedWindowIsObscured = obscured;
1032
1033 if (newTouchedWindow->hasWallpaper) {
1034 mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
1035 }
1036 } else {
1037 /* Case 2: Everything but ACTION_DOWN */
1038
1039 // Check permissions.
1040 if (! checkInjectionPermission(mTouchedWindow, entry->injectorPid, entry->injectorUid)) {
1041 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1042 injectionPermission = INJECTION_PERMISSION_DENIED;
1043 goto Failed;
1044 }
1045
1046 // If the pointer is not currently down, then ignore the event.
1047 if (! mTouchDown) {
1048 LOGI("Dropping event because the pointer is not down.");
1049 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1050 injectionPermission = INJECTION_PERMISSION_GRANTED;
1051 goto Failed;
1052 }
1053
1054 // If there is no currently touched window then fail.
1055 if (! mTouchedWindow) {
1056#if DEBUG_INPUT_DISPATCHER_POLICY
1057 LOGD("Dropping event because there is no touched window to receive it.");
1058#endif
1059 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1060 injectionPermission = INJECTION_PERMISSION_GRANTED;
1061 goto Failed;
1062 }
1063
1064 // If the touched window is paused then keep waiting.
1065 if (mTouchedWindow->paused) {
1066#if DEBUG_INPUT_DISPATCHER_POLICY
1067 LOGD("Waiting because touched window is paused.");
1068#endif
1069 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1070 NULL, mTouchedWindow, nextWakeupTime);
1071 injectionPermission = INJECTION_PERMISSION_GRANTED;
1072 goto Unresponsive;
1073 }
Jeff Brown519e0242010-09-15 15:18:56 -07001074
1075 // If the touched window is still working on previous events then keep waiting.
1076 if (! isWindowFinishedWithPreviousInputLocked(mTouchedWindow)) {
1077#if DEBUG_FOCUS
1078 LOGD("Waiting because touched window still processing previous input.");
1079#endif
1080 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1081 NULL, mTouchedWindow, nextWakeupTime);
1082 injectionPermission = INJECTION_PERMISSION_GRANTED;
1083 goto Unresponsive;
1084 }
Jeff Brownb88102f2010-09-08 11:49:43 -07001085 }
1086
1087 // Success! Output targets.
1088 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1089 injectionPermission = INJECTION_PERMISSION_GRANTED;
1090
1091 {
1092 size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
1093 for (size_t i = 0; i < numWallpaperWindows; i++) {
1094 addWindowTargetLocked(mTouchedWallpaperWindows[i],
Jeff Brown519e0242010-09-15 15:18:56 -07001095 InputTarget::FLAG_WINDOW_IS_OBSCURED);
Jeff Brownb88102f2010-09-08 11:49:43 -07001096 }
1097
1098 size_t numOutsideTargets = mTempTouchedOutsideTargets.size();
1099 for (size_t i = 0; i < numOutsideTargets; i++) {
1100 const OutsideTarget& outsideTarget = mTempTouchedOutsideTargets[i];
1101 int32_t outsideTargetFlags = InputTarget::FLAG_OUTSIDE;
1102 if (outsideTarget.obscured) {
1103 outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
1104 }
Jeff Brown519e0242010-09-15 15:18:56 -07001105 addWindowTargetLocked(outsideTarget.window, outsideTargetFlags);
Jeff Brownb88102f2010-09-08 11:49:43 -07001106 }
1107 mTempTouchedOutsideTargets.clear();
1108
Jeff Brown519e0242010-09-15 15:18:56 -07001109 int32_t targetFlags = InputTarget::FLAG_FOREGROUND;
Jeff Brownb88102f2010-09-08 11:49:43 -07001110 if (mTouchedWindowIsObscured) {
1111 targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
1112 }
Jeff Brown519e0242010-09-15 15:18:56 -07001113 addWindowTargetLocked(mTouchedWindow, targetFlags);
Jeff Brownb88102f2010-09-08 11:49:43 -07001114 *outWindow = mTouchedWindow;
1115 }
1116
1117Failed:
1118 // Check injection permission once and for all.
1119 if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
1120 if (checkInjectionPermission(action == AMOTION_EVENT_ACTION_DOWN ? NULL : mTouchedWindow,
1121 entry->injectorPid, entry->injectorUid)) {
1122 injectionPermission = INJECTION_PERMISSION_GRANTED;
1123 } else {
1124 injectionPermission = INJECTION_PERMISSION_DENIED;
1125 }
1126 }
1127
1128 // Update final pieces of touch state if the injector had permission.
1129 if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
1130 if (action == AMOTION_EVENT_ACTION_DOWN) {
1131 if (mTouchDown) {
1132 // This is weird. We got a down but we thought it was already down!
1133 LOGW("Pointer down received while already down.");
1134 } else {
1135 mTouchDown = true;
1136 }
1137
1138 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1139 // Since we failed to identify a target for this touch down, we may still
1140 // be holding on to an earlier target from a previous touch down. Release it.
1141 releaseTouchedWindowLocked();
1142 }
1143 } else if (action == AMOTION_EVENT_ACTION_UP) {
1144 mTouchDown = false;
1145 releaseTouchedWindowLocked();
1146 }
1147 } else {
1148 LOGW("Not updating touch focus because injection was denied.");
1149 }
1150
1151Unresponsive:
Jeff Brown519e0242010-09-15 15:18:56 -07001152 nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
1153 updateDispatchStatisticsLocked(currentTime, entry,
1154 injectionResult, timeSpentWaitingForApplication);
Jeff Brownb88102f2010-09-08 11:49:43 -07001155#if DEBUG_FOCUS
Jeff Brown519e0242010-09-15 15:18:56 -07001156 LOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d,"
1157 "timeSpendWaitingForApplication=%0.1fms",
1158 injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0);
Jeff Brownb88102f2010-09-08 11:49:43 -07001159#endif
1160 return injectionResult;
1161}
1162
1163void InputDispatcher::releaseTouchedWindowLocked() {
1164 mTouchedWindow = NULL;
1165 mTouchedWindowIsObscured = false;
1166 mTouchedWallpaperWindows.clear();
1167}
1168
Jeff Brown519e0242010-09-15 15:18:56 -07001169void InputDispatcher::addWindowTargetLocked(const InputWindow* window, int32_t targetFlags) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001170 mCurrentInputTargets.push();
1171
1172 InputTarget& target = mCurrentInputTargets.editTop();
1173 target.inputChannel = window->inputChannel;
1174 target.flags = targetFlags;
Jeff Brownb88102f2010-09-08 11:49:43 -07001175 target.xOffset = - window->frameLeft;
1176 target.yOffset = - window->frameTop;
1177}
1178
1179void InputDispatcher::addMonitoringTargetsLocked() {
1180 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
1181 mCurrentInputTargets.push();
1182
1183 InputTarget& target = mCurrentInputTargets.editTop();
1184 target.inputChannel = mMonitoringChannels[i];
1185 target.flags = 0;
Jeff Brownb88102f2010-09-08 11:49:43 -07001186 target.xOffset = 0;
1187 target.yOffset = 0;
1188 }
1189}
1190
1191bool InputDispatcher::checkInjectionPermission(const InputWindow* window,
1192 int32_t injectorPid, int32_t injectorUid) {
1193 if (injectorUid > 0 && (window == NULL || window->ownerUid != injectorUid)) {
1194 bool result = mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
1195 if (! result) {
1196 if (window) {
1197 LOGW("Permission denied: injecting event from pid %d uid %d to window "
1198 "with input channel %s owned by uid %d",
1199 injectorPid, injectorUid, window->inputChannel->getName().string(),
1200 window->ownerUid);
1201 } else {
1202 LOGW("Permission denied: injecting event from pid %d uid %d",
1203 injectorPid, injectorUid);
1204 }
1205 return false;
1206 }
1207 }
1208 return true;
1209}
1210
1211bool InputDispatcher::isWindowObscuredLocked(const InputWindow* window) {
1212 size_t numWindows = mWindows.size();
1213 for (size_t i = 0; i < numWindows; i++) {
1214 const InputWindow* other = & mWindows.itemAt(i);
1215 if (other == window) {
1216 break;
1217 }
1218 if (other->visible && window->visibleFrameIntersects(other)) {
1219 return true;
1220 }
1221 }
1222 return false;
1223}
1224
Jeff Brown519e0242010-09-15 15:18:56 -07001225bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(const InputWindow* window) {
1226 ssize_t connectionIndex = getConnectionIndexLocked(window->inputChannel);
1227 if (connectionIndex >= 0) {
1228 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1229 return connection->outboundQueue.isEmpty();
1230 } else {
1231 return true;
1232 }
1233}
1234
1235String8 InputDispatcher::getApplicationWindowLabelLocked(const InputApplication* application,
1236 const InputWindow* window) {
1237 if (application) {
1238 if (window) {
1239 String8 label(application->name);
1240 label.append(" - ");
1241 label.append(window->name);
1242 return label;
1243 } else {
1244 return application->name;
1245 }
1246 } else if (window) {
1247 return window->name;
1248 } else {
1249 return String8("<unknown application or window>");
1250 }
1251}
1252
Jeff Brownb88102f2010-09-08 11:49:43 -07001253void InputDispatcher::pokeUserActivityLocked(nsecs_t eventTime,
1254 int32_t windowType, int32_t eventType) {
1255 CommandEntry* commandEntry = postCommandLocked(
1256 & InputDispatcher::doPokeUserActivityLockedInterruptible);
1257 commandEntry->eventTime = eventTime;
1258 commandEntry->windowType = windowType;
1259 commandEntry->userActivityEventType = eventType;
1260}
1261
Jeff Brown7fbdc842010-06-17 20:52:56 -07001262void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
1263 const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001264 bool resumeWithAppendedMotionSample) {
1265#if DEBUG_DISPATCH_CYCLE
Jeff Brown519e0242010-09-15 15:18:56 -07001266 LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001267 "xOffset=%f, yOffset=%f, resumeWithAppendedMotionSample=%s",
Jeff Brown519e0242010-09-15 15:18:56 -07001268 connection->getInputChannelName(), inputTarget->flags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001269 inputTarget->xOffset, inputTarget->yOffset,
Jeff Brownb88102f2010-09-08 11:49:43 -07001270 toString(resumeWithAppendedMotionSample));
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001271#endif
1272
1273 // Skip this event if the connection status is not normal.
Jeff Brown519e0242010-09-15 15:18:56 -07001274 // We don't want to enqueue additional outbound events if the connection is broken.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001275 if (connection->status != Connection::STATUS_NORMAL) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001276 LOGW("channel '%s' ~ Dropping event because the channel status is %s",
1277 connection->getInputChannelName(), connection->getStatusLabel());
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001278 return;
1279 }
1280
1281 // Resume the dispatch cycle with a freshly appended motion sample.
1282 // First we check that the last dispatch entry in the outbound queue is for the same
1283 // motion event to which we appended the motion sample. If we find such a dispatch
1284 // entry, and if it is currently in progress then we try to stream the new sample.
1285 bool wasEmpty = connection->outboundQueue.isEmpty();
1286
1287 if (! wasEmpty && resumeWithAppendedMotionSample) {
1288 DispatchEntry* motionEventDispatchEntry =
1289 connection->findQueuedDispatchEntryForEvent(eventEntry);
1290 if (motionEventDispatchEntry) {
1291 // If the dispatch entry is not in progress, then we must be busy dispatching an
1292 // earlier event. Not a problem, the motion event is on the outbound queue and will
1293 // be dispatched later.
1294 if (! motionEventDispatchEntry->inProgress) {
1295#if DEBUG_BATCHING
1296 LOGD("channel '%s' ~ Not streaming because the motion event has "
1297 "not yet been dispatched. "
1298 "(Waiting for earlier events to be consumed.)",
1299 connection->getInputChannelName());
1300#endif
1301 return;
1302 }
1303
1304 // If the dispatch entry is in progress but it already has a tail of pending
1305 // motion samples, then it must mean that the shared memory buffer filled up.
1306 // Not a problem, when this dispatch cycle is finished, we will eventually start
1307 // a new dispatch cycle to process the tail and that tail includes the newly
1308 // appended motion sample.
1309 if (motionEventDispatchEntry->tailMotionSample) {
1310#if DEBUG_BATCHING
1311 LOGD("channel '%s' ~ Not streaming because no new samples can "
1312 "be appended to the motion event in this dispatch cycle. "
1313 "(Waiting for next dispatch cycle to start.)",
1314 connection->getInputChannelName());
1315#endif
1316 return;
1317 }
1318
1319 // The dispatch entry is in progress and is still potentially open for streaming.
1320 // Try to stream the new motion sample. This might fail if the consumer has already
1321 // consumed the motion event (or if the channel is broken).
1322 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
1323 status_t status = connection->inputPublisher.appendMotionSample(
1324 appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
1325 if (status == OK) {
1326#if DEBUG_BATCHING
1327 LOGD("channel '%s' ~ Successfully streamed new motion sample.",
1328 connection->getInputChannelName());
1329#endif
1330 return;
1331 }
1332
1333#if DEBUG_BATCHING
1334 if (status == NO_MEMORY) {
1335 LOGD("channel '%s' ~ Could not append motion sample to currently "
1336 "dispatched move event because the shared memory buffer is full. "
1337 "(Waiting for next dispatch cycle to start.)",
1338 connection->getInputChannelName());
1339 } else if (status == status_t(FAILED_TRANSACTION)) {
1340 LOGD("channel '%s' ~ Could not append motion sample to currently "
Jeff Brown349703e2010-06-22 01:27:15 -07001341 "dispatched move event because the event has already been consumed. "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001342 "(Waiting for next dispatch cycle to start.)",
1343 connection->getInputChannelName());
1344 } else {
1345 LOGD("channel '%s' ~ Could not append motion sample to currently "
1346 "dispatched move event due to an error, status=%d. "
1347 "(Waiting for next dispatch cycle to start.)",
1348 connection->getInputChannelName(), status);
1349 }
1350#endif
1351 // Failed to stream. Start a new tail of pending motion samples to dispatch
1352 // in the next cycle.
1353 motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
1354 return;
1355 }
1356 }
1357
Jeff Brownb88102f2010-09-08 11:49:43 -07001358 // Bring the input state back in line with reality in case it drifted off during an ANR.
1359 if (connection->inputState.isOutOfSync()) {
1360 mTempCancelationEvents.clear();
1361 connection->inputState.synthesizeCancelationEvents(& mAllocator, mTempCancelationEvents);
1362 connection->inputState.resetOutOfSync();
1363
1364 if (! mTempCancelationEvents.isEmpty()) {
1365 LOGI("channel '%s' ~ Generated %d cancelation events to bring channel back in sync "
1366 "with reality.",
1367 connection->getInputChannelName(), mTempCancelationEvents.size());
1368
1369 for (size_t i = 0; i < mTempCancelationEvents.size(); i++) {
1370 EventEntry* cancelationEventEntry = mTempCancelationEvents.itemAt(i);
1371 switch (cancelationEventEntry->type) {
1372 case EventEntry::TYPE_KEY:
1373 logOutboundKeyDetailsLocked(" ",
1374 static_cast<KeyEntry*>(cancelationEventEntry));
1375 break;
1376 case EventEntry::TYPE_MOTION:
1377 logOutboundMotionDetailsLocked(" ",
1378 static_cast<MotionEntry*>(cancelationEventEntry));
1379 break;
1380 }
1381
1382 DispatchEntry* cancelationDispatchEntry =
1383 mAllocator.obtainDispatchEntry(cancelationEventEntry,
Jeff Brown519e0242010-09-15 15:18:56 -07001384 0, inputTarget->xOffset, inputTarget->yOffset); // increments ref
Jeff Brownb88102f2010-09-08 11:49:43 -07001385 connection->outboundQueue.enqueueAtTail(cancelationDispatchEntry);
1386
1387 mAllocator.releaseEventEntry(cancelationEventEntry);
1388 }
1389 }
1390 }
1391
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001392 // This is a new event.
1393 // Enqueue a new dispatch entry onto the outbound queue for this connection.
Jeff Brownb88102f2010-09-08 11:49:43 -07001394 DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry, // increments ref
Jeff Brown519e0242010-09-15 15:18:56 -07001395 inputTarget->flags, inputTarget->xOffset, inputTarget->yOffset);
1396 if (dispatchEntry->hasForegroundTarget()) {
1397 eventEntry->pendingForegroundDispatches += 1;
Jeff Brown6ec402b2010-07-28 15:48:59 -07001398 }
1399
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001400 // Handle the case where we could not stream a new motion sample because the consumer has
1401 // already consumed the motion event (otherwise the corresponding dispatch entry would
1402 // still be in the outbound queue for this connection). We set the head motion sample
1403 // to the list starting with the newly appended motion sample.
1404 if (resumeWithAppendedMotionSample) {
1405#if DEBUG_BATCHING
1406 LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
1407 "that cannot be streamed because the motion event has already been consumed.",
1408 connection->getInputChannelName());
1409#endif
1410 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
1411 dispatchEntry->headMotionSample = appendedMotionSample;
1412 }
1413
1414 // Enqueue the dispatch entry.
1415 connection->outboundQueue.enqueueAtTail(dispatchEntry);
1416
1417 // If the outbound queue was previously empty, start the dispatch cycle going.
1418 if (wasEmpty) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001419 activateConnectionLocked(connection.get());
Jeff Brown519e0242010-09-15 15:18:56 -07001420 startDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001421 }
1422}
1423
Jeff Brown7fbdc842010-06-17 20:52:56 -07001424void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
Jeff Brown519e0242010-09-15 15:18:56 -07001425 const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001426#if DEBUG_DISPATCH_CYCLE
1427 LOGD("channel '%s' ~ startDispatchCycle",
1428 connection->getInputChannelName());
1429#endif
1430
1431 assert(connection->status == Connection::STATUS_NORMAL);
1432 assert(! connection->outboundQueue.isEmpty());
1433
Jeff Brownb88102f2010-09-08 11:49:43 -07001434 DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001435 assert(! dispatchEntry->inProgress);
1436
Jeff Brownb88102f2010-09-08 11:49:43 -07001437 // Mark the dispatch entry as in progress.
1438 dispatchEntry->inProgress = true;
1439
1440 // Update the connection's input state.
1441 InputState::Consistency consistency = connection->inputState.trackEvent(
1442 dispatchEntry->eventEntry);
1443
1444#if FILTER_INPUT_EVENTS
1445 // Filter out inconsistent sequences of input events.
1446 // The input system may drop or inject events in a way that could violate implicit
1447 // invariants on input state and potentially cause an application to crash
1448 // or think that a key or pointer is stuck down. Technically we make no guarantees
1449 // of consistency but it would be nice to improve on this where possible.
1450 // XXX: This code is a proof of concept only. Not ready for prime time.
1451 if (consistency == InputState::TOLERABLE) {
1452#if DEBUG_DISPATCH_CYCLE
1453 LOGD("channel '%s' ~ Sending an event that is inconsistent with the connection's "
1454 "current input state but that is likely to be tolerated by the application.",
1455 connection->getInputChannelName());
1456#endif
1457 } else if (consistency == InputState::BROKEN) {
1458 LOGI("channel '%s' ~ Dropping an event that is inconsistent with the connection's "
1459 "current input state and that is likely to cause the application to crash.",
1460 connection->getInputChannelName());
1461 startNextDispatchCycleLocked(currentTime, connection);
1462 return;
1463 }
1464#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001465
1466 // Publish the event.
1467 status_t status;
1468 switch (dispatchEntry->eventEntry->type) {
1469 case EventEntry::TYPE_KEY: {
1470 KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
1471
1472 // Apply target flags.
1473 int32_t action = keyEntry->action;
1474 int32_t flags = keyEntry->flags;
1475 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001476 flags |= AKEY_EVENT_FLAG_CANCELED;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001477 }
1478
1479 // Publish the key event.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001480 status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001481 action, flags, keyEntry->keyCode, keyEntry->scanCode,
1482 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
1483 keyEntry->eventTime);
1484
1485 if (status) {
1486 LOGE("channel '%s' ~ Could not publish key event, "
1487 "status=%d", connection->getInputChannelName(), status);
1488 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
1489 return;
1490 }
1491 break;
1492 }
1493
1494 case EventEntry::TYPE_MOTION: {
1495 MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
1496
1497 // Apply target flags.
1498 int32_t action = motionEntry->action;
Jeff Brown85a31762010-09-01 17:01:00 -07001499 int32_t flags = motionEntry->flags;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001500 if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001501 action = AMOTION_EVENT_ACTION_OUTSIDE;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001502 }
1503 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001504 action = AMOTION_EVENT_ACTION_CANCEL;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001505 }
Jeff Brown85a31762010-09-01 17:01:00 -07001506 if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
1507 flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
1508 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001509
1510 // If headMotionSample is non-NULL, then it points to the first new sample that we
1511 // were unable to dispatch during the previous cycle so we resume dispatching from
1512 // that point in the list of motion samples.
1513 // Otherwise, we just start from the first sample of the motion event.
1514 MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
1515 if (! firstMotionSample) {
1516 firstMotionSample = & motionEntry->firstSample;
1517 }
1518
Jeff Brownd3616592010-07-16 17:21:06 -07001519 // Set the X and Y offset depending on the input source.
1520 float xOffset, yOffset;
1521 if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
1522 xOffset = dispatchEntry->xOffset;
1523 yOffset = dispatchEntry->yOffset;
1524 } else {
1525 xOffset = 0.0f;
1526 yOffset = 0.0f;
1527 }
1528
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001529 // Publish the motion event and the first motion sample.
1530 status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
Jeff Brown85a31762010-09-01 17:01:00 -07001531 motionEntry->source, action, flags, motionEntry->edgeFlags, motionEntry->metaState,
Jeff Brownd3616592010-07-16 17:21:06 -07001532 xOffset, yOffset,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001533 motionEntry->xPrecision, motionEntry->yPrecision,
1534 motionEntry->downTime, firstMotionSample->eventTime,
1535 motionEntry->pointerCount, motionEntry->pointerIds,
1536 firstMotionSample->pointerCoords);
1537
1538 if (status) {
1539 LOGE("channel '%s' ~ Could not publish motion event, "
1540 "status=%d", connection->getInputChannelName(), status);
1541 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
1542 return;
1543 }
1544
1545 // Append additional motion samples.
1546 MotionSample* nextMotionSample = firstMotionSample->next;
1547 for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
1548 status = connection->inputPublisher.appendMotionSample(
1549 nextMotionSample->eventTime, nextMotionSample->pointerCoords);
1550 if (status == NO_MEMORY) {
1551#if DEBUG_DISPATCH_CYCLE
1552 LOGD("channel '%s' ~ Shared memory buffer full. Some motion samples will "
1553 "be sent in the next dispatch cycle.",
1554 connection->getInputChannelName());
1555#endif
1556 break;
1557 }
1558 if (status != OK) {
1559 LOGE("channel '%s' ~ Could not append motion sample "
1560 "for a reason other than out of memory, status=%d",
1561 connection->getInputChannelName(), status);
1562 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
1563 return;
1564 }
1565 }
1566
1567 // Remember the next motion sample that we could not dispatch, in case we ran out
1568 // of space in the shared memory buffer.
1569 dispatchEntry->tailMotionSample = nextMotionSample;
1570 break;
1571 }
1572
1573 default: {
1574 assert(false);
1575 }
1576 }
1577
1578 // Send the dispatch signal.
1579 status = connection->inputPublisher.sendDispatchSignal();
1580 if (status) {
1581 LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
1582 connection->getInputChannelName(), status);
1583 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
1584 return;
1585 }
1586
1587 // Record information about the newly started dispatch cycle.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001588 connection->lastEventTime = dispatchEntry->eventEntry->eventTime;
1589 connection->lastDispatchTime = currentTime;
1590
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001591 // Notify other system components.
1592 onDispatchCycleStartedLocked(currentTime, connection);
1593}
1594
Jeff Brown7fbdc842010-06-17 20:52:56 -07001595void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
1596 const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001597#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -07001598 LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001599 "%01.1fms since dispatch",
1600 connection->getInputChannelName(),
1601 connection->getEventLatencyMillis(currentTime),
1602 connection->getDispatchLatencyMillis(currentTime));
1603#endif
1604
Jeff Brown9c3cda02010-06-15 01:31:58 -07001605 if (connection->status == Connection::STATUS_BROKEN
1606 || connection->status == Connection::STATUS_ZOMBIE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001607 return;
1608 }
1609
Jeff Brown519e0242010-09-15 15:18:56 -07001610 // Notify other system components.
1611 onDispatchCycleFinishedLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001612
1613 // Reset the publisher since the event has been consumed.
1614 // We do this now so that the publisher can release some of its internal resources
1615 // while waiting for the next dispatch cycle to begin.
1616 status_t status = connection->inputPublisher.reset();
1617 if (status) {
1618 LOGE("channel '%s' ~ Could not reset publisher, status=%d",
1619 connection->getInputChannelName(), status);
1620 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
1621 return;
1622 }
1623
Jeff Brownb88102f2010-09-08 11:49:43 -07001624 startNextDispatchCycleLocked(currentTime, connection);
1625}
1626
1627void InputDispatcher::startNextDispatchCycleLocked(nsecs_t currentTime,
1628 const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001629 // Start the next dispatch cycle for this connection.
1630 while (! connection->outboundQueue.isEmpty()) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001631 DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001632 if (dispatchEntry->inProgress) {
1633 // Finish or resume current event in progress.
1634 if (dispatchEntry->tailMotionSample) {
1635 // We have a tail of undispatched motion samples.
1636 // Reuse the same DispatchEntry and start a new cycle.
1637 dispatchEntry->inProgress = false;
1638 dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
1639 dispatchEntry->tailMotionSample = NULL;
Jeff Brown519e0242010-09-15 15:18:56 -07001640 startDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001641 return;
1642 }
1643 // Finished.
1644 connection->outboundQueue.dequeueAtHead();
Jeff Brown519e0242010-09-15 15:18:56 -07001645 if (dispatchEntry->hasForegroundTarget()) {
1646 decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
Jeff Brown6ec402b2010-07-28 15:48:59 -07001647 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001648 mAllocator.releaseDispatchEntry(dispatchEntry);
1649 } else {
1650 // If the head is not in progress, then we must have already dequeued the in
Jeff Brown519e0242010-09-15 15:18:56 -07001651 // progress event, which means we actually aborted it.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001652 // So just start the next event for this connection.
Jeff Brown519e0242010-09-15 15:18:56 -07001653 startDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001654 return;
1655 }
1656 }
1657
1658 // Outbound queue is empty, deactivate the connection.
Jeff Brown7fbdc842010-06-17 20:52:56 -07001659 deactivateConnectionLocked(connection.get());
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001660}
1661
Jeff Brown7fbdc842010-06-17 20:52:56 -07001662void InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime,
1663 const sp<Connection>& connection, bool broken) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001664#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -07001665 LOGD("channel '%s' ~ abortDispatchCycle - broken=%s",
Jeff Brownb88102f2010-09-08 11:49:43 -07001666 connection->getInputChannelName(), toString(broken));
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001667#endif
1668
Jeff Brownb88102f2010-09-08 11:49:43 -07001669 // Input state will no longer be realistic.
1670 connection->inputState.setOutOfSync();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001671
Jeff Brownb88102f2010-09-08 11:49:43 -07001672 // Clear the outbound queue.
Jeff Brown519e0242010-09-15 15:18:56 -07001673 drainOutboundQueueLocked(connection.get());
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001674
1675 // Handle the case where the connection appears to be unrecoverably broken.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001676 // Ignore already broken or zombie connections.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001677 if (broken) {
Jeff Brown519e0242010-09-15 15:18:56 -07001678 if (connection->status == Connection::STATUS_NORMAL) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001679 connection->status = Connection::STATUS_BROKEN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001680
Jeff Brown9c3cda02010-06-15 01:31:58 -07001681 // Notify other system components.
1682 onDispatchCycleBrokenLocked(currentTime, connection);
1683 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001684 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001685}
1686
Jeff Brown519e0242010-09-15 15:18:56 -07001687void InputDispatcher::drainOutboundQueueLocked(Connection* connection) {
1688 while (! connection->outboundQueue.isEmpty()) {
1689 DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
1690 if (dispatchEntry->hasForegroundTarget()) {
1691 decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
Jeff Brownb88102f2010-09-08 11:49:43 -07001692 }
1693 mAllocator.releaseDispatchEntry(dispatchEntry);
Jeff Brownb88102f2010-09-08 11:49:43 -07001694 }
1695
Jeff Brown519e0242010-09-15 15:18:56 -07001696 deactivateConnectionLocked(connection);
Jeff Brownb88102f2010-09-08 11:49:43 -07001697}
1698
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001699int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001700 InputDispatcher* d = static_cast<InputDispatcher*>(data);
1701
1702 { // acquire lock
1703 AutoMutex _l(d->mLock);
1704
1705 ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
1706 if (connectionIndex < 0) {
1707 LOGE("Received spurious receive callback for unknown input channel. "
1708 "fd=%d, events=0x%x", receiveFd, events);
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001709 return 0; // remove the callback
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001710 }
1711
Jeff Brown7fbdc842010-06-17 20:52:56 -07001712 nsecs_t currentTime = now();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001713
1714 sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001715 if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001716 LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
1717 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001718 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001719 d->runCommandsLockedInterruptible();
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001720 return 0; // remove the callback
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001721 }
1722
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001723 if (! (events & ALOOPER_EVENT_INPUT)) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001724 LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
1725 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001726 return 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001727 }
1728
1729 status_t status = connection->inputPublisher.receiveFinishedSignal();
1730 if (status) {
1731 LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
1732 connection->getInputChannelName(), status);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001733 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001734 d->runCommandsLockedInterruptible();
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001735 return 0; // remove the callback
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001736 }
1737
Jeff Brown7fbdc842010-06-17 20:52:56 -07001738 d->finishDispatchCycleLocked(currentTime, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001739 d->runCommandsLockedInterruptible();
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001740 return 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001741 } // release lock
1742}
1743
Jeff Brown9c3cda02010-06-15 01:31:58 -07001744void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001745#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown9c3cda02010-06-15 01:31:58 -07001746 LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001747#endif
1748
Jeff Brownb88102f2010-09-08 11:49:43 -07001749 bool needWake;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001750 { // acquire lock
1751 AutoMutex _l(mLock);
1752
Jeff Brown7fbdc842010-06-17 20:52:56 -07001753 ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
Jeff Brownb88102f2010-09-08 11:49:43 -07001754 needWake = enqueueInboundEventLocked(newEntry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001755 } // release lock
1756
Jeff Brownb88102f2010-09-08 11:49:43 -07001757 if (needWake) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001758 mLooper->wake();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001759 }
1760}
1761
Jeff Brownc5ed5912010-07-14 18:48:53 -07001762void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001763 uint32_t policyFlags, int32_t action, int32_t flags,
1764 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
1765#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brownc5ed5912010-07-14 18:48:53 -07001766 LOGD("notifyKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001767 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
Jeff Brownc5ed5912010-07-14 18:48:53 -07001768 eventTime, deviceId, source, policyFlags, action, flags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001769 keyCode, scanCode, metaState, downTime);
1770#endif
1771
Jeff Brownb88102f2010-09-08 11:49:43 -07001772 bool needWake;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001773 { // acquire lock
1774 AutoMutex _l(mLock);
1775
Jeff Brown7fbdc842010-06-17 20:52:56 -07001776 int32_t repeatCount = 0;
1777 KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -07001778 deviceId, source, policyFlags, action, flags, keyCode, scanCode,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001779 metaState, repeatCount, downTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001780
Jeff Brownb88102f2010-09-08 11:49:43 -07001781 needWake = enqueueInboundEventLocked(newEntry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001782 } // release lock
1783
Jeff Brownb88102f2010-09-08 11:49:43 -07001784 if (needWake) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001785 mLooper->wake();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001786 }
1787}
1788
Jeff Brownc5ed5912010-07-14 18:48:53 -07001789void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Brown85a31762010-09-01 17:01:00 -07001790 uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t edgeFlags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001791 uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
1792 float xPrecision, float yPrecision, nsecs_t downTime) {
1793#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brownc5ed5912010-07-14 18:48:53 -07001794 LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Brown85a31762010-09-01 17:01:00 -07001795 "action=0x%x, flags=0x%x, metaState=0x%x, edgeFlags=0x%x, "
1796 "xPrecision=%f, yPrecision=%f, downTime=%lld",
1797 eventTime, deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001798 xPrecision, yPrecision, downTime);
1799 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Brown8d608662010-08-30 03:02:23 -07001800 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
Jeff Brown85a31762010-09-01 17:01:00 -07001801 "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
Jeff Brown8d608662010-08-30 03:02:23 -07001802 "orientation=%f",
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001803 i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
Jeff Brown8d608662010-08-30 03:02:23 -07001804 pointerCoords[i].pressure, pointerCoords[i].size,
1805 pointerCoords[i].touchMajor, pointerCoords[i].touchMinor,
1806 pointerCoords[i].toolMajor, pointerCoords[i].toolMinor,
1807 pointerCoords[i].orientation);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001808 }
1809#endif
1810
Jeff Brownb88102f2010-09-08 11:49:43 -07001811 bool needWake;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001812 { // acquire lock
1813 AutoMutex _l(mLock);
1814
1815 // Attempt batching and streaming of move events.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001816 if (action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001817 // BATCHING CASE
1818 //
1819 // Try to append a move sample to the tail of the inbound queue for this device.
1820 // Give up if we encounter a non-move motion event for this device since that
1821 // means we cannot append any new samples until a new motion event has started.
Jeff Brownb88102f2010-09-08 11:49:43 -07001822 for (EventEntry* entry = mInboundQueue.tailSentinel.prev;
1823 entry != & mInboundQueue.headSentinel; entry = entry->prev) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001824 if (entry->type != EventEntry::TYPE_MOTION) {
1825 // Keep looking for motion events.
1826 continue;
1827 }
1828
1829 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
1830 if (motionEntry->deviceId != deviceId) {
1831 // Keep looking for this device.
1832 continue;
1833 }
1834
Jeff Brownc5ed5912010-07-14 18:48:53 -07001835 if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown7fbdc842010-06-17 20:52:56 -07001836 || motionEntry->pointerCount != pointerCount
1837 || motionEntry->isInjected()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001838 // Last motion event in the queue for this device is not compatible for
1839 // appending new samples. Stop here.
1840 goto NoBatchingOrStreaming;
1841 }
1842
1843 // The last motion event is a move and is compatible for appending.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001844 // Do the batching magic.
Jeff Brown7fbdc842010-06-17 20:52:56 -07001845 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001846#if DEBUG_BATCHING
1847 LOGD("Appended motion sample onto batch for most recent "
1848 "motion event for this device in the inbound queue.");
1849#endif
Jeff Brown9c3cda02010-06-15 01:31:58 -07001850 return; // done!
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001851 }
1852
1853 // STREAMING CASE
1854 //
1855 // There is no pending motion event (of any kind) for this device in the inbound queue.
Jeff Brown519e0242010-09-15 15:18:56 -07001856 // Search the outbound queue for the current foreground targets to find a dispatched
1857 // motion event that is still in progress. If found, then, appen the new sample to
1858 // that event and push it out to all current targets. The logic in
1859 // prepareDispatchCycleLocked takes care of the case where some targets may
1860 // already have consumed the motion event by starting a new dispatch cycle if needed.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001861 if (mCurrentInputTargetsValid) {
Jeff Brown519e0242010-09-15 15:18:56 -07001862 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
1863 const InputTarget& inputTarget = mCurrentInputTargets[i];
1864 if ((inputTarget.flags & InputTarget::FLAG_FOREGROUND) == 0) {
1865 // Skip non-foreground targets. We only want to stream if there is at
1866 // least one foreground target whose dispatch is still in progress.
1867 continue;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001868 }
Jeff Brown519e0242010-09-15 15:18:56 -07001869
1870 ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
1871 if (connectionIndex < 0) {
1872 // Connection must no longer be valid.
1873 continue;
1874 }
1875
1876 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1877 if (connection->outboundQueue.isEmpty()) {
1878 // This foreground target has an empty outbound queue.
1879 continue;
1880 }
1881
1882 DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
1883 if (! dispatchEntry->inProgress
1884 || dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION) {
1885 // No motion event is being dispatched.
1886 continue;
1887 }
1888
1889 MotionEntry* motionEntry = static_cast<MotionEntry*>(
1890 dispatchEntry->eventEntry);
1891 if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
1892 || motionEntry->deviceId != deviceId
1893 || motionEntry->pointerCount != pointerCount
1894 || motionEntry->isInjected()) {
1895 // The motion event is not compatible with this move.
1896 continue;
1897 }
1898
1899 // Hurray! This foreground target is currently dispatching a move event
1900 // that we can stream onto. Append the motion sample and resume dispatch.
1901 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
1902#if DEBUG_BATCHING
1903 LOGD("Appended motion sample onto batch for most recently dispatched "
1904 "motion event for this device in the outbound queues. "
1905 "Attempting to stream the motion sample.");
1906#endif
1907 nsecs_t currentTime = now();
1908 dispatchEventToCurrentInputTargetsLocked(currentTime, motionEntry,
1909 true /*resumeWithAppendedMotionSample*/);
1910
1911 runCommandsLockedInterruptible();
1912 return; // done!
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001913 }
1914 }
1915
1916NoBatchingOrStreaming:;
1917 }
1918
1919 // Just enqueue a new motion event.
Jeff Brown7fbdc842010-06-17 20:52:56 -07001920 MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
Jeff Brown85a31762010-09-01 17:01:00 -07001921 deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001922 xPrecision, yPrecision, downTime,
1923 pointerCount, pointerIds, pointerCoords);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001924
Jeff Brownb88102f2010-09-08 11:49:43 -07001925 needWake = enqueueInboundEventLocked(newEntry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001926 } // release lock
1927
Jeff Brownb88102f2010-09-08 11:49:43 -07001928 if (needWake) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001929 mLooper->wake();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001930 }
1931}
1932
Jeff Brown7fbdc842010-06-17 20:52:56 -07001933int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
Jeff Brown6ec402b2010-07-28 15:48:59 -07001934 int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001935#if DEBUG_INBOUND_EVENT_DETAILS
1936 LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
Jeff Brown6ec402b2010-07-28 15:48:59 -07001937 "syncMode=%d, timeoutMillis=%d",
1938 event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001939#endif
1940
1941 nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
1942
1943 EventEntry* injectedEntry;
Jeff Brownb88102f2010-09-08 11:49:43 -07001944 bool needWake;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001945 { // acquire lock
1946 AutoMutex _l(mLock);
1947
Jeff Brownb88102f2010-09-08 11:49:43 -07001948 injectedEntry = createEntryFromInjectedInputEventLocked(event);
1949 if (! injectedEntry) {
1950 return INPUT_EVENT_INJECTION_FAILED;
1951 }
1952
Jeff Brown7fbdc842010-06-17 20:52:56 -07001953 injectedEntry->refCount += 1;
1954 injectedEntry->injectorPid = injectorPid;
1955 injectedEntry->injectorUid = injectorUid;
1956
Jeff Brown6ec402b2010-07-28 15:48:59 -07001957 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
1958 injectedEntry->injectionIsAsync = true;
1959 }
1960
Jeff Brownb88102f2010-09-08 11:49:43 -07001961 needWake = enqueueInboundEventLocked(injectedEntry);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001962 } // release lock
1963
Jeff Brownb88102f2010-09-08 11:49:43 -07001964 if (needWake) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001965 mLooper->wake();
Jeff Brown7fbdc842010-06-17 20:52:56 -07001966 }
1967
1968 int32_t injectionResult;
1969 { // acquire lock
1970 AutoMutex _l(mLock);
1971
Jeff Brown6ec402b2010-07-28 15:48:59 -07001972 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
1973 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1974 } else {
1975 for (;;) {
1976 injectionResult = injectedEntry->injectionResult;
1977 if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
1978 break;
1979 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07001980
Jeff Brown7fbdc842010-06-17 20:52:56 -07001981 nsecs_t remainingTimeout = endTime - now();
1982 if (remainingTimeout <= 0) {
Jeff Brown6ec402b2010-07-28 15:48:59 -07001983#if DEBUG_INJECTION
1984 LOGD("injectInputEvent - Timed out waiting for injection result "
1985 "to become available.");
1986#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001987 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1988 break;
1989 }
1990
Jeff Brown6ec402b2010-07-28 15:48:59 -07001991 mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
1992 }
1993
1994 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
1995 && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
Jeff Brown519e0242010-09-15 15:18:56 -07001996 while (injectedEntry->pendingForegroundDispatches != 0) {
Jeff Brown6ec402b2010-07-28 15:48:59 -07001997#if DEBUG_INJECTION
Jeff Brown519e0242010-09-15 15:18:56 -07001998 LOGD("injectInputEvent - Waiting for %d pending foreground dispatches.",
1999 injectedEntry->pendingForegroundDispatches);
Jeff Brown6ec402b2010-07-28 15:48:59 -07002000#endif
2001 nsecs_t remainingTimeout = endTime - now();
2002 if (remainingTimeout <= 0) {
2003#if DEBUG_INJECTION
Jeff Brown519e0242010-09-15 15:18:56 -07002004 LOGD("injectInputEvent - Timed out waiting for pending foreground "
Jeff Brown6ec402b2010-07-28 15:48:59 -07002005 "dispatches to finish.");
2006#endif
2007 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
2008 break;
2009 }
2010
2011 mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
2012 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07002013 }
2014 }
2015
2016 mAllocator.releaseEventEntry(injectedEntry);
2017 } // release lock
2018
Jeff Brown6ec402b2010-07-28 15:48:59 -07002019#if DEBUG_INJECTION
2020 LOGD("injectInputEvent - Finished with result %d. "
2021 "injectorPid=%d, injectorUid=%d",
2022 injectionResult, injectorPid, injectorUid);
2023#endif
2024
Jeff Brown7fbdc842010-06-17 20:52:56 -07002025 return injectionResult;
2026}
2027
2028void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
2029 if (entry->isInjected()) {
2030#if DEBUG_INJECTION
2031 LOGD("Setting input event injection result to %d. "
2032 "injectorPid=%d, injectorUid=%d",
2033 injectionResult, entry->injectorPid, entry->injectorUid);
2034#endif
2035
Jeff Brown6ec402b2010-07-28 15:48:59 -07002036 if (entry->injectionIsAsync) {
2037 // Log the outcome since the injector did not wait for the injection result.
2038 switch (injectionResult) {
2039 case INPUT_EVENT_INJECTION_SUCCEEDED:
2040 LOGV("Asynchronous input event injection succeeded.");
2041 break;
2042 case INPUT_EVENT_INJECTION_FAILED:
2043 LOGW("Asynchronous input event injection failed.");
2044 break;
2045 case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
2046 LOGW("Asynchronous input event injection permission denied.");
2047 break;
2048 case INPUT_EVENT_INJECTION_TIMED_OUT:
2049 LOGW("Asynchronous input event injection timed out.");
2050 break;
2051 }
2052 }
2053
Jeff Brown7fbdc842010-06-17 20:52:56 -07002054 entry->injectionResult = injectionResult;
2055 mInjectionResultAvailableCondition.broadcast();
2056 }
2057}
2058
Jeff Brown519e0242010-09-15 15:18:56 -07002059void InputDispatcher::decrementPendingForegroundDispatchesLocked(EventEntry* entry) {
2060 entry->pendingForegroundDispatches -= 1;
Jeff Brown6ec402b2010-07-28 15:48:59 -07002061
Jeff Brown519e0242010-09-15 15:18:56 -07002062 if (entry->isInjected() && entry->pendingForegroundDispatches == 0) {
Jeff Brown6ec402b2010-07-28 15:48:59 -07002063 mInjectionSyncFinishedCondition.broadcast();
2064 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07002065}
2066
Jeff Brownb88102f2010-09-08 11:49:43 -07002067static bool isValidKeyAction(int32_t action) {
2068 switch (action) {
2069 case AKEY_EVENT_ACTION_DOWN:
2070 case AKEY_EVENT_ACTION_UP:
2071 return true;
2072 default:
2073 return false;
2074 }
2075}
2076
2077static bool isValidMotionAction(int32_t action) {
2078 switch (action & AMOTION_EVENT_ACTION_MASK) {
2079 case AMOTION_EVENT_ACTION_DOWN:
2080 case AMOTION_EVENT_ACTION_UP:
2081 case AMOTION_EVENT_ACTION_CANCEL:
2082 case AMOTION_EVENT_ACTION_MOVE:
2083 case AMOTION_EVENT_ACTION_POINTER_DOWN:
2084 case AMOTION_EVENT_ACTION_POINTER_UP:
2085 case AMOTION_EVENT_ACTION_OUTSIDE:
2086 return true;
2087 default:
2088 return false;
2089 }
2090}
2091
2092InputDispatcher::EventEntry* InputDispatcher::createEntryFromInjectedInputEventLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07002093 const InputEvent* event) {
2094 switch (event->getType()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002095 case AINPUT_EVENT_TYPE_KEY: {
Jeff Brown7fbdc842010-06-17 20:52:56 -07002096 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
Jeff Brownb88102f2010-09-08 11:49:43 -07002097 if (! isValidKeyAction(keyEvent->getAction())) {
2098 LOGE("Dropping injected key event since it has invalid action code 0x%x",
2099 keyEvent->getAction());
2100 return NULL;
2101 }
2102
Jeff Brown85a31762010-09-01 17:01:00 -07002103 uint32_t policyFlags = POLICY_FLAG_INJECTED;
Jeff Brown7fbdc842010-06-17 20:52:56 -07002104
2105 KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
Jeff Brownc5ed5912010-07-14 18:48:53 -07002106 keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -07002107 keyEvent->getAction(), keyEvent->getFlags(),
2108 keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
2109 keyEvent->getRepeatCount(), keyEvent->getDownTime());
2110 return keyEntry;
2111 }
2112
Jeff Brownc5ed5912010-07-14 18:48:53 -07002113 case AINPUT_EVENT_TYPE_MOTION: {
Jeff Brown7fbdc842010-06-17 20:52:56 -07002114 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
Jeff Brownb88102f2010-09-08 11:49:43 -07002115 if (! isValidMotionAction(motionEvent->getAction())) {
2116 LOGE("Dropping injected motion event since it has invalid action code 0x%x.",
2117 motionEvent->getAction());
2118 return NULL;
2119 }
2120 if (motionEvent->getPointerCount() == 0
2121 || motionEvent->getPointerCount() > MAX_POINTERS) {
2122 LOGE("Dropping injected motion event since it has an invalid pointer count %d.",
2123 motionEvent->getPointerCount());
2124 }
2125
Jeff Brown85a31762010-09-01 17:01:00 -07002126 uint32_t policyFlags = POLICY_FLAG_INJECTED;
Jeff Brown7fbdc842010-06-17 20:52:56 -07002127
2128 const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
2129 const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
2130 size_t pointerCount = motionEvent->getPointerCount();
2131
2132 MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
Jeff Brownc5ed5912010-07-14 18:48:53 -07002133 motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
Jeff Brown85a31762010-09-01 17:01:00 -07002134 motionEvent->getAction(), motionEvent->getFlags(),
2135 motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
Jeff Brown7fbdc842010-06-17 20:52:56 -07002136 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
2137 motionEvent->getDownTime(), uint32_t(pointerCount),
2138 motionEvent->getPointerIds(), samplePointerCoords);
2139 for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
2140 sampleEventTimes += 1;
2141 samplePointerCoords += pointerCount;
2142 mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
2143 }
2144 return motionEntry;
2145 }
2146
2147 default:
2148 assert(false);
2149 return NULL;
2150 }
2151}
2152
Jeff Brownb88102f2010-09-08 11:49:43 -07002153void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
2154#if DEBUG_FOCUS
2155 LOGD("setInputWindows");
2156#endif
2157 { // acquire lock
2158 AutoMutex _l(mLock);
2159
Jeff Brown519e0242010-09-15 15:18:56 -07002160 sp<InputChannel> oldFocusedWindowChannel = mFocusedWindow
2161 ? mFocusedWindow->inputChannel : NULL;
2162 int32_t oldFocusedWindowLayer = mFocusedWindow ? mFocusedWindow->layer : -1;
2163
Jeff Brownb88102f2010-09-08 11:49:43 -07002164 sp<InputChannel> touchedWindowChannel;
2165 if (mTouchedWindow) {
2166 touchedWindowChannel = mTouchedWindow->inputChannel;
2167 mTouchedWindow = NULL;
2168 }
2169 size_t numTouchedWallpapers = mTouchedWallpaperWindows.size();
2170 if (numTouchedWallpapers != 0) {
2171 for (size_t i = 0; i < numTouchedWallpapers; i++) {
2172 mTempTouchedWallpaperChannels.push(mTouchedWallpaperWindows[i]->inputChannel);
2173 }
2174 mTouchedWallpaperWindows.clear();
2175 }
2176
Jeff Brownb88102f2010-09-08 11:49:43 -07002177 mFocusedWindow = NULL;
2178 mWallpaperWindows.clear();
2179
2180 mWindows.clear();
2181 mWindows.appendVector(inputWindows);
2182
2183 size_t numWindows = mWindows.size();
2184 for (size_t i = 0; i < numWindows; i++) {
2185 InputWindow* window = & mWindows.editItemAt(i);
2186 if (window->hasFocus) {
2187 mFocusedWindow = window;
2188 }
2189
2190 if (window->layoutParamsType == InputWindow::TYPE_WALLPAPER) {
2191 mWallpaperWindows.push(window);
2192
2193 for (size_t j = 0; j < numTouchedWallpapers; j++) {
2194 if (window->inputChannel == mTempTouchedWallpaperChannels[i]) {
2195 mTouchedWallpaperWindows.push(window);
2196 }
2197 }
2198 }
2199
2200 if (window->inputChannel == touchedWindowChannel) {
2201 mTouchedWindow = window;
2202 }
2203 }
2204
2205 mTempTouchedWallpaperChannels.clear();
2206
Jeff Brown519e0242010-09-15 15:18:56 -07002207 bool preempt = false;
2208 if (mFocusedWindow
2209 && mFocusedWindow->inputChannel != oldFocusedWindowChannel
2210 && mFocusedWindow->canReceiveKeys) {
2211 // If the new input focus is an error window or appears above the current
2212 // input focus, drop the current touched window so that we can start
2213 // delivering events to the new input focus as soon as possible.
2214 if (mFocusedWindow->layoutParamsFlags & InputWindow::FLAG_SYSTEM_ERROR) {
2215#if DEBUG_FOCUS
2216 LOGD("Preempting: New SYSTEM_ERROR window; resetting state");
2217#endif
2218 preempt = true;
2219 } else if (oldFocusedWindowChannel.get() != NULL
2220 && mFocusedWindow->layer > oldFocusedWindowLayer) {
2221#if DEBUG_FOCUS
2222 LOGD("Preempting: Transferring focus to new window at higher layer: "
2223 "old win layer=%d, new win layer=%d",
2224 oldFocusedWindowLayer, mFocusedWindow->layer);
2225#endif
2226 preempt = true;
2227 }
2228 }
2229 if (mTouchedWindow && ! mTouchedWindow->visible) {
2230#if DEBUG_FOCUS
2231 LOGD("Preempting: Touched window became invisible.");
2232#endif
2233 preempt = true;
2234 }
2235 if (preempt) {
2236 releaseTouchedWindowLocked();
Jeff Brownb88102f2010-09-08 11:49:43 -07002237 }
2238
2239#if DEBUG_FOCUS
2240 logDispatchStateLocked();
2241#endif
2242 } // release lock
2243
2244 // Wake up poll loop since it may need to make new input dispatching choices.
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002245 mLooper->wake();
Jeff Brownb88102f2010-09-08 11:49:43 -07002246}
2247
2248void InputDispatcher::setFocusedApplication(const InputApplication* inputApplication) {
2249#if DEBUG_FOCUS
2250 LOGD("setFocusedApplication");
2251#endif
2252 { // acquire lock
2253 AutoMutex _l(mLock);
2254
2255 releaseFocusedApplicationLocked();
2256
2257 if (inputApplication) {
2258 mFocusedApplicationStorage = *inputApplication;
2259 mFocusedApplication = & mFocusedApplicationStorage;
2260 }
2261
2262#if DEBUG_FOCUS
2263 logDispatchStateLocked();
2264#endif
2265 } // release lock
2266
2267 // Wake up poll loop since it may need to make new input dispatching choices.
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002268 mLooper->wake();
Jeff Brownb88102f2010-09-08 11:49:43 -07002269}
2270
2271void InputDispatcher::releaseFocusedApplicationLocked() {
2272 if (mFocusedApplication) {
2273 mFocusedApplication = NULL;
2274 mFocusedApplicationStorage.handle.clear();
2275 }
2276}
2277
2278void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
2279#if DEBUG_FOCUS
2280 LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
2281#endif
2282
2283 bool changed;
2284 { // acquire lock
2285 AutoMutex _l(mLock);
2286
2287 if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
2288 if (mDispatchFrozen && ! frozen) {
2289 resetANRTimeoutsLocked();
2290 }
2291
2292 mDispatchEnabled = enabled;
2293 mDispatchFrozen = frozen;
2294 changed = true;
2295 } else {
2296 changed = false;
2297 }
2298
2299#if DEBUG_FOCUS
2300 logDispatchStateLocked();
2301#endif
2302 } // release lock
2303
2304 if (changed) {
2305 // Wake up poll loop since it may need to make new input dispatching choices.
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002306 mLooper->wake();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002307 }
2308}
2309
Jeff Brownb88102f2010-09-08 11:49:43 -07002310void InputDispatcher::logDispatchStateLocked() {
2311 String8 dump;
2312 dumpDispatchStateLocked(dump);
2313 LOGD("%s", dump.string());
2314}
2315
2316void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
2317 dump.appendFormat(" dispatchEnabled: %d\n", mDispatchEnabled);
2318 dump.appendFormat(" dispatchFrozen: %d\n", mDispatchFrozen);
2319
2320 if (mFocusedApplication) {
2321 dump.appendFormat(" focusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
2322 mFocusedApplication->name.string(),
2323 mFocusedApplication->dispatchingTimeout / 1000000.0);
2324 } else {
2325 dump.append(" focusedApplication: <null>\n");
2326 }
2327 dump.appendFormat(" focusedWindow: '%s'\n",
2328 mFocusedWindow != NULL ? mFocusedWindow->inputChannel->getName().string() : "<null>");
2329 dump.appendFormat(" touchedWindow: '%s', touchDown=%d\n",
2330 mTouchedWindow != NULL ? mTouchedWindow->inputChannel->getName().string() : "<null>",
2331 mTouchDown);
2332 for (size_t i = 0; i < mTouchedWallpaperWindows.size(); i++) {
2333 dump.appendFormat(" touchedWallpaperWindows[%d]: '%s'\n",
2334 i, mTouchedWallpaperWindows[i]->inputChannel->getName().string());
2335 }
2336 for (size_t i = 0; i < mWindows.size(); i++) {
2337 dump.appendFormat(" windows[%d]: '%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
2338 "visible=%s, flags=0x%08x, type=0x%08x, "
2339 "frame=[%d,%d][%d,%d], "
2340 "visibleFrame=[%d,%d][%d,%d], "
2341 "touchableArea=[%d,%d][%d,%d], "
2342 "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
2343 i, mWindows[i].inputChannel->getName().string(),
2344 toString(mWindows[i].paused),
2345 toString(mWindows[i].hasFocus),
2346 toString(mWindows[i].hasWallpaper),
2347 toString(mWindows[i].visible),
2348 mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
2349 mWindows[i].frameLeft, mWindows[i].frameTop,
2350 mWindows[i].frameRight, mWindows[i].frameBottom,
2351 mWindows[i].visibleFrameLeft, mWindows[i].visibleFrameTop,
2352 mWindows[i].visibleFrameRight, mWindows[i].visibleFrameBottom,
2353 mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop,
2354 mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom,
2355 mWindows[i].ownerPid, mWindows[i].ownerUid,
2356 mWindows[i].dispatchingTimeout / 1000000.0);
2357 }
2358
2359 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
2360 const sp<InputChannel>& channel = mMonitoringChannels[i];
2361 dump.appendFormat(" monitoringChannel[%d]: '%s'\n",
2362 i, channel->getName().string());
2363 }
2364
Jeff Brown519e0242010-09-15 15:18:56 -07002365 dump.appendFormat(" inboundQueue: length=%u", mInboundQueue.count());
2366
Jeff Brownb88102f2010-09-08 11:49:43 -07002367 for (size_t i = 0; i < mActiveConnections.size(); i++) {
2368 const Connection* connection = mActiveConnections[i];
Jeff Brown519e0242010-09-15 15:18:56 -07002369 dump.appendFormat(" activeConnection[%d]: '%s', status=%s, outboundQueueLength=%u"
Jeff Brownb88102f2010-09-08 11:49:43 -07002370 "inputState.isNeutral=%s, inputState.isOutOfSync=%s\n",
2371 i, connection->getInputChannelName(), connection->getStatusLabel(),
Jeff Brown519e0242010-09-15 15:18:56 -07002372 connection->outboundQueue.count(),
Jeff Brownb88102f2010-09-08 11:49:43 -07002373 toString(connection->inputState.isNeutral()),
2374 toString(connection->inputState.isOutOfSync()));
2375 }
2376
2377 if (isAppSwitchPendingLocked()) {
2378 dump.appendFormat(" appSwitch: pending, due in %01.1fms\n",
2379 (mAppSwitchDueTime - now()) / 1000000.0);
2380 } else {
2381 dump.append(" appSwitch: not pending\n");
2382 }
2383}
2384
2385status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07002386#if DEBUG_REGISTRATION
Jeff Brownb88102f2010-09-08 11:49:43 -07002387 LOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().string(),
2388 toString(monitor));
Jeff Brown9c3cda02010-06-15 01:31:58 -07002389#endif
2390
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002391 { // acquire lock
2392 AutoMutex _l(mLock);
2393
Jeff Brown519e0242010-09-15 15:18:56 -07002394 if (getConnectionIndexLocked(inputChannel) >= 0) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002395 LOGW("Attempted to register already registered input channel '%s'",
2396 inputChannel->getName().string());
2397 return BAD_VALUE;
2398 }
2399
2400 sp<Connection> connection = new Connection(inputChannel);
2401 status_t status = connection->initialize();
2402 if (status) {
2403 LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
2404 inputChannel->getName().string(), status);
2405 return status;
2406 }
2407
Jeff Brown2cbecea2010-08-17 15:59:26 -07002408 int32_t receiveFd = inputChannel->getReceivePipeFd();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002409 mConnectionsByReceiveFd.add(receiveFd, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -07002410
Jeff Brownb88102f2010-09-08 11:49:43 -07002411 if (monitor) {
2412 mMonitoringChannels.push(inputChannel);
2413 }
2414
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002415 mLooper->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
Jeff Brown2cbecea2010-08-17 15:59:26 -07002416
Jeff Brown9c3cda02010-06-15 01:31:58 -07002417 runCommandsLockedInterruptible();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002418 } // release lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002419 return OK;
2420}
2421
2422status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07002423#if DEBUG_REGISTRATION
Jeff Brown349703e2010-06-22 01:27:15 -07002424 LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
Jeff Brown9c3cda02010-06-15 01:31:58 -07002425#endif
2426
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002427 { // acquire lock
2428 AutoMutex _l(mLock);
2429
Jeff Brown519e0242010-09-15 15:18:56 -07002430 ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002431 if (connectionIndex < 0) {
2432 LOGW("Attempted to unregister already unregistered input channel '%s'",
2433 inputChannel->getName().string());
2434 return BAD_VALUE;
2435 }
2436
2437 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
2438 mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
2439
2440 connection->status = Connection::STATUS_ZOMBIE;
2441
Jeff Brownb88102f2010-09-08 11:49:43 -07002442 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
2443 if (mMonitoringChannels[i] == inputChannel) {
2444 mMonitoringChannels.removeAt(i);
2445 break;
2446 }
2447 }
2448
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002449 mLooper->removeFd(inputChannel->getReceivePipeFd());
Jeff Brown2cbecea2010-08-17 15:59:26 -07002450
Jeff Brown7fbdc842010-06-17 20:52:56 -07002451 nsecs_t currentTime = now();
2452 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown9c3cda02010-06-15 01:31:58 -07002453
2454 runCommandsLockedInterruptible();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002455 } // release lock
2456
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002457 // Wake the poll loop because removing the connection may have changed the current
2458 // synchronization state.
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002459 mLooper->wake();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002460 return OK;
2461}
2462
Jeff Brown519e0242010-09-15 15:18:56 -07002463ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
Jeff Brown2cbecea2010-08-17 15:59:26 -07002464 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(inputChannel->getReceivePipeFd());
2465 if (connectionIndex >= 0) {
2466 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
2467 if (connection->inputChannel.get() == inputChannel.get()) {
2468 return connectionIndex;
2469 }
2470 }
2471
2472 return -1;
2473}
2474
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002475void InputDispatcher::activateConnectionLocked(Connection* connection) {
2476 for (size_t i = 0; i < mActiveConnections.size(); i++) {
2477 if (mActiveConnections.itemAt(i) == connection) {
2478 return;
2479 }
2480 }
2481 mActiveConnections.add(connection);
2482}
2483
2484void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
2485 for (size_t i = 0; i < mActiveConnections.size(); i++) {
2486 if (mActiveConnections.itemAt(i) == connection) {
2487 mActiveConnections.removeAt(i);
2488 return;
2489 }
2490 }
2491}
2492
Jeff Brown9c3cda02010-06-15 01:31:58 -07002493void InputDispatcher::onDispatchCycleStartedLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07002494 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002495}
2496
Jeff Brown9c3cda02010-06-15 01:31:58 -07002497void InputDispatcher::onDispatchCycleFinishedLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07002498 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002499}
2500
Jeff Brown9c3cda02010-06-15 01:31:58 -07002501void InputDispatcher::onDispatchCycleBrokenLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07002502 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002503 LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
2504 connection->getInputChannelName());
2505
Jeff Brown9c3cda02010-06-15 01:31:58 -07002506 CommandEntry* commandEntry = postCommandLocked(
2507 & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002508 commandEntry->connection = connection;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002509}
2510
Jeff Brown519e0242010-09-15 15:18:56 -07002511void InputDispatcher::onANRLocked(
2512 nsecs_t currentTime, const InputApplication* application, const InputWindow* window,
2513 nsecs_t eventTime, nsecs_t waitStartTime) {
2514 LOGI("Application is not responding: %s. "
2515 "%01.1fms since event, %01.1fms since wait started",
2516 getApplicationWindowLabelLocked(application, window).string(),
2517 (currentTime - eventTime) / 1000000.0,
2518 (currentTime - waitStartTime) / 1000000.0);
2519
2520 CommandEntry* commandEntry = postCommandLocked(
2521 & InputDispatcher::doNotifyANRLockedInterruptible);
2522 if (application) {
2523 commandEntry->inputApplicationHandle = application->handle;
2524 }
2525 if (window) {
2526 commandEntry->inputChannel = window->inputChannel;
2527 }
2528}
2529
Jeff Brownb88102f2010-09-08 11:49:43 -07002530void InputDispatcher::doNotifyConfigurationChangedInterruptible(
2531 CommandEntry* commandEntry) {
2532 mLock.unlock();
2533
2534 mPolicy->notifyConfigurationChanged(commandEntry->eventTime);
2535
2536 mLock.lock();
2537}
2538
Jeff Brown9c3cda02010-06-15 01:31:58 -07002539void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
2540 CommandEntry* commandEntry) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07002541 sp<Connection> connection = commandEntry->connection;
Jeff Brown9c3cda02010-06-15 01:31:58 -07002542
Jeff Brown7fbdc842010-06-17 20:52:56 -07002543 if (connection->status != Connection::STATUS_ZOMBIE) {
2544 mLock.unlock();
Jeff Brown9c3cda02010-06-15 01:31:58 -07002545
Jeff Brown7fbdc842010-06-17 20:52:56 -07002546 mPolicy->notifyInputChannelBroken(connection->inputChannel);
2547
2548 mLock.lock();
2549 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07002550}
2551
Jeff Brown519e0242010-09-15 15:18:56 -07002552void InputDispatcher::doNotifyANRLockedInterruptible(
Jeff Brown9c3cda02010-06-15 01:31:58 -07002553 CommandEntry* commandEntry) {
Jeff Brown519e0242010-09-15 15:18:56 -07002554 mLock.unlock();
Jeff Brown9c3cda02010-06-15 01:31:58 -07002555
Jeff Brown519e0242010-09-15 15:18:56 -07002556 nsecs_t newTimeout = mPolicy->notifyANR(
2557 commandEntry->inputApplicationHandle, commandEntry->inputChannel);
Jeff Brown9c3cda02010-06-15 01:31:58 -07002558
Jeff Brown519e0242010-09-15 15:18:56 -07002559 mLock.lock();
Jeff Brown7fbdc842010-06-17 20:52:56 -07002560
Jeff Brown519e0242010-09-15 15:18:56 -07002561 resumeAfterTargetsNotReadyTimeoutLocked(newTimeout, commandEntry->inputChannel);
Jeff Brown9c3cda02010-06-15 01:31:58 -07002562}
2563
Jeff Brownb88102f2010-09-08 11:49:43 -07002564void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
2565 CommandEntry* commandEntry) {
2566 KeyEntry* entry = commandEntry->keyEntry;
2567 mReusableKeyEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
2568 entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
2569 entry->downTime, entry->eventTime);
2570
2571 mLock.unlock();
2572
2573 bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputChannel,
2574 & mReusableKeyEvent, entry->policyFlags);
2575
2576 mLock.lock();
2577
2578 entry->interceptKeyResult = consumed
2579 ? KeyEntry::INTERCEPT_KEY_RESULT_SKIP
2580 : KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
2581 mAllocator.releaseKeyEntry(entry);
2582}
2583
2584void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
2585 mLock.unlock();
2586
2587 mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->windowType,
2588 commandEntry->userActivityEventType);
2589
2590 mLock.lock();
2591}
2592
Jeff Brown519e0242010-09-15 15:18:56 -07002593void InputDispatcher::updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
2594 int32_t injectionResult, nsecs_t timeSpentWaitingForApplication) {
2595 // TODO Write some statistics about how long we spend waiting.
Jeff Brownb88102f2010-09-08 11:49:43 -07002596}
2597
2598void InputDispatcher::dump(String8& dump) {
2599 dumpDispatchStateLocked(dump);
2600}
2601
Jeff Brown9c3cda02010-06-15 01:31:58 -07002602
Jeff Brown519e0242010-09-15 15:18:56 -07002603// --- InputDispatcher::Queue ---
2604
2605template <typename T>
2606uint32_t InputDispatcher::Queue<T>::count() const {
2607 uint32_t result = 0;
2608 for (const T* entry = headSentinel.next; entry != & tailSentinel; entry = entry->next) {
2609 result += 1;
2610 }
2611 return result;
2612}
2613
2614
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002615// --- InputDispatcher::Allocator ---
2616
2617InputDispatcher::Allocator::Allocator() {
2618}
2619
Jeff Brown7fbdc842010-06-17 20:52:56 -07002620void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
2621 nsecs_t eventTime) {
2622 entry->type = type;
2623 entry->refCount = 1;
2624 entry->dispatchInProgress = false;
Christopher Tatee91a5db2010-06-23 16:50:30 -07002625 entry->eventTime = eventTime;
Jeff Brown7fbdc842010-06-17 20:52:56 -07002626 entry->injectionResult = INPUT_EVENT_INJECTION_PENDING;
Jeff Brown6ec402b2010-07-28 15:48:59 -07002627 entry->injectionIsAsync = false;
Jeff Brown7fbdc842010-06-17 20:52:56 -07002628 entry->injectorPid = -1;
2629 entry->injectorUid = -1;
Jeff Brown519e0242010-09-15 15:18:56 -07002630 entry->pendingForegroundDispatches = 0;
Jeff Brown7fbdc842010-06-17 20:52:56 -07002631}
2632
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002633InputDispatcher::ConfigurationChangedEntry*
Jeff Brown7fbdc842010-06-17 20:52:56 -07002634InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002635 ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
Jeff Brown7fbdc842010-06-17 20:52:56 -07002636 initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002637 return entry;
2638}
2639
Jeff Brown7fbdc842010-06-17 20:52:56 -07002640InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -07002641 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
Jeff Brown7fbdc842010-06-17 20:52:56 -07002642 int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
2643 int32_t repeatCount, nsecs_t downTime) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002644 KeyEntry* entry = mKeyEntryPool.alloc();
Jeff Brown7fbdc842010-06-17 20:52:56 -07002645 initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime);
2646
2647 entry->deviceId = deviceId;
Jeff Brownc5ed5912010-07-14 18:48:53 -07002648 entry->source = source;
Jeff Brown7fbdc842010-06-17 20:52:56 -07002649 entry->policyFlags = policyFlags;
2650 entry->action = action;
2651 entry->flags = flags;
2652 entry->keyCode = keyCode;
2653 entry->scanCode = scanCode;
2654 entry->metaState = metaState;
2655 entry->repeatCount = repeatCount;
2656 entry->downTime = downTime;
Jeff Brownb88102f2010-09-08 11:49:43 -07002657 entry->syntheticRepeat = false;
2658 entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002659 return entry;
2660}
2661
Jeff Brown7fbdc842010-06-17 20:52:56 -07002662InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
Jeff Brown85a31762010-09-01 17:01:00 -07002663 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
Jeff Brown7fbdc842010-06-17 20:52:56 -07002664 int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
2665 nsecs_t downTime, uint32_t pointerCount,
2666 const int32_t* pointerIds, const PointerCoords* pointerCoords) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002667 MotionEntry* entry = mMotionEntryPool.alloc();
Jeff Brown7fbdc842010-06-17 20:52:56 -07002668 initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime);
2669
2670 entry->eventTime = eventTime;
2671 entry->deviceId = deviceId;
Jeff Brownc5ed5912010-07-14 18:48:53 -07002672 entry->source = source;
Jeff Brown7fbdc842010-06-17 20:52:56 -07002673 entry->policyFlags = policyFlags;
2674 entry->action = action;
Jeff Brown85a31762010-09-01 17:01:00 -07002675 entry->flags = flags;
Jeff Brown7fbdc842010-06-17 20:52:56 -07002676 entry->metaState = metaState;
2677 entry->edgeFlags = edgeFlags;
2678 entry->xPrecision = xPrecision;
2679 entry->yPrecision = yPrecision;
2680 entry->downTime = downTime;
2681 entry->pointerCount = pointerCount;
2682 entry->firstSample.eventTime = eventTime;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002683 entry->firstSample.next = NULL;
Jeff Brown7fbdc842010-06-17 20:52:56 -07002684 entry->lastSample = & entry->firstSample;
2685 for (uint32_t i = 0; i < pointerCount; i++) {
2686 entry->pointerIds[i] = pointerIds[i];
2687 entry->firstSample.pointerCoords[i] = pointerCoords[i];
2688 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002689 return entry;
2690}
2691
2692InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
Jeff Brownb88102f2010-09-08 11:49:43 -07002693 EventEntry* eventEntry,
Jeff Brown519e0242010-09-15 15:18:56 -07002694 int32_t targetFlags, float xOffset, float yOffset) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002695 DispatchEntry* entry = mDispatchEntryPool.alloc();
2696 entry->eventEntry = eventEntry;
2697 eventEntry->refCount += 1;
Jeff Brownb88102f2010-09-08 11:49:43 -07002698 entry->targetFlags = targetFlags;
2699 entry->xOffset = xOffset;
2700 entry->yOffset = yOffset;
Jeff Brownb88102f2010-09-08 11:49:43 -07002701 entry->inProgress = false;
2702 entry->headMotionSample = NULL;
2703 entry->tailMotionSample = NULL;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002704 return entry;
2705}
2706
Jeff Brown9c3cda02010-06-15 01:31:58 -07002707InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
2708 CommandEntry* entry = mCommandEntryPool.alloc();
2709 entry->command = command;
2710 return entry;
2711}
2712
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002713void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
2714 switch (entry->type) {
2715 case EventEntry::TYPE_CONFIGURATION_CHANGED:
2716 releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
2717 break;
2718 case EventEntry::TYPE_KEY:
2719 releaseKeyEntry(static_cast<KeyEntry*>(entry));
2720 break;
2721 case EventEntry::TYPE_MOTION:
2722 releaseMotionEntry(static_cast<MotionEntry*>(entry));
2723 break;
2724 default:
2725 assert(false);
2726 break;
2727 }
2728}
2729
2730void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
2731 ConfigurationChangedEntry* entry) {
2732 entry->refCount -= 1;
2733 if (entry->refCount == 0) {
2734 mConfigurationChangeEntryPool.free(entry);
2735 } else {
2736 assert(entry->refCount > 0);
2737 }
2738}
2739
2740void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
2741 entry->refCount -= 1;
2742 if (entry->refCount == 0) {
2743 mKeyEntryPool.free(entry);
2744 } else {
2745 assert(entry->refCount > 0);
2746 }
2747}
2748
2749void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
2750 entry->refCount -= 1;
2751 if (entry->refCount == 0) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07002752 for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
2753 MotionSample* next = sample->next;
2754 mMotionSamplePool.free(sample);
2755 sample = next;
2756 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002757 mMotionEntryPool.free(entry);
2758 } else {
2759 assert(entry->refCount > 0);
2760 }
2761}
2762
2763void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
2764 releaseEventEntry(entry->eventEntry);
2765 mDispatchEntryPool.free(entry);
2766}
2767
Jeff Brown9c3cda02010-06-15 01:31:58 -07002768void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
2769 mCommandEntryPool.free(entry);
2770}
2771
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002772void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
Jeff Brown7fbdc842010-06-17 20:52:56 -07002773 nsecs_t eventTime, const PointerCoords* pointerCoords) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002774 MotionSample* sample = mMotionSamplePool.alloc();
2775 sample->eventTime = eventTime;
Jeff Brown7fbdc842010-06-17 20:52:56 -07002776 uint32_t pointerCount = motionEntry->pointerCount;
2777 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002778 sample->pointerCoords[i] = pointerCoords[i];
2779 }
2780
2781 sample->next = NULL;
2782 motionEntry->lastSample->next = sample;
2783 motionEntry->lastSample = sample;
2784}
2785
Jeff Brownb88102f2010-09-08 11:49:43 -07002786
2787// --- InputDispatcher::EventEntry ---
2788
2789void InputDispatcher::EventEntry::recycle() {
2790 injectionResult = INPUT_EVENT_INJECTION_PENDING;
2791 dispatchInProgress = false;
Jeff Brown519e0242010-09-15 15:18:56 -07002792 pendingForegroundDispatches = 0;
Jeff Brownb88102f2010-09-08 11:49:43 -07002793}
2794
2795
2796// --- InputDispatcher::KeyEntry ---
2797
2798void InputDispatcher::KeyEntry::recycle() {
2799 EventEntry::recycle();
2800 syntheticRepeat = false;
2801 interceptKeyResult = INTERCEPT_KEY_RESULT_UNKNOWN;
2802}
2803
2804
Jeff Brownae9fc032010-08-18 15:51:08 -07002805// --- InputDispatcher::MotionEntry ---
2806
2807uint32_t InputDispatcher::MotionEntry::countSamples() const {
2808 uint32_t count = 1;
2809 for (MotionSample* sample = firstSample.next; sample != NULL; sample = sample->next) {
2810 count += 1;
2811 }
2812 return count;
2813}
2814
Jeff Brownb88102f2010-09-08 11:49:43 -07002815
2816// --- InputDispatcher::InputState ---
2817
2818InputDispatcher::InputState::InputState() :
2819 mIsOutOfSync(false) {
2820}
2821
2822InputDispatcher::InputState::~InputState() {
2823}
2824
2825bool InputDispatcher::InputState::isNeutral() const {
2826 return mKeyMementos.isEmpty() && mMotionMementos.isEmpty();
2827}
2828
2829bool InputDispatcher::InputState::isOutOfSync() const {
2830 return mIsOutOfSync;
2831}
2832
2833void InputDispatcher::InputState::setOutOfSync() {
2834 if (! isNeutral()) {
2835 mIsOutOfSync = true;
2836 }
2837}
2838
2839void InputDispatcher::InputState::resetOutOfSync() {
2840 mIsOutOfSync = false;
2841}
2842
2843InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackEvent(
2844 const EventEntry* entry) {
2845 switch (entry->type) {
2846 case EventEntry::TYPE_KEY:
2847 return trackKey(static_cast<const KeyEntry*>(entry));
2848
2849 case EventEntry::TYPE_MOTION:
2850 return trackMotion(static_cast<const MotionEntry*>(entry));
2851
2852 default:
2853 return CONSISTENT;
2854 }
2855}
2856
2857InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackKey(
2858 const KeyEntry* entry) {
2859 int32_t action = entry->action;
2860 for (size_t i = 0; i < mKeyMementos.size(); i++) {
2861 KeyMemento& memento = mKeyMementos.editItemAt(i);
2862 if (memento.deviceId == entry->deviceId
2863 && memento.source == entry->source
2864 && memento.keyCode == entry->keyCode
2865 && memento.scanCode == entry->scanCode) {
2866 switch (action) {
2867 case AKEY_EVENT_ACTION_UP:
2868 mKeyMementos.removeAt(i);
2869 if (isNeutral()) {
2870 mIsOutOfSync = false;
2871 }
2872 return CONSISTENT;
2873
2874 case AKEY_EVENT_ACTION_DOWN:
2875 return TOLERABLE;
2876
2877 default:
2878 return BROKEN;
2879 }
2880 }
2881 }
2882
2883 switch (action) {
2884 case AKEY_EVENT_ACTION_DOWN: {
2885 mKeyMementos.push();
2886 KeyMemento& memento = mKeyMementos.editTop();
2887 memento.deviceId = entry->deviceId;
2888 memento.source = entry->source;
2889 memento.keyCode = entry->keyCode;
2890 memento.scanCode = entry->scanCode;
2891 memento.downTime = entry->downTime;
2892 return CONSISTENT;
2893 }
2894
2895 default:
2896 return BROKEN;
2897 }
2898}
2899
2900InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackMotion(
2901 const MotionEntry* entry) {
2902 int32_t action = entry->action & AMOTION_EVENT_ACTION_MASK;
2903 for (size_t i = 0; i < mMotionMementos.size(); i++) {
2904 MotionMemento& memento = mMotionMementos.editItemAt(i);
2905 if (memento.deviceId == entry->deviceId
2906 && memento.source == entry->source) {
2907 switch (action) {
2908 case AMOTION_EVENT_ACTION_UP:
2909 case AMOTION_EVENT_ACTION_CANCEL:
2910 mMotionMementos.removeAt(i);
2911 if (isNeutral()) {
2912 mIsOutOfSync = false;
2913 }
2914 return CONSISTENT;
2915
2916 case AMOTION_EVENT_ACTION_DOWN:
2917 return TOLERABLE;
2918
2919 case AMOTION_EVENT_ACTION_POINTER_DOWN:
2920 if (entry->pointerCount == memento.pointerCount + 1) {
2921 memento.setPointers(entry);
2922 return CONSISTENT;
2923 }
2924 return BROKEN;
2925
2926 case AMOTION_EVENT_ACTION_POINTER_UP:
2927 if (entry->pointerCount == memento.pointerCount - 1) {
2928 memento.setPointers(entry);
2929 return CONSISTENT;
2930 }
2931 return BROKEN;
2932
2933 case AMOTION_EVENT_ACTION_MOVE:
2934 if (entry->pointerCount == memento.pointerCount) {
2935 return CONSISTENT;
2936 }
2937 return BROKEN;
2938
2939 default:
2940 return BROKEN;
2941 }
2942 }
2943 }
2944
2945 switch (action) {
2946 case AMOTION_EVENT_ACTION_DOWN: {
2947 mMotionMementos.push();
2948 MotionMemento& memento = mMotionMementos.editTop();
2949 memento.deviceId = entry->deviceId;
2950 memento.source = entry->source;
2951 memento.xPrecision = entry->xPrecision;
2952 memento.yPrecision = entry->yPrecision;
2953 memento.downTime = entry->downTime;
2954 memento.setPointers(entry);
2955 return CONSISTENT;
2956 }
2957
2958 default:
2959 return BROKEN;
2960 }
2961}
2962
2963void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) {
2964 pointerCount = entry->pointerCount;
2965 for (uint32_t i = 0; i < entry->pointerCount; i++) {
2966 pointerIds[i] = entry->pointerIds[i];
2967 pointerCoords[i] = entry->lastSample->pointerCoords[i];
2968 }
2969}
2970
2971void InputDispatcher::InputState::synthesizeCancelationEvents(
2972 Allocator* allocator, Vector<EventEntry*>& outEvents) const {
2973 for (size_t i = 0; i < mKeyMementos.size(); i++) {
2974 const KeyMemento& memento = mKeyMementos.itemAt(i);
2975 outEvents.push(allocator->obtainKeyEntry(now(),
2976 memento.deviceId, memento.source, 0,
2977 AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_CANCELED,
2978 memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
2979 }
2980
2981 for (size_t i = 0; i < mMotionMementos.size(); i++) {
2982 const MotionMemento& memento = mMotionMementos.itemAt(i);
2983 outEvents.push(allocator->obtainMotionEntry(now(),
2984 memento.deviceId, memento.source, 0,
2985 AMOTION_EVENT_ACTION_CANCEL, 0, 0, 0,
2986 memento.xPrecision, memento.yPrecision, memento.downTime,
2987 memento.pointerCount, memento.pointerIds, memento.pointerCoords));
2988 }
2989}
2990
2991void InputDispatcher::InputState::clear() {
2992 mKeyMementos.clear();
2993 mMotionMementos.clear();
2994 mIsOutOfSync = false;
2995}
2996
2997
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002998// --- InputDispatcher::Connection ---
2999
3000InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
3001 status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
Jeff Brown519e0242010-09-15 15:18:56 -07003002 lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003003}
3004
3005InputDispatcher::Connection::~Connection() {
3006}
3007
3008status_t InputDispatcher::Connection::initialize() {
3009 return inputPublisher.initialize();
3010}
3011
Jeff Brown9c3cda02010-06-15 01:31:58 -07003012const char* InputDispatcher::Connection::getStatusLabel() const {
3013 switch (status) {
3014 case STATUS_NORMAL:
3015 return "NORMAL";
3016
3017 case STATUS_BROKEN:
3018 return "BROKEN";
3019
Jeff Brown9c3cda02010-06-15 01:31:58 -07003020 case STATUS_ZOMBIE:
3021 return "ZOMBIE";
3022
3023 default:
3024 return "UNKNOWN";
3025 }
3026}
3027
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003028InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
3029 const EventEntry* eventEntry) const {
Jeff Brownb88102f2010-09-08 11:49:43 -07003030 for (DispatchEntry* dispatchEntry = outboundQueue.tailSentinel.prev;
3031 dispatchEntry != & outboundQueue.headSentinel; dispatchEntry = dispatchEntry->prev) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003032 if (dispatchEntry->eventEntry == eventEntry) {
3033 return dispatchEntry;
3034 }
3035 }
3036 return NULL;
3037}
3038
Jeff Brownb88102f2010-09-08 11:49:43 -07003039
Jeff Brown9c3cda02010-06-15 01:31:58 -07003040// --- InputDispatcher::CommandEntry ---
3041
Jeff Brownb88102f2010-09-08 11:49:43 -07003042InputDispatcher::CommandEntry::CommandEntry() :
3043 keyEntry(NULL) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07003044}
3045
3046InputDispatcher::CommandEntry::~CommandEntry() {
3047}
3048
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003049
3050// --- InputDispatcherThread ---
3051
3052InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
3053 Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
3054}
3055
3056InputDispatcherThread::~InputDispatcherThread() {
3057}
3058
3059bool InputDispatcherThread::threadLoop() {
3060 mDispatcher->dispatchOnce();
3061 return true;
3062}
3063
3064} // namespace android