|
1 /* |
|
2 * Copyright (C) 2010 The Android Open Source Project |
|
3 * |
|
4 * Licensed under the Apache License, Version 2.0 (the "License"); |
|
5 * you may not use this file except in compliance with the License. |
|
6 * You may obtain a copy of the License at |
|
7 * |
|
8 * http://www.apache.org/licenses/LICENSE-2.0 |
|
9 * |
|
10 * Unless required by applicable law or agreed to in writing, software |
|
11 * distributed under the License is distributed on an "AS IS" BASIS, |
|
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
13 * See the License for the specific language governing permissions and |
|
14 * limitations under the License. |
|
15 */ |
|
16 |
|
17 #define LOG_TAG "InputDispatcher" |
|
18 #define ATRACE_TAG ATRACE_TAG_INPUT |
|
19 |
|
20 //#define LOG_NDEBUG 0 |
|
21 #include "cutils_log.h" |
|
22 |
|
23 // Log detailed debug messages about each inbound event notification to the dispatcher. |
|
24 #define DEBUG_INBOUND_EVENT_DETAILS 0 |
|
25 |
|
26 // Log detailed debug messages about each outbound event processed by the dispatcher. |
|
27 #define DEBUG_OUTBOUND_EVENT_DETAILS 0 |
|
28 |
|
29 // Log debug messages about the dispatch cycle. |
|
30 #define DEBUG_DISPATCH_CYCLE 0 |
|
31 |
|
32 // Log debug messages about registrations. |
|
33 #define DEBUG_REGISTRATION 0 |
|
34 |
|
35 // Log debug messages about input event injection. |
|
36 #define DEBUG_INJECTION 0 |
|
37 |
|
38 // Log debug messages about input focus tracking. |
|
39 #define DEBUG_FOCUS 0 |
|
40 |
|
41 // Log debug messages about the app switch latency optimization. |
|
42 #define DEBUG_APP_SWITCH 0 |
|
43 |
|
44 // Log debug messages about hover events. |
|
45 #define DEBUG_HOVER 0 |
|
46 |
|
47 #include "InputDispatcher.h" |
|
48 |
|
49 #include "Trace.h" |
|
50 #include "PowerManager.h" |
|
51 |
|
52 #include <stddef.h> |
|
53 #include <unistd.h> |
|
54 #include <errno.h> |
|
55 #include <limits.h> |
|
56 #include <time.h> |
|
57 |
|
58 #define INDENT " " |
|
59 #define INDENT2 " " |
|
60 #define INDENT3 " " |
|
61 #define INDENT4 " " |
|
62 |
|
63 namespace android { |
|
64 |
|
65 // Default input dispatching timeout if there is no focused application or paused window |
|
66 // from which to determine an appropriate dispatching timeout. |
|
67 const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec |
|
68 |
|
69 // Amount of time to allow for all pending events to be processed when an app switch |
|
70 // key is on the way. This is used to preempt input dispatch and drop input events |
|
71 // when an application takes too long to respond and the user has pressed an app switch key. |
|
72 const nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec |
|
73 |
|
74 // Amount of time to allow for an event to be dispatched (measured since its eventTime) |
|
75 // before considering it stale and dropping it. |
|
76 const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL; // 10sec |
|
77 |
|
78 // Amount of time to allow touch events to be streamed out to a connection before requiring |
|
79 // that the first event be finished. This value extends the ANR timeout by the specified |
|
80 // amount. For example, if streaming is allowed to get ahead by one second relative to the |
|
81 // queue of waiting unfinished events, then ANRs will similarly be delayed by one second. |
|
82 const nsecs_t STREAM_AHEAD_EVENT_TIMEOUT = 500 * 1000000LL; // 0.5sec |
|
83 |
|
84 // Log a warning when an event takes longer than this to process, even if an ANR does not occur. |
|
85 const nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec |
|
86 |
|
87 |
|
88 static inline nsecs_t now() { |
|
89 return systemTime(SYSTEM_TIME_MONOTONIC); |
|
90 } |
|
91 |
|
92 static inline const char* toString(bool value) { |
|
93 return value ? "true" : "false"; |
|
94 } |
|
95 |
|
96 static inline int32_t getMotionEventActionPointerIndex(int32_t action) { |
|
97 return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) |
|
98 >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; |
|
99 } |
|
100 |
|
101 static bool isValidKeyAction(int32_t action) { |
|
102 switch (action) { |
|
103 case AKEY_EVENT_ACTION_DOWN: |
|
104 case AKEY_EVENT_ACTION_UP: |
|
105 return true; |
|
106 default: |
|
107 return false; |
|
108 } |
|
109 } |
|
110 |
|
111 static bool validateKeyEvent(int32_t action) { |
|
112 if (! isValidKeyAction(action)) { |
|
113 ALOGE("Key event has invalid action code 0x%x", action); |
|
114 return false; |
|
115 } |
|
116 return true; |
|
117 } |
|
118 |
|
119 static bool isValidMotionAction(int32_t action, size_t pointerCount) { |
|
120 switch (action & AMOTION_EVENT_ACTION_MASK) { |
|
121 case AMOTION_EVENT_ACTION_DOWN: |
|
122 case AMOTION_EVENT_ACTION_UP: |
|
123 case AMOTION_EVENT_ACTION_CANCEL: |
|
124 case AMOTION_EVENT_ACTION_MOVE: |
|
125 case AMOTION_EVENT_ACTION_OUTSIDE: |
|
126 case AMOTION_EVENT_ACTION_HOVER_ENTER: |
|
127 case AMOTION_EVENT_ACTION_HOVER_MOVE: |
|
128 case AMOTION_EVENT_ACTION_HOVER_EXIT: |
|
129 case AMOTION_EVENT_ACTION_SCROLL: |
|
130 return true; |
|
131 case AMOTION_EVENT_ACTION_POINTER_DOWN: |
|
132 case AMOTION_EVENT_ACTION_POINTER_UP: { |
|
133 int32_t index = getMotionEventActionPointerIndex(action); |
|
134 return index >= 0 && size_t(index) < pointerCount; |
|
135 } |
|
136 default: |
|
137 return false; |
|
138 } |
|
139 } |
|
140 |
|
141 static bool validateMotionEvent(int32_t action, size_t pointerCount, |
|
142 const PointerProperties* pointerProperties) { |
|
143 if (! isValidMotionAction(action, pointerCount)) { |
|
144 ALOGE("Motion event has invalid action code 0x%x", action); |
|
145 return false; |
|
146 } |
|
147 if (pointerCount < 1 || pointerCount > MAX_POINTERS) { |
|
148 ALOGE("Motion event has invalid pointer count %d; value must be between 1 and %d.", |
|
149 pointerCount, MAX_POINTERS); |
|
150 return false; |
|
151 } |
|
152 BitSet32 pointerIdBits; |
|
153 for (size_t i = 0; i < pointerCount; i++) { |
|
154 int32_t id = pointerProperties[i].id; |
|
155 if (id < 0 || id > MAX_POINTER_ID) { |
|
156 ALOGE("Motion event has invalid pointer id %d; value must be between 0 and %d", |
|
157 id, MAX_POINTER_ID); |
|
158 return false; |
|
159 } |
|
160 if (pointerIdBits.hasBit(id)) { |
|
161 ALOGE("Motion event has duplicate pointer id %d", id); |
|
162 return false; |
|
163 } |
|
164 pointerIdBits.markBit(id); |
|
165 } |
|
166 return true; |
|
167 } |
|
168 |
|
169 static bool isMainDisplay(int32_t displayId) { |
|
170 return displayId == ADISPLAY_ID_DEFAULT || displayId == ADISPLAY_ID_NONE; |
|
171 } |
|
172 |
|
173 static void dumpRegion(String8& dump, const SkRegion& region) { |
|
174 if (region.isEmpty()) { |
|
175 dump.append("<empty>"); |
|
176 return; |
|
177 } |
|
178 |
|
179 bool first = true; |
|
180 for (SkRegion::Iterator it(region); !it.done(); it.next()) { |
|
181 if (first) { |
|
182 first = false; |
|
183 } else { |
|
184 dump.append("|"); |
|
185 } |
|
186 const SkIRect& rect = it.rect(); |
|
187 dump.appendFormat("[%d,%d][%d,%d]", rect.fLeft, rect.fTop, rect.fRight, rect.fBottom); |
|
188 } |
|
189 } |
|
190 |
|
191 |
|
192 // --- InputDispatcher --- |
|
193 |
|
194 InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) : |
|
195 mPolicy(policy), |
|
196 mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX), |
|
197 mNextUnblockedEvent(NULL), |
|
198 mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false), |
|
199 mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) { |
|
200 mLooper = new Looper(false); |
|
201 |
|
202 mKeyRepeatState.lastKeyEntry = NULL; |
|
203 |
|
204 policy->getDispatcherConfiguration(&mConfig); |
|
205 } |
|
206 |
|
207 InputDispatcher::~InputDispatcher() { |
|
208 { // acquire lock |
|
209 AutoMutex _l(mLock); |
|
210 |
|
211 resetKeyRepeatLocked(); |
|
212 releasePendingEventLocked(); |
|
213 drainInboundQueueLocked(); |
|
214 } |
|
215 |
|
216 while (mConnectionsByFd.size() != 0) { |
|
217 unregisterInputChannel(mConnectionsByFd.valueAt(0)->inputChannel); |
|
218 } |
|
219 } |
|
220 |
|
221 void InputDispatcher::dispatchOnce() { |
|
222 nsecs_t nextWakeupTime = LONG_LONG_MAX; |
|
223 { // acquire lock |
|
224 AutoMutex _l(mLock); |
|
225 mDispatcherIsAliveCondition.broadcast(); |
|
226 |
|
227 // Run a dispatch loop if there are no pending commands. |
|
228 // The dispatch loop might enqueue commands to run afterwards. |
|
229 if (!haveCommandsLocked()) { |
|
230 dispatchOnceInnerLocked(&nextWakeupTime); |
|
231 } |
|
232 |
|
233 // Run all pending commands if there are any. |
|
234 // If any commands were run then force the next poll to wake up immediately. |
|
235 if (runCommandsLockedInterruptible()) { |
|
236 nextWakeupTime = LONG_LONG_MIN; |
|
237 } |
|
238 } // release lock |
|
239 |
|
240 // Wait for callback or timeout or wake. (make sure we round up, not down) |
|
241 nsecs_t currentTime = now(); |
|
242 int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime); |
|
243 mLooper->pollOnce(timeoutMillis); |
|
244 } |
|
245 |
|
246 void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { |
|
247 nsecs_t currentTime = now(); |
|
248 |
|
249 // Reset the key repeat timer whenever we disallow key events, even if the next event |
|
250 // is not a key. This is to ensure that we abort a key repeat if the device is just coming |
|
251 // out of sleep. |
|
252 if (!mPolicy->isKeyRepeatEnabled()) { |
|
253 resetKeyRepeatLocked(); |
|
254 } |
|
255 |
|
256 // If dispatching is frozen, do not process timeouts or try to deliver any new events. |
|
257 if (mDispatchFrozen) { |
|
258 #if DEBUG_FOCUS |
|
259 ALOGD("Dispatch frozen. Waiting some more."); |
|
260 #endif |
|
261 return; |
|
262 } |
|
263 |
|
264 // Optimize latency of app switches. |
|
265 // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has |
|
266 // been pressed. When it expires, we preempt dispatch and drop all other pending events. |
|
267 bool isAppSwitchDue = mAppSwitchDueTime <= currentTime; |
|
268 if (mAppSwitchDueTime < *nextWakeupTime) { |
|
269 *nextWakeupTime = mAppSwitchDueTime; |
|
270 } |
|
271 |
|
272 // Ready to start a new event. |
|
273 // If we don't already have a pending event, go grab one. |
|
274 if (! mPendingEvent) { |
|
275 if (mInboundQueue.isEmpty()) { |
|
276 if (isAppSwitchDue) { |
|
277 // The inbound queue is empty so the app switch key we were waiting |
|
278 // for will never arrive. Stop waiting for it. |
|
279 resetPendingAppSwitchLocked(false); |
|
280 isAppSwitchDue = false; |
|
281 } |
|
282 |
|
283 // Synthesize a key repeat if appropriate. |
|
284 if (mKeyRepeatState.lastKeyEntry) { |
|
285 if (currentTime >= mKeyRepeatState.nextRepeatTime) { |
|
286 mPendingEvent = synthesizeKeyRepeatLocked(currentTime); |
|
287 } else { |
|
288 if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) { |
|
289 *nextWakeupTime = mKeyRepeatState.nextRepeatTime; |
|
290 } |
|
291 } |
|
292 } |
|
293 |
|
294 // Nothing to do if there is no pending event. |
|
295 if (!mPendingEvent) { |
|
296 return; |
|
297 } |
|
298 } else { |
|
299 // Inbound queue has at least one entry. |
|
300 mPendingEvent = mInboundQueue.dequeueAtHead(); |
|
301 traceInboundQueueLengthLocked(); |
|
302 } |
|
303 |
|
304 // Poke user activity for this event. |
|
305 if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) { |
|
306 pokeUserActivityLocked(mPendingEvent); |
|
307 } |
|
308 |
|
309 // Get ready to dispatch the event. |
|
310 resetANRTimeoutsLocked(); |
|
311 } |
|
312 |
|
313 // Now we have an event to dispatch. |
|
314 // All events are eventually dequeued and processed this way, even if we intend to drop them. |
|
315 ALOG_ASSERT(mPendingEvent != NULL); |
|
316 bool done = false; |
|
317 DropReason dropReason = DROP_REASON_NOT_DROPPED; |
|
318 if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) { |
|
319 dropReason = DROP_REASON_POLICY; |
|
320 } else if (!mDispatchEnabled) { |
|
321 dropReason = DROP_REASON_DISABLED; |
|
322 } |
|
323 |
|
324 if (mNextUnblockedEvent == mPendingEvent) { |
|
325 mNextUnblockedEvent = NULL; |
|
326 } |
|
327 |
|
328 switch (mPendingEvent->type) { |
|
329 case EventEntry::TYPE_CONFIGURATION_CHANGED: { |
|
330 ConfigurationChangedEntry* typedEntry = |
|
331 static_cast<ConfigurationChangedEntry*>(mPendingEvent); |
|
332 done = dispatchConfigurationChangedLocked(currentTime, typedEntry); |
|
333 dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped |
|
334 break; |
|
335 } |
|
336 |
|
337 case EventEntry::TYPE_DEVICE_RESET: { |
|
338 DeviceResetEntry* typedEntry = |
|
339 static_cast<DeviceResetEntry*>(mPendingEvent); |
|
340 done = dispatchDeviceResetLocked(currentTime, typedEntry); |
|
341 dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped |
|
342 break; |
|
343 } |
|
344 |
|
345 case EventEntry::TYPE_KEY: { |
|
346 KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent); |
|
347 if (isAppSwitchDue) { |
|
348 if (isAppSwitchKeyEventLocked(typedEntry)) { |
|
349 resetPendingAppSwitchLocked(true); |
|
350 isAppSwitchDue = false; |
|
351 } else if (dropReason == DROP_REASON_NOT_DROPPED) { |
|
352 dropReason = DROP_REASON_APP_SWITCH; |
|
353 } |
|
354 } |
|
355 if (dropReason == DROP_REASON_NOT_DROPPED |
|
356 && isStaleEventLocked(currentTime, typedEntry)) { |
|
357 dropReason = DROP_REASON_STALE; |
|
358 } |
|
359 if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) { |
|
360 dropReason = DROP_REASON_BLOCKED; |
|
361 } |
|
362 done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime); |
|
363 break; |
|
364 } |
|
365 |
|
366 case EventEntry::TYPE_MOTION: { |
|
367 MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent); |
|
368 if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) { |
|
369 dropReason = DROP_REASON_APP_SWITCH; |
|
370 } |
|
371 if (dropReason == DROP_REASON_NOT_DROPPED |
|
372 && isStaleEventLocked(currentTime, typedEntry)) { |
|
373 dropReason = DROP_REASON_STALE; |
|
374 } |
|
375 if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) { |
|
376 dropReason = DROP_REASON_BLOCKED; |
|
377 } |
|
378 done = dispatchMotionLocked(currentTime, typedEntry, |
|
379 &dropReason, nextWakeupTime); |
|
380 break; |
|
381 } |
|
382 |
|
383 default: |
|
384 ALOG_ASSERT(false); |
|
385 break; |
|
386 } |
|
387 |
|
388 if (done) { |
|
389 if (dropReason != DROP_REASON_NOT_DROPPED) { |
|
390 dropInboundEventLocked(mPendingEvent, dropReason); |
|
391 } |
|
392 |
|
393 releasePendingEventLocked(); |
|
394 *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately |
|
395 } |
|
396 } |
|
397 |
|
398 bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { |
|
399 bool needWake = mInboundQueue.isEmpty(); |
|
400 mInboundQueue.enqueueAtTail(entry); |
|
401 traceInboundQueueLengthLocked(); |
|
402 |
|
403 switch (entry->type) { |
|
404 case EventEntry::TYPE_KEY: { |
|
405 // Optimize app switch latency. |
|
406 // If the application takes too long to catch up then we drop all events preceding |
|
407 // the app switch 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 ALOGD("App switch is pending!"); |
|
416 #endif |
|
417 mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT; |
|
418 mAppSwitchSawKeyDown = false; |
|
419 needWake = true; |
|
420 } |
|
421 } |
|
422 } |
|
423 break; |
|
424 } |
|
425 |
|
426 case EventEntry::TYPE_MOTION: { |
|
427 // Optimize case where the current application is unresponsive and the user |
|
428 // decides to touch a window in a different application. |
|
429 // If the application takes too long to catch up then we drop all events preceding |
|
430 // the touch into the other window. |
|
431 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry); |
|
432 if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN |
|
433 && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) |
|
434 && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY |
|
435 && mInputTargetWaitApplicationHandle != NULL) { |
|
436 int32_t displayId = motionEntry->displayId; |
|
437 int32_t x = int32_t(motionEntry->pointerCoords[0]. |
|
438 getAxisValue(AMOTION_EVENT_AXIS_X)); |
|
439 int32_t y = int32_t(motionEntry->pointerCoords[0]. |
|
440 getAxisValue(AMOTION_EVENT_AXIS_Y)); |
|
441 sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y); |
|
442 if (touchedWindowHandle != NULL |
|
443 && touchedWindowHandle->inputApplicationHandle |
|
444 != mInputTargetWaitApplicationHandle) { |
|
445 // User touched a different application than the one we are waiting on. |
|
446 // Flag the event, and start pruning the input queue. |
|
447 mNextUnblockedEvent = motionEntry; |
|
448 needWake = true; |
|
449 } |
|
450 } |
|
451 break; |
|
452 } |
|
453 } |
|
454 |
|
455 return needWake; |
|
456 } |
|
457 |
|
458 sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, |
|
459 int32_t x, int32_t y) { |
|
460 // Traverse windows from front to back to find touched window. |
|
461 size_t numWindows = mWindowHandles.size(); |
|
462 for (size_t i = 0; i < numWindows; i++) { |
|
463 sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i); |
|
464 const InputWindowInfo* windowInfo = windowHandle->getInfo(); |
|
465 if (windowInfo->displayId == displayId) { |
|
466 int32_t flags = windowInfo->layoutParamsFlags; |
|
467 |
|
468 if (windowInfo->visible) { |
|
469 if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) { |
|
470 bool isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE |
|
471 | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0; |
|
472 if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) { |
|
473 // Found window. |
|
474 return windowHandle; |
|
475 } |
|
476 } |
|
477 } |
|
478 |
|
479 if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) { |
|
480 // Error window is on top but not visible, so touch is dropped. |
|
481 return NULL; |
|
482 } |
|
483 } |
|
484 } |
|
485 return NULL; |
|
486 } |
|
487 |
|
488 void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) { |
|
489 const char* reason; |
|
490 switch (dropReason) { |
|
491 case DROP_REASON_POLICY: |
|
492 #if DEBUG_INBOUND_EVENT_DETAILS |
|
493 ALOGD("Dropped event because policy consumed it."); |
|
494 #endif |
|
495 reason = "inbound event was dropped because the policy consumed it"; |
|
496 break; |
|
497 case DROP_REASON_DISABLED: |
|
498 ALOGI("Dropped event because input dispatch is disabled."); |
|
499 reason = "inbound event was dropped because input dispatch is disabled"; |
|
500 break; |
|
501 case DROP_REASON_APP_SWITCH: |
|
502 ALOGI("Dropped event because of pending overdue app switch."); |
|
503 reason = "inbound event was dropped because of pending overdue app switch"; |
|
504 break; |
|
505 case DROP_REASON_BLOCKED: |
|
506 ALOGI("Dropped event because the current application is not responding and the user " |
|
507 "has started interacting with a different application."); |
|
508 reason = "inbound event was dropped because the current application is not responding " |
|
509 "and the user has started interacting with a different application"; |
|
510 break; |
|
511 case DROP_REASON_STALE: |
|
512 ALOGI("Dropped event because it is stale."); |
|
513 reason = "inbound event was dropped because it is stale"; |
|
514 break; |
|
515 default: |
|
516 ALOG_ASSERT(false); |
|
517 return; |
|
518 } |
|
519 |
|
520 switch (entry->type) { |
|
521 case EventEntry::TYPE_KEY: { |
|
522 CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, reason); |
|
523 synthesizeCancelationEventsForAllConnectionsLocked(options); |
|
524 break; |
|
525 } |
|
526 case EventEntry::TYPE_MOTION: { |
|
527 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry); |
|
528 if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) { |
|
529 CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, reason); |
|
530 synthesizeCancelationEventsForAllConnectionsLocked(options); |
|
531 } else { |
|
532 CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, reason); |
|
533 synthesizeCancelationEventsForAllConnectionsLocked(options); |
|
534 } |
|
535 break; |
|
536 } |
|
537 } |
|
538 } |
|
539 |
|
540 bool InputDispatcher::isAppSwitchKeyCode(int32_t keyCode) { |
|
541 return keyCode == AKEYCODE_HOME |
|
542 || keyCode == AKEYCODE_ENDCALL |
|
543 || keyCode == AKEYCODE_APP_SWITCH; |
|
544 } |
|
545 |
|
546 bool InputDispatcher::isAppSwitchKeyEventLocked(KeyEntry* keyEntry) { |
|
547 return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) |
|
548 && isAppSwitchKeyCode(keyEntry->keyCode) |
|
549 && (keyEntry->policyFlags & POLICY_FLAG_TRUSTED) |
|
550 && (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER); |
|
551 } |
|
552 |
|
553 bool InputDispatcher::isAppSwitchPendingLocked() { |
|
554 return mAppSwitchDueTime != LONG_LONG_MAX; |
|
555 } |
|
556 |
|
557 void InputDispatcher::resetPendingAppSwitchLocked(bool handled) { |
|
558 mAppSwitchDueTime = LONG_LONG_MAX; |
|
559 |
|
560 #if DEBUG_APP_SWITCH |
|
561 if (handled) { |
|
562 ALOGD("App switch has arrived."); |
|
563 } else { |
|
564 ALOGD("App switch was abandoned."); |
|
565 } |
|
566 #endif |
|
567 } |
|
568 |
|
569 bool InputDispatcher::isStaleEventLocked(nsecs_t currentTime, EventEntry* entry) { |
|
570 return currentTime - entry->eventTime >= STALE_EVENT_TIMEOUT; |
|
571 } |
|
572 |
|
573 bool InputDispatcher::haveCommandsLocked() const { |
|
574 return !mCommandQueue.isEmpty(); |
|
575 } |
|
576 |
|
577 bool InputDispatcher::runCommandsLockedInterruptible() { |
|
578 if (mCommandQueue.isEmpty()) { |
|
579 return false; |
|
580 } |
|
581 |
|
582 do { |
|
583 CommandEntry* commandEntry = mCommandQueue.dequeueAtHead(); |
|
584 |
|
585 Command command = commandEntry->command; |
|
586 (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible' |
|
587 |
|
588 commandEntry->connection.clear(); |
|
589 delete commandEntry; |
|
590 } while (! mCommandQueue.isEmpty()); |
|
591 return true; |
|
592 } |
|
593 |
|
594 InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) { |
|
595 CommandEntry* commandEntry = new CommandEntry(command); |
|
596 mCommandQueue.enqueueAtTail(commandEntry); |
|
597 return commandEntry; |
|
598 } |
|
599 |
|
600 void InputDispatcher::drainInboundQueueLocked() { |
|
601 while (! mInboundQueue.isEmpty()) { |
|
602 EventEntry* entry = mInboundQueue.dequeueAtHead(); |
|
603 releaseInboundEventLocked(entry); |
|
604 } |
|
605 traceInboundQueueLengthLocked(); |
|
606 } |
|
607 |
|
608 void InputDispatcher::releasePendingEventLocked() { |
|
609 if (mPendingEvent) { |
|
610 resetANRTimeoutsLocked(); |
|
611 releaseInboundEventLocked(mPendingEvent); |
|
612 mPendingEvent = NULL; |
|
613 } |
|
614 } |
|
615 |
|
616 void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) { |
|
617 InjectionState* injectionState = entry->injectionState; |
|
618 if (injectionState && injectionState->injectionResult == INPUT_EVENT_INJECTION_PENDING) { |
|
619 #if DEBUG_DISPATCH_CYCLE |
|
620 ALOGD("Injected inbound event was dropped."); |
|
621 #endif |
|
622 setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED); |
|
623 } |
|
624 if (entry == mNextUnblockedEvent) { |
|
625 mNextUnblockedEvent = NULL; |
|
626 } |
|
627 entry->release(); |
|
628 } |
|
629 |
|
630 void InputDispatcher::resetKeyRepeatLocked() { |
|
631 if (mKeyRepeatState.lastKeyEntry) { |
|
632 mKeyRepeatState.lastKeyEntry->release(); |
|
633 mKeyRepeatState.lastKeyEntry = NULL; |
|
634 } |
|
635 } |
|
636 |
|
637 InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(nsecs_t currentTime) { |
|
638 KeyEntry* entry = mKeyRepeatState.lastKeyEntry; |
|
639 |
|
640 // Reuse the repeated key entry if it is otherwise unreferenced. |
|
641 uint32_t policyFlags = (entry->policyFlags & POLICY_FLAG_RAW_MASK) |
|
642 | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED; |
|
643 if (entry->refCount == 1) { |
|
644 entry->recycle(); |
|
645 entry->eventTime = currentTime; |
|
646 entry->policyFlags = policyFlags; |
|
647 entry->repeatCount += 1; |
|
648 } else { |
|
649 KeyEntry* newEntry = new KeyEntry(currentTime, |
|
650 entry->deviceId, entry->source, policyFlags, |
|
651 entry->action, entry->flags, entry->keyCode, entry->scanCode, |
|
652 entry->metaState, entry->repeatCount + 1, entry->downTime); |
|
653 |
|
654 mKeyRepeatState.lastKeyEntry = newEntry; |
|
655 entry->release(); |
|
656 |
|
657 entry = newEntry; |
|
658 } |
|
659 entry->syntheticRepeat = true; |
|
660 |
|
661 // Increment reference count since we keep a reference to the event in |
|
662 // mKeyRepeatState.lastKeyEntry in addition to the one we return. |
|
663 entry->refCount += 1; |
|
664 |
|
665 mKeyRepeatState.nextRepeatTime = currentTime + mConfig.keyRepeatDelay; |
|
666 return entry; |
|
667 } |
|
668 |
|
669 bool InputDispatcher::dispatchConfigurationChangedLocked( |
|
670 nsecs_t currentTime, ConfigurationChangedEntry* entry) { |
|
671 #if DEBUG_OUTBOUND_EVENT_DETAILS |
|
672 ALOGD("dispatchConfigurationChanged - eventTime=%lld", entry->eventTime); |
|
673 #endif |
|
674 |
|
675 // Reset key repeating in case a keyboard device was added or removed or something. |
|
676 resetKeyRepeatLocked(); |
|
677 |
|
678 // Enqueue a command to run outside the lock to tell the policy that the configuration changed. |
|
679 CommandEntry* commandEntry = postCommandLocked( |
|
680 & InputDispatcher::doNotifyConfigurationChangedInterruptible); |
|
681 commandEntry->eventTime = entry->eventTime; |
|
682 return true; |
|
683 } |
|
684 |
|
685 bool InputDispatcher::dispatchDeviceResetLocked( |
|
686 nsecs_t currentTime, DeviceResetEntry* entry) { |
|
687 #if DEBUG_OUTBOUND_EVENT_DETAILS |
|
688 ALOGD("dispatchDeviceReset - eventTime=%lld, deviceId=%d", entry->eventTime, entry->deviceId); |
|
689 #endif |
|
690 |
|
691 CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS, |
|
692 "device was reset"); |
|
693 options.deviceId = entry->deviceId; |
|
694 synthesizeCancelationEventsForAllConnectionsLocked(options); |
|
695 return true; |
|
696 } |
|
697 |
|
698 bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry, |
|
699 DropReason* dropReason, nsecs_t* nextWakeupTime) { |
|
700 // Preprocessing. |
|
701 if (! entry->dispatchInProgress) { |
|
702 if (entry->repeatCount == 0 |
|
703 && entry->action == AKEY_EVENT_ACTION_DOWN |
|
704 && (entry->policyFlags & POLICY_FLAG_TRUSTED) |
|
705 && (!(entry->policyFlags & POLICY_FLAG_DISABLE_KEY_REPEAT))) { |
|
706 if (mKeyRepeatState.lastKeyEntry |
|
707 && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) { |
|
708 // We have seen two identical key downs in a row which indicates that the device |
|
709 // driver is automatically generating key repeats itself. We take note of the |
|
710 // repeat here, but we disable our own next key repeat timer since it is clear that |
|
711 // we will not need to synthesize key repeats ourselves. |
|
712 entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1; |
|
713 resetKeyRepeatLocked(); |
|
714 mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves |
|
715 } else { |
|
716 // Not a repeat. Save key down state in case we do see a repeat later. |
|
717 resetKeyRepeatLocked(); |
|
718 mKeyRepeatState.nextRepeatTime = entry->eventTime + mConfig.keyRepeatTimeout; |
|
719 } |
|
720 mKeyRepeatState.lastKeyEntry = entry; |
|
721 entry->refCount += 1; |
|
722 } else if (! entry->syntheticRepeat) { |
|
723 resetKeyRepeatLocked(); |
|
724 } |
|
725 |
|
726 if (entry->repeatCount == 1) { |
|
727 entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS; |
|
728 } else { |
|
729 entry->flags &= ~AKEY_EVENT_FLAG_LONG_PRESS; |
|
730 } |
|
731 |
|
732 entry->dispatchInProgress = true; |
|
733 |
|
734 logOutboundKeyDetailsLocked("dispatchKey - ", entry); |
|
735 } |
|
736 |
|
737 // Handle case where the policy asked us to try again later last time. |
|
738 if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) { |
|
739 if (currentTime < entry->interceptKeyWakeupTime) { |
|
740 if (entry->interceptKeyWakeupTime < *nextWakeupTime) { |
|
741 *nextWakeupTime = entry->interceptKeyWakeupTime; |
|
742 } |
|
743 return false; // wait until next wakeup |
|
744 } |
|
745 entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN; |
|
746 entry->interceptKeyWakeupTime = 0; |
|
747 } |
|
748 |
|
749 // Give the policy a chance to intercept the key. |
|
750 if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) { |
|
751 if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) { |
|
752 CommandEntry* commandEntry = postCommandLocked( |
|
753 & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible); |
|
754 if (mFocusedWindowHandle != NULL) { |
|
755 commandEntry->inputWindowHandle = mFocusedWindowHandle; |
|
756 } |
|
757 commandEntry->keyEntry = entry; |
|
758 entry->refCount += 1; |
|
759 return false; // wait for the command to run |
|
760 } else { |
|
761 entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE; |
|
762 } |
|
763 } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) { |
|
764 if (*dropReason == DROP_REASON_NOT_DROPPED) { |
|
765 *dropReason = DROP_REASON_POLICY; |
|
766 } |
|
767 } |
|
768 |
|
769 // Clean up if dropping the event. |
|
770 if (*dropReason != DROP_REASON_NOT_DROPPED) { |
|
771 setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY |
|
772 ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED); |
|
773 return true; |
|
774 } |
|
775 |
|
776 // Identify targets. |
|
777 Vector<InputTarget> inputTargets; |
|
778 int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime, |
|
779 entry, inputTargets, nextWakeupTime); |
|
780 if (injectionResult == INPUT_EVENT_INJECTION_PENDING) { |
|
781 return false; |
|
782 } |
|
783 |
|
784 setInjectionResultLocked(entry, injectionResult); |
|
785 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) { |
|
786 return true; |
|
787 } |
|
788 |
|
789 addMonitoringTargetsLocked(inputTargets); |
|
790 |
|
791 // Dispatch the key. |
|
792 dispatchEventLocked(currentTime, entry, inputTargets); |
|
793 return true; |
|
794 } |
|
795 |
|
796 void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry) { |
|
797 #if DEBUG_OUTBOUND_EVENT_DETAILS |
|
798 ALOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, " |
|
799 "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, " |
|
800 "repeatCount=%d, downTime=%lld", |
|
801 prefix, |
|
802 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, |
|
803 entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState, |
|
804 entry->repeatCount, entry->downTime); |
|
805 #endif |
|
806 } |
|
807 |
|
808 bool InputDispatcher::dispatchMotionLocked( |
|
809 nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) { |
|
810 // Preprocessing. |
|
811 if (! entry->dispatchInProgress) { |
|
812 entry->dispatchInProgress = true; |
|
813 |
|
814 logOutboundMotionDetailsLocked("dispatchMotion - ", entry); |
|
815 } |
|
816 |
|
817 // Clean up if dropping the event. |
|
818 if (*dropReason != DROP_REASON_NOT_DROPPED) { |
|
819 setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY |
|
820 ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED); |
|
821 return true; |
|
822 } |
|
823 |
|
824 bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER; |
|
825 |
|
826 // Identify targets. |
|
827 Vector<InputTarget> inputTargets; |
|
828 |
|
829 bool conflictingPointerActions = false; |
|
830 int32_t injectionResult; |
|
831 if (isPointerEvent) { |
|
832 // Pointer event. (eg. touchscreen) |
|
833 injectionResult = findTouchedWindowTargetsLocked(currentTime, |
|
834 entry, inputTargets, nextWakeupTime, &conflictingPointerActions); |
|
835 } else { |
|
836 // Non touch event. (eg. trackball) |
|
837 injectionResult = findFocusedWindowTargetsLocked(currentTime, |
|
838 entry, inputTargets, nextWakeupTime); |
|
839 } |
|
840 if (injectionResult == INPUT_EVENT_INJECTION_PENDING) { |
|
841 return false; |
|
842 } |
|
843 |
|
844 setInjectionResultLocked(entry, injectionResult); |
|
845 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) { |
|
846 return true; |
|
847 } |
|
848 |
|
849 // TODO: support sending secondary display events to input monitors |
|
850 if (isMainDisplay(entry->displayId)) { |
|
851 addMonitoringTargetsLocked(inputTargets); |
|
852 } |
|
853 |
|
854 // Dispatch the motion. |
|
855 if (conflictingPointerActions) { |
|
856 CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, |
|
857 "conflicting pointer actions"); |
|
858 synthesizeCancelationEventsForAllConnectionsLocked(options); |
|
859 } |
|
860 dispatchEventLocked(currentTime, entry, inputTargets); |
|
861 return true; |
|
862 } |
|
863 |
|
864 |
|
865 void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) { |
|
866 #if DEBUG_OUTBOUND_EVENT_DETAILS |
|
867 ALOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, " |
|
868 "action=0x%x, flags=0x%x, " |
|
869 "metaState=0x%x, buttonState=0x%x, " |
|
870 "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld", |
|
871 prefix, |
|
872 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, |
|
873 entry->action, entry->flags, |
|
874 entry->metaState, entry->buttonState, |
|
875 entry->edgeFlags, entry->xPrecision, entry->yPrecision, |
|
876 entry->downTime); |
|
877 |
|
878 for (uint32_t i = 0; i < entry->pointerCount; i++) { |
|
879 ALOGD(" Pointer %d: id=%d, toolType=%d, " |
|
880 "x=%f, y=%f, pressure=%f, size=%f, " |
|
881 "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, " |
|
882 "orientation=%f", |
|
883 i, entry->pointerProperties[i].id, |
|
884 entry->pointerProperties[i].toolType, |
|
885 entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X), |
|
886 entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y), |
|
887 entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), |
|
888 entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE), |
|
889 entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR), |
|
890 entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR), |
|
891 entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), |
|
892 entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), |
|
893 entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION)); |
|
894 } |
|
895 #endif |
|
896 } |
|
897 |
|
898 void InputDispatcher::dispatchEventLocked(nsecs_t currentTime, |
|
899 EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) { |
|
900 #if DEBUG_DISPATCH_CYCLE |
|
901 ALOGD("dispatchEventToCurrentInputTargets"); |
|
902 #endif |
|
903 |
|
904 ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true |
|
905 |
|
906 pokeUserActivityLocked(eventEntry); |
|
907 |
|
908 for (size_t i = 0; i < inputTargets.size(); i++) { |
|
909 const InputTarget& inputTarget = inputTargets.itemAt(i); |
|
910 |
|
911 ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel); |
|
912 if (connectionIndex >= 0) { |
|
913 sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex); |
|
914 prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget); |
|
915 } else { |
|
916 #if DEBUG_FOCUS |
|
917 ALOGD("Dropping event delivery to target with channel '%s' because it " |
|
918 "is no longer registered with the input dispatcher.", |
|
919 inputTarget.inputChannel->getName().string()); |
|
920 #endif |
|
921 } |
|
922 } |
|
923 } |
|
924 |
|
925 int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime, |
|
926 const EventEntry* entry, |
|
927 const sp<InputApplicationHandle>& applicationHandle, |
|
928 const sp<InputWindowHandle>& windowHandle, |
|
929 nsecs_t* nextWakeupTime, const char* reason) { |
|
930 if (applicationHandle == NULL && windowHandle == NULL) { |
|
931 if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) { |
|
932 #if DEBUG_FOCUS |
|
933 ALOGD("Waiting for system to become ready for input. Reason: %s", reason); |
|
934 #endif |
|
935 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY; |
|
936 mInputTargetWaitStartTime = currentTime; |
|
937 mInputTargetWaitTimeoutTime = LONG_LONG_MAX; |
|
938 mInputTargetWaitTimeoutExpired = false; |
|
939 mInputTargetWaitApplicationHandle.clear(); |
|
940 } |
|
941 } else { |
|
942 if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) { |
|
943 #if DEBUG_FOCUS |
|
944 ALOGD("Waiting for application to become ready for input: %s. Reason: %s", |
|
945 getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(), |
|
946 reason); |
|
947 #endif |
|
948 nsecs_t timeout; |
|
949 if (windowHandle != NULL) { |
|
950 timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT); |
|
951 } else if (applicationHandle != NULL) { |
|
952 timeout = applicationHandle->getDispatchingTimeout( |
|
953 DEFAULT_INPUT_DISPATCHING_TIMEOUT); |
|
954 } else { |
|
955 timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT; |
|
956 } |
|
957 |
|
958 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY; |
|
959 mInputTargetWaitStartTime = currentTime; |
|
960 mInputTargetWaitTimeoutTime = currentTime + timeout; |
|
961 mInputTargetWaitTimeoutExpired = false; |
|
962 mInputTargetWaitApplicationHandle.clear(); |
|
963 |
|
964 if (windowHandle != NULL) { |
|
965 mInputTargetWaitApplicationHandle = windowHandle->inputApplicationHandle; |
|
966 } |
|
967 if (mInputTargetWaitApplicationHandle == NULL && applicationHandle != NULL) { |
|
968 mInputTargetWaitApplicationHandle = applicationHandle; |
|
969 } |
|
970 } |
|
971 } |
|
972 |
|
973 if (mInputTargetWaitTimeoutExpired) { |
|
974 return INPUT_EVENT_INJECTION_TIMED_OUT; |
|
975 } |
|
976 |
|
977 if (currentTime >= mInputTargetWaitTimeoutTime) { |
|
978 onANRLocked(currentTime, applicationHandle, windowHandle, |
|
979 entry->eventTime, mInputTargetWaitStartTime, reason); |
|
980 |
|
981 // Force poll loop to wake up immediately on next iteration once we get the |
|
982 // ANR response back from the policy. |
|
983 *nextWakeupTime = LONG_LONG_MIN; |
|
984 return INPUT_EVENT_INJECTION_PENDING; |
|
985 } else { |
|
986 // Force poll loop to wake up when timeout is due. |
|
987 if (mInputTargetWaitTimeoutTime < *nextWakeupTime) { |
|
988 *nextWakeupTime = mInputTargetWaitTimeoutTime; |
|
989 } |
|
990 return INPUT_EVENT_INJECTION_PENDING; |
|
991 } |
|
992 } |
|
993 |
|
994 void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout, |
|
995 const sp<InputChannel>& inputChannel) { |
|
996 if (newTimeout > 0) { |
|
997 // Extend the timeout. |
|
998 mInputTargetWaitTimeoutTime = now() + newTimeout; |
|
999 } else { |
|
1000 // Give up. |
|
1001 mInputTargetWaitTimeoutExpired = true; |
|
1002 |
|
1003 // Input state will not be realistic. Mark it out of sync. |
|
1004 if (inputChannel.get()) { |
|
1005 ssize_t connectionIndex = getConnectionIndexLocked(inputChannel); |
|
1006 if (connectionIndex >= 0) { |
|
1007 sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex); |
|
1008 sp<InputWindowHandle> windowHandle = connection->inputWindowHandle; |
|
1009 |
|
1010 if (windowHandle != NULL) { |
|
1011 mTouchState.removeWindow(windowHandle); |
|
1012 } |
|
1013 |
|
1014 if (connection->status == Connection::STATUS_NORMAL) { |
|
1015 CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS, |
|
1016 "application not responding"); |
|
1017 synthesizeCancelationEventsForConnectionLocked(connection, options); |
|
1018 } |
|
1019 } |
|
1020 } |
|
1021 } |
|
1022 } |
|
1023 |
|
1024 nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked( |
|
1025 nsecs_t currentTime) { |
|
1026 if (mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) { |
|
1027 return currentTime - mInputTargetWaitStartTime; |
|
1028 } |
|
1029 return 0; |
|
1030 } |
|
1031 |
|
1032 void InputDispatcher::resetANRTimeoutsLocked() { |
|
1033 #if DEBUG_FOCUS |
|
1034 ALOGD("Resetting ANR timeouts."); |
|
1035 #endif |
|
1036 |
|
1037 // Reset input target wait timeout. |
|
1038 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE; |
|
1039 mInputTargetWaitApplicationHandle.clear(); |
|
1040 } |
|
1041 |
|
1042 int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime, |
|
1043 const EventEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) { |
|
1044 int32_t injectionResult; |
|
1045 |
|
1046 // If there is no currently focused window and no focused application |
|
1047 // then drop the event. |
|
1048 if (mFocusedWindowHandle == NULL) { |
|
1049 if (mFocusedApplicationHandle != NULL) { |
|
1050 injectionResult = handleTargetsNotReadyLocked(currentTime, entry, |
|
1051 mFocusedApplicationHandle, NULL, nextWakeupTime, |
|
1052 "Waiting because no window has focus but there is a " |
|
1053 "focused application that may eventually add a window " |
|
1054 "when it finishes starting up."); |
|
1055 goto Unresponsive; |
|
1056 } |
|
1057 |
|
1058 ALOGI("Dropping event because there is no focused window or focused application."); |
|
1059 injectionResult = INPUT_EVENT_INJECTION_FAILED; |
|
1060 goto Failed; |
|
1061 } |
|
1062 |
|
1063 // Check permissions. |
|
1064 if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) { |
|
1065 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED; |
|
1066 goto Failed; |
|
1067 } |
|
1068 |
|
1069 // If the currently focused window is paused then keep waiting. |
|
1070 if (mFocusedWindowHandle->getInfo()->paused) { |
|
1071 injectionResult = handleTargetsNotReadyLocked(currentTime, entry, |
|
1072 mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime, |
|
1073 "Waiting because the focused window is paused."); |
|
1074 goto Unresponsive; |
|
1075 } |
|
1076 |
|
1077 // If the currently focused window is still working on previous events then keep waiting. |
|
1078 if (!isWindowReadyForMoreInputLocked(currentTime, mFocusedWindowHandle, entry)) { |
|
1079 injectionResult = handleTargetsNotReadyLocked(currentTime, entry, |
|
1080 mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime, |
|
1081 "Waiting because the focused window has not finished " |
|
1082 "processing the input events that were previously delivered to it."); |
|
1083 goto Unresponsive; |
|
1084 } |
|
1085 |
|
1086 // Success! Output targets. |
|
1087 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED; |
|
1088 addWindowTargetLocked(mFocusedWindowHandle, |
|
1089 InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0), |
|
1090 inputTargets); |
|
1091 |
|
1092 // Done. |
|
1093 Failed: |
|
1094 Unresponsive: |
|
1095 nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime); |
|
1096 updateDispatchStatisticsLocked(currentTime, entry, |
|
1097 injectionResult, timeSpentWaitingForApplication); |
|
1098 #if DEBUG_FOCUS |
|
1099 ALOGD("findFocusedWindow finished: injectionResult=%d, " |
|
1100 "timeSpentWaitingForApplication=%0.1fms", |
|
1101 injectionResult, timeSpentWaitingForApplication / 1000000.0); |
|
1102 #endif |
|
1103 return injectionResult; |
|
1104 } |
|
1105 |
|
1106 int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, |
|
1107 const MotionEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime, |
|
1108 bool* outConflictingPointerActions) { |
|
1109 enum InjectionPermission { |
|
1110 INJECTION_PERMISSION_UNKNOWN, |
|
1111 INJECTION_PERMISSION_GRANTED, |
|
1112 INJECTION_PERMISSION_DENIED |
|
1113 }; |
|
1114 |
|
1115 nsecs_t startTime = now(); |
|
1116 |
|
1117 // For security reasons, we defer updating the touch state until we are sure that |
|
1118 // event injection will be allowed. |
|
1119 // |
|
1120 // FIXME In the original code, screenWasOff could never be set to true. |
|
1121 // The reason is that the POLICY_FLAG_WOKE_HERE |
|
1122 // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw |
|
1123 // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was |
|
1124 // actually enqueued using the policyFlags that appeared in the final EV_SYN |
|
1125 // events upon which no preprocessing took place. So policyFlags was always 0. |
|
1126 // In the new native input dispatcher we're a bit more careful about event |
|
1127 // preprocessing so the touches we receive can actually have non-zero policyFlags. |
|
1128 // Unfortunately we obtain undesirable behavior. |
|
1129 // |
|
1130 // Here's what happens: |
|
1131 // |
|
1132 // When the device dims in anticipation of going to sleep, touches |
|
1133 // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause |
|
1134 // the device to brighten and reset the user activity timer. |
|
1135 // Touches on other windows (such as the launcher window) |
|
1136 // are dropped. Then after a moment, the device goes to sleep. Oops. |
|
1137 // |
|
1138 // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE |
|
1139 // instead of POLICY_FLAG_WOKE_HERE... |
|
1140 // |
|
1141 bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE; |
|
1142 |
|
1143 int32_t displayId = entry->displayId; |
|
1144 int32_t action = entry->action; |
|
1145 int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK; |
|
1146 |
|
1147 // Update the touch state as needed based on the properties of the touch event. |
|
1148 int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING; |
|
1149 InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN; |
|
1150 sp<InputWindowHandle> newHoverWindowHandle; |
|
1151 |
|
1152 bool isSplit = mTouchState.split; |
|
1153 bool switchedDevice = mTouchState.deviceId >= 0 && mTouchState.displayId >= 0 |
|
1154 && (mTouchState.deviceId != entry->deviceId |
|
1155 || mTouchState.source != entry->source |
|
1156 || mTouchState.displayId != displayId); |
|
1157 bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE |
|
1158 || maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER |
|
1159 || maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT); |
|
1160 bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN |
|
1161 || maskedAction == AMOTION_EVENT_ACTION_SCROLL |
|
1162 || isHoverAction); |
|
1163 bool wrongDevice = false; |
|
1164 if (newGesture) { |
|
1165 bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN; |
|
1166 if (switchedDevice && mTouchState.down && !down) { |
|
1167 #if DEBUG_FOCUS |
|
1168 ALOGD("Dropping event because a pointer for a different device is already down."); |
|
1169 #endif |
|
1170 mTempTouchState.copyFrom(mTouchState); |
|
1171 injectionResult = INPUT_EVENT_INJECTION_FAILED; |
|
1172 switchedDevice = false; |
|
1173 wrongDevice = true; |
|
1174 goto Failed; |
|
1175 } |
|
1176 mTempTouchState.reset(); |
|
1177 mTempTouchState.down = down; |
|
1178 mTempTouchState.deviceId = entry->deviceId; |
|
1179 mTempTouchState.source = entry->source; |
|
1180 mTempTouchState.displayId = displayId; |
|
1181 isSplit = false; |
|
1182 } else { |
|
1183 mTempTouchState.copyFrom(mTouchState); |
|
1184 } |
|
1185 |
|
1186 if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) { |
|
1187 /* Case 1: New splittable pointer going down, or need target for hover or scroll. */ |
|
1188 |
|
1189 int32_t pointerIndex = getMotionEventActionPointerIndex(action); |
|
1190 int32_t x = int32_t(entry->pointerCoords[pointerIndex]. |
|
1191 getAxisValue(AMOTION_EVENT_AXIS_X)); |
|
1192 int32_t y = int32_t(entry->pointerCoords[pointerIndex]. |
|
1193 getAxisValue(AMOTION_EVENT_AXIS_Y)); |
|
1194 sp<InputWindowHandle> newTouchedWindowHandle; |
|
1195 sp<InputWindowHandle> topErrorWindowHandle; |
|
1196 bool isTouchModal = false; |
|
1197 |
|
1198 // Traverse windows from front to back to find touched window and outside targets. |
|
1199 size_t numWindows = mWindowHandles.size(); |
|
1200 for (size_t i = 0; i < numWindows; i++) { |
|
1201 sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i); |
|
1202 const InputWindowInfo* windowInfo = windowHandle->getInfo(); |
|
1203 if (windowInfo->displayId != displayId) { |
|
1204 continue; // wrong display |
|
1205 } |
|
1206 |
|
1207 int32_t flags = windowInfo->layoutParamsFlags; |
|
1208 if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) { |
|
1209 if (topErrorWindowHandle == NULL) { |
|
1210 topErrorWindowHandle = windowHandle; |
|
1211 } |
|
1212 } |
|
1213 |
|
1214 if (windowInfo->visible) { |
|
1215 if (! (flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) { |
|
1216 isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE |
|
1217 | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0; |
|
1218 if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) { |
|
1219 if (! screenWasOff |
|
1220 || (flags & InputWindowInfo::FLAG_TOUCHABLE_WHEN_WAKING)) { |
|
1221 newTouchedWindowHandle = windowHandle; |
|
1222 } |
|
1223 break; // found touched window, exit window loop |
|
1224 } |
|
1225 } |
|
1226 |
|
1227 if (maskedAction == AMOTION_EVENT_ACTION_DOWN |
|
1228 && (flags & InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH)) { |
|
1229 int32_t outsideTargetFlags = InputTarget::FLAG_DISPATCH_AS_OUTSIDE; |
|
1230 if (isWindowObscuredAtPointLocked(windowHandle, x, y)) { |
|
1231 outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED; |
|
1232 } |
|
1233 |
|
1234 mTempTouchState.addOrUpdateWindow( |
|
1235 windowHandle, outsideTargetFlags, BitSet32(0)); |
|
1236 } |
|
1237 } |
|
1238 } |
|
1239 |
|
1240 // If there is an error window but it is not taking focus (typically because |
|
1241 // it is invisible) then wait for it. Any other focused window may in |
|
1242 // fact be in ANR state. |
|
1243 if (topErrorWindowHandle != NULL && newTouchedWindowHandle != topErrorWindowHandle) { |
|
1244 injectionResult = handleTargetsNotReadyLocked(currentTime, entry, |
|
1245 NULL, NULL, nextWakeupTime, |
|
1246 "Waiting because a system error window is about to be displayed."); |
|
1247 injectionPermission = INJECTION_PERMISSION_UNKNOWN; |
|
1248 goto Unresponsive; |
|
1249 } |
|
1250 |
|
1251 // Figure out whether splitting will be allowed for this window. |
|
1252 if (newTouchedWindowHandle != NULL |
|
1253 && newTouchedWindowHandle->getInfo()->supportsSplitTouch()) { |
|
1254 // New window supports splitting. |
|
1255 isSplit = true; |
|
1256 } else if (isSplit) { |
|
1257 // New window does not support splitting but we have already split events. |
|
1258 // Ignore the new window. |
|
1259 newTouchedWindowHandle = NULL; |
|
1260 } |
|
1261 |
|
1262 // Handle the case where we did not find a window. |
|
1263 if (newTouchedWindowHandle == NULL) { |
|
1264 // Try to assign the pointer to the first foreground window we find, if there is one. |
|
1265 newTouchedWindowHandle = mTempTouchState.getFirstForegroundWindowHandle(); |
|
1266 if (newTouchedWindowHandle == NULL) { |
|
1267 // There is no touched window. If this is an initial down event |
|
1268 // then wait for a window to appear that will handle the touch. This is |
|
1269 // to ensure that we report an ANR in the case where an application has started |
|
1270 // but not yet put up a window and the user is starting to get impatient. |
|
1271 if (maskedAction == AMOTION_EVENT_ACTION_DOWN |
|
1272 && mFocusedApplicationHandle != NULL) { |
|
1273 injectionResult = handleTargetsNotReadyLocked(currentTime, entry, |
|
1274 mFocusedApplicationHandle, NULL, nextWakeupTime, |
|
1275 "Waiting because there is no touchable window that can " |
|
1276 "handle the event but there is focused application that may " |
|
1277 "eventually add a new window when it finishes starting up."); |
|
1278 goto Unresponsive; |
|
1279 } |
|
1280 |
|
1281 ALOGI("Dropping event because there is no touched window."); |
|
1282 injectionResult = INPUT_EVENT_INJECTION_FAILED; |
|
1283 goto Failed; |
|
1284 } |
|
1285 } |
|
1286 |
|
1287 // Set target flags. |
|
1288 int32_t targetFlags = InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS; |
|
1289 if (isSplit) { |
|
1290 targetFlags |= InputTarget::FLAG_SPLIT; |
|
1291 } |
|
1292 if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) { |
|
1293 targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED; |
|
1294 } |
|
1295 |
|
1296 // Update hover state. |
|
1297 if (isHoverAction) { |
|
1298 newHoverWindowHandle = newTouchedWindowHandle; |
|
1299 } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) { |
|
1300 newHoverWindowHandle = mLastHoverWindowHandle; |
|
1301 } |
|
1302 |
|
1303 // Update the temporary touch state. |
|
1304 BitSet32 pointerIds; |
|
1305 if (isSplit) { |
|
1306 uint32_t pointerId = entry->pointerProperties[pointerIndex].id; |
|
1307 pointerIds.markBit(pointerId); |
|
1308 } |
|
1309 mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds); |
|
1310 } else { |
|
1311 /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */ |
|
1312 |
|
1313 // If the pointer is not currently down, then ignore the event. |
|
1314 if (! mTempTouchState.down) { |
|
1315 #if DEBUG_FOCUS |
|
1316 ALOGD("Dropping event because the pointer is not down or we previously " |
|
1317 "dropped the pointer down event."); |
|
1318 #endif |
|
1319 injectionResult = INPUT_EVENT_INJECTION_FAILED; |
|
1320 goto Failed; |
|
1321 } |
|
1322 |
|
1323 // Check whether touches should slip outside of the current foreground window. |
|
1324 if (maskedAction == AMOTION_EVENT_ACTION_MOVE |
|
1325 && entry->pointerCount == 1 |
|
1326 && mTempTouchState.isSlippery()) { |
|
1327 int32_t x = int32_t(entry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X)); |
|
1328 int32_t y = int32_t(entry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y)); |
|
1329 |
|
1330 sp<InputWindowHandle> oldTouchedWindowHandle = |
|
1331 mTempTouchState.getFirstForegroundWindowHandle(); |
|
1332 sp<InputWindowHandle> newTouchedWindowHandle = |
|
1333 findTouchedWindowAtLocked(displayId, x, y); |
|
1334 if (oldTouchedWindowHandle != newTouchedWindowHandle |
|
1335 && newTouchedWindowHandle != NULL) { |
|
1336 #if DEBUG_FOCUS |
|
1337 ALOGD("Touch is slipping out of window %s into window %s.", |
|
1338 oldTouchedWindowHandle->getName().string(), |
|
1339 newTouchedWindowHandle->getName().string()); |
|
1340 #endif |
|
1341 // Make a slippery exit from the old window. |
|
1342 mTempTouchState.addOrUpdateWindow(oldTouchedWindowHandle, |
|
1343 InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT, BitSet32(0)); |
|
1344 |
|
1345 // Make a slippery entrance into the new window. |
|
1346 if (newTouchedWindowHandle->getInfo()->supportsSplitTouch()) { |
|
1347 isSplit = true; |
|
1348 } |
|
1349 |
|
1350 int32_t targetFlags = InputTarget::FLAG_FOREGROUND |
|
1351 | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER; |
|
1352 if (isSplit) { |
|
1353 targetFlags |= InputTarget::FLAG_SPLIT; |
|
1354 } |
|
1355 if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) { |
|
1356 targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED; |
|
1357 } |
|
1358 |
|
1359 BitSet32 pointerIds; |
|
1360 if (isSplit) { |
|
1361 pointerIds.markBit(entry->pointerProperties[0].id); |
|
1362 } |
|
1363 mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds); |
|
1364 } |
|
1365 } |
|
1366 } |
|
1367 |
|
1368 if (newHoverWindowHandle != mLastHoverWindowHandle) { |
|
1369 // Let the previous window know that the hover sequence is over. |
|
1370 if (mLastHoverWindowHandle != NULL) { |
|
1371 #if DEBUG_HOVER |
|
1372 ALOGD("Sending hover exit event to window %s.", |
|
1373 mLastHoverWindowHandle->getName().string()); |
|
1374 #endif |
|
1375 mTempTouchState.addOrUpdateWindow(mLastHoverWindowHandle, |
|
1376 InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT, BitSet32(0)); |
|
1377 } |
|
1378 |
|
1379 // Let the new window know that the hover sequence is starting. |
|
1380 if (newHoverWindowHandle != NULL) { |
|
1381 #if DEBUG_HOVER |
|
1382 ALOGD("Sending hover enter event to window %s.", |
|
1383 newHoverWindowHandle->getName().string()); |
|
1384 #endif |
|
1385 mTempTouchState.addOrUpdateWindow(newHoverWindowHandle, |
|
1386 InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER, BitSet32(0)); |
|
1387 } |
|
1388 } |
|
1389 |
|
1390 // Check permission to inject into all touched foreground windows and ensure there |
|
1391 // is at least one touched foreground window. |
|
1392 { |
|
1393 bool haveForegroundWindow = false; |
|
1394 for (size_t i = 0; i < mTempTouchState.windows.size(); i++) { |
|
1395 const TouchedWindow& touchedWindow = mTempTouchState.windows[i]; |
|
1396 if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) { |
|
1397 haveForegroundWindow = true; |
|
1398 if (! checkInjectionPermission(touchedWindow.windowHandle, |
|
1399 entry->injectionState)) { |
|
1400 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED; |
|
1401 injectionPermission = INJECTION_PERMISSION_DENIED; |
|
1402 goto Failed; |
|
1403 } |
|
1404 } |
|
1405 } |
|
1406 if (! haveForegroundWindow) { |
|
1407 #if DEBUG_FOCUS |
|
1408 ALOGD("Dropping event because there is no touched foreground window to receive it."); |
|
1409 #endif |
|
1410 injectionResult = INPUT_EVENT_INJECTION_FAILED; |
|
1411 goto Failed; |
|
1412 } |
|
1413 |
|
1414 // Permission granted to injection into all touched foreground windows. |
|
1415 injectionPermission = INJECTION_PERMISSION_GRANTED; |
|
1416 } |
|
1417 |
|
1418 // Check whether windows listening for outside touches are owned by the same UID. If it is |
|
1419 // set the policy flag that we will not reveal coordinate information to this window. |
|
1420 if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { |
|
1421 sp<InputWindowHandle> foregroundWindowHandle = |
|
1422 mTempTouchState.getFirstForegroundWindowHandle(); |
|
1423 const int32_t foregroundWindowUid = foregroundWindowHandle->getInfo()->ownerUid; |
|
1424 for (size_t i = 0; i < mTempTouchState.windows.size(); i++) { |
|
1425 const TouchedWindow& touchedWindow = mTempTouchState.windows[i]; |
|
1426 if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) { |
|
1427 sp<InputWindowHandle> inputWindowHandle = touchedWindow.windowHandle; |
|
1428 if (inputWindowHandle->getInfo()->ownerUid != foregroundWindowUid) { |
|
1429 mTempTouchState.addOrUpdateWindow(inputWindowHandle, |
|
1430 InputTarget::FLAG_ZERO_COORDS, BitSet32(0)); |
|
1431 } |
|
1432 } |
|
1433 } |
|
1434 } |
|
1435 |
|
1436 // Ensure all touched foreground windows are ready for new input. |
|
1437 for (size_t i = 0; i < mTempTouchState.windows.size(); i++) { |
|
1438 const TouchedWindow& touchedWindow = mTempTouchState.windows[i]; |
|
1439 if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) { |
|
1440 // If the touched window is paused then keep waiting. |
|
1441 if (touchedWindow.windowHandle->getInfo()->paused) { |
|
1442 injectionResult = handleTargetsNotReadyLocked(currentTime, entry, |
|
1443 NULL, touchedWindow.windowHandle, nextWakeupTime, |
|
1444 "Waiting because the touched window is paused."); |
|
1445 goto Unresponsive; |
|
1446 } |
|
1447 |
|
1448 // If the touched window is still working on previous events then keep waiting. |
|
1449 if (!isWindowReadyForMoreInputLocked(currentTime, touchedWindow.windowHandle, entry)) { |
|
1450 injectionResult = handleTargetsNotReadyLocked(currentTime, entry, |
|
1451 NULL, touchedWindow.windowHandle, nextWakeupTime, |
|
1452 "Waiting because the touched window has not finished " |
|
1453 "processing the input events that were previously delivered to it."); |
|
1454 goto Unresponsive; |
|
1455 } |
|
1456 } |
|
1457 } |
|
1458 |
|
1459 // If this is the first pointer going down and the touched window has a wallpaper |
|
1460 // then also add the touched wallpaper windows so they are locked in for the duration |
|
1461 // of the touch gesture. |
|
1462 // We do not collect wallpapers during HOVER_MOVE or SCROLL because the wallpaper |
|
1463 // engine only supports touch events. We would need to add a mechanism similar |
|
1464 // to View.onGenericMotionEvent to enable wallpapers to handle these events. |
|
1465 if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { |
|
1466 sp<InputWindowHandle> foregroundWindowHandle = |
|
1467 mTempTouchState.getFirstForegroundWindowHandle(); |
|
1468 if (foregroundWindowHandle->getInfo()->hasWallpaper) { |
|
1469 for (size_t i = 0; i < mWindowHandles.size(); i++) { |
|
1470 sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i); |
|
1471 const InputWindowInfo* info = windowHandle->getInfo(); |
|
1472 if (info->displayId == displayId |
|
1473 && windowHandle->getInfo()->layoutParamsType |
|
1474 == InputWindowInfo::TYPE_WALLPAPER) { |
|
1475 mTempTouchState.addOrUpdateWindow(windowHandle, |
|
1476 InputTarget::FLAG_WINDOW_IS_OBSCURED |
|
1477 | InputTarget::FLAG_DISPATCH_AS_IS, |
|
1478 BitSet32(0)); |
|
1479 } |
|
1480 } |
|
1481 } |
|
1482 } |
|
1483 |
|
1484 // Success! Output targets. |
|
1485 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED; |
|
1486 |
|
1487 for (size_t i = 0; i < mTempTouchState.windows.size(); i++) { |
|
1488 const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i); |
|
1489 addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags, |
|
1490 touchedWindow.pointerIds, inputTargets); |
|
1491 } |
|
1492 |
|
1493 // Drop the outside or hover touch windows since we will not care about them |
|
1494 // in the next iteration. |
|
1495 mTempTouchState.filterNonAsIsTouchWindows(); |
|
1496 |
|
1497 Failed: |
|
1498 // Check injection permission once and for all. |
|
1499 if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) { |
|
1500 if (checkInjectionPermission(NULL, entry->injectionState)) { |
|
1501 injectionPermission = INJECTION_PERMISSION_GRANTED; |
|
1502 } else { |
|
1503 injectionPermission = INJECTION_PERMISSION_DENIED; |
|
1504 } |
|
1505 } |
|
1506 |
|
1507 // Update final pieces of touch state if the injector had permission. |
|
1508 if (injectionPermission == INJECTION_PERMISSION_GRANTED) { |
|
1509 if (!wrongDevice) { |
|
1510 if (switchedDevice) { |
|
1511 #if DEBUG_FOCUS |
|
1512 ALOGD("Conflicting pointer actions: Switched to a different device."); |
|
1513 #endif |
|
1514 *outConflictingPointerActions = true; |
|
1515 } |
|
1516 |
|
1517 if (isHoverAction) { |
|
1518 // Started hovering, therefore no longer down. |
|
1519 if (mTouchState.down) { |
|
1520 #if DEBUG_FOCUS |
|
1521 ALOGD("Conflicting pointer actions: Hover received while pointer was down."); |
|
1522 #endif |
|
1523 *outConflictingPointerActions = true; |
|
1524 } |
|
1525 mTouchState.reset(); |
|
1526 if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER |
|
1527 || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) { |
|
1528 mTouchState.deviceId = entry->deviceId; |
|
1529 mTouchState.source = entry->source; |
|
1530 mTouchState.displayId = displayId; |
|
1531 } |
|
1532 } else if (maskedAction == AMOTION_EVENT_ACTION_UP |
|
1533 || maskedAction == AMOTION_EVENT_ACTION_CANCEL) { |
|
1534 // All pointers up or canceled. |
|
1535 mTouchState.reset(); |
|
1536 } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { |
|
1537 // First pointer went down. |
|
1538 if (mTouchState.down) { |
|
1539 #if DEBUG_FOCUS |
|
1540 ALOGD("Conflicting pointer actions: Down received while already down."); |
|
1541 #endif |
|
1542 *outConflictingPointerActions = true; |
|
1543 } |
|
1544 mTouchState.copyFrom(mTempTouchState); |
|
1545 } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) { |
|
1546 // One pointer went up. |
|
1547 if (isSplit) { |
|
1548 int32_t pointerIndex = getMotionEventActionPointerIndex(action); |
|
1549 uint32_t pointerId = entry->pointerProperties[pointerIndex].id; |
|
1550 |
|
1551 for (size_t i = 0; i < mTempTouchState.windows.size(); ) { |
|
1552 TouchedWindow& touchedWindow = mTempTouchState.windows.editItemAt(i); |
|
1553 if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) { |
|
1554 touchedWindow.pointerIds.clearBit(pointerId); |
|
1555 if (touchedWindow.pointerIds.isEmpty()) { |
|
1556 mTempTouchState.windows.removeAt(i); |
|
1557 continue; |
|
1558 } |
|
1559 } |
|
1560 i += 1; |
|
1561 } |
|
1562 } |
|
1563 mTouchState.copyFrom(mTempTouchState); |
|
1564 } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) { |
|
1565 // Discard temporary touch state since it was only valid for this action. |
|
1566 } else { |
|
1567 // Save changes to touch state as-is for all other actions. |
|
1568 mTouchState.copyFrom(mTempTouchState); |
|
1569 } |
|
1570 |
|
1571 // Update hover state. |
|
1572 mLastHoverWindowHandle = newHoverWindowHandle; |
|
1573 } |
|
1574 } else { |
|
1575 #if DEBUG_FOCUS |
|
1576 ALOGD("Not updating touch focus because injection was denied."); |
|
1577 #endif |
|
1578 } |
|
1579 |
|
1580 Unresponsive: |
|
1581 // Reset temporary touch state to ensure we release unnecessary references to input channels. |
|
1582 mTempTouchState.reset(); |
|
1583 |
|
1584 nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime); |
|
1585 updateDispatchStatisticsLocked(currentTime, entry, |
|
1586 injectionResult, timeSpentWaitingForApplication); |
|
1587 #if DEBUG_FOCUS |
|
1588 ALOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d, " |
|
1589 "timeSpentWaitingForApplication=%0.1fms", |
|
1590 injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0); |
|
1591 #endif |
|
1592 return injectionResult; |
|
1593 } |
|
1594 |
|
1595 void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle, |
|
1596 int32_t targetFlags, BitSet32 pointerIds, Vector<InputTarget>& inputTargets) { |
|
1597 inputTargets.push(); |
|
1598 |
|
1599 const InputWindowInfo* windowInfo = windowHandle->getInfo(); |
|
1600 InputTarget& target = inputTargets.editTop(); |
|
1601 target.inputChannel = windowInfo->inputChannel; |
|
1602 target.flags = targetFlags; |
|
1603 target.xOffset = - windowInfo->frameLeft; |
|
1604 target.yOffset = - windowInfo->frameTop; |
|
1605 target.scaleFactor = windowInfo->scaleFactor; |
|
1606 target.pointerIds = pointerIds; |
|
1607 } |
|
1608 |
|
1609 void InputDispatcher::addMonitoringTargetsLocked(Vector<InputTarget>& inputTargets) { |
|
1610 for (size_t i = 0; i < mMonitoringChannels.size(); i++) { |
|
1611 inputTargets.push(); |
|
1612 |
|
1613 InputTarget& target = inputTargets.editTop(); |
|
1614 target.inputChannel = mMonitoringChannels[i]; |
|
1615 target.flags = InputTarget::FLAG_DISPATCH_AS_IS; |
|
1616 target.xOffset = 0; |
|
1617 target.yOffset = 0; |
|
1618 target.pointerIds.clear(); |
|
1619 target.scaleFactor = 1.0f; |
|
1620 } |
|
1621 } |
|
1622 |
|
1623 bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& windowHandle, |
|
1624 const InjectionState* injectionState) { |
|
1625 if (injectionState |
|
1626 && (windowHandle == NULL |
|
1627 || windowHandle->getInfo()->ownerUid != injectionState->injectorUid) |
|
1628 && !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) { |
|
1629 if (windowHandle != NULL) { |
|
1630 ALOGW("Permission denied: injecting event from pid %d uid %d to window %s " |
|
1631 "owned by uid %d", |
|
1632 injectionState->injectorPid, injectionState->injectorUid, |
|
1633 windowHandle->getName().string(), |
|
1634 windowHandle->getInfo()->ownerUid); |
|
1635 } else { |
|
1636 ALOGW("Permission denied: injecting event from pid %d uid %d", |
|
1637 injectionState->injectorPid, injectionState->injectorUid); |
|
1638 } |
|
1639 return false; |
|
1640 } |
|
1641 return true; |
|
1642 } |
|
1643 |
|
1644 bool InputDispatcher::isWindowObscuredAtPointLocked( |
|
1645 const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const { |
|
1646 int32_t displayId = windowHandle->getInfo()->displayId; |
|
1647 size_t numWindows = mWindowHandles.size(); |
|
1648 for (size_t i = 0; i < numWindows; i++) { |
|
1649 sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i); |
|
1650 if (otherHandle == windowHandle) { |
|
1651 break; |
|
1652 } |
|
1653 |
|
1654 const InputWindowInfo* otherInfo = otherHandle->getInfo(); |
|
1655 if (otherInfo->displayId == displayId |
|
1656 && otherInfo->visible && !otherInfo->isTrustedOverlay() |
|
1657 && otherInfo->frameContainsPoint(x, y)) { |
|
1658 return true; |
|
1659 } |
|
1660 } |
|
1661 return false; |
|
1662 } |
|
1663 |
|
1664 bool InputDispatcher::isWindowReadyForMoreInputLocked(nsecs_t currentTime, |
|
1665 const sp<InputWindowHandle>& windowHandle, const EventEntry* eventEntry) { |
|
1666 ssize_t connectionIndex = getConnectionIndexLocked(windowHandle->getInputChannel()); |
|
1667 if (connectionIndex >= 0) { |
|
1668 sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex); |
|
1669 if (connection->inputPublisherBlocked) { |
|
1670 return false; |
|
1671 } |
|
1672 if (eventEntry->type == EventEntry::TYPE_KEY) { |
|
1673 // If the event is a key event, then we must wait for all previous events to |
|
1674 // complete before delivering it because previous events may have the |
|
1675 // side-effect of transferring focus to a different window and we want to |
|
1676 // ensure that the following keys are sent to the new window. |
|
1677 // |
|
1678 // Suppose the user touches a button in a window then immediately presses "A". |
|
1679 // If the button causes a pop-up window to appear then we want to ensure that |
|
1680 // the "A" key is delivered to the new pop-up window. This is because users |
|
1681 // often anticipate pending UI changes when typing on a keyboard. |
|
1682 // To obtain this behavior, we must serialize key events with respect to all |
|
1683 // prior input events. |
|
1684 return connection->outboundQueue.isEmpty() |
|
1685 && connection->waitQueue.isEmpty(); |
|
1686 } |
|
1687 // Touch events can always be sent to a window immediately because the user intended |
|
1688 // to touch whatever was visible at the time. Even if focus changes or a new |
|
1689 // window appears moments later, the touch event was meant to be delivered to |
|
1690 // whatever window happened to be on screen at the time. |
|
1691 // |
|
1692 // Generic motion events, such as trackball or joystick events are a little trickier. |
|
1693 // Like key events, generic motion events are delivered to the focused window. |
|
1694 // Unlike key events, generic motion events don't tend to transfer focus to other |
|
1695 // windows and it is not important for them to be serialized. So we prefer to deliver |
|
1696 // generic motion events as soon as possible to improve efficiency and reduce lag |
|
1697 // through batching. |
|
1698 // |
|
1699 // The one case where we pause input event delivery is when the wait queue is piling |
|
1700 // up with lots of events because the application is not responding. |
|
1701 // This condition ensures that ANRs are detected reliably. |
|
1702 if (!connection->waitQueue.isEmpty() |
|
1703 && currentTime >= connection->waitQueue.head->eventEntry->eventTime |
|
1704 + STREAM_AHEAD_EVENT_TIMEOUT) { |
|
1705 return false; |
|
1706 } |
|
1707 } |
|
1708 return true; |
|
1709 } |
|
1710 |
|
1711 String8 InputDispatcher::getApplicationWindowLabelLocked( |
|
1712 const sp<InputApplicationHandle>& applicationHandle, |
|
1713 const sp<InputWindowHandle>& windowHandle) { |
|
1714 if (applicationHandle != NULL) { |
|
1715 if (windowHandle != NULL) { |
|
1716 String8 label(applicationHandle->getName()); |
|
1717 label.append(" - "); |
|
1718 label.append(windowHandle->getName()); |
|
1719 return label; |
|
1720 } else { |
|
1721 return applicationHandle->getName(); |
|
1722 } |
|
1723 } else if (windowHandle != NULL) { |
|
1724 return windowHandle->getName(); |
|
1725 } else { |
|
1726 return String8("<unknown application or window>"); |
|
1727 } |
|
1728 } |
|
1729 |
|
1730 void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) { |
|
1731 if (mFocusedWindowHandle != NULL) { |
|
1732 const InputWindowInfo* info = mFocusedWindowHandle->getInfo(); |
|
1733 if (info->inputFeatures & InputWindowInfo::INPUT_FEATURE_DISABLE_USER_ACTIVITY) { |
|
1734 #if DEBUG_DISPATCH_CYCLE |
|
1735 ALOGD("Not poking user activity: disabled by window '%s'.", info->name.string()); |
|
1736 #endif |
|
1737 return; |
|
1738 } |
|
1739 } |
|
1740 |
|
1741 int32_t eventType = USER_ACTIVITY_EVENT_OTHER; |
|
1742 switch (eventEntry->type) { |
|
1743 case EventEntry::TYPE_MOTION: { |
|
1744 const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry); |
|
1745 if (motionEntry->action == AMOTION_EVENT_ACTION_CANCEL) { |
|
1746 return; |
|
1747 } |
|
1748 |
|
1749 if (MotionEvent::isTouchEvent(motionEntry->source, motionEntry->action)) { |
|
1750 eventType = USER_ACTIVITY_EVENT_TOUCH; |
|
1751 } |
|
1752 break; |
|
1753 } |
|
1754 case EventEntry::TYPE_KEY: { |
|
1755 const KeyEntry* keyEntry = static_cast<const KeyEntry*>(eventEntry); |
|
1756 if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) { |
|
1757 return; |
|
1758 } |
|
1759 eventType = USER_ACTIVITY_EVENT_BUTTON; |
|
1760 break; |
|
1761 } |
|
1762 } |
|
1763 |
|
1764 CommandEntry* commandEntry = postCommandLocked( |
|
1765 & InputDispatcher::doPokeUserActivityLockedInterruptible); |
|
1766 commandEntry->eventTime = eventEntry->eventTime; |
|
1767 commandEntry->userActivityEventType = eventType; |
|
1768 } |
|
1769 |
|
1770 void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, |
|
1771 const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) { |
|
1772 #if DEBUG_DISPATCH_CYCLE |
|
1773 ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, " |
|
1774 "xOffset=%f, yOffset=%f, scaleFactor=%f, " |
|
1775 "pointerIds=0x%x", |
|
1776 connection->getInputChannelName(), inputTarget->flags, |
|
1777 inputTarget->xOffset, inputTarget->yOffset, |
|
1778 inputTarget->scaleFactor, inputTarget->pointerIds.value); |
|
1779 #endif |
|
1780 |
|
1781 // Skip this event if the connection status is not normal. |
|
1782 // We don't want to enqueue additional outbound events if the connection is broken. |
|
1783 if (connection->status != Connection::STATUS_NORMAL) { |
|
1784 #if DEBUG_DISPATCH_CYCLE |
|
1785 ALOGD("channel '%s' ~ Dropping event because the channel status is %s", |
|
1786 connection->getInputChannelName(), connection->getStatusLabel()); |
|
1787 #endif |
|
1788 return; |
|
1789 } |
|
1790 |
|
1791 // Split a motion event if needed. |
|
1792 if (inputTarget->flags & InputTarget::FLAG_SPLIT) { |
|
1793 ALOG_ASSERT(eventEntry->type == EventEntry::TYPE_MOTION); |
|
1794 |
|
1795 MotionEntry* originalMotionEntry = static_cast<MotionEntry*>(eventEntry); |
|
1796 if (inputTarget->pointerIds.count() != originalMotionEntry->pointerCount) { |
|
1797 MotionEntry* splitMotionEntry = splitMotionEvent( |
|
1798 originalMotionEntry, inputTarget->pointerIds); |
|
1799 if (!splitMotionEntry) { |
|
1800 return; // split event was dropped |
|
1801 } |
|
1802 #if DEBUG_FOCUS |
|
1803 ALOGD("channel '%s' ~ Split motion event.", |
|
1804 connection->getInputChannelName()); |
|
1805 logOutboundMotionDetailsLocked(" ", splitMotionEntry); |
|
1806 #endif |
|
1807 enqueueDispatchEntriesLocked(currentTime, connection, |
|
1808 splitMotionEntry, inputTarget); |
|
1809 splitMotionEntry->release(); |
|
1810 return; |
|
1811 } |
|
1812 } |
|
1813 |
|
1814 // Not splitting. Enqueue dispatch entries for the event as is. |
|
1815 enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget); |
|
1816 } |
|
1817 |
|
1818 void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime, |
|
1819 const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) { |
|
1820 bool wasEmpty = connection->outboundQueue.isEmpty(); |
|
1821 |
|
1822 // Enqueue dispatch entries for the requested modes. |
|
1823 enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, |
|
1824 InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT); |
|
1825 enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, |
|
1826 InputTarget::FLAG_DISPATCH_AS_OUTSIDE); |
|
1827 enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, |
|
1828 InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER); |
|
1829 enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, |
|
1830 InputTarget::FLAG_DISPATCH_AS_IS); |
|
1831 enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, |
|
1832 InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT); |
|
1833 enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, |
|
1834 InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER); |
|
1835 |
|
1836 // If the outbound queue was previously empty, start the dispatch cycle going. |
|
1837 if (wasEmpty && !connection->outboundQueue.isEmpty()) { |
|
1838 startDispatchCycleLocked(currentTime, connection); |
|
1839 } |
|
1840 } |
|
1841 |
|
1842 void InputDispatcher::enqueueDispatchEntryLocked( |
|
1843 const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget, |
|
1844 int32_t dispatchMode) { |
|
1845 int32_t inputTargetFlags = inputTarget->flags; |
|
1846 if (!(inputTargetFlags & dispatchMode)) { |
|
1847 return; |
|
1848 } |
|
1849 inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode; |
|
1850 |
|
1851 // This is a new event. |
|
1852 // Enqueue a new dispatch entry onto the outbound queue for this connection. |
|
1853 DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments ref |
|
1854 inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset, |
|
1855 inputTarget->scaleFactor); |
|
1856 |
|
1857 // Apply target flags and update the connection's input state. |
|
1858 switch (eventEntry->type) { |
|
1859 case EventEntry::TYPE_KEY: { |
|
1860 KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry); |
|
1861 dispatchEntry->resolvedAction = keyEntry->action; |
|
1862 dispatchEntry->resolvedFlags = keyEntry->flags; |
|
1863 |
|
1864 if (!connection->inputState.trackKey(keyEntry, |
|
1865 dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) { |
|
1866 #if DEBUG_DISPATCH_CYCLE |
|
1867 ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event", |
|
1868 connection->getInputChannelName()); |
|
1869 #endif |
|
1870 delete dispatchEntry; |
|
1871 return; // skip the inconsistent event |
|
1872 } |
|
1873 break; |
|
1874 } |
|
1875 |
|
1876 case EventEntry::TYPE_MOTION: { |
|
1877 MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry); |
|
1878 if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) { |
|
1879 dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE; |
|
1880 } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) { |
|
1881 dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT; |
|
1882 } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) { |
|
1883 dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER; |
|
1884 } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) { |
|
1885 dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_CANCEL; |
|
1886 } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) { |
|
1887 dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_DOWN; |
|
1888 } else { |
|
1889 dispatchEntry->resolvedAction = motionEntry->action; |
|
1890 } |
|
1891 if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE |
|
1892 && !connection->inputState.isHovering( |
|
1893 motionEntry->deviceId, motionEntry->source, motionEntry->displayId)) { |
|
1894 #if DEBUG_DISPATCH_CYCLE |
|
1895 ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover enter event", |
|
1896 connection->getInputChannelName()); |
|
1897 #endif |
|
1898 dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER; |
|
1899 } |
|
1900 |
|
1901 dispatchEntry->resolvedFlags = motionEntry->flags; |
|
1902 if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) { |
|
1903 dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED; |
|
1904 } |
|
1905 |
|
1906 if (!connection->inputState.trackMotion(motionEntry, |
|
1907 dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) { |
|
1908 #if DEBUG_DISPATCH_CYCLE |
|
1909 ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent motion event", |
|
1910 connection->getInputChannelName()); |
|
1911 #endif |
|
1912 delete dispatchEntry; |
|
1913 return; // skip the inconsistent event |
|
1914 } |
|
1915 break; |
|
1916 } |
|
1917 } |
|
1918 |
|
1919 // Remember that we are waiting for this dispatch to complete. |
|
1920 if (dispatchEntry->hasForegroundTarget()) { |
|
1921 incrementPendingForegroundDispatchesLocked(eventEntry); |
|
1922 } |
|
1923 |
|
1924 // Enqueue the dispatch entry. |
|
1925 connection->outboundQueue.enqueueAtTail(dispatchEntry); |
|
1926 traceOutboundQueueLengthLocked(connection); |
|
1927 } |
|
1928 |
|
1929 void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, |
|
1930 const sp<Connection>& connection) { |
|
1931 #if DEBUG_DISPATCH_CYCLE |
|
1932 ALOGD("channel '%s' ~ startDispatchCycle", |
|
1933 connection->getInputChannelName()); |
|
1934 #endif |
|
1935 |
|
1936 while (connection->status == Connection::STATUS_NORMAL |
|
1937 && !connection->outboundQueue.isEmpty()) { |
|
1938 DispatchEntry* dispatchEntry = connection->outboundQueue.head; |
|
1939 dispatchEntry->deliveryTime = currentTime; |
|
1940 |
|
1941 // Publish the event. |
|
1942 status_t status; |
|
1943 EventEntry* eventEntry = dispatchEntry->eventEntry; |
|
1944 switch (eventEntry->type) { |
|
1945 case EventEntry::TYPE_KEY: { |
|
1946 KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry); |
|
1947 |
|
1948 // Publish the key event. |
|
1949 status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq, |
|
1950 keyEntry->deviceId, keyEntry->source, |
|
1951 dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags, |
|
1952 keyEntry->keyCode, keyEntry->scanCode, |
|
1953 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime, |
|
1954 keyEntry->eventTime); |
|
1955 break; |
|
1956 } |
|
1957 |
|
1958 case EventEntry::TYPE_MOTION: { |
|
1959 MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry); |
|
1960 |
|
1961 PointerCoords scaledCoords[MAX_POINTERS]; |
|
1962 const PointerCoords* usingCoords = motionEntry->pointerCoords; |
|
1963 |
|
1964 // Set the X and Y offset depending on the input source. |
|
1965 float xOffset, yOffset, scaleFactor; |
|
1966 if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) |
|
1967 && !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) { |
|
1968 scaleFactor = dispatchEntry->scaleFactor; |
|
1969 xOffset = dispatchEntry->xOffset * scaleFactor; |
|
1970 yOffset = dispatchEntry->yOffset * scaleFactor; |
|
1971 if (scaleFactor != 1.0f) { |
|
1972 for (size_t i = 0; i < motionEntry->pointerCount; i++) { |
|
1973 scaledCoords[i] = motionEntry->pointerCoords[i]; |
|
1974 scaledCoords[i].scale(scaleFactor); |
|
1975 } |
|
1976 usingCoords = scaledCoords; |
|
1977 } |
|
1978 } else { |
|
1979 xOffset = 0.0f; |
|
1980 yOffset = 0.0f; |
|
1981 scaleFactor = 1.0f; |
|
1982 |
|
1983 // We don't want the dispatch target to know. |
|
1984 if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) { |
|
1985 for (size_t i = 0; i < motionEntry->pointerCount; i++) { |
|
1986 scaledCoords[i].clear(); |
|
1987 } |
|
1988 usingCoords = scaledCoords; |
|
1989 } |
|
1990 } |
|
1991 |
|
1992 // Publish the motion event. |
|
1993 status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq, |
|
1994 motionEntry->deviceId, motionEntry->source, |
|
1995 dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags, |
|
1996 motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState, |
|
1997 xOffset, yOffset, |
|
1998 motionEntry->xPrecision, motionEntry->yPrecision, |
|
1999 motionEntry->downTime, motionEntry->eventTime, |
|
2000 motionEntry->pointerCount, motionEntry->pointerProperties, |
|
2001 usingCoords); |
|
2002 break; |
|
2003 } |
|
2004 |
|
2005 default: |
|
2006 ALOG_ASSERT(false); |
|
2007 return; |
|
2008 } |
|
2009 |
|
2010 // Check the result. |
|
2011 if (status) { |
|
2012 if (status == WOULD_BLOCK) { |
|
2013 if (connection->waitQueue.isEmpty()) { |
|
2014 ALOGE("channel '%s' ~ Could not publish event because the pipe is full. " |
|
2015 "This is unexpected because the wait queue is empty, so the pipe " |
|
2016 "should be empty and we shouldn't have any problems writing an " |
|
2017 "event to it, status=%d", connection->getInputChannelName(), status); |
|
2018 abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/); |
|
2019 } else { |
|
2020 // Pipe is full and we are waiting for the app to finish process some events |
|
2021 // before sending more events to it. |
|
2022 #if DEBUG_DISPATCH_CYCLE |
|
2023 ALOGD("channel '%s' ~ Could not publish event because the pipe is full, " |
|
2024 "waiting for the application to catch up", |
|
2025 connection->getInputChannelName()); |
|
2026 #endif |
|
2027 connection->inputPublisherBlocked = true; |
|
2028 } |
|
2029 } else { |
|
2030 ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, " |
|
2031 "status=%d", connection->getInputChannelName(), status); |
|
2032 abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/); |
|
2033 } |
|
2034 return; |
|
2035 } |
|
2036 |
|
2037 // Re-enqueue the event on the wait queue. |
|
2038 connection->outboundQueue.dequeue(dispatchEntry); |
|
2039 traceOutboundQueueLengthLocked(connection); |
|
2040 connection->waitQueue.enqueueAtTail(dispatchEntry); |
|
2041 traceWaitQueueLengthLocked(connection); |
|
2042 } |
|
2043 } |
|
2044 |
|
2045 void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime, |
|
2046 const sp<Connection>& connection, uint32_t seq, bool handled) { |
|
2047 #if DEBUG_DISPATCH_CYCLE |
|
2048 ALOGD("channel '%s' ~ finishDispatchCycle - seq=%u, handled=%s", |
|
2049 connection->getInputChannelName(), seq, toString(handled)); |
|
2050 #endif |
|
2051 |
|
2052 connection->inputPublisherBlocked = false; |
|
2053 |
|
2054 if (connection->status == Connection::STATUS_BROKEN |
|
2055 || connection->status == Connection::STATUS_ZOMBIE) { |
|
2056 return; |
|
2057 } |
|
2058 |
|
2059 // Notify other system components and prepare to start the next dispatch cycle. |
|
2060 onDispatchCycleFinishedLocked(currentTime, connection, seq, handled); |
|
2061 } |
|
2062 |
|
2063 void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime, |
|
2064 const sp<Connection>& connection, bool notify) { |
|
2065 #if DEBUG_DISPATCH_CYCLE |
|
2066 ALOGD("channel '%s' ~ abortBrokenDispatchCycle - notify=%s", |
|
2067 connection->getInputChannelName(), toString(notify)); |
|
2068 #endif |
|
2069 |
|
2070 // Clear the dispatch queues. |
|
2071 drainDispatchQueueLocked(&connection->outboundQueue); |
|
2072 traceOutboundQueueLengthLocked(connection); |
|
2073 drainDispatchQueueLocked(&connection->waitQueue); |
|
2074 traceWaitQueueLengthLocked(connection); |
|
2075 |
|
2076 // The connection appears to be unrecoverably broken. |
|
2077 // Ignore already broken or zombie connections. |
|
2078 if (connection->status == Connection::STATUS_NORMAL) { |
|
2079 connection->status = Connection::STATUS_BROKEN; |
|
2080 |
|
2081 if (notify) { |
|
2082 // Notify other system components. |
|
2083 onDispatchCycleBrokenLocked(currentTime, connection); |
|
2084 } |
|
2085 } |
|
2086 } |
|
2087 |
|
2088 void InputDispatcher::drainDispatchQueueLocked(Queue<DispatchEntry>* queue) { |
|
2089 while (!queue->isEmpty()) { |
|
2090 DispatchEntry* dispatchEntry = queue->dequeueAtHead(); |
|
2091 releaseDispatchEntryLocked(dispatchEntry); |
|
2092 } |
|
2093 } |
|
2094 |
|
2095 void InputDispatcher::releaseDispatchEntryLocked(DispatchEntry* dispatchEntry) { |
|
2096 if (dispatchEntry->hasForegroundTarget()) { |
|
2097 decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry); |
|
2098 } |
|
2099 delete dispatchEntry; |
|
2100 } |
|
2101 |
|
2102 int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) { |
|
2103 InputDispatcher* d = static_cast<InputDispatcher*>(data); |
|
2104 |
|
2105 { // acquire lock |
|
2106 AutoMutex _l(d->mLock); |
|
2107 |
|
2108 ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd); |
|
2109 if (connectionIndex < 0) { |
|
2110 ALOGE("Received spurious receive callback for unknown input channel. " |
|
2111 "fd=%d, events=0x%x", fd, events); |
|
2112 return 0; // remove the callback |
|
2113 } |
|
2114 |
|
2115 bool notify; |
|
2116 sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex); |
|
2117 if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) { |
|
2118 if (!(events & ALOOPER_EVENT_INPUT)) { |
|
2119 ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. " |
|
2120 "events=0x%x", connection->getInputChannelName(), events); |
|
2121 return 1; |
|
2122 } |
|
2123 |
|
2124 nsecs_t currentTime = now(); |
|
2125 bool gotOne = false; |
|
2126 status_t status; |
|
2127 for (;;) { |
|
2128 uint32_t seq; |
|
2129 bool handled; |
|
2130 status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled); |
|
2131 if (status) { |
|
2132 break; |
|
2133 } |
|
2134 d->finishDispatchCycleLocked(currentTime, connection, seq, handled); |
|
2135 gotOne = true; |
|
2136 } |
|
2137 if (gotOne) { |
|
2138 d->runCommandsLockedInterruptible(); |
|
2139 if (status == WOULD_BLOCK) { |
|
2140 return 1; |
|
2141 } |
|
2142 } |
|
2143 |
|
2144 notify = status != DEAD_OBJECT || !connection->monitor; |
|
2145 if (notify) { |
|
2146 ALOGE("channel '%s' ~ Failed to receive finished signal. status=%d", |
|
2147 connection->getInputChannelName(), status); |
|
2148 } |
|
2149 } else { |
|
2150 // Monitor channels are never explicitly unregistered. |
|
2151 // We do it automatically when the remote endpoint is closed so don't warn |
|
2152 // about them. |
|
2153 notify = !connection->monitor; |
|
2154 if (notify) { |
|
2155 ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred. " |
|
2156 "events=0x%x", connection->getInputChannelName(), events); |
|
2157 } |
|
2158 } |
|
2159 |
|
2160 // Unregister the channel. |
|
2161 d->unregisterInputChannelLocked(connection->inputChannel, notify); |
|
2162 return 0; // remove the callback |
|
2163 } // release lock |
|
2164 } |
|
2165 |
|
2166 void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked( |
|
2167 const CancelationOptions& options) { |
|
2168 for (size_t i = 0; i < mConnectionsByFd.size(); i++) { |
|
2169 synthesizeCancelationEventsForConnectionLocked( |
|
2170 mConnectionsByFd.valueAt(i), options); |
|
2171 } |
|
2172 } |
|
2173 |
|
2174 void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked( |
|
2175 const sp<InputChannel>& channel, const CancelationOptions& options) { |
|
2176 ssize_t index = getConnectionIndexLocked(channel); |
|
2177 if (index >= 0) { |
|
2178 synthesizeCancelationEventsForConnectionLocked( |
|
2179 mConnectionsByFd.valueAt(index), options); |
|
2180 } |
|
2181 } |
|
2182 |
|
2183 void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( |
|
2184 const sp<Connection>& connection, const CancelationOptions& options) { |
|
2185 if (connection->status == Connection::STATUS_BROKEN) { |
|
2186 return; |
|
2187 } |
|
2188 |
|
2189 nsecs_t currentTime = now(); |
|
2190 |
|
2191 Vector<EventEntry*> cancelationEvents; |
|
2192 connection->inputState.synthesizeCancelationEvents(currentTime, |
|
2193 cancelationEvents, options); |
|
2194 |
|
2195 if (!cancelationEvents.isEmpty()) { |
|
2196 #if DEBUG_OUTBOUND_EVENT_DETAILS |
|
2197 ALOGD("channel '%s' ~ Synthesized %d cancelation events to bring channel back in sync " |
|
2198 "with reality: %s, mode=%d.", |
|
2199 connection->getInputChannelName(), cancelationEvents.size(), |
|
2200 options.reason, options.mode); |
|
2201 #endif |
|
2202 for (size_t i = 0; i < cancelationEvents.size(); i++) { |
|
2203 EventEntry* cancelationEventEntry = cancelationEvents.itemAt(i); |
|
2204 switch (cancelationEventEntry->type) { |
|
2205 case EventEntry::TYPE_KEY: |
|
2206 logOutboundKeyDetailsLocked("cancel - ", |
|
2207 static_cast<KeyEntry*>(cancelationEventEntry)); |
|
2208 break; |
|
2209 case EventEntry::TYPE_MOTION: |
|
2210 logOutboundMotionDetailsLocked("cancel - ", |
|
2211 static_cast<MotionEntry*>(cancelationEventEntry)); |
|
2212 break; |
|
2213 } |
|
2214 |
|
2215 InputTarget target; |
|
2216 sp<InputWindowHandle> windowHandle = getWindowHandleLocked(connection->inputChannel); |
|
2217 if (windowHandle != NULL) { |
|
2218 const InputWindowInfo* windowInfo = windowHandle->getInfo(); |
|
2219 target.xOffset = -windowInfo->frameLeft; |
|
2220 target.yOffset = -windowInfo->frameTop; |
|
2221 target.scaleFactor = windowInfo->scaleFactor; |
|
2222 } else { |
|
2223 target.xOffset = 0; |
|
2224 target.yOffset = 0; |
|
2225 target.scaleFactor = 1.0f; |
|
2226 } |
|
2227 target.inputChannel = connection->inputChannel; |
|
2228 target.flags = InputTarget::FLAG_DISPATCH_AS_IS; |
|
2229 |
|
2230 enqueueDispatchEntryLocked(connection, cancelationEventEntry, // increments ref |
|
2231 &target, InputTarget::FLAG_DISPATCH_AS_IS); |
|
2232 |
|
2233 cancelationEventEntry->release(); |
|
2234 } |
|
2235 |
|
2236 startDispatchCycleLocked(currentTime, connection); |
|
2237 } |
|
2238 } |
|
2239 |
|
2240 InputDispatcher::MotionEntry* |
|
2241 InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds) { |
|
2242 ALOG_ASSERT(pointerIds.value != 0); |
|
2243 |
|
2244 uint32_t splitPointerIndexMap[MAX_POINTERS]; |
|
2245 PointerProperties splitPointerProperties[MAX_POINTERS]; |
|
2246 PointerCoords splitPointerCoords[MAX_POINTERS]; |
|
2247 |
|
2248 uint32_t originalPointerCount = originalMotionEntry->pointerCount; |
|
2249 uint32_t splitPointerCount = 0; |
|
2250 |
|
2251 for (uint32_t originalPointerIndex = 0; originalPointerIndex < originalPointerCount; |
|
2252 originalPointerIndex++) { |
|
2253 const PointerProperties& pointerProperties = |
|
2254 originalMotionEntry->pointerProperties[originalPointerIndex]; |
|
2255 uint32_t pointerId = uint32_t(pointerProperties.id); |
|
2256 if (pointerIds.hasBit(pointerId)) { |
|
2257 splitPointerIndexMap[splitPointerCount] = originalPointerIndex; |
|
2258 splitPointerProperties[splitPointerCount].copyFrom(pointerProperties); |
|
2259 splitPointerCoords[splitPointerCount].copyFrom( |
|
2260 originalMotionEntry->pointerCoords[originalPointerIndex]); |
|
2261 splitPointerCount += 1; |
|
2262 } |
|
2263 } |
|
2264 |
|
2265 if (splitPointerCount != pointerIds.count()) { |
|
2266 // This is bad. We are missing some of the pointers that we expected to deliver. |
|
2267 // Most likely this indicates that we received an ACTION_MOVE events that has |
|
2268 // different pointer ids than we expected based on the previous ACTION_DOWN |
|
2269 // or ACTION_POINTER_DOWN events that caused us to decide to split the pointers |
|
2270 // in this way. |
|
2271 ALOGW("Dropping split motion event because the pointer count is %d but " |
|
2272 "we expected there to be %d pointers. This probably means we received " |
|
2273 "a broken sequence of pointer ids from the input device.", |
|
2274 splitPointerCount, pointerIds.count()); |
|
2275 return NULL; |
|
2276 } |
|
2277 |
|
2278 int32_t action = originalMotionEntry->action; |
|
2279 int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK; |
|
2280 if (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN |
|
2281 || maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) { |
|
2282 int32_t originalPointerIndex = getMotionEventActionPointerIndex(action); |
|
2283 const PointerProperties& pointerProperties = |
|
2284 originalMotionEntry->pointerProperties[originalPointerIndex]; |
|
2285 uint32_t pointerId = uint32_t(pointerProperties.id); |
|
2286 if (pointerIds.hasBit(pointerId)) { |
|
2287 if (pointerIds.count() == 1) { |
|
2288 // The first/last pointer went down/up. |
|
2289 action = maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN |
|
2290 ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP; |
|
2291 } else { |
|
2292 // A secondary pointer went down/up. |
|
2293 uint32_t splitPointerIndex = 0; |
|
2294 while (pointerId != uint32_t(splitPointerProperties[splitPointerIndex].id)) { |
|
2295 splitPointerIndex += 1; |
|
2296 } |
|
2297 action = maskedAction | (splitPointerIndex |
|
2298 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); |
|
2299 } |
|
2300 } else { |
|
2301 // An unrelated pointer changed. |
|
2302 action = AMOTION_EVENT_ACTION_MOVE; |
|
2303 } |
|
2304 } |
|
2305 |
|
2306 MotionEntry* splitMotionEntry = new MotionEntry( |
|
2307 originalMotionEntry->eventTime, |
|
2308 originalMotionEntry->deviceId, |
|
2309 originalMotionEntry->source, |
|
2310 originalMotionEntry->policyFlags, |
|
2311 action, |
|
2312 originalMotionEntry->flags, |
|
2313 originalMotionEntry->metaState, |
|
2314 originalMotionEntry->buttonState, |
|
2315 originalMotionEntry->edgeFlags, |
|
2316 originalMotionEntry->xPrecision, |
|
2317 originalMotionEntry->yPrecision, |
|
2318 originalMotionEntry->downTime, |
|
2319 originalMotionEntry->displayId, |
|
2320 splitPointerCount, splitPointerProperties, splitPointerCoords); |
|
2321 |
|
2322 if (originalMotionEntry->injectionState) { |
|
2323 splitMotionEntry->injectionState = originalMotionEntry->injectionState; |
|
2324 splitMotionEntry->injectionState->refCount += 1; |
|
2325 } |
|
2326 |
|
2327 return splitMotionEntry; |
|
2328 } |
|
2329 |
|
2330 void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) { |
|
2331 #if DEBUG_INBOUND_EVENT_DETAILS |
|
2332 ALOGD("notifyConfigurationChanged - eventTime=%lld", args->eventTime); |
|
2333 #endif |
|
2334 |
|
2335 bool needWake; |
|
2336 { // acquire lock |
|
2337 AutoMutex _l(mLock); |
|
2338 |
|
2339 ConfigurationChangedEntry* newEntry = new ConfigurationChangedEntry(args->eventTime); |
|
2340 needWake = enqueueInboundEventLocked(newEntry); |
|
2341 } // release lock |
|
2342 |
|
2343 if (needWake) { |
|
2344 mLooper->wake(); |
|
2345 } |
|
2346 } |
|
2347 |
|
2348 void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { |
|
2349 #if DEBUG_INBOUND_EVENT_DETAILS |
|
2350 ALOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, " |
|
2351 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld", |
|
2352 args->eventTime, args->deviceId, args->source, args->policyFlags, |
|
2353 args->action, args->flags, args->keyCode, args->scanCode, |
|
2354 args->metaState, args->downTime); |
|
2355 #endif |
|
2356 if (!validateKeyEvent(args->action)) { |
|
2357 return; |
|
2358 } |
|
2359 |
|
2360 uint32_t policyFlags = args->policyFlags; |
|
2361 int32_t flags = args->flags; |
|
2362 int32_t metaState = args->metaState; |
|
2363 if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) { |
|
2364 policyFlags |= POLICY_FLAG_VIRTUAL; |
|
2365 flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY; |
|
2366 } |
|
2367 if (policyFlags & POLICY_FLAG_ALT) { |
|
2368 metaState |= AMETA_ALT_ON | AMETA_ALT_LEFT_ON; |
|
2369 } |
|
2370 if (policyFlags & POLICY_FLAG_ALT_GR) { |
|
2371 metaState |= AMETA_ALT_ON | AMETA_ALT_RIGHT_ON; |
|
2372 } |
|
2373 if (policyFlags & POLICY_FLAG_SHIFT) { |
|
2374 metaState |= AMETA_SHIFT_ON | AMETA_SHIFT_LEFT_ON; |
|
2375 } |
|
2376 if (policyFlags & POLICY_FLAG_CAPS_LOCK) { |
|
2377 metaState |= AMETA_CAPS_LOCK_ON; |
|
2378 } |
|
2379 if (policyFlags & POLICY_FLAG_FUNCTION) { |
|
2380 metaState |= AMETA_FUNCTION_ON; |
|
2381 } |
|
2382 |
|
2383 policyFlags |= POLICY_FLAG_TRUSTED; |
|
2384 |
|
2385 KeyEvent event; |
|
2386 event.initialize(args->deviceId, args->source, args->action, |
|
2387 flags, args->keyCode, args->scanCode, metaState, 0, |
|
2388 args->downTime, args->eventTime); |
|
2389 |
|
2390 mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags); |
|
2391 |
|
2392 if (policyFlags & POLICY_FLAG_WOKE_HERE) { |
|
2393 flags |= AKEY_EVENT_FLAG_WOKE_HERE; |
|
2394 } |
|
2395 |
|
2396 bool needWake; |
|
2397 { // acquire lock |
|
2398 mLock.lock(); |
|
2399 |
|
2400 if (shouldSendKeyToInputFilterLocked(args)) { |
|
2401 mLock.unlock(); |
|
2402 |
|
2403 policyFlags |= POLICY_FLAG_FILTERED; |
|
2404 if (!mPolicy->filterInputEvent(&event, policyFlags)) { |
|
2405 return; // event was consumed by the filter |
|
2406 } |
|
2407 |
|
2408 mLock.lock(); |
|
2409 } |
|
2410 |
|
2411 int32_t repeatCount = 0; |
|
2412 KeyEntry* newEntry = new KeyEntry(args->eventTime, |
|
2413 args->deviceId, args->source, policyFlags, |
|
2414 args->action, flags, args->keyCode, args->scanCode, |
|
2415 metaState, repeatCount, args->downTime); |
|
2416 |
|
2417 needWake = enqueueInboundEventLocked(newEntry); |
|
2418 mLock.unlock(); |
|
2419 } // release lock |
|
2420 |
|
2421 if (needWake) { |
|
2422 mLooper->wake(); |
|
2423 } |
|
2424 } |
|
2425 |
|
2426 bool InputDispatcher::shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) { |
|
2427 return mInputFilterEnabled; |
|
2428 } |
|
2429 |
|
2430 void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { |
|
2431 #if DEBUG_INBOUND_EVENT_DETAILS |
|
2432 ALOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, " |
|
2433 "action=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, edgeFlags=0x%x, " |
|
2434 "xPrecision=%f, yPrecision=%f, downTime=%lld", |
|
2435 args->eventTime, args->deviceId, args->source, args->policyFlags, |
|
2436 args->action, args->flags, args->metaState, args->buttonState, |
|
2437 args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime); |
|
2438 for (uint32_t i = 0; i < args->pointerCount; i++) { |
|
2439 ALOGD(" Pointer %d: id=%d, toolType=%d, " |
|
2440 "x=%f, y=%f, pressure=%f, size=%f, " |
|
2441 "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, " |
|
2442 "orientation=%f", |
|
2443 i, args->pointerProperties[i].id, |
|
2444 args->pointerProperties[i].toolType, |
|
2445 args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X), |
|
2446 args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y), |
|
2447 args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), |
|
2448 args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE), |
|
2449 args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR), |
|
2450 args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR), |
|
2451 args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), |
|
2452 args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), |
|
2453 args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION)); |
|
2454 } |
|
2455 #endif |
|
2456 if (!validateMotionEvent(args->action, args->pointerCount, args->pointerProperties)) { |
|
2457 return; |
|
2458 } |
|
2459 |
|
2460 uint32_t policyFlags = args->policyFlags; |
|
2461 policyFlags |= POLICY_FLAG_TRUSTED; |
|
2462 mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags); |
|
2463 |
|
2464 bool needWake; |
|
2465 { // acquire lock |
|
2466 mLock.lock(); |
|
2467 |
|
2468 if (shouldSendMotionToInputFilterLocked(args)) { |
|
2469 mLock.unlock(); |
|
2470 |
|
2471 MotionEvent event; |
|
2472 event.initialize(args->deviceId, args->source, args->action, args->flags, |
|
2473 args->edgeFlags, args->metaState, args->buttonState, 0, 0, |
|
2474 args->xPrecision, args->yPrecision, |
|
2475 args->downTime, args->eventTime, |
|
2476 args->pointerCount, args->pointerProperties, args->pointerCoords); |
|
2477 |
|
2478 policyFlags |= POLICY_FLAG_FILTERED; |
|
2479 if (!mPolicy->filterInputEvent(&event, policyFlags)) { |
|
2480 return; // event was consumed by the filter |
|
2481 } |
|
2482 |
|
2483 mLock.lock(); |
|
2484 } |
|
2485 |
|
2486 // Just enqueue a new motion event. |
|
2487 MotionEntry* newEntry = new MotionEntry(args->eventTime, |
|
2488 args->deviceId, args->source, policyFlags, |
|
2489 args->action, args->flags, args->metaState, args->buttonState, |
|
2490 args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime, |
|
2491 args->displayId, |
|
2492 args->pointerCount, args->pointerProperties, args->pointerCoords); |
|
2493 |
|
2494 needWake = enqueueInboundEventLocked(newEntry); |
|
2495 mLock.unlock(); |
|
2496 } // release lock |
|
2497 |
|
2498 if (needWake) { |
|
2499 mLooper->wake(); |
|
2500 } |
|
2501 } |
|
2502 |
|
2503 bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) { |
|
2504 // TODO: support sending secondary display events to input filter |
|
2505 return mInputFilterEnabled && isMainDisplay(args->displayId); |
|
2506 } |
|
2507 |
|
2508 void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) { |
|
2509 #if DEBUG_INBOUND_EVENT_DETAILS |
|
2510 ALOGD("notifySwitch - eventTime=%lld, policyFlags=0x%x, switchValues=0x%08x, switchMask=0x%08x", |
|
2511 args->eventTime, args->policyFlags, |
|
2512 args->switchValues, args->switchMask); |
|
2513 #endif |
|
2514 |
|
2515 uint32_t policyFlags = args->policyFlags; |
|
2516 policyFlags |= POLICY_FLAG_TRUSTED; |
|
2517 mPolicy->notifySwitch(args->eventTime, |
|
2518 args->switchValues, args->switchMask, policyFlags); |
|
2519 } |
|
2520 |
|
2521 void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) { |
|
2522 #if DEBUG_INBOUND_EVENT_DETAILS |
|
2523 ALOGD("notifyDeviceReset - eventTime=%lld, deviceId=%d", |
|
2524 args->eventTime, args->deviceId); |
|
2525 #endif |
|
2526 |
|
2527 bool needWake; |
|
2528 { // acquire lock |
|
2529 AutoMutex _l(mLock); |
|
2530 |
|
2531 DeviceResetEntry* newEntry = new DeviceResetEntry(args->eventTime, args->deviceId); |
|
2532 needWake = enqueueInboundEventLocked(newEntry); |
|
2533 } // release lock |
|
2534 |
|
2535 if (needWake) { |
|
2536 mLooper->wake(); |
|
2537 } |
|
2538 } |
|
2539 |
|
2540 int32_t InputDispatcher::injectInputEvent(const InputEvent* event, |
|
2541 int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis, |
|
2542 uint32_t policyFlags) { |
|
2543 #if DEBUG_INBOUND_EVENT_DETAILS |
|
2544 ALOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, " |
|
2545 "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x", |
|
2546 event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags); |
|
2547 #endif |
|
2548 |
|
2549 nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis); |
|
2550 |
|
2551 policyFlags |= POLICY_FLAG_INJECTED; |
|
2552 if (hasInjectionPermission(injectorPid, injectorUid)) { |
|
2553 policyFlags |= POLICY_FLAG_TRUSTED; |
|
2554 } |
|
2555 |
|
2556 EventEntry* firstInjectedEntry; |
|
2557 EventEntry* lastInjectedEntry; |
|
2558 switch (event->getType()) { |
|
2559 case AINPUT_EVENT_TYPE_KEY: { |
|
2560 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event); |
|
2561 int32_t action = keyEvent->getAction(); |
|
2562 if (! validateKeyEvent(action)) { |
|
2563 return INPUT_EVENT_INJECTION_FAILED; |
|
2564 } |
|
2565 |
|
2566 int32_t flags = keyEvent->getFlags(); |
|
2567 if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) { |
|
2568 policyFlags |= POLICY_FLAG_VIRTUAL; |
|
2569 } |
|
2570 |
|
2571 if (!(policyFlags & POLICY_FLAG_FILTERED)) { |
|
2572 mPolicy->interceptKeyBeforeQueueing(keyEvent, /*byref*/ policyFlags); |
|
2573 } |
|
2574 |
|
2575 if (policyFlags & POLICY_FLAG_WOKE_HERE) { |
|
2576 flags |= AKEY_EVENT_FLAG_WOKE_HERE; |
|
2577 } |
|
2578 |
|
2579 mLock.lock(); |
|
2580 firstInjectedEntry = new KeyEntry(keyEvent->getEventTime(), |
|
2581 keyEvent->getDeviceId(), keyEvent->getSource(), |
|
2582 policyFlags, action, flags, |
|
2583 keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(), |
|
2584 keyEvent->getRepeatCount(), keyEvent->getDownTime()); |
|
2585 lastInjectedEntry = firstInjectedEntry; |
|
2586 break; |
|
2587 } |
|
2588 |
|
2589 case AINPUT_EVENT_TYPE_MOTION: { |
|
2590 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event); |
|
2591 int32_t displayId = ADISPLAY_ID_DEFAULT; |
|
2592 int32_t action = motionEvent->getAction(); |
|
2593 size_t pointerCount = motionEvent->getPointerCount(); |
|
2594 const PointerProperties* pointerProperties = motionEvent->getPointerProperties(); |
|
2595 if (! validateMotionEvent(action, pointerCount, pointerProperties)) { |
|
2596 return INPUT_EVENT_INJECTION_FAILED; |
|
2597 } |
|
2598 |
|
2599 if (!(policyFlags & POLICY_FLAG_FILTERED)) { |
|
2600 nsecs_t eventTime = motionEvent->getEventTime(); |
|
2601 mPolicy->interceptMotionBeforeQueueing(eventTime, /*byref*/ policyFlags); |
|
2602 } |
|
2603 |
|
2604 mLock.lock(); |
|
2605 const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes(); |
|
2606 const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords(); |
|
2607 firstInjectedEntry = new MotionEntry(*sampleEventTimes, |
|
2608 motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags, |
|
2609 action, motionEvent->getFlags(), |
|
2610 motionEvent->getMetaState(), motionEvent->getButtonState(), |
|
2611 motionEvent->getEdgeFlags(), |
|
2612 motionEvent->getXPrecision(), motionEvent->getYPrecision(), |
|
2613 motionEvent->getDownTime(), displayId, |
|
2614 uint32_t(pointerCount), pointerProperties, samplePointerCoords); |
|
2615 lastInjectedEntry = firstInjectedEntry; |
|
2616 for (size_t i = motionEvent->getHistorySize(); i > 0; i--) { |
|
2617 sampleEventTimes += 1; |
|
2618 samplePointerCoords += pointerCount; |
|
2619 MotionEntry* nextInjectedEntry = new MotionEntry(*sampleEventTimes, |
|
2620 motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags, |
|
2621 action, motionEvent->getFlags(), |
|
2622 motionEvent->getMetaState(), motionEvent->getButtonState(), |
|
2623 motionEvent->getEdgeFlags(), |
|
2624 motionEvent->getXPrecision(), motionEvent->getYPrecision(), |
|
2625 motionEvent->getDownTime(), displayId, |
|
2626 uint32_t(pointerCount), pointerProperties, samplePointerCoords); |
|
2627 lastInjectedEntry->next = nextInjectedEntry; |
|
2628 lastInjectedEntry = nextInjectedEntry; |
|
2629 } |
|
2630 break; |
|
2631 } |
|
2632 |
|
2633 default: |
|
2634 ALOGW("Cannot inject event of type %d", event->getType()); |
|
2635 return INPUT_EVENT_INJECTION_FAILED; |
|
2636 } |
|
2637 |
|
2638 InjectionState* injectionState = new InjectionState(injectorPid, injectorUid); |
|
2639 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) { |
|
2640 injectionState->injectionIsAsync = true; |
|
2641 } |
|
2642 |
|
2643 injectionState->refCount += 1; |
|
2644 lastInjectedEntry->injectionState = injectionState; |
|
2645 |
|
2646 bool needWake = false; |
|
2647 for (EventEntry* entry = firstInjectedEntry; entry != NULL; ) { |
|
2648 EventEntry* nextEntry = entry->next; |
|
2649 needWake |= enqueueInboundEventLocked(entry); |
|
2650 entry = nextEntry; |
|
2651 } |
|
2652 |
|
2653 mLock.unlock(); |
|
2654 |
|
2655 if (needWake) { |
|
2656 mLooper->wake(); |
|
2657 } |
|
2658 |
|
2659 int32_t injectionResult; |
|
2660 { // acquire lock |
|
2661 AutoMutex _l(mLock); |
|
2662 |
|
2663 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) { |
|
2664 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED; |
|
2665 } else { |
|
2666 for (;;) { |
|
2667 injectionResult = injectionState->injectionResult; |
|
2668 if (injectionResult != INPUT_EVENT_INJECTION_PENDING) { |
|
2669 break; |
|
2670 } |
|
2671 |
|
2672 nsecs_t remainingTimeout = endTime - now(); |
|
2673 if (remainingTimeout <= 0) { |
|
2674 #if DEBUG_INJECTION |
|
2675 ALOGD("injectInputEvent - Timed out waiting for injection result " |
|
2676 "to become available."); |
|
2677 #endif |
|
2678 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT; |
|
2679 break; |
|
2680 } |
|
2681 |
|
2682 mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout); |
|
2683 } |
|
2684 |
|
2685 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED |
|
2686 && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) { |
|
2687 while (injectionState->pendingForegroundDispatches != 0) { |
|
2688 #if DEBUG_INJECTION |
|
2689 ALOGD("injectInputEvent - Waiting for %d pending foreground dispatches.", |
|
2690 injectionState->pendingForegroundDispatches); |
|
2691 #endif |
|
2692 nsecs_t remainingTimeout = endTime - now(); |
|
2693 if (remainingTimeout <= 0) { |
|
2694 #if DEBUG_INJECTION |
|
2695 ALOGD("injectInputEvent - Timed out waiting for pending foreground " |
|
2696 "dispatches to finish."); |
|
2697 #endif |
|
2698 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT; |
|
2699 break; |
|
2700 } |
|
2701 |
|
2702 mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout); |
|
2703 } |
|
2704 } |
|
2705 } |
|
2706 |
|
2707 injectionState->release(); |
|
2708 } // release lock |
|
2709 |
|
2710 #if DEBUG_INJECTION |
|
2711 ALOGD("injectInputEvent - Finished with result %d. " |
|
2712 "injectorPid=%d, injectorUid=%d", |
|
2713 injectionResult, injectorPid, injectorUid); |
|
2714 #endif |
|
2715 |
|
2716 return injectionResult; |
|
2717 } |
|
2718 |
|
2719 bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) { |
|
2720 return injectorUid == 0 |
|
2721 || mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid); |
|
2722 } |
|
2723 |
|
2724 void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) { |
|
2725 InjectionState* injectionState = entry->injectionState; |
|
2726 if (injectionState) { |
|
2727 #if DEBUG_INJECTION |
|
2728 ALOGD("Setting input event injection result to %d. " |
|
2729 "injectorPid=%d, injectorUid=%d", |
|
2730 injectionResult, injectionState->injectorPid, injectionState->injectorUid); |
|
2731 #endif |
|
2732 |
|
2733 if (injectionState->injectionIsAsync |
|
2734 && !(entry->policyFlags & POLICY_FLAG_FILTERED)) { |
|
2735 // Log the outcome since the injector did not wait for the injection result. |
|
2736 switch (injectionResult) { |
|
2737 case INPUT_EVENT_INJECTION_SUCCEEDED: |
|
2738 ALOGV("Asynchronous input event injection succeeded."); |
|
2739 break; |
|
2740 case INPUT_EVENT_INJECTION_FAILED: |
|
2741 ALOGW("Asynchronous input event injection failed."); |
|
2742 break; |
|
2743 case INPUT_EVENT_INJECTION_PERMISSION_DENIED: |
|
2744 ALOGW("Asynchronous input event injection permission denied."); |
|
2745 break; |
|
2746 case INPUT_EVENT_INJECTION_TIMED_OUT: |
|
2747 ALOGW("Asynchronous input event injection timed out."); |
|
2748 break; |
|
2749 } |
|
2750 } |
|
2751 |
|
2752 injectionState->injectionResult = injectionResult; |
|
2753 mInjectionResultAvailableCondition.broadcast(); |
|
2754 } |
|
2755 } |
|
2756 |
|
2757 void InputDispatcher::incrementPendingForegroundDispatchesLocked(EventEntry* entry) { |
|
2758 InjectionState* injectionState = entry->injectionState; |
|
2759 if (injectionState) { |
|
2760 injectionState->pendingForegroundDispatches += 1; |
|
2761 } |
|
2762 } |
|
2763 |
|
2764 void InputDispatcher::decrementPendingForegroundDispatchesLocked(EventEntry* entry) { |
|
2765 InjectionState* injectionState = entry->injectionState; |
|
2766 if (injectionState) { |
|
2767 injectionState->pendingForegroundDispatches -= 1; |
|
2768 |
|
2769 if (injectionState->pendingForegroundDispatches == 0) { |
|
2770 mInjectionSyncFinishedCondition.broadcast(); |
|
2771 } |
|
2772 } |
|
2773 } |
|
2774 |
|
2775 sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked( |
|
2776 const sp<InputChannel>& inputChannel) const { |
|
2777 size_t numWindows = mWindowHandles.size(); |
|
2778 for (size_t i = 0; i < numWindows; i++) { |
|
2779 const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i); |
|
2780 if (windowHandle->getInputChannel() == inputChannel) { |
|
2781 return windowHandle; |
|
2782 } |
|
2783 } |
|
2784 return NULL; |
|
2785 } |
|
2786 |
|
2787 bool InputDispatcher::hasWindowHandleLocked( |
|
2788 const sp<InputWindowHandle>& windowHandle) const { |
|
2789 size_t numWindows = mWindowHandles.size(); |
|
2790 for (size_t i = 0; i < numWindows; i++) { |
|
2791 if (mWindowHandles.itemAt(i) == windowHandle) { |
|
2792 return true; |
|
2793 } |
|
2794 } |
|
2795 return false; |
|
2796 } |
|
2797 |
|
2798 void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) { |
|
2799 #if DEBUG_FOCUS |
|
2800 ALOGD("setInputWindows"); |
|
2801 #endif |
|
2802 { // acquire lock |
|
2803 AutoMutex _l(mLock); |
|
2804 |
|
2805 Vector<sp<InputWindowHandle> > oldWindowHandles = mWindowHandles; |
|
2806 mWindowHandles = inputWindowHandles; |
|
2807 |
|
2808 sp<InputWindowHandle> newFocusedWindowHandle; |
|
2809 bool foundHoveredWindow = false; |
|
2810 for (size_t i = 0; i < mWindowHandles.size(); i++) { |
|
2811 const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i); |
|
2812 if (!windowHandle->updateInfo() || windowHandle->getInputChannel() == NULL) { |
|
2813 mWindowHandles.removeAt(i--); |
|
2814 continue; |
|
2815 } |
|
2816 if (windowHandle->getInfo()->hasFocus) { |
|
2817 newFocusedWindowHandle = windowHandle; |
|
2818 } |
|
2819 if (windowHandle == mLastHoverWindowHandle) { |
|
2820 foundHoveredWindow = true; |
|
2821 } |
|
2822 } |
|
2823 |
|
2824 if (!foundHoveredWindow) { |
|
2825 mLastHoverWindowHandle = NULL; |
|
2826 } |
|
2827 |
|
2828 if (mFocusedWindowHandle != newFocusedWindowHandle) { |
|
2829 if (mFocusedWindowHandle != NULL) { |
|
2830 #if DEBUG_FOCUS |
|
2831 ALOGD("Focus left window: %s", |
|
2832 mFocusedWindowHandle->getName().string()); |
|
2833 #endif |
|
2834 sp<InputChannel> focusedInputChannel = mFocusedWindowHandle->getInputChannel(); |
|
2835 if (focusedInputChannel != NULL) { |
|
2836 CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, |
|
2837 "focus left window"); |
|
2838 synthesizeCancelationEventsForInputChannelLocked( |
|
2839 focusedInputChannel, options); |
|
2840 } |
|
2841 } |
|
2842 if (newFocusedWindowHandle != NULL) { |
|
2843 #if DEBUG_FOCUS |
|
2844 ALOGD("Focus entered window: %s", |
|
2845 newFocusedWindowHandle->getName().string()); |
|
2846 #endif |
|
2847 } |
|
2848 mFocusedWindowHandle = newFocusedWindowHandle; |
|
2849 } |
|
2850 |
|
2851 for (size_t i = 0; i < mTouchState.windows.size(); i++) { |
|
2852 TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i); |
|
2853 if (!hasWindowHandleLocked(touchedWindow.windowHandle)) { |
|
2854 #if DEBUG_FOCUS |
|
2855 ALOGD("Touched window was removed: %s", |
|
2856 touchedWindow.windowHandle->getName().string()); |
|
2857 #endif |
|
2858 sp<InputChannel> touchedInputChannel = |
|
2859 touchedWindow.windowHandle->getInputChannel(); |
|
2860 if (touchedInputChannel != NULL) { |
|
2861 CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, |
|
2862 "touched window was removed"); |
|
2863 synthesizeCancelationEventsForInputChannelLocked( |
|
2864 touchedInputChannel, options); |
|
2865 } |
|
2866 mTouchState.windows.removeAt(i--); |
|
2867 } |
|
2868 } |
|
2869 |
|
2870 // Release information for windows that are no longer present. |
|
2871 // This ensures that unused input channels are released promptly. |
|
2872 // Otherwise, they might stick around until the window handle is destroyed |
|
2873 // which might not happen until the next GC. |
|
2874 for (size_t i = 0; i < oldWindowHandles.size(); i++) { |
|
2875 const sp<InputWindowHandle>& oldWindowHandle = oldWindowHandles.itemAt(i); |
|
2876 if (!hasWindowHandleLocked(oldWindowHandle)) { |
|
2877 #if DEBUG_FOCUS |
|
2878 ALOGD("Window went away: %s", oldWindowHandle->getName().string()); |
|
2879 #endif |
|
2880 oldWindowHandle->releaseInfo(); |
|
2881 } |
|
2882 } |
|
2883 } // release lock |
|
2884 |
|
2885 // Wake up poll loop since it may need to make new input dispatching choices. |
|
2886 mLooper->wake(); |
|
2887 } |
|
2888 |
|
2889 void InputDispatcher::setFocusedApplication( |
|
2890 const sp<InputApplicationHandle>& inputApplicationHandle) { |
|
2891 #if DEBUG_FOCUS |
|
2892 ALOGD("setFocusedApplication"); |
|
2893 #endif |
|
2894 { // acquire lock |
|
2895 AutoMutex _l(mLock); |
|
2896 |
|
2897 if (inputApplicationHandle != NULL && inputApplicationHandle->updateInfo()) { |
|
2898 if (mFocusedApplicationHandle != inputApplicationHandle) { |
|
2899 if (mFocusedApplicationHandle != NULL) { |
|
2900 resetANRTimeoutsLocked(); |
|
2901 mFocusedApplicationHandle->releaseInfo(); |
|
2902 } |
|
2903 mFocusedApplicationHandle = inputApplicationHandle; |
|
2904 } |
|
2905 } else if (mFocusedApplicationHandle != NULL) { |
|
2906 resetANRTimeoutsLocked(); |
|
2907 mFocusedApplicationHandle->releaseInfo(); |
|
2908 mFocusedApplicationHandle.clear(); |
|
2909 } |
|
2910 |
|
2911 #if DEBUG_FOCUS |
|
2912 //logDispatchStateLocked(); |
|
2913 #endif |
|
2914 } // release lock |
|
2915 |
|
2916 // Wake up poll loop since it may need to make new input dispatching choices. |
|
2917 mLooper->wake(); |
|
2918 } |
|
2919 |
|
2920 void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) { |
|
2921 #if DEBUG_FOCUS |
|
2922 ALOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen); |
|
2923 #endif |
|
2924 |
|
2925 bool changed; |
|
2926 { // acquire lock |
|
2927 AutoMutex _l(mLock); |
|
2928 |
|
2929 if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) { |
|
2930 if (mDispatchFrozen && !frozen) { |
|
2931 resetANRTimeoutsLocked(); |
|
2932 } |
|
2933 |
|
2934 if (mDispatchEnabled && !enabled) { |
|
2935 resetAndDropEverythingLocked("dispatcher is being disabled"); |
|
2936 } |
|
2937 |
|
2938 mDispatchEnabled = enabled; |
|
2939 mDispatchFrozen = frozen; |
|
2940 changed = true; |
|
2941 } else { |
|
2942 changed = false; |
|
2943 } |
|
2944 |
|
2945 #if DEBUG_FOCUS |
|
2946 //logDispatchStateLocked(); |
|
2947 #endif |
|
2948 } // release lock |
|
2949 |
|
2950 if (changed) { |
|
2951 // Wake up poll loop since it may need to make new input dispatching choices. |
|
2952 mLooper->wake(); |
|
2953 } |
|
2954 } |
|
2955 |
|
2956 void InputDispatcher::setInputFilterEnabled(bool enabled) { |
|
2957 #if DEBUG_FOCUS |
|
2958 ALOGD("setInputFilterEnabled: enabled=%d", enabled); |
|
2959 #endif |
|
2960 |
|
2961 { // acquire lock |
|
2962 AutoMutex _l(mLock); |
|
2963 |
|
2964 if (mInputFilterEnabled == enabled) { |
|
2965 return; |
|
2966 } |
|
2967 |
|
2968 mInputFilterEnabled = enabled; |
|
2969 resetAndDropEverythingLocked("input filter is being enabled or disabled"); |
|
2970 } // release lock |
|
2971 |
|
2972 // Wake up poll loop since there might be work to do to drop everything. |
|
2973 mLooper->wake(); |
|
2974 } |
|
2975 |
|
2976 bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel, |
|
2977 const sp<InputChannel>& toChannel) { |
|
2978 #if DEBUG_FOCUS |
|
2979 ALOGD("transferTouchFocus: fromChannel=%s, toChannel=%s", |
|
2980 fromChannel->getName().string(), toChannel->getName().string()); |
|
2981 #endif |
|
2982 { // acquire lock |
|
2983 AutoMutex _l(mLock); |
|
2984 |
|
2985 sp<InputWindowHandle> fromWindowHandle = getWindowHandleLocked(fromChannel); |
|
2986 sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(toChannel); |
|
2987 if (fromWindowHandle == NULL || toWindowHandle == NULL) { |
|
2988 #if DEBUG_FOCUS |
|
2989 ALOGD("Cannot transfer focus because from or to window not found."); |
|
2990 #endif |
|
2991 return false; |
|
2992 } |
|
2993 if (fromWindowHandle == toWindowHandle) { |
|
2994 #if DEBUG_FOCUS |
|
2995 ALOGD("Trivial transfer to same window."); |
|
2996 #endif |
|
2997 return true; |
|
2998 } |
|
2999 if (fromWindowHandle->getInfo()->displayId != toWindowHandle->getInfo()->displayId) { |
|
3000 #if DEBUG_FOCUS |
|
3001 ALOGD("Cannot transfer focus because windows are on different displays."); |
|
3002 #endif |
|
3003 return false; |
|
3004 } |
|
3005 |
|
3006 bool found = false; |
|
3007 for (size_t i = 0; i < mTouchState.windows.size(); i++) { |
|
3008 const TouchedWindow& touchedWindow = mTouchState.windows[i]; |
|
3009 if (touchedWindow.windowHandle == fromWindowHandle) { |
|
3010 int32_t oldTargetFlags = touchedWindow.targetFlags; |
|
3011 BitSet32 pointerIds = touchedWindow.pointerIds; |
|
3012 |
|
3013 mTouchState.windows.removeAt(i); |
|
3014 |
|
3015 int32_t newTargetFlags = oldTargetFlags |
|
3016 & (InputTarget::FLAG_FOREGROUND |
|
3017 | InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS); |
|
3018 mTouchState.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds); |
|
3019 |
|
3020 found = true; |
|
3021 break; |
|
3022 } |
|
3023 } |
|
3024 |
|
3025 if (! found) { |
|
3026 #if DEBUG_FOCUS |
|
3027 ALOGD("Focus transfer failed because from window did not have focus."); |
|
3028 #endif |
|
3029 return false; |
|
3030 } |
|
3031 |
|
3032 ssize_t fromConnectionIndex = getConnectionIndexLocked(fromChannel); |
|
3033 ssize_t toConnectionIndex = getConnectionIndexLocked(toChannel); |
|
3034 if (fromConnectionIndex >= 0 && toConnectionIndex >= 0) { |
|
3035 sp<Connection> fromConnection = mConnectionsByFd.valueAt(fromConnectionIndex); |
|
3036 sp<Connection> toConnection = mConnectionsByFd.valueAt(toConnectionIndex); |
|
3037 |
|
3038 fromConnection->inputState.copyPointerStateTo(toConnection->inputState); |
|
3039 CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, |
|
3040 "transferring touch focus from this window to another window"); |
|
3041 synthesizeCancelationEventsForConnectionLocked(fromConnection, options); |
|
3042 } |
|
3043 |
|
3044 #if DEBUG_FOCUS |
|
3045 logDispatchStateLocked(); |
|
3046 #endif |
|
3047 } // release lock |
|
3048 |
|
3049 // Wake up poll loop since it may need to make new input dispatching choices. |
|
3050 mLooper->wake(); |
|
3051 return true; |
|
3052 } |
|
3053 |
|
3054 void InputDispatcher::resetAndDropEverythingLocked(const char* reason) { |
|
3055 #if DEBUG_FOCUS |
|
3056 ALOGD("Resetting and dropping all events (%s).", reason); |
|
3057 #endif |
|
3058 |
|
3059 CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS, reason); |
|
3060 synthesizeCancelationEventsForAllConnectionsLocked(options); |
|
3061 |
|
3062 resetKeyRepeatLocked(); |
|
3063 releasePendingEventLocked(); |
|
3064 drainInboundQueueLocked(); |
|
3065 resetANRTimeoutsLocked(); |
|
3066 |
|
3067 mTouchState.reset(); |
|
3068 mLastHoverWindowHandle.clear(); |
|
3069 } |
|
3070 |
|
3071 void InputDispatcher::logDispatchStateLocked() { |
|
3072 String8 dump; |
|
3073 dumpDispatchStateLocked(dump); |
|
3074 |
|
3075 char* text = dump.lockBuffer(dump.size()); |
|
3076 char* start = text; |
|
3077 while (*start != '\0') { |
|
3078 char* end = strchr(start, '\n'); |
|
3079 if (*end == '\n') { |
|
3080 *(end++) = '\0'; |
|
3081 } |
|
3082 ALOGD("%s", start); |
|
3083 start = end; |
|
3084 } |
|
3085 } |
|
3086 |
|
3087 void InputDispatcher::dumpDispatchStateLocked(String8& dump) { |
|
3088 dump.appendFormat(INDENT "DispatchEnabled: %d\n", mDispatchEnabled); |
|
3089 dump.appendFormat(INDENT "DispatchFrozen: %d\n", mDispatchFrozen); |
|
3090 |
|
3091 if (mFocusedApplicationHandle != NULL) { |
|
3092 dump.appendFormat(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n", |
|
3093 mFocusedApplicationHandle->getName().string(), |
|
3094 mFocusedApplicationHandle->getDispatchingTimeout( |
|
3095 DEFAULT_INPUT_DISPATCHING_TIMEOUT) / 1000000.0); |
|
3096 } else { |
|
3097 dump.append(INDENT "FocusedApplication: <null>\n"); |
|
3098 } |
|
3099 dump.appendFormat(INDENT "FocusedWindow: name='%s'\n", |
|
3100 mFocusedWindowHandle != NULL ? mFocusedWindowHandle->getName().string() : "<null>"); |
|
3101 |
|
3102 dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down)); |
|
3103 dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split)); |
|
3104 dump.appendFormat(INDENT "TouchDeviceId: %d\n", mTouchState.deviceId); |
|
3105 dump.appendFormat(INDENT "TouchSource: 0x%08x\n", mTouchState.source); |
|
3106 dump.appendFormat(INDENT "TouchDisplayId: %d\n", mTouchState.displayId); |
|
3107 if (!mTouchState.windows.isEmpty()) { |
|
3108 dump.append(INDENT "TouchedWindows:\n"); |
|
3109 for (size_t i = 0; i < mTouchState.windows.size(); i++) { |
|
3110 const TouchedWindow& touchedWindow = mTouchState.windows[i]; |
|
3111 dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n", |
|
3112 i, touchedWindow.windowHandle->getName().string(), |
|
3113 touchedWindow.pointerIds.value, |
|
3114 touchedWindow.targetFlags); |
|
3115 } |
|
3116 } else { |
|
3117 dump.append(INDENT "TouchedWindows: <none>\n"); |
|
3118 } |
|
3119 |
|
3120 if (!mWindowHandles.isEmpty()) { |
|
3121 dump.append(INDENT "Windows:\n"); |
|
3122 for (size_t i = 0; i < mWindowHandles.size(); i++) { |
|
3123 const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i); |
|
3124 const InputWindowInfo* windowInfo = windowHandle->getInfo(); |
|
3125 |
|
3126 dump.appendFormat(INDENT2 "%d: name='%s', displayId=%d, " |
|
3127 "paused=%s, hasFocus=%s, hasWallpaper=%s, " |
|
3128 "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, " |
|
3129 "frame=[%d,%d][%d,%d], scale=%f, " |
|
3130 "touchableRegion=", |
|
3131 i, windowInfo->name.string(), windowInfo->displayId, |
|
3132 toString(windowInfo->paused), |
|
3133 toString(windowInfo->hasFocus), |
|
3134 toString(windowInfo->hasWallpaper), |
|
3135 toString(windowInfo->visible), |
|
3136 toString(windowInfo->canReceiveKeys), |
|
3137 windowInfo->layoutParamsFlags, windowInfo->layoutParamsType, |
|
3138 windowInfo->layer, |
|
3139 windowInfo->frameLeft, windowInfo->frameTop, |
|
3140 windowInfo->frameRight, windowInfo->frameBottom, |
|
3141 windowInfo->scaleFactor); |
|
3142 dumpRegion(dump, windowInfo->touchableRegion); |
|
3143 dump.appendFormat(", inputFeatures=0x%08x", windowInfo->inputFeatures); |
|
3144 dump.appendFormat(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n", |
|
3145 windowInfo->ownerPid, windowInfo->ownerUid, |
|
3146 windowInfo->dispatchingTimeout / 1000000.0); |
|
3147 } |
|
3148 } else { |
|
3149 dump.append(INDENT "Windows: <none>\n"); |
|
3150 } |
|
3151 |
|
3152 if (!mMonitoringChannels.isEmpty()) { |
|
3153 dump.append(INDENT "MonitoringChannels:\n"); |
|
3154 for (size_t i = 0; i < mMonitoringChannels.size(); i++) { |
|
3155 const sp<InputChannel>& channel = mMonitoringChannels[i]; |
|
3156 dump.appendFormat(INDENT2 "%d: '%s'\n", i, channel->getName().string()); |
|
3157 } |
|
3158 } else { |
|
3159 dump.append(INDENT "MonitoringChannels: <none>\n"); |
|
3160 } |
|
3161 |
|
3162 nsecs_t currentTime = now(); |
|
3163 |
|
3164 if (!mInboundQueue.isEmpty()) { |
|
3165 dump.appendFormat(INDENT "InboundQueue: length=%u\n", mInboundQueue.count()); |
|
3166 for (EventEntry* entry = mInboundQueue.head; entry; entry = entry->next) { |
|
3167 dump.append(INDENT2); |
|
3168 entry->appendDescription(dump); |
|
3169 dump.appendFormat(", age=%0.1fms\n", |
|
3170 (currentTime - entry->eventTime) * 0.000001f); |
|
3171 } |
|
3172 } else { |
|
3173 dump.append(INDENT "InboundQueue: <empty>\n"); |
|
3174 } |
|
3175 |
|
3176 if (!mConnectionsByFd.isEmpty()) { |
|
3177 dump.append(INDENT "Connections:\n"); |
|
3178 for (size_t i = 0; i < mConnectionsByFd.size(); i++) { |
|
3179 const sp<Connection>& connection = mConnectionsByFd.valueAt(i); |
|
3180 dump.appendFormat(INDENT2 "%d: channelName='%s', windowName='%s', " |
|
3181 "status=%s, monitor=%s, inputPublisherBlocked=%s\n", |
|
3182 i, connection->getInputChannelName(), connection->getWindowName(), |
|
3183 connection->getStatusLabel(), toString(connection->monitor), |
|
3184 toString(connection->inputPublisherBlocked)); |
|
3185 |
|
3186 if (!connection->outboundQueue.isEmpty()) { |
|
3187 dump.appendFormat(INDENT3 "OutboundQueue: length=%u\n", |
|
3188 connection->outboundQueue.count()); |
|
3189 for (DispatchEntry* entry = connection->outboundQueue.head; entry; |
|
3190 entry = entry->next) { |
|
3191 dump.append(INDENT4); |
|
3192 entry->eventEntry->appendDescription(dump); |
|
3193 dump.appendFormat(", targetFlags=0x%08x, resolvedAction=%d, age=%0.1fms\n", |
|
3194 entry->targetFlags, entry->resolvedAction, |
|
3195 (currentTime - entry->eventEntry->eventTime) * 0.000001f); |
|
3196 } |
|
3197 } else { |
|
3198 dump.append(INDENT3 "OutboundQueue: <empty>\n"); |
|
3199 } |
|
3200 |
|
3201 if (!connection->waitQueue.isEmpty()) { |
|
3202 dump.appendFormat(INDENT3 "WaitQueue: length=%u\n", |
|
3203 connection->waitQueue.count()); |
|
3204 for (DispatchEntry* entry = connection->waitQueue.head; entry; |
|
3205 entry = entry->next) { |
|
3206 dump.append(INDENT4); |
|
3207 entry->eventEntry->appendDescription(dump); |
|
3208 dump.appendFormat(", targetFlags=0x%08x, resolvedAction=%d, " |
|
3209 "age=%0.1fms, wait=%0.1fms\n", |
|
3210 entry->targetFlags, entry->resolvedAction, |
|
3211 (currentTime - entry->eventEntry->eventTime) * 0.000001f, |
|
3212 (currentTime - entry->deliveryTime) * 0.000001f); |
|
3213 } |
|
3214 } else { |
|
3215 dump.append(INDENT3 "WaitQueue: <empty>\n"); |
|
3216 } |
|
3217 } |
|
3218 } else { |
|
3219 dump.append(INDENT "Connections: <none>\n"); |
|
3220 } |
|
3221 |
|
3222 if (isAppSwitchPendingLocked()) { |
|
3223 dump.appendFormat(INDENT "AppSwitch: pending, due in %0.1fms\n", |
|
3224 (mAppSwitchDueTime - now()) / 1000000.0); |
|
3225 } else { |
|
3226 dump.append(INDENT "AppSwitch: not pending\n"); |
|
3227 } |
|
3228 |
|
3229 dump.append(INDENT "Configuration:\n"); |
|
3230 dump.appendFormat(INDENT2 "KeyRepeatDelay: %0.1fms\n", |
|
3231 mConfig.keyRepeatDelay * 0.000001f); |
|
3232 dump.appendFormat(INDENT2 "KeyRepeatTimeout: %0.1fms\n", |
|
3233 mConfig.keyRepeatTimeout * 0.000001f); |
|
3234 } |
|
3235 |
|
3236 status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel, |
|
3237 const sp<InputWindowHandle>& inputWindowHandle, bool monitor) { |
|
3238 #if DEBUG_REGISTRATION |
|
3239 ALOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().string(), |
|
3240 toString(monitor)); |
|
3241 #endif |
|
3242 |
|
3243 { // acquire lock |
|
3244 AutoMutex _l(mLock); |
|
3245 |
|
3246 if (getConnectionIndexLocked(inputChannel) >= 0) { |
|
3247 ALOGW("Attempted to register already registered input channel '%s'", |
|
3248 inputChannel->getName().string()); |
|
3249 return BAD_VALUE; |
|
3250 } |
|
3251 |
|
3252 sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor); |
|
3253 |
|
3254 int fd = inputChannel->getFd(); |
|
3255 mConnectionsByFd.add(fd, connection); |
|
3256 |
|
3257 if (monitor) { |
|
3258 mMonitoringChannels.push(inputChannel); |
|
3259 } |
|
3260 |
|
3261 mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this); |
|
3262 } // release lock |
|
3263 |
|
3264 // Wake the looper because some connections have changed. |
|
3265 mLooper->wake(); |
|
3266 return OK; |
|
3267 } |
|
3268 |
|
3269 status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) { |
|
3270 #if DEBUG_REGISTRATION |
|
3271 ALOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string()); |
|
3272 #endif |
|
3273 |
|
3274 { // acquire lock |
|
3275 AutoMutex _l(mLock); |
|
3276 |
|
3277 status_t status = unregisterInputChannelLocked(inputChannel, false /*notify*/); |
|
3278 if (status) { |
|
3279 return status; |
|
3280 } |
|
3281 } // release lock |
|
3282 |
|
3283 // Wake the poll loop because removing the connection may have changed the current |
|
3284 // synchronization state. |
|
3285 mLooper->wake(); |
|
3286 return OK; |
|
3287 } |
|
3288 |
|
3289 status_t InputDispatcher::unregisterInputChannelLocked(const sp<InputChannel>& inputChannel, |
|
3290 bool notify) { |
|
3291 ssize_t connectionIndex = getConnectionIndexLocked(inputChannel); |
|
3292 if (connectionIndex < 0) { |
|
3293 ALOGW("Attempted to unregister already unregistered input channel '%s'", |
|
3294 inputChannel->getName().string()); |
|
3295 return BAD_VALUE; |
|
3296 } |
|
3297 |
|
3298 sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex); |
|
3299 mConnectionsByFd.removeItemsAt(connectionIndex); |
|
3300 |
|
3301 if (connection->monitor) { |
|
3302 removeMonitorChannelLocked(inputChannel); |
|
3303 } |
|
3304 |
|
3305 mLooper->removeFd(inputChannel->getFd()); |
|
3306 |
|
3307 nsecs_t currentTime = now(); |
|
3308 abortBrokenDispatchCycleLocked(currentTime, connection, notify); |
|
3309 |
|
3310 connection->status = Connection::STATUS_ZOMBIE; |
|
3311 return OK; |
|
3312 } |
|
3313 |
|
3314 void InputDispatcher::removeMonitorChannelLocked(const sp<InputChannel>& inputChannel) { |
|
3315 for (size_t i = 0; i < mMonitoringChannels.size(); i++) { |
|
3316 if (mMonitoringChannels[i] == inputChannel) { |
|
3317 mMonitoringChannels.removeAt(i); |
|
3318 break; |
|
3319 } |
|
3320 } |
|
3321 } |
|
3322 |
|
3323 ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) { |
|
3324 ssize_t connectionIndex = mConnectionsByFd.indexOfKey(inputChannel->getFd()); |
|
3325 if (connectionIndex >= 0) { |
|
3326 sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex); |
|
3327 if (connection->inputChannel.get() == inputChannel.get()) { |
|
3328 return connectionIndex; |
|
3329 } |
|
3330 } |
|
3331 |
|
3332 return -1; |
|
3333 } |
|
3334 |
|
3335 void InputDispatcher::onDispatchCycleFinishedLocked( |
|
3336 nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled) { |
|
3337 CommandEntry* commandEntry = postCommandLocked( |
|
3338 & InputDispatcher::doDispatchCycleFinishedLockedInterruptible); |
|
3339 commandEntry->connection = connection; |
|
3340 commandEntry->eventTime = currentTime; |
|
3341 commandEntry->seq = seq; |
|
3342 commandEntry->handled = handled; |
|
3343 } |
|
3344 |
|
3345 void InputDispatcher::onDispatchCycleBrokenLocked( |
|
3346 nsecs_t currentTime, const sp<Connection>& connection) { |
|
3347 ALOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!", |
|
3348 connection->getInputChannelName()); |
|
3349 |
|
3350 CommandEntry* commandEntry = postCommandLocked( |
|
3351 & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible); |
|
3352 commandEntry->connection = connection; |
|
3353 } |
|
3354 |
|
3355 void InputDispatcher::onANRLocked( |
|
3356 nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle, |
|
3357 const sp<InputWindowHandle>& windowHandle, |
|
3358 nsecs_t eventTime, nsecs_t waitStartTime, const char* reason) { |
|
3359 float dispatchLatency = (currentTime - eventTime) * 0.000001f; |
|
3360 float waitDuration = (currentTime - waitStartTime) * 0.000001f; |
|
3361 ALOGI("Application is not responding: %s. " |
|
3362 "It has been %0.1fms since event, %0.1fms since wait started. Reason: %s", |
|
3363 getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(), |
|
3364 dispatchLatency, waitDuration, reason); |
|
3365 |
|
3366 // Capture a record of the InputDispatcher state at the time of the ANR. |
|
3367 time_t t = time(NULL); |
|
3368 struct tm tm; |
|
3369 localtime_r(&t, &tm); |
|
3370 char timestr[64]; |
|
3371 strftime(timestr, sizeof(timestr), "%F %T", &tm); |
|
3372 mLastANRState.clear(); |
|
3373 mLastANRState.append(INDENT "ANR:\n"); |
|
3374 mLastANRState.appendFormat(INDENT2 "Time: %s\n", timestr); |
|
3375 mLastANRState.appendFormat(INDENT2 "Window: %s\n", |
|
3376 getApplicationWindowLabelLocked(applicationHandle, windowHandle).string()); |
|
3377 mLastANRState.appendFormat(INDENT2 "DispatchLatency: %0.1fms\n", dispatchLatency); |
|
3378 mLastANRState.appendFormat(INDENT2 "WaitDuration: %0.1fms\n", waitDuration); |
|
3379 mLastANRState.appendFormat(INDENT2 "Reason: %s\n", reason); |
|
3380 dumpDispatchStateLocked(mLastANRState); |
|
3381 |
|
3382 CommandEntry* commandEntry = postCommandLocked( |
|
3383 & InputDispatcher::doNotifyANRLockedInterruptible); |
|
3384 commandEntry->inputApplicationHandle = applicationHandle; |
|
3385 commandEntry->inputWindowHandle = windowHandle; |
|
3386 } |
|
3387 |
|
3388 void InputDispatcher::doNotifyConfigurationChangedInterruptible( |
|
3389 CommandEntry* commandEntry) { |
|
3390 mLock.unlock(); |
|
3391 |
|
3392 mPolicy->notifyConfigurationChanged(commandEntry->eventTime); |
|
3393 |
|
3394 mLock.lock(); |
|
3395 } |
|
3396 |
|
3397 void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible( |
|
3398 CommandEntry* commandEntry) { |
|
3399 sp<Connection> connection = commandEntry->connection; |
|
3400 |
|
3401 if (connection->status != Connection::STATUS_ZOMBIE) { |
|
3402 mLock.unlock(); |
|
3403 |
|
3404 mPolicy->notifyInputChannelBroken(connection->inputWindowHandle); |
|
3405 |
|
3406 mLock.lock(); |
|
3407 } |
|
3408 } |
|
3409 |
|
3410 void InputDispatcher::doNotifyANRLockedInterruptible( |
|
3411 CommandEntry* commandEntry) { |
|
3412 mLock.unlock(); |
|
3413 |
|
3414 nsecs_t newTimeout = mPolicy->notifyANR( |
|
3415 commandEntry->inputApplicationHandle, commandEntry->inputWindowHandle); |
|
3416 |
|
3417 mLock.lock(); |
|
3418 |
|
3419 resumeAfterTargetsNotReadyTimeoutLocked(newTimeout, |
|
3420 commandEntry->inputWindowHandle != NULL |
|
3421 ? commandEntry->inputWindowHandle->getInputChannel() : NULL); |
|
3422 } |
|
3423 |
|
3424 void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible( |
|
3425 CommandEntry* commandEntry) { |
|
3426 KeyEntry* entry = commandEntry->keyEntry; |
|
3427 |
|
3428 KeyEvent event; |
|
3429 initializeKeyEvent(&event, entry); |
|
3430 |
|
3431 mLock.unlock(); |
|
3432 |
|
3433 nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle, |
|
3434 &event, entry->policyFlags); |
|
3435 |
|
3436 mLock.lock(); |
|
3437 |
|
3438 if (delay < 0) { |
|
3439 entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP; |
|
3440 } else if (!delay) { |
|
3441 entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE; |
|
3442 } else { |
|
3443 entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER; |
|
3444 entry->interceptKeyWakeupTime = now() + delay; |
|
3445 } |
|
3446 entry->release(); |
|
3447 } |
|
3448 |
|
3449 void InputDispatcher::doDispatchCycleFinishedLockedInterruptible( |
|
3450 CommandEntry* commandEntry) { |
|
3451 sp<Connection> connection = commandEntry->connection; |
|
3452 nsecs_t finishTime = commandEntry->eventTime; |
|
3453 uint32_t seq = commandEntry->seq; |
|
3454 bool handled = commandEntry->handled; |
|
3455 |
|
3456 // Handle post-event policy actions. |
|
3457 DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq); |
|
3458 if (dispatchEntry) { |
|
3459 nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime; |
|
3460 if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) { |
|
3461 String8 msg; |
|
3462 msg.appendFormat("Window '%s' spent %0.1fms processing the last input event: ", |
|
3463 connection->getWindowName(), eventDuration * 0.000001f); |
|
3464 dispatchEntry->eventEntry->appendDescription(msg); |
|
3465 ALOGI("%s", msg.string()); |
|
3466 } |
|
3467 |
|
3468 bool restartEvent; |
|
3469 if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) { |
|
3470 KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry); |
|
3471 restartEvent = afterKeyEventLockedInterruptible(connection, |
|
3472 dispatchEntry, keyEntry, handled); |
|
3473 } else if (dispatchEntry->eventEntry->type == EventEntry::TYPE_MOTION) { |
|
3474 MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry); |
|
3475 restartEvent = afterMotionEventLockedInterruptible(connection, |
|
3476 dispatchEntry, motionEntry, handled); |
|
3477 } else { |
|
3478 restartEvent = false; |
|
3479 } |
|
3480 |
|
3481 // Dequeue the event and start the next cycle. |
|
3482 // Note that because the lock might have been released, it is possible that the |
|
3483 // contents of the wait queue to have been drained, so we need to double-check |
|
3484 // a few things. |
|
3485 if (dispatchEntry == connection->findWaitQueueEntry(seq)) { |
|
3486 connection->waitQueue.dequeue(dispatchEntry); |
|
3487 traceWaitQueueLengthLocked(connection); |
|
3488 if (restartEvent && connection->status == Connection::STATUS_NORMAL) { |
|
3489 connection->outboundQueue.enqueueAtHead(dispatchEntry); |
|
3490 traceOutboundQueueLengthLocked(connection); |
|
3491 } else { |
|
3492 releaseDispatchEntryLocked(dispatchEntry); |
|
3493 } |
|
3494 } |
|
3495 |
|
3496 // Start the next dispatch cycle for this connection. |
|
3497 startDispatchCycleLocked(now(), connection); |
|
3498 } |
|
3499 } |
|
3500 |
|
3501 bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection, |
|
3502 DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled) { |
|
3503 if (!(keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK)) { |
|
3504 // Get the fallback key state. |
|
3505 // Clear it out after dispatching the UP. |
|
3506 int32_t originalKeyCode = keyEntry->keyCode; |
|
3507 int32_t fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode); |
|
3508 if (keyEntry->action == AKEY_EVENT_ACTION_UP) { |
|
3509 connection->inputState.removeFallbackKey(originalKeyCode); |
|
3510 } |
|
3511 |
|
3512 if (handled || !dispatchEntry->hasForegroundTarget()) { |
|
3513 // If the application handles the original key for which we previously |
|
3514 // generated a fallback or if the window is not a foreground window, |
|
3515 // then cancel the associated fallback key, if any. |
|
3516 if (fallbackKeyCode != -1) { |
|
3517 // Dispatch the unhandled key to the policy with the cancel flag. |
|
3518 #if DEBUG_OUTBOUND_EVENT_DETAILS |
|
3519 ALOGD("Unhandled key event: Asking policy to cancel fallback action. " |
|
3520 "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x", |
|
3521 keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount, |
|
3522 keyEntry->policyFlags); |
|
3523 #endif |
|
3524 KeyEvent event; |
|
3525 initializeKeyEvent(&event, keyEntry); |
|
3526 event.setFlags(event.getFlags() | AKEY_EVENT_FLAG_CANCELED); |
|
3527 |
|
3528 mLock.unlock(); |
|
3529 |
|
3530 mPolicy->dispatchUnhandledKey(connection->inputWindowHandle, |
|
3531 &event, keyEntry->policyFlags, &event); |
|
3532 |
|
3533 mLock.lock(); |
|
3534 |
|
3535 // Cancel the fallback key. |
|
3536 if (fallbackKeyCode != AKEYCODE_UNKNOWN) { |
|
3537 CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS, |
|
3538 "application handled the original non-fallback key " |
|
3539 "or is no longer a foreground target, " |
|
3540 "canceling previously dispatched fallback key"); |
|
3541 options.keyCode = fallbackKeyCode; |
|
3542 synthesizeCancelationEventsForConnectionLocked(connection, options); |
|
3543 } |
|
3544 connection->inputState.removeFallbackKey(originalKeyCode); |
|
3545 } |
|
3546 } else { |
|
3547 // If the application did not handle a non-fallback key, first check |
|
3548 // that we are in a good state to perform unhandled key event processing |
|
3549 // Then ask the policy what to do with it. |
|
3550 bool initialDown = keyEntry->action == AKEY_EVENT_ACTION_DOWN |
|
3551 && keyEntry->repeatCount == 0; |
|
3552 if (fallbackKeyCode == -1 && !initialDown) { |
|
3553 #if DEBUG_OUTBOUND_EVENT_DETAILS |
|
3554 ALOGD("Unhandled key event: Skipping unhandled key event processing " |
|
3555 "since this is not an initial down. " |
|
3556 "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x", |
|
3557 originalKeyCode, keyEntry->action, keyEntry->repeatCount, |
|
3558 keyEntry->policyFlags); |
|
3559 #endif |
|
3560 return false; |
|
3561 } |
|
3562 |
|
3563 // Dispatch the unhandled key to the policy. |
|
3564 #if DEBUG_OUTBOUND_EVENT_DETAILS |
|
3565 ALOGD("Unhandled key event: Asking policy to perform fallback action. " |
|
3566 "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x", |
|
3567 keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount, |
|
3568 keyEntry->policyFlags); |
|
3569 #endif |
|
3570 KeyEvent event; |
|
3571 initializeKeyEvent(&event, keyEntry); |
|
3572 |
|
3573 mLock.unlock(); |
|
3574 |
|
3575 bool fallback = mPolicy->dispatchUnhandledKey(connection->inputWindowHandle, |
|
3576 &event, keyEntry->policyFlags, &event); |
|
3577 |
|
3578 mLock.lock(); |
|
3579 |
|
3580 if (connection->status != Connection::STATUS_NORMAL) { |
|
3581 connection->inputState.removeFallbackKey(originalKeyCode); |
|
3582 return false; |
|
3583 } |
|
3584 |
|
3585 // Latch the fallback keycode for this key on an initial down. |
|
3586 // The fallback keycode cannot change at any other point in the lifecycle. |
|
3587 if (initialDown) { |
|
3588 if (fallback) { |
|
3589 fallbackKeyCode = event.getKeyCode(); |
|
3590 } else { |
|
3591 fallbackKeyCode = AKEYCODE_UNKNOWN; |
|
3592 } |
|
3593 connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode); |
|
3594 } |
|
3595 |
|
3596 ALOG_ASSERT(fallbackKeyCode != -1); |
|
3597 |
|
3598 // Cancel the fallback key if the policy decides not to send it anymore. |
|
3599 // We will continue to dispatch the key to the policy but we will no |
|
3600 // longer dispatch a fallback key to the application. |
|
3601 if (fallbackKeyCode != AKEYCODE_UNKNOWN |
|
3602 && (!fallback || fallbackKeyCode != event.getKeyCode())) { |
|
3603 #if DEBUG_OUTBOUND_EVENT_DETAILS |
|
3604 if (fallback) { |
|
3605 ALOGD("Unhandled key event: Policy requested to send key %d" |
|
3606 "as a fallback for %d, but on the DOWN it had requested " |
|
3607 "to send %d instead. Fallback canceled.", |
|
3608 event.getKeyCode(), originalKeyCode, fallbackKeyCode); |
|
3609 } else { |
|
3610 ALOGD("Unhandled key event: Policy did not request fallback for %d, " |
|
3611 "but on the DOWN it had requested to send %d. " |
|
3612 "Fallback canceled.", |
|
3613 originalKeyCode, fallbackKeyCode); |
|
3614 } |
|
3615 #endif |
|
3616 |
|
3617 CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS, |
|
3618 "canceling fallback, policy no longer desires it"); |
|
3619 options.keyCode = fallbackKeyCode; |
|
3620 synthesizeCancelationEventsForConnectionLocked(connection, options); |
|
3621 |
|
3622 fallback = false; |
|
3623 fallbackKeyCode = AKEYCODE_UNKNOWN; |
|
3624 if (keyEntry->action != AKEY_EVENT_ACTION_UP) { |
|
3625 connection->inputState.setFallbackKey(originalKeyCode, |
|
3626 fallbackKeyCode); |
|
3627 } |
|
3628 } |
|
3629 |
|
3630 #if DEBUG_OUTBOUND_EVENT_DETAILS |
|
3631 { |
|
3632 String8 msg; |
|
3633 const KeyedVector<int32_t, int32_t>& fallbackKeys = |
|
3634 connection->inputState.getFallbackKeys(); |
|
3635 for (size_t i = 0; i < fallbackKeys.size(); i++) { |
|
3636 msg.appendFormat(", %d->%d", fallbackKeys.keyAt(i), |
|
3637 fallbackKeys.valueAt(i)); |
|
3638 } |
|
3639 ALOGD("Unhandled key event: %d currently tracked fallback keys%s.", |
|
3640 fallbackKeys.size(), msg.string()); |
|
3641 } |
|
3642 #endif |
|
3643 |
|
3644 if (fallback) { |
|
3645 // Restart the dispatch cycle using the fallback key. |
|
3646 keyEntry->eventTime = event.getEventTime(); |
|
3647 keyEntry->deviceId = event.getDeviceId(); |
|
3648 keyEntry->source = event.getSource(); |
|
3649 keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK; |
|
3650 keyEntry->keyCode = fallbackKeyCode; |
|
3651 keyEntry->scanCode = event.getScanCode(); |
|
3652 keyEntry->metaState = event.getMetaState(); |
|
3653 keyEntry->repeatCount = event.getRepeatCount(); |
|
3654 keyEntry->downTime = event.getDownTime(); |
|
3655 keyEntry->syntheticRepeat = false; |
|
3656 |
|
3657 #if DEBUG_OUTBOUND_EVENT_DETAILS |
|
3658 ALOGD("Unhandled key event: Dispatching fallback key. " |
|
3659 "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x", |
|
3660 originalKeyCode, fallbackKeyCode, keyEntry->metaState); |
|
3661 #endif |
|
3662 return true; // restart the event |
|
3663 } else { |
|
3664 #if DEBUG_OUTBOUND_EVENT_DETAILS |
|
3665 ALOGD("Unhandled key event: No fallback key."); |
|
3666 #endif |
|
3667 } |
|
3668 } |
|
3669 } |
|
3670 return false; |
|
3671 } |
|
3672 |
|
3673 bool InputDispatcher::afterMotionEventLockedInterruptible(const sp<Connection>& connection, |
|
3674 DispatchEntry* dispatchEntry, MotionEntry* motionEntry, bool handled) { |
|
3675 return false; |
|
3676 } |
|
3677 |
|
3678 void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) { |
|
3679 mLock.unlock(); |
|
3680 |
|
3681 mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType); |
|
3682 |
|
3683 mLock.lock(); |
|
3684 } |
|
3685 |
|
3686 void InputDispatcher::initializeKeyEvent(KeyEvent* event, const KeyEntry* entry) { |
|
3687 event->initialize(entry->deviceId, entry->source, entry->action, entry->flags, |
|
3688 entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount, |
|
3689 entry->downTime, entry->eventTime); |
|
3690 } |
|
3691 |
|
3692 void InputDispatcher::updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry, |
|
3693 int32_t injectionResult, nsecs_t timeSpentWaitingForApplication) { |
|
3694 // TODO Write some statistics about how long we spend waiting. |
|
3695 } |
|
3696 |
|
3697 void InputDispatcher::traceInboundQueueLengthLocked() { |
|
3698 #ifdef HAVE_ANDROID_OS |
|
3699 if (ATRACE_ENABLED()) { |
|
3700 ATRACE_INT("iq", mInboundQueue.count()); |
|
3701 } |
|
3702 #endif |
|
3703 } |
|
3704 |
|
3705 void InputDispatcher::traceOutboundQueueLengthLocked(const sp<Connection>& connection) { |
|
3706 #ifdef HAVE_ANDROID_OS |
|
3707 if (ATRACE_ENABLED()) { |
|
3708 char counterName[40]; |
|
3709 snprintf(counterName, sizeof(counterName), "oq:%s", connection->getWindowName()); |
|
3710 ATRACE_INT(counterName, connection->outboundQueue.count()); |
|
3711 } |
|
3712 #endif |
|
3713 } |
|
3714 |
|
3715 void InputDispatcher::traceWaitQueueLengthLocked(const sp<Connection>& connection) { |
|
3716 #ifdef HAVE_ANDROID_OS |
|
3717 if (ATRACE_ENABLED()) { |
|
3718 char counterName[40]; |
|
3719 snprintf(counterName, sizeof(counterName), "wq:%s", connection->getWindowName()); |
|
3720 ATRACE_INT(counterName, connection->waitQueue.count()); |
|
3721 } |
|
3722 #endif |
|
3723 } |
|
3724 |
|
3725 void InputDispatcher::dump(String8& dump) { |
|
3726 AutoMutex _l(mLock); |
|
3727 |
|
3728 dump.append("Input Dispatcher State:\n"); |
|
3729 dumpDispatchStateLocked(dump); |
|
3730 |
|
3731 if (!mLastANRState.isEmpty()) { |
|
3732 dump.append("\nInput Dispatcher State at time of last ANR:\n"); |
|
3733 dump.append(mLastANRState); |
|
3734 } |
|
3735 } |
|
3736 |
|
3737 void InputDispatcher::monitor() { |
|
3738 // Acquire and release the lock to ensure that the dispatcher has not deadlocked. |
|
3739 mLock.lock(); |
|
3740 mLooper->wake(); |
|
3741 mDispatcherIsAliveCondition.wait(mLock); |
|
3742 mLock.unlock(); |
|
3743 } |
|
3744 |
|
3745 |
|
3746 // --- InputDispatcher::Queue --- |
|
3747 |
|
3748 template <typename T> |
|
3749 uint32_t InputDispatcher::Queue<T>::count() const { |
|
3750 uint32_t result = 0; |
|
3751 for (const T* entry = head; entry; entry = entry->next) { |
|
3752 result += 1; |
|
3753 } |
|
3754 return result; |
|
3755 } |
|
3756 |
|
3757 |
|
3758 // --- InputDispatcher::InjectionState --- |
|
3759 |
|
3760 InputDispatcher::InjectionState::InjectionState(int32_t injectorPid, int32_t injectorUid) : |
|
3761 refCount(1), |
|
3762 injectorPid(injectorPid), injectorUid(injectorUid), |
|
3763 injectionResult(INPUT_EVENT_INJECTION_PENDING), injectionIsAsync(false), |
|
3764 pendingForegroundDispatches(0) { |
|
3765 } |
|
3766 |
|
3767 InputDispatcher::InjectionState::~InjectionState() { |
|
3768 } |
|
3769 |
|
3770 void InputDispatcher::InjectionState::release() { |
|
3771 refCount -= 1; |
|
3772 if (refCount == 0) { |
|
3773 delete this; |
|
3774 } else { |
|
3775 ALOG_ASSERT(refCount > 0); |
|
3776 } |
|
3777 } |
|
3778 |
|
3779 |
|
3780 // --- InputDispatcher::EventEntry --- |
|
3781 |
|
3782 InputDispatcher::EventEntry::EventEntry(int32_t type, nsecs_t eventTime, uint32_t policyFlags) : |
|
3783 refCount(1), type(type), eventTime(eventTime), policyFlags(policyFlags), |
|
3784 injectionState(NULL), dispatchInProgress(false) { |
|
3785 } |
|
3786 |
|
3787 InputDispatcher::EventEntry::~EventEntry() { |
|
3788 releaseInjectionState(); |
|
3789 } |
|
3790 |
|
3791 void InputDispatcher::EventEntry::release() { |
|
3792 refCount -= 1; |
|
3793 if (refCount == 0) { |
|
3794 delete this; |
|
3795 } else { |
|
3796 ALOG_ASSERT(refCount > 0); |
|
3797 } |
|
3798 } |
|
3799 |
|
3800 void InputDispatcher::EventEntry::releaseInjectionState() { |
|
3801 if (injectionState) { |
|
3802 injectionState->release(); |
|
3803 injectionState = NULL; |
|
3804 } |
|
3805 } |
|
3806 |
|
3807 |
|
3808 // --- InputDispatcher::ConfigurationChangedEntry --- |
|
3809 |
|
3810 InputDispatcher::ConfigurationChangedEntry::ConfigurationChangedEntry(nsecs_t eventTime) : |
|
3811 EventEntry(TYPE_CONFIGURATION_CHANGED, eventTime, 0) { |
|
3812 } |
|
3813 |
|
3814 InputDispatcher::ConfigurationChangedEntry::~ConfigurationChangedEntry() { |
|
3815 } |
|
3816 |
|
3817 void InputDispatcher::ConfigurationChangedEntry::appendDescription(String8& msg) const { |
|
3818 msg.append("ConfigurationChangedEvent()"); |
|
3819 } |
|
3820 |
|
3821 |
|
3822 // --- InputDispatcher::DeviceResetEntry --- |
|
3823 |
|
3824 InputDispatcher::DeviceResetEntry::DeviceResetEntry(nsecs_t eventTime, int32_t deviceId) : |
|
3825 EventEntry(TYPE_DEVICE_RESET, eventTime, 0), |
|
3826 deviceId(deviceId) { |
|
3827 } |
|
3828 |
|
3829 InputDispatcher::DeviceResetEntry::~DeviceResetEntry() { |
|
3830 } |
|
3831 |
|
3832 void InputDispatcher::DeviceResetEntry::appendDescription(String8& msg) const { |
|
3833 msg.appendFormat("DeviceResetEvent(deviceId=%d)", deviceId); |
|
3834 } |
|
3835 |
|
3836 |
|
3837 // --- InputDispatcher::KeyEntry --- |
|
3838 |
|
3839 InputDispatcher::KeyEntry::KeyEntry(nsecs_t eventTime, |
|
3840 int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, |
|
3841 int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState, |
|
3842 int32_t repeatCount, nsecs_t downTime) : |
|
3843 EventEntry(TYPE_KEY, eventTime, policyFlags), |
|
3844 deviceId(deviceId), source(source), action(action), flags(flags), |
|
3845 keyCode(keyCode), scanCode(scanCode), metaState(metaState), |
|
3846 repeatCount(repeatCount), downTime(downTime), |
|
3847 syntheticRepeat(false), interceptKeyResult(KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN), |
|
3848 interceptKeyWakeupTime(0) { |
|
3849 } |
|
3850 |
|
3851 InputDispatcher::KeyEntry::~KeyEntry() { |
|
3852 } |
|
3853 |
|
3854 void InputDispatcher::KeyEntry::appendDescription(String8& msg) const { |
|
3855 msg.appendFormat("KeyEvent(action=%d, deviceId=%d, source=0x%08x)", |
|
3856 action, deviceId, source); |
|
3857 } |
|
3858 |
|
3859 void InputDispatcher::KeyEntry::recycle() { |
|
3860 releaseInjectionState(); |
|
3861 |
|
3862 dispatchInProgress = false; |
|
3863 syntheticRepeat = false; |
|
3864 interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN; |
|
3865 interceptKeyWakeupTime = 0; |
|
3866 } |
|
3867 |
|
3868 |
|
3869 // --- InputDispatcher::MotionEntry --- |
|
3870 |
|
3871 InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime, |
|
3872 int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags, |
|
3873 int32_t metaState, int32_t buttonState, |
|
3874 int32_t edgeFlags, float xPrecision, float yPrecision, |
|
3875 nsecs_t downTime, int32_t displayId, uint32_t pointerCount, |
|
3876 const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) : |
|
3877 EventEntry(TYPE_MOTION, eventTime, policyFlags), |
|
3878 eventTime(eventTime), |
|
3879 deviceId(deviceId), source(source), action(action), flags(flags), |
|
3880 metaState(metaState), buttonState(buttonState), edgeFlags(edgeFlags), |
|
3881 xPrecision(xPrecision), yPrecision(yPrecision), |
|
3882 downTime(downTime), displayId(displayId), pointerCount(pointerCount) { |
|
3883 for (uint32_t i = 0; i < pointerCount; i++) { |
|
3884 this->pointerProperties[i].copyFrom(pointerProperties[i]); |
|
3885 this->pointerCoords[i].copyFrom(pointerCoords[i]); |
|
3886 } |
|
3887 } |
|
3888 |
|
3889 InputDispatcher::MotionEntry::~MotionEntry() { |
|
3890 } |
|
3891 |
|
3892 void InputDispatcher::MotionEntry::appendDescription(String8& msg) const { |
|
3893 msg.appendFormat("MotionEvent(action=%d, deviceId=%d, source=0x%08x, displayId=%d)", |
|
3894 action, deviceId, source, displayId); |
|
3895 } |
|
3896 |
|
3897 |
|
3898 // --- InputDispatcher::DispatchEntry --- |
|
3899 |
|
3900 volatile int32_t InputDispatcher::DispatchEntry::sNextSeqAtomic; |
|
3901 |
|
3902 InputDispatcher::DispatchEntry::DispatchEntry(EventEntry* eventEntry, |
|
3903 int32_t targetFlags, float xOffset, float yOffset, float scaleFactor) : |
|
3904 seq(nextSeq()), |
|
3905 eventEntry(eventEntry), targetFlags(targetFlags), |
|
3906 xOffset(xOffset), yOffset(yOffset), scaleFactor(scaleFactor), |
|
3907 deliveryTime(0), resolvedAction(0), resolvedFlags(0) { |
|
3908 eventEntry->refCount += 1; |
|
3909 } |
|
3910 |
|
3911 InputDispatcher::DispatchEntry::~DispatchEntry() { |
|
3912 eventEntry->release(); |
|
3913 } |
|
3914 |
|
3915 uint32_t InputDispatcher::DispatchEntry::nextSeq() { |
|
3916 // Sequence number 0 is reserved and will never be returned. |
|
3917 uint32_t seq; |
|
3918 do { |
|
3919 seq = android_atomic_inc(&sNextSeqAtomic); |
|
3920 } while (!seq); |
|
3921 return seq; |
|
3922 } |
|
3923 |
|
3924 |
|
3925 // --- InputDispatcher::InputState --- |
|
3926 |
|
3927 InputDispatcher::InputState::InputState() { |
|
3928 } |
|
3929 |
|
3930 InputDispatcher::InputState::~InputState() { |
|
3931 } |
|
3932 |
|
3933 bool InputDispatcher::InputState::isNeutral() const { |
|
3934 return mKeyMementos.isEmpty() && mMotionMementos.isEmpty(); |
|
3935 } |
|
3936 |
|
3937 bool InputDispatcher::InputState::isHovering(int32_t deviceId, uint32_t source, |
|
3938 int32_t displayId) const { |
|
3939 for (size_t i = 0; i < mMotionMementos.size(); i++) { |
|
3940 const MotionMemento& memento = mMotionMementos.itemAt(i); |
|
3941 if (memento.deviceId == deviceId |
|
3942 && memento.source == source |
|
3943 && memento.displayId == displayId |
|
3944 && memento.hovering) { |
|
3945 return true; |
|
3946 } |
|
3947 } |
|
3948 return false; |
|
3949 } |
|
3950 |
|
3951 bool InputDispatcher::InputState::trackKey(const KeyEntry* entry, |
|
3952 int32_t action, int32_t flags) { |
|
3953 switch (action) { |
|
3954 case AKEY_EVENT_ACTION_UP: { |
|
3955 if (entry->flags & AKEY_EVENT_FLAG_FALLBACK) { |
|
3956 for (size_t i = 0; i < mFallbackKeys.size(); ) { |
|
3957 if (mFallbackKeys.valueAt(i) == entry->keyCode) { |
|
3958 mFallbackKeys.removeItemsAt(i); |
|
3959 } else { |
|
3960 i += 1; |
|
3961 } |
|
3962 } |
|
3963 } |
|
3964 ssize_t index = findKeyMemento(entry); |
|
3965 if (index >= 0) { |
|
3966 mKeyMementos.removeAt(index); |
|
3967 return true; |
|
3968 } |
|
3969 /* FIXME: We can't just drop the key up event because that prevents creating |
|
3970 * popup windows that are automatically shown when a key is held and then |
|
3971 * dismissed when the key is released. The problem is that the popup will |
|
3972 * not have received the original key down, so the key up will be considered |
|
3973 * to be inconsistent with its observed state. We could perhaps handle this |
|
3974 * by synthesizing a key down but that will cause other problems. |
|
3975 * |
|
3976 * So for now, allow inconsistent key up events to be dispatched. |
|
3977 * |
|
3978 #if DEBUG_OUTBOUND_EVENT_DETAILS |
|
3979 ALOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, " |
|
3980 "keyCode=%d, scanCode=%d", |
|
3981 entry->deviceId, entry->source, entry->keyCode, entry->scanCode); |
|
3982 #endif |
|
3983 return false; |
|
3984 */ |
|
3985 return true; |
|
3986 } |
|
3987 |
|
3988 case AKEY_EVENT_ACTION_DOWN: { |
|
3989 ssize_t index = findKeyMemento(entry); |
|
3990 if (index >= 0) { |
|
3991 mKeyMementos.removeAt(index); |
|
3992 } |
|
3993 addKeyMemento(entry, flags); |
|
3994 return true; |
|
3995 } |
|
3996 |
|
3997 default: |
|
3998 return true; |
|
3999 } |
|
4000 } |
|
4001 |
|
4002 bool InputDispatcher::InputState::trackMotion(const MotionEntry* entry, |
|
4003 int32_t action, int32_t flags) { |
|
4004 int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK; |
|
4005 switch (actionMasked) { |
|
4006 case AMOTION_EVENT_ACTION_UP: |
|
4007 case AMOTION_EVENT_ACTION_CANCEL: { |
|
4008 ssize_t index = findMotionMemento(entry, false /*hovering*/); |
|
4009 if (index >= 0) { |
|
4010 mMotionMementos.removeAt(index); |
|
4011 return true; |
|
4012 } |
|
4013 #if DEBUG_OUTBOUND_EVENT_DETAILS |
|
4014 ALOGD("Dropping inconsistent motion up or cancel event: deviceId=%d, source=%08x, " |
|
4015 "actionMasked=%d", |
|
4016 entry->deviceId, entry->source, actionMasked); |
|
4017 #endif |
|
4018 return false; |
|
4019 } |
|
4020 |
|
4021 case AMOTION_EVENT_ACTION_DOWN: { |
|
4022 ssize_t index = findMotionMemento(entry, false /*hovering*/); |
|
4023 if (index >= 0) { |
|
4024 mMotionMementos.removeAt(index); |
|
4025 } |
|
4026 addMotionMemento(entry, flags, false /*hovering*/); |
|
4027 return true; |
|
4028 } |
|
4029 |
|
4030 case AMOTION_EVENT_ACTION_POINTER_UP: |
|
4031 case AMOTION_EVENT_ACTION_POINTER_DOWN: |
|
4032 case AMOTION_EVENT_ACTION_MOVE: { |
|
4033 ssize_t index = findMotionMemento(entry, false /*hovering*/); |
|
4034 if (index >= 0) { |
|
4035 MotionMemento& memento = mMotionMementos.editItemAt(index); |
|
4036 memento.setPointers(entry); |
|
4037 return true; |
|
4038 } |
|
4039 if (actionMasked == AMOTION_EVENT_ACTION_MOVE |
|
4040 && (entry->source & (AINPUT_SOURCE_CLASS_JOYSTICK |
|
4041 | AINPUT_SOURCE_CLASS_NAVIGATION))) { |
|
4042 // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP. |
|
4043 return true; |
|
4044 } |
|
4045 #if DEBUG_OUTBOUND_EVENT_DETAILS |
|
4046 ALOGD("Dropping inconsistent motion pointer up/down or move event: " |
|
4047 "deviceId=%d, source=%08x, actionMasked=%d", |
|
4048 entry->deviceId, entry->source, actionMasked); |
|
4049 #endif |
|
4050 return false; |
|
4051 } |
|
4052 |
|
4053 case AMOTION_EVENT_ACTION_HOVER_EXIT: { |
|
4054 ssize_t index = findMotionMemento(entry, true /*hovering*/); |
|
4055 if (index >= 0) { |
|
4056 mMotionMementos.removeAt(index); |
|
4057 return true; |
|
4058 } |
|
4059 #if DEBUG_OUTBOUND_EVENT_DETAILS |
|
4060 ALOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x", |
|
4061 entry->deviceId, entry->source); |
|
4062 #endif |
|
4063 return false; |
|
4064 } |
|
4065 |
|
4066 case AMOTION_EVENT_ACTION_HOVER_ENTER: |
|
4067 case AMOTION_EVENT_ACTION_HOVER_MOVE: { |
|
4068 ssize_t index = findMotionMemento(entry, true /*hovering*/); |
|
4069 if (index >= 0) { |
|
4070 mMotionMementos.removeAt(index); |
|
4071 } |
|
4072 addMotionMemento(entry, flags, true /*hovering*/); |
|
4073 return true; |
|
4074 } |
|
4075 |
|
4076 default: |
|
4077 return true; |
|
4078 } |
|
4079 } |
|
4080 |
|
4081 ssize_t InputDispatcher::InputState::findKeyMemento(const KeyEntry* entry) const { |
|
4082 for (size_t i = 0; i < mKeyMementos.size(); i++) { |
|
4083 const KeyMemento& memento = mKeyMementos.itemAt(i); |
|
4084 if (memento.deviceId == entry->deviceId |
|
4085 && memento.source == entry->source |
|
4086 && memento.keyCode == entry->keyCode |
|
4087 && memento.scanCode == entry->scanCode) { |
|
4088 return i; |
|
4089 } |
|
4090 } |
|
4091 return -1; |
|
4092 } |
|
4093 |
|
4094 ssize_t InputDispatcher::InputState::findMotionMemento(const MotionEntry* entry, |
|
4095 bool hovering) const { |
|
4096 for (size_t i = 0; i < mMotionMementos.size(); i++) { |
|
4097 const MotionMemento& memento = mMotionMementos.itemAt(i); |
|
4098 if (memento.deviceId == entry->deviceId |
|
4099 && memento.source == entry->source |
|
4100 && memento.displayId == entry->displayId |
|
4101 && memento.hovering == hovering) { |
|
4102 return i; |
|
4103 } |
|
4104 } |
|
4105 return -1; |
|
4106 } |
|
4107 |
|
4108 void InputDispatcher::InputState::addKeyMemento(const KeyEntry* entry, int32_t flags) { |
|
4109 mKeyMementos.push(); |
|
4110 KeyMemento& memento = mKeyMementos.editTop(); |
|
4111 memento.deviceId = entry->deviceId; |
|
4112 memento.source = entry->source; |
|
4113 memento.keyCode = entry->keyCode; |
|
4114 memento.scanCode = entry->scanCode; |
|
4115 memento.metaState = entry->metaState; |
|
4116 memento.flags = flags; |
|
4117 memento.downTime = entry->downTime; |
|
4118 memento.policyFlags = entry->policyFlags; |
|
4119 } |
|
4120 |
|
4121 void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry, |
|
4122 int32_t flags, bool hovering) { |
|
4123 mMotionMementos.push(); |
|
4124 MotionMemento& memento = mMotionMementos.editTop(); |
|
4125 memento.deviceId = entry->deviceId; |
|
4126 memento.source = entry->source; |
|
4127 memento.flags = flags; |
|
4128 memento.xPrecision = entry->xPrecision; |
|
4129 memento.yPrecision = entry->yPrecision; |
|
4130 memento.downTime = entry->downTime; |
|
4131 memento.displayId = entry->displayId; |
|
4132 memento.setPointers(entry); |
|
4133 memento.hovering = hovering; |
|
4134 memento.policyFlags = entry->policyFlags; |
|
4135 } |
|
4136 |
|
4137 void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) { |
|
4138 pointerCount = entry->pointerCount; |
|
4139 for (uint32_t i = 0; i < entry->pointerCount; i++) { |
|
4140 pointerProperties[i].copyFrom(entry->pointerProperties[i]); |
|
4141 pointerCoords[i].copyFrom(entry->pointerCoords[i]); |
|
4142 } |
|
4143 } |
|
4144 |
|
4145 void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime, |
|
4146 Vector<EventEntry*>& outEvents, const CancelationOptions& options) { |
|
4147 for (size_t i = 0; i < mKeyMementos.size(); i++) { |
|
4148 const KeyMemento& memento = mKeyMementos.itemAt(i); |
|
4149 if (shouldCancelKey(memento, options)) { |
|
4150 outEvents.push(new KeyEntry(currentTime, |
|
4151 memento.deviceId, memento.source, memento.policyFlags, |
|
4152 AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED, |
|
4153 memento.keyCode, memento.scanCode, memento.metaState, 0, memento.downTime)); |
|
4154 } |
|
4155 } |
|
4156 |
|
4157 for (size_t i = 0; i < mMotionMementos.size(); i++) { |
|
4158 const MotionMemento& memento = mMotionMementos.itemAt(i); |
|
4159 if (shouldCancelMotion(memento, options)) { |
|
4160 outEvents.push(new MotionEntry(currentTime, |
|
4161 memento.deviceId, memento.source, memento.policyFlags, |
|
4162 memento.hovering |
|
4163 ? AMOTION_EVENT_ACTION_HOVER_EXIT |
|
4164 : AMOTION_EVENT_ACTION_CANCEL, |
|
4165 memento.flags, 0, 0, 0, |
|
4166 memento.xPrecision, memento.yPrecision, memento.downTime, |
|
4167 memento.displayId, |
|
4168 memento.pointerCount, memento.pointerProperties, memento.pointerCoords)); |
|
4169 } |
|
4170 } |
|
4171 } |
|
4172 |
|
4173 void InputDispatcher::InputState::clear() { |
|
4174 mKeyMementos.clear(); |
|
4175 mMotionMementos.clear(); |
|
4176 mFallbackKeys.clear(); |
|
4177 } |
|
4178 |
|
4179 void InputDispatcher::InputState::copyPointerStateTo(InputState& other) const { |
|
4180 for (size_t i = 0; i < mMotionMementos.size(); i++) { |
|
4181 const MotionMemento& memento = mMotionMementos.itemAt(i); |
|
4182 if (memento.source & AINPUT_SOURCE_CLASS_POINTER) { |
|
4183 for (size_t j = 0; j < other.mMotionMementos.size(); ) { |
|
4184 const MotionMemento& otherMemento = other.mMotionMementos.itemAt(j); |
|
4185 if (memento.deviceId == otherMemento.deviceId |
|
4186 && memento.source == otherMemento.source |
|
4187 && memento.displayId == otherMemento.displayId) { |
|
4188 other.mMotionMementos.removeAt(j); |
|
4189 } else { |
|
4190 j += 1; |
|
4191 } |
|
4192 } |
|
4193 other.mMotionMementos.push(memento); |
|
4194 } |
|
4195 } |
|
4196 } |
|
4197 |
|
4198 int32_t InputDispatcher::InputState::getFallbackKey(int32_t originalKeyCode) { |
|
4199 ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode); |
|
4200 return index >= 0 ? mFallbackKeys.valueAt(index) : -1; |
|
4201 } |
|
4202 |
|
4203 void InputDispatcher::InputState::setFallbackKey(int32_t originalKeyCode, |
|
4204 int32_t fallbackKeyCode) { |
|
4205 ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode); |
|
4206 if (index >= 0) { |
|
4207 mFallbackKeys.replaceValueAt(index, fallbackKeyCode); |
|
4208 } else { |
|
4209 mFallbackKeys.add(originalKeyCode, fallbackKeyCode); |
|
4210 } |
|
4211 } |
|
4212 |
|
4213 void InputDispatcher::InputState::removeFallbackKey(int32_t originalKeyCode) { |
|
4214 mFallbackKeys.removeItem(originalKeyCode); |
|
4215 } |
|
4216 |
|
4217 bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento, |
|
4218 const CancelationOptions& options) { |
|
4219 if (options.keyCode != -1 && memento.keyCode != options.keyCode) { |
|
4220 return false; |
|
4221 } |
|
4222 |
|
4223 if (options.deviceId != -1 && memento.deviceId != options.deviceId) { |
|
4224 return false; |
|
4225 } |
|
4226 |
|
4227 switch (options.mode) { |
|
4228 case CancelationOptions::CANCEL_ALL_EVENTS: |
|
4229 case CancelationOptions::CANCEL_NON_POINTER_EVENTS: |
|
4230 return true; |
|
4231 case CancelationOptions::CANCEL_FALLBACK_EVENTS: |
|
4232 return memento.flags & AKEY_EVENT_FLAG_FALLBACK; |
|
4233 default: |
|
4234 return false; |
|
4235 } |
|
4236 } |
|
4237 |
|
4238 bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& memento, |
|
4239 const CancelationOptions& options) { |
|
4240 if (options.deviceId != -1 && memento.deviceId != options.deviceId) { |
|
4241 return false; |
|
4242 } |
|
4243 |
|
4244 switch (options.mode) { |
|
4245 case CancelationOptions::CANCEL_ALL_EVENTS: |
|
4246 return true; |
|
4247 case CancelationOptions::CANCEL_POINTER_EVENTS: |
|
4248 return memento.source & AINPUT_SOURCE_CLASS_POINTER; |
|
4249 case CancelationOptions::CANCEL_NON_POINTER_EVENTS: |
|
4250 return !(memento.source & AINPUT_SOURCE_CLASS_POINTER); |
|
4251 default: |
|
4252 return false; |
|
4253 } |
|
4254 } |
|
4255 |
|
4256 |
|
4257 // --- InputDispatcher::Connection --- |
|
4258 |
|
4259 InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel, |
|
4260 const sp<InputWindowHandle>& inputWindowHandle, bool monitor) : |
|
4261 status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle), |
|
4262 monitor(monitor), |
|
4263 inputPublisher(inputChannel), inputPublisherBlocked(false) { |
|
4264 } |
|
4265 |
|
4266 InputDispatcher::Connection::~Connection() { |
|
4267 } |
|
4268 |
|
4269 const char* InputDispatcher::Connection::getWindowName() const { |
|
4270 if (inputWindowHandle != NULL) { |
|
4271 return inputWindowHandle->getName().string(); |
|
4272 } |
|
4273 if (monitor) { |
|
4274 return "monitor"; |
|
4275 } |
|
4276 return "?"; |
|
4277 } |
|
4278 |
|
4279 const char* InputDispatcher::Connection::getStatusLabel() const { |
|
4280 switch (status) { |
|
4281 case STATUS_NORMAL: |
|
4282 return "NORMAL"; |
|
4283 |
|
4284 case STATUS_BROKEN: |
|
4285 return "BROKEN"; |
|
4286 |
|
4287 case STATUS_ZOMBIE: |
|
4288 return "ZOMBIE"; |
|
4289 |
|
4290 default: |
|
4291 return "UNKNOWN"; |
|
4292 } |
|
4293 } |
|
4294 |
|
4295 InputDispatcher::DispatchEntry* InputDispatcher::Connection::findWaitQueueEntry(uint32_t seq) { |
|
4296 for (DispatchEntry* entry = waitQueue.head; entry != NULL; entry = entry->next) { |
|
4297 if (entry->seq == seq) { |
|
4298 return entry; |
|
4299 } |
|
4300 } |
|
4301 return NULL; |
|
4302 } |
|
4303 |
|
4304 |
|
4305 // --- InputDispatcher::CommandEntry --- |
|
4306 |
|
4307 InputDispatcher::CommandEntry::CommandEntry(Command command) : |
|
4308 command(command), eventTime(0), keyEntry(NULL), userActivityEventType(0), |
|
4309 seq(0), handled(false) { |
|
4310 } |
|
4311 |
|
4312 InputDispatcher::CommandEntry::~CommandEntry() { |
|
4313 } |
|
4314 |
|
4315 |
|
4316 // --- InputDispatcher::TouchState --- |
|
4317 |
|
4318 InputDispatcher::TouchState::TouchState() : |
|
4319 down(false), split(false), deviceId(-1), source(0), displayId(-1) { |
|
4320 } |
|
4321 |
|
4322 InputDispatcher::TouchState::~TouchState() { |
|
4323 } |
|
4324 |
|
4325 void InputDispatcher::TouchState::reset() { |
|
4326 down = false; |
|
4327 split = false; |
|
4328 deviceId = -1; |
|
4329 source = 0; |
|
4330 displayId = -1; |
|
4331 windows.clear(); |
|
4332 } |
|
4333 |
|
4334 void InputDispatcher::TouchState::copyFrom(const TouchState& other) { |
|
4335 down = other.down; |
|
4336 split = other.split; |
|
4337 deviceId = other.deviceId; |
|
4338 source = other.source; |
|
4339 displayId = other.displayId; |
|
4340 windows = other.windows; |
|
4341 } |
|
4342 |
|
4343 void InputDispatcher::TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle, |
|
4344 int32_t targetFlags, BitSet32 pointerIds) { |
|
4345 if (targetFlags & InputTarget::FLAG_SPLIT) { |
|
4346 split = true; |
|
4347 } |
|
4348 |
|
4349 for (size_t i = 0; i < windows.size(); i++) { |
|
4350 TouchedWindow& touchedWindow = windows.editItemAt(i); |
|
4351 if (touchedWindow.windowHandle == windowHandle) { |
|
4352 touchedWindow.targetFlags |= targetFlags; |
|
4353 if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) { |
|
4354 touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS; |
|
4355 } |
|
4356 touchedWindow.pointerIds.value |= pointerIds.value; |
|
4357 return; |
|
4358 } |
|
4359 } |
|
4360 |
|
4361 windows.push(); |
|
4362 |
|
4363 TouchedWindow& touchedWindow = windows.editTop(); |
|
4364 touchedWindow.windowHandle = windowHandle; |
|
4365 touchedWindow.targetFlags = targetFlags; |
|
4366 touchedWindow.pointerIds = pointerIds; |
|
4367 } |
|
4368 |
|
4369 void InputDispatcher::TouchState::removeWindow(const sp<InputWindowHandle>& windowHandle) { |
|
4370 for (size_t i = 0; i < windows.size(); i++) { |
|
4371 if (windows.itemAt(i).windowHandle == windowHandle) { |
|
4372 windows.removeAt(i); |
|
4373 return; |
|
4374 } |
|
4375 } |
|
4376 } |
|
4377 |
|
4378 void InputDispatcher::TouchState::filterNonAsIsTouchWindows() { |
|
4379 for (size_t i = 0 ; i < windows.size(); ) { |
|
4380 TouchedWindow& window = windows.editItemAt(i); |
|
4381 if (window.targetFlags & (InputTarget::FLAG_DISPATCH_AS_IS |
|
4382 | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) { |
|
4383 window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK; |
|
4384 window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS; |
|
4385 i += 1; |
|
4386 } else { |
|
4387 windows.removeAt(i); |
|
4388 } |
|
4389 } |
|
4390 } |
|
4391 |
|
4392 sp<InputWindowHandle> InputDispatcher::TouchState::getFirstForegroundWindowHandle() const { |
|
4393 for (size_t i = 0; i < windows.size(); i++) { |
|
4394 const TouchedWindow& window = windows.itemAt(i); |
|
4395 if (window.targetFlags & InputTarget::FLAG_FOREGROUND) { |
|
4396 return window.windowHandle; |
|
4397 } |
|
4398 } |
|
4399 return NULL; |
|
4400 } |
|
4401 |
|
4402 bool InputDispatcher::TouchState::isSlippery() const { |
|
4403 // Must have exactly one foreground window. |
|
4404 bool haveSlipperyForegroundWindow = false; |
|
4405 for (size_t i = 0; i < windows.size(); i++) { |
|
4406 const TouchedWindow& window = windows.itemAt(i); |
|
4407 if (window.targetFlags & InputTarget::FLAG_FOREGROUND) { |
|
4408 if (haveSlipperyForegroundWindow |
|
4409 || !(window.windowHandle->getInfo()->layoutParamsFlags |
|
4410 & InputWindowInfo::FLAG_SLIPPERY)) { |
|
4411 return false; |
|
4412 } |
|
4413 haveSlipperyForegroundWindow = true; |
|
4414 } |
|
4415 } |
|
4416 return haveSlipperyForegroundWindow; |
|
4417 } |
|
4418 |
|
4419 |
|
4420 // --- InputDispatcherThread --- |
|
4421 |
|
4422 InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) : |
|
4423 Thread(/*canCallJava*/ true), mDispatcher(dispatcher) { |
|
4424 } |
|
4425 |
|
4426 InputDispatcherThread::~InputDispatcherThread() { |
|
4427 } |
|
4428 |
|
4429 bool InputDispatcherThread::threadLoop() { |
|
4430 mDispatcher->dispatchOnce(); |
|
4431 return true; |
|
4432 } |
|
4433 |
|
4434 } // namespace android |