blob: b8a26b04f0e156346ccc0319cfde61677288d90c [file] [log] [blame]
Jeff Browne839a582010-04-22 18:58:52 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4// The input dispatcher.
5//
6#define LOG_TAG "InputDispatcher"
7
8//#define LOG_NDEBUG 0
9
10// Log detailed debug messages about each inbound event notification to the dispatcher.
Jeff Brown50de30a2010-06-22 01:27:15 -070011#define DEBUG_INBOUND_EVENT_DETAILS 0
Jeff Browne839a582010-04-22 18:58:52 -070012
13// Log detailed debug messages about each outbound event processed by the dispatcher.
Jeff Brown50de30a2010-06-22 01:27:15 -070014#define DEBUG_OUTBOUND_EVENT_DETAILS 0
Jeff Browne839a582010-04-22 18:58:52 -070015
16// Log debug messages about batching.
Jeff Brown50de30a2010-06-22 01:27:15 -070017#define DEBUG_BATCHING 0
Jeff Browne839a582010-04-22 18:58:52 -070018
19// Log debug messages about the dispatch cycle.
Jeff Brown50de30a2010-06-22 01:27:15 -070020#define DEBUG_DISPATCH_CYCLE 0
Jeff Browne839a582010-04-22 18:58:52 -070021
Jeff Brown54bc2812010-06-15 01:31:58 -070022// Log debug messages about registrations.
Jeff Brown50de30a2010-06-22 01:27:15 -070023#define DEBUG_REGISTRATION 0
Jeff Brown54bc2812010-06-15 01:31:58 -070024
Jeff Browne839a582010-04-22 18:58:52 -070025// Log debug messages about performance statistics.
Jeff Brown50de30a2010-06-22 01:27:15 -070026#define DEBUG_PERFORMANCE_STATISTICS 0
Jeff Browne839a582010-04-22 18:58:52 -070027
Jeff Brown51d45a72010-06-17 20:52:56 -070028// Log debug messages about input event injection.
Jeff Brown50de30a2010-06-22 01:27:15 -070029#define DEBUG_INJECTION 0
Jeff Brown51d45a72010-06-17 20:52:56 -070030
Jeff Brown542412c2010-08-18 15:51:08 -070031// Log debug messages about input event throttling.
32#define DEBUG_THROTTLING 0
33
Jeff Browna665ca82010-09-08 11:49:43 -070034// Log debug messages about input focus tracking.
35#define DEBUG_FOCUS 0
36
37// Log debug messages about the app switch latency optimization.
38#define DEBUG_APP_SWITCH 0
39
Jeff Browne839a582010-04-22 18:58:52 -070040#include <cutils/log.h>
41#include <ui/InputDispatcher.h>
Jeff Browna665ca82010-09-08 11:49:43 -070042#include <ui/PowerManager.h>
Jeff Browne839a582010-04-22 18:58:52 -070043
44#include <stddef.h>
45#include <unistd.h>
Jeff Browne839a582010-04-22 18:58:52 -070046#include <errno.h>
47#include <limits.h>
Jeff Browne839a582010-04-22 18:58:52 -070048
49namespace android {
50
Jeff Browna665ca82010-09-08 11:49:43 -070051// Delay between reporting long touch events to the power manager.
52const nsecs_t EVENT_IGNORE_DURATION = 300 * 1000000LL; // 300 ms
53
54// Default input dispatching timeout if there is no focused application or paused window
55// from which to determine an appropriate dispatching timeout.
56const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
57
58// Amount of time to allow for all pending events to be processed when an app switch
59// key is on the way. This is used to preempt input dispatch and drop input events
60// when an application takes too long to respond and the user has pressed an app switch key.
61const nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
62
Jeff Browne839a582010-04-22 18:58:52 -070063
Jeff Brown51d45a72010-06-17 20:52:56 -070064static inline nsecs_t now() {
65 return systemTime(SYSTEM_TIME_MONOTONIC);
66}
67
Jeff Browna665ca82010-09-08 11:49:43 -070068static inline const char* toString(bool value) {
69 return value ? "true" : "false";
70}
71
72
73// --- InputWindow ---
74
75bool InputWindow::visibleFrameIntersects(const InputWindow* other) const {
76 return visibleFrameRight > other->visibleFrameLeft
77 && visibleFrameLeft < other->visibleFrameRight
78 && visibleFrameBottom > other->visibleFrameTop
79 && visibleFrameTop < other->visibleFrameBottom;
80}
81
82bool InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
83 return x >= touchableAreaLeft && x <= touchableAreaRight
84 && y >= touchableAreaTop && y <= touchableAreaBottom;
85}
86
87
Jeff Browne839a582010-04-22 18:58:52 -070088// --- InputDispatcher ---
89
Jeff Brown54bc2812010-06-15 01:31:58 -070090InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
Jeff Browna665ca82010-09-08 11:49:43 -070091 mPolicy(policy),
92 mPendingEvent(NULL), mAppSwitchDueTime(LONG_LONG_MAX),
93 mDispatchEnabled(true), mDispatchFrozen(false),
94 mFocusedWindow(NULL), mTouchDown(false), mTouchedWindow(NULL),
95 mFocusedApplication(NULL),
96 mCurrentInputTargetsValid(false),
97 mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
Dianne Hackborn3c5d1252010-07-07 14:27:31 -070098 mPollLoop = new PollLoop(false);
Jeff Browne839a582010-04-22 18:58:52 -070099
Jeff Browna665ca82010-09-08 11:49:43 -0700100 mInboundQueue.headSentinel.refCount = -1;
101 mInboundQueue.headSentinel.type = EventEntry::TYPE_SENTINEL;
102 mInboundQueue.headSentinel.eventTime = LONG_LONG_MIN;
Jeff Browne839a582010-04-22 18:58:52 -0700103
Jeff Browna665ca82010-09-08 11:49:43 -0700104 mInboundQueue.tailSentinel.refCount = -1;
105 mInboundQueue.tailSentinel.type = EventEntry::TYPE_SENTINEL;
106 mInboundQueue.tailSentinel.eventTime = LONG_LONG_MAX;
Jeff Browne839a582010-04-22 18:58:52 -0700107
108 mKeyRepeatState.lastKeyEntry = NULL;
Jeff Brown54bc2812010-06-15 01:31:58 -0700109
Jeff Brown542412c2010-08-18 15:51:08 -0700110 int32_t maxEventsPerSecond = policy->getMaxEventsPerSecond();
111 mThrottleState.minTimeBetweenEvents = 1000000000LL / maxEventsPerSecond;
112 mThrottleState.lastDeviceId = -1;
113
114#if DEBUG_THROTTLING
115 mThrottleState.originalSampleCount = 0;
116 LOGD("Throttling - Max events per second = %d", maxEventsPerSecond);
117#endif
Jeff Browne839a582010-04-22 18:58:52 -0700118}
119
120InputDispatcher::~InputDispatcher() {
Jeff Browna665ca82010-09-08 11:49:43 -0700121 { // acquire lock
122 AutoMutex _l(mLock);
123
124 resetKeyRepeatLocked();
125 releasePendingEventLocked(true);
126 drainInboundQueueLocked();
127 }
Jeff Browne839a582010-04-22 18:58:52 -0700128
129 while (mConnectionsByReceiveFd.size() != 0) {
130 unregisterInputChannel(mConnectionsByReceiveFd.valueAt(0)->inputChannel);
131 }
Jeff Browne839a582010-04-22 18:58:52 -0700132}
133
134void InputDispatcher::dispatchOnce() {
Jeff Brown54bc2812010-06-15 01:31:58 -0700135 nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
Jeff Brown61ce3982010-09-07 10:44:57 -0700136 nsecs_t keyRepeatDelay = mPolicy->getKeyRepeatDelay();
Jeff Browne839a582010-04-22 18:58:52 -0700137
Jeff Browne839a582010-04-22 18:58:52 -0700138 nsecs_t nextWakeupTime = LONG_LONG_MAX;
139 { // acquire lock
140 AutoMutex _l(mLock);
Jeff Browna665ca82010-09-08 11:49:43 -0700141 dispatchOnceInnerLocked(keyRepeatTimeout, keyRepeatDelay, & nextWakeupTime);
Jeff Browne839a582010-04-22 18:58:52 -0700142
Jeff Browna665ca82010-09-08 11:49:43 -0700143 if (runCommandsLockedInterruptible()) {
144 nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
Jeff Browne839a582010-04-22 18:58:52 -0700145 }
Jeff Browne839a582010-04-22 18:58:52 -0700146 } // release lock
147
Jeff Browna665ca82010-09-08 11:49:43 -0700148 // Wait for callback or timeout or wake. (make sure we round up, not down)
149 nsecs_t currentTime = now();
150 int32_t timeoutMillis;
151 if (nextWakeupTime > currentTime) {
152 uint64_t timeout = uint64_t(nextWakeupTime - currentTime);
153 timeout = (timeout + 999999LL) / 1000000LL;
154 timeoutMillis = timeout > INT_MAX ? -1 : int32_t(timeout);
155 } else {
156 timeoutMillis = 0;
157 }
158
159 mPollLoop->pollOnce(timeoutMillis);
160}
161
162void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
163 nsecs_t keyRepeatDelay, nsecs_t* nextWakeupTime) {
164 nsecs_t currentTime = now();
165
166 // Reset the key repeat timer whenever we disallow key events, even if the next event
167 // is not a key. This is to ensure that we abort a key repeat if the device is just coming
168 // out of sleep.
169 if (keyRepeatTimeout < 0) {
170 resetKeyRepeatLocked();
171 }
172
173 // If dispatching is disabled, drop all events in the queue.
174 if (! mDispatchEnabled) {
175 if (mPendingEvent || ! mInboundQueue.isEmpty()) {
176 LOGI("Dropping pending events because input dispatch is disabled.");
177 releasePendingEventLocked(true);
178 drainInboundQueueLocked();
179 }
Jeff Brown54bc2812010-06-15 01:31:58 -0700180 return;
181 }
182
Jeff Browna665ca82010-09-08 11:49:43 -0700183 // If dispatching is frozen, do not process timeouts or try to deliver any new events.
184 if (mDispatchFrozen) {
185#if DEBUG_FOCUS
186 LOGD("Dispatch frozen. Waiting some more.");
187#endif
188 return;
189 }
190
191 // Optimize latency of app switches.
192 // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
193 // been pressed. When it expires, we preempt dispatch and drop all other pending events.
194 bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
195 if (mAppSwitchDueTime < *nextWakeupTime) {
196 *nextWakeupTime = mAppSwitchDueTime;
197 }
198
199 // Detect and process timeouts for all connections and determine if there are any
200 // synchronous event dispatches pending. This step is entirely non-interruptible.
201 bool havePendingSyncTarget = false;
202 size_t activeConnectionCount = mActiveConnections.size();
203 for (size_t i = 0; i < activeConnectionCount; i++) {
204 Connection* connection = mActiveConnections.itemAt(i);
205
206 if (connection->hasPendingSyncTarget()) {
207 if (isAppSwitchDue) {
208 connection->preemptSyncTarget();
209 } else {
210 havePendingSyncTarget = true;
211 }
212 }
213
214 nsecs_t connectionTimeoutTime = connection->nextTimeoutTime;
215 if (connectionTimeoutTime <= currentTime) {
216 mTimedOutConnections.add(connection);
217 } else if (connectionTimeoutTime < *nextWakeupTime) {
218 *nextWakeupTime = connectionTimeoutTime;
219 }
220 }
221
222 size_t timedOutConnectionCount = mTimedOutConnections.size();
223 for (size_t i = 0; i < timedOutConnectionCount; i++) {
224 Connection* connection = mTimedOutConnections.itemAt(i);
225 timeoutDispatchCycleLocked(currentTime, connection);
226 *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
227 }
228 mTimedOutConnections.clear();
229
230 // If we have a pending synchronous target, skip dispatch.
231 if (havePendingSyncTarget) {
232 return;
233 }
234
235 // Ready to start a new event.
236 // If we don't already have a pending event, go grab one.
237 if (! mPendingEvent) {
238 if (mInboundQueue.isEmpty()) {
239 if (isAppSwitchDue) {
240 // The inbound queue is empty so the app switch key we were waiting
241 // for will never arrive. Stop waiting for it.
242 resetPendingAppSwitchLocked(false);
243 isAppSwitchDue = false;
244 }
245
246 // Synthesize a key repeat if appropriate.
247 if (mKeyRepeatState.lastKeyEntry) {
248 if (currentTime >= mKeyRepeatState.nextRepeatTime) {
249 mPendingEvent = synthesizeKeyRepeatLocked(currentTime, keyRepeatDelay);
250 } else {
251 if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
252 *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
253 }
254 }
255 }
256 if (! mPendingEvent) {
257 return;
258 }
259 } else {
260 // Inbound queue has at least one entry.
261 EventEntry* entry = mInboundQueue.headSentinel.next;
262
263 // Throttle the entry if it is a move event and there are no
264 // other events behind it in the queue. Due to movement batching, additional
265 // samples may be appended to this event by the time the throttling timeout
266 // expires.
267 // TODO Make this smarter and consider throttling per device independently.
268 if (entry->type == EventEntry::TYPE_MOTION) {
269 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
270 int32_t deviceId = motionEntry->deviceId;
271 uint32_t source = motionEntry->source;
272 if (! isAppSwitchDue
273 && motionEntry->next == & mInboundQueue.tailSentinel // exactly one event
274 && motionEntry->action == AMOTION_EVENT_ACTION_MOVE
275 && deviceId == mThrottleState.lastDeviceId
276 && source == mThrottleState.lastSource) {
277 nsecs_t nextTime = mThrottleState.lastEventTime
278 + mThrottleState.minTimeBetweenEvents;
279 if (currentTime < nextTime) {
280 // Throttle it!
281#if DEBUG_THROTTLING
282 LOGD("Throttling - Delaying motion event for "
283 "device 0x%x, source 0x%08x by up to %0.3fms.",
284 deviceId, source, (nextTime - currentTime) * 0.000001);
285#endif
286 if (nextTime < *nextWakeupTime) {
287 *nextWakeupTime = nextTime;
288 }
289 if (mThrottleState.originalSampleCount == 0) {
290 mThrottleState.originalSampleCount =
291 motionEntry->countSamples();
292 }
293 return;
294 }
295 }
296
297#if DEBUG_THROTTLING
298 if (mThrottleState.originalSampleCount != 0) {
299 uint32_t count = motionEntry->countSamples();
300 LOGD("Throttling - Motion event sample count grew by %d from %d to %d.",
301 count - mThrottleState.originalSampleCount,
302 mThrottleState.originalSampleCount, count);
303 mThrottleState.originalSampleCount = 0;
304 }
305#endif
306
307 mThrottleState.lastEventTime = entry->eventTime < currentTime
308 ? entry->eventTime : currentTime;
309 mThrottleState.lastDeviceId = deviceId;
310 mThrottleState.lastSource = source;
311 }
312
313 mInboundQueue.dequeue(entry);
314 mPendingEvent = entry;
315 }
316 }
317
318 // Now we have an event to dispatch.
319 assert(mPendingEvent != NULL);
320 bool wasDispatched = false;
321 bool wasDropped = false;
322 switch (mPendingEvent->type) {
323 case EventEntry::TYPE_CONFIGURATION_CHANGED: {
324 ConfigurationChangedEntry* typedEntry =
325 static_cast<ConfigurationChangedEntry*>(mPendingEvent);
326 wasDispatched = dispatchConfigurationChangedLocked(currentTime, typedEntry);
327 break;
328 }
329
330 case EventEntry::TYPE_KEY: {
331 KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
332 if (isAppSwitchPendingLocked()) {
333 if (isAppSwitchKey(typedEntry->keyCode)) {
334 resetPendingAppSwitchLocked(true);
335 } else if (isAppSwitchDue) {
336 LOGI("Dropping key because of pending overdue app switch.");
337 wasDropped = true;
338 break;
339 }
340 }
341 wasDispatched = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
342 nextWakeupTime);
343 break;
344 }
345
346 case EventEntry::TYPE_MOTION: {
347 MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
348 if (isAppSwitchDue) {
349 LOGI("Dropping motion because of pending overdue app switch.");
350 wasDropped = true;
351 break;
352 }
353 wasDispatched = dispatchMotionLocked(currentTime, typedEntry, nextWakeupTime);
354 break;
355 }
356
357 default:
358 assert(false);
359 wasDropped = true;
360 break;
361 }
362
363 if (wasDispatched || wasDropped) {
364 releasePendingEventLocked(wasDropped);
365 *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
366 }
367}
368
369bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
370 bool needWake = mInboundQueue.isEmpty();
371 mInboundQueue.enqueueAtTail(entry);
372
373 switch (entry->type) {
374 case EventEntry::TYPE_KEY:
375 needWake |= detectPendingAppSwitchLocked(static_cast<KeyEntry*>(entry));
376 break;
377 }
378
379 return needWake;
380}
381
382bool InputDispatcher::isAppSwitchKey(int32_t keyCode) {
383 return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
384}
385
386bool InputDispatcher::isAppSwitchPendingLocked() {
387 return mAppSwitchDueTime != LONG_LONG_MAX;
388}
389
390bool InputDispatcher::detectPendingAppSwitchLocked(KeyEntry* inboundKeyEntry) {
391 if (inboundKeyEntry->action == AKEY_EVENT_ACTION_UP
392 && ! (inboundKeyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
393 && isAppSwitchKey(inboundKeyEntry->keyCode)
394 && isEventFromReliableSourceLocked(inboundKeyEntry)) {
395#if DEBUG_APP_SWITCH
396 LOGD("App switch is pending!");
397#endif
398 mAppSwitchDueTime = inboundKeyEntry->eventTime + APP_SWITCH_TIMEOUT;
399 return true; // need wake
400 }
401 return false;
402}
403
404void InputDispatcher::resetPendingAppSwitchLocked(bool handled) {
405 mAppSwitchDueTime = LONG_LONG_MAX;
406
407#if DEBUG_APP_SWITCH
408 if (handled) {
409 LOGD("App switch has arrived.");
410 } else {
411 LOGD("App switch was abandoned.");
412 }
413#endif
Jeff Browne839a582010-04-22 18:58:52 -0700414}
415
Jeff Brown54bc2812010-06-15 01:31:58 -0700416bool InputDispatcher::runCommandsLockedInterruptible() {
417 if (mCommandQueue.isEmpty()) {
418 return false;
419 }
Jeff Browne839a582010-04-22 18:58:52 -0700420
Jeff Brown54bc2812010-06-15 01:31:58 -0700421 do {
422 CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
423
424 Command command = commandEntry->command;
425 (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
426
Jeff Brown51d45a72010-06-17 20:52:56 -0700427 commandEntry->connection.clear();
Jeff Brown54bc2812010-06-15 01:31:58 -0700428 mAllocator.releaseCommandEntry(commandEntry);
429 } while (! mCommandQueue.isEmpty());
430 return true;
Jeff Browne839a582010-04-22 18:58:52 -0700431}
432
Jeff Brown54bc2812010-06-15 01:31:58 -0700433InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
434 CommandEntry* commandEntry = mAllocator.obtainCommandEntry(command);
435 mCommandQueue.enqueueAtTail(commandEntry);
436 return commandEntry;
437}
438
Jeff Browna665ca82010-09-08 11:49:43 -0700439void InputDispatcher::drainInboundQueueLocked() {
440 while (! mInboundQueue.isEmpty()) {
441 EventEntry* entry = mInboundQueue.dequeueAtHead();
442 releaseInboundEventLocked(entry, true /*wasDropped*/);
Jeff Browne839a582010-04-22 18:58:52 -0700443 }
Jeff Browne839a582010-04-22 18:58:52 -0700444}
445
Jeff Browna665ca82010-09-08 11:49:43 -0700446void InputDispatcher::releasePendingEventLocked(bool wasDropped) {
447 if (mPendingEvent) {
448 releaseInboundEventLocked(mPendingEvent, wasDropped);
449 mPendingEvent = NULL;
450 }
451}
452
453void InputDispatcher::releaseInboundEventLocked(EventEntry* entry, bool wasDropped) {
454 if (wasDropped) {
455#if DEBUG_DISPATCH_CYCLE
456 LOGD("Pending event was dropped.");
457#endif
458 setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
459 }
460 mAllocator.releaseEventEntry(entry);
461}
462
463bool InputDispatcher::isEventFromReliableSourceLocked(EventEntry* entry) {
464 return ! entry->isInjected()
465 || entry->injectorUid == 0
466 || mPolicy->checkInjectEventsPermissionNonReentrant(
467 entry->injectorPid, entry->injectorUid);
468}
469
470void InputDispatcher::resetKeyRepeatLocked() {
471 if (mKeyRepeatState.lastKeyEntry) {
472 mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
473 mKeyRepeatState.lastKeyEntry = NULL;
474 }
475}
476
477InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(
Jeff Brown61ce3982010-09-07 10:44:57 -0700478 nsecs_t currentTime, nsecs_t keyRepeatDelay) {
Jeff Brown50de30a2010-06-22 01:27:15 -0700479 KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
480
Jeff Brown50de30a2010-06-22 01:27:15 -0700481 // Reuse the repeated key entry if it is otherwise unreferenced.
Jeff Brown51d45a72010-06-17 20:52:56 -0700482 uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
Jeff Browne839a582010-04-22 18:58:52 -0700483 if (entry->refCount == 1) {
Jeff Browna665ca82010-09-08 11:49:43 -0700484 entry->recycle();
Jeff Brown51d45a72010-06-17 20:52:56 -0700485 entry->eventTime = currentTime;
Jeff Brown51d45a72010-06-17 20:52:56 -0700486 entry->policyFlags = policyFlags;
Jeff Browne839a582010-04-22 18:58:52 -0700487 entry->repeatCount += 1;
488 } else {
Jeff Brown51d45a72010-06-17 20:52:56 -0700489 KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700490 entry->deviceId, entry->source, policyFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -0700491 entry->action, entry->flags, entry->keyCode, entry->scanCode,
Jeff Brownf16c26d2010-07-02 15:37:36 -0700492 entry->metaState, entry->repeatCount + 1, entry->downTime);
Jeff Browne839a582010-04-22 18:58:52 -0700493
494 mKeyRepeatState.lastKeyEntry = newEntry;
495 mAllocator.releaseKeyEntry(entry);
496
497 entry = newEntry;
498 }
Jeff Browna665ca82010-09-08 11:49:43 -0700499 entry->syntheticRepeat = true;
500
501 // Increment reference count since we keep a reference to the event in
502 // mKeyRepeatState.lastKeyEntry in addition to the one we return.
503 entry->refCount += 1;
Jeff Browne839a582010-04-22 18:58:52 -0700504
Jeff Brownf16c26d2010-07-02 15:37:36 -0700505 if (entry->repeatCount == 1) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700506 entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
Jeff Brownf16c26d2010-07-02 15:37:36 -0700507 }
508
Jeff Brown61ce3982010-09-07 10:44:57 -0700509 mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatDelay;
Jeff Browna665ca82010-09-08 11:49:43 -0700510 return entry;
Jeff Browne839a582010-04-22 18:58:52 -0700511}
512
Jeff Browna665ca82010-09-08 11:49:43 -0700513bool InputDispatcher::dispatchConfigurationChangedLocked(
514 nsecs_t currentTime, ConfigurationChangedEntry* entry) {
Jeff Browne839a582010-04-22 18:58:52 -0700515#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Browna665ca82010-09-08 11:49:43 -0700516 LOGD("dispatchConfigurationChanged - eventTime=%lld", entry->eventTime);
517#endif
518
519 // Reset key repeating in case a keyboard device was added or removed or something.
520 resetKeyRepeatLocked();
521
522 // Enqueue a command to run outside the lock to tell the policy that the configuration changed.
523 CommandEntry* commandEntry = postCommandLocked(
524 & InputDispatcher::doNotifyConfigurationChangedInterruptible);
525 commandEntry->eventTime = entry->eventTime;
526 return true;
527}
528
529bool InputDispatcher::dispatchKeyLocked(
530 nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
531 nsecs_t* nextWakeupTime) {
532 // Preprocessing.
533 if (! entry->dispatchInProgress) {
534 logOutboundKeyDetailsLocked("dispatchKey - ", entry);
535
536 if (entry->repeatCount == 0
537 && entry->action == AKEY_EVENT_ACTION_DOWN
538 && ! entry->isInjected()) {
539 if (mKeyRepeatState.lastKeyEntry
540 && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
541 // We have seen two identical key downs in a row which indicates that the device
542 // driver is automatically generating key repeats itself. We take note of the
543 // repeat here, but we disable our own next key repeat timer since it is clear that
544 // we will not need to synthesize key repeats ourselves.
545 entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
546 resetKeyRepeatLocked();
547 mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
548 } else {
549 // Not a repeat. Save key down state in case we do see a repeat later.
550 resetKeyRepeatLocked();
551 mKeyRepeatState.nextRepeatTime = entry->eventTime + keyRepeatTimeout;
552 }
553 mKeyRepeatState.lastKeyEntry = entry;
554 entry->refCount += 1;
555 } else if (! entry->syntheticRepeat) {
556 resetKeyRepeatLocked();
557 }
558
559 entry->dispatchInProgress = true;
560 startFindingTargetsLocked();
561 }
562
563 // Identify targets.
564 if (! mCurrentInputTargetsValid) {
565 InputWindow* window = NULL;
566 int32_t injectionResult = findFocusedWindowLocked(currentTime,
567 entry, nextWakeupTime, & window);
568 if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
569 return false;
570 }
571
572 setInjectionResultLocked(entry, injectionResult);
573 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
574 return true;
575 }
576
577 addMonitoringTargetsLocked();
578 finishFindingTargetsLocked(window);
579 }
580
581 // Give the policy a chance to intercept the key.
582 if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
583 CommandEntry* commandEntry = postCommandLocked(
584 & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
585 commandEntry->inputChannel = mCurrentInputChannel;
586 commandEntry->keyEntry = entry;
587 entry->refCount += 1;
588 return false; // wait for the command to run
589 }
590 if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
591 return true;
592 }
593
594 // Dispatch the key.
595 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
596
597 // Poke user activity.
598 pokeUserActivityLocked(entry->eventTime, mCurrentInputWindowType, POWER_MANAGER_BUTTON_EVENT);
599 return true;
600}
601
602void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry) {
603#if DEBUG_OUTBOUND_EVENT_DETAILS
604 LOGD("%seventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
605 "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
606 "downTime=%lld",
607 prefix,
608 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
609 entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
610 entry->downTime);
611#endif
612}
613
614bool InputDispatcher::dispatchMotionLocked(
615 nsecs_t currentTime, MotionEntry* entry, nsecs_t* nextWakeupTime) {
616 // Preprocessing.
617 if (! entry->dispatchInProgress) {
618 logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
619
620 entry->dispatchInProgress = true;
621 startFindingTargetsLocked();
622 }
623
624 bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
625
626 // Identify targets.
627 if (! mCurrentInputTargetsValid) {
628 InputWindow* window = NULL;
629 int32_t injectionResult;
630 if (isPointerEvent) {
631 // Pointer event. (eg. touchscreen)
632 injectionResult = findTouchedWindowLocked(currentTime,
633 entry, nextWakeupTime, & window);
634 } else {
635 // Non touch event. (eg. trackball)
636 injectionResult = findFocusedWindowLocked(currentTime,
637 entry, nextWakeupTime, & window);
638 }
639 if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
640 return false;
641 }
642
643 setInjectionResultLocked(entry, injectionResult);
644 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
645 return true;
646 }
647
648 addMonitoringTargetsLocked();
649 finishFindingTargetsLocked(window);
650 }
651
652 // Dispatch the motion.
653 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
654
655 // Poke user activity.
656 int32_t eventType;
657 if (isPointerEvent) {
658 switch (entry->action) {
659 case AMOTION_EVENT_ACTION_DOWN:
660 eventType = POWER_MANAGER_TOUCH_EVENT;
661 break;
662 case AMOTION_EVENT_ACTION_UP:
663 eventType = POWER_MANAGER_TOUCH_UP_EVENT;
664 break;
665 default:
666 if (entry->eventTime - entry->downTime >= EVENT_IGNORE_DURATION) {
667 eventType = POWER_MANAGER_TOUCH_EVENT;
668 } else {
669 eventType = POWER_MANAGER_LONG_TOUCH_EVENT;
670 }
671 break;
672 }
673 } else {
674 eventType = POWER_MANAGER_BUTTON_EVENT;
675 }
676 pokeUserActivityLocked(entry->eventTime, mCurrentInputWindowType, eventType);
677 return true;
678}
679
680
681void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) {
682#if DEBUG_OUTBOUND_EVENT_DETAILS
683 LOGD("%seventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Brownaf30ff62010-09-01 17:01:00 -0700684 "action=0x%x, flags=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -0700685 "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
Jeff Browna665ca82010-09-08 11:49:43 -0700686 prefix,
Jeff Brownaf30ff62010-09-01 17:01:00 -0700687 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
688 entry->action, entry->flags,
Jeff Browne839a582010-04-22 18:58:52 -0700689 entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
690 entry->downTime);
691
692 // Print the most recent sample that we have available, this may change due to batching.
693 size_t sampleCount = 1;
Jeff Browna665ca82010-09-08 11:49:43 -0700694 const MotionSample* sample = & entry->firstSample;
Jeff Browne839a582010-04-22 18:58:52 -0700695 for (; sample->next != NULL; sample = sample->next) {
696 sampleCount += 1;
697 }
698 for (uint32_t i = 0; i < entry->pointerCount; i++) {
Jeff Brown38a7fab2010-08-30 03:02:23 -0700699 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
Jeff Brownaf30ff62010-09-01 17:01:00 -0700700 "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
Jeff Brown38a7fab2010-08-30 03:02:23 -0700701 "orientation=%f",
Jeff Browne839a582010-04-22 18:58:52 -0700702 i, entry->pointerIds[i],
Jeff Brown38a7fab2010-08-30 03:02:23 -0700703 sample->pointerCoords[i].x, sample->pointerCoords[i].y,
704 sample->pointerCoords[i].pressure, sample->pointerCoords[i].size,
705 sample->pointerCoords[i].touchMajor, sample->pointerCoords[i].touchMinor,
706 sample->pointerCoords[i].toolMajor, sample->pointerCoords[i].toolMinor,
707 sample->pointerCoords[i].orientation);
Jeff Browne839a582010-04-22 18:58:52 -0700708 }
709
710 // Keep in mind that due to batching, it is possible for the number of samples actually
711 // dispatched to change before the application finally consumed them.
Jeff Brown5c1ed842010-07-14 18:48:53 -0700712 if (entry->action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Browne839a582010-04-22 18:58:52 -0700713 LOGD(" ... Total movement samples currently batched %d ...", sampleCount);
714 }
715#endif
Jeff Browne839a582010-04-22 18:58:52 -0700716}
717
718void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
719 EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
720#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -0700721 LOGD("dispatchEventToCurrentInputTargets - "
Jeff Browne839a582010-04-22 18:58:52 -0700722 "resumeWithAppendedMotionSample=%s",
Jeff Browna665ca82010-09-08 11:49:43 -0700723 toString(resumeWithAppendedMotionSample));
Jeff Browne839a582010-04-22 18:58:52 -0700724#endif
725
Jeff Brown54bc2812010-06-15 01:31:58 -0700726 assert(eventEntry->dispatchInProgress); // should already have been set to true
727
Jeff Browne839a582010-04-22 18:58:52 -0700728 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
729 const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
730
Jeff Brown0cacb872010-08-17 15:59:26 -0700731 ssize_t connectionIndex = getConnectionIndex(inputTarget.inputChannel);
Jeff Browne839a582010-04-22 18:58:52 -0700732 if (connectionIndex >= 0) {
733 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown51d45a72010-06-17 20:52:56 -0700734 prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
Jeff Browne839a582010-04-22 18:58:52 -0700735 resumeWithAppendedMotionSample);
736 } else {
737 LOGW("Framework requested delivery of an input event to channel '%s' but it "
738 "is not registered with the input dispatcher.",
739 inputTarget.inputChannel->getName().string());
740 }
741 }
742}
743
Jeff Browna665ca82010-09-08 11:49:43 -0700744void InputDispatcher::startFindingTargetsLocked() {
745 mCurrentInputTargetsValid = false;
746 mCurrentInputTargets.clear();
747 mCurrentInputChannel.clear();
748 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
749}
750
751void InputDispatcher::finishFindingTargetsLocked(const InputWindow* window) {
752 mCurrentInputWindowType = window->layoutParamsType;
753 mCurrentInputChannel = window->inputChannel;
754 mCurrentInputTargetsValid = true;
755}
756
757int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
758 const EventEntry* entry, const InputApplication* application, const InputWindow* window,
759 nsecs_t* nextWakeupTime) {
760 if (application == NULL && window == NULL) {
761 if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
762#if DEBUG_FOCUS
763 LOGD("Waiting for system to become ready for input.");
764#endif
765 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
766 mInputTargetWaitStartTime = currentTime;
767 mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
768 mInputTargetWaitTimeoutExpired = false;
769 }
770 } else {
771 if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
772#if DEBUG_FOCUS
773 LOGD("Waiting for application to become ready for input: name=%s, window=%s",
774 application ? application->name.string() : "<unknown>",
775 window ? window->inputChannel->getName().string() : "<unknown>");
776#endif
777 nsecs_t timeout = window ? window->dispatchingTimeout :
778 application ? application->dispatchingTimeout : DEFAULT_INPUT_DISPATCHING_TIMEOUT;
779
780 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
781 mInputTargetWaitStartTime = currentTime;
782 mInputTargetWaitTimeoutTime = currentTime + timeout;
783 mInputTargetWaitTimeoutExpired = false;
784 }
785 }
786
787 if (mInputTargetWaitTimeoutExpired) {
788 return INPUT_EVENT_INJECTION_TIMED_OUT;
789 }
790
791 if (currentTime >= mInputTargetWaitTimeoutTime) {
792 LOGI("Application is not ready for input: name=%s, window=%s,"
793 "%01.1fms since event, %01.1fms since wait started",
794 application ? application->name.string() : "<unknown>",
795 window ? window->inputChannel->getName().string() : "<unknown>",
796 (currentTime - entry->eventTime) / 1000000.0,
797 (currentTime - mInputTargetWaitStartTime) / 1000000.0);
798
799 CommandEntry* commandEntry = postCommandLocked(
800 & InputDispatcher::doTargetsNotReadyTimeoutLockedInterruptible);
801 if (application) {
802 commandEntry->inputApplicationHandle = application->handle;
803 }
804 if (window) {
805 commandEntry->inputChannel = window->inputChannel;
806 }
807
808 // Force poll loop to wake up immediately on next iteration once we get the
809 // ANR response back from the policy.
810 *nextWakeupTime = LONG_LONG_MIN;
811 return INPUT_EVENT_INJECTION_PENDING;
812 } else {
813 // Force poll loop to wake up when timeout is due.
814 if (mInputTargetWaitTimeoutTime < *nextWakeupTime) {
815 *nextWakeupTime = mInputTargetWaitTimeoutTime;
816 }
817 return INPUT_EVENT_INJECTION_PENDING;
818 }
819}
820
821void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout) {
822 if (newTimeout > 0) {
823 // Extend the timeout.
824 mInputTargetWaitTimeoutTime = now() + newTimeout;
825 } else {
826 // Give up.
827 mInputTargetWaitTimeoutExpired = true;
828 }
829}
830
831nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationWhileFindingTargetsLocked(
832 nsecs_t currentTime) {
833 if (mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
834 return currentTime - mInputTargetWaitStartTime;
835 }
836 return 0;
837}
838
839void InputDispatcher::resetANRTimeoutsLocked() {
840#if DEBUG_FOCUS
841 LOGD("Resetting ANR timeouts.");
842#endif
843
844 // Reset timeouts for all active connections.
845 nsecs_t currentTime = now();
846 for (size_t i = 0; i < mActiveConnections.size(); i++) {
847 Connection* connection = mActiveConnections[i];
848 connection->resetTimeout(currentTime);
849 }
850
851 // Reset input target wait timeout.
852 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
853}
854
855int32_t InputDispatcher::findFocusedWindowLocked(nsecs_t currentTime, const EventEntry* entry,
856 nsecs_t* nextWakeupTime, InputWindow** outWindow) {
857 *outWindow = NULL;
858 mCurrentInputTargets.clear();
859
860 int32_t injectionResult;
861
862 // If there is no currently focused window and no focused application
863 // then drop the event.
864 if (! mFocusedWindow) {
865 if (mFocusedApplication) {
866#if DEBUG_FOCUS
867 LOGD("Waiting because there is no focused window but there is a "
868 "focused application that may eventually add a window: '%s'.",
869 mFocusedApplication->name.string());
870#endif
871 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
872 mFocusedApplication, NULL, nextWakeupTime);
873 goto Unresponsive;
874 }
875
876 LOGI("Dropping event because there is no focused window or focused application.");
877 injectionResult = INPUT_EVENT_INJECTION_FAILED;
878 goto Failed;
879 }
880
881 // Check permissions.
882 if (! checkInjectionPermission(mFocusedWindow, entry->injectorPid, entry->injectorUid)) {
883 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
884 goto Failed;
885 }
886
887 // If the currently focused window is paused then keep waiting.
888 if (mFocusedWindow->paused) {
889#if DEBUG_FOCUS
890 LOGD("Waiting because focused window is paused.");
891#endif
892 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
893 mFocusedApplication, mFocusedWindow, nextWakeupTime);
894 goto Unresponsive;
895 }
896
897 // Success! Output targets.
898 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
899 *outWindow = mFocusedWindow;
900 addWindowTargetLocked(mFocusedWindow, InputTarget::FLAG_SYNC,
901 getTimeSpentWaitingForApplicationWhileFindingTargetsLocked(currentTime));
902
903 // Done.
904Failed:
905Unresponsive:
906#if DEBUG_FOCUS
907 LOGD("findFocusedWindow finished: injectionResult=%d",
908 injectionResult);
909 logDispatchStateLocked();
910#endif
911 return injectionResult;
912}
913
914int32_t InputDispatcher::findTouchedWindowLocked(nsecs_t currentTime, const MotionEntry* entry,
915 nsecs_t* nextWakeupTime, InputWindow** outWindow) {
916 enum InjectionPermission {
917 INJECTION_PERMISSION_UNKNOWN,
918 INJECTION_PERMISSION_GRANTED,
919 INJECTION_PERMISSION_DENIED
920 };
921
922 *outWindow = NULL;
923 mCurrentInputTargets.clear();
924
925 nsecs_t startTime = now();
926
927 // For security reasons, we defer updating the touch state until we are sure that
928 // event injection will be allowed.
929 //
930 // FIXME In the original code, screenWasOff could never be set to true.
931 // The reason is that the POLICY_FLAG_WOKE_HERE
932 // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
933 // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
934 // actually enqueued using the policyFlags that appeared in the final EV_SYN
935 // events upon which no preprocessing took place. So policyFlags was always 0.
936 // In the new native input dispatcher we're a bit more careful about event
937 // preprocessing so the touches we receive can actually have non-zero policyFlags.
938 // Unfortunately we obtain undesirable behavior.
939 //
940 // Here's what happens:
941 //
942 // When the device dims in anticipation of going to sleep, touches
943 // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
944 // the device to brighten and reset the user activity timer.
945 // Touches on other windows (such as the launcher window)
946 // are dropped. Then after a moment, the device goes to sleep. Oops.
947 //
948 // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
949 // instead of POLICY_FLAG_WOKE_HERE...
950 //
951 bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
952
953 int32_t action = entry->action;
954
955 // Update the touch state as needed based on the properties of the touch event.
956 int32_t injectionResult;
957 InjectionPermission injectionPermission;
958 if (action == AMOTION_EVENT_ACTION_DOWN) {
959 /* Case 1: ACTION_DOWN */
960
961 InputWindow* newTouchedWindow = NULL;
962 mTempTouchedOutsideTargets.clear();
963
964 int32_t x = int32_t(entry->firstSample.pointerCoords[0].x);
965 int32_t y = int32_t(entry->firstSample.pointerCoords[0].y);
966 InputWindow* topErrorWindow = NULL;
967 bool obscured = false;
968
969 // Traverse windows from front to back to find touched window and outside targets.
970 size_t numWindows = mWindows.size();
971 for (size_t i = 0; i < numWindows; i++) {
972 InputWindow* window = & mWindows.editItemAt(i);
973 int32_t flags = window->layoutParamsFlags;
974
975 if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
976 if (! topErrorWindow) {
977 topErrorWindow = window;
978 }
979 }
980
981 if (window->visible) {
982 if (! (flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
983 bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
984 | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
985 if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
986 if (! screenWasOff || flags & InputWindow::FLAG_TOUCHABLE_WHEN_WAKING) {
987 newTouchedWindow = window;
988 obscured = isWindowObscuredLocked(window);
989 }
990 break; // found touched window, exit window loop
991 }
992 }
993
994 if (flags & InputWindow::FLAG_WATCH_OUTSIDE_TOUCH) {
995 OutsideTarget outsideTarget;
996 outsideTarget.window = window;
997 outsideTarget.obscured = isWindowObscuredLocked(window);
998 mTempTouchedOutsideTargets.push(outsideTarget);
999 }
1000 }
1001 }
1002
1003 // If there is an error window but it is not taking focus (typically because
1004 // it is invisible) then wait for it. Any other focused window may in
1005 // fact be in ANR state.
1006 if (topErrorWindow && newTouchedWindow != topErrorWindow) {
1007#if DEBUG_FOCUS
1008 LOGD("Waiting because system error window is pending.");
1009#endif
1010 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1011 NULL, NULL, nextWakeupTime);
1012 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
1013 goto Unresponsive;
1014 }
1015
1016 // If we did not find a touched window then fail.
1017 if (! newTouchedWindow) {
1018 if (mFocusedApplication) {
1019#if DEBUG_FOCUS
1020 LOGD("Waiting because there is no touched window but there is a "
1021 "focused application that may eventually add a new window: '%s'.",
1022 mFocusedApplication->name.string());
1023#endif
1024 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1025 mFocusedApplication, NULL, nextWakeupTime);
1026 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
1027 goto Unresponsive;
1028 }
1029
1030 LOGI("Dropping event because there is no touched window or focused application.");
1031 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1032 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
1033 goto Failed;
1034 }
1035
1036 // Check permissions.
1037 if (! checkInjectionPermission(newTouchedWindow, entry->injectorPid, entry->injectorUid)) {
1038 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1039 injectionPermission = INJECTION_PERMISSION_DENIED;
1040 goto Failed;
1041 }
1042
1043 // If the touched window is paused then keep waiting.
1044 if (newTouchedWindow->paused) {
1045#if DEBUG_INPUT_DISPATCHER_POLICY
1046 LOGD("Waiting because touched window is paused.");
1047#endif
1048 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1049 NULL, newTouchedWindow, nextWakeupTime);
1050 injectionPermission = INJECTION_PERMISSION_GRANTED;
1051 goto Unresponsive;
1052 }
1053
1054 // Success! Update the touch dispatch state for real.
1055 releaseTouchedWindowLocked();
1056
1057 mTouchedWindow = newTouchedWindow;
1058 mTouchedWindowIsObscured = obscured;
1059
1060 if (newTouchedWindow->hasWallpaper) {
1061 mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
1062 }
1063 } else {
1064 /* Case 2: Everything but ACTION_DOWN */
1065
1066 // Check permissions.
1067 if (! checkInjectionPermission(mTouchedWindow, entry->injectorPid, entry->injectorUid)) {
1068 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1069 injectionPermission = INJECTION_PERMISSION_DENIED;
1070 goto Failed;
1071 }
1072
1073 // If the pointer is not currently down, then ignore the event.
1074 if (! mTouchDown) {
1075 LOGI("Dropping event because the pointer is not down.");
1076 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1077 injectionPermission = INJECTION_PERMISSION_GRANTED;
1078 goto Failed;
1079 }
1080
1081 // If there is no currently touched window then fail.
1082 if (! mTouchedWindow) {
1083#if DEBUG_INPUT_DISPATCHER_POLICY
1084 LOGD("Dropping event because there is no touched window to receive it.");
1085#endif
1086 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1087 injectionPermission = INJECTION_PERMISSION_GRANTED;
1088 goto Failed;
1089 }
1090
1091 // If the touched window is paused then keep waiting.
1092 if (mTouchedWindow->paused) {
1093#if DEBUG_INPUT_DISPATCHER_POLICY
1094 LOGD("Waiting because touched window is paused.");
1095#endif
1096 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1097 NULL, mTouchedWindow, nextWakeupTime);
1098 injectionPermission = INJECTION_PERMISSION_GRANTED;
1099 goto Unresponsive;
1100 }
1101 }
1102
1103 // Success! Output targets.
1104 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1105 injectionPermission = INJECTION_PERMISSION_GRANTED;
1106
1107 {
1108 size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
1109 for (size_t i = 0; i < numWallpaperWindows; i++) {
1110 addWindowTargetLocked(mTouchedWallpaperWindows[i],
1111 InputTarget::FLAG_WINDOW_IS_OBSCURED, 0);
1112 }
1113
1114 size_t numOutsideTargets = mTempTouchedOutsideTargets.size();
1115 for (size_t i = 0; i < numOutsideTargets; i++) {
1116 const OutsideTarget& outsideTarget = mTempTouchedOutsideTargets[i];
1117 int32_t outsideTargetFlags = InputTarget::FLAG_OUTSIDE;
1118 if (outsideTarget.obscured) {
1119 outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
1120 }
1121 addWindowTargetLocked(outsideTarget.window, outsideTargetFlags, 0);
1122 }
1123 mTempTouchedOutsideTargets.clear();
1124
1125 int32_t targetFlags = InputTarget::FLAG_SYNC;
1126 if (mTouchedWindowIsObscured) {
1127 targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
1128 }
1129 addWindowTargetLocked(mTouchedWindow, targetFlags,
1130 getTimeSpentWaitingForApplicationWhileFindingTargetsLocked(currentTime));
1131 *outWindow = mTouchedWindow;
1132 }
1133
1134Failed:
1135 // Check injection permission once and for all.
1136 if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
1137 if (checkInjectionPermission(action == AMOTION_EVENT_ACTION_DOWN ? NULL : mTouchedWindow,
1138 entry->injectorPid, entry->injectorUid)) {
1139 injectionPermission = INJECTION_PERMISSION_GRANTED;
1140 } else {
1141 injectionPermission = INJECTION_PERMISSION_DENIED;
1142 }
1143 }
1144
1145 // Update final pieces of touch state if the injector had permission.
1146 if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
1147 if (action == AMOTION_EVENT_ACTION_DOWN) {
1148 if (mTouchDown) {
1149 // This is weird. We got a down but we thought it was already down!
1150 LOGW("Pointer down received while already down.");
1151 } else {
1152 mTouchDown = true;
1153 }
1154
1155 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1156 // Since we failed to identify a target for this touch down, we may still
1157 // be holding on to an earlier target from a previous touch down. Release it.
1158 releaseTouchedWindowLocked();
1159 }
1160 } else if (action == AMOTION_EVENT_ACTION_UP) {
1161 mTouchDown = false;
1162 releaseTouchedWindowLocked();
1163 }
1164 } else {
1165 LOGW("Not updating touch focus because injection was denied.");
1166 }
1167
1168Unresponsive:
1169#if DEBUG_FOCUS
1170 LOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d",
1171 injectionResult, injectionPermission);
1172 logDispatchStateLocked();
1173#endif
1174 return injectionResult;
1175}
1176
1177void InputDispatcher::releaseTouchedWindowLocked() {
1178 mTouchedWindow = NULL;
1179 mTouchedWindowIsObscured = false;
1180 mTouchedWallpaperWindows.clear();
1181}
1182
1183void InputDispatcher::addWindowTargetLocked(const InputWindow* window, int32_t targetFlags,
1184 nsecs_t timeSpentWaitingForApplication) {
1185 mCurrentInputTargets.push();
1186
1187 InputTarget& target = mCurrentInputTargets.editTop();
1188 target.inputChannel = window->inputChannel;
1189 target.flags = targetFlags;
1190 target.timeout = window->dispatchingTimeout;
1191 target.timeSpentWaitingForApplication = timeSpentWaitingForApplication;
1192 target.xOffset = - window->frameLeft;
1193 target.yOffset = - window->frameTop;
1194}
1195
1196void InputDispatcher::addMonitoringTargetsLocked() {
1197 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
1198 mCurrentInputTargets.push();
1199
1200 InputTarget& target = mCurrentInputTargets.editTop();
1201 target.inputChannel = mMonitoringChannels[i];
1202 target.flags = 0;
1203 target.timeout = -1;
1204 target.timeSpentWaitingForApplication = 0;
1205 target.xOffset = 0;
1206 target.yOffset = 0;
1207 }
1208}
1209
1210bool InputDispatcher::checkInjectionPermission(const InputWindow* window,
1211 int32_t injectorPid, int32_t injectorUid) {
1212 if (injectorUid > 0 && (window == NULL || window->ownerUid != injectorUid)) {
1213 bool result = mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
1214 if (! result) {
1215 if (window) {
1216 LOGW("Permission denied: injecting event from pid %d uid %d to window "
1217 "with input channel %s owned by uid %d",
1218 injectorPid, injectorUid, window->inputChannel->getName().string(),
1219 window->ownerUid);
1220 } else {
1221 LOGW("Permission denied: injecting event from pid %d uid %d",
1222 injectorPid, injectorUid);
1223 }
1224 return false;
1225 }
1226 }
1227 return true;
1228}
1229
1230bool InputDispatcher::isWindowObscuredLocked(const InputWindow* window) {
1231 size_t numWindows = mWindows.size();
1232 for (size_t i = 0; i < numWindows; i++) {
1233 const InputWindow* other = & mWindows.itemAt(i);
1234 if (other == window) {
1235 break;
1236 }
1237 if (other->visible && window->visibleFrameIntersects(other)) {
1238 return true;
1239 }
1240 }
1241 return false;
1242}
1243
1244void InputDispatcher::pokeUserActivityLocked(nsecs_t eventTime,
1245 int32_t windowType, int32_t eventType) {
1246 CommandEntry* commandEntry = postCommandLocked(
1247 & InputDispatcher::doPokeUserActivityLockedInterruptible);
1248 commandEntry->eventTime = eventTime;
1249 commandEntry->windowType = windowType;
1250 commandEntry->userActivityEventType = eventType;
1251}
1252
Jeff Brown51d45a72010-06-17 20:52:56 -07001253void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
1254 const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
Jeff Browne839a582010-04-22 18:58:52 -07001255 bool resumeWithAppendedMotionSample) {
1256#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -07001257 LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, timeout=%lldns, "
Jeff Browne839a582010-04-22 18:58:52 -07001258 "xOffset=%f, yOffset=%f, resumeWithAppendedMotionSample=%s",
1259 connection->getInputChannelName(), inputTarget->flags, inputTarget->timeout,
1260 inputTarget->xOffset, inputTarget->yOffset,
Jeff Browna665ca82010-09-08 11:49:43 -07001261 toString(resumeWithAppendedMotionSample));
Jeff Browne839a582010-04-22 18:58:52 -07001262#endif
1263
1264 // Skip this event if the connection status is not normal.
Jeff Browna665ca82010-09-08 11:49:43 -07001265 // We don't want to enqueue additional outbound events if the connection is broken or
Jeff Browne839a582010-04-22 18:58:52 -07001266 // not responding.
1267 if (connection->status != Connection::STATUS_NORMAL) {
Jeff Browna665ca82010-09-08 11:49:43 -07001268 LOGW("channel '%s' ~ Dropping event because the channel status is %s",
1269 connection->getInputChannelName(), connection->getStatusLabel());
1270
1271 // If the connection is not responding but the user is poking the application anyways,
1272 // retrigger the original timeout.
1273 if (connection->status == Connection::STATUS_NOT_RESPONDING) {
1274 timeoutDispatchCycleLocked(currentTime, connection);
1275 }
Jeff Browne839a582010-04-22 18:58:52 -07001276 return;
1277 }
1278
1279 // Resume the dispatch cycle with a freshly appended motion sample.
1280 // First we check that the last dispatch entry in the outbound queue is for the same
1281 // motion event to which we appended the motion sample. If we find such a dispatch
1282 // entry, and if it is currently in progress then we try to stream the new sample.
1283 bool wasEmpty = connection->outboundQueue.isEmpty();
1284
1285 if (! wasEmpty && resumeWithAppendedMotionSample) {
1286 DispatchEntry* motionEventDispatchEntry =
1287 connection->findQueuedDispatchEntryForEvent(eventEntry);
1288 if (motionEventDispatchEntry) {
1289 // If the dispatch entry is not in progress, then we must be busy dispatching an
1290 // earlier event. Not a problem, the motion event is on the outbound queue and will
1291 // be dispatched later.
1292 if (! motionEventDispatchEntry->inProgress) {
1293#if DEBUG_BATCHING
1294 LOGD("channel '%s' ~ Not streaming because the motion event has "
1295 "not yet been dispatched. "
1296 "(Waiting for earlier events to be consumed.)",
1297 connection->getInputChannelName());
1298#endif
1299 return;
1300 }
1301
1302 // If the dispatch entry is in progress but it already has a tail of pending
1303 // motion samples, then it must mean that the shared memory buffer filled up.
1304 // Not a problem, when this dispatch cycle is finished, we will eventually start
1305 // a new dispatch cycle to process the tail and that tail includes the newly
1306 // appended motion sample.
1307 if (motionEventDispatchEntry->tailMotionSample) {
1308#if DEBUG_BATCHING
1309 LOGD("channel '%s' ~ Not streaming because no new samples can "
1310 "be appended to the motion event in this dispatch cycle. "
1311 "(Waiting for next dispatch cycle to start.)",
1312 connection->getInputChannelName());
1313#endif
1314 return;
1315 }
1316
1317 // The dispatch entry is in progress and is still potentially open for streaming.
1318 // Try to stream the new motion sample. This might fail if the consumer has already
1319 // consumed the motion event (or if the channel is broken).
1320 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
1321 status_t status = connection->inputPublisher.appendMotionSample(
1322 appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
1323 if (status == OK) {
1324#if DEBUG_BATCHING
1325 LOGD("channel '%s' ~ Successfully streamed new motion sample.",
1326 connection->getInputChannelName());
1327#endif
1328 return;
1329 }
1330
1331#if DEBUG_BATCHING
1332 if (status == NO_MEMORY) {
1333 LOGD("channel '%s' ~ Could not append motion sample to currently "
1334 "dispatched move event because the shared memory buffer is full. "
1335 "(Waiting for next dispatch cycle to start.)",
1336 connection->getInputChannelName());
1337 } else if (status == status_t(FAILED_TRANSACTION)) {
1338 LOGD("channel '%s' ~ Could not append motion sample to currently "
Jeff Brown50de30a2010-06-22 01:27:15 -07001339 "dispatched move event because the event has already been consumed. "
Jeff Browne839a582010-04-22 18:58:52 -07001340 "(Waiting for next dispatch cycle to start.)",
1341 connection->getInputChannelName());
1342 } else {
1343 LOGD("channel '%s' ~ Could not append motion sample to currently "
1344 "dispatched move event due to an error, status=%d. "
1345 "(Waiting for next dispatch cycle to start.)",
1346 connection->getInputChannelName(), status);
1347 }
1348#endif
1349 // Failed to stream. Start a new tail of pending motion samples to dispatch
1350 // in the next cycle.
1351 motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
1352 return;
1353 }
1354 }
1355
Jeff Browna665ca82010-09-08 11:49:43 -07001356 // Bring the input state back in line with reality in case it drifted off during an ANR.
1357 if (connection->inputState.isOutOfSync()) {
1358 mTempCancelationEvents.clear();
1359 connection->inputState.synthesizeCancelationEvents(& mAllocator, mTempCancelationEvents);
1360 connection->inputState.resetOutOfSync();
1361
1362 if (! mTempCancelationEvents.isEmpty()) {
1363 LOGI("channel '%s' ~ Generated %d cancelation events to bring channel back in sync "
1364 "with reality.",
1365 connection->getInputChannelName(), mTempCancelationEvents.size());
1366
1367 for (size_t i = 0; i < mTempCancelationEvents.size(); i++) {
1368 EventEntry* cancelationEventEntry = mTempCancelationEvents.itemAt(i);
1369 switch (cancelationEventEntry->type) {
1370 case EventEntry::TYPE_KEY:
1371 logOutboundKeyDetailsLocked(" ",
1372 static_cast<KeyEntry*>(cancelationEventEntry));
1373 break;
1374 case EventEntry::TYPE_MOTION:
1375 logOutboundMotionDetailsLocked(" ",
1376 static_cast<MotionEntry*>(cancelationEventEntry));
1377 break;
1378 }
1379
1380 DispatchEntry* cancelationDispatchEntry =
1381 mAllocator.obtainDispatchEntry(cancelationEventEntry,
1382 0, inputTarget->xOffset, inputTarget->yOffset, inputTarget->timeout);
1383 connection->outboundQueue.enqueueAtTail(cancelationDispatchEntry);
1384
1385 mAllocator.releaseEventEntry(cancelationEventEntry);
1386 }
1387 }
1388 }
1389
Jeff Browne839a582010-04-22 18:58:52 -07001390 // This is a new event.
1391 // Enqueue a new dispatch entry onto the outbound queue for this connection.
Jeff Browna665ca82010-09-08 11:49:43 -07001392 DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry, // increments ref
1393 inputTarget->flags, inputTarget->xOffset, inputTarget->yOffset,
1394 inputTarget->timeout);
Jeff Brownf67c53e2010-07-28 15:48:59 -07001395 if (dispatchEntry->isSyncTarget()) {
1396 eventEntry->pendingSyncDispatches += 1;
1397 }
1398
Jeff Browne839a582010-04-22 18:58:52 -07001399 // Handle the case where we could not stream a new motion sample because the consumer has
1400 // already consumed the motion event (otherwise the corresponding dispatch entry would
1401 // still be in the outbound queue for this connection). We set the head motion sample
1402 // to the list starting with the newly appended motion sample.
1403 if (resumeWithAppendedMotionSample) {
1404#if DEBUG_BATCHING
1405 LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
1406 "that cannot be streamed because the motion event has already been consumed.",
1407 connection->getInputChannelName());
1408#endif
1409 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
1410 dispatchEntry->headMotionSample = appendedMotionSample;
1411 }
1412
1413 // Enqueue the dispatch entry.
1414 connection->outboundQueue.enqueueAtTail(dispatchEntry);
1415
1416 // If the outbound queue was previously empty, start the dispatch cycle going.
1417 if (wasEmpty) {
Jeff Brown51d45a72010-06-17 20:52:56 -07001418 activateConnectionLocked(connection.get());
Jeff Browna665ca82010-09-08 11:49:43 -07001419 startDispatchCycleLocked(currentTime, connection,
1420 inputTarget->timeSpentWaitingForApplication);
Jeff Browne839a582010-04-22 18:58:52 -07001421 }
1422}
1423
Jeff Brown51d45a72010-06-17 20:52:56 -07001424void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
Jeff Browna665ca82010-09-08 11:49:43 -07001425 const sp<Connection>& connection, nsecs_t timeSpentWaitingForApplication) {
Jeff Browne839a582010-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 Browna665ca82010-09-08 11:49:43 -07001434 DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
Jeff Browne839a582010-04-22 18:58:52 -07001435 assert(! dispatchEntry->inProgress);
1436
Jeff Browna665ca82010-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 Browne839a582010-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 Brown5c1ed842010-07-14 18:48:53 -07001476 flags |= AKEY_EVENT_FLAG_CANCELED;
Jeff Browne839a582010-04-22 18:58:52 -07001477 }
1478
1479 // Publish the key event.
Jeff Brown5c1ed842010-07-14 18:48:53 -07001480 status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
Jeff Browne839a582010-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 Brownaf30ff62010-09-01 17:01:00 -07001499 int32_t flags = motionEntry->flags;
Jeff Browne839a582010-04-22 18:58:52 -07001500 if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07001501 action = AMOTION_EVENT_ACTION_OUTSIDE;
Jeff Browne839a582010-04-22 18:58:52 -07001502 }
1503 if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07001504 action = AMOTION_EVENT_ACTION_CANCEL;
Jeff Browne839a582010-04-22 18:58:52 -07001505 }
Jeff Brownaf30ff62010-09-01 17:01:00 -07001506 if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
1507 flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
1508 }
Jeff Browne839a582010-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 Brownf26db0d2010-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 Browne839a582010-04-22 18:58:52 -07001529 // Publish the motion event and the first motion sample.
1530 status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001531 motionEntry->source, action, flags, motionEntry->edgeFlags, motionEntry->metaState,
Jeff Brownf26db0d2010-07-16 17:21:06 -07001532 xOffset, yOffset,
Jeff Browne839a582010-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 Browne839a582010-04-22 18:58:52 -07001588 connection->lastEventTime = dispatchEntry->eventEntry->eventTime;
1589 connection->lastDispatchTime = currentTime;
1590
Jeff Browna665ca82010-09-08 11:49:43 -07001591 nsecs_t timeout = dispatchEntry->timeout - timeSpentWaitingForApplication;
Jeff Brown51d45a72010-06-17 20:52:56 -07001592 connection->setNextTimeoutTime(currentTime, timeout);
Jeff Browne839a582010-04-22 18:58:52 -07001593
1594 // Notify other system components.
1595 onDispatchCycleStartedLocked(currentTime, connection);
1596}
1597
Jeff Brown51d45a72010-06-17 20:52:56 -07001598void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
1599 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001600#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -07001601 LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
Jeff Browne839a582010-04-22 18:58:52 -07001602 "%01.1fms since dispatch",
1603 connection->getInputChannelName(),
1604 connection->getEventLatencyMillis(currentTime),
1605 connection->getDispatchLatencyMillis(currentTime));
1606#endif
1607
Jeff Brown54bc2812010-06-15 01:31:58 -07001608 if (connection->status == Connection::STATUS_BROKEN
1609 || connection->status == Connection::STATUS_ZOMBIE) {
Jeff Browne839a582010-04-22 18:58:52 -07001610 return;
1611 }
1612
1613 // Clear the pending timeout.
1614 connection->nextTimeoutTime = LONG_LONG_MAX;
1615
1616 if (connection->status == Connection::STATUS_NOT_RESPONDING) {
1617 // Recovering from an ANR.
1618 connection->status = Connection::STATUS_NORMAL;
1619
1620 // Notify other system components.
1621 onDispatchCycleFinishedLocked(currentTime, connection, true /*recoveredFromANR*/);
1622 } else {
1623 // Normal finish. Not much to do here.
1624
1625 // Notify other system components.
1626 onDispatchCycleFinishedLocked(currentTime, connection, false /*recoveredFromANR*/);
1627 }
1628
1629 // Reset the publisher since the event has been consumed.
1630 // We do this now so that the publisher can release some of its internal resources
1631 // while waiting for the next dispatch cycle to begin.
1632 status_t status = connection->inputPublisher.reset();
1633 if (status) {
1634 LOGE("channel '%s' ~ Could not reset publisher, status=%d",
1635 connection->getInputChannelName(), status);
1636 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
1637 return;
1638 }
1639
Jeff Browna665ca82010-09-08 11:49:43 -07001640 startNextDispatchCycleLocked(currentTime, connection);
1641}
1642
1643void InputDispatcher::startNextDispatchCycleLocked(nsecs_t currentTime,
1644 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001645 // Start the next dispatch cycle for this connection.
1646 while (! connection->outboundQueue.isEmpty()) {
Jeff Browna665ca82010-09-08 11:49:43 -07001647 DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
Jeff Browne839a582010-04-22 18:58:52 -07001648 if (dispatchEntry->inProgress) {
1649 // Finish or resume current event in progress.
1650 if (dispatchEntry->tailMotionSample) {
1651 // We have a tail of undispatched motion samples.
1652 // Reuse the same DispatchEntry and start a new cycle.
1653 dispatchEntry->inProgress = false;
1654 dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
1655 dispatchEntry->tailMotionSample = NULL;
Jeff Browna665ca82010-09-08 11:49:43 -07001656 startDispatchCycleLocked(currentTime, connection, 0);
Jeff Browne839a582010-04-22 18:58:52 -07001657 return;
1658 }
1659 // Finished.
1660 connection->outboundQueue.dequeueAtHead();
Jeff Brownf67c53e2010-07-28 15:48:59 -07001661 if (dispatchEntry->isSyncTarget()) {
1662 decrementPendingSyncDispatchesLocked(dispatchEntry->eventEntry);
1663 }
Jeff Browne839a582010-04-22 18:58:52 -07001664 mAllocator.releaseDispatchEntry(dispatchEntry);
1665 } else {
1666 // If the head is not in progress, then we must have already dequeued the in
1667 // progress event, which means we actually aborted it (due to ANR).
1668 // So just start the next event for this connection.
Jeff Browna665ca82010-09-08 11:49:43 -07001669 startDispatchCycleLocked(currentTime, connection, 0);
Jeff Browne839a582010-04-22 18:58:52 -07001670 return;
1671 }
1672 }
1673
1674 // Outbound queue is empty, deactivate the connection.
Jeff Brown51d45a72010-06-17 20:52:56 -07001675 deactivateConnectionLocked(connection.get());
Jeff Browne839a582010-04-22 18:58:52 -07001676}
1677
Jeff Brown51d45a72010-06-17 20:52:56 -07001678void InputDispatcher::timeoutDispatchCycleLocked(nsecs_t currentTime,
1679 const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07001680#if DEBUG_DISPATCH_CYCLE
1681 LOGD("channel '%s' ~ timeoutDispatchCycle",
1682 connection->getInputChannelName());
1683#endif
1684
Jeff Browna665ca82010-09-08 11:49:43 -07001685 if (connection->status == Connection::STATUS_NORMAL) {
1686 // Enter the not responding state.
1687 connection->status = Connection::STATUS_NOT_RESPONDING;
1688 connection->lastANRTime = currentTime;
1689 } else if (connection->status != Connection::STATUS_NOT_RESPONDING) {
1690 // Connection is broken or dead.
Jeff Brown51d45a72010-06-17 20:52:56 -07001691 return;
Jeff Browne839a582010-04-22 18:58:52 -07001692 }
1693
Jeff Browne839a582010-04-22 18:58:52 -07001694 // Notify other system components.
Jeff Browna665ca82010-09-08 11:49:43 -07001695 // This enqueues a command which will eventually call resumeAfterTimeoutDispatchCycleLocked.
Jeff Browne839a582010-04-22 18:58:52 -07001696 onDispatchCycleANRLocked(currentTime, connection);
Jeff Browne839a582010-04-22 18:58:52 -07001697}
1698
Jeff Brown51d45a72010-06-17 20:52:56 -07001699void InputDispatcher::resumeAfterTimeoutDispatchCycleLocked(nsecs_t currentTime,
1700 const sp<Connection>& connection, nsecs_t newTimeout) {
1701#if DEBUG_DISPATCH_CYCLE
Jeff Browna665ca82010-09-08 11:49:43 -07001702 LOGD("channel '%s' ~ resumeAfterTimeoutDispatchCycleLocked - newTimeout=%lld",
1703 connection->getInputChannelName(), newTimeout);
Jeff Brown51d45a72010-06-17 20:52:56 -07001704#endif
1705
1706 if (connection->status != Connection::STATUS_NOT_RESPONDING) {
1707 return;
1708 }
1709
Jeff Browna665ca82010-09-08 11:49:43 -07001710 if (newTimeout > 0) {
1711 // The system has decided to give the application some more time.
1712 // Keep waiting synchronously and resume normal dispatch.
1713 connection->status = Connection::STATUS_NORMAL;
1714 connection->setNextTimeoutTime(currentTime, newTimeout);
1715 } else {
1716 // The system is about to throw up an ANR dialog and has requested that we abort dispatch.
1717 // Reset the timeout.
1718 connection->nextTimeoutTime = LONG_LONG_MAX;
1719
1720 // Input state will no longer be realistic.
1721 connection->inputState.setOutOfSync();
1722
1723 if (! connection->outboundQueue.isEmpty()) {
1724 // Make the current pending dispatch asynchronous (if it isn't already) so that
1725 // subsequent events can be delivered to the ANR dialog or to another application.
1726 DispatchEntry* currentDispatchEntry = connection->outboundQueue.headSentinel.next;
1727 currentDispatchEntry->preemptSyncTarget();
1728
1729 // Drain all but the first entry in the outbound queue. We keep the first entry
1730 // since that is the one that dispatch is stuck on. We throw away the others
1731 // so that we don't spam the application with stale messages if it eventually
1732 // wakes up and recovers from the ANR.
1733 drainOutboundQueueLocked(connection.get(), currentDispatchEntry->next);
1734 }
1735 }
Jeff Brown51d45a72010-06-17 20:52:56 -07001736}
1737
1738void InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime,
1739 const sp<Connection>& connection, bool broken) {
Jeff Browne839a582010-04-22 18:58:52 -07001740#if DEBUG_DISPATCH_CYCLE
Jeff Brown54bc2812010-06-15 01:31:58 -07001741 LOGD("channel '%s' ~ abortDispatchCycle - broken=%s",
Jeff Browna665ca82010-09-08 11:49:43 -07001742 connection->getInputChannelName(), toString(broken));
Jeff Browne839a582010-04-22 18:58:52 -07001743#endif
1744
Jeff Browne839a582010-04-22 18:58:52 -07001745 // Clear the pending timeout.
1746 connection->nextTimeoutTime = LONG_LONG_MAX;
1747
Jeff Browna665ca82010-09-08 11:49:43 -07001748 // Input state will no longer be realistic.
1749 connection->inputState.setOutOfSync();
Jeff Browne839a582010-04-22 18:58:52 -07001750
Jeff Browna665ca82010-09-08 11:49:43 -07001751 // Clear the outbound queue.
1752 drainOutboundQueueLocked(connection.get(), connection->outboundQueue.headSentinel.next);
Jeff Browne839a582010-04-22 18:58:52 -07001753
1754 // Handle the case where the connection appears to be unrecoverably broken.
Jeff Brown54bc2812010-06-15 01:31:58 -07001755 // Ignore already broken or zombie connections.
Jeff Browne839a582010-04-22 18:58:52 -07001756 if (broken) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001757 if (connection->status == Connection::STATUS_NORMAL
1758 || connection->status == Connection::STATUS_NOT_RESPONDING) {
1759 connection->status = Connection::STATUS_BROKEN;
Jeff Browne839a582010-04-22 18:58:52 -07001760
Jeff Brown54bc2812010-06-15 01:31:58 -07001761 // Notify other system components.
1762 onDispatchCycleBrokenLocked(currentTime, connection);
1763 }
Jeff Browne839a582010-04-22 18:58:52 -07001764 }
Jeff Browne839a582010-04-22 18:58:52 -07001765}
1766
Jeff Browna665ca82010-09-08 11:49:43 -07001767void InputDispatcher::drainOutboundQueueLocked(Connection* connection,
1768 DispatchEntry* firstDispatchEntryToDrain) {
1769 for (DispatchEntry* dispatchEntry = firstDispatchEntryToDrain;
1770 dispatchEntry != & connection->outboundQueue.tailSentinel;) {
1771 DispatchEntry* next = dispatchEntry->next;
1772 connection->outboundQueue.dequeue(dispatchEntry);
1773
1774 if (dispatchEntry->isSyncTarget()) {
1775 decrementPendingSyncDispatchesLocked(dispatchEntry->eventEntry);
1776 }
1777 mAllocator.releaseDispatchEntry(dispatchEntry);
1778
1779 dispatchEntry = next;
1780 }
1781
1782 if (connection->outboundQueue.isEmpty()) {
1783 deactivateConnectionLocked(connection);
1784 }
1785}
1786
Jeff Browne839a582010-04-22 18:58:52 -07001787bool InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
1788 InputDispatcher* d = static_cast<InputDispatcher*>(data);
1789
1790 { // acquire lock
1791 AutoMutex _l(d->mLock);
1792
1793 ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
1794 if (connectionIndex < 0) {
1795 LOGE("Received spurious receive callback for unknown input channel. "
1796 "fd=%d, events=0x%x", receiveFd, events);
1797 return false; // remove the callback
1798 }
1799
Jeff Brown51d45a72010-06-17 20:52:56 -07001800 nsecs_t currentTime = now();
Jeff Browne839a582010-04-22 18:58:52 -07001801
1802 sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
1803 if (events & (POLLERR | POLLHUP | POLLNVAL)) {
1804 LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
1805 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brown51d45a72010-06-17 20:52:56 -07001806 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -07001807 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07001808 return false; // remove the callback
1809 }
1810
1811 if (! (events & POLLIN)) {
1812 LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
1813 "events=0x%x", connection->getInputChannelName(), events);
1814 return true;
1815 }
1816
1817 status_t status = connection->inputPublisher.receiveFinishedSignal();
1818 if (status) {
1819 LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
1820 connection->getInputChannelName(), status);
Jeff Brown51d45a72010-06-17 20:52:56 -07001821 d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -07001822 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07001823 return false; // remove the callback
1824 }
1825
Jeff Brown51d45a72010-06-17 20:52:56 -07001826 d->finishDispatchCycleLocked(currentTime, connection);
Jeff Brown54bc2812010-06-15 01:31:58 -07001827 d->runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07001828 return true;
1829 } // release lock
1830}
1831
Jeff Brown54bc2812010-06-15 01:31:58 -07001832void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
Jeff Browne839a582010-04-22 18:58:52 -07001833#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown54bc2812010-06-15 01:31:58 -07001834 LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
Jeff Browne839a582010-04-22 18:58:52 -07001835#endif
1836
Jeff Browna665ca82010-09-08 11:49:43 -07001837 bool needWake;
Jeff Browne839a582010-04-22 18:58:52 -07001838 { // acquire lock
1839 AutoMutex _l(mLock);
1840
Jeff Brown51d45a72010-06-17 20:52:56 -07001841 ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
Jeff Browna665ca82010-09-08 11:49:43 -07001842 needWake = enqueueInboundEventLocked(newEntry);
Jeff Browne839a582010-04-22 18:58:52 -07001843 } // release lock
1844
Jeff Browna665ca82010-09-08 11:49:43 -07001845 if (needWake) {
Jeff Browne839a582010-04-22 18:58:52 -07001846 mPollLoop->wake();
1847 }
1848}
1849
Jeff Brown5c1ed842010-07-14 18:48:53 -07001850void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Browne839a582010-04-22 18:58:52 -07001851 uint32_t policyFlags, int32_t action, int32_t flags,
1852 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
1853#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -07001854 LOGD("notifyKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Browne839a582010-04-22 18:58:52 -07001855 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
Jeff Brown5c1ed842010-07-14 18:48:53 -07001856 eventTime, deviceId, source, policyFlags, action, flags,
Jeff Browne839a582010-04-22 18:58:52 -07001857 keyCode, scanCode, metaState, downTime);
1858#endif
1859
Jeff Browna665ca82010-09-08 11:49:43 -07001860 bool needWake;
Jeff Browne839a582010-04-22 18:58:52 -07001861 { // acquire lock
1862 AutoMutex _l(mLock);
1863
Jeff Brown51d45a72010-06-17 20:52:56 -07001864 int32_t repeatCount = 0;
1865 KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07001866 deviceId, source, policyFlags, action, flags, keyCode, scanCode,
Jeff Brown51d45a72010-06-17 20:52:56 -07001867 metaState, repeatCount, downTime);
Jeff Browne839a582010-04-22 18:58:52 -07001868
Jeff Browna665ca82010-09-08 11:49:43 -07001869 needWake = enqueueInboundEventLocked(newEntry);
Jeff Browne839a582010-04-22 18:58:52 -07001870 } // release lock
1871
Jeff Browna665ca82010-09-08 11:49:43 -07001872 if (needWake) {
Jeff Browne839a582010-04-22 18:58:52 -07001873 mPollLoop->wake();
1874 }
1875}
1876
Jeff Brown5c1ed842010-07-14 18:48:53 -07001877void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001878 uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t edgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07001879 uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
1880 float xPrecision, float yPrecision, nsecs_t downTime) {
1881#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown5c1ed842010-07-14 18:48:53 -07001882 LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Brownaf30ff62010-09-01 17:01:00 -07001883 "action=0x%x, flags=0x%x, metaState=0x%x, edgeFlags=0x%x, "
1884 "xPrecision=%f, yPrecision=%f, downTime=%lld",
1885 eventTime, deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07001886 xPrecision, yPrecision, downTime);
1887 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001888 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
Jeff Brownaf30ff62010-09-01 17:01:00 -07001889 "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
Jeff Brown38a7fab2010-08-30 03:02:23 -07001890 "orientation=%f",
Jeff Browne839a582010-04-22 18:58:52 -07001891 i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
Jeff Brown38a7fab2010-08-30 03:02:23 -07001892 pointerCoords[i].pressure, pointerCoords[i].size,
1893 pointerCoords[i].touchMajor, pointerCoords[i].touchMinor,
1894 pointerCoords[i].toolMajor, pointerCoords[i].toolMinor,
1895 pointerCoords[i].orientation);
Jeff Browne839a582010-04-22 18:58:52 -07001896 }
1897#endif
1898
Jeff Browna665ca82010-09-08 11:49:43 -07001899 bool needWake;
Jeff Browne839a582010-04-22 18:58:52 -07001900 { // acquire lock
1901 AutoMutex _l(mLock);
1902
1903 // Attempt batching and streaming of move events.
Jeff Brown5c1ed842010-07-14 18:48:53 -07001904 if (action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Browne839a582010-04-22 18:58:52 -07001905 // BATCHING CASE
1906 //
1907 // Try to append a move sample to the tail of the inbound queue for this device.
1908 // Give up if we encounter a non-move motion event for this device since that
1909 // means we cannot append any new samples until a new motion event has started.
Jeff Browna665ca82010-09-08 11:49:43 -07001910 for (EventEntry* entry = mInboundQueue.tailSentinel.prev;
1911 entry != & mInboundQueue.headSentinel; entry = entry->prev) {
Jeff Browne839a582010-04-22 18:58:52 -07001912 if (entry->type != EventEntry::TYPE_MOTION) {
1913 // Keep looking for motion events.
1914 continue;
1915 }
1916
1917 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
1918 if (motionEntry->deviceId != deviceId) {
1919 // Keep looking for this device.
1920 continue;
1921 }
1922
Jeff Brown5c1ed842010-07-14 18:48:53 -07001923 if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown51d45a72010-06-17 20:52:56 -07001924 || motionEntry->pointerCount != pointerCount
1925 || motionEntry->isInjected()) {
Jeff Browne839a582010-04-22 18:58:52 -07001926 // Last motion event in the queue for this device is not compatible for
1927 // appending new samples. Stop here.
1928 goto NoBatchingOrStreaming;
1929 }
1930
1931 // The last motion event is a move and is compatible for appending.
Jeff Brown54bc2812010-06-15 01:31:58 -07001932 // Do the batching magic.
Jeff Brown51d45a72010-06-17 20:52:56 -07001933 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
Jeff Browne839a582010-04-22 18:58:52 -07001934#if DEBUG_BATCHING
1935 LOGD("Appended motion sample onto batch for most recent "
1936 "motion event for this device in the inbound queue.");
1937#endif
Jeff Brown54bc2812010-06-15 01:31:58 -07001938 return; // done!
Jeff Browne839a582010-04-22 18:58:52 -07001939 }
1940
1941 // STREAMING CASE
1942 //
1943 // There is no pending motion event (of any kind) for this device in the inbound queue.
1944 // Search the outbound queues for a synchronously dispatched motion event for this
1945 // device. If found, then we append the new sample to that event and then try to
1946 // push it out to all current targets. It is possible that some targets will already
1947 // have consumed the motion event. This case is automatically handled by the
1948 // logic in prepareDispatchCycleLocked by tracking where resumption takes place.
1949 //
1950 // The reason we look for a synchronously dispatched motion event is because we
1951 // want to be sure that no other motion events have been dispatched since the move.
1952 // It's also convenient because it means that the input targets are still valid.
1953 // This code could be improved to support streaming of asynchronously dispatched
1954 // motion events (which might be significantly more efficient) but it may become
1955 // a little more complicated as a result.
1956 //
1957 // Note: This code crucially depends on the invariant that an outbound queue always
1958 // contains at most one synchronous event and it is always last (but it might
1959 // not be first!).
Jeff Brown54bc2812010-06-15 01:31:58 -07001960 if (mCurrentInputTargetsValid) {
1961 for (size_t i = 0; i < mActiveConnections.size(); i++) {
1962 Connection* connection = mActiveConnections.itemAt(i);
1963 if (! connection->outboundQueue.isEmpty()) {
Jeff Browna665ca82010-09-08 11:49:43 -07001964 DispatchEntry* dispatchEntry = connection->outboundQueue.tailSentinel.prev;
Jeff Brownf67c53e2010-07-28 15:48:59 -07001965 if (dispatchEntry->isSyncTarget()) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001966 if (dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION) {
1967 goto NoBatchingOrStreaming;
1968 }
Jeff Browne839a582010-04-22 18:58:52 -07001969
Jeff Brown54bc2812010-06-15 01:31:58 -07001970 MotionEntry* syncedMotionEntry = static_cast<MotionEntry*>(
1971 dispatchEntry->eventEntry);
Jeff Brown5c1ed842010-07-14 18:48:53 -07001972 if (syncedMotionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown54bc2812010-06-15 01:31:58 -07001973 || syncedMotionEntry->deviceId != deviceId
Jeff Brown51d45a72010-06-17 20:52:56 -07001974 || syncedMotionEntry->pointerCount != pointerCount
1975 || syncedMotionEntry->isInjected()) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001976 goto NoBatchingOrStreaming;
1977 }
Jeff Browne839a582010-04-22 18:58:52 -07001978
Jeff Brown54bc2812010-06-15 01:31:58 -07001979 // Found synced move entry. Append sample and resume dispatch.
1980 mAllocator.appendMotionSample(syncedMotionEntry, eventTime,
Jeff Brown51d45a72010-06-17 20:52:56 -07001981 pointerCoords);
Jeff Brown54bc2812010-06-15 01:31:58 -07001982 #if DEBUG_BATCHING
1983 LOGD("Appended motion sample onto batch for most recent synchronously "
1984 "dispatched motion event for this device in the outbound queues.");
1985 #endif
Jeff Brown51d45a72010-06-17 20:52:56 -07001986 nsecs_t currentTime = now();
Jeff Brown54bc2812010-06-15 01:31:58 -07001987 dispatchEventToCurrentInputTargetsLocked(currentTime, syncedMotionEntry,
1988 true /*resumeWithAppendedMotionSample*/);
1989
1990 runCommandsLockedInterruptible();
1991 return; // done!
1992 }
Jeff Browne839a582010-04-22 18:58:52 -07001993 }
1994 }
1995 }
1996
1997NoBatchingOrStreaming:;
1998 }
1999
2000 // Just enqueue a new motion event.
Jeff Brown51d45a72010-06-17 20:52:56 -07002001 MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
Jeff Brownaf30ff62010-09-01 17:01:00 -07002002 deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -07002003 xPrecision, yPrecision, downTime,
2004 pointerCount, pointerIds, pointerCoords);
Jeff Browne839a582010-04-22 18:58:52 -07002005
Jeff Browna665ca82010-09-08 11:49:43 -07002006 needWake = enqueueInboundEventLocked(newEntry);
Jeff Browne839a582010-04-22 18:58:52 -07002007 } // release lock
2008
Jeff Browna665ca82010-09-08 11:49:43 -07002009 if (needWake) {
Jeff Browne839a582010-04-22 18:58:52 -07002010 mPollLoop->wake();
2011 }
2012}
2013
Jeff Brown51d45a72010-06-17 20:52:56 -07002014int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
Jeff Brownf67c53e2010-07-28 15:48:59 -07002015 int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
Jeff Brown51d45a72010-06-17 20:52:56 -07002016#if DEBUG_INBOUND_EVENT_DETAILS
2017 LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
Jeff Brownf67c53e2010-07-28 15:48:59 -07002018 "syncMode=%d, timeoutMillis=%d",
2019 event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis);
Jeff Brown51d45a72010-06-17 20:52:56 -07002020#endif
2021
2022 nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
2023
2024 EventEntry* injectedEntry;
Jeff Browna665ca82010-09-08 11:49:43 -07002025 bool needWake;
Jeff Brown51d45a72010-06-17 20:52:56 -07002026 { // acquire lock
2027 AutoMutex _l(mLock);
2028
Jeff Browna665ca82010-09-08 11:49:43 -07002029 injectedEntry = createEntryFromInjectedInputEventLocked(event);
2030 if (! injectedEntry) {
2031 return INPUT_EVENT_INJECTION_FAILED;
2032 }
2033
Jeff Brown51d45a72010-06-17 20:52:56 -07002034 injectedEntry->refCount += 1;
2035 injectedEntry->injectorPid = injectorPid;
2036 injectedEntry->injectorUid = injectorUid;
2037
Jeff Brownf67c53e2010-07-28 15:48:59 -07002038 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
2039 injectedEntry->injectionIsAsync = true;
2040 }
2041
Jeff Browna665ca82010-09-08 11:49:43 -07002042 needWake = enqueueInboundEventLocked(injectedEntry);
Jeff Brown51d45a72010-06-17 20:52:56 -07002043 } // release lock
2044
Jeff Browna665ca82010-09-08 11:49:43 -07002045 if (needWake) {
Jeff Brown51d45a72010-06-17 20:52:56 -07002046 mPollLoop->wake();
2047 }
2048
2049 int32_t injectionResult;
2050 { // acquire lock
2051 AutoMutex _l(mLock);
2052
Jeff Brownf67c53e2010-07-28 15:48:59 -07002053 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
2054 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
2055 } else {
2056 for (;;) {
2057 injectionResult = injectedEntry->injectionResult;
2058 if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
2059 break;
2060 }
Jeff Brown51d45a72010-06-17 20:52:56 -07002061
Jeff Brown51d45a72010-06-17 20:52:56 -07002062 nsecs_t remainingTimeout = endTime - now();
2063 if (remainingTimeout <= 0) {
Jeff Brownf67c53e2010-07-28 15:48:59 -07002064#if DEBUG_INJECTION
2065 LOGD("injectInputEvent - Timed out waiting for injection result "
2066 "to become available.");
2067#endif
Jeff Brown51d45a72010-06-17 20:52:56 -07002068 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
2069 break;
2070 }
2071
Jeff Brownf67c53e2010-07-28 15:48:59 -07002072 mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
2073 }
2074
2075 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
2076 && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
2077 while (injectedEntry->pendingSyncDispatches != 0) {
2078#if DEBUG_INJECTION
2079 LOGD("injectInputEvent - Waiting for %d pending synchronous dispatches.",
2080 injectedEntry->pendingSyncDispatches);
2081#endif
2082 nsecs_t remainingTimeout = endTime - now();
2083 if (remainingTimeout <= 0) {
2084#if DEBUG_INJECTION
2085 LOGD("injectInputEvent - Timed out waiting for pending synchronous "
2086 "dispatches to finish.");
2087#endif
2088 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
2089 break;
2090 }
2091
2092 mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
2093 }
Jeff Brown51d45a72010-06-17 20:52:56 -07002094 }
2095 }
2096
2097 mAllocator.releaseEventEntry(injectedEntry);
2098 } // release lock
2099
Jeff Brownf67c53e2010-07-28 15:48:59 -07002100#if DEBUG_INJECTION
2101 LOGD("injectInputEvent - Finished with result %d. "
2102 "injectorPid=%d, injectorUid=%d",
2103 injectionResult, injectorPid, injectorUid);
2104#endif
2105
Jeff Brown51d45a72010-06-17 20:52:56 -07002106 return injectionResult;
2107}
2108
2109void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
2110 if (entry->isInjected()) {
2111#if DEBUG_INJECTION
2112 LOGD("Setting input event injection result to %d. "
2113 "injectorPid=%d, injectorUid=%d",
2114 injectionResult, entry->injectorPid, entry->injectorUid);
2115#endif
2116
Jeff Brownf67c53e2010-07-28 15:48:59 -07002117 if (entry->injectionIsAsync) {
2118 // Log the outcome since the injector did not wait for the injection result.
2119 switch (injectionResult) {
2120 case INPUT_EVENT_INJECTION_SUCCEEDED:
2121 LOGV("Asynchronous input event injection succeeded.");
2122 break;
2123 case INPUT_EVENT_INJECTION_FAILED:
2124 LOGW("Asynchronous input event injection failed.");
2125 break;
2126 case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
2127 LOGW("Asynchronous input event injection permission denied.");
2128 break;
2129 case INPUT_EVENT_INJECTION_TIMED_OUT:
2130 LOGW("Asynchronous input event injection timed out.");
2131 break;
2132 }
2133 }
2134
Jeff Brown51d45a72010-06-17 20:52:56 -07002135 entry->injectionResult = injectionResult;
2136 mInjectionResultAvailableCondition.broadcast();
2137 }
2138}
2139
Jeff Brownf67c53e2010-07-28 15:48:59 -07002140void InputDispatcher::decrementPendingSyncDispatchesLocked(EventEntry* entry) {
2141 entry->pendingSyncDispatches -= 1;
2142
2143 if (entry->isInjected() && entry->pendingSyncDispatches == 0) {
2144 mInjectionSyncFinishedCondition.broadcast();
2145 }
Jeff Brown51d45a72010-06-17 20:52:56 -07002146}
2147
Jeff Browna665ca82010-09-08 11:49:43 -07002148static bool isValidKeyAction(int32_t action) {
2149 switch (action) {
2150 case AKEY_EVENT_ACTION_DOWN:
2151 case AKEY_EVENT_ACTION_UP:
2152 return true;
2153 default:
2154 return false;
2155 }
2156}
2157
2158static bool isValidMotionAction(int32_t action) {
2159 switch (action & AMOTION_EVENT_ACTION_MASK) {
2160 case AMOTION_EVENT_ACTION_DOWN:
2161 case AMOTION_EVENT_ACTION_UP:
2162 case AMOTION_EVENT_ACTION_CANCEL:
2163 case AMOTION_EVENT_ACTION_MOVE:
2164 case AMOTION_EVENT_ACTION_POINTER_DOWN:
2165 case AMOTION_EVENT_ACTION_POINTER_UP:
2166 case AMOTION_EVENT_ACTION_OUTSIDE:
2167 return true;
2168 default:
2169 return false;
2170 }
2171}
2172
2173InputDispatcher::EventEntry* InputDispatcher::createEntryFromInjectedInputEventLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07002174 const InputEvent* event) {
2175 switch (event->getType()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07002176 case AINPUT_EVENT_TYPE_KEY: {
Jeff Brown51d45a72010-06-17 20:52:56 -07002177 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
Jeff Browna665ca82010-09-08 11:49:43 -07002178 if (! isValidKeyAction(keyEvent->getAction())) {
2179 LOGE("Dropping injected key event since it has invalid action code 0x%x",
2180 keyEvent->getAction());
2181 return NULL;
2182 }
2183
Jeff Brownaf30ff62010-09-01 17:01:00 -07002184 uint32_t policyFlags = POLICY_FLAG_INJECTED;
Jeff Brown51d45a72010-06-17 20:52:56 -07002185
2186 KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
Jeff Brown5c1ed842010-07-14 18:48:53 -07002187 keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags,
Jeff Brown51d45a72010-06-17 20:52:56 -07002188 keyEvent->getAction(), keyEvent->getFlags(),
2189 keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
2190 keyEvent->getRepeatCount(), keyEvent->getDownTime());
2191 return keyEntry;
2192 }
2193
Jeff Brown5c1ed842010-07-14 18:48:53 -07002194 case AINPUT_EVENT_TYPE_MOTION: {
Jeff Brown51d45a72010-06-17 20:52:56 -07002195 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
Jeff Browna665ca82010-09-08 11:49:43 -07002196 if (! isValidMotionAction(motionEvent->getAction())) {
2197 LOGE("Dropping injected motion event since it has invalid action code 0x%x.",
2198 motionEvent->getAction());
2199 return NULL;
2200 }
2201 if (motionEvent->getPointerCount() == 0
2202 || motionEvent->getPointerCount() > MAX_POINTERS) {
2203 LOGE("Dropping injected motion event since it has an invalid pointer count %d.",
2204 motionEvent->getPointerCount());
2205 }
2206
Jeff Brownaf30ff62010-09-01 17:01:00 -07002207 uint32_t policyFlags = POLICY_FLAG_INJECTED;
Jeff Brown51d45a72010-06-17 20:52:56 -07002208
2209 const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
2210 const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
2211 size_t pointerCount = motionEvent->getPointerCount();
2212
2213 MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
Jeff Brown5c1ed842010-07-14 18:48:53 -07002214 motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
Jeff Brownaf30ff62010-09-01 17:01:00 -07002215 motionEvent->getAction(), motionEvent->getFlags(),
2216 motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
Jeff Brown51d45a72010-06-17 20:52:56 -07002217 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
2218 motionEvent->getDownTime(), uint32_t(pointerCount),
2219 motionEvent->getPointerIds(), samplePointerCoords);
2220 for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
2221 sampleEventTimes += 1;
2222 samplePointerCoords += pointerCount;
2223 mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
2224 }
2225 return motionEntry;
2226 }
2227
2228 default:
2229 assert(false);
2230 return NULL;
2231 }
2232}
2233
Jeff Browna665ca82010-09-08 11:49:43 -07002234void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
2235#if DEBUG_FOCUS
2236 LOGD("setInputWindows");
2237#endif
2238 { // acquire lock
2239 AutoMutex _l(mLock);
2240
2241 sp<InputChannel> touchedWindowChannel;
2242 if (mTouchedWindow) {
2243 touchedWindowChannel = mTouchedWindow->inputChannel;
2244 mTouchedWindow = NULL;
2245 }
2246 size_t numTouchedWallpapers = mTouchedWallpaperWindows.size();
2247 if (numTouchedWallpapers != 0) {
2248 for (size_t i = 0; i < numTouchedWallpapers; i++) {
2249 mTempTouchedWallpaperChannels.push(mTouchedWallpaperWindows[i]->inputChannel);
2250 }
2251 mTouchedWallpaperWindows.clear();
2252 }
2253
2254 bool hadFocusedWindow = mFocusedWindow != NULL;
2255
2256 mFocusedWindow = NULL;
2257 mWallpaperWindows.clear();
2258
2259 mWindows.clear();
2260 mWindows.appendVector(inputWindows);
2261
2262 size_t numWindows = mWindows.size();
2263 for (size_t i = 0; i < numWindows; i++) {
2264 InputWindow* window = & mWindows.editItemAt(i);
2265 if (window->hasFocus) {
2266 mFocusedWindow = window;
2267 }
2268
2269 if (window->layoutParamsType == InputWindow::TYPE_WALLPAPER) {
2270 mWallpaperWindows.push(window);
2271
2272 for (size_t j = 0; j < numTouchedWallpapers; j++) {
2273 if (window->inputChannel == mTempTouchedWallpaperChannels[i]) {
2274 mTouchedWallpaperWindows.push(window);
2275 }
2276 }
2277 }
2278
2279 if (window->inputChannel == touchedWindowChannel) {
2280 mTouchedWindow = window;
2281 }
2282 }
2283
2284 mTempTouchedWallpaperChannels.clear();
2285
2286 if ((hadFocusedWindow && ! mFocusedWindow)
2287 || (mFocusedWindow && ! mFocusedWindow->visible)) {
2288 preemptInputDispatchInnerLocked();
2289 }
2290
2291#if DEBUG_FOCUS
2292 logDispatchStateLocked();
2293#endif
2294 } // release lock
2295
2296 // Wake up poll loop since it may need to make new input dispatching choices.
2297 mPollLoop->wake();
2298}
2299
2300void InputDispatcher::setFocusedApplication(const InputApplication* inputApplication) {
2301#if DEBUG_FOCUS
2302 LOGD("setFocusedApplication");
2303#endif
2304 { // acquire lock
2305 AutoMutex _l(mLock);
2306
2307 releaseFocusedApplicationLocked();
2308
2309 if (inputApplication) {
2310 mFocusedApplicationStorage = *inputApplication;
2311 mFocusedApplication = & mFocusedApplicationStorage;
2312 }
2313
2314#if DEBUG_FOCUS
2315 logDispatchStateLocked();
2316#endif
2317 } // release lock
2318
2319 // Wake up poll loop since it may need to make new input dispatching choices.
2320 mPollLoop->wake();
2321}
2322
2323void InputDispatcher::releaseFocusedApplicationLocked() {
2324 if (mFocusedApplication) {
2325 mFocusedApplication = NULL;
2326 mFocusedApplicationStorage.handle.clear();
2327 }
2328}
2329
2330void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
2331#if DEBUG_FOCUS
2332 LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
2333#endif
2334
2335 bool changed;
2336 { // acquire lock
2337 AutoMutex _l(mLock);
2338
2339 if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
2340 if (mDispatchFrozen && ! frozen) {
2341 resetANRTimeoutsLocked();
2342 }
2343
2344 mDispatchEnabled = enabled;
2345 mDispatchFrozen = frozen;
2346 changed = true;
2347 } else {
2348 changed = false;
2349 }
2350
2351#if DEBUG_FOCUS
2352 logDispatchStateLocked();
2353#endif
2354 } // release lock
2355
2356 if (changed) {
2357 // Wake up poll loop since it may need to make new input dispatching choices.
2358 mPollLoop->wake();
Jeff Browne839a582010-04-22 18:58:52 -07002359 }
2360}
2361
Jeff Brown50de30a2010-06-22 01:27:15 -07002362void InputDispatcher::preemptInputDispatch() {
Jeff Browna665ca82010-09-08 11:49:43 -07002363#if DEBUG_FOCUS
Jeff Brown50de30a2010-06-22 01:27:15 -07002364 LOGD("preemptInputDispatch");
2365#endif
2366
Jeff Browna665ca82010-09-08 11:49:43 -07002367 bool preemptedOne;
Jeff Brown50de30a2010-06-22 01:27:15 -07002368 { // acquire lock
2369 AutoMutex _l(mLock);
Jeff Browna665ca82010-09-08 11:49:43 -07002370 preemptedOne = preemptInputDispatchInnerLocked();
Jeff Brown50de30a2010-06-22 01:27:15 -07002371 } // release lock
2372
2373 if (preemptedOne) {
2374 // Wake up the poll loop so it can get a head start dispatching the next event.
2375 mPollLoop->wake();
2376 }
2377}
2378
Jeff Browna665ca82010-09-08 11:49:43 -07002379bool InputDispatcher::preemptInputDispatchInnerLocked() {
2380 bool preemptedOne = false;
2381 for (size_t i = 0; i < mActiveConnections.size(); i++) {
2382 Connection* connection = mActiveConnections[i];
2383 if (connection->hasPendingSyncTarget()) {
2384#if DEBUG_DISPATCH_CYCLE
2385 LOGD("channel '%s' ~ Preempted pending synchronous dispatch",
2386 connection->getInputChannelName());
2387#endif
2388 connection->preemptSyncTarget();
2389 preemptedOne = true;
2390 }
2391 }
2392 return preemptedOne;
2393}
2394
2395void InputDispatcher::logDispatchStateLocked() {
2396 String8 dump;
2397 dumpDispatchStateLocked(dump);
2398 LOGD("%s", dump.string());
2399}
2400
2401void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
2402 dump.appendFormat(" dispatchEnabled: %d\n", mDispatchEnabled);
2403 dump.appendFormat(" dispatchFrozen: %d\n", mDispatchFrozen);
2404
2405 if (mFocusedApplication) {
2406 dump.appendFormat(" focusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
2407 mFocusedApplication->name.string(),
2408 mFocusedApplication->dispatchingTimeout / 1000000.0);
2409 } else {
2410 dump.append(" focusedApplication: <null>\n");
2411 }
2412 dump.appendFormat(" focusedWindow: '%s'\n",
2413 mFocusedWindow != NULL ? mFocusedWindow->inputChannel->getName().string() : "<null>");
2414 dump.appendFormat(" touchedWindow: '%s', touchDown=%d\n",
2415 mTouchedWindow != NULL ? mTouchedWindow->inputChannel->getName().string() : "<null>",
2416 mTouchDown);
2417 for (size_t i = 0; i < mTouchedWallpaperWindows.size(); i++) {
2418 dump.appendFormat(" touchedWallpaperWindows[%d]: '%s'\n",
2419 i, mTouchedWallpaperWindows[i]->inputChannel->getName().string());
2420 }
2421 for (size_t i = 0; i < mWindows.size(); i++) {
2422 dump.appendFormat(" windows[%d]: '%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
2423 "visible=%s, flags=0x%08x, type=0x%08x, "
2424 "frame=[%d,%d][%d,%d], "
2425 "visibleFrame=[%d,%d][%d,%d], "
2426 "touchableArea=[%d,%d][%d,%d], "
2427 "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
2428 i, mWindows[i].inputChannel->getName().string(),
2429 toString(mWindows[i].paused),
2430 toString(mWindows[i].hasFocus),
2431 toString(mWindows[i].hasWallpaper),
2432 toString(mWindows[i].visible),
2433 mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
2434 mWindows[i].frameLeft, mWindows[i].frameTop,
2435 mWindows[i].frameRight, mWindows[i].frameBottom,
2436 mWindows[i].visibleFrameLeft, mWindows[i].visibleFrameTop,
2437 mWindows[i].visibleFrameRight, mWindows[i].visibleFrameBottom,
2438 mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop,
2439 mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom,
2440 mWindows[i].ownerPid, mWindows[i].ownerUid,
2441 mWindows[i].dispatchingTimeout / 1000000.0);
2442 }
2443
2444 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
2445 const sp<InputChannel>& channel = mMonitoringChannels[i];
2446 dump.appendFormat(" monitoringChannel[%d]: '%s'\n",
2447 i, channel->getName().string());
2448 }
2449
2450 for (size_t i = 0; i < mActiveConnections.size(); i++) {
2451 const Connection* connection = mActiveConnections[i];
2452 dump.appendFormat(" activeConnection[%d]: '%s', status=%s, hasPendingSyncTarget=%s, "
2453 "inputState.isNeutral=%s, inputState.isOutOfSync=%s\n",
2454 i, connection->getInputChannelName(), connection->getStatusLabel(),
2455 toString(connection->hasPendingSyncTarget()),
2456 toString(connection->inputState.isNeutral()),
2457 toString(connection->inputState.isOutOfSync()));
2458 }
2459
2460 if (isAppSwitchPendingLocked()) {
2461 dump.appendFormat(" appSwitch: pending, due in %01.1fms\n",
2462 (mAppSwitchDueTime - now()) / 1000000.0);
2463 } else {
2464 dump.append(" appSwitch: not pending\n");
2465 }
2466}
2467
2468status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
Jeff Brown54bc2812010-06-15 01:31:58 -07002469#if DEBUG_REGISTRATION
Jeff Browna665ca82010-09-08 11:49:43 -07002470 LOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().string(),
2471 toString(monitor));
Jeff Brown54bc2812010-06-15 01:31:58 -07002472#endif
2473
Jeff Browne839a582010-04-22 18:58:52 -07002474 { // acquire lock
2475 AutoMutex _l(mLock);
2476
Jeff Brown0cacb872010-08-17 15:59:26 -07002477 if (getConnectionIndex(inputChannel) >= 0) {
Jeff Browne839a582010-04-22 18:58:52 -07002478 LOGW("Attempted to register already registered input channel '%s'",
2479 inputChannel->getName().string());
2480 return BAD_VALUE;
2481 }
2482
2483 sp<Connection> connection = new Connection(inputChannel);
2484 status_t status = connection->initialize();
2485 if (status) {
2486 LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
2487 inputChannel->getName().string(), status);
2488 return status;
2489 }
2490
Jeff Brown0cacb872010-08-17 15:59:26 -07002491 int32_t receiveFd = inputChannel->getReceivePipeFd();
Jeff Browne839a582010-04-22 18:58:52 -07002492 mConnectionsByReceiveFd.add(receiveFd, connection);
Jeff Brown54bc2812010-06-15 01:31:58 -07002493
Jeff Browna665ca82010-09-08 11:49:43 -07002494 if (monitor) {
2495 mMonitoringChannels.push(inputChannel);
2496 }
2497
Jeff Brown0cacb872010-08-17 15:59:26 -07002498 mPollLoop->setCallback(receiveFd, POLLIN, handleReceiveCallback, this);
2499
Jeff Brown54bc2812010-06-15 01:31:58 -07002500 runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07002501 } // release lock
Jeff Browne839a582010-04-22 18:58:52 -07002502 return OK;
2503}
2504
2505status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown54bc2812010-06-15 01:31:58 -07002506#if DEBUG_REGISTRATION
Jeff Brown50de30a2010-06-22 01:27:15 -07002507 LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
Jeff Brown54bc2812010-06-15 01:31:58 -07002508#endif
2509
Jeff Browne839a582010-04-22 18:58:52 -07002510 { // acquire lock
2511 AutoMutex _l(mLock);
2512
Jeff Brown0cacb872010-08-17 15:59:26 -07002513 ssize_t connectionIndex = getConnectionIndex(inputChannel);
Jeff Browne839a582010-04-22 18:58:52 -07002514 if (connectionIndex < 0) {
2515 LOGW("Attempted to unregister already unregistered input channel '%s'",
2516 inputChannel->getName().string());
2517 return BAD_VALUE;
2518 }
2519
2520 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
2521 mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
2522
2523 connection->status = Connection::STATUS_ZOMBIE;
2524
Jeff Browna665ca82010-09-08 11:49:43 -07002525 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
2526 if (mMonitoringChannels[i] == inputChannel) {
2527 mMonitoringChannels.removeAt(i);
2528 break;
2529 }
2530 }
2531
Jeff Brown0cacb872010-08-17 15:59:26 -07002532 mPollLoop->removeCallback(inputChannel->getReceivePipeFd());
2533
Jeff Brown51d45a72010-06-17 20:52:56 -07002534 nsecs_t currentTime = now();
2535 abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
Jeff Brown54bc2812010-06-15 01:31:58 -07002536
2537 runCommandsLockedInterruptible();
Jeff Browne839a582010-04-22 18:58:52 -07002538 } // release lock
2539
Jeff Browne839a582010-04-22 18:58:52 -07002540 // Wake the poll loop because removing the connection may have changed the current
2541 // synchronization state.
2542 mPollLoop->wake();
2543 return OK;
2544}
2545
Jeff Brown0cacb872010-08-17 15:59:26 -07002546ssize_t InputDispatcher::getConnectionIndex(const sp<InputChannel>& inputChannel) {
2547 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(inputChannel->getReceivePipeFd());
2548 if (connectionIndex >= 0) {
2549 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
2550 if (connection->inputChannel.get() == inputChannel.get()) {
2551 return connectionIndex;
2552 }
2553 }
2554
2555 return -1;
2556}
2557
Jeff Browne839a582010-04-22 18:58:52 -07002558void InputDispatcher::activateConnectionLocked(Connection* connection) {
2559 for (size_t i = 0; i < mActiveConnections.size(); i++) {
2560 if (mActiveConnections.itemAt(i) == connection) {
2561 return;
2562 }
2563 }
2564 mActiveConnections.add(connection);
2565}
2566
2567void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
2568 for (size_t i = 0; i < mActiveConnections.size(); i++) {
2569 if (mActiveConnections.itemAt(i) == connection) {
2570 mActiveConnections.removeAt(i);
2571 return;
2572 }
2573 }
2574}
2575
Jeff Brown54bc2812010-06-15 01:31:58 -07002576void InputDispatcher::onDispatchCycleStartedLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07002577 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07002578}
2579
Jeff Brown54bc2812010-06-15 01:31:58 -07002580void InputDispatcher::onDispatchCycleFinishedLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07002581 nsecs_t currentTime, const sp<Connection>& connection, bool recoveredFromANR) {
Jeff Browne839a582010-04-22 18:58:52 -07002582 if (recoveredFromANR) {
2583 LOGI("channel '%s' ~ Recovered from ANR. %01.1fms since event, "
2584 "%01.1fms since dispatch, %01.1fms since ANR",
2585 connection->getInputChannelName(),
2586 connection->getEventLatencyMillis(currentTime),
2587 connection->getDispatchLatencyMillis(currentTime),
2588 connection->getANRLatencyMillis(currentTime));
2589
Jeff Brown54bc2812010-06-15 01:31:58 -07002590 CommandEntry* commandEntry = postCommandLocked(
2591 & InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07002592 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07002593 }
2594}
2595
Jeff Brown54bc2812010-06-15 01:31:58 -07002596void InputDispatcher::onDispatchCycleANRLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07002597 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07002598 LOGI("channel '%s' ~ Not responding! %01.1fms since event, %01.1fms since dispatch",
2599 connection->getInputChannelName(),
2600 connection->getEventLatencyMillis(currentTime),
2601 connection->getDispatchLatencyMillis(currentTime));
2602
Jeff Brown54bc2812010-06-15 01:31:58 -07002603 CommandEntry* commandEntry = postCommandLocked(
2604 & InputDispatcher::doNotifyInputChannelANRLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07002605 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07002606}
2607
Jeff Brown54bc2812010-06-15 01:31:58 -07002608void InputDispatcher::onDispatchCycleBrokenLocked(
Jeff Brown51d45a72010-06-17 20:52:56 -07002609 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Browne839a582010-04-22 18:58:52 -07002610 LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
2611 connection->getInputChannelName());
2612
Jeff Brown54bc2812010-06-15 01:31:58 -07002613 CommandEntry* commandEntry = postCommandLocked(
2614 & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
Jeff Brown51d45a72010-06-17 20:52:56 -07002615 commandEntry->connection = connection;
Jeff Browne839a582010-04-22 18:58:52 -07002616}
2617
Jeff Browna665ca82010-09-08 11:49:43 -07002618void InputDispatcher::doNotifyConfigurationChangedInterruptible(
2619 CommandEntry* commandEntry) {
2620 mLock.unlock();
2621
2622 mPolicy->notifyConfigurationChanged(commandEntry->eventTime);
2623
2624 mLock.lock();
2625}
2626
Jeff Brown54bc2812010-06-15 01:31:58 -07002627void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
2628 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07002629 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07002630
Jeff Brown51d45a72010-06-17 20:52:56 -07002631 if (connection->status != Connection::STATUS_ZOMBIE) {
2632 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07002633
Jeff Brown51d45a72010-06-17 20:52:56 -07002634 mPolicy->notifyInputChannelBroken(connection->inputChannel);
2635
2636 mLock.lock();
2637 }
Jeff Brown54bc2812010-06-15 01:31:58 -07002638}
2639
2640void InputDispatcher::doNotifyInputChannelANRLockedInterruptible(
2641 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07002642 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07002643
Jeff Brown51d45a72010-06-17 20:52:56 -07002644 if (connection->status != Connection::STATUS_ZOMBIE) {
2645 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07002646
Jeff Browna665ca82010-09-08 11:49:43 -07002647 nsecs_t newTimeout = mPolicy->notifyInputChannelANR(connection->inputChannel);
Jeff Brown51d45a72010-06-17 20:52:56 -07002648
2649 mLock.lock();
2650
2651 nsecs_t currentTime = now();
Jeff Browna665ca82010-09-08 11:49:43 -07002652 resumeAfterTimeoutDispatchCycleLocked(currentTime, connection, newTimeout);
Jeff Brown51d45a72010-06-17 20:52:56 -07002653 }
Jeff Brown54bc2812010-06-15 01:31:58 -07002654}
2655
2656void InputDispatcher::doNotifyInputChannelRecoveredFromANRLockedInterruptible(
2657 CommandEntry* commandEntry) {
Jeff Brown51d45a72010-06-17 20:52:56 -07002658 sp<Connection> connection = commandEntry->connection;
Jeff Brown54bc2812010-06-15 01:31:58 -07002659
Jeff Brown51d45a72010-06-17 20:52:56 -07002660 if (connection->status != Connection::STATUS_ZOMBIE) {
2661 mLock.unlock();
Jeff Brown54bc2812010-06-15 01:31:58 -07002662
Jeff Brown51d45a72010-06-17 20:52:56 -07002663 mPolicy->notifyInputChannelRecoveredFromANR(connection->inputChannel);
2664
2665 mLock.lock();
2666 }
Jeff Brown54bc2812010-06-15 01:31:58 -07002667}
2668
Jeff Browna665ca82010-09-08 11:49:43 -07002669void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
2670 CommandEntry* commandEntry) {
2671 KeyEntry* entry = commandEntry->keyEntry;
2672 mReusableKeyEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
2673 entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
2674 entry->downTime, entry->eventTime);
2675
2676 mLock.unlock();
2677
2678 bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputChannel,
2679 & mReusableKeyEvent, entry->policyFlags);
2680
2681 mLock.lock();
2682
2683 entry->interceptKeyResult = consumed
2684 ? KeyEntry::INTERCEPT_KEY_RESULT_SKIP
2685 : KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
2686 mAllocator.releaseKeyEntry(entry);
2687}
2688
2689void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
2690 mLock.unlock();
2691
2692 mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->windowType,
2693 commandEntry->userActivityEventType);
2694
2695 mLock.lock();
2696}
2697
2698void InputDispatcher::doTargetsNotReadyTimeoutLockedInterruptible(
2699 CommandEntry* commandEntry) {
2700 mLock.unlock();
2701
2702 nsecs_t newTimeout;
2703 if (commandEntry->inputChannel.get()) {
2704 newTimeout = mPolicy->notifyInputChannelANR(commandEntry->inputChannel);
2705 } else if (commandEntry->inputApplicationHandle.get()) {
2706 newTimeout = mPolicy->notifyANR(commandEntry->inputApplicationHandle);
2707 } else {
2708 newTimeout = 0;
2709 }
2710
2711 mLock.lock();
2712
2713 resumeAfterTargetsNotReadyTimeoutLocked(newTimeout);
2714}
2715
2716void InputDispatcher::dump(String8& dump) {
2717 dumpDispatchStateLocked(dump);
2718}
2719
Jeff Brown54bc2812010-06-15 01:31:58 -07002720
Jeff Browne839a582010-04-22 18:58:52 -07002721// --- InputDispatcher::Allocator ---
2722
2723InputDispatcher::Allocator::Allocator() {
2724}
2725
Jeff Brown51d45a72010-06-17 20:52:56 -07002726void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
2727 nsecs_t eventTime) {
2728 entry->type = type;
2729 entry->refCount = 1;
2730 entry->dispatchInProgress = false;
Christopher Tated974e002010-06-23 16:50:30 -07002731 entry->eventTime = eventTime;
Jeff Brown51d45a72010-06-17 20:52:56 -07002732 entry->injectionResult = INPUT_EVENT_INJECTION_PENDING;
Jeff Brownf67c53e2010-07-28 15:48:59 -07002733 entry->injectionIsAsync = false;
Jeff Brown51d45a72010-06-17 20:52:56 -07002734 entry->injectorPid = -1;
2735 entry->injectorUid = -1;
Jeff Brownf67c53e2010-07-28 15:48:59 -07002736 entry->pendingSyncDispatches = 0;
Jeff Brown51d45a72010-06-17 20:52:56 -07002737}
2738
Jeff Browne839a582010-04-22 18:58:52 -07002739InputDispatcher::ConfigurationChangedEntry*
Jeff Brown51d45a72010-06-17 20:52:56 -07002740InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
Jeff Browne839a582010-04-22 18:58:52 -07002741 ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07002742 initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime);
Jeff Browne839a582010-04-22 18:58:52 -07002743 return entry;
2744}
2745
Jeff Brown51d45a72010-06-17 20:52:56 -07002746InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
Jeff Brown5c1ed842010-07-14 18:48:53 -07002747 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
Jeff Brown51d45a72010-06-17 20:52:56 -07002748 int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
2749 int32_t repeatCount, nsecs_t downTime) {
Jeff Browne839a582010-04-22 18:58:52 -07002750 KeyEntry* entry = mKeyEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07002751 initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime);
2752
2753 entry->deviceId = deviceId;
Jeff Brown5c1ed842010-07-14 18:48:53 -07002754 entry->source = source;
Jeff Brown51d45a72010-06-17 20:52:56 -07002755 entry->policyFlags = policyFlags;
2756 entry->action = action;
2757 entry->flags = flags;
2758 entry->keyCode = keyCode;
2759 entry->scanCode = scanCode;
2760 entry->metaState = metaState;
2761 entry->repeatCount = repeatCount;
2762 entry->downTime = downTime;
Jeff Browna665ca82010-09-08 11:49:43 -07002763 entry->syntheticRepeat = false;
2764 entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
Jeff Browne839a582010-04-22 18:58:52 -07002765 return entry;
2766}
2767
Jeff Brown51d45a72010-06-17 20:52:56 -07002768InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
Jeff Brownaf30ff62010-09-01 17:01:00 -07002769 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
Jeff Brown51d45a72010-06-17 20:52:56 -07002770 int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
2771 nsecs_t downTime, uint32_t pointerCount,
2772 const int32_t* pointerIds, const PointerCoords* pointerCoords) {
Jeff Browne839a582010-04-22 18:58:52 -07002773 MotionEntry* entry = mMotionEntryPool.alloc();
Jeff Brown51d45a72010-06-17 20:52:56 -07002774 initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime);
2775
2776 entry->eventTime = eventTime;
2777 entry->deviceId = deviceId;
Jeff Brown5c1ed842010-07-14 18:48:53 -07002778 entry->source = source;
Jeff Brown51d45a72010-06-17 20:52:56 -07002779 entry->policyFlags = policyFlags;
2780 entry->action = action;
Jeff Brownaf30ff62010-09-01 17:01:00 -07002781 entry->flags = flags;
Jeff Brown51d45a72010-06-17 20:52:56 -07002782 entry->metaState = metaState;
2783 entry->edgeFlags = edgeFlags;
2784 entry->xPrecision = xPrecision;
2785 entry->yPrecision = yPrecision;
2786 entry->downTime = downTime;
2787 entry->pointerCount = pointerCount;
2788 entry->firstSample.eventTime = eventTime;
Jeff Browne839a582010-04-22 18:58:52 -07002789 entry->firstSample.next = NULL;
Jeff Brown51d45a72010-06-17 20:52:56 -07002790 entry->lastSample = & entry->firstSample;
2791 for (uint32_t i = 0; i < pointerCount; i++) {
2792 entry->pointerIds[i] = pointerIds[i];
2793 entry->firstSample.pointerCoords[i] = pointerCoords[i];
2794 }
Jeff Browne839a582010-04-22 18:58:52 -07002795 return entry;
2796}
2797
2798InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
Jeff Browna665ca82010-09-08 11:49:43 -07002799 EventEntry* eventEntry,
2800 int32_t targetFlags, float xOffset, float yOffset, nsecs_t timeout) {
Jeff Browne839a582010-04-22 18:58:52 -07002801 DispatchEntry* entry = mDispatchEntryPool.alloc();
2802 entry->eventEntry = eventEntry;
2803 eventEntry->refCount += 1;
Jeff Browna665ca82010-09-08 11:49:43 -07002804 entry->targetFlags = targetFlags;
2805 entry->xOffset = xOffset;
2806 entry->yOffset = yOffset;
2807 entry->timeout = timeout;
2808 entry->inProgress = false;
2809 entry->headMotionSample = NULL;
2810 entry->tailMotionSample = NULL;
Jeff Browne839a582010-04-22 18:58:52 -07002811 return entry;
2812}
2813
Jeff Brown54bc2812010-06-15 01:31:58 -07002814InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
2815 CommandEntry* entry = mCommandEntryPool.alloc();
2816 entry->command = command;
2817 return entry;
2818}
2819
Jeff Browne839a582010-04-22 18:58:52 -07002820void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
2821 switch (entry->type) {
2822 case EventEntry::TYPE_CONFIGURATION_CHANGED:
2823 releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
2824 break;
2825 case EventEntry::TYPE_KEY:
2826 releaseKeyEntry(static_cast<KeyEntry*>(entry));
2827 break;
2828 case EventEntry::TYPE_MOTION:
2829 releaseMotionEntry(static_cast<MotionEntry*>(entry));
2830 break;
2831 default:
2832 assert(false);
2833 break;
2834 }
2835}
2836
2837void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
2838 ConfigurationChangedEntry* entry) {
2839 entry->refCount -= 1;
2840 if (entry->refCount == 0) {
2841 mConfigurationChangeEntryPool.free(entry);
2842 } else {
2843 assert(entry->refCount > 0);
2844 }
2845}
2846
2847void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
2848 entry->refCount -= 1;
2849 if (entry->refCount == 0) {
2850 mKeyEntryPool.free(entry);
2851 } else {
2852 assert(entry->refCount > 0);
2853 }
2854}
2855
2856void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
2857 entry->refCount -= 1;
2858 if (entry->refCount == 0) {
Jeff Brown54bc2812010-06-15 01:31:58 -07002859 for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
2860 MotionSample* next = sample->next;
2861 mMotionSamplePool.free(sample);
2862 sample = next;
2863 }
Jeff Browne839a582010-04-22 18:58:52 -07002864 mMotionEntryPool.free(entry);
2865 } else {
2866 assert(entry->refCount > 0);
2867 }
2868}
2869
2870void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
2871 releaseEventEntry(entry->eventEntry);
2872 mDispatchEntryPool.free(entry);
2873}
2874
Jeff Brown54bc2812010-06-15 01:31:58 -07002875void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
2876 mCommandEntryPool.free(entry);
2877}
2878
Jeff Browne839a582010-04-22 18:58:52 -07002879void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
Jeff Brown51d45a72010-06-17 20:52:56 -07002880 nsecs_t eventTime, const PointerCoords* pointerCoords) {
Jeff Browne839a582010-04-22 18:58:52 -07002881 MotionSample* sample = mMotionSamplePool.alloc();
2882 sample->eventTime = eventTime;
Jeff Brown51d45a72010-06-17 20:52:56 -07002883 uint32_t pointerCount = motionEntry->pointerCount;
2884 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Browne839a582010-04-22 18:58:52 -07002885 sample->pointerCoords[i] = pointerCoords[i];
2886 }
2887
2888 sample->next = NULL;
2889 motionEntry->lastSample->next = sample;
2890 motionEntry->lastSample = sample;
2891}
2892
Jeff Browna665ca82010-09-08 11:49:43 -07002893
2894// --- InputDispatcher::EventEntry ---
2895
2896void InputDispatcher::EventEntry::recycle() {
2897 injectionResult = INPUT_EVENT_INJECTION_PENDING;
2898 dispatchInProgress = false;
2899 pendingSyncDispatches = 0;
2900}
2901
2902
2903// --- InputDispatcher::KeyEntry ---
2904
2905void InputDispatcher::KeyEntry::recycle() {
2906 EventEntry::recycle();
2907 syntheticRepeat = false;
2908 interceptKeyResult = INTERCEPT_KEY_RESULT_UNKNOWN;
2909}
2910
2911
Jeff Brown542412c2010-08-18 15:51:08 -07002912// --- InputDispatcher::MotionEntry ---
2913
2914uint32_t InputDispatcher::MotionEntry::countSamples() const {
2915 uint32_t count = 1;
2916 for (MotionSample* sample = firstSample.next; sample != NULL; sample = sample->next) {
2917 count += 1;
2918 }
2919 return count;
2920}
2921
Jeff Browna665ca82010-09-08 11:49:43 -07002922
2923// --- InputDispatcher::InputState ---
2924
2925InputDispatcher::InputState::InputState() :
2926 mIsOutOfSync(false) {
2927}
2928
2929InputDispatcher::InputState::~InputState() {
2930}
2931
2932bool InputDispatcher::InputState::isNeutral() const {
2933 return mKeyMementos.isEmpty() && mMotionMementos.isEmpty();
2934}
2935
2936bool InputDispatcher::InputState::isOutOfSync() const {
2937 return mIsOutOfSync;
2938}
2939
2940void InputDispatcher::InputState::setOutOfSync() {
2941 if (! isNeutral()) {
2942 mIsOutOfSync = true;
2943 }
2944}
2945
2946void InputDispatcher::InputState::resetOutOfSync() {
2947 mIsOutOfSync = false;
2948}
2949
2950InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackEvent(
2951 const EventEntry* entry) {
2952 switch (entry->type) {
2953 case EventEntry::TYPE_KEY:
2954 return trackKey(static_cast<const KeyEntry*>(entry));
2955
2956 case EventEntry::TYPE_MOTION:
2957 return trackMotion(static_cast<const MotionEntry*>(entry));
2958
2959 default:
2960 return CONSISTENT;
2961 }
2962}
2963
2964InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackKey(
2965 const KeyEntry* entry) {
2966 int32_t action = entry->action;
2967 for (size_t i = 0; i < mKeyMementos.size(); i++) {
2968 KeyMemento& memento = mKeyMementos.editItemAt(i);
2969 if (memento.deviceId == entry->deviceId
2970 && memento.source == entry->source
2971 && memento.keyCode == entry->keyCode
2972 && memento.scanCode == entry->scanCode) {
2973 switch (action) {
2974 case AKEY_EVENT_ACTION_UP:
2975 mKeyMementos.removeAt(i);
2976 if (isNeutral()) {
2977 mIsOutOfSync = false;
2978 }
2979 return CONSISTENT;
2980
2981 case AKEY_EVENT_ACTION_DOWN:
2982 return TOLERABLE;
2983
2984 default:
2985 return BROKEN;
2986 }
2987 }
2988 }
2989
2990 switch (action) {
2991 case AKEY_EVENT_ACTION_DOWN: {
2992 mKeyMementos.push();
2993 KeyMemento& memento = mKeyMementos.editTop();
2994 memento.deviceId = entry->deviceId;
2995 memento.source = entry->source;
2996 memento.keyCode = entry->keyCode;
2997 memento.scanCode = entry->scanCode;
2998 memento.downTime = entry->downTime;
2999 return CONSISTENT;
3000 }
3001
3002 default:
3003 return BROKEN;
3004 }
3005}
3006
3007InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackMotion(
3008 const MotionEntry* entry) {
3009 int32_t action = entry->action & AMOTION_EVENT_ACTION_MASK;
3010 for (size_t i = 0; i < mMotionMementos.size(); i++) {
3011 MotionMemento& memento = mMotionMementos.editItemAt(i);
3012 if (memento.deviceId == entry->deviceId
3013 && memento.source == entry->source) {
3014 switch (action) {
3015 case AMOTION_EVENT_ACTION_UP:
3016 case AMOTION_EVENT_ACTION_CANCEL:
3017 mMotionMementos.removeAt(i);
3018 if (isNeutral()) {
3019 mIsOutOfSync = false;
3020 }
3021 return CONSISTENT;
3022
3023 case AMOTION_EVENT_ACTION_DOWN:
3024 return TOLERABLE;
3025
3026 case AMOTION_EVENT_ACTION_POINTER_DOWN:
3027 if (entry->pointerCount == memento.pointerCount + 1) {
3028 memento.setPointers(entry);
3029 return CONSISTENT;
3030 }
3031 return BROKEN;
3032
3033 case AMOTION_EVENT_ACTION_POINTER_UP:
3034 if (entry->pointerCount == memento.pointerCount - 1) {
3035 memento.setPointers(entry);
3036 return CONSISTENT;
3037 }
3038 return BROKEN;
3039
3040 case AMOTION_EVENT_ACTION_MOVE:
3041 if (entry->pointerCount == memento.pointerCount) {
3042 return CONSISTENT;
3043 }
3044 return BROKEN;
3045
3046 default:
3047 return BROKEN;
3048 }
3049 }
3050 }
3051
3052 switch (action) {
3053 case AMOTION_EVENT_ACTION_DOWN: {
3054 mMotionMementos.push();
3055 MotionMemento& memento = mMotionMementos.editTop();
3056 memento.deviceId = entry->deviceId;
3057 memento.source = entry->source;
3058 memento.xPrecision = entry->xPrecision;
3059 memento.yPrecision = entry->yPrecision;
3060 memento.downTime = entry->downTime;
3061 memento.setPointers(entry);
3062 return CONSISTENT;
3063 }
3064
3065 default:
3066 return BROKEN;
3067 }
3068}
3069
3070void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) {
3071 pointerCount = entry->pointerCount;
3072 for (uint32_t i = 0; i < entry->pointerCount; i++) {
3073 pointerIds[i] = entry->pointerIds[i];
3074 pointerCoords[i] = entry->lastSample->pointerCoords[i];
3075 }
3076}
3077
3078void InputDispatcher::InputState::synthesizeCancelationEvents(
3079 Allocator* allocator, Vector<EventEntry*>& outEvents) const {
3080 for (size_t i = 0; i < mKeyMementos.size(); i++) {
3081 const KeyMemento& memento = mKeyMementos.itemAt(i);
3082 outEvents.push(allocator->obtainKeyEntry(now(),
3083 memento.deviceId, memento.source, 0,
3084 AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_CANCELED,
3085 memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
3086 }
3087
3088 for (size_t i = 0; i < mMotionMementos.size(); i++) {
3089 const MotionMemento& memento = mMotionMementos.itemAt(i);
3090 outEvents.push(allocator->obtainMotionEntry(now(),
3091 memento.deviceId, memento.source, 0,
3092 AMOTION_EVENT_ACTION_CANCEL, 0, 0, 0,
3093 memento.xPrecision, memento.yPrecision, memento.downTime,
3094 memento.pointerCount, memento.pointerIds, memento.pointerCoords));
3095 }
3096}
3097
3098void InputDispatcher::InputState::clear() {
3099 mKeyMementos.clear();
3100 mMotionMementos.clear();
3101 mIsOutOfSync = false;
3102}
3103
3104
Jeff Browne839a582010-04-22 18:58:52 -07003105// --- InputDispatcher::Connection ---
3106
3107InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
3108 status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
3109 nextTimeoutTime(LONG_LONG_MAX),
3110 lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX),
3111 lastANRTime(LONG_LONG_MAX) {
3112}
3113
3114InputDispatcher::Connection::~Connection() {
3115}
3116
3117status_t InputDispatcher::Connection::initialize() {
3118 return inputPublisher.initialize();
3119}
3120
Jeff Brown51d45a72010-06-17 20:52:56 -07003121void InputDispatcher::Connection::setNextTimeoutTime(nsecs_t currentTime, nsecs_t timeout) {
3122 nextTimeoutTime = (timeout >= 0) ? currentTime + timeout : LONG_LONG_MAX;
3123}
3124
Jeff Browna665ca82010-09-08 11:49:43 -07003125void InputDispatcher::Connection::resetTimeout(nsecs_t currentTime) {
3126 if (outboundQueue.isEmpty()) {
3127 nextTimeoutTime = LONG_LONG_MAX;
3128 } else {
3129 setNextTimeoutTime(currentTime, outboundQueue.headSentinel.next->timeout);
3130 }
3131}
3132
Jeff Brown54bc2812010-06-15 01:31:58 -07003133const char* InputDispatcher::Connection::getStatusLabel() const {
3134 switch (status) {
3135 case STATUS_NORMAL:
3136 return "NORMAL";
3137
3138 case STATUS_BROKEN:
3139 return "BROKEN";
3140
3141 case STATUS_NOT_RESPONDING:
3142 return "NOT_RESPONDING";
3143
3144 case STATUS_ZOMBIE:
3145 return "ZOMBIE";
3146
3147 default:
3148 return "UNKNOWN";
3149 }
3150}
3151
Jeff Browne839a582010-04-22 18:58:52 -07003152InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
3153 const EventEntry* eventEntry) const {
Jeff Browna665ca82010-09-08 11:49:43 -07003154 for (DispatchEntry* dispatchEntry = outboundQueue.tailSentinel.prev;
3155 dispatchEntry != & outboundQueue.headSentinel; dispatchEntry = dispatchEntry->prev) {
Jeff Browne839a582010-04-22 18:58:52 -07003156 if (dispatchEntry->eventEntry == eventEntry) {
3157 return dispatchEntry;
3158 }
3159 }
3160 return NULL;
3161}
3162
Jeff Browna665ca82010-09-08 11:49:43 -07003163
Jeff Brown54bc2812010-06-15 01:31:58 -07003164// --- InputDispatcher::CommandEntry ---
3165
Jeff Browna665ca82010-09-08 11:49:43 -07003166InputDispatcher::CommandEntry::CommandEntry() :
3167 keyEntry(NULL) {
Jeff Brown54bc2812010-06-15 01:31:58 -07003168}
3169
3170InputDispatcher::CommandEntry::~CommandEntry() {
3171}
3172
Jeff Browne839a582010-04-22 18:58:52 -07003173
3174// --- InputDispatcherThread ---
3175
3176InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
3177 Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
3178}
3179
3180InputDispatcherThread::~InputDispatcherThread() {
3181}
3182
3183bool InputDispatcherThread::threadLoop() {
3184 mDispatcher->dispatchOnce();
3185 return true;
3186}
3187
3188} // namespace android