blob: 41b6ff318d47bbe77a9b0a8c1b44ad0dee3f4563 [file] [log] [blame]
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4// The input dispatcher.
5//
6#define LOG_TAG "InputDispatcher"
7
8//#define LOG_NDEBUG 0
9
10// Log detailed debug messages about each inbound event notification to the dispatcher.
Jeff Brown349703e2010-06-22 01:27:15 -070011#define DEBUG_INBOUND_EVENT_DETAILS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070012
13// Log detailed debug messages about each outbound event processed by the dispatcher.
Jeff Brown349703e2010-06-22 01:27:15 -070014#define DEBUG_OUTBOUND_EVENT_DETAILS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070015
16// Log debug messages about batching.
Jeff Brown349703e2010-06-22 01:27:15 -070017#define DEBUG_BATCHING 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070018
19// Log debug messages about the dispatch cycle.
Jeff Brown349703e2010-06-22 01:27:15 -070020#define DEBUG_DISPATCH_CYCLE 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070021
Jeff Brown9c3cda02010-06-15 01:31:58 -070022// Log debug messages about registrations.
Jeff Brown349703e2010-06-22 01:27:15 -070023#define DEBUG_REGISTRATION 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070024
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070025// Log debug messages about performance statistics.
Jeff Brown349703e2010-06-22 01:27:15 -070026#define DEBUG_PERFORMANCE_STATISTICS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070027
Jeff Brown7fbdc842010-06-17 20:52:56 -070028// Log debug messages about input event injection.
Jeff Brown349703e2010-06-22 01:27:15 -070029#define DEBUG_INJECTION 0
Jeff Brown7fbdc842010-06-17 20:52:56 -070030
Jeff Brownae9fc032010-08-18 15:51:08 -070031// Log debug messages about input event throttling.
32#define DEBUG_THROTTLING 0
33
Jeff Brownb88102f2010-09-08 11:49:43 -070034// Log debug messages about input focus tracking.
35#define DEBUG_FOCUS 0
36
37// Log debug messages about the app switch latency optimization.
38#define DEBUG_APP_SWITCH 0
39
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070040#include <cutils/log.h>
41#include <ui/InputDispatcher.h>
Jeff Brownb88102f2010-09-08 11:49:43 -070042#include <ui/PowerManager.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070043
44#include <stddef.h>
45#include <unistd.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070046#include <errno.h>
47#include <limits.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070048
Jeff Brownf2f487182010-10-01 17:46:21 -070049#define INDENT " "
50#define INDENT2 " "
51
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070052namespace android {
53
Jeff Brownb88102f2010-09-08 11:49:43 -070054// Delay between reporting long touch events to the power manager.
55const nsecs_t EVENT_IGNORE_DURATION = 300 * 1000000LL; // 300 ms
56
57// Default input dispatching timeout if there is no focused application or paused window
58// from which to determine an appropriate dispatching timeout.
59const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
60
61// Amount of time to allow for all pending events to be processed when an app switch
62// key is on the way. This is used to preempt input dispatch and drop input events
63// when an application takes too long to respond and the user has pressed an app switch key.
64const nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
65
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070066
Jeff Brown7fbdc842010-06-17 20:52:56 -070067static inline nsecs_t now() {
68 return systemTime(SYSTEM_TIME_MONOTONIC);
69}
70
Jeff Brownb88102f2010-09-08 11:49:43 -070071static inline const char* toString(bool value) {
72 return value ? "true" : "false";
73}
74
Jeff Brown01ce2e92010-09-26 22:20:12 -070075static inline int32_t getMotionEventActionPointerIndex(int32_t action) {
76 return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
77 >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
78}
79
80static bool isValidKeyAction(int32_t action) {
81 switch (action) {
82 case AKEY_EVENT_ACTION_DOWN:
83 case AKEY_EVENT_ACTION_UP:
84 return true;
85 default:
86 return false;
87 }
88}
89
90static bool validateKeyEvent(int32_t action) {
91 if (! isValidKeyAction(action)) {
92 LOGE("Key event has invalid action code 0x%x", action);
93 return false;
94 }
95 return true;
96}
97
Jeff Brownb6997262010-10-08 22:31:17 -070098static bool isValidMotionAction(int32_t action, size_t pointerCount) {
Jeff Brown01ce2e92010-09-26 22:20:12 -070099 switch (action & AMOTION_EVENT_ACTION_MASK) {
100 case AMOTION_EVENT_ACTION_DOWN:
101 case AMOTION_EVENT_ACTION_UP:
102 case AMOTION_EVENT_ACTION_CANCEL:
103 case AMOTION_EVENT_ACTION_MOVE:
Jeff Brown01ce2e92010-09-26 22:20:12 -0700104 case AMOTION_EVENT_ACTION_OUTSIDE:
105 return true;
Jeff Brownb6997262010-10-08 22:31:17 -0700106 case AMOTION_EVENT_ACTION_POINTER_DOWN:
107 case AMOTION_EVENT_ACTION_POINTER_UP: {
108 int32_t index = getMotionEventActionPointerIndex(action);
109 return index >= 0 && size_t(index) < pointerCount;
110 }
Jeff Brown01ce2e92010-09-26 22:20:12 -0700111 default:
112 return false;
113 }
114}
115
116static bool validateMotionEvent(int32_t action, size_t pointerCount,
117 const int32_t* pointerIds) {
Jeff Brownb6997262010-10-08 22:31:17 -0700118 if (! isValidMotionAction(action, pointerCount)) {
Jeff Brown01ce2e92010-09-26 22:20:12 -0700119 LOGE("Motion event has invalid action code 0x%x", action);
120 return false;
121 }
122 if (pointerCount < 1 || pointerCount > MAX_POINTERS) {
123 LOGE("Motion event has invalid pointer count %d; value must be between 1 and %d.",
124 pointerCount, MAX_POINTERS);
125 return false;
126 }
127 for (size_t i = 0; i < pointerCount; i++) {
128 if (pointerIds[i] < 0 || pointerIds[i] > MAX_POINTER_ID) {
129 LOGE("Motion event has invalid pointer id %d; value must be between 0 and %d",
130 pointerIds[i], MAX_POINTER_ID);
131 return false;
132 }
133 }
134 return true;
135}
136
Jeff Brownb88102f2010-09-08 11:49:43 -0700137
138// --- InputWindow ---
139
Jeff Brownb88102f2010-09-08 11:49:43 -0700140bool InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
141 return x >= touchableAreaLeft && x <= touchableAreaRight
142 && y >= touchableAreaTop && y <= touchableAreaBottom;
143}
144
Jeff Brown19dfc832010-10-05 12:26:23 -0700145bool InputWindow::frameContainsPoint(int32_t x, int32_t y) const {
146 return x >= frameLeft && x <= frameRight
147 && y >= frameTop && y <= frameBottom;
148}
149
150bool InputWindow::isTrustedOverlay() const {
151 return layoutParamsType == TYPE_INPUT_METHOD
152 || layoutParamsType == TYPE_INPUT_METHOD_DIALOG;
153}
154
Jeff Brownb88102f2010-09-08 11:49:43 -0700155
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700156// --- InputDispatcher ---
157
Jeff Brown9c3cda02010-06-15 01:31:58 -0700158InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
Jeff Brownb88102f2010-09-08 11:49:43 -0700159 mPolicy(policy),
160 mPendingEvent(NULL), mAppSwitchDueTime(LONG_LONG_MAX),
161 mDispatchEnabled(true), mDispatchFrozen(false),
Jeff Brown01ce2e92010-09-26 22:20:12 -0700162 mFocusedWindow(NULL),
Jeff Brownb88102f2010-09-08 11:49:43 -0700163 mFocusedApplication(NULL),
164 mCurrentInputTargetsValid(false),
165 mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700166 mLooper = new Looper(false);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700167
Jeff Brownb88102f2010-09-08 11:49:43 -0700168 mInboundQueue.headSentinel.refCount = -1;
169 mInboundQueue.headSentinel.type = EventEntry::TYPE_SENTINEL;
170 mInboundQueue.headSentinel.eventTime = LONG_LONG_MIN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700171
Jeff Brownb88102f2010-09-08 11:49:43 -0700172 mInboundQueue.tailSentinel.refCount = -1;
173 mInboundQueue.tailSentinel.type = EventEntry::TYPE_SENTINEL;
174 mInboundQueue.tailSentinel.eventTime = LONG_LONG_MAX;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700175
176 mKeyRepeatState.lastKeyEntry = NULL;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700177
Jeff Brownae9fc032010-08-18 15:51:08 -0700178 int32_t maxEventsPerSecond = policy->getMaxEventsPerSecond();
179 mThrottleState.minTimeBetweenEvents = 1000000000LL / maxEventsPerSecond;
180 mThrottleState.lastDeviceId = -1;
181
182#if DEBUG_THROTTLING
183 mThrottleState.originalSampleCount = 0;
184 LOGD("Throttling - Max events per second = %d", maxEventsPerSecond);
185#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700186}
187
188InputDispatcher::~InputDispatcher() {
Jeff Brownb88102f2010-09-08 11:49:43 -0700189 { // acquire lock
190 AutoMutex _l(mLock);
191
192 resetKeyRepeatLocked();
Jeff Brown54a18252010-09-16 14:07:33 -0700193 releasePendingEventLocked();
Jeff Brownb88102f2010-09-08 11:49:43 -0700194 drainInboundQueueLocked();
195 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700196
197 while (mConnectionsByReceiveFd.size() != 0) {
198 unregisterInputChannel(mConnectionsByReceiveFd.valueAt(0)->inputChannel);
199 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700200}
201
202void InputDispatcher::dispatchOnce() {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700203 nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
Jeff Brownb21fb102010-09-07 10:44:57 -0700204 nsecs_t keyRepeatDelay = mPolicy->getKeyRepeatDelay();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700205
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700206 nsecs_t nextWakeupTime = LONG_LONG_MAX;
207 { // acquire lock
208 AutoMutex _l(mLock);
Jeff Brownb88102f2010-09-08 11:49:43 -0700209 dispatchOnceInnerLocked(keyRepeatTimeout, keyRepeatDelay, & nextWakeupTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700210
Jeff Brownb88102f2010-09-08 11:49:43 -0700211 if (runCommandsLockedInterruptible()) {
212 nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700213 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700214 } // release lock
215
Jeff Brownb88102f2010-09-08 11:49:43 -0700216 // Wait for callback or timeout or wake. (make sure we round up, not down)
217 nsecs_t currentTime = now();
218 int32_t timeoutMillis;
219 if (nextWakeupTime > currentTime) {
220 uint64_t timeout = uint64_t(nextWakeupTime - currentTime);
221 timeout = (timeout + 999999LL) / 1000000LL;
222 timeoutMillis = timeout > INT_MAX ? -1 : int32_t(timeout);
223 } else {
224 timeoutMillis = 0;
225 }
226
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700227 mLooper->pollOnce(timeoutMillis);
Jeff Brownb88102f2010-09-08 11:49:43 -0700228}
229
230void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
231 nsecs_t keyRepeatDelay, nsecs_t* nextWakeupTime) {
232 nsecs_t currentTime = now();
233
234 // Reset the key repeat timer whenever we disallow key events, even if the next event
235 // is not a key. This is to ensure that we abort a key repeat if the device is just coming
236 // out of sleep.
237 if (keyRepeatTimeout < 0) {
238 resetKeyRepeatLocked();
239 }
240
Jeff Brownb88102f2010-09-08 11:49:43 -0700241 // If dispatching is frozen, do not process timeouts or try to deliver any new events.
242 if (mDispatchFrozen) {
243#if DEBUG_FOCUS
244 LOGD("Dispatch frozen. Waiting some more.");
245#endif
246 return;
247 }
248
249 // Optimize latency of app switches.
250 // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
251 // been pressed. When it expires, we preempt dispatch and drop all other pending events.
252 bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
253 if (mAppSwitchDueTime < *nextWakeupTime) {
254 *nextWakeupTime = mAppSwitchDueTime;
255 }
256
Jeff Brownb88102f2010-09-08 11:49:43 -0700257 // Ready to start a new event.
258 // If we don't already have a pending event, go grab one.
259 if (! mPendingEvent) {
260 if (mInboundQueue.isEmpty()) {
261 if (isAppSwitchDue) {
262 // The inbound queue is empty so the app switch key we were waiting
263 // for will never arrive. Stop waiting for it.
264 resetPendingAppSwitchLocked(false);
265 isAppSwitchDue = false;
266 }
267
268 // Synthesize a key repeat if appropriate.
269 if (mKeyRepeatState.lastKeyEntry) {
270 if (currentTime >= mKeyRepeatState.nextRepeatTime) {
271 mPendingEvent = synthesizeKeyRepeatLocked(currentTime, keyRepeatDelay);
272 } else {
273 if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
274 *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
275 }
276 }
277 }
278 if (! mPendingEvent) {
279 return;
280 }
281 } else {
282 // Inbound queue has at least one entry.
283 EventEntry* entry = mInboundQueue.headSentinel.next;
284
285 // Throttle the entry if it is a move event and there are no
286 // other events behind it in the queue. Due to movement batching, additional
287 // samples may be appended to this event by the time the throttling timeout
288 // expires.
289 // TODO Make this smarter and consider throttling per device independently.
Jeff Brownb6997262010-10-08 22:31:17 -0700290 if (entry->type == EventEntry::TYPE_MOTION
291 && !isAppSwitchDue
292 && mDispatchEnabled
293 && (entry->policyFlags & POLICY_FLAG_PASS_TO_USER)
294 && !entry->isInjected()) {
Jeff Brownb88102f2010-09-08 11:49:43 -0700295 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
296 int32_t deviceId = motionEntry->deviceId;
297 uint32_t source = motionEntry->source;
298 if (! isAppSwitchDue
299 && motionEntry->next == & mInboundQueue.tailSentinel // exactly one event
300 && motionEntry->action == AMOTION_EVENT_ACTION_MOVE
301 && deviceId == mThrottleState.lastDeviceId
302 && source == mThrottleState.lastSource) {
303 nsecs_t nextTime = mThrottleState.lastEventTime
304 + mThrottleState.minTimeBetweenEvents;
305 if (currentTime < nextTime) {
306 // Throttle it!
307#if DEBUG_THROTTLING
308 LOGD("Throttling - Delaying motion event for "
309 "device 0x%x, source 0x%08x by up to %0.3fms.",
310 deviceId, source, (nextTime - currentTime) * 0.000001);
311#endif
312 if (nextTime < *nextWakeupTime) {
313 *nextWakeupTime = nextTime;
314 }
315 if (mThrottleState.originalSampleCount == 0) {
316 mThrottleState.originalSampleCount =
317 motionEntry->countSamples();
318 }
319 return;
320 }
321 }
322
323#if DEBUG_THROTTLING
324 if (mThrottleState.originalSampleCount != 0) {
325 uint32_t count = motionEntry->countSamples();
326 LOGD("Throttling - Motion event sample count grew by %d from %d to %d.",
327 count - mThrottleState.originalSampleCount,
328 mThrottleState.originalSampleCount, count);
329 mThrottleState.originalSampleCount = 0;
330 }
331#endif
332
333 mThrottleState.lastEventTime = entry->eventTime < currentTime
334 ? entry->eventTime : currentTime;
335 mThrottleState.lastDeviceId = deviceId;
336 mThrottleState.lastSource = source;
337 }
338
339 mInboundQueue.dequeue(entry);
340 mPendingEvent = entry;
341 }
342 }
343
344 // Now we have an event to dispatch.
345 assert(mPendingEvent != NULL);
Jeff Brown54a18252010-09-16 14:07:33 -0700346 bool done = false;
Jeff Brownb6997262010-10-08 22:31:17 -0700347 DropReason dropReason = DROP_REASON_NOT_DROPPED;
348 if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
349 dropReason = DROP_REASON_POLICY;
350 } else if (!mDispatchEnabled) {
351 dropReason = DROP_REASON_DISABLED;
352 }
Jeff Brownb88102f2010-09-08 11:49:43 -0700353 switch (mPendingEvent->type) {
354 case EventEntry::TYPE_CONFIGURATION_CHANGED: {
355 ConfigurationChangedEntry* typedEntry =
356 static_cast<ConfigurationChangedEntry*>(mPendingEvent);
Jeff Brown54a18252010-09-16 14:07:33 -0700357 done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
Jeff Brownb6997262010-10-08 22:31:17 -0700358 dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
Jeff Brownb88102f2010-09-08 11:49:43 -0700359 break;
360 }
361
362 case EventEntry::TYPE_KEY: {
363 KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
Jeff Brownb6997262010-10-08 22:31:17 -0700364 if (isAppSwitchDue) {
365 if (isAppSwitchKeyEventLocked(typedEntry)) {
Jeff Brownb88102f2010-09-08 11:49:43 -0700366 resetPendingAppSwitchLocked(true);
Jeff Brownb6997262010-10-08 22:31:17 -0700367 isAppSwitchDue = false;
368 } else if (dropReason == DROP_REASON_NOT_DROPPED) {
369 dropReason = DROP_REASON_APP_SWITCH;
Jeff Brownb88102f2010-09-08 11:49:43 -0700370 }
371 }
Jeff Brownb6997262010-10-08 22:31:17 -0700372 done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
Jeff Brownb931a1b2010-10-11 14:20:19 -0700373 &dropReason, nextWakeupTime);
Jeff Brownb88102f2010-09-08 11:49:43 -0700374 break;
375 }
376
377 case EventEntry::TYPE_MOTION: {
378 MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
Jeff Brownb6997262010-10-08 22:31:17 -0700379 if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
380 dropReason = DROP_REASON_APP_SWITCH;
Jeff Brownb88102f2010-09-08 11:49:43 -0700381 }
Jeff Brownb6997262010-10-08 22:31:17 -0700382 done = dispatchMotionLocked(currentTime, typedEntry,
Jeff Brownb931a1b2010-10-11 14:20:19 -0700383 &dropReason, nextWakeupTime);
Jeff Brownb88102f2010-09-08 11:49:43 -0700384 break;
385 }
386
387 default:
388 assert(false);
Jeff Brownb88102f2010-09-08 11:49:43 -0700389 break;
390 }
391
Jeff Brown54a18252010-09-16 14:07:33 -0700392 if (done) {
Jeff Brownb6997262010-10-08 22:31:17 -0700393 if (dropReason != DROP_REASON_NOT_DROPPED) {
394 dropInboundEventLocked(mPendingEvent, dropReason);
395 }
396
Jeff Brown54a18252010-09-16 14:07:33 -0700397 releasePendingEventLocked();
Jeff Brownb88102f2010-09-08 11:49:43 -0700398 *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
399 }
400}
401
402bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
403 bool needWake = mInboundQueue.isEmpty();
404 mInboundQueue.enqueueAtTail(entry);
405
406 switch (entry->type) {
Jeff Brownb6997262010-10-08 22:31:17 -0700407 case EventEntry::TYPE_KEY: {
408 KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
409 if (isAppSwitchKeyEventLocked(keyEntry)) {
410 if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
411 mAppSwitchSawKeyDown = true;
412 } else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
413 if (mAppSwitchSawKeyDown) {
414#if DEBUG_APP_SWITCH
415 LOGD("App switch is pending!");
416#endif
417 mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
418 mAppSwitchSawKeyDown = false;
419 needWake = true;
420 }
421 }
422 }
Jeff Brownb88102f2010-09-08 11:49:43 -0700423 break;
424 }
Jeff Brownb6997262010-10-08 22:31:17 -0700425 }
Jeff Brownb88102f2010-09-08 11:49:43 -0700426
427 return needWake;
428}
429
Jeff Brownb6997262010-10-08 22:31:17 -0700430void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
431 const char* reason;
432 switch (dropReason) {
433 case DROP_REASON_POLICY:
Jeff Brownb931a1b2010-10-11 14:20:19 -0700434#if DEBUG_INBOUND_EVENT_DETAILS
435 LOGD("Dropped event because policy requested that it not be delivered to the application.");
436#endif
Jeff Brownb6997262010-10-08 22:31:17 -0700437 reason = "inbound event was dropped because the policy requested that it not be "
438 "delivered to the application";
439 break;
440 case DROP_REASON_DISABLED:
441 LOGI("Dropped event because input dispatch is disabled.");
442 reason = "inbound event was dropped because input dispatch is disabled";
443 break;
444 case DROP_REASON_APP_SWITCH:
445 LOGI("Dropped event because of pending overdue app switch.");
446 reason = "inbound event was dropped because of pending overdue app switch";
447 break;
448 default:
449 assert(false);
450 return;
451 }
452
453 switch (entry->type) {
454 case EventEntry::TYPE_KEY:
455 synthesizeCancelationEventsForAllConnectionsLocked(
456 InputState::CANCEL_NON_POINTER_EVENTS, reason);
457 break;
458 case EventEntry::TYPE_MOTION: {
459 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
460 if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
461 synthesizeCancelationEventsForAllConnectionsLocked(
462 InputState::CANCEL_POINTER_EVENTS, reason);
463 } else {
464 synthesizeCancelationEventsForAllConnectionsLocked(
465 InputState::CANCEL_NON_POINTER_EVENTS, reason);
466 }
467 break;
468 }
469 }
470}
471
472bool InputDispatcher::isAppSwitchKeyCode(int32_t keyCode) {
Jeff Brownb88102f2010-09-08 11:49:43 -0700473 return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
474}
475
Jeff Brownb6997262010-10-08 22:31:17 -0700476bool InputDispatcher::isAppSwitchKeyEventLocked(KeyEntry* keyEntry) {
477 return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
478 && isAppSwitchKeyCode(keyEntry->keyCode)
Jeff Brownb931a1b2010-10-11 14:20:19 -0700479 && (keyEntry->policyFlags & POLICY_FLAG_TRUSTED)
Jeff Brownb6997262010-10-08 22:31:17 -0700480 && (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
481}
482
Jeff Brownb88102f2010-09-08 11:49:43 -0700483bool InputDispatcher::isAppSwitchPendingLocked() {
484 return mAppSwitchDueTime != LONG_LONG_MAX;
485}
486
Jeff Brownb88102f2010-09-08 11:49:43 -0700487void InputDispatcher::resetPendingAppSwitchLocked(bool handled) {
488 mAppSwitchDueTime = LONG_LONG_MAX;
489
490#if DEBUG_APP_SWITCH
491 if (handled) {
492 LOGD("App switch has arrived.");
493 } else {
494 LOGD("App switch was abandoned.");
495 }
496#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700497}
498
Jeff Brown9c3cda02010-06-15 01:31:58 -0700499bool InputDispatcher::runCommandsLockedInterruptible() {
500 if (mCommandQueue.isEmpty()) {
501 return false;
502 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700503
Jeff Brown9c3cda02010-06-15 01:31:58 -0700504 do {
505 CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
506
507 Command command = commandEntry->command;
508 (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
509
Jeff Brown7fbdc842010-06-17 20:52:56 -0700510 commandEntry->connection.clear();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700511 mAllocator.releaseCommandEntry(commandEntry);
512 } while (! mCommandQueue.isEmpty());
513 return true;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700514}
515
Jeff Brown9c3cda02010-06-15 01:31:58 -0700516InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
517 CommandEntry* commandEntry = mAllocator.obtainCommandEntry(command);
518 mCommandQueue.enqueueAtTail(commandEntry);
519 return commandEntry;
520}
521
Jeff Brownb88102f2010-09-08 11:49:43 -0700522void InputDispatcher::drainInboundQueueLocked() {
523 while (! mInboundQueue.isEmpty()) {
524 EventEntry* entry = mInboundQueue.dequeueAtHead();
Jeff Brown54a18252010-09-16 14:07:33 -0700525 releaseInboundEventLocked(entry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700526 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700527}
528
Jeff Brown54a18252010-09-16 14:07:33 -0700529void InputDispatcher::releasePendingEventLocked() {
Jeff Brownb88102f2010-09-08 11:49:43 -0700530 if (mPendingEvent) {
Jeff Brown54a18252010-09-16 14:07:33 -0700531 releaseInboundEventLocked(mPendingEvent);
Jeff Brownb88102f2010-09-08 11:49:43 -0700532 mPendingEvent = NULL;
533 }
534}
535
Jeff Brown54a18252010-09-16 14:07:33 -0700536void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) {
Jeff Brown01ce2e92010-09-26 22:20:12 -0700537 InjectionState* injectionState = entry->injectionState;
538 if (injectionState && injectionState->injectionResult == INPUT_EVENT_INJECTION_PENDING) {
Jeff Brownb88102f2010-09-08 11:49:43 -0700539#if DEBUG_DISPATCH_CYCLE
Jeff Brown01ce2e92010-09-26 22:20:12 -0700540 LOGD("Injected inbound event was dropped.");
Jeff Brownb88102f2010-09-08 11:49:43 -0700541#endif
542 setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
543 }
544 mAllocator.releaseEventEntry(entry);
545}
546
Jeff Brownb88102f2010-09-08 11:49:43 -0700547void InputDispatcher::resetKeyRepeatLocked() {
548 if (mKeyRepeatState.lastKeyEntry) {
549 mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
550 mKeyRepeatState.lastKeyEntry = NULL;
551 }
552}
553
554InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(
Jeff Brownb21fb102010-09-07 10:44:57 -0700555 nsecs_t currentTime, nsecs_t keyRepeatDelay) {
Jeff Brown349703e2010-06-22 01:27:15 -0700556 KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
557
Jeff Brown349703e2010-06-22 01:27:15 -0700558 // Reuse the repeated key entry if it is otherwise unreferenced.
Jeff Brownb931a1b2010-10-11 14:20:19 -0700559 uint32_t policyFlags = (entry->policyFlags & POLICY_FLAG_RAW_MASK)
560 | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700561 if (entry->refCount == 1) {
Jeff Brown01ce2e92010-09-26 22:20:12 -0700562 mAllocator.recycleKeyEntry(entry);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700563 entry->eventTime = currentTime;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700564 entry->policyFlags = policyFlags;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700565 entry->repeatCount += 1;
566 } else {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700567 KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700568 entry->deviceId, entry->source, policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700569 entry->action, entry->flags, entry->keyCode, entry->scanCode,
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700570 entry->metaState, entry->repeatCount + 1, entry->downTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700571
572 mKeyRepeatState.lastKeyEntry = newEntry;
573 mAllocator.releaseKeyEntry(entry);
574
575 entry = newEntry;
576 }
Jeff Brownb88102f2010-09-08 11:49:43 -0700577 entry->syntheticRepeat = true;
578
579 // Increment reference count since we keep a reference to the event in
580 // mKeyRepeatState.lastKeyEntry in addition to the one we return.
581 entry->refCount += 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700582
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700583 if (entry->repeatCount == 1) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700584 entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700585 }
586
Jeff Brownb21fb102010-09-07 10:44:57 -0700587 mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatDelay;
Jeff Brownb88102f2010-09-08 11:49:43 -0700588 return entry;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700589}
590
Jeff Brownb88102f2010-09-08 11:49:43 -0700591bool InputDispatcher::dispatchConfigurationChangedLocked(
592 nsecs_t currentTime, ConfigurationChangedEntry* entry) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700593#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brownb88102f2010-09-08 11:49:43 -0700594 LOGD("dispatchConfigurationChanged - eventTime=%lld", entry->eventTime);
595#endif
596
597 // Reset key repeating in case a keyboard device was added or removed or something.
598 resetKeyRepeatLocked();
599
600 // Enqueue a command to run outside the lock to tell the policy that the configuration changed.
601 CommandEntry* commandEntry = postCommandLocked(
602 & InputDispatcher::doNotifyConfigurationChangedInterruptible);
603 commandEntry->eventTime = entry->eventTime;
604 return true;
605}
606
607bool InputDispatcher::dispatchKeyLocked(
608 nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
Jeff Brownb931a1b2010-10-11 14:20:19 -0700609 DropReason* dropReason, nsecs_t* nextWakeupTime) {
Jeff Brown54a18252010-09-16 14:07:33 -0700610 // Give the policy a chance to intercept the key.
611 if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
Jeff Brownb931a1b2010-10-11 14:20:19 -0700612 if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
Jeff Brown54a18252010-09-16 14:07:33 -0700613 CommandEntry* commandEntry = postCommandLocked(
614 & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
Jeff Brownb931a1b2010-10-11 14:20:19 -0700615 if (mFocusedWindow) {
Jeff Brown54a18252010-09-16 14:07:33 -0700616 commandEntry->inputChannel = mFocusedWindow->inputChannel;
617 }
618 commandEntry->keyEntry = entry;
619 entry->refCount += 1;
620 return false; // wait for the command to run
621 } else {
622 entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
623 }
624 } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
Jeff Brownb931a1b2010-10-11 14:20:19 -0700625 if (*dropReason == DROP_REASON_NOT_DROPPED) {
626 *dropReason = DROP_REASON_POLICY;
627 }
Jeff Brown54a18252010-09-16 14:07:33 -0700628 resetTargetsLocked();
629 setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_SUCCEEDED);
630 return true;
631 }
632
633 // Clean up if dropping the event.
Jeff Brownb931a1b2010-10-11 14:20:19 -0700634 if (*dropReason != DROP_REASON_NOT_DROPPED) {
Jeff Brown54a18252010-09-16 14:07:33 -0700635 resetTargetsLocked();
636 setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
637 return true;
638 }
639
Jeff Brownb88102f2010-09-08 11:49:43 -0700640 // Preprocessing.
641 if (! entry->dispatchInProgress) {
642 logOutboundKeyDetailsLocked("dispatchKey - ", entry);
643
644 if (entry->repeatCount == 0
645 && entry->action == AKEY_EVENT_ACTION_DOWN
Jeff Brownb931a1b2010-10-11 14:20:19 -0700646 && (entry->policyFlags & POLICY_FLAG_TRUSTED)
647 && !entry->isInjected()) {
Jeff Brownb88102f2010-09-08 11:49:43 -0700648 if (mKeyRepeatState.lastKeyEntry
649 && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
650 // We have seen two identical key downs in a row which indicates that the device
651 // driver is automatically generating key repeats itself. We take note of the
652 // repeat here, but we disable our own next key repeat timer since it is clear that
653 // we will not need to synthesize key repeats ourselves.
654 entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
655 resetKeyRepeatLocked();
656 mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
657 } else {
658 // Not a repeat. Save key down state in case we do see a repeat later.
659 resetKeyRepeatLocked();
660 mKeyRepeatState.nextRepeatTime = entry->eventTime + keyRepeatTimeout;
661 }
662 mKeyRepeatState.lastKeyEntry = entry;
663 entry->refCount += 1;
664 } else if (! entry->syntheticRepeat) {
665 resetKeyRepeatLocked();
666 }
667
668 entry->dispatchInProgress = true;
Jeff Brown54a18252010-09-16 14:07:33 -0700669 resetTargetsLocked();
Jeff Brownb88102f2010-09-08 11:49:43 -0700670 }
671
672 // Identify targets.
673 if (! mCurrentInputTargetsValid) {
Jeff Brown01ce2e92010-09-26 22:20:12 -0700674 int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
675 entry, nextWakeupTime);
Jeff Brownb88102f2010-09-08 11:49:43 -0700676 if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
677 return false;
678 }
679
680 setInjectionResultLocked(entry, injectionResult);
681 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
682 return true;
683 }
684
685 addMonitoringTargetsLocked();
Jeff Brown01ce2e92010-09-26 22:20:12 -0700686 commitTargetsLocked();
Jeff Brownb88102f2010-09-08 11:49:43 -0700687 }
688
689 // Dispatch the key.
690 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
691
692 // Poke user activity.
Jeff Brown01ce2e92010-09-26 22:20:12 -0700693 if (shouldPokeUserActivityForCurrentInputTargetsLocked()) {
694 pokeUserActivityLocked(entry->eventTime, POWER_MANAGER_BUTTON_EVENT);
695 }
Jeff Brownb88102f2010-09-08 11:49:43 -0700696 return true;
697}
698
699void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry) {
700#if DEBUG_OUTBOUND_EVENT_DETAILS
701 LOGD("%seventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
702 "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
703 "downTime=%lld",
704 prefix,
705 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
706 entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
707 entry->downTime);
708#endif
709}
710
711bool InputDispatcher::dispatchMotionLocked(
Jeff Brownb931a1b2010-10-11 14:20:19 -0700712 nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
Jeff Brown54a18252010-09-16 14:07:33 -0700713 // Clean up if dropping the event.
Jeff Brownb931a1b2010-10-11 14:20:19 -0700714 if (*dropReason != DROP_REASON_NOT_DROPPED) {
Jeff Brown54a18252010-09-16 14:07:33 -0700715 resetTargetsLocked();
716 setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
717 return true;
718 }
719
Jeff Brownb88102f2010-09-08 11:49:43 -0700720 // Preprocessing.
721 if (! entry->dispatchInProgress) {
722 logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
723
724 entry->dispatchInProgress = true;
Jeff Brown54a18252010-09-16 14:07:33 -0700725 resetTargetsLocked();
Jeff Brownb88102f2010-09-08 11:49:43 -0700726 }
727
728 bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
729
730 // Identify targets.
731 if (! mCurrentInputTargetsValid) {
Jeff Brownb88102f2010-09-08 11:49:43 -0700732 int32_t injectionResult;
733 if (isPointerEvent) {
734 // Pointer event. (eg. touchscreen)
Jeff Brown01ce2e92010-09-26 22:20:12 -0700735 injectionResult = findTouchedWindowTargetsLocked(currentTime,
736 entry, nextWakeupTime);
Jeff Brownb88102f2010-09-08 11:49:43 -0700737 } else {
738 // Non touch event. (eg. trackball)
Jeff Brown01ce2e92010-09-26 22:20:12 -0700739 injectionResult = findFocusedWindowTargetsLocked(currentTime,
740 entry, nextWakeupTime);
Jeff Brownb88102f2010-09-08 11:49:43 -0700741 }
742 if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
743 return false;
744 }
745
746 setInjectionResultLocked(entry, injectionResult);
747 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
748 return true;
749 }
750
751 addMonitoringTargetsLocked();
Jeff Brown01ce2e92010-09-26 22:20:12 -0700752 commitTargetsLocked();
Jeff Brownb88102f2010-09-08 11:49:43 -0700753 }
754
755 // Dispatch the motion.
756 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
757
758 // Poke user activity.
Jeff Brown01ce2e92010-09-26 22:20:12 -0700759 if (shouldPokeUserActivityForCurrentInputTargetsLocked()) {
760 int32_t eventType;
761 if (isPointerEvent) {
762 switch (entry->action) {
763 case AMOTION_EVENT_ACTION_DOWN:
Jeff Brownb88102f2010-09-08 11:49:43 -0700764 eventType = POWER_MANAGER_TOUCH_EVENT;
Jeff Brown01ce2e92010-09-26 22:20:12 -0700765 break;
766 case AMOTION_EVENT_ACTION_UP:
767 eventType = POWER_MANAGER_TOUCH_UP_EVENT;
768 break;
769 default:
770 if (entry->eventTime - entry->downTime >= EVENT_IGNORE_DURATION) {
771 eventType = POWER_MANAGER_TOUCH_EVENT;
772 } else {
773 eventType = POWER_MANAGER_LONG_TOUCH_EVENT;
774 }
775 break;
Jeff Brownb88102f2010-09-08 11:49:43 -0700776 }
Jeff Brown01ce2e92010-09-26 22:20:12 -0700777 } else {
778 eventType = POWER_MANAGER_BUTTON_EVENT;
Jeff Brownb88102f2010-09-08 11:49:43 -0700779 }
Jeff Brown01ce2e92010-09-26 22:20:12 -0700780 pokeUserActivityLocked(entry->eventTime, eventType);
Jeff Brownb88102f2010-09-08 11:49:43 -0700781 }
Jeff Brownb88102f2010-09-08 11:49:43 -0700782 return true;
783}
784
785
786void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) {
787#if DEBUG_OUTBOUND_EVENT_DETAILS
788 LOGD("%seventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Brown85a31762010-09-01 17:01:00 -0700789 "action=0x%x, flags=0x%x, "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700790 "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
Jeff Brownb88102f2010-09-08 11:49:43 -0700791 prefix,
Jeff Brown85a31762010-09-01 17:01:00 -0700792 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
793 entry->action, entry->flags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700794 entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
795 entry->downTime);
796
797 // Print the most recent sample that we have available, this may change due to batching.
798 size_t sampleCount = 1;
Jeff Brownb88102f2010-09-08 11:49:43 -0700799 const MotionSample* sample = & entry->firstSample;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700800 for (; sample->next != NULL; sample = sample->next) {
801 sampleCount += 1;
802 }
803 for (uint32_t i = 0; i < entry->pointerCount; i++) {
Jeff Brown8d608662010-08-30 03:02:23 -0700804 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
Jeff Brown85a31762010-09-01 17:01:00 -0700805 "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
Jeff Brown8d608662010-08-30 03:02:23 -0700806 "orientation=%f",
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700807 i, entry->pointerIds[i],
Jeff Brown8d608662010-08-30 03:02:23 -0700808 sample->pointerCoords[i].x, sample->pointerCoords[i].y,
809 sample->pointerCoords[i].pressure, sample->pointerCoords[i].size,
810 sample->pointerCoords[i].touchMajor, sample->pointerCoords[i].touchMinor,
811 sample->pointerCoords[i].toolMajor, sample->pointerCoords[i].toolMinor,
812 sample->pointerCoords[i].orientation);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700813 }
814
815 // Keep in mind that due to batching, it is possible for the number of samples actually
816 // dispatched to change before the application finally consumed them.
Jeff Brownc5ed5912010-07-14 18:48:53 -0700817 if (entry->action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700818 LOGD(" ... Total movement samples currently batched %d ...", sampleCount);
819 }
820#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700821}
822
823void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
824 EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
825#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700826 LOGD("dispatchEventToCurrentInputTargets - "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700827 "resumeWithAppendedMotionSample=%s",
Jeff Brownb88102f2010-09-08 11:49:43 -0700828 toString(resumeWithAppendedMotionSample));
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700829#endif
830
Jeff Brown9c3cda02010-06-15 01:31:58 -0700831 assert(eventEntry->dispatchInProgress); // should already have been set to true
832
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700833 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
834 const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
835
Jeff Brown519e0242010-09-15 15:18:56 -0700836 ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700837 if (connectionIndex >= 0) {
838 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700839 prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700840 resumeWithAppendedMotionSample);
841 } else {
Jeff Brownb6997262010-10-08 22:31:17 -0700842#if DEBUG_FOCUS
843 LOGD("Dropping event delivery to target with channel '%s' because it "
844 "is no longer registered with the input dispatcher.",
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700845 inputTarget.inputChannel->getName().string());
Jeff Brownb6997262010-10-08 22:31:17 -0700846#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700847 }
848 }
849}
850
Jeff Brown54a18252010-09-16 14:07:33 -0700851void InputDispatcher::resetTargetsLocked() {
Jeff Brownb88102f2010-09-08 11:49:43 -0700852 mCurrentInputTargetsValid = false;
853 mCurrentInputTargets.clear();
Jeff Brownb88102f2010-09-08 11:49:43 -0700854 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
855}
856
Jeff Brown01ce2e92010-09-26 22:20:12 -0700857void InputDispatcher::commitTargetsLocked() {
Jeff Brownb88102f2010-09-08 11:49:43 -0700858 mCurrentInputTargetsValid = true;
859}
860
861int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
862 const EventEntry* entry, const InputApplication* application, const InputWindow* window,
863 nsecs_t* nextWakeupTime) {
864 if (application == NULL && window == NULL) {
865 if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
866#if DEBUG_FOCUS
867 LOGD("Waiting for system to become ready for input.");
868#endif
869 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
870 mInputTargetWaitStartTime = currentTime;
871 mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
872 mInputTargetWaitTimeoutExpired = false;
873 }
874 } else {
875 if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
876#if DEBUG_FOCUS
Jeff Brown519e0242010-09-15 15:18:56 -0700877 LOGD("Waiting for application to become ready for input: %s",
878 getApplicationWindowLabelLocked(application, window).string());
Jeff Brownb88102f2010-09-08 11:49:43 -0700879#endif
880 nsecs_t timeout = window ? window->dispatchingTimeout :
881 application ? application->dispatchingTimeout : DEFAULT_INPUT_DISPATCHING_TIMEOUT;
882
883 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
884 mInputTargetWaitStartTime = currentTime;
885 mInputTargetWaitTimeoutTime = currentTime + timeout;
886 mInputTargetWaitTimeoutExpired = false;
887 }
888 }
889
890 if (mInputTargetWaitTimeoutExpired) {
891 return INPUT_EVENT_INJECTION_TIMED_OUT;
892 }
893
894 if (currentTime >= mInputTargetWaitTimeoutTime) {
Jeff Brown519e0242010-09-15 15:18:56 -0700895 onANRLocked(currentTime, application, window, entry->eventTime, mInputTargetWaitStartTime);
Jeff Brownb88102f2010-09-08 11:49:43 -0700896
897 // Force poll loop to wake up immediately on next iteration once we get the
898 // ANR response back from the policy.
899 *nextWakeupTime = LONG_LONG_MIN;
900 return INPUT_EVENT_INJECTION_PENDING;
901 } else {
902 // Force poll loop to wake up when timeout is due.
903 if (mInputTargetWaitTimeoutTime < *nextWakeupTime) {
904 *nextWakeupTime = mInputTargetWaitTimeoutTime;
905 }
906 return INPUT_EVENT_INJECTION_PENDING;
907 }
908}
909
Jeff Brown519e0242010-09-15 15:18:56 -0700910void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
911 const sp<InputChannel>& inputChannel) {
Jeff Brownb88102f2010-09-08 11:49:43 -0700912 if (newTimeout > 0) {
913 // Extend the timeout.
914 mInputTargetWaitTimeoutTime = now() + newTimeout;
915 } else {
916 // Give up.
917 mInputTargetWaitTimeoutExpired = true;
Jeff Brown519e0242010-09-15 15:18:56 -0700918
Jeff Brown01ce2e92010-09-26 22:20:12 -0700919 // Release the touch targets.
920 mTouchState.reset();
Jeff Brown2a95c2a2010-09-16 12:31:46 -0700921
Jeff Brown519e0242010-09-15 15:18:56 -0700922 // Input state will not be realistic. Mark it out of sync.
Jeff Browndc3e0052010-09-16 11:02:16 -0700923 if (inputChannel.get()) {
924 ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
925 if (connectionIndex >= 0) {
926 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brownb6997262010-10-08 22:31:17 -0700927 synthesizeCancelationEventsForConnectionLocked(
928 connection, InputState::CANCEL_ALL_EVENTS,
929 "application not responding");
Jeff Browndc3e0052010-09-16 11:02:16 -0700930 }
Jeff Brown519e0242010-09-15 15:18:56 -0700931 }
Jeff Brownb88102f2010-09-08 11:49:43 -0700932 }
933}
934
Jeff Brown519e0242010-09-15 15:18:56 -0700935nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(
Jeff Brownb88102f2010-09-08 11:49:43 -0700936 nsecs_t currentTime) {
937 if (mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
938 return currentTime - mInputTargetWaitStartTime;
939 }
940 return 0;
941}
942
943void InputDispatcher::resetANRTimeoutsLocked() {
944#if DEBUG_FOCUS
945 LOGD("Resetting ANR timeouts.");
946#endif
947
Jeff Brownb88102f2010-09-08 11:49:43 -0700948 // Reset input target wait timeout.
949 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
950}
951
Jeff Brown01ce2e92010-09-26 22:20:12 -0700952int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
953 const EventEntry* entry, nsecs_t* nextWakeupTime) {
Jeff Brownb88102f2010-09-08 11:49:43 -0700954 mCurrentInputTargets.clear();
955
956 int32_t injectionResult;
957
958 // If there is no currently focused window and no focused application
959 // then drop the event.
960 if (! mFocusedWindow) {
961 if (mFocusedApplication) {
962#if DEBUG_FOCUS
963 LOGD("Waiting because there is no focused window but there is a "
Jeff Brown519e0242010-09-15 15:18:56 -0700964 "focused application that may eventually add a window: %s.",
965 getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
Jeff Brownb88102f2010-09-08 11:49:43 -0700966#endif
967 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
968 mFocusedApplication, NULL, nextWakeupTime);
969 goto Unresponsive;
970 }
971
972 LOGI("Dropping event because there is no focused window or focused application.");
973 injectionResult = INPUT_EVENT_INJECTION_FAILED;
974 goto Failed;
975 }
976
977 // Check permissions.
Jeff Brown01ce2e92010-09-26 22:20:12 -0700978 if (! checkInjectionPermission(mFocusedWindow, entry->injectionState)) {
Jeff Brownb88102f2010-09-08 11:49:43 -0700979 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
980 goto Failed;
981 }
982
983 // If the currently focused window is paused then keep waiting.
984 if (mFocusedWindow->paused) {
985#if DEBUG_FOCUS
986 LOGD("Waiting because focused window is paused.");
987#endif
988 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
989 mFocusedApplication, mFocusedWindow, nextWakeupTime);
990 goto Unresponsive;
991 }
992
Jeff Brown519e0242010-09-15 15:18:56 -0700993 // If the currently focused window is still working on previous events then keep waiting.
994 if (! isWindowFinishedWithPreviousInputLocked(mFocusedWindow)) {
995#if DEBUG_FOCUS
996 LOGD("Waiting because focused window still processing previous input.");
997#endif
998 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
999 mFocusedApplication, mFocusedWindow, nextWakeupTime);
1000 goto Unresponsive;
1001 }
1002
Jeff Brownb88102f2010-09-08 11:49:43 -07001003 // Success! Output targets.
1004 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
Jeff Brown01ce2e92010-09-26 22:20:12 -07001005 addWindowTargetLocked(mFocusedWindow, InputTarget::FLAG_FOREGROUND, BitSet32(0));
Jeff Brownb88102f2010-09-08 11:49:43 -07001006
1007 // Done.
1008Failed:
1009Unresponsive:
Jeff Brown519e0242010-09-15 15:18:56 -07001010 nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
1011 updateDispatchStatisticsLocked(currentTime, entry,
1012 injectionResult, timeSpentWaitingForApplication);
Jeff Brownb88102f2010-09-08 11:49:43 -07001013#if DEBUG_FOCUS
Jeff Brown519e0242010-09-15 15:18:56 -07001014 LOGD("findFocusedWindow finished: injectionResult=%d, "
1015 "timeSpendWaitingForApplication=%0.1fms",
1016 injectionResult, timeSpentWaitingForApplication / 1000000.0);
Jeff Brownb88102f2010-09-08 11:49:43 -07001017#endif
1018 return injectionResult;
1019}
1020
Jeff Brown01ce2e92010-09-26 22:20:12 -07001021int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
1022 const MotionEntry* entry, nsecs_t* nextWakeupTime) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001023 enum InjectionPermission {
1024 INJECTION_PERMISSION_UNKNOWN,
1025 INJECTION_PERMISSION_GRANTED,
1026 INJECTION_PERMISSION_DENIED
1027 };
1028
Jeff Brownb88102f2010-09-08 11:49:43 -07001029 mCurrentInputTargets.clear();
1030
1031 nsecs_t startTime = now();
1032
1033 // For security reasons, we defer updating the touch state until we are sure that
1034 // event injection will be allowed.
1035 //
1036 // FIXME In the original code, screenWasOff could never be set to true.
1037 // The reason is that the POLICY_FLAG_WOKE_HERE
1038 // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
1039 // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
1040 // actually enqueued using the policyFlags that appeared in the final EV_SYN
1041 // events upon which no preprocessing took place. So policyFlags was always 0.
1042 // In the new native input dispatcher we're a bit more careful about event
1043 // preprocessing so the touches we receive can actually have non-zero policyFlags.
1044 // Unfortunately we obtain undesirable behavior.
1045 //
1046 // Here's what happens:
1047 //
1048 // When the device dims in anticipation of going to sleep, touches
1049 // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
1050 // the device to brighten and reset the user activity timer.
1051 // Touches on other windows (such as the launcher window)
1052 // are dropped. Then after a moment, the device goes to sleep. Oops.
1053 //
1054 // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
1055 // instead of POLICY_FLAG_WOKE_HERE...
1056 //
1057 bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
1058
1059 int32_t action = entry->action;
Jeff Brown01ce2e92010-09-26 22:20:12 -07001060 int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
Jeff Brownb88102f2010-09-08 11:49:43 -07001061
1062 // Update the touch state as needed based on the properties of the touch event.
Jeff Brown01ce2e92010-09-26 22:20:12 -07001063 int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING;
1064 InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
1065 if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
1066 mTempTouchState.reset();
1067 mTempTouchState.down = true;
1068 } else {
1069 mTempTouchState.copyFrom(mTouchState);
1070 }
Jeff Brownb88102f2010-09-08 11:49:43 -07001071
Jeff Brown01ce2e92010-09-26 22:20:12 -07001072 bool isSplit = mTempTouchState.split && mTempTouchState.down;
1073 if (maskedAction == AMOTION_EVENT_ACTION_DOWN
1074 || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
1075 /* Case 1: New splittable pointer going down. */
Jeff Brownb88102f2010-09-08 11:49:43 -07001076
Jeff Brown01ce2e92010-09-26 22:20:12 -07001077 int32_t pointerIndex = getMotionEventActionPointerIndex(action);
1078 int32_t x = int32_t(entry->firstSample.pointerCoords[pointerIndex].x);
1079 int32_t y = int32_t(entry->firstSample.pointerCoords[pointerIndex].y);
1080 const InputWindow* newTouchedWindow = NULL;
1081 const InputWindow* topErrorWindow = NULL;
Jeff Brownb88102f2010-09-08 11:49:43 -07001082
1083 // Traverse windows from front to back to find touched window and outside targets.
1084 size_t numWindows = mWindows.size();
1085 for (size_t i = 0; i < numWindows; i++) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07001086 const InputWindow* window = & mWindows.editItemAt(i);
Jeff Brownb88102f2010-09-08 11:49:43 -07001087 int32_t flags = window->layoutParamsFlags;
1088
1089 if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
1090 if (! topErrorWindow) {
1091 topErrorWindow = window;
1092 }
1093 }
1094
1095 if (window->visible) {
1096 if (! (flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
1097 bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
1098 | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
1099 if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
1100 if (! screenWasOff || flags & InputWindow::FLAG_TOUCHABLE_WHEN_WAKING) {
1101 newTouchedWindow = window;
Jeff Brownb88102f2010-09-08 11:49:43 -07001102 }
1103 break; // found touched window, exit window loop
1104 }
1105 }
1106
Jeff Brown01ce2e92010-09-26 22:20:12 -07001107 if (maskedAction == AMOTION_EVENT_ACTION_DOWN
1108 && (flags & InputWindow::FLAG_WATCH_OUTSIDE_TOUCH)) {
Jeff Brown19dfc832010-10-05 12:26:23 -07001109 int32_t outsideTargetFlags = InputTarget::FLAG_OUTSIDE;
1110 if (isWindowObscuredAtPointLocked(window, x, y)) {
1111 outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
1112 }
1113
1114 mTempTouchState.addOrUpdateWindow(window, outsideTargetFlags, BitSet32(0));
Jeff Brownb88102f2010-09-08 11:49:43 -07001115 }
1116 }
1117 }
1118
1119 // If there is an error window but it is not taking focus (typically because
1120 // it is invisible) then wait for it. Any other focused window may in
1121 // fact be in ANR state.
1122 if (topErrorWindow && newTouchedWindow != topErrorWindow) {
1123#if DEBUG_FOCUS
1124 LOGD("Waiting because system error window is pending.");
1125#endif
1126 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1127 NULL, NULL, nextWakeupTime);
1128 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
1129 goto Unresponsive;
1130 }
1131
Jeff Brown01ce2e92010-09-26 22:20:12 -07001132 // Figure out whether splitting will be allowed for this window.
Jeff Brownaeec2bf2010-09-28 13:24:41 -07001133 if (newTouchedWindow
1134 && (newTouchedWindow->layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH)) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07001135 // New window supports splitting.
1136 isSplit = true;
1137 } else if (isSplit) {
1138 // New window does not support splitting but we have already split events.
1139 // Assign the pointer to the first foreground window we find.
1140 // (May be NULL which is why we put this code block before the next check.)
1141 newTouchedWindow = mTempTouchState.getFirstForegroundWindow();
1142 }
Jeff Brown01ce2e92010-09-26 22:20:12 -07001143
Jeff Brownb88102f2010-09-08 11:49:43 -07001144 // If we did not find a touched window then fail.
1145 if (! newTouchedWindow) {
1146 if (mFocusedApplication) {
1147#if DEBUG_FOCUS
1148 LOGD("Waiting because there is no touched window but there is a "
Jeff Brown519e0242010-09-15 15:18:56 -07001149 "focused application that may eventually add a new window: %s.",
1150 getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
Jeff Brownb88102f2010-09-08 11:49:43 -07001151#endif
1152 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1153 mFocusedApplication, NULL, nextWakeupTime);
Jeff Brownb88102f2010-09-08 11:49:43 -07001154 goto Unresponsive;
1155 }
1156
1157 LOGI("Dropping event because there is no touched window or focused application.");
1158 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownb88102f2010-09-08 11:49:43 -07001159 goto Failed;
1160 }
1161
Jeff Brown19dfc832010-10-05 12:26:23 -07001162 // Set target flags.
1163 int32_t targetFlags = InputTarget::FLAG_FOREGROUND;
1164 if (isSplit) {
1165 targetFlags |= InputTarget::FLAG_SPLIT;
1166 }
1167 if (isWindowObscuredAtPointLocked(newTouchedWindow, x, y)) {
1168 targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
1169 }
1170
Jeff Brown01ce2e92010-09-26 22:20:12 -07001171 // Update the temporary touch state.
1172 BitSet32 pointerIds;
1173 if (isSplit) {
1174 uint32_t pointerId = entry->pointerIds[pointerIndex];
1175 pointerIds.markBit(pointerId);
Jeff Brownb88102f2010-09-08 11:49:43 -07001176 }
Jeff Brown01ce2e92010-09-26 22:20:12 -07001177 mTempTouchState.addOrUpdateWindow(newTouchedWindow, targetFlags, pointerIds);
Jeff Brownb88102f2010-09-08 11:49:43 -07001178 } else {
Jeff Brown01ce2e92010-09-26 22:20:12 -07001179 /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */
Jeff Brownb88102f2010-09-08 11:49:43 -07001180
1181 // If the pointer is not currently down, then ignore the event.
Jeff Brown01ce2e92010-09-26 22:20:12 -07001182 if (! mTempTouchState.down) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001183 LOGI("Dropping event because the pointer is not down.");
1184 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownb88102f2010-09-08 11:49:43 -07001185 goto Failed;
1186 }
Jeff Brown01ce2e92010-09-26 22:20:12 -07001187 }
Jeff Brownb88102f2010-09-08 11:49:43 -07001188
Jeff Brown01ce2e92010-09-26 22:20:12 -07001189 // Check permission to inject into all touched foreground windows and ensure there
1190 // is at least one touched foreground window.
1191 {
1192 bool haveForegroundWindow = false;
1193 for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
1194 const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
1195 if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
1196 haveForegroundWindow = true;
1197 if (! checkInjectionPermission(touchedWindow.window, entry->injectionState)) {
1198 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1199 injectionPermission = INJECTION_PERMISSION_DENIED;
1200 goto Failed;
1201 }
1202 }
1203 }
1204 if (! haveForegroundWindow) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001205#if DEBUG_INPUT_DISPATCHER_POLICY
Jeff Brown01ce2e92010-09-26 22:20:12 -07001206 LOGD("Dropping event because there is no touched foreground window to receive it.");
Jeff Brownb88102f2010-09-08 11:49:43 -07001207#endif
1208 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownb88102f2010-09-08 11:49:43 -07001209 goto Failed;
1210 }
1211
Jeff Brown01ce2e92010-09-26 22:20:12 -07001212 // Permission granted to injection into all touched foreground windows.
1213 injectionPermission = INJECTION_PERMISSION_GRANTED;
1214 }
Jeff Brown519e0242010-09-15 15:18:56 -07001215
Jeff Brown01ce2e92010-09-26 22:20:12 -07001216 // Ensure all touched foreground windows are ready for new input.
1217 for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
1218 const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
1219 if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
1220 // If the touched window is paused then keep waiting.
1221 if (touchedWindow.window->paused) {
1222#if DEBUG_INPUT_DISPATCHER_POLICY
1223 LOGD("Waiting because touched window is paused.");
Jeff Brown519e0242010-09-15 15:18:56 -07001224#endif
Jeff Brown01ce2e92010-09-26 22:20:12 -07001225 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1226 NULL, touchedWindow.window, nextWakeupTime);
1227 goto Unresponsive;
1228 }
1229
1230 // If the touched window is still working on previous events then keep waiting.
1231 if (! isWindowFinishedWithPreviousInputLocked(touchedWindow.window)) {
1232#if DEBUG_FOCUS
1233 LOGD("Waiting because touched window still processing previous input.");
1234#endif
1235 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1236 NULL, touchedWindow.window, nextWakeupTime);
1237 goto Unresponsive;
1238 }
1239 }
1240 }
1241
1242 // If this is the first pointer going down and the touched window has a wallpaper
1243 // then also add the touched wallpaper windows so they are locked in for the duration
1244 // of the touch gesture.
1245 if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
1246 const InputWindow* foregroundWindow = mTempTouchState.getFirstForegroundWindow();
1247 if (foregroundWindow->hasWallpaper) {
1248 for (size_t i = 0; i < mWindows.size(); i++) {
1249 const InputWindow* window = & mWindows[i];
1250 if (window->layoutParamsType == InputWindow::TYPE_WALLPAPER) {
Jeff Brown19dfc832010-10-05 12:26:23 -07001251 mTempTouchState.addOrUpdateWindow(window,
1252 InputTarget::FLAG_WINDOW_IS_OBSCURED, BitSet32(0));
Jeff Brown01ce2e92010-09-26 22:20:12 -07001253 }
1254 }
1255 }
1256 }
1257
Jeff Brownb88102f2010-09-08 11:49:43 -07001258 // Success! Output targets.
1259 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
Jeff Brownb88102f2010-09-08 11:49:43 -07001260
Jeff Brown01ce2e92010-09-26 22:20:12 -07001261 for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
1262 const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
1263 addWindowTargetLocked(touchedWindow.window, touchedWindow.targetFlags,
1264 touchedWindow.pointerIds);
Jeff Brownb88102f2010-09-08 11:49:43 -07001265 }
1266
Jeff Brown01ce2e92010-09-26 22:20:12 -07001267 // Drop the outside touch window since we will not care about them in the next iteration.
1268 mTempTouchState.removeOutsideTouchWindows();
1269
Jeff Brownb88102f2010-09-08 11:49:43 -07001270Failed:
1271 // Check injection permission once and for all.
1272 if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07001273 if (checkInjectionPermission(NULL, entry->injectionState)) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001274 injectionPermission = INJECTION_PERMISSION_GRANTED;
1275 } else {
1276 injectionPermission = INJECTION_PERMISSION_DENIED;
1277 }
1278 }
1279
1280 // Update final pieces of touch state if the injector had permission.
1281 if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07001282 if (maskedAction == AMOTION_EVENT_ACTION_UP
1283 || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
1284 // All pointers up or canceled.
1285 mTempTouchState.reset();
1286 } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
1287 // First pointer went down.
1288 if (mTouchState.down) {
Jeff Brownb6997262010-10-08 22:31:17 -07001289#if DEBUG_FOCUS
1290 LOGD("Pointer down received while already down.");
1291#endif
Jeff Brownb88102f2010-09-08 11:49:43 -07001292 }
Jeff Brown01ce2e92010-09-26 22:20:12 -07001293 } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
1294 // One pointer went up.
1295 if (isSplit) {
1296 int32_t pointerIndex = getMotionEventActionPointerIndex(action);
1297 uint32_t pointerId = entry->pointerIds[pointerIndex];
Jeff Brownb88102f2010-09-08 11:49:43 -07001298
Jeff Brown01ce2e92010-09-26 22:20:12 -07001299 for (size_t i = 0; i < mTempTouchState.windows.size(); ) {
1300 TouchedWindow& touchedWindow = mTempTouchState.windows.editItemAt(i);
1301 if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
1302 touchedWindow.pointerIds.clearBit(pointerId);
1303 if (touchedWindow.pointerIds.isEmpty()) {
1304 mTempTouchState.windows.removeAt(i);
1305 continue;
1306 }
1307 }
1308 i += 1;
1309 }
Jeff Brownb88102f2010-09-08 11:49:43 -07001310 }
Jeff Brownb88102f2010-09-08 11:49:43 -07001311 }
Jeff Brown01ce2e92010-09-26 22:20:12 -07001312
1313 // Save changes to touch state.
1314 mTouchState.copyFrom(mTempTouchState);
Jeff Brownb88102f2010-09-08 11:49:43 -07001315 } else {
Jeff Brown01ce2e92010-09-26 22:20:12 -07001316#if DEBUG_FOCUS
1317 LOGD("Not updating touch focus because injection was denied.");
1318#endif
Jeff Brownb88102f2010-09-08 11:49:43 -07001319 }
1320
1321Unresponsive:
Jeff Brown519e0242010-09-15 15:18:56 -07001322 nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
1323 updateDispatchStatisticsLocked(currentTime, entry,
1324 injectionResult, timeSpentWaitingForApplication);
Jeff Brownb88102f2010-09-08 11:49:43 -07001325#if DEBUG_FOCUS
Jeff Brown01ce2e92010-09-26 22:20:12 -07001326 LOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d, "
1327 "timeSpentWaitingForApplication=%0.1fms",
Jeff Brown519e0242010-09-15 15:18:56 -07001328 injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0);
Jeff Brownb88102f2010-09-08 11:49:43 -07001329#endif
1330 return injectionResult;
1331}
1332
Jeff Brown01ce2e92010-09-26 22:20:12 -07001333void InputDispatcher::addWindowTargetLocked(const InputWindow* window, int32_t targetFlags,
1334 BitSet32 pointerIds) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001335 mCurrentInputTargets.push();
1336
1337 InputTarget& target = mCurrentInputTargets.editTop();
1338 target.inputChannel = window->inputChannel;
1339 target.flags = targetFlags;
Jeff Brownb88102f2010-09-08 11:49:43 -07001340 target.xOffset = - window->frameLeft;
1341 target.yOffset = - window->frameTop;
Jeff Brown01ce2e92010-09-26 22:20:12 -07001342 target.windowType = window->layoutParamsType;
1343 target.pointerIds = pointerIds;
Jeff Brownb88102f2010-09-08 11:49:43 -07001344}
1345
1346void InputDispatcher::addMonitoringTargetsLocked() {
1347 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
1348 mCurrentInputTargets.push();
1349
1350 InputTarget& target = mCurrentInputTargets.editTop();
1351 target.inputChannel = mMonitoringChannels[i];
1352 target.flags = 0;
Jeff Brownb88102f2010-09-08 11:49:43 -07001353 target.xOffset = 0;
1354 target.yOffset = 0;
Jeff Brown01ce2e92010-09-26 22:20:12 -07001355 target.windowType = InputWindow::TYPE_SYSTEM_OVERLAY;
Jeff Brownb88102f2010-09-08 11:49:43 -07001356 }
1357}
1358
1359bool InputDispatcher::checkInjectionPermission(const InputWindow* window,
Jeff Brown01ce2e92010-09-26 22:20:12 -07001360 const InjectionState* injectionState) {
1361 if (injectionState
Jeff Brownb6997262010-10-08 22:31:17 -07001362 && (window == NULL || window->ownerUid != injectionState->injectorUid)
1363 && !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
1364 if (window) {
1365 LOGW("Permission denied: injecting event from pid %d uid %d to window "
1366 "with input channel %s owned by uid %d",
1367 injectionState->injectorPid, injectionState->injectorUid,
1368 window->inputChannel->getName().string(),
1369 window->ownerUid);
1370 } else {
1371 LOGW("Permission denied: injecting event from pid %d uid %d",
1372 injectionState->injectorPid, injectionState->injectorUid);
Jeff Brownb88102f2010-09-08 11:49:43 -07001373 }
Jeff Brownb6997262010-10-08 22:31:17 -07001374 return false;
Jeff Brownb88102f2010-09-08 11:49:43 -07001375 }
1376 return true;
1377}
1378
Jeff Brown19dfc832010-10-05 12:26:23 -07001379bool InputDispatcher::isWindowObscuredAtPointLocked(
1380 const InputWindow* window, int32_t x, int32_t y) const {
Jeff Brownb88102f2010-09-08 11:49:43 -07001381 size_t numWindows = mWindows.size();
1382 for (size_t i = 0; i < numWindows; i++) {
1383 const InputWindow* other = & mWindows.itemAt(i);
1384 if (other == window) {
1385 break;
1386 }
Jeff Brown19dfc832010-10-05 12:26:23 -07001387 if (other->visible && ! other->isTrustedOverlay() && other->frameContainsPoint(x, y)) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001388 return true;
1389 }
1390 }
1391 return false;
1392}
1393
Jeff Brown519e0242010-09-15 15:18:56 -07001394bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(const InputWindow* window) {
1395 ssize_t connectionIndex = getConnectionIndexLocked(window->inputChannel);
1396 if (connectionIndex >= 0) {
1397 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1398 return connection->outboundQueue.isEmpty();
1399 } else {
1400 return true;
1401 }
1402}
1403
1404String8 InputDispatcher::getApplicationWindowLabelLocked(const InputApplication* application,
1405 const InputWindow* window) {
1406 if (application) {
1407 if (window) {
1408 String8 label(application->name);
1409 label.append(" - ");
1410 label.append(window->name);
1411 return label;
1412 } else {
1413 return application->name;
1414 }
1415 } else if (window) {
1416 return window->name;
1417 } else {
1418 return String8("<unknown application or window>");
1419 }
1420}
1421
Jeff Brown01ce2e92010-09-26 22:20:12 -07001422bool InputDispatcher::shouldPokeUserActivityForCurrentInputTargetsLocked() {
1423 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
1424 if (mCurrentInputTargets[i].windowType == InputWindow::TYPE_KEYGUARD) {
1425 return false;
1426 }
1427 }
1428 return true;
1429}
1430
1431void InputDispatcher::pokeUserActivityLocked(nsecs_t eventTime, int32_t eventType) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001432 CommandEntry* commandEntry = postCommandLocked(
1433 & InputDispatcher::doPokeUserActivityLockedInterruptible);
1434 commandEntry->eventTime = eventTime;
Jeff Brownb88102f2010-09-08 11:49:43 -07001435 commandEntry->userActivityEventType = eventType;
1436}
1437
Jeff Brown7fbdc842010-06-17 20:52:56 -07001438void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
1439 const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001440 bool resumeWithAppendedMotionSample) {
1441#if DEBUG_DISPATCH_CYCLE
Jeff Brown519e0242010-09-15 15:18:56 -07001442 LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, "
Jeff Brown01ce2e92010-09-26 22:20:12 -07001443 "xOffset=%f, yOffset=%f, "
1444 "windowType=%d, pointerIds=0x%x, "
1445 "resumeWithAppendedMotionSample=%s",
Jeff Brown519e0242010-09-15 15:18:56 -07001446 connection->getInputChannelName(), inputTarget->flags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001447 inputTarget->xOffset, inputTarget->yOffset,
Jeff Brown01ce2e92010-09-26 22:20:12 -07001448 inputTarget->windowType, inputTarget->pointerIds.value,
Jeff Brownb88102f2010-09-08 11:49:43 -07001449 toString(resumeWithAppendedMotionSample));
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001450#endif
1451
Jeff Brown01ce2e92010-09-26 22:20:12 -07001452 // Make sure we are never called for streaming when splitting across multiple windows.
1453 bool isSplit = inputTarget->flags & InputTarget::FLAG_SPLIT;
1454 assert(! (resumeWithAppendedMotionSample && isSplit));
1455
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001456 // Skip this event if the connection status is not normal.
Jeff Brown519e0242010-09-15 15:18:56 -07001457 // We don't want to enqueue additional outbound events if the connection is broken.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001458 if (connection->status != Connection::STATUS_NORMAL) {
Jeff Brownb6997262010-10-08 22:31:17 -07001459#if DEBUG_DISPATCH_CYCLE
1460 LOGD("channel '%s' ~ Dropping event because the channel status is %s",
Jeff Brownb88102f2010-09-08 11:49:43 -07001461 connection->getInputChannelName(), connection->getStatusLabel());
Jeff Brownb6997262010-10-08 22:31:17 -07001462#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001463 return;
1464 }
1465
Jeff Brown01ce2e92010-09-26 22:20:12 -07001466 // Split a motion event if needed.
1467 if (isSplit) {
1468 assert(eventEntry->type == EventEntry::TYPE_MOTION);
1469
1470 MotionEntry* originalMotionEntry = static_cast<MotionEntry*>(eventEntry);
1471 if (inputTarget->pointerIds.count() != originalMotionEntry->pointerCount) {
1472 MotionEntry* splitMotionEntry = splitMotionEvent(
1473 originalMotionEntry, inputTarget->pointerIds);
1474#if DEBUG_FOCUS
1475 LOGD("channel '%s' ~ Split motion event.",
1476 connection->getInputChannelName());
1477 logOutboundMotionDetailsLocked(" ", splitMotionEntry);
1478#endif
1479 eventEntry = splitMotionEntry;
1480 }
1481 }
1482
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001483 // Resume the dispatch cycle with a freshly appended motion sample.
1484 // First we check that the last dispatch entry in the outbound queue is for the same
1485 // motion event to which we appended the motion sample. If we find such a dispatch
1486 // entry, and if it is currently in progress then we try to stream the new sample.
1487 bool wasEmpty = connection->outboundQueue.isEmpty();
1488
1489 if (! wasEmpty && resumeWithAppendedMotionSample) {
1490 DispatchEntry* motionEventDispatchEntry =
1491 connection->findQueuedDispatchEntryForEvent(eventEntry);
1492 if (motionEventDispatchEntry) {
1493 // If the dispatch entry is not in progress, then we must be busy dispatching an
1494 // earlier event. Not a problem, the motion event is on the outbound queue and will
1495 // be dispatched later.
1496 if (! motionEventDispatchEntry->inProgress) {
1497#if DEBUG_BATCHING
1498 LOGD("channel '%s' ~ Not streaming because the motion event has "
1499 "not yet been dispatched. "
1500 "(Waiting for earlier events to be consumed.)",
1501 connection->getInputChannelName());
1502#endif
1503 return;
1504 }
1505
1506 // If the dispatch entry is in progress but it already has a tail of pending
1507 // motion samples, then it must mean that the shared memory buffer filled up.
1508 // Not a problem, when this dispatch cycle is finished, we will eventually start
1509 // a new dispatch cycle to process the tail and that tail includes the newly
1510 // appended motion sample.
1511 if (motionEventDispatchEntry->tailMotionSample) {
1512#if DEBUG_BATCHING
1513 LOGD("channel '%s' ~ Not streaming because no new samples can "
1514 "be appended to the motion event in this dispatch cycle. "
1515 "(Waiting for next dispatch cycle to start.)",
1516 connection->getInputChannelName());
1517#endif
1518 return;
1519 }
1520
1521 // The dispatch entry is in progress and is still potentially open for streaming.
1522 // Try to stream the new motion sample. This might fail if the consumer has already
1523 // consumed the motion event (or if the channel is broken).
Jeff Brown01ce2e92010-09-26 22:20:12 -07001524 MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
1525 MotionSample* appendedMotionSample = motionEntry->lastSample;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001526 status_t status = connection->inputPublisher.appendMotionSample(
1527 appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
1528 if (status == OK) {
1529#if DEBUG_BATCHING
1530 LOGD("channel '%s' ~ Successfully streamed new motion sample.",
1531 connection->getInputChannelName());
1532#endif
1533 return;
1534 }
1535
1536#if DEBUG_BATCHING
1537 if (status == NO_MEMORY) {
1538 LOGD("channel '%s' ~ Could not append motion sample to currently "
1539 "dispatched move event because the shared memory buffer is full. "
1540 "(Waiting for next dispatch cycle to start.)",
1541 connection->getInputChannelName());
1542 } else if (status == status_t(FAILED_TRANSACTION)) {
1543 LOGD("channel '%s' ~ Could not append motion sample to currently "
Jeff Brown349703e2010-06-22 01:27:15 -07001544 "dispatched move event because the event has already been consumed. "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001545 "(Waiting for next dispatch cycle to start.)",
1546 connection->getInputChannelName());
1547 } else {
1548 LOGD("channel '%s' ~ Could not append motion sample to currently "
1549 "dispatched move event due to an error, status=%d. "
1550 "(Waiting for next dispatch cycle to start.)",
1551 connection->getInputChannelName(), status);
1552 }
1553#endif
1554 // Failed to stream. Start a new tail of pending motion samples to dispatch
1555 // in the next cycle.
1556 motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
1557 return;
1558 }
1559 }
1560
1561 // This is a new event.
1562 // Enqueue a new dispatch entry onto the outbound queue for this connection.
Jeff Brownb88102f2010-09-08 11:49:43 -07001563 DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry, // increments ref
Jeff Brown519e0242010-09-15 15:18:56 -07001564 inputTarget->flags, inputTarget->xOffset, inputTarget->yOffset);
1565 if (dispatchEntry->hasForegroundTarget()) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07001566 incrementPendingForegroundDispatchesLocked(eventEntry);
Jeff Brown6ec402b2010-07-28 15:48:59 -07001567 }
1568
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001569 // Handle the case where we could not stream a new motion sample because the consumer has
1570 // already consumed the motion event (otherwise the corresponding dispatch entry would
1571 // still be in the outbound queue for this connection). We set the head motion sample
1572 // to the list starting with the newly appended motion sample.
1573 if (resumeWithAppendedMotionSample) {
1574#if DEBUG_BATCHING
1575 LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
1576 "that cannot be streamed because the motion event has already been consumed.",
1577 connection->getInputChannelName());
1578#endif
1579 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
1580 dispatchEntry->headMotionSample = appendedMotionSample;
1581 }
1582
1583 // Enqueue the dispatch entry.
1584 connection->outboundQueue.enqueueAtTail(dispatchEntry);
1585
1586 // If the outbound queue was previously empty, start the dispatch cycle going.
1587 if (wasEmpty) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001588 activateConnectionLocked(connection.get());
Jeff Brown519e0242010-09-15 15:18:56 -07001589 startDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001590 }
1591}
1592
Jeff Brown7fbdc842010-06-17 20:52:56 -07001593void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
Jeff Brown519e0242010-09-15 15:18:56 -07001594 const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001595#if DEBUG_DISPATCH_CYCLE
1596 LOGD("channel '%s' ~ startDispatchCycle",
1597 connection->getInputChannelName());
1598#endif
1599
1600 assert(connection->status == Connection::STATUS_NORMAL);
1601 assert(! connection->outboundQueue.isEmpty());
1602
Jeff Brownb88102f2010-09-08 11:49:43 -07001603 DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001604 assert(! dispatchEntry->inProgress);
1605
Jeff Brownb88102f2010-09-08 11:49:43 -07001606 // Mark the dispatch entry as in progress.
1607 dispatchEntry->inProgress = true;
1608
1609 // Update the connection's input state.
Jeff Brown01ce2e92010-09-26 22:20:12 -07001610 EventEntry* eventEntry = dispatchEntry->eventEntry;
1611 InputState::Consistency consistency = connection->inputState.trackEvent(eventEntry);
Jeff Brownb88102f2010-09-08 11:49:43 -07001612
1613#if FILTER_INPUT_EVENTS
1614 // Filter out inconsistent sequences of input events.
1615 // The input system may drop or inject events in a way that could violate implicit
1616 // invariants on input state and potentially cause an application to crash
1617 // or think that a key or pointer is stuck down. Technically we make no guarantees
1618 // of consistency but it would be nice to improve on this where possible.
1619 // XXX: This code is a proof of concept only. Not ready for prime time.
1620 if (consistency == InputState::TOLERABLE) {
1621#if DEBUG_DISPATCH_CYCLE
1622 LOGD("channel '%s' ~ Sending an event that is inconsistent with the connection's "
1623 "current input state but that is likely to be tolerated by the application.",
1624 connection->getInputChannelName());
1625#endif
1626 } else if (consistency == InputState::BROKEN) {
1627 LOGI("channel '%s' ~ Dropping an event that is inconsistent with the connection's "
1628 "current input state and that is likely to cause the application to crash.",
1629 connection->getInputChannelName());
1630 startNextDispatchCycleLocked(currentTime, connection);
1631 return;
1632 }
1633#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001634
1635 // Publish the event.
1636 status_t status;
Jeff Brown01ce2e92010-09-26 22:20:12 -07001637 switch (eventEntry->type) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001638 case EventEntry::TYPE_KEY: {
Jeff Brown01ce2e92010-09-26 22:20:12 -07001639 KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001640
1641 // Apply target flags.
1642 int32_t action = keyEntry->action;
1643 int32_t flags = keyEntry->flags;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001644
1645 // Publish the key event.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001646 status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001647 action, flags, keyEntry->keyCode, keyEntry->scanCode,
1648 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
1649 keyEntry->eventTime);
1650
1651 if (status) {
1652 LOGE("channel '%s' ~ Could not publish key event, "
1653 "status=%d", connection->getInputChannelName(), status);
Jeff Brownb6997262010-10-08 22:31:17 -07001654 abortBrokenDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001655 return;
1656 }
1657 break;
1658 }
1659
1660 case EventEntry::TYPE_MOTION: {
Jeff Brown01ce2e92010-09-26 22:20:12 -07001661 MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001662
1663 // Apply target flags.
1664 int32_t action = motionEntry->action;
Jeff Brown85a31762010-09-01 17:01:00 -07001665 int32_t flags = motionEntry->flags;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001666 if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001667 action = AMOTION_EVENT_ACTION_OUTSIDE;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001668 }
Jeff Brown85a31762010-09-01 17:01:00 -07001669 if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
1670 flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
1671 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001672
1673 // If headMotionSample is non-NULL, then it points to the first new sample that we
1674 // were unable to dispatch during the previous cycle so we resume dispatching from
1675 // that point in the list of motion samples.
1676 // Otherwise, we just start from the first sample of the motion event.
1677 MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
1678 if (! firstMotionSample) {
1679 firstMotionSample = & motionEntry->firstSample;
1680 }
1681
Jeff Brownd3616592010-07-16 17:21:06 -07001682 // Set the X and Y offset depending on the input source.
1683 float xOffset, yOffset;
1684 if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
1685 xOffset = dispatchEntry->xOffset;
1686 yOffset = dispatchEntry->yOffset;
1687 } else {
1688 xOffset = 0.0f;
1689 yOffset = 0.0f;
1690 }
1691
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001692 // Publish the motion event and the first motion sample.
1693 status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
Jeff Brown85a31762010-09-01 17:01:00 -07001694 motionEntry->source, action, flags, motionEntry->edgeFlags, motionEntry->metaState,
Jeff Brownd3616592010-07-16 17:21:06 -07001695 xOffset, yOffset,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001696 motionEntry->xPrecision, motionEntry->yPrecision,
1697 motionEntry->downTime, firstMotionSample->eventTime,
1698 motionEntry->pointerCount, motionEntry->pointerIds,
1699 firstMotionSample->pointerCoords);
1700
1701 if (status) {
1702 LOGE("channel '%s' ~ Could not publish motion event, "
1703 "status=%d", connection->getInputChannelName(), status);
Jeff Brownb6997262010-10-08 22:31:17 -07001704 abortBrokenDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001705 return;
1706 }
1707
1708 // Append additional motion samples.
1709 MotionSample* nextMotionSample = firstMotionSample->next;
1710 for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
1711 status = connection->inputPublisher.appendMotionSample(
1712 nextMotionSample->eventTime, nextMotionSample->pointerCoords);
1713 if (status == NO_MEMORY) {
1714#if DEBUG_DISPATCH_CYCLE
1715 LOGD("channel '%s' ~ Shared memory buffer full. Some motion samples will "
1716 "be sent in the next dispatch cycle.",
1717 connection->getInputChannelName());
1718#endif
1719 break;
1720 }
1721 if (status != OK) {
1722 LOGE("channel '%s' ~ Could not append motion sample "
1723 "for a reason other than out of memory, status=%d",
1724 connection->getInputChannelName(), status);
Jeff Brownb6997262010-10-08 22:31:17 -07001725 abortBrokenDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001726 return;
1727 }
1728 }
1729
1730 // Remember the next motion sample that we could not dispatch, in case we ran out
1731 // of space in the shared memory buffer.
1732 dispatchEntry->tailMotionSample = nextMotionSample;
1733 break;
1734 }
1735
1736 default: {
1737 assert(false);
1738 }
1739 }
1740
1741 // Send the dispatch signal.
1742 status = connection->inputPublisher.sendDispatchSignal();
1743 if (status) {
1744 LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
1745 connection->getInputChannelName(), status);
Jeff Brownb6997262010-10-08 22:31:17 -07001746 abortBrokenDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001747 return;
1748 }
1749
1750 // Record information about the newly started dispatch cycle.
Jeff Brown01ce2e92010-09-26 22:20:12 -07001751 connection->lastEventTime = eventEntry->eventTime;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001752 connection->lastDispatchTime = currentTime;
1753
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001754 // Notify other system components.
1755 onDispatchCycleStartedLocked(currentTime, connection);
1756}
1757
Jeff Brown7fbdc842010-06-17 20:52:56 -07001758void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
1759 const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001760#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -07001761 LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001762 "%01.1fms since dispatch",
1763 connection->getInputChannelName(),
1764 connection->getEventLatencyMillis(currentTime),
1765 connection->getDispatchLatencyMillis(currentTime));
1766#endif
1767
Jeff Brown9c3cda02010-06-15 01:31:58 -07001768 if (connection->status == Connection::STATUS_BROKEN
1769 || connection->status == Connection::STATUS_ZOMBIE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001770 return;
1771 }
1772
Jeff Brown519e0242010-09-15 15:18:56 -07001773 // Notify other system components.
1774 onDispatchCycleFinishedLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001775
1776 // Reset the publisher since the event has been consumed.
1777 // We do this now so that the publisher can release some of its internal resources
1778 // while waiting for the next dispatch cycle to begin.
1779 status_t status = connection->inputPublisher.reset();
1780 if (status) {
1781 LOGE("channel '%s' ~ Could not reset publisher, status=%d",
1782 connection->getInputChannelName(), status);
Jeff Brownb6997262010-10-08 22:31:17 -07001783 abortBrokenDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001784 return;
1785 }
1786
Jeff Brownb88102f2010-09-08 11:49:43 -07001787 startNextDispatchCycleLocked(currentTime, connection);
1788}
1789
1790void InputDispatcher::startNextDispatchCycleLocked(nsecs_t currentTime,
1791 const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001792 // Start the next dispatch cycle for this connection.
1793 while (! connection->outboundQueue.isEmpty()) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001794 DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001795 if (dispatchEntry->inProgress) {
1796 // Finish or resume current event in progress.
1797 if (dispatchEntry->tailMotionSample) {
1798 // We have a tail of undispatched motion samples.
1799 // Reuse the same DispatchEntry and start a new cycle.
1800 dispatchEntry->inProgress = false;
1801 dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
1802 dispatchEntry->tailMotionSample = NULL;
Jeff Brown519e0242010-09-15 15:18:56 -07001803 startDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001804 return;
1805 }
1806 // Finished.
1807 connection->outboundQueue.dequeueAtHead();
Jeff Brown519e0242010-09-15 15:18:56 -07001808 if (dispatchEntry->hasForegroundTarget()) {
1809 decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
Jeff Brown6ec402b2010-07-28 15:48:59 -07001810 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001811 mAllocator.releaseDispatchEntry(dispatchEntry);
1812 } else {
1813 // If the head is not in progress, then we must have already dequeued the in
Jeff Brown519e0242010-09-15 15:18:56 -07001814 // progress event, which means we actually aborted it.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001815 // So just start the next event for this connection.
Jeff Brown519e0242010-09-15 15:18:56 -07001816 startDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001817 return;
1818 }
1819 }
1820
1821 // Outbound queue is empty, deactivate the connection.
Jeff Brown7fbdc842010-06-17 20:52:56 -07001822 deactivateConnectionLocked(connection.get());
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001823}
1824
Jeff Brownb6997262010-10-08 22:31:17 -07001825void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
1826 const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001827#if DEBUG_DISPATCH_CYCLE
Jeff Brownb6997262010-10-08 22:31:17 -07001828 LOGD("channel '%s' ~ abortBrokenDispatchCycle - broken=%s",
Jeff Brownb88102f2010-09-08 11:49:43 -07001829 connection->getInputChannelName(), toString(broken));
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001830#endif
1831
Jeff Brownb88102f2010-09-08 11:49:43 -07001832 // Clear the outbound queue.
Jeff Brown519e0242010-09-15 15:18:56 -07001833 drainOutboundQueueLocked(connection.get());
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001834
Jeff Brownb6997262010-10-08 22:31:17 -07001835 // The connection appears to be unrecoverably broken.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001836 // Ignore already broken or zombie connections.
Jeff Brownb6997262010-10-08 22:31:17 -07001837 if (connection->status == Connection::STATUS_NORMAL) {
1838 connection->status = Connection::STATUS_BROKEN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001839
Jeff Brownb6997262010-10-08 22:31:17 -07001840 // Notify other system components.
1841 onDispatchCycleBrokenLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001842 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001843}
1844
Jeff Brown519e0242010-09-15 15:18:56 -07001845void InputDispatcher::drainOutboundQueueLocked(Connection* connection) {
1846 while (! connection->outboundQueue.isEmpty()) {
1847 DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
1848 if (dispatchEntry->hasForegroundTarget()) {
1849 decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
Jeff Brownb88102f2010-09-08 11:49:43 -07001850 }
1851 mAllocator.releaseDispatchEntry(dispatchEntry);
Jeff Brownb88102f2010-09-08 11:49:43 -07001852 }
1853
Jeff Brown519e0242010-09-15 15:18:56 -07001854 deactivateConnectionLocked(connection);
Jeff Brownb88102f2010-09-08 11:49:43 -07001855}
1856
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001857int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001858 InputDispatcher* d = static_cast<InputDispatcher*>(data);
1859
1860 { // acquire lock
1861 AutoMutex _l(d->mLock);
1862
1863 ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
1864 if (connectionIndex < 0) {
1865 LOGE("Received spurious receive callback for unknown input channel. "
1866 "fd=%d, events=0x%x", receiveFd, events);
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001867 return 0; // remove the callback
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001868 }
1869
Jeff Brown7fbdc842010-06-17 20:52:56 -07001870 nsecs_t currentTime = now();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001871
1872 sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001873 if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001874 LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
1875 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brownb6997262010-10-08 22:31:17 -07001876 d->abortBrokenDispatchCycleLocked(currentTime, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001877 d->runCommandsLockedInterruptible();
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001878 return 0; // remove the callback
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001879 }
1880
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001881 if (! (events & ALOOPER_EVENT_INPUT)) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001882 LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
1883 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001884 return 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001885 }
1886
1887 status_t status = connection->inputPublisher.receiveFinishedSignal();
1888 if (status) {
1889 LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
1890 connection->getInputChannelName(), status);
Jeff Brownb6997262010-10-08 22:31:17 -07001891 d->abortBrokenDispatchCycleLocked(currentTime, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001892 d->runCommandsLockedInterruptible();
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001893 return 0; // remove the callback
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001894 }
1895
Jeff Brown7fbdc842010-06-17 20:52:56 -07001896 d->finishDispatchCycleLocked(currentTime, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001897 d->runCommandsLockedInterruptible();
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001898 return 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001899 } // release lock
1900}
1901
Jeff Brownb6997262010-10-08 22:31:17 -07001902void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked(
1903 InputState::CancelationOptions options, const char* reason) {
1904 for (size_t i = 0; i < mConnectionsByReceiveFd.size(); i++) {
1905 synthesizeCancelationEventsForConnectionLocked(
1906 mConnectionsByReceiveFd.valueAt(i), options, reason);
1907 }
1908}
1909
1910void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked(
1911 const sp<InputChannel>& channel, InputState::CancelationOptions options,
1912 const char* reason) {
1913 ssize_t index = getConnectionIndexLocked(channel);
1914 if (index >= 0) {
1915 synthesizeCancelationEventsForConnectionLocked(
1916 mConnectionsByReceiveFd.valueAt(index), options, reason);
1917 }
1918}
1919
1920void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
1921 const sp<Connection>& connection, InputState::CancelationOptions options,
1922 const char* reason) {
1923 nsecs_t currentTime = now();
1924
1925 mTempCancelationEvents.clear();
1926 connection->inputState.synthesizeCancelationEvents(currentTime, & mAllocator,
1927 mTempCancelationEvents, options);
1928
1929 if (! mTempCancelationEvents.isEmpty()
1930 && connection->status != Connection::STATUS_BROKEN) {
1931#if DEBUG_OUTBOUND_EVENT_DETAILS
1932 LOGD("channel '%s' ~ Synthesized %d cancelation events to bring channel back in sync "
1933 "with reality: %s, options=%d.",
1934 connection->getInputChannelName(), mTempCancelationEvents.size(), reason, options);
1935#endif
1936 for (size_t i = 0; i < mTempCancelationEvents.size(); i++) {
1937 EventEntry* cancelationEventEntry = mTempCancelationEvents.itemAt(i);
1938 switch (cancelationEventEntry->type) {
1939 case EventEntry::TYPE_KEY:
1940 logOutboundKeyDetailsLocked("cancel - ",
1941 static_cast<KeyEntry*>(cancelationEventEntry));
1942 break;
1943 case EventEntry::TYPE_MOTION:
1944 logOutboundMotionDetailsLocked("cancel - ",
1945 static_cast<MotionEntry*>(cancelationEventEntry));
1946 break;
1947 }
1948
1949 int32_t xOffset, yOffset;
1950 const InputWindow* window = getWindowLocked(connection->inputChannel);
1951 if (window) {
1952 xOffset = -window->frameLeft;
1953 yOffset = -window->frameTop;
1954 } else {
1955 xOffset = 0;
1956 yOffset = 0;
1957 }
1958
1959 DispatchEntry* cancelationDispatchEntry =
1960 mAllocator.obtainDispatchEntry(cancelationEventEntry, // increments ref
1961 0, xOffset, yOffset);
1962 connection->outboundQueue.enqueueAtTail(cancelationDispatchEntry);
1963
1964 mAllocator.releaseEventEntry(cancelationEventEntry);
1965 }
1966
1967 if (!connection->outboundQueue.headSentinel.next->inProgress) {
1968 startDispatchCycleLocked(currentTime, connection);
1969 }
1970 }
1971}
1972
Jeff Brown01ce2e92010-09-26 22:20:12 -07001973InputDispatcher::MotionEntry*
1974InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds) {
1975 assert(pointerIds.value != 0);
1976
1977 uint32_t splitPointerIndexMap[MAX_POINTERS];
1978 int32_t splitPointerIds[MAX_POINTERS];
1979 PointerCoords splitPointerCoords[MAX_POINTERS];
1980
1981 uint32_t originalPointerCount = originalMotionEntry->pointerCount;
1982 uint32_t splitPointerCount = 0;
1983
1984 for (uint32_t originalPointerIndex = 0; originalPointerIndex < originalPointerCount;
1985 originalPointerIndex++) {
1986 int32_t pointerId = uint32_t(originalMotionEntry->pointerIds[originalPointerIndex]);
1987 if (pointerIds.hasBit(pointerId)) {
1988 splitPointerIndexMap[splitPointerCount] = originalPointerIndex;
1989 splitPointerIds[splitPointerCount] = pointerId;
1990 splitPointerCoords[splitPointerCount] =
1991 originalMotionEntry->firstSample.pointerCoords[originalPointerIndex];
1992 splitPointerCount += 1;
1993 }
1994 }
1995 assert(splitPointerCount == pointerIds.count());
1996
1997 int32_t action = originalMotionEntry->action;
1998 int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
1999 if (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
2000 || maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
2001 int32_t originalPointerIndex = getMotionEventActionPointerIndex(action);
2002 int32_t pointerId = originalMotionEntry->pointerIds[originalPointerIndex];
2003 if (pointerIds.hasBit(pointerId)) {
2004 if (pointerIds.count() == 1) {
2005 // The first/last pointer went down/up.
2006 action = maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
2007 ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Brown9a01d052010-09-27 16:35:11 -07002008 } else {
2009 // A secondary pointer went down/up.
2010 uint32_t splitPointerIndex = 0;
2011 while (pointerId != splitPointerIds[splitPointerIndex]) {
2012 splitPointerIndex += 1;
2013 }
2014 action = maskedAction | (splitPointerIndex
2015 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Jeff Brown01ce2e92010-09-26 22:20:12 -07002016 }
2017 } else {
2018 // An unrelated pointer changed.
2019 action = AMOTION_EVENT_ACTION_MOVE;
2020 }
2021 }
2022
2023 MotionEntry* splitMotionEntry = mAllocator.obtainMotionEntry(
2024 originalMotionEntry->eventTime,
2025 originalMotionEntry->deviceId,
2026 originalMotionEntry->source,
2027 originalMotionEntry->policyFlags,
2028 action,
2029 originalMotionEntry->flags,
2030 originalMotionEntry->metaState,
2031 originalMotionEntry->edgeFlags,
2032 originalMotionEntry->xPrecision,
2033 originalMotionEntry->yPrecision,
2034 originalMotionEntry->downTime,
2035 splitPointerCount, splitPointerIds, splitPointerCoords);
2036
2037 for (MotionSample* originalMotionSample = originalMotionEntry->firstSample.next;
2038 originalMotionSample != NULL; originalMotionSample = originalMotionSample->next) {
2039 for (uint32_t splitPointerIndex = 0; splitPointerIndex < splitPointerCount;
2040 splitPointerIndex++) {
2041 uint32_t originalPointerIndex = splitPointerIndexMap[splitPointerIndex];
2042 splitPointerCoords[splitPointerIndex] =
2043 originalMotionSample->pointerCoords[originalPointerIndex];
2044 }
2045
2046 mAllocator.appendMotionSample(splitMotionEntry, originalMotionSample->eventTime,
2047 splitPointerCoords);
2048 }
2049
2050 return splitMotionEntry;
2051}
2052
Jeff Brown9c3cda02010-06-15 01:31:58 -07002053void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002054#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown9c3cda02010-06-15 01:31:58 -07002055 LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002056#endif
2057
Jeff Brownb88102f2010-09-08 11:49:43 -07002058 bool needWake;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002059 { // acquire lock
2060 AutoMutex _l(mLock);
2061
Jeff Brown7fbdc842010-06-17 20:52:56 -07002062 ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
Jeff Brownb88102f2010-09-08 11:49:43 -07002063 needWake = enqueueInboundEventLocked(newEntry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002064 } // release lock
2065
Jeff Brownb88102f2010-09-08 11:49:43 -07002066 if (needWake) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002067 mLooper->wake();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002068 }
2069}
2070
Jeff Brownc5ed5912010-07-14 18:48:53 -07002071void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002072 uint32_t policyFlags, int32_t action, int32_t flags,
2073 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
2074#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brownc5ed5912010-07-14 18:48:53 -07002075 LOGD("notifyKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002076 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
Jeff Brownc5ed5912010-07-14 18:48:53 -07002077 eventTime, deviceId, source, policyFlags, action, flags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002078 keyCode, scanCode, metaState, downTime);
2079#endif
Jeff Brown01ce2e92010-09-26 22:20:12 -07002080 if (! validateKeyEvent(action)) {
2081 return;
2082 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002083
Jeff Brownb931a1b2010-10-11 14:20:19 -07002084 policyFlags |= POLICY_FLAG_TRUSTED;
Jeff Brownb6997262010-10-08 22:31:17 -07002085 mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
2086 keyCode, scanCode, /*byref*/ policyFlags);
2087
Jeff Brownb88102f2010-09-08 11:49:43 -07002088 bool needWake;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002089 { // acquire lock
2090 AutoMutex _l(mLock);
2091
Jeff Brown7fbdc842010-06-17 20:52:56 -07002092 int32_t repeatCount = 0;
2093 KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -07002094 deviceId, source, policyFlags, action, flags, keyCode, scanCode,
Jeff Brown7fbdc842010-06-17 20:52:56 -07002095 metaState, repeatCount, downTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002096
Jeff Brownb88102f2010-09-08 11:49:43 -07002097 needWake = enqueueInboundEventLocked(newEntry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002098 } // release lock
2099
Jeff Brownb88102f2010-09-08 11:49:43 -07002100 if (needWake) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002101 mLooper->wake();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002102 }
2103}
2104
Jeff Brownc5ed5912010-07-14 18:48:53 -07002105void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Brown85a31762010-09-01 17:01:00 -07002106 uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t edgeFlags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002107 uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
2108 float xPrecision, float yPrecision, nsecs_t downTime) {
2109#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brownc5ed5912010-07-14 18:48:53 -07002110 LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
Jeff Brown85a31762010-09-01 17:01:00 -07002111 "action=0x%x, flags=0x%x, metaState=0x%x, edgeFlags=0x%x, "
2112 "xPrecision=%f, yPrecision=%f, downTime=%lld",
2113 eventTime, deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002114 xPrecision, yPrecision, downTime);
2115 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Brown8d608662010-08-30 03:02:23 -07002116 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
Jeff Brown85a31762010-09-01 17:01:00 -07002117 "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
Jeff Brown8d608662010-08-30 03:02:23 -07002118 "orientation=%f",
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002119 i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
Jeff Brown8d608662010-08-30 03:02:23 -07002120 pointerCoords[i].pressure, pointerCoords[i].size,
2121 pointerCoords[i].touchMajor, pointerCoords[i].touchMinor,
2122 pointerCoords[i].toolMajor, pointerCoords[i].toolMinor,
2123 pointerCoords[i].orientation);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002124 }
2125#endif
Jeff Brown01ce2e92010-09-26 22:20:12 -07002126 if (! validateMotionEvent(action, pointerCount, pointerIds)) {
2127 return;
2128 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002129
Jeff Brownb931a1b2010-10-11 14:20:19 -07002130 policyFlags |= POLICY_FLAG_TRUSTED;
Jeff Brownb6997262010-10-08 22:31:17 -07002131 mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
2132
Jeff Brownb88102f2010-09-08 11:49:43 -07002133 bool needWake;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002134 { // acquire lock
2135 AutoMutex _l(mLock);
2136
2137 // Attempt batching and streaming of move events.
Jeff Brownc5ed5912010-07-14 18:48:53 -07002138 if (action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002139 // BATCHING CASE
2140 //
2141 // Try to append a move sample to the tail of the inbound queue for this device.
2142 // Give up if we encounter a non-move motion event for this device since that
2143 // means we cannot append any new samples until a new motion event has started.
Jeff Brownb88102f2010-09-08 11:49:43 -07002144 for (EventEntry* entry = mInboundQueue.tailSentinel.prev;
2145 entry != & mInboundQueue.headSentinel; entry = entry->prev) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002146 if (entry->type != EventEntry::TYPE_MOTION) {
2147 // Keep looking for motion events.
2148 continue;
2149 }
2150
2151 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
2152 if (motionEntry->deviceId != deviceId) {
2153 // Keep looking for this device.
2154 continue;
2155 }
2156
Jeff Brownc5ed5912010-07-14 18:48:53 -07002157 if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown7fbdc842010-06-17 20:52:56 -07002158 || motionEntry->pointerCount != pointerCount
2159 || motionEntry->isInjected()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002160 // Last motion event in the queue for this device is not compatible for
2161 // appending new samples. Stop here.
2162 goto NoBatchingOrStreaming;
2163 }
2164
2165 // The last motion event is a move and is compatible for appending.
Jeff Brown9c3cda02010-06-15 01:31:58 -07002166 // Do the batching magic.
Jeff Brown7fbdc842010-06-17 20:52:56 -07002167 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002168#if DEBUG_BATCHING
2169 LOGD("Appended motion sample onto batch for most recent "
2170 "motion event for this device in the inbound queue.");
2171#endif
Jeff Brown9c3cda02010-06-15 01:31:58 -07002172 return; // done!
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002173 }
2174
2175 // STREAMING CASE
2176 //
2177 // There is no pending motion event (of any kind) for this device in the inbound queue.
Jeff Brown519e0242010-09-15 15:18:56 -07002178 // Search the outbound queue for the current foreground targets to find a dispatched
2179 // motion event that is still in progress. If found, then, appen the new sample to
2180 // that event and push it out to all current targets. The logic in
2181 // prepareDispatchCycleLocked takes care of the case where some targets may
2182 // already have consumed the motion event by starting a new dispatch cycle if needed.
Jeff Brown9c3cda02010-06-15 01:31:58 -07002183 if (mCurrentInputTargetsValid) {
Jeff Brown519e0242010-09-15 15:18:56 -07002184 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
2185 const InputTarget& inputTarget = mCurrentInputTargets[i];
2186 if ((inputTarget.flags & InputTarget::FLAG_FOREGROUND) == 0) {
2187 // Skip non-foreground targets. We only want to stream if there is at
2188 // least one foreground target whose dispatch is still in progress.
2189 continue;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002190 }
Jeff Brown519e0242010-09-15 15:18:56 -07002191
2192 ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
2193 if (connectionIndex < 0) {
2194 // Connection must no longer be valid.
2195 continue;
2196 }
2197
2198 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
2199 if (connection->outboundQueue.isEmpty()) {
2200 // This foreground target has an empty outbound queue.
2201 continue;
2202 }
2203
2204 DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
2205 if (! dispatchEntry->inProgress
Jeff Brown01ce2e92010-09-26 22:20:12 -07002206 || dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION
2207 || dispatchEntry->isSplit()) {
2208 // No motion event is being dispatched, or it is being split across
2209 // windows in which case we cannot stream.
Jeff Brown519e0242010-09-15 15:18:56 -07002210 continue;
2211 }
2212
2213 MotionEntry* motionEntry = static_cast<MotionEntry*>(
2214 dispatchEntry->eventEntry);
2215 if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
2216 || motionEntry->deviceId != deviceId
2217 || motionEntry->pointerCount != pointerCount
2218 || motionEntry->isInjected()) {
2219 // The motion event is not compatible with this move.
2220 continue;
2221 }
2222
2223 // Hurray! This foreground target is currently dispatching a move event
2224 // that we can stream onto. Append the motion sample and resume dispatch.
2225 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
2226#if DEBUG_BATCHING
2227 LOGD("Appended motion sample onto batch for most recently dispatched "
2228 "motion event for this device in the outbound queues. "
2229 "Attempting to stream the motion sample.");
2230#endif
2231 nsecs_t currentTime = now();
2232 dispatchEventToCurrentInputTargetsLocked(currentTime, motionEntry,
2233 true /*resumeWithAppendedMotionSample*/);
2234
2235 runCommandsLockedInterruptible();
2236 return; // done!
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002237 }
2238 }
2239
2240NoBatchingOrStreaming:;
2241 }
2242
2243 // Just enqueue a new motion event.
Jeff Brown7fbdc842010-06-17 20:52:56 -07002244 MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
Jeff Brown85a31762010-09-01 17:01:00 -07002245 deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -07002246 xPrecision, yPrecision, downTime,
2247 pointerCount, pointerIds, pointerCoords);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002248
Jeff Brownb88102f2010-09-08 11:49:43 -07002249 needWake = enqueueInboundEventLocked(newEntry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002250 } // release lock
2251
Jeff Brownb88102f2010-09-08 11:49:43 -07002252 if (needWake) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002253 mLooper->wake();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002254 }
2255}
2256
Jeff Brownb6997262010-10-08 22:31:17 -07002257void InputDispatcher::notifySwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
2258 uint32_t policyFlags) {
2259#if DEBUG_INBOUND_EVENT_DETAILS
2260 LOGD("notifySwitch - switchCode=%d, switchValue=%d, policyFlags=0x%x",
2261 switchCode, switchValue, policyFlags);
2262#endif
2263
Jeff Brownb931a1b2010-10-11 14:20:19 -07002264 policyFlags |= POLICY_FLAG_TRUSTED;
Jeff Brownb6997262010-10-08 22:31:17 -07002265 mPolicy->notifySwitch(when, switchCode, switchValue, policyFlags);
2266}
2267
Jeff Brown7fbdc842010-06-17 20:52:56 -07002268int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
Jeff Brown6ec402b2010-07-28 15:48:59 -07002269 int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07002270#if DEBUG_INBOUND_EVENT_DETAILS
2271 LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
Jeff Brown6ec402b2010-07-28 15:48:59 -07002272 "syncMode=%d, timeoutMillis=%d",
2273 event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002274#endif
2275
2276 nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
Jeff Brownb931a1b2010-10-11 14:20:19 -07002277
2278 uint32_t policyFlags = POLICY_FLAG_INJECTED;
2279 if (hasInjectionPermission(injectorPid, injectorUid)) {
2280 policyFlags |= POLICY_FLAG_TRUSTED;
2281 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07002282
Jeff Brownb6997262010-10-08 22:31:17 -07002283 EventEntry* injectedEntry;
2284 switch (event->getType()) {
2285 case AINPUT_EVENT_TYPE_KEY: {
2286 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
2287 int32_t action = keyEvent->getAction();
2288 if (! validateKeyEvent(action)) {
Jeff Brownb88102f2010-09-08 11:49:43 -07002289 return INPUT_EVENT_INJECTION_FAILED;
2290 }
2291
Jeff Brownb6997262010-10-08 22:31:17 -07002292 nsecs_t eventTime = keyEvent->getEventTime();
2293 int32_t deviceId = keyEvent->getDeviceId();
2294 int32_t flags = keyEvent->getFlags();
2295 int32_t keyCode = keyEvent->getKeyCode();
2296 int32_t scanCode = keyEvent->getScanCode();
Jeff Brownb931a1b2010-10-11 14:20:19 -07002297 mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
2298 keyCode, scanCode, /*byref*/ policyFlags);
Jeff Brown6ec402b2010-07-28 15:48:59 -07002299
Jeff Brownb6997262010-10-08 22:31:17 -07002300 mLock.lock();
2301 injectedEntry = mAllocator.obtainKeyEntry(eventTime, deviceId, keyEvent->getSource(),
2302 policyFlags, action, flags, keyCode, scanCode, keyEvent->getMetaState(),
2303 keyEvent->getRepeatCount(), keyEvent->getDownTime());
2304 break;
2305 }
Jeff Brown01ce2e92010-09-26 22:20:12 -07002306
Jeff Brownb6997262010-10-08 22:31:17 -07002307 case AINPUT_EVENT_TYPE_MOTION: {
2308 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
2309 int32_t action = motionEvent->getAction();
2310 size_t pointerCount = motionEvent->getPointerCount();
2311 const int32_t* pointerIds = motionEvent->getPointerIds();
2312 if (! validateMotionEvent(action, pointerCount, pointerIds)) {
2313 return INPUT_EVENT_INJECTION_FAILED;
2314 }
2315
2316 nsecs_t eventTime = motionEvent->getEventTime();
Jeff Brownb931a1b2010-10-11 14:20:19 -07002317 mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
Jeff Brownb6997262010-10-08 22:31:17 -07002318
2319 mLock.lock();
2320 const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
2321 const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
2322 MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
2323 motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
2324 action, motionEvent->getFlags(),
2325 motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
2326 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
2327 motionEvent->getDownTime(), uint32_t(pointerCount),
2328 pointerIds, samplePointerCoords);
2329 for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
2330 sampleEventTimes += 1;
2331 samplePointerCoords += pointerCount;
2332 mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
2333 }
2334 injectedEntry = motionEntry;
2335 break;
2336 }
2337
2338 default:
2339 LOGW("Cannot inject event of type %d", event->getType());
2340 return INPUT_EVENT_INJECTION_FAILED;
2341 }
2342
2343 InjectionState* injectionState = mAllocator.obtainInjectionState(injectorPid, injectorUid);
2344 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
2345 injectionState->injectionIsAsync = true;
2346 }
2347
2348 injectionState->refCount += 1;
2349 injectedEntry->injectionState = injectionState;
2350
2351 bool needWake = enqueueInboundEventLocked(injectedEntry);
2352 mLock.unlock();
Jeff Brown7fbdc842010-06-17 20:52:56 -07002353
Jeff Brownb88102f2010-09-08 11:49:43 -07002354 if (needWake) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002355 mLooper->wake();
Jeff Brown7fbdc842010-06-17 20:52:56 -07002356 }
2357
2358 int32_t injectionResult;
2359 { // acquire lock
2360 AutoMutex _l(mLock);
2361
Jeff Brown6ec402b2010-07-28 15:48:59 -07002362 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
2363 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
2364 } else {
2365 for (;;) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07002366 injectionResult = injectionState->injectionResult;
Jeff Brown6ec402b2010-07-28 15:48:59 -07002367 if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
2368 break;
2369 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07002370
Jeff Brown7fbdc842010-06-17 20:52:56 -07002371 nsecs_t remainingTimeout = endTime - now();
2372 if (remainingTimeout <= 0) {
Jeff Brown6ec402b2010-07-28 15:48:59 -07002373#if DEBUG_INJECTION
2374 LOGD("injectInputEvent - Timed out waiting for injection result "
2375 "to become available.");
2376#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07002377 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
2378 break;
2379 }
2380
Jeff Brown6ec402b2010-07-28 15:48:59 -07002381 mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
2382 }
2383
2384 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
2385 && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07002386 while (injectionState->pendingForegroundDispatches != 0) {
Jeff Brown6ec402b2010-07-28 15:48:59 -07002387#if DEBUG_INJECTION
Jeff Brown519e0242010-09-15 15:18:56 -07002388 LOGD("injectInputEvent - Waiting for %d pending foreground dispatches.",
Jeff Brown01ce2e92010-09-26 22:20:12 -07002389 injectionState->pendingForegroundDispatches);
Jeff Brown6ec402b2010-07-28 15:48:59 -07002390#endif
2391 nsecs_t remainingTimeout = endTime - now();
2392 if (remainingTimeout <= 0) {
2393#if DEBUG_INJECTION
Jeff Brown519e0242010-09-15 15:18:56 -07002394 LOGD("injectInputEvent - Timed out waiting for pending foreground "
Jeff Brown6ec402b2010-07-28 15:48:59 -07002395 "dispatches to finish.");
2396#endif
2397 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
2398 break;
2399 }
2400
2401 mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
2402 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07002403 }
2404 }
2405
Jeff Brown01ce2e92010-09-26 22:20:12 -07002406 mAllocator.releaseInjectionState(injectionState);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002407 } // release lock
2408
Jeff Brown6ec402b2010-07-28 15:48:59 -07002409#if DEBUG_INJECTION
2410 LOGD("injectInputEvent - Finished with result %d. "
2411 "injectorPid=%d, injectorUid=%d",
2412 injectionResult, injectorPid, injectorUid);
2413#endif
2414
Jeff Brown7fbdc842010-06-17 20:52:56 -07002415 return injectionResult;
2416}
2417
Jeff Brownb6997262010-10-08 22:31:17 -07002418bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) {
2419 return injectorUid == 0
2420 || mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
2421}
2422
Jeff Brown7fbdc842010-06-17 20:52:56 -07002423void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07002424 InjectionState* injectionState = entry->injectionState;
2425 if (injectionState) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07002426#if DEBUG_INJECTION
2427 LOGD("Setting input event injection result to %d. "
2428 "injectorPid=%d, injectorUid=%d",
Jeff Brown01ce2e92010-09-26 22:20:12 -07002429 injectionResult, injectionState->injectorPid, injectionState->injectorUid);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002430#endif
2431
Jeff Brown01ce2e92010-09-26 22:20:12 -07002432 if (injectionState->injectionIsAsync) {
Jeff Brown6ec402b2010-07-28 15:48:59 -07002433 // Log the outcome since the injector did not wait for the injection result.
2434 switch (injectionResult) {
2435 case INPUT_EVENT_INJECTION_SUCCEEDED:
2436 LOGV("Asynchronous input event injection succeeded.");
2437 break;
2438 case INPUT_EVENT_INJECTION_FAILED:
2439 LOGW("Asynchronous input event injection failed.");
2440 break;
2441 case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
2442 LOGW("Asynchronous input event injection permission denied.");
2443 break;
2444 case INPUT_EVENT_INJECTION_TIMED_OUT:
2445 LOGW("Asynchronous input event injection timed out.");
2446 break;
2447 }
2448 }
2449
Jeff Brown01ce2e92010-09-26 22:20:12 -07002450 injectionState->injectionResult = injectionResult;
Jeff Brown7fbdc842010-06-17 20:52:56 -07002451 mInjectionResultAvailableCondition.broadcast();
2452 }
2453}
2454
Jeff Brown01ce2e92010-09-26 22:20:12 -07002455void InputDispatcher::incrementPendingForegroundDispatchesLocked(EventEntry* entry) {
2456 InjectionState* injectionState = entry->injectionState;
2457 if (injectionState) {
2458 injectionState->pendingForegroundDispatches += 1;
2459 }
2460}
2461
Jeff Brown519e0242010-09-15 15:18:56 -07002462void InputDispatcher::decrementPendingForegroundDispatchesLocked(EventEntry* entry) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07002463 InjectionState* injectionState = entry->injectionState;
2464 if (injectionState) {
2465 injectionState->pendingForegroundDispatches -= 1;
Jeff Brown6ec402b2010-07-28 15:48:59 -07002466
Jeff Brown01ce2e92010-09-26 22:20:12 -07002467 if (injectionState->pendingForegroundDispatches == 0) {
2468 mInjectionSyncFinishedCondition.broadcast();
2469 }
Jeff Brownb88102f2010-09-08 11:49:43 -07002470 }
2471}
2472
Jeff Brown01ce2e92010-09-26 22:20:12 -07002473const InputWindow* InputDispatcher::getWindowLocked(const sp<InputChannel>& inputChannel) {
2474 for (size_t i = 0; i < mWindows.size(); i++) {
2475 const InputWindow* window = & mWindows[i];
2476 if (window->inputChannel == inputChannel) {
2477 return window;
2478 }
2479 }
2480 return NULL;
2481}
2482
Jeff Brownb88102f2010-09-08 11:49:43 -07002483void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
2484#if DEBUG_FOCUS
2485 LOGD("setInputWindows");
2486#endif
2487 { // acquire lock
2488 AutoMutex _l(mLock);
2489
Jeff Brown01ce2e92010-09-26 22:20:12 -07002490 // Clear old window pointers.
Jeff Brownb6997262010-10-08 22:31:17 -07002491 sp<InputChannel> oldFocusedWindowChannel;
2492 if (mFocusedWindow) {
2493 oldFocusedWindowChannel = mFocusedWindow->inputChannel;
2494 mFocusedWindow = NULL;
2495 }
2496
Jeff Brownb88102f2010-09-08 11:49:43 -07002497 mWindows.clear();
Jeff Brown2a95c2a2010-09-16 12:31:46 -07002498
2499 // Loop over new windows and rebuild the necessary window pointers for
2500 // tracking focus and touch.
Jeff Brownb88102f2010-09-08 11:49:43 -07002501 mWindows.appendVector(inputWindows);
2502
2503 size_t numWindows = mWindows.size();
2504 for (size_t i = 0; i < numWindows; i++) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07002505 const InputWindow* window = & mWindows.itemAt(i);
Jeff Brownb88102f2010-09-08 11:49:43 -07002506 if (window->hasFocus) {
2507 mFocusedWindow = window;
Jeff Brown01ce2e92010-09-26 22:20:12 -07002508 break;
Jeff Brownb88102f2010-09-08 11:49:43 -07002509 }
2510 }
Jeff Brown01ce2e92010-09-26 22:20:12 -07002511
Jeff Brownb6997262010-10-08 22:31:17 -07002512 if (oldFocusedWindowChannel != NULL) {
2513 if (!mFocusedWindow || oldFocusedWindowChannel != mFocusedWindow->inputChannel) {
2514#if DEBUG_FOCUS
2515 LOGD("Focus left window: %s",
2516 oldFocusedWindowChannel->getName().string());
2517#endif
2518 synthesizeCancelationEventsForInputChannelLocked(oldFocusedWindowChannel,
2519 InputState::CANCEL_NON_POINTER_EVENTS, "focus left window");
2520 oldFocusedWindowChannel.clear();
2521 }
2522 }
2523 if (mFocusedWindow && oldFocusedWindowChannel == NULL) {
2524#if DEBUG_FOCUS
2525 LOGD("Focus entered window: %s",
2526 mFocusedWindow->inputChannel->getName().string());
2527#endif
2528 }
2529
Jeff Brown01ce2e92010-09-26 22:20:12 -07002530 for (size_t i = 0; i < mTouchState.windows.size(); ) {
2531 TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i);
2532 const InputWindow* window = getWindowLocked(touchedWindow.channel);
2533 if (window) {
2534 touchedWindow.window = window;
2535 i += 1;
2536 } else {
Jeff Brownb6997262010-10-08 22:31:17 -07002537#if DEBUG_FOCUS
2538 LOGD("Touched window was removed: %s", touchedWindow.channel->getName().string());
2539#endif
Jeff Brown01ce2e92010-09-26 22:20:12 -07002540 mTouchState.windows.removeAt(i);
Jeff Brownb6997262010-10-08 22:31:17 -07002541 synthesizeCancelationEventsForInputChannelLocked(touchedWindow.channel,
2542 InputState::CANCEL_POINTER_EVENTS, "touched window was removed");
Jeff Brown01ce2e92010-09-26 22:20:12 -07002543 }
2544 }
Jeff Brownb88102f2010-09-08 11:49:43 -07002545
Jeff Brownb88102f2010-09-08 11:49:43 -07002546#if DEBUG_FOCUS
Jeff Brownb6997262010-10-08 22:31:17 -07002547 //logDispatchStateLocked();
Jeff Brownb88102f2010-09-08 11:49:43 -07002548#endif
2549 } // release lock
2550
2551 // Wake up poll loop since it may need to make new input dispatching choices.
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002552 mLooper->wake();
Jeff Brownb88102f2010-09-08 11:49:43 -07002553}
2554
2555void InputDispatcher::setFocusedApplication(const InputApplication* inputApplication) {
2556#if DEBUG_FOCUS
2557 LOGD("setFocusedApplication");
2558#endif
2559 { // acquire lock
2560 AutoMutex _l(mLock);
2561
2562 releaseFocusedApplicationLocked();
2563
2564 if (inputApplication) {
2565 mFocusedApplicationStorage = *inputApplication;
2566 mFocusedApplication = & mFocusedApplicationStorage;
2567 }
2568
2569#if DEBUG_FOCUS
Jeff Brownb6997262010-10-08 22:31:17 -07002570 //logDispatchStateLocked();
Jeff Brownb88102f2010-09-08 11:49:43 -07002571#endif
2572 } // release lock
2573
2574 // Wake up poll loop since it may need to make new input dispatching choices.
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002575 mLooper->wake();
Jeff Brownb88102f2010-09-08 11:49:43 -07002576}
2577
2578void InputDispatcher::releaseFocusedApplicationLocked() {
2579 if (mFocusedApplication) {
2580 mFocusedApplication = NULL;
2581 mFocusedApplicationStorage.handle.clear();
2582 }
2583}
2584
2585void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
2586#if DEBUG_FOCUS
2587 LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
2588#endif
2589
2590 bool changed;
2591 { // acquire lock
2592 AutoMutex _l(mLock);
2593
2594 if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
2595 if (mDispatchFrozen && ! frozen) {
2596 resetANRTimeoutsLocked();
2597 }
2598
2599 mDispatchEnabled = enabled;
2600 mDispatchFrozen = frozen;
2601 changed = true;
2602 } else {
2603 changed = false;
2604 }
2605
2606#if DEBUG_FOCUS
Jeff Brownb6997262010-10-08 22:31:17 -07002607 //logDispatchStateLocked();
Jeff Brownb88102f2010-09-08 11:49:43 -07002608#endif
2609 } // release lock
2610
2611 if (changed) {
2612 // Wake up poll loop since it may need to make new input dispatching choices.
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002613 mLooper->wake();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002614 }
2615}
2616
Jeff Brownb88102f2010-09-08 11:49:43 -07002617void InputDispatcher::logDispatchStateLocked() {
2618 String8 dump;
2619 dumpDispatchStateLocked(dump);
Jeff Brown2a95c2a2010-09-16 12:31:46 -07002620
2621 char* text = dump.lockBuffer(dump.size());
2622 char* start = text;
2623 while (*start != '\0') {
2624 char* end = strchr(start, '\n');
2625 if (*end == '\n') {
2626 *(end++) = '\0';
2627 }
2628 LOGD("%s", start);
2629 start = end;
2630 }
Jeff Brownb88102f2010-09-08 11:49:43 -07002631}
2632
2633void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
Jeff Brownf2f487182010-10-01 17:46:21 -07002634 dump.appendFormat(INDENT "DispatchEnabled: %d\n", mDispatchEnabled);
2635 dump.appendFormat(INDENT "DispatchFrozen: %d\n", mDispatchFrozen);
Jeff Brownb88102f2010-09-08 11:49:43 -07002636
2637 if (mFocusedApplication) {
Jeff Brownf2f487182010-10-01 17:46:21 -07002638 dump.appendFormat(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
Jeff Brownb88102f2010-09-08 11:49:43 -07002639 mFocusedApplication->name.string(),
2640 mFocusedApplication->dispatchingTimeout / 1000000.0);
2641 } else {
Jeff Brownf2f487182010-10-01 17:46:21 -07002642 dump.append(INDENT "FocusedApplication: <null>\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002643 }
Jeff Brownf2f487182010-10-01 17:46:21 -07002644 dump.appendFormat(INDENT "FocusedWindow: name='%s'\n",
Jeff Brown2a95c2a2010-09-16 12:31:46 -07002645 mFocusedWindow != NULL ? mFocusedWindow->name.string() : "<null>");
Jeff Brownf2f487182010-10-01 17:46:21 -07002646
2647 dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down));
2648 dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split));
2649 if (!mTouchState.windows.isEmpty()) {
2650 dump.append(INDENT "TouchedWindows:\n");
2651 for (size_t i = 0; i < mTouchState.windows.size(); i++) {
2652 const TouchedWindow& touchedWindow = mTouchState.windows[i];
2653 dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
2654 i, touchedWindow.window->name.string(), touchedWindow.pointerIds.value,
2655 touchedWindow.targetFlags);
2656 }
2657 } else {
2658 dump.append(INDENT "TouchedWindows: <none>\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002659 }
2660
Jeff Brownf2f487182010-10-01 17:46:21 -07002661 if (!mWindows.isEmpty()) {
2662 dump.append(INDENT "Windows:\n");
2663 for (size_t i = 0; i < mWindows.size(); i++) {
2664 const InputWindow& window = mWindows[i];
2665 dump.appendFormat(INDENT2 "%d: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
2666 "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
2667 "frame=[%d,%d][%d,%d], "
2668 "visibleFrame=[%d,%d][%d,%d], "
2669 "touchableArea=[%d,%d][%d,%d], "
2670 "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
2671 i, window.name.string(),
2672 toString(window.paused),
2673 toString(window.hasFocus),
2674 toString(window.hasWallpaper),
2675 toString(window.visible),
2676 toString(window.canReceiveKeys),
2677 window.layoutParamsFlags, window.layoutParamsType,
2678 window.layer,
2679 window.frameLeft, window.frameTop,
2680 window.frameRight, window.frameBottom,
2681 window.visibleFrameLeft, window.visibleFrameTop,
2682 window.visibleFrameRight, window.visibleFrameBottom,
2683 window.touchableAreaLeft, window.touchableAreaTop,
2684 window.touchableAreaRight, window.touchableAreaBottom,
2685 window.ownerPid, window.ownerUid,
2686 window.dispatchingTimeout / 1000000.0);
2687 }
2688 } else {
2689 dump.append(INDENT "Windows: <none>\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002690 }
2691
Jeff Brownf2f487182010-10-01 17:46:21 -07002692 if (!mMonitoringChannels.isEmpty()) {
2693 dump.append(INDENT "MonitoringChannels:\n");
2694 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
2695 const sp<InputChannel>& channel = mMonitoringChannels[i];
2696 dump.appendFormat(INDENT2 "%d: '%s'\n", i, channel->getName().string());
2697 }
2698 } else {
2699 dump.append(INDENT "MonitoringChannels: <none>\n");
2700 }
Jeff Brown519e0242010-09-15 15:18:56 -07002701
Jeff Brownf2f487182010-10-01 17:46:21 -07002702 dump.appendFormat(INDENT "InboundQueue: length=%u\n", mInboundQueue.count());
2703
2704 if (!mActiveConnections.isEmpty()) {
2705 dump.append(INDENT "ActiveConnections:\n");
2706 for (size_t i = 0; i < mActiveConnections.size(); i++) {
2707 const Connection* connection = mActiveConnections[i];
2708 dump.appendFormat(INDENT2 "%d: '%s', status=%s, outboundQueueLength=%u"
Jeff Brownb6997262010-10-08 22:31:17 -07002709 "inputState.isNeutral=%s\n",
Jeff Brownf2f487182010-10-01 17:46:21 -07002710 i, connection->getInputChannelName(), connection->getStatusLabel(),
2711 connection->outboundQueue.count(),
Jeff Brownb6997262010-10-08 22:31:17 -07002712 toString(connection->inputState.isNeutral()));
Jeff Brownf2f487182010-10-01 17:46:21 -07002713 }
2714 } else {
2715 dump.append(INDENT "ActiveConnections: <none>\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002716 }
2717
2718 if (isAppSwitchPendingLocked()) {
Jeff Brownf2f487182010-10-01 17:46:21 -07002719 dump.appendFormat(INDENT "AppSwitch: pending, due in %01.1fms\n",
Jeff Brownb88102f2010-09-08 11:49:43 -07002720 (mAppSwitchDueTime - now()) / 1000000.0);
2721 } else {
Jeff Brownf2f487182010-10-01 17:46:21 -07002722 dump.append(INDENT "AppSwitch: not pending\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002723 }
2724}
2725
2726status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07002727#if DEBUG_REGISTRATION
Jeff Brownb88102f2010-09-08 11:49:43 -07002728 LOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().string(),
2729 toString(monitor));
Jeff Brown9c3cda02010-06-15 01:31:58 -07002730#endif
2731
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002732 { // acquire lock
2733 AutoMutex _l(mLock);
2734
Jeff Brown519e0242010-09-15 15:18:56 -07002735 if (getConnectionIndexLocked(inputChannel) >= 0) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002736 LOGW("Attempted to register already registered input channel '%s'",
2737 inputChannel->getName().string());
2738 return BAD_VALUE;
2739 }
2740
2741 sp<Connection> connection = new Connection(inputChannel);
2742 status_t status = connection->initialize();
2743 if (status) {
2744 LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
2745 inputChannel->getName().string(), status);
2746 return status;
2747 }
2748
Jeff Brown2cbecea2010-08-17 15:59:26 -07002749 int32_t receiveFd = inputChannel->getReceivePipeFd();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002750 mConnectionsByReceiveFd.add(receiveFd, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -07002751
Jeff Brownb88102f2010-09-08 11:49:43 -07002752 if (monitor) {
2753 mMonitoringChannels.push(inputChannel);
2754 }
2755
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002756 mLooper->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
Jeff Brown2cbecea2010-08-17 15:59:26 -07002757
Jeff Brown9c3cda02010-06-15 01:31:58 -07002758 runCommandsLockedInterruptible();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002759 } // release lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002760 return OK;
2761}
2762
2763status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07002764#if DEBUG_REGISTRATION
Jeff Brown349703e2010-06-22 01:27:15 -07002765 LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
Jeff Brown9c3cda02010-06-15 01:31:58 -07002766#endif
2767
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002768 { // acquire lock
2769 AutoMutex _l(mLock);
2770
Jeff Brown519e0242010-09-15 15:18:56 -07002771 ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002772 if (connectionIndex < 0) {
2773 LOGW("Attempted to unregister already unregistered input channel '%s'",
2774 inputChannel->getName().string());
2775 return BAD_VALUE;
2776 }
2777
2778 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
2779 mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
2780
2781 connection->status = Connection::STATUS_ZOMBIE;
2782
Jeff Brownb88102f2010-09-08 11:49:43 -07002783 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
2784 if (mMonitoringChannels[i] == inputChannel) {
2785 mMonitoringChannels.removeAt(i);
2786 break;
2787 }
2788 }
2789
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002790 mLooper->removeFd(inputChannel->getReceivePipeFd());
Jeff Brown2cbecea2010-08-17 15:59:26 -07002791
Jeff Brown7fbdc842010-06-17 20:52:56 -07002792 nsecs_t currentTime = now();
Jeff Brownb6997262010-10-08 22:31:17 -07002793 abortBrokenDispatchCycleLocked(currentTime, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -07002794
2795 runCommandsLockedInterruptible();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002796 } // release lock
2797
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002798 // Wake the poll loop because removing the connection may have changed the current
2799 // synchronization state.
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002800 mLooper->wake();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002801 return OK;
2802}
2803
Jeff Brown519e0242010-09-15 15:18:56 -07002804ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
Jeff Brown2cbecea2010-08-17 15:59:26 -07002805 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(inputChannel->getReceivePipeFd());
2806 if (connectionIndex >= 0) {
2807 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
2808 if (connection->inputChannel.get() == inputChannel.get()) {
2809 return connectionIndex;
2810 }
2811 }
2812
2813 return -1;
2814}
2815
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002816void InputDispatcher::activateConnectionLocked(Connection* connection) {
2817 for (size_t i = 0; i < mActiveConnections.size(); i++) {
2818 if (mActiveConnections.itemAt(i) == connection) {
2819 return;
2820 }
2821 }
2822 mActiveConnections.add(connection);
2823}
2824
2825void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
2826 for (size_t i = 0; i < mActiveConnections.size(); i++) {
2827 if (mActiveConnections.itemAt(i) == connection) {
2828 mActiveConnections.removeAt(i);
2829 return;
2830 }
2831 }
2832}
2833
Jeff Brown9c3cda02010-06-15 01:31:58 -07002834void InputDispatcher::onDispatchCycleStartedLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07002835 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002836}
2837
Jeff Brown9c3cda02010-06-15 01:31:58 -07002838void InputDispatcher::onDispatchCycleFinishedLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07002839 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002840}
2841
Jeff Brown9c3cda02010-06-15 01:31:58 -07002842void InputDispatcher::onDispatchCycleBrokenLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07002843 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002844 LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
2845 connection->getInputChannelName());
2846
Jeff Brown9c3cda02010-06-15 01:31:58 -07002847 CommandEntry* commandEntry = postCommandLocked(
2848 & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002849 commandEntry->connection = connection;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002850}
2851
Jeff Brown519e0242010-09-15 15:18:56 -07002852void InputDispatcher::onANRLocked(
2853 nsecs_t currentTime, const InputApplication* application, const InputWindow* window,
2854 nsecs_t eventTime, nsecs_t waitStartTime) {
2855 LOGI("Application is not responding: %s. "
2856 "%01.1fms since event, %01.1fms since wait started",
2857 getApplicationWindowLabelLocked(application, window).string(),
2858 (currentTime - eventTime) / 1000000.0,
2859 (currentTime - waitStartTime) / 1000000.0);
2860
2861 CommandEntry* commandEntry = postCommandLocked(
2862 & InputDispatcher::doNotifyANRLockedInterruptible);
2863 if (application) {
2864 commandEntry->inputApplicationHandle = application->handle;
2865 }
2866 if (window) {
2867 commandEntry->inputChannel = window->inputChannel;
2868 }
2869}
2870
Jeff Brownb88102f2010-09-08 11:49:43 -07002871void InputDispatcher::doNotifyConfigurationChangedInterruptible(
2872 CommandEntry* commandEntry) {
2873 mLock.unlock();
2874
2875 mPolicy->notifyConfigurationChanged(commandEntry->eventTime);
2876
2877 mLock.lock();
2878}
2879
Jeff Brown9c3cda02010-06-15 01:31:58 -07002880void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
2881 CommandEntry* commandEntry) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07002882 sp<Connection> connection = commandEntry->connection;
Jeff Brown9c3cda02010-06-15 01:31:58 -07002883
Jeff Brown7fbdc842010-06-17 20:52:56 -07002884 if (connection->status != Connection::STATUS_ZOMBIE) {
2885 mLock.unlock();
Jeff Brown9c3cda02010-06-15 01:31:58 -07002886
Jeff Brown7fbdc842010-06-17 20:52:56 -07002887 mPolicy->notifyInputChannelBroken(connection->inputChannel);
2888
2889 mLock.lock();
2890 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07002891}
2892
Jeff Brown519e0242010-09-15 15:18:56 -07002893void InputDispatcher::doNotifyANRLockedInterruptible(
Jeff Brown9c3cda02010-06-15 01:31:58 -07002894 CommandEntry* commandEntry) {
Jeff Brown519e0242010-09-15 15:18:56 -07002895 mLock.unlock();
Jeff Brown9c3cda02010-06-15 01:31:58 -07002896
Jeff Brown519e0242010-09-15 15:18:56 -07002897 nsecs_t newTimeout = mPolicy->notifyANR(
2898 commandEntry->inputApplicationHandle, commandEntry->inputChannel);
Jeff Brown9c3cda02010-06-15 01:31:58 -07002899
Jeff Brown519e0242010-09-15 15:18:56 -07002900 mLock.lock();
Jeff Brown7fbdc842010-06-17 20:52:56 -07002901
Jeff Brown519e0242010-09-15 15:18:56 -07002902 resumeAfterTargetsNotReadyTimeoutLocked(newTimeout, commandEntry->inputChannel);
Jeff Brown9c3cda02010-06-15 01:31:58 -07002903}
2904
Jeff Brownb88102f2010-09-08 11:49:43 -07002905void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
2906 CommandEntry* commandEntry) {
2907 KeyEntry* entry = commandEntry->keyEntry;
2908 mReusableKeyEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
2909 entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
2910 entry->downTime, entry->eventTime);
2911
2912 mLock.unlock();
2913
2914 bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputChannel,
2915 & mReusableKeyEvent, entry->policyFlags);
2916
2917 mLock.lock();
2918
2919 entry->interceptKeyResult = consumed
2920 ? KeyEntry::INTERCEPT_KEY_RESULT_SKIP
2921 : KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
2922 mAllocator.releaseKeyEntry(entry);
2923}
2924
2925void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
2926 mLock.unlock();
2927
Jeff Brown01ce2e92010-09-26 22:20:12 -07002928 mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType);
Jeff Brownb88102f2010-09-08 11:49:43 -07002929
2930 mLock.lock();
2931}
2932
Jeff Brown519e0242010-09-15 15:18:56 -07002933void InputDispatcher::updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
2934 int32_t injectionResult, nsecs_t timeSpentWaitingForApplication) {
2935 // TODO Write some statistics about how long we spend waiting.
Jeff Brownb88102f2010-09-08 11:49:43 -07002936}
2937
2938void InputDispatcher::dump(String8& dump) {
Jeff Brownf2f487182010-10-01 17:46:21 -07002939 dump.append("Input Dispatcher State:\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002940 dumpDispatchStateLocked(dump);
2941}
2942
Jeff Brown9c3cda02010-06-15 01:31:58 -07002943
Jeff Brown519e0242010-09-15 15:18:56 -07002944// --- InputDispatcher::Queue ---
2945
2946template <typename T>
2947uint32_t InputDispatcher::Queue<T>::count() const {
2948 uint32_t result = 0;
2949 for (const T* entry = headSentinel.next; entry != & tailSentinel; entry = entry->next) {
2950 result += 1;
2951 }
2952 return result;
2953}
2954
2955
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002956// --- InputDispatcher::Allocator ---
2957
2958InputDispatcher::Allocator::Allocator() {
2959}
2960
Jeff Brown01ce2e92010-09-26 22:20:12 -07002961InputDispatcher::InjectionState*
2962InputDispatcher::Allocator::obtainInjectionState(int32_t injectorPid, int32_t injectorUid) {
2963 InjectionState* injectionState = mInjectionStatePool.alloc();
2964 injectionState->refCount = 1;
2965 injectionState->injectorPid = injectorPid;
2966 injectionState->injectorUid = injectorUid;
2967 injectionState->injectionIsAsync = false;
2968 injectionState->injectionResult = INPUT_EVENT_INJECTION_PENDING;
2969 injectionState->pendingForegroundDispatches = 0;
2970 return injectionState;
2971}
2972
Jeff Brown7fbdc842010-06-17 20:52:56 -07002973void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
Jeff Brownb6997262010-10-08 22:31:17 -07002974 nsecs_t eventTime, uint32_t policyFlags) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07002975 entry->type = type;
2976 entry->refCount = 1;
2977 entry->dispatchInProgress = false;
Christopher Tatee91a5db2010-06-23 16:50:30 -07002978 entry->eventTime = eventTime;
Jeff Brownb6997262010-10-08 22:31:17 -07002979 entry->policyFlags = policyFlags;
Jeff Brown01ce2e92010-09-26 22:20:12 -07002980 entry->injectionState = NULL;
2981}
2982
2983void InputDispatcher::Allocator::releaseEventEntryInjectionState(EventEntry* entry) {
2984 if (entry->injectionState) {
2985 releaseInjectionState(entry->injectionState);
2986 entry->injectionState = NULL;
2987 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07002988}
2989
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002990InputDispatcher::ConfigurationChangedEntry*
Jeff Brown7fbdc842010-06-17 20:52:56 -07002991InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002992 ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
Jeff Brownb6997262010-10-08 22:31:17 -07002993 initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime, 0);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002994 return entry;
2995}
2996
Jeff Brown7fbdc842010-06-17 20:52:56 -07002997InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -07002998 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
Jeff Brown7fbdc842010-06-17 20:52:56 -07002999 int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
3000 int32_t repeatCount, nsecs_t downTime) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003001 KeyEntry* entry = mKeyEntryPool.alloc();
Jeff Brownb6997262010-10-08 22:31:17 -07003002 initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime, policyFlags);
Jeff Brown7fbdc842010-06-17 20:52:56 -07003003
3004 entry->deviceId = deviceId;
Jeff Brownc5ed5912010-07-14 18:48:53 -07003005 entry->source = source;
Jeff Brown7fbdc842010-06-17 20:52:56 -07003006 entry->action = action;
3007 entry->flags = flags;
3008 entry->keyCode = keyCode;
3009 entry->scanCode = scanCode;
3010 entry->metaState = metaState;
3011 entry->repeatCount = repeatCount;
3012 entry->downTime = downTime;
Jeff Brownb88102f2010-09-08 11:49:43 -07003013 entry->syntheticRepeat = false;
3014 entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003015 return entry;
3016}
3017
Jeff Brown7fbdc842010-06-17 20:52:56 -07003018InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
Jeff Brown85a31762010-09-01 17:01:00 -07003019 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
Jeff Brown7fbdc842010-06-17 20:52:56 -07003020 int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
3021 nsecs_t downTime, uint32_t pointerCount,
3022 const int32_t* pointerIds, const PointerCoords* pointerCoords) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003023 MotionEntry* entry = mMotionEntryPool.alloc();
Jeff Brownb6997262010-10-08 22:31:17 -07003024 initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime, policyFlags);
Jeff Brown7fbdc842010-06-17 20:52:56 -07003025
3026 entry->eventTime = eventTime;
3027 entry->deviceId = deviceId;
Jeff Brownc5ed5912010-07-14 18:48:53 -07003028 entry->source = source;
Jeff Brown7fbdc842010-06-17 20:52:56 -07003029 entry->action = action;
Jeff Brown85a31762010-09-01 17:01:00 -07003030 entry->flags = flags;
Jeff Brown7fbdc842010-06-17 20:52:56 -07003031 entry->metaState = metaState;
3032 entry->edgeFlags = edgeFlags;
3033 entry->xPrecision = xPrecision;
3034 entry->yPrecision = yPrecision;
3035 entry->downTime = downTime;
3036 entry->pointerCount = pointerCount;
3037 entry->firstSample.eventTime = eventTime;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003038 entry->firstSample.next = NULL;
Jeff Brown7fbdc842010-06-17 20:52:56 -07003039 entry->lastSample = & entry->firstSample;
3040 for (uint32_t i = 0; i < pointerCount; i++) {
3041 entry->pointerIds[i] = pointerIds[i];
3042 entry->firstSample.pointerCoords[i] = pointerCoords[i];
3043 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003044 return entry;
3045}
3046
3047InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
Jeff Brownb88102f2010-09-08 11:49:43 -07003048 EventEntry* eventEntry,
Jeff Brown519e0242010-09-15 15:18:56 -07003049 int32_t targetFlags, float xOffset, float yOffset) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003050 DispatchEntry* entry = mDispatchEntryPool.alloc();
3051 entry->eventEntry = eventEntry;
3052 eventEntry->refCount += 1;
Jeff Brownb88102f2010-09-08 11:49:43 -07003053 entry->targetFlags = targetFlags;
3054 entry->xOffset = xOffset;
3055 entry->yOffset = yOffset;
Jeff Brownb88102f2010-09-08 11:49:43 -07003056 entry->inProgress = false;
3057 entry->headMotionSample = NULL;
3058 entry->tailMotionSample = NULL;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003059 return entry;
3060}
3061
Jeff Brown9c3cda02010-06-15 01:31:58 -07003062InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
3063 CommandEntry* entry = mCommandEntryPool.alloc();
3064 entry->command = command;
3065 return entry;
3066}
3067
Jeff Brown01ce2e92010-09-26 22:20:12 -07003068void InputDispatcher::Allocator::releaseInjectionState(InjectionState* injectionState) {
3069 injectionState->refCount -= 1;
3070 if (injectionState->refCount == 0) {
3071 mInjectionStatePool.free(injectionState);
3072 } else {
3073 assert(injectionState->refCount > 0);
3074 }
3075}
3076
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003077void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
3078 switch (entry->type) {
3079 case EventEntry::TYPE_CONFIGURATION_CHANGED:
3080 releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
3081 break;
3082 case EventEntry::TYPE_KEY:
3083 releaseKeyEntry(static_cast<KeyEntry*>(entry));
3084 break;
3085 case EventEntry::TYPE_MOTION:
3086 releaseMotionEntry(static_cast<MotionEntry*>(entry));
3087 break;
3088 default:
3089 assert(false);
3090 break;
3091 }
3092}
3093
3094void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
3095 ConfigurationChangedEntry* entry) {
3096 entry->refCount -= 1;
3097 if (entry->refCount == 0) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07003098 releaseEventEntryInjectionState(entry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003099 mConfigurationChangeEntryPool.free(entry);
3100 } else {
3101 assert(entry->refCount > 0);
3102 }
3103}
3104
3105void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
3106 entry->refCount -= 1;
3107 if (entry->refCount == 0) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07003108 releaseEventEntryInjectionState(entry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003109 mKeyEntryPool.free(entry);
3110 } else {
3111 assert(entry->refCount > 0);
3112 }
3113}
3114
3115void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
3116 entry->refCount -= 1;
3117 if (entry->refCount == 0) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07003118 releaseEventEntryInjectionState(entry);
Jeff Brown9c3cda02010-06-15 01:31:58 -07003119 for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
3120 MotionSample* next = sample->next;
3121 mMotionSamplePool.free(sample);
3122 sample = next;
3123 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003124 mMotionEntryPool.free(entry);
3125 } else {
3126 assert(entry->refCount > 0);
3127 }
3128}
3129
3130void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
3131 releaseEventEntry(entry->eventEntry);
3132 mDispatchEntryPool.free(entry);
3133}
3134
Jeff Brown9c3cda02010-06-15 01:31:58 -07003135void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
3136 mCommandEntryPool.free(entry);
3137}
3138
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003139void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
Jeff Brown7fbdc842010-06-17 20:52:56 -07003140 nsecs_t eventTime, const PointerCoords* pointerCoords) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003141 MotionSample* sample = mMotionSamplePool.alloc();
3142 sample->eventTime = eventTime;
Jeff Brown7fbdc842010-06-17 20:52:56 -07003143 uint32_t pointerCount = motionEntry->pointerCount;
3144 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003145 sample->pointerCoords[i] = pointerCoords[i];
3146 }
3147
3148 sample->next = NULL;
3149 motionEntry->lastSample->next = sample;
3150 motionEntry->lastSample = sample;
3151}
3152
Jeff Brown01ce2e92010-09-26 22:20:12 -07003153void InputDispatcher::Allocator::recycleKeyEntry(KeyEntry* keyEntry) {
3154 releaseEventEntryInjectionState(keyEntry);
Jeff Brownb88102f2010-09-08 11:49:43 -07003155
Jeff Brown01ce2e92010-09-26 22:20:12 -07003156 keyEntry->dispatchInProgress = false;
3157 keyEntry->syntheticRepeat = false;
3158 keyEntry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
Jeff Brownb88102f2010-09-08 11:49:43 -07003159}
3160
3161
Jeff Brownae9fc032010-08-18 15:51:08 -07003162// --- InputDispatcher::MotionEntry ---
3163
3164uint32_t InputDispatcher::MotionEntry::countSamples() const {
3165 uint32_t count = 1;
3166 for (MotionSample* sample = firstSample.next; sample != NULL; sample = sample->next) {
3167 count += 1;
3168 }
3169 return count;
3170}
3171
Jeff Brownb88102f2010-09-08 11:49:43 -07003172
3173// --- InputDispatcher::InputState ---
3174
Jeff Brownb6997262010-10-08 22:31:17 -07003175InputDispatcher::InputState::InputState() {
Jeff Brownb88102f2010-09-08 11:49:43 -07003176}
3177
3178InputDispatcher::InputState::~InputState() {
3179}
3180
3181bool InputDispatcher::InputState::isNeutral() const {
3182 return mKeyMementos.isEmpty() && mMotionMementos.isEmpty();
3183}
3184
Jeff Brownb88102f2010-09-08 11:49:43 -07003185InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackEvent(
3186 const EventEntry* entry) {
3187 switch (entry->type) {
3188 case EventEntry::TYPE_KEY:
3189 return trackKey(static_cast<const KeyEntry*>(entry));
3190
3191 case EventEntry::TYPE_MOTION:
3192 return trackMotion(static_cast<const MotionEntry*>(entry));
3193
3194 default:
3195 return CONSISTENT;
3196 }
3197}
3198
3199InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackKey(
3200 const KeyEntry* entry) {
3201 int32_t action = entry->action;
3202 for (size_t i = 0; i < mKeyMementos.size(); i++) {
3203 KeyMemento& memento = mKeyMementos.editItemAt(i);
3204 if (memento.deviceId == entry->deviceId
3205 && memento.source == entry->source
3206 && memento.keyCode == entry->keyCode
3207 && memento.scanCode == entry->scanCode) {
3208 switch (action) {
3209 case AKEY_EVENT_ACTION_UP:
3210 mKeyMementos.removeAt(i);
Jeff Brownb88102f2010-09-08 11:49:43 -07003211 return CONSISTENT;
3212
3213 case AKEY_EVENT_ACTION_DOWN:
3214 return TOLERABLE;
3215
3216 default:
3217 return BROKEN;
3218 }
3219 }
3220 }
3221
3222 switch (action) {
3223 case AKEY_EVENT_ACTION_DOWN: {
3224 mKeyMementos.push();
3225 KeyMemento& memento = mKeyMementos.editTop();
3226 memento.deviceId = entry->deviceId;
3227 memento.source = entry->source;
3228 memento.keyCode = entry->keyCode;
3229 memento.scanCode = entry->scanCode;
3230 memento.downTime = entry->downTime;
3231 return CONSISTENT;
3232 }
3233
3234 default:
3235 return BROKEN;
3236 }
3237}
3238
3239InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackMotion(
3240 const MotionEntry* entry) {
3241 int32_t action = entry->action & AMOTION_EVENT_ACTION_MASK;
3242 for (size_t i = 0; i < mMotionMementos.size(); i++) {
3243 MotionMemento& memento = mMotionMementos.editItemAt(i);
3244 if (memento.deviceId == entry->deviceId
3245 && memento.source == entry->source) {
3246 switch (action) {
3247 case AMOTION_EVENT_ACTION_UP:
3248 case AMOTION_EVENT_ACTION_CANCEL:
3249 mMotionMementos.removeAt(i);
Jeff Brownb88102f2010-09-08 11:49:43 -07003250 return CONSISTENT;
3251
3252 case AMOTION_EVENT_ACTION_DOWN:
3253 return TOLERABLE;
3254
3255 case AMOTION_EVENT_ACTION_POINTER_DOWN:
3256 if (entry->pointerCount == memento.pointerCount + 1) {
3257 memento.setPointers(entry);
3258 return CONSISTENT;
3259 }
3260 return BROKEN;
3261
3262 case AMOTION_EVENT_ACTION_POINTER_UP:
3263 if (entry->pointerCount == memento.pointerCount - 1) {
3264 memento.setPointers(entry);
3265 return CONSISTENT;
3266 }
3267 return BROKEN;
3268
3269 case AMOTION_EVENT_ACTION_MOVE:
3270 if (entry->pointerCount == memento.pointerCount) {
3271 return CONSISTENT;
3272 }
3273 return BROKEN;
3274
3275 default:
3276 return BROKEN;
3277 }
3278 }
3279 }
3280
3281 switch (action) {
3282 case AMOTION_EVENT_ACTION_DOWN: {
3283 mMotionMementos.push();
3284 MotionMemento& memento = mMotionMementos.editTop();
3285 memento.deviceId = entry->deviceId;
3286 memento.source = entry->source;
3287 memento.xPrecision = entry->xPrecision;
3288 memento.yPrecision = entry->yPrecision;
3289 memento.downTime = entry->downTime;
3290 memento.setPointers(entry);
3291 return CONSISTENT;
3292 }
3293
3294 default:
3295 return BROKEN;
3296 }
3297}
3298
3299void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) {
3300 pointerCount = entry->pointerCount;
3301 for (uint32_t i = 0; i < entry->pointerCount; i++) {
3302 pointerIds[i] = entry->pointerIds[i];
3303 pointerCoords[i] = entry->lastSample->pointerCoords[i];
3304 }
3305}
3306
Jeff Brownb6997262010-10-08 22:31:17 -07003307void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime,
3308 Allocator* allocator, Vector<EventEntry*>& outEvents,
3309 CancelationOptions options) {
3310 for (size_t i = 0; i < mKeyMementos.size(); ) {
Jeff Brownb88102f2010-09-08 11:49:43 -07003311 const KeyMemento& memento = mKeyMementos.itemAt(i);
Jeff Brownb6997262010-10-08 22:31:17 -07003312 if (shouldCancelEvent(memento.source, options)) {
3313 outEvents.push(allocator->obtainKeyEntry(currentTime,
3314 memento.deviceId, memento.source, 0,
3315 AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_CANCELED,
3316 memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
3317 mKeyMementos.removeAt(i);
3318 } else {
3319 i += 1;
3320 }
Jeff Brownb88102f2010-09-08 11:49:43 -07003321 }
3322
3323 for (size_t i = 0; i < mMotionMementos.size(); i++) {
3324 const MotionMemento& memento = mMotionMementos.itemAt(i);
Jeff Brownb6997262010-10-08 22:31:17 -07003325 if (shouldCancelEvent(memento.source, options)) {
3326 outEvents.push(allocator->obtainMotionEntry(currentTime,
3327 memento.deviceId, memento.source, 0,
3328 AMOTION_EVENT_ACTION_CANCEL, 0, 0, 0,
3329 memento.xPrecision, memento.yPrecision, memento.downTime,
3330 memento.pointerCount, memento.pointerIds, memento.pointerCoords));
3331 mMotionMementos.removeAt(i);
3332 } else {
3333 i += 1;
3334 }
Jeff Brownb88102f2010-09-08 11:49:43 -07003335 }
3336}
3337
3338void InputDispatcher::InputState::clear() {
3339 mKeyMementos.clear();
3340 mMotionMementos.clear();
Jeff Brownb6997262010-10-08 22:31:17 -07003341}
3342
3343bool InputDispatcher::InputState::shouldCancelEvent(int32_t eventSource,
3344 CancelationOptions options) {
3345 switch (options) {
3346 case CANCEL_POINTER_EVENTS:
3347 return eventSource & AINPUT_SOURCE_CLASS_POINTER;
3348 case CANCEL_NON_POINTER_EVENTS:
3349 return !(eventSource & AINPUT_SOURCE_CLASS_POINTER);
3350 default:
3351 return true;
3352 }
Jeff Brownb88102f2010-09-08 11:49:43 -07003353}
3354
3355
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003356// --- InputDispatcher::Connection ---
3357
3358InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
3359 status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
Jeff Brown519e0242010-09-15 15:18:56 -07003360 lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003361}
3362
3363InputDispatcher::Connection::~Connection() {
3364}
3365
3366status_t InputDispatcher::Connection::initialize() {
3367 return inputPublisher.initialize();
3368}
3369
Jeff Brown9c3cda02010-06-15 01:31:58 -07003370const char* InputDispatcher::Connection::getStatusLabel() const {
3371 switch (status) {
3372 case STATUS_NORMAL:
3373 return "NORMAL";
3374
3375 case STATUS_BROKEN:
3376 return "BROKEN";
3377
Jeff Brown9c3cda02010-06-15 01:31:58 -07003378 case STATUS_ZOMBIE:
3379 return "ZOMBIE";
3380
3381 default:
3382 return "UNKNOWN";
3383 }
3384}
3385
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003386InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
3387 const EventEntry* eventEntry) const {
Jeff Brownb88102f2010-09-08 11:49:43 -07003388 for (DispatchEntry* dispatchEntry = outboundQueue.tailSentinel.prev;
3389 dispatchEntry != & outboundQueue.headSentinel; dispatchEntry = dispatchEntry->prev) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003390 if (dispatchEntry->eventEntry == eventEntry) {
3391 return dispatchEntry;
3392 }
3393 }
3394 return NULL;
3395}
3396
Jeff Brownb88102f2010-09-08 11:49:43 -07003397
Jeff Brown9c3cda02010-06-15 01:31:58 -07003398// --- InputDispatcher::CommandEntry ---
3399
Jeff Brownb88102f2010-09-08 11:49:43 -07003400InputDispatcher::CommandEntry::CommandEntry() :
3401 keyEntry(NULL) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07003402}
3403
3404InputDispatcher::CommandEntry::~CommandEntry() {
3405}
3406
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003407
Jeff Brown01ce2e92010-09-26 22:20:12 -07003408// --- InputDispatcher::TouchState ---
3409
3410InputDispatcher::TouchState::TouchState() :
3411 down(false), split(false) {
3412}
3413
3414InputDispatcher::TouchState::~TouchState() {
3415}
3416
3417void InputDispatcher::TouchState::reset() {
3418 down = false;
3419 split = false;
3420 windows.clear();
3421}
3422
3423void InputDispatcher::TouchState::copyFrom(const TouchState& other) {
3424 down = other.down;
3425 split = other.split;
3426 windows.clear();
3427 windows.appendVector(other.windows);
3428}
3429
3430void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window,
3431 int32_t targetFlags, BitSet32 pointerIds) {
3432 if (targetFlags & InputTarget::FLAG_SPLIT) {
3433 split = true;
3434 }
3435
3436 for (size_t i = 0; i < windows.size(); i++) {
3437 TouchedWindow& touchedWindow = windows.editItemAt(i);
3438 if (touchedWindow.window == window) {
3439 touchedWindow.targetFlags |= targetFlags;
3440 touchedWindow.pointerIds.value |= pointerIds.value;
3441 return;
3442 }
3443 }
3444
3445 windows.push();
3446
3447 TouchedWindow& touchedWindow = windows.editTop();
3448 touchedWindow.window = window;
3449 touchedWindow.targetFlags = targetFlags;
3450 touchedWindow.pointerIds = pointerIds;
3451 touchedWindow.channel = window->inputChannel;
3452}
3453
3454void InputDispatcher::TouchState::removeOutsideTouchWindows() {
3455 for (size_t i = 0 ; i < windows.size(); ) {
3456 if (windows[i].targetFlags & InputTarget::FLAG_OUTSIDE) {
3457 windows.removeAt(i);
3458 } else {
3459 i += 1;
3460 }
3461 }
3462}
3463
3464const InputWindow* InputDispatcher::TouchState::getFirstForegroundWindow() {
3465 for (size_t i = 0; i < windows.size(); i++) {
3466 if (windows[i].targetFlags & InputTarget::FLAG_FOREGROUND) {
3467 return windows[i].window;
3468 }
3469 }
3470 return NULL;
3471}
3472
3473
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003474// --- InputDispatcherThread ---
3475
3476InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
3477 Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
3478}
3479
3480InputDispatcherThread::~InputDispatcherThread() {
3481}
3482
3483bool InputDispatcherThread::threadLoop() {
3484 mDispatcher->dispatchOnce();
3485 return true;
3486}
3487
3488} // namespace android