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