blob: b5a4bd2da0c7534422855121483710910e92cd82 [file] [log] [blame]
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070017#define LOG_TAG "InputDispatcher"
18
19//#define LOG_NDEBUG 0
20
21// Log detailed debug messages about each inbound event notification to the dispatcher.
Jeff Brown349703e2010-06-22 01:27:15 -070022#define DEBUG_INBOUND_EVENT_DETAILS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070023
24// Log detailed debug messages about each outbound event processed by the dispatcher.
Jeff Brown349703e2010-06-22 01:27:15 -070025#define DEBUG_OUTBOUND_EVENT_DETAILS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070026
27// Log debug messages about batching.
Jeff Brown349703e2010-06-22 01:27:15 -070028#define DEBUG_BATCHING 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070029
30// Log debug messages about the dispatch cycle.
Jeff Brown349703e2010-06-22 01:27:15 -070031#define DEBUG_DISPATCH_CYCLE 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070032
Jeff Brown9c3cda02010-06-15 01:31:58 -070033// Log debug messages about registrations.
Jeff Brown349703e2010-06-22 01:27:15 -070034#define DEBUG_REGISTRATION 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070035
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070036// Log debug messages about performance statistics.
Jeff Brown349703e2010-06-22 01:27:15 -070037#define DEBUG_PERFORMANCE_STATISTICS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070038
Jeff Brown7fbdc842010-06-17 20:52:56 -070039// Log debug messages about input event injection.
Jeff Brown349703e2010-06-22 01:27:15 -070040#define DEBUG_INJECTION 0
Jeff Brown7fbdc842010-06-17 20:52:56 -070041
Jeff Brownae9fc032010-08-18 15:51:08 -070042// Log debug messages about input event throttling.
43#define DEBUG_THROTTLING 0
44
Jeff Brownb88102f2010-09-08 11:49:43 -070045// Log debug messages about input focus tracking.
46#define DEBUG_FOCUS 0
47
48// Log debug messages about the app switch latency optimization.
49#define DEBUG_APP_SWITCH 0
50
Jeff Brownb4ff35d2011-01-02 16:37:43 -080051#include "InputDispatcher.h"
52
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070053#include <cutils/log.h>
Jeff Brownb88102f2010-09-08 11:49:43 -070054#include <ui/PowerManager.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070055
56#include <stddef.h>
57#include <unistd.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070058#include <errno.h>
59#include <limits.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070060
Jeff Brownf2f487182010-10-01 17:46:21 -070061#define INDENT " "
62#define INDENT2 " "
63
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070064namespace android {
65
Jeff Brownb88102f2010-09-08 11:49:43 -070066// Default input dispatching timeout if there is no focused application or paused window
67// from which to determine an appropriate dispatching timeout.
68const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
69
70// Amount of time to allow for all pending events to be processed when an app switch
71// key is on the way. This is used to preempt input dispatch and drop input events
72// when an application takes too long to respond and the user has pressed an app switch key.
73const nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
74
Jeff Brown928e0542011-01-10 11:17:36 -080075// Amount of time to allow for an event to be dispatched (measured since its eventTime)
76// before considering it stale and dropping it.
77const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL; // 10sec
78
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070079
Jeff Brown7fbdc842010-06-17 20:52:56 -070080static inline nsecs_t now() {
81 return systemTime(SYSTEM_TIME_MONOTONIC);
82}
83
Jeff Brownb88102f2010-09-08 11:49:43 -070084static inline const char* toString(bool value) {
85 return value ? "true" : "false";
86}
87
Jeff Brown01ce2e92010-09-26 22:20:12 -070088static inline int32_t getMotionEventActionPointerIndex(int32_t action) {
89 return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
90 >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
91}
92
93static bool isValidKeyAction(int32_t action) {
94 switch (action) {
95 case AKEY_EVENT_ACTION_DOWN:
96 case AKEY_EVENT_ACTION_UP:
97 return true;
98 default:
99 return false;
100 }
101}
102
103static bool validateKeyEvent(int32_t action) {
104 if (! isValidKeyAction(action)) {
105 LOGE("Key event has invalid action code 0x%x", action);
106 return false;
107 }
108 return true;
109}
110
Jeff Brownb6997262010-10-08 22:31:17 -0700111static bool isValidMotionAction(int32_t action, size_t pointerCount) {
Jeff Brown01ce2e92010-09-26 22:20:12 -0700112 switch (action & AMOTION_EVENT_ACTION_MASK) {
113 case AMOTION_EVENT_ACTION_DOWN:
114 case AMOTION_EVENT_ACTION_UP:
115 case AMOTION_EVENT_ACTION_CANCEL:
116 case AMOTION_EVENT_ACTION_MOVE:
Jeff Brown01ce2e92010-09-26 22:20:12 -0700117 case AMOTION_EVENT_ACTION_OUTSIDE:
118 return true;
Jeff Brownb6997262010-10-08 22:31:17 -0700119 case AMOTION_EVENT_ACTION_POINTER_DOWN:
120 case AMOTION_EVENT_ACTION_POINTER_UP: {
121 int32_t index = getMotionEventActionPointerIndex(action);
122 return index >= 0 && size_t(index) < pointerCount;
123 }
Jeff Brown01ce2e92010-09-26 22:20:12 -0700124 default:
125 return false;
126 }
127}
128
129static bool validateMotionEvent(int32_t action, size_t pointerCount,
130 const int32_t* pointerIds) {
Jeff Brownb6997262010-10-08 22:31:17 -0700131 if (! isValidMotionAction(action, pointerCount)) {
Jeff Brown01ce2e92010-09-26 22:20:12 -0700132 LOGE("Motion event has invalid action code 0x%x", action);
133 return false;
134 }
135 if (pointerCount < 1 || pointerCount > MAX_POINTERS) {
136 LOGE("Motion event has invalid pointer count %d; value must be between 1 and %d.",
137 pointerCount, MAX_POINTERS);
138 return false;
139 }
Jeff Brownc3db8582010-10-20 15:33:38 -0700140 BitSet32 pointerIdBits;
Jeff Brown01ce2e92010-09-26 22:20:12 -0700141 for (size_t i = 0; i < pointerCount; i++) {
Jeff Brownc3db8582010-10-20 15:33:38 -0700142 int32_t id = pointerIds[i];
143 if (id < 0 || id > MAX_POINTER_ID) {
Jeff Brown01ce2e92010-09-26 22:20:12 -0700144 LOGE("Motion event has invalid pointer id %d; value must be between 0 and %d",
Jeff Brownc3db8582010-10-20 15:33:38 -0700145 id, MAX_POINTER_ID);
Jeff Brown01ce2e92010-09-26 22:20:12 -0700146 return false;
147 }
Jeff Brownc3db8582010-10-20 15:33:38 -0700148 if (pointerIdBits.hasBit(id)) {
149 LOGE("Motion event has duplicate pointer id %d", id);
150 return false;
151 }
152 pointerIdBits.markBit(id);
Jeff Brown01ce2e92010-09-26 22:20:12 -0700153 }
154 return true;
155}
156
Jeff Brownb88102f2010-09-08 11:49:43 -0700157
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700158// --- InputDispatcher ---
159
Jeff Brown9c3cda02010-06-15 01:31:58 -0700160InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
Jeff Brownb88102f2010-09-08 11:49:43 -0700161 mPolicy(policy),
Jeff Brown928e0542011-01-10 11:17:36 -0800162 mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
163 mNextUnblockedEvent(NULL),
Jeff Brownb88102f2010-09-08 11:49:43 -0700164 mDispatchEnabled(true), mDispatchFrozen(false),
Jeff Brown01ce2e92010-09-26 22:20:12 -0700165 mFocusedWindow(NULL),
Jeff Brownb88102f2010-09-08 11:49:43 -0700166 mFocusedApplication(NULL),
167 mCurrentInputTargetsValid(false),
168 mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700169 mLooper = new Looper(false);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700170
Jeff Brownb88102f2010-09-08 11:49:43 -0700171 mInboundQueue.headSentinel.refCount = -1;
172 mInboundQueue.headSentinel.type = EventEntry::TYPE_SENTINEL;
173 mInboundQueue.headSentinel.eventTime = LONG_LONG_MIN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700174
Jeff Brownb88102f2010-09-08 11:49:43 -0700175 mInboundQueue.tailSentinel.refCount = -1;
176 mInboundQueue.tailSentinel.type = EventEntry::TYPE_SENTINEL;
177 mInboundQueue.tailSentinel.eventTime = LONG_LONG_MAX;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700178
179 mKeyRepeatState.lastKeyEntry = NULL;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700180
Jeff Brownae9fc032010-08-18 15:51:08 -0700181 int32_t maxEventsPerSecond = policy->getMaxEventsPerSecond();
182 mThrottleState.minTimeBetweenEvents = 1000000000LL / maxEventsPerSecond;
183 mThrottleState.lastDeviceId = -1;
184
185#if DEBUG_THROTTLING
186 mThrottleState.originalSampleCount = 0;
187 LOGD("Throttling - Max events per second = %d", maxEventsPerSecond);
188#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700189}
190
191InputDispatcher::~InputDispatcher() {
Jeff Brownb88102f2010-09-08 11:49:43 -0700192 { // acquire lock
193 AutoMutex _l(mLock);
194
195 resetKeyRepeatLocked();
Jeff Brown54a18252010-09-16 14:07:33 -0700196 releasePendingEventLocked();
Jeff Brownb88102f2010-09-08 11:49:43 -0700197 drainInboundQueueLocked();
198 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700199
200 while (mConnectionsByReceiveFd.size() != 0) {
201 unregisterInputChannel(mConnectionsByReceiveFd.valueAt(0)->inputChannel);
202 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700203}
204
205void InputDispatcher::dispatchOnce() {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700206 nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
Jeff Brownb21fb102010-09-07 10:44:57 -0700207 nsecs_t keyRepeatDelay = mPolicy->getKeyRepeatDelay();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700208
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700209 nsecs_t nextWakeupTime = LONG_LONG_MAX;
210 { // acquire lock
211 AutoMutex _l(mLock);
Jeff Brownb88102f2010-09-08 11:49:43 -0700212 dispatchOnceInnerLocked(keyRepeatTimeout, keyRepeatDelay, & nextWakeupTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700213
Jeff Brownb88102f2010-09-08 11:49:43 -0700214 if (runCommandsLockedInterruptible()) {
215 nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700216 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700217 } // release lock
218
Jeff Brownb88102f2010-09-08 11:49:43 -0700219 // Wait for callback or timeout or wake. (make sure we round up, not down)
220 nsecs_t currentTime = now();
221 int32_t timeoutMillis;
222 if (nextWakeupTime > currentTime) {
223 uint64_t timeout = uint64_t(nextWakeupTime - currentTime);
224 timeout = (timeout + 999999LL) / 1000000LL;
225 timeoutMillis = timeout > INT_MAX ? -1 : int32_t(timeout);
226 } else {
227 timeoutMillis = 0;
228 }
229
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700230 mLooper->pollOnce(timeoutMillis);
Jeff Brownb88102f2010-09-08 11:49:43 -0700231}
232
233void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
234 nsecs_t keyRepeatDelay, nsecs_t* nextWakeupTime) {
235 nsecs_t currentTime = now();
236
237 // Reset the key repeat timer whenever we disallow key events, even if the next event
238 // is not a key. This is to ensure that we abort a key repeat if the device is just coming
239 // out of sleep.
240 if (keyRepeatTimeout < 0) {
241 resetKeyRepeatLocked();
242 }
243
Jeff Brownb88102f2010-09-08 11:49:43 -0700244 // If dispatching is frozen, do not process timeouts or try to deliver any new events.
245 if (mDispatchFrozen) {
246#if DEBUG_FOCUS
247 LOGD("Dispatch frozen. Waiting some more.");
248#endif
249 return;
250 }
251
252 // Optimize latency of app switches.
253 // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
254 // been pressed. When it expires, we preempt dispatch and drop all other pending events.
255 bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
256 if (mAppSwitchDueTime < *nextWakeupTime) {
257 *nextWakeupTime = mAppSwitchDueTime;
258 }
259
Jeff Brownb88102f2010-09-08 11:49:43 -0700260 // Ready to start a new event.
261 // If we don't already have a pending event, go grab one.
262 if (! mPendingEvent) {
263 if (mInboundQueue.isEmpty()) {
264 if (isAppSwitchDue) {
265 // The inbound queue is empty so the app switch key we were waiting
266 // for will never arrive. Stop waiting for it.
267 resetPendingAppSwitchLocked(false);
268 isAppSwitchDue = false;
269 }
270
271 // Synthesize a key repeat if appropriate.
272 if (mKeyRepeatState.lastKeyEntry) {
273 if (currentTime >= mKeyRepeatState.nextRepeatTime) {
274 mPendingEvent = synthesizeKeyRepeatLocked(currentTime, keyRepeatDelay);
275 } else {
276 if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
277 *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
278 }
279 }
280 }
281 if (! mPendingEvent) {
282 return;
283 }
284 } else {
285 // Inbound queue has at least one entry.
286 EventEntry* entry = mInboundQueue.headSentinel.next;
287
288 // Throttle the entry if it is a move event and there are no
289 // other events behind it in the queue. Due to movement batching, additional
290 // samples may be appended to this event by the time the throttling timeout
291 // expires.
292 // TODO Make this smarter and consider throttling per device independently.
Jeff Brownb6997262010-10-08 22:31:17 -0700293 if (entry->type == EventEntry::TYPE_MOTION
294 && !isAppSwitchDue
295 && mDispatchEnabled
296 && (entry->policyFlags & POLICY_FLAG_PASS_TO_USER)
297 && !entry->isInjected()) {
Jeff Brownb88102f2010-09-08 11:49:43 -0700298 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
299 int32_t deviceId = motionEntry->deviceId;
300 uint32_t source = motionEntry->source;
301 if (! isAppSwitchDue
302 && motionEntry->next == & mInboundQueue.tailSentinel // exactly one event
303 && motionEntry->action == AMOTION_EVENT_ACTION_MOVE
304 && deviceId == mThrottleState.lastDeviceId
305 && source == mThrottleState.lastSource) {
306 nsecs_t nextTime = mThrottleState.lastEventTime
307 + mThrottleState.minTimeBetweenEvents;
308 if (currentTime < nextTime) {
309 // Throttle it!
310#if DEBUG_THROTTLING
311 LOGD("Throttling - Delaying motion event for "
Jeff Brown90655042010-12-02 13:50:46 -0800312 "device %d, source 0x%08x by up to %0.3fms.",
Jeff Brownb88102f2010-09-08 11:49:43 -0700313 deviceId, source, (nextTime - currentTime) * 0.000001);
314#endif
315 if (nextTime < *nextWakeupTime) {
316 *nextWakeupTime = nextTime;
317 }
318 if (mThrottleState.originalSampleCount == 0) {
319 mThrottleState.originalSampleCount =
320 motionEntry->countSamples();
321 }
322 return;
323 }
324 }
325
326#if DEBUG_THROTTLING
327 if (mThrottleState.originalSampleCount != 0) {
328 uint32_t count = motionEntry->countSamples();
329 LOGD("Throttling - Motion event sample count grew by %d from %d to %d.",
330 count - mThrottleState.originalSampleCount,
331 mThrottleState.originalSampleCount, count);
332 mThrottleState.originalSampleCount = 0;
333 }
334#endif
335
336 mThrottleState.lastEventTime = entry->eventTime < currentTime
337 ? entry->eventTime : currentTime;
338 mThrottleState.lastDeviceId = deviceId;
339 mThrottleState.lastSource = source;
340 }
341
342 mInboundQueue.dequeue(entry);
343 mPendingEvent = entry;
344 }
Jeff Browne2fe69e2010-10-18 13:21:23 -0700345
346 // Poke user activity for this event.
347 if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
348 pokeUserActivityLocked(mPendingEvent);
349 }
Jeff Brownb88102f2010-09-08 11:49:43 -0700350 }
351
352 // Now we have an event to dispatch.
Jeff Brown928e0542011-01-10 11:17:36 -0800353 // All events are eventually dequeued and processed this way, even if we intend to drop them.
Jeff Brownb88102f2010-09-08 11:49:43 -0700354 assert(mPendingEvent != NULL);
Jeff Brown54a18252010-09-16 14:07:33 -0700355 bool done = false;
Jeff Brownb6997262010-10-08 22:31:17 -0700356 DropReason dropReason = DROP_REASON_NOT_DROPPED;
357 if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
358 dropReason = DROP_REASON_POLICY;
359 } else if (!mDispatchEnabled) {
360 dropReason = DROP_REASON_DISABLED;
361 }
Jeff Brown928e0542011-01-10 11:17:36 -0800362
363 if (mNextUnblockedEvent == mPendingEvent) {
364 mNextUnblockedEvent = NULL;
365 }
366
Jeff Brownb88102f2010-09-08 11:49:43 -0700367 switch (mPendingEvent->type) {
368 case EventEntry::TYPE_CONFIGURATION_CHANGED: {
369 ConfigurationChangedEntry* typedEntry =
370 static_cast<ConfigurationChangedEntry*>(mPendingEvent);
Jeff Brown54a18252010-09-16 14:07:33 -0700371 done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
Jeff Brownb6997262010-10-08 22:31:17 -0700372 dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
Jeff Brownb88102f2010-09-08 11:49:43 -0700373 break;
374 }
375
376 case EventEntry::TYPE_KEY: {
377 KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
Jeff Brownb6997262010-10-08 22:31:17 -0700378 if (isAppSwitchDue) {
379 if (isAppSwitchKeyEventLocked(typedEntry)) {
Jeff Brownb88102f2010-09-08 11:49:43 -0700380 resetPendingAppSwitchLocked(true);
Jeff Brownb6997262010-10-08 22:31:17 -0700381 isAppSwitchDue = false;
382 } else if (dropReason == DROP_REASON_NOT_DROPPED) {
383 dropReason = DROP_REASON_APP_SWITCH;
Jeff Brownb88102f2010-09-08 11:49:43 -0700384 }
385 }
Jeff Brown928e0542011-01-10 11:17:36 -0800386 if (dropReason == DROP_REASON_NOT_DROPPED
387 && isStaleEventLocked(currentTime, typedEntry)) {
388 dropReason = DROP_REASON_STALE;
389 }
390 if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
391 dropReason = DROP_REASON_BLOCKED;
392 }
Jeff Brownb6997262010-10-08 22:31:17 -0700393 done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
Jeff Browne20c9e02010-10-11 14:20:19 -0700394 &dropReason, nextWakeupTime);
Jeff Brownb88102f2010-09-08 11:49:43 -0700395 break;
396 }
397
398 case EventEntry::TYPE_MOTION: {
399 MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
Jeff Brownb6997262010-10-08 22:31:17 -0700400 if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
401 dropReason = DROP_REASON_APP_SWITCH;
Jeff Brownb88102f2010-09-08 11:49:43 -0700402 }
Jeff Brown928e0542011-01-10 11:17:36 -0800403 if (dropReason == DROP_REASON_NOT_DROPPED
404 && isStaleEventLocked(currentTime, typedEntry)) {
405 dropReason = DROP_REASON_STALE;
406 }
407 if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
408 dropReason = DROP_REASON_BLOCKED;
409 }
Jeff Brownb6997262010-10-08 22:31:17 -0700410 done = dispatchMotionLocked(currentTime, typedEntry,
Jeff Browne20c9e02010-10-11 14:20:19 -0700411 &dropReason, nextWakeupTime);
Jeff Brownb88102f2010-09-08 11:49:43 -0700412 break;
413 }
414
415 default:
416 assert(false);
Jeff Brownb88102f2010-09-08 11:49:43 -0700417 break;
418 }
419
Jeff Brown54a18252010-09-16 14:07:33 -0700420 if (done) {
Jeff Brownb6997262010-10-08 22:31:17 -0700421 if (dropReason != DROP_REASON_NOT_DROPPED) {
422 dropInboundEventLocked(mPendingEvent, dropReason);
423 }
424
Jeff Brown54a18252010-09-16 14:07:33 -0700425 releasePendingEventLocked();
Jeff Brownb88102f2010-09-08 11:49:43 -0700426 *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
427 }
428}
429
430bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
431 bool needWake = mInboundQueue.isEmpty();
432 mInboundQueue.enqueueAtTail(entry);
433
434 switch (entry->type) {
Jeff Brownb6997262010-10-08 22:31:17 -0700435 case EventEntry::TYPE_KEY: {
Jeff Brown928e0542011-01-10 11:17:36 -0800436 // Optimize app switch latency.
437 // If the application takes too long to catch up then we drop all events preceding
438 // the app switch key.
Jeff Brownb6997262010-10-08 22:31:17 -0700439 KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
440 if (isAppSwitchKeyEventLocked(keyEntry)) {
441 if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
442 mAppSwitchSawKeyDown = true;
443 } else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
444 if (mAppSwitchSawKeyDown) {
445#if DEBUG_APP_SWITCH
446 LOGD("App switch is pending!");
447#endif
448 mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
449 mAppSwitchSawKeyDown = false;
450 needWake = true;
451 }
452 }
453 }
Jeff Brownb88102f2010-09-08 11:49:43 -0700454 break;
455 }
Jeff Brown928e0542011-01-10 11:17:36 -0800456
457 case EventEntry::TYPE_MOTION: {
458 // Optimize case where the current application is unresponsive and the user
459 // decides to touch a window in a different application.
460 // If the application takes too long to catch up then we drop all events preceding
461 // the touch into the other window.
462 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
463 if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN
464 && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
465 && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY
466 && mInputTargetWaitApplication != NULL) {
467 int32_t x = int32_t(motionEntry->firstSample.pointerCoords[0].x);
468 int32_t y = int32_t(motionEntry->firstSample.pointerCoords[0].y);
469 const InputWindow* touchedWindow = findTouchedWindowAtLocked(x, y);
470 if (touchedWindow
471 && touchedWindow->inputWindowHandle != NULL
472 && touchedWindow->inputWindowHandle->getInputApplicationHandle()
473 != mInputTargetWaitApplication) {
474 // User touched a different application than the one we are waiting on.
475 // Flag the event, and start pruning the input queue.
476 mNextUnblockedEvent = motionEntry;
477 needWake = true;
478 }
479 }
480 break;
481 }
Jeff Brownb6997262010-10-08 22:31:17 -0700482 }
Jeff Brownb88102f2010-09-08 11:49:43 -0700483
484 return needWake;
485}
486
Jeff Brown928e0542011-01-10 11:17:36 -0800487const InputWindow* InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) {
488 // Traverse windows from front to back to find touched window.
489 size_t numWindows = mWindows.size();
490 for (size_t i = 0; i < numWindows; i++) {
491 const InputWindow* window = & mWindows.editItemAt(i);
492 int32_t flags = window->layoutParamsFlags;
493
494 if (window->visible) {
495 if (!(flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
496 bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
497 | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
498 if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
499 // Found window.
500 return window;
501 }
502 }
503 }
504
505 if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
506 // Error window is on top but not visible, so touch is dropped.
507 return NULL;
508 }
509 }
510 return NULL;
511}
512
Jeff Brownb6997262010-10-08 22:31:17 -0700513void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
514 const char* reason;
515 switch (dropReason) {
516 case DROP_REASON_POLICY:
Jeff Browne20c9e02010-10-11 14:20:19 -0700517#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown3122e442010-10-11 23:32:49 -0700518 LOGD("Dropped event because policy consumed it.");
Jeff Browne20c9e02010-10-11 14:20:19 -0700519#endif
Jeff Brown3122e442010-10-11 23:32:49 -0700520 reason = "inbound event was dropped because the policy consumed it";
Jeff Brownb6997262010-10-08 22:31:17 -0700521 break;
522 case DROP_REASON_DISABLED:
523 LOGI("Dropped event because input dispatch is disabled.");
524 reason = "inbound event was dropped because input dispatch is disabled";
525 break;
526 case DROP_REASON_APP_SWITCH:
527 LOGI("Dropped event because of pending overdue app switch.");
528 reason = "inbound event was dropped because of pending overdue app switch";
529 break;
Jeff Brown928e0542011-01-10 11:17:36 -0800530 case DROP_REASON_BLOCKED:
531 LOGI("Dropped event because the current application is not responding and the user "
532 "has started interating with a different application.");
533 reason = "inbound event was dropped because the current application is not responding "
534 "and the user has started interating with a different application";
535 break;
536 case DROP_REASON_STALE:
537 LOGI("Dropped event because it is stale.");
538 reason = "inbound event was dropped because it is stale";
539 break;
Jeff Brownb6997262010-10-08 22:31:17 -0700540 default:
541 assert(false);
542 return;
543 }
544
545 switch (entry->type) {
546 case EventEntry::TYPE_KEY:
547 synthesizeCancelationEventsForAllConnectionsLocked(
548 InputState::CANCEL_NON_POINTER_EVENTS, reason);
549 break;
550 case EventEntry::TYPE_MOTION: {
551 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
552 if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
553 synthesizeCancelationEventsForAllConnectionsLocked(
554 InputState::CANCEL_POINTER_EVENTS, reason);
555 } else {
556 synthesizeCancelationEventsForAllConnectionsLocked(
557 InputState::CANCEL_NON_POINTER_EVENTS, reason);
558 }
559 break;
560 }
561 }
562}
563
564bool InputDispatcher::isAppSwitchKeyCode(int32_t keyCode) {
Jeff Brownb88102f2010-09-08 11:49:43 -0700565 return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
566}
567
Jeff Brownb6997262010-10-08 22:31:17 -0700568bool InputDispatcher::isAppSwitchKeyEventLocked(KeyEntry* keyEntry) {
569 return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
570 && isAppSwitchKeyCode(keyEntry->keyCode)
Jeff Browne20c9e02010-10-11 14:20:19 -0700571 && (keyEntry->policyFlags & POLICY_FLAG_TRUSTED)
Jeff Brownb6997262010-10-08 22:31:17 -0700572 && (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
573}
574
Jeff Brownb88102f2010-09-08 11:49:43 -0700575bool InputDispatcher::isAppSwitchPendingLocked() {
576 return mAppSwitchDueTime != LONG_LONG_MAX;
577}
578
Jeff Brownb88102f2010-09-08 11:49:43 -0700579void InputDispatcher::resetPendingAppSwitchLocked(bool handled) {
580 mAppSwitchDueTime = LONG_LONG_MAX;
581
582#if DEBUG_APP_SWITCH
583 if (handled) {
584 LOGD("App switch has arrived.");
585 } else {
586 LOGD("App switch was abandoned.");
587 }
588#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700589}
590
Jeff Brown928e0542011-01-10 11:17:36 -0800591bool InputDispatcher::isStaleEventLocked(nsecs_t currentTime, EventEntry* entry) {
592 return currentTime - entry->eventTime >= STALE_EVENT_TIMEOUT;
593}
594
Jeff Brown9c3cda02010-06-15 01:31:58 -0700595bool InputDispatcher::runCommandsLockedInterruptible() {
596 if (mCommandQueue.isEmpty()) {
597 return false;
598 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700599
Jeff Brown9c3cda02010-06-15 01:31:58 -0700600 do {
601 CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
602
603 Command command = commandEntry->command;
604 (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
605
Jeff Brown7fbdc842010-06-17 20:52:56 -0700606 commandEntry->connection.clear();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700607 mAllocator.releaseCommandEntry(commandEntry);
608 } while (! mCommandQueue.isEmpty());
609 return true;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700610}
611
Jeff Brown9c3cda02010-06-15 01:31:58 -0700612InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
613 CommandEntry* commandEntry = mAllocator.obtainCommandEntry(command);
614 mCommandQueue.enqueueAtTail(commandEntry);
615 return commandEntry;
616}
617
Jeff Brownb88102f2010-09-08 11:49:43 -0700618void InputDispatcher::drainInboundQueueLocked() {
619 while (! mInboundQueue.isEmpty()) {
620 EventEntry* entry = mInboundQueue.dequeueAtHead();
Jeff Brown54a18252010-09-16 14:07:33 -0700621 releaseInboundEventLocked(entry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700622 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700623}
624
Jeff Brown54a18252010-09-16 14:07:33 -0700625void InputDispatcher::releasePendingEventLocked() {
Jeff Brownb88102f2010-09-08 11:49:43 -0700626 if (mPendingEvent) {
Jeff Brown54a18252010-09-16 14:07:33 -0700627 releaseInboundEventLocked(mPendingEvent);
Jeff Brownb88102f2010-09-08 11:49:43 -0700628 mPendingEvent = NULL;
629 }
630}
631
Jeff Brown54a18252010-09-16 14:07:33 -0700632void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) {
Jeff Brown01ce2e92010-09-26 22:20:12 -0700633 InjectionState* injectionState = entry->injectionState;
634 if (injectionState && injectionState->injectionResult == INPUT_EVENT_INJECTION_PENDING) {
Jeff Brownb88102f2010-09-08 11:49:43 -0700635#if DEBUG_DISPATCH_CYCLE
Jeff Brown01ce2e92010-09-26 22:20:12 -0700636 LOGD("Injected inbound event was dropped.");
Jeff Brownb88102f2010-09-08 11:49:43 -0700637#endif
638 setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
639 }
640 mAllocator.releaseEventEntry(entry);
641}
642
Jeff Brownb88102f2010-09-08 11:49:43 -0700643void InputDispatcher::resetKeyRepeatLocked() {
644 if (mKeyRepeatState.lastKeyEntry) {
645 mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
646 mKeyRepeatState.lastKeyEntry = NULL;
647 }
648}
649
650InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(
Jeff Brownb21fb102010-09-07 10:44:57 -0700651 nsecs_t currentTime, nsecs_t keyRepeatDelay) {
Jeff Brown349703e2010-06-22 01:27:15 -0700652 KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
653
Jeff Brown349703e2010-06-22 01:27:15 -0700654 // Reuse the repeated key entry if it is otherwise unreferenced.
Jeff Browne20c9e02010-10-11 14:20:19 -0700655 uint32_t policyFlags = (entry->policyFlags & POLICY_FLAG_RAW_MASK)
656 | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700657 if (entry->refCount == 1) {
Jeff Brown01ce2e92010-09-26 22:20:12 -0700658 mAllocator.recycleKeyEntry(entry);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700659 entry->eventTime = currentTime;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700660 entry->policyFlags = policyFlags;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700661 entry->repeatCount += 1;
662 } else {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700663 KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700664 entry->deviceId, entry->source, policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700665 entry->action, entry->flags, entry->keyCode, entry->scanCode,
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700666 entry->metaState, entry->repeatCount + 1, entry->downTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700667
668 mKeyRepeatState.lastKeyEntry = newEntry;
669 mAllocator.releaseKeyEntry(entry);
670
671 entry = newEntry;
672 }
Jeff Brownb88102f2010-09-08 11:49:43 -0700673 entry->syntheticRepeat = true;
674
675 // Increment reference count since we keep a reference to the event in
676 // mKeyRepeatState.lastKeyEntry in addition to the one we return.
677 entry->refCount += 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700678
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700679 if (entry->repeatCount == 1) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700680 entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700681 }
682
Jeff Brownb21fb102010-09-07 10:44:57 -0700683 mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatDelay;
Jeff Brownb88102f2010-09-08 11:49:43 -0700684 return entry;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700685}
686
Jeff Brownb88102f2010-09-08 11:49:43 -0700687bool InputDispatcher::dispatchConfigurationChangedLocked(
688 nsecs_t currentTime, ConfigurationChangedEntry* entry) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700689#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brownb88102f2010-09-08 11:49:43 -0700690 LOGD("dispatchConfigurationChanged - eventTime=%lld", entry->eventTime);
691#endif
692
693 // Reset key repeating in case a keyboard device was added or removed or something.
694 resetKeyRepeatLocked();
695
696 // Enqueue a command to run outside the lock to tell the policy that the configuration changed.
697 CommandEntry* commandEntry = postCommandLocked(
698 & InputDispatcher::doNotifyConfigurationChangedInterruptible);
699 commandEntry->eventTime = entry->eventTime;
700 return true;
701}
702
703bool InputDispatcher::dispatchKeyLocked(
704 nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
Jeff Browne20c9e02010-10-11 14:20:19 -0700705 DropReason* dropReason, nsecs_t* nextWakeupTime) {
Jeff Browne46a0a42010-11-02 17:58:22 -0700706 // Preprocessing.
707 if (! entry->dispatchInProgress) {
708 if (entry->repeatCount == 0
709 && entry->action == AKEY_EVENT_ACTION_DOWN
710 && (entry->policyFlags & POLICY_FLAG_TRUSTED)
711 && !entry->isInjected()) {
712 if (mKeyRepeatState.lastKeyEntry
713 && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
714 // We have seen two identical key downs in a row which indicates that the device
715 // driver is automatically generating key repeats itself. We take note of the
716 // repeat here, but we disable our own next key repeat timer since it is clear that
717 // we will not need to synthesize key repeats ourselves.
718 entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
719 resetKeyRepeatLocked();
720 mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
721 } else {
722 // Not a repeat. Save key down state in case we do see a repeat later.
723 resetKeyRepeatLocked();
724 mKeyRepeatState.nextRepeatTime = entry->eventTime + keyRepeatTimeout;
725 }
726 mKeyRepeatState.lastKeyEntry = entry;
727 entry->refCount += 1;
728 } else if (! entry->syntheticRepeat) {
729 resetKeyRepeatLocked();
730 }
731
732 entry->dispatchInProgress = true;
733 resetTargetsLocked();
734
735 logOutboundKeyDetailsLocked("dispatchKey - ", entry);
736 }
737
Jeff Brown54a18252010-09-16 14:07:33 -0700738 // Give the policy a chance to intercept the key.
739 if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
Jeff Browne20c9e02010-10-11 14:20:19 -0700740 if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
Jeff Brown54a18252010-09-16 14:07:33 -0700741 CommandEntry* commandEntry = postCommandLocked(
742 & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
Jeff Browne20c9e02010-10-11 14:20:19 -0700743 if (mFocusedWindow) {
Jeff Brown928e0542011-01-10 11:17:36 -0800744 commandEntry->inputWindowHandle = mFocusedWindow->inputWindowHandle;
Jeff Brown54a18252010-09-16 14:07:33 -0700745 }
746 commandEntry->keyEntry = entry;
747 entry->refCount += 1;
748 return false; // wait for the command to run
749 } else {
750 entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
751 }
752 } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
Jeff Browne20c9e02010-10-11 14:20:19 -0700753 if (*dropReason == DROP_REASON_NOT_DROPPED) {
754 *dropReason = DROP_REASON_POLICY;
755 }
Jeff Brown54a18252010-09-16 14:07:33 -0700756 }
757
758 // Clean up if dropping the event.
Jeff Browne20c9e02010-10-11 14:20:19 -0700759 if (*dropReason != DROP_REASON_NOT_DROPPED) {
Jeff Brown54a18252010-09-16 14:07:33 -0700760 resetTargetsLocked();
Jeff Brown3122e442010-10-11 23:32:49 -0700761 setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
762 ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
Jeff Brown54a18252010-09-16 14:07:33 -0700763 return true;
764 }
765
Jeff Brownb88102f2010-09-08 11:49:43 -0700766 // Identify targets.
767 if (! mCurrentInputTargetsValid) {
Jeff Brown01ce2e92010-09-26 22:20:12 -0700768 int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
769 entry, nextWakeupTime);
Jeff Brownb88102f2010-09-08 11:49:43 -0700770 if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
771 return false;
772 }
773
774 setInjectionResultLocked(entry, injectionResult);
775 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
776 return true;
777 }
778
779 addMonitoringTargetsLocked();
Jeff Brown01ce2e92010-09-26 22:20:12 -0700780 commitTargetsLocked();
Jeff Brownb88102f2010-09-08 11:49:43 -0700781 }
782
783 // Dispatch the key.
784 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
Jeff Brownb88102f2010-09-08 11:49:43 -0700785 return true;
786}
787
788void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry) {
789#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brown90655042010-12-02 13:50:46 -0800790 LOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
Jeff Brownb88102f2010-09-08 11:49:43 -0700791 "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
Jeff Browne46a0a42010-11-02 17:58:22 -0700792 "repeatCount=%d, downTime=%lld",
Jeff Brownb88102f2010-09-08 11:49:43 -0700793 prefix,
794 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
795 entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
Jeff Browne46a0a42010-11-02 17:58:22 -0700796 entry->repeatCount, entry->downTime);
Jeff Brownb88102f2010-09-08 11:49:43 -0700797#endif
798}
799
800bool InputDispatcher::dispatchMotionLocked(
Jeff Browne20c9e02010-10-11 14:20:19 -0700801 nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
Jeff Browne46a0a42010-11-02 17:58:22 -0700802 // Preprocessing.
803 if (! entry->dispatchInProgress) {
804 entry->dispatchInProgress = true;
805 resetTargetsLocked();
806
807 logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
808 }
809
Jeff Brown54a18252010-09-16 14:07:33 -0700810 // Clean up if dropping the event.
Jeff Browne20c9e02010-10-11 14:20:19 -0700811 if (*dropReason != DROP_REASON_NOT_DROPPED) {
Jeff Brown54a18252010-09-16 14:07:33 -0700812 resetTargetsLocked();
Jeff Brown3122e442010-10-11 23:32:49 -0700813 setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
814 ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
Jeff Brown54a18252010-09-16 14:07:33 -0700815 return true;
816 }
817
Jeff Brownb88102f2010-09-08 11:49:43 -0700818 bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
819
820 // Identify targets.
821 if (! mCurrentInputTargetsValid) {
Jeff Brownb88102f2010-09-08 11:49:43 -0700822 int32_t injectionResult;
823 if (isPointerEvent) {
824 // Pointer event. (eg. touchscreen)
Jeff Brown01ce2e92010-09-26 22:20:12 -0700825 injectionResult = findTouchedWindowTargetsLocked(currentTime,
826 entry, nextWakeupTime);
Jeff Brownb88102f2010-09-08 11:49:43 -0700827 } else {
828 // Non touch event. (eg. trackball)
Jeff Brown01ce2e92010-09-26 22:20:12 -0700829 injectionResult = findFocusedWindowTargetsLocked(currentTime,
830 entry, nextWakeupTime);
Jeff Brownb88102f2010-09-08 11:49:43 -0700831 }
832 if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
833 return false;
834 }
835
836 setInjectionResultLocked(entry, injectionResult);
837 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
838 return true;
839 }
840
841 addMonitoringTargetsLocked();
Jeff Brown01ce2e92010-09-26 22:20:12 -0700842 commitTargetsLocked();
Jeff Brownb88102f2010-09-08 11:49:43 -0700843 }
844
845 // Dispatch the motion.
846 dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
Jeff Brownb88102f2010-09-08 11:49:43 -0700847 return true;
848}
849
850
851void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) {
852#if DEBUG_OUTBOUND_EVENT_DETAILS
Jeff Brown90655042010-12-02 13:50:46 -0800853 LOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
Jeff Brown85a31762010-09-01 17:01:00 -0700854 "action=0x%x, flags=0x%x, "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700855 "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
Jeff Brownb88102f2010-09-08 11:49:43 -0700856 prefix,
Jeff Brown85a31762010-09-01 17:01:00 -0700857 entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
858 entry->action, entry->flags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700859 entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
860 entry->downTime);
861
862 // Print the most recent sample that we have available, this may change due to batching.
863 size_t sampleCount = 1;
Jeff Brownb88102f2010-09-08 11:49:43 -0700864 const MotionSample* sample = & entry->firstSample;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700865 for (; sample->next != NULL; sample = sample->next) {
866 sampleCount += 1;
867 }
868 for (uint32_t i = 0; i < entry->pointerCount; i++) {
Jeff Brown8d608662010-08-30 03:02:23 -0700869 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
Jeff Brown85a31762010-09-01 17:01:00 -0700870 "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
Jeff Brown8d608662010-08-30 03:02:23 -0700871 "orientation=%f",
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700872 i, entry->pointerIds[i],
Jeff Brown8d608662010-08-30 03:02:23 -0700873 sample->pointerCoords[i].x, sample->pointerCoords[i].y,
874 sample->pointerCoords[i].pressure, sample->pointerCoords[i].size,
875 sample->pointerCoords[i].touchMajor, sample->pointerCoords[i].touchMinor,
876 sample->pointerCoords[i].toolMajor, sample->pointerCoords[i].toolMinor,
877 sample->pointerCoords[i].orientation);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700878 }
879
880 // Keep in mind that due to batching, it is possible for the number of samples actually
881 // dispatched to change before the application finally consumed them.
Jeff Brownc5ed5912010-07-14 18:48:53 -0700882 if (entry->action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700883 LOGD(" ... Total movement samples currently batched %d ...", sampleCount);
884 }
885#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700886}
887
888void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
889 EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
890#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -0700891 LOGD("dispatchEventToCurrentInputTargets - "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700892 "resumeWithAppendedMotionSample=%s",
Jeff Brownb88102f2010-09-08 11:49:43 -0700893 toString(resumeWithAppendedMotionSample));
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700894#endif
895
Jeff Brown9c3cda02010-06-15 01:31:58 -0700896 assert(eventEntry->dispatchInProgress); // should already have been set to true
897
Jeff Browne2fe69e2010-10-18 13:21:23 -0700898 pokeUserActivityLocked(eventEntry);
899
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700900 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
901 const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
902
Jeff Brown519e0242010-09-15 15:18:56 -0700903 ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700904 if (connectionIndex >= 0) {
905 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700906 prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700907 resumeWithAppendedMotionSample);
908 } else {
Jeff Brownb6997262010-10-08 22:31:17 -0700909#if DEBUG_FOCUS
910 LOGD("Dropping event delivery to target with channel '%s' because it "
911 "is no longer registered with the input dispatcher.",
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700912 inputTarget.inputChannel->getName().string());
Jeff Brownb6997262010-10-08 22:31:17 -0700913#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700914 }
915 }
916}
917
Jeff Brown54a18252010-09-16 14:07:33 -0700918void InputDispatcher::resetTargetsLocked() {
Jeff Brownb88102f2010-09-08 11:49:43 -0700919 mCurrentInputTargetsValid = false;
920 mCurrentInputTargets.clear();
Jeff Brownb88102f2010-09-08 11:49:43 -0700921 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
Jeff Brown928e0542011-01-10 11:17:36 -0800922 mInputTargetWaitApplication.clear();
Jeff Brownb88102f2010-09-08 11:49:43 -0700923}
924
Jeff Brown01ce2e92010-09-26 22:20:12 -0700925void InputDispatcher::commitTargetsLocked() {
Jeff Brownb88102f2010-09-08 11:49:43 -0700926 mCurrentInputTargetsValid = true;
927}
928
929int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
930 const EventEntry* entry, const InputApplication* application, const InputWindow* window,
931 nsecs_t* nextWakeupTime) {
932 if (application == NULL && window == NULL) {
933 if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
934#if DEBUG_FOCUS
935 LOGD("Waiting for system to become ready for input.");
936#endif
937 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
938 mInputTargetWaitStartTime = currentTime;
939 mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
940 mInputTargetWaitTimeoutExpired = false;
Jeff Brown928e0542011-01-10 11:17:36 -0800941 mInputTargetWaitApplication.clear();
Jeff Brownb88102f2010-09-08 11:49:43 -0700942 }
943 } else {
944 if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
945#if DEBUG_FOCUS
Jeff Brown519e0242010-09-15 15:18:56 -0700946 LOGD("Waiting for application to become ready for input: %s",
947 getApplicationWindowLabelLocked(application, window).string());
Jeff Brownb88102f2010-09-08 11:49:43 -0700948#endif
949 nsecs_t timeout = window ? window->dispatchingTimeout :
950 application ? application->dispatchingTimeout : DEFAULT_INPUT_DISPATCHING_TIMEOUT;
951
952 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
953 mInputTargetWaitStartTime = currentTime;
954 mInputTargetWaitTimeoutTime = currentTime + timeout;
955 mInputTargetWaitTimeoutExpired = false;
Jeff Brown928e0542011-01-10 11:17:36 -0800956 mInputTargetWaitApplication.clear();
957
958 if (window && window->inputWindowHandle != NULL) {
959 mInputTargetWaitApplication =
960 window->inputWindowHandle->getInputApplicationHandle();
961 }
962 if (mInputTargetWaitApplication == NULL && application) {
963 mInputTargetWaitApplication = application->inputApplicationHandle;
964 }
Jeff Brownb88102f2010-09-08 11:49:43 -0700965 }
966 }
967
968 if (mInputTargetWaitTimeoutExpired) {
969 return INPUT_EVENT_INJECTION_TIMED_OUT;
970 }
971
972 if (currentTime >= mInputTargetWaitTimeoutTime) {
Jeff Brown519e0242010-09-15 15:18:56 -0700973 onANRLocked(currentTime, application, window, entry->eventTime, mInputTargetWaitStartTime);
Jeff Brownb88102f2010-09-08 11:49:43 -0700974
975 // Force poll loop to wake up immediately on next iteration once we get the
976 // ANR response back from the policy.
977 *nextWakeupTime = LONG_LONG_MIN;
978 return INPUT_EVENT_INJECTION_PENDING;
979 } else {
980 // Force poll loop to wake up when timeout is due.
981 if (mInputTargetWaitTimeoutTime < *nextWakeupTime) {
982 *nextWakeupTime = mInputTargetWaitTimeoutTime;
983 }
984 return INPUT_EVENT_INJECTION_PENDING;
985 }
986}
987
Jeff Brown519e0242010-09-15 15:18:56 -0700988void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
989 const sp<InputChannel>& inputChannel) {
Jeff Brownb88102f2010-09-08 11:49:43 -0700990 if (newTimeout > 0) {
991 // Extend the timeout.
992 mInputTargetWaitTimeoutTime = now() + newTimeout;
993 } else {
994 // Give up.
995 mInputTargetWaitTimeoutExpired = true;
Jeff Brown519e0242010-09-15 15:18:56 -0700996
Jeff Brown01ce2e92010-09-26 22:20:12 -0700997 // Release the touch targets.
998 mTouchState.reset();
Jeff Brown2a95c2a2010-09-16 12:31:46 -0700999
Jeff Brown519e0242010-09-15 15:18:56 -07001000 // Input state will not be realistic. Mark it out of sync.
Jeff Browndc3e0052010-09-16 11:02:16 -07001001 if (inputChannel.get()) {
1002 ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
1003 if (connectionIndex >= 0) {
1004 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown00045a72010-12-09 18:10:30 -08001005 if (connection->status == Connection::STATUS_NORMAL) {
1006 synthesizeCancelationEventsForConnectionLocked(
1007 connection, InputState::CANCEL_ALL_EVENTS,
1008 "application not responding");
1009 }
Jeff Browndc3e0052010-09-16 11:02:16 -07001010 }
Jeff Brown519e0242010-09-15 15:18:56 -07001011 }
Jeff Brownb88102f2010-09-08 11:49:43 -07001012 }
1013}
1014
Jeff Brown519e0242010-09-15 15:18:56 -07001015nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(
Jeff Brownb88102f2010-09-08 11:49:43 -07001016 nsecs_t currentTime) {
1017 if (mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
1018 return currentTime - mInputTargetWaitStartTime;
1019 }
1020 return 0;
1021}
1022
1023void InputDispatcher::resetANRTimeoutsLocked() {
1024#if DEBUG_FOCUS
1025 LOGD("Resetting ANR timeouts.");
1026#endif
1027
Jeff Brownb88102f2010-09-08 11:49:43 -07001028 // Reset input target wait timeout.
1029 mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
1030}
1031
Jeff Brown01ce2e92010-09-26 22:20:12 -07001032int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
1033 const EventEntry* entry, nsecs_t* nextWakeupTime) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001034 mCurrentInputTargets.clear();
1035
1036 int32_t injectionResult;
1037
1038 // If there is no currently focused window and no focused application
1039 // then drop the event.
1040 if (! mFocusedWindow) {
1041 if (mFocusedApplication) {
1042#if DEBUG_FOCUS
1043 LOGD("Waiting because there is no focused window but there is a "
Jeff Brown519e0242010-09-15 15:18:56 -07001044 "focused application that may eventually add a window: %s.",
1045 getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
Jeff Brownb88102f2010-09-08 11:49:43 -07001046#endif
1047 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1048 mFocusedApplication, NULL, nextWakeupTime);
1049 goto Unresponsive;
1050 }
1051
1052 LOGI("Dropping event because there is no focused window or focused application.");
1053 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1054 goto Failed;
1055 }
1056
1057 // Check permissions.
Jeff Brown01ce2e92010-09-26 22:20:12 -07001058 if (! checkInjectionPermission(mFocusedWindow, entry->injectionState)) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001059 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1060 goto Failed;
1061 }
1062
1063 // If the currently focused window is paused then keep waiting.
1064 if (mFocusedWindow->paused) {
1065#if DEBUG_FOCUS
1066 LOGD("Waiting because focused window is paused.");
1067#endif
1068 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1069 mFocusedApplication, mFocusedWindow, nextWakeupTime);
1070 goto Unresponsive;
1071 }
1072
Jeff Brown519e0242010-09-15 15:18:56 -07001073 // If the currently focused window is still working on previous events then keep waiting.
1074 if (! isWindowFinishedWithPreviousInputLocked(mFocusedWindow)) {
1075#if DEBUG_FOCUS
1076 LOGD("Waiting because focused window still processing previous input.");
1077#endif
1078 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1079 mFocusedApplication, mFocusedWindow, nextWakeupTime);
1080 goto Unresponsive;
1081 }
1082
Jeff Brownb88102f2010-09-08 11:49:43 -07001083 // Success! Output targets.
1084 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
Jeff Brown01ce2e92010-09-26 22:20:12 -07001085 addWindowTargetLocked(mFocusedWindow, InputTarget::FLAG_FOREGROUND, BitSet32(0));
Jeff Brownb88102f2010-09-08 11:49:43 -07001086
1087 // Done.
1088Failed:
1089Unresponsive:
Jeff Brown519e0242010-09-15 15:18:56 -07001090 nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
1091 updateDispatchStatisticsLocked(currentTime, entry,
1092 injectionResult, timeSpentWaitingForApplication);
Jeff Brownb88102f2010-09-08 11:49:43 -07001093#if DEBUG_FOCUS
Jeff Brown519e0242010-09-15 15:18:56 -07001094 LOGD("findFocusedWindow finished: injectionResult=%d, "
1095 "timeSpendWaitingForApplication=%0.1fms",
1096 injectionResult, timeSpentWaitingForApplication / 1000000.0);
Jeff Brownb88102f2010-09-08 11:49:43 -07001097#endif
1098 return injectionResult;
1099}
1100
Jeff Brown01ce2e92010-09-26 22:20:12 -07001101int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
1102 const MotionEntry* entry, nsecs_t* nextWakeupTime) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001103 enum InjectionPermission {
1104 INJECTION_PERMISSION_UNKNOWN,
1105 INJECTION_PERMISSION_GRANTED,
1106 INJECTION_PERMISSION_DENIED
1107 };
1108
Jeff Brownb88102f2010-09-08 11:49:43 -07001109 mCurrentInputTargets.clear();
1110
1111 nsecs_t startTime = now();
1112
1113 // For security reasons, we defer updating the touch state until we are sure that
1114 // event injection will be allowed.
1115 //
1116 // FIXME In the original code, screenWasOff could never be set to true.
1117 // The reason is that the POLICY_FLAG_WOKE_HERE
1118 // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
1119 // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
1120 // actually enqueued using the policyFlags that appeared in the final EV_SYN
1121 // events upon which no preprocessing took place. So policyFlags was always 0.
1122 // In the new native input dispatcher we're a bit more careful about event
1123 // preprocessing so the touches we receive can actually have non-zero policyFlags.
1124 // Unfortunately we obtain undesirable behavior.
1125 //
1126 // Here's what happens:
1127 //
1128 // When the device dims in anticipation of going to sleep, touches
1129 // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
1130 // the device to brighten and reset the user activity timer.
1131 // Touches on other windows (such as the launcher window)
1132 // are dropped. Then after a moment, the device goes to sleep. Oops.
1133 //
1134 // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
1135 // instead of POLICY_FLAG_WOKE_HERE...
1136 //
1137 bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
1138
1139 int32_t action = entry->action;
Jeff Brown01ce2e92010-09-26 22:20:12 -07001140 int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
Jeff Brownb88102f2010-09-08 11:49:43 -07001141
1142 // Update the touch state as needed based on the properties of the touch event.
Jeff Brown01ce2e92010-09-26 22:20:12 -07001143 int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING;
1144 InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
Jeff Brown95712852011-01-04 19:41:59 -08001145 bool isSplit, wrongDevice;
Jeff Brown01ce2e92010-09-26 22:20:12 -07001146 if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
1147 mTempTouchState.reset();
1148 mTempTouchState.down = true;
Jeff Brown95712852011-01-04 19:41:59 -08001149 mTempTouchState.deviceId = entry->deviceId;
1150 isSplit = false;
1151 wrongDevice = false;
Jeff Brown01ce2e92010-09-26 22:20:12 -07001152 } else {
1153 mTempTouchState.copyFrom(mTouchState);
Jeff Brown95712852011-01-04 19:41:59 -08001154 isSplit = mTempTouchState.split;
1155 wrongDevice = mTempTouchState.down && mTempTouchState.deviceId != entry->deviceId;
1156 if (wrongDevice) {
1157#if DEBUG_INPUT_DISPATCHER_POLICY
1158 LOGD("Dropping event because a pointer for a different device is already down.");
1159#endif
1160 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1161 goto Failed;
1162 }
Jeff Brown01ce2e92010-09-26 22:20:12 -07001163 }
Jeff Brownb88102f2010-09-08 11:49:43 -07001164
Jeff Brown01ce2e92010-09-26 22:20:12 -07001165 if (maskedAction == AMOTION_EVENT_ACTION_DOWN
1166 || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
1167 /* Case 1: New splittable pointer going down. */
Jeff Brownb88102f2010-09-08 11:49:43 -07001168
Jeff Brown01ce2e92010-09-26 22:20:12 -07001169 int32_t pointerIndex = getMotionEventActionPointerIndex(action);
1170 int32_t x = int32_t(entry->firstSample.pointerCoords[pointerIndex].x);
1171 int32_t y = int32_t(entry->firstSample.pointerCoords[pointerIndex].y);
1172 const InputWindow* newTouchedWindow = NULL;
1173 const InputWindow* topErrorWindow = NULL;
Jeff Brownb88102f2010-09-08 11:49:43 -07001174
1175 // Traverse windows from front to back to find touched window and outside targets.
1176 size_t numWindows = mWindows.size();
1177 for (size_t i = 0; i < numWindows; i++) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07001178 const InputWindow* window = & mWindows.editItemAt(i);
Jeff Brownb88102f2010-09-08 11:49:43 -07001179 int32_t flags = window->layoutParamsFlags;
1180
1181 if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
1182 if (! topErrorWindow) {
1183 topErrorWindow = window;
1184 }
1185 }
1186
1187 if (window->visible) {
1188 if (! (flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
1189 bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
1190 | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
1191 if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
1192 if (! screenWasOff || flags & InputWindow::FLAG_TOUCHABLE_WHEN_WAKING) {
1193 newTouchedWindow = window;
Jeff Brownb88102f2010-09-08 11:49:43 -07001194 }
1195 break; // found touched window, exit window loop
1196 }
1197 }
1198
Jeff Brown01ce2e92010-09-26 22:20:12 -07001199 if (maskedAction == AMOTION_EVENT_ACTION_DOWN
1200 && (flags & InputWindow::FLAG_WATCH_OUTSIDE_TOUCH)) {
Jeff Brown19dfc832010-10-05 12:26:23 -07001201 int32_t outsideTargetFlags = InputTarget::FLAG_OUTSIDE;
1202 if (isWindowObscuredAtPointLocked(window, x, y)) {
1203 outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
1204 }
1205
1206 mTempTouchState.addOrUpdateWindow(window, outsideTargetFlags, BitSet32(0));
Jeff Brownb88102f2010-09-08 11:49:43 -07001207 }
1208 }
1209 }
1210
1211 // If there is an error window but it is not taking focus (typically because
1212 // it is invisible) then wait for it. Any other focused window may in
1213 // fact be in ANR state.
1214 if (topErrorWindow && newTouchedWindow != topErrorWindow) {
1215#if DEBUG_FOCUS
1216 LOGD("Waiting because system error window is pending.");
1217#endif
1218 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1219 NULL, NULL, nextWakeupTime);
1220 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
1221 goto Unresponsive;
1222 }
1223
Jeff Brown01ce2e92010-09-26 22:20:12 -07001224 // Figure out whether splitting will be allowed for this window.
Jeff Brown46e75292010-11-10 16:53:45 -08001225 if (newTouchedWindow && newTouchedWindow->supportsSplitTouch()) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07001226 // New window supports splitting.
1227 isSplit = true;
1228 } else if (isSplit) {
1229 // New window does not support splitting but we have already split events.
1230 // Assign the pointer to the first foreground window we find.
1231 // (May be NULL which is why we put this code block before the next check.)
1232 newTouchedWindow = mTempTouchState.getFirstForegroundWindow();
1233 }
Jeff Brown01ce2e92010-09-26 22:20:12 -07001234
Jeff Brownb88102f2010-09-08 11:49:43 -07001235 // If we did not find a touched window then fail.
1236 if (! newTouchedWindow) {
1237 if (mFocusedApplication) {
1238#if DEBUG_FOCUS
1239 LOGD("Waiting because there is no touched window but there is a "
Jeff Brown519e0242010-09-15 15:18:56 -07001240 "focused application that may eventually add a new window: %s.",
1241 getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
Jeff Brownb88102f2010-09-08 11:49:43 -07001242#endif
1243 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1244 mFocusedApplication, NULL, nextWakeupTime);
Jeff Brownb88102f2010-09-08 11:49:43 -07001245 goto Unresponsive;
1246 }
1247
1248 LOGI("Dropping event because there is no touched window or focused application.");
1249 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownb88102f2010-09-08 11:49:43 -07001250 goto Failed;
1251 }
1252
Jeff Brown19dfc832010-10-05 12:26:23 -07001253 // Set target flags.
1254 int32_t targetFlags = InputTarget::FLAG_FOREGROUND;
1255 if (isSplit) {
1256 targetFlags |= InputTarget::FLAG_SPLIT;
1257 }
1258 if (isWindowObscuredAtPointLocked(newTouchedWindow, x, y)) {
1259 targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
1260 }
1261
Jeff Brown01ce2e92010-09-26 22:20:12 -07001262 // Update the temporary touch state.
1263 BitSet32 pointerIds;
1264 if (isSplit) {
1265 uint32_t pointerId = entry->pointerIds[pointerIndex];
1266 pointerIds.markBit(pointerId);
Jeff Brownb88102f2010-09-08 11:49:43 -07001267 }
Jeff Brown01ce2e92010-09-26 22:20:12 -07001268 mTempTouchState.addOrUpdateWindow(newTouchedWindow, targetFlags, pointerIds);
Jeff Brownb88102f2010-09-08 11:49:43 -07001269 } else {
Jeff Brown01ce2e92010-09-26 22:20:12 -07001270 /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */
Jeff Brownb88102f2010-09-08 11:49:43 -07001271
1272 // If the pointer is not currently down, then ignore the event.
Jeff Brown01ce2e92010-09-26 22:20:12 -07001273 if (! mTempTouchState.down) {
Jeff Brown76860e32010-10-25 17:37:46 -07001274#if DEBUG_INPUT_DISPATCHER_POLICY
1275 LOGD("Dropping event because the pointer is not down or we previously "
1276 "dropped the pointer down event.");
1277#endif
Jeff Brownb88102f2010-09-08 11:49:43 -07001278 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownb88102f2010-09-08 11:49:43 -07001279 goto Failed;
1280 }
Jeff Brown01ce2e92010-09-26 22:20:12 -07001281 }
Jeff Brownb88102f2010-09-08 11:49:43 -07001282
Jeff Brown01ce2e92010-09-26 22:20:12 -07001283 // Check permission to inject into all touched foreground windows and ensure there
1284 // is at least one touched foreground window.
1285 {
1286 bool haveForegroundWindow = false;
1287 for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
1288 const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
1289 if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
1290 haveForegroundWindow = true;
1291 if (! checkInjectionPermission(touchedWindow.window, entry->injectionState)) {
1292 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1293 injectionPermission = INJECTION_PERMISSION_DENIED;
1294 goto Failed;
1295 }
1296 }
1297 }
1298 if (! haveForegroundWindow) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001299#if DEBUG_INPUT_DISPATCHER_POLICY
Jeff Brown01ce2e92010-09-26 22:20:12 -07001300 LOGD("Dropping event because there is no touched foreground window to receive it.");
Jeff Brownb88102f2010-09-08 11:49:43 -07001301#endif
1302 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownb88102f2010-09-08 11:49:43 -07001303 goto Failed;
1304 }
1305
Jeff Brown01ce2e92010-09-26 22:20:12 -07001306 // Permission granted to injection into all touched foreground windows.
1307 injectionPermission = INJECTION_PERMISSION_GRANTED;
1308 }
Jeff Brown519e0242010-09-15 15:18:56 -07001309
Jeff Brown01ce2e92010-09-26 22:20:12 -07001310 // Ensure all touched foreground windows are ready for new input.
1311 for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
1312 const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
1313 if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
1314 // If the touched window is paused then keep waiting.
1315 if (touchedWindow.window->paused) {
1316#if DEBUG_INPUT_DISPATCHER_POLICY
1317 LOGD("Waiting because touched window is paused.");
Jeff Brown519e0242010-09-15 15:18:56 -07001318#endif
Jeff Brown01ce2e92010-09-26 22:20:12 -07001319 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1320 NULL, touchedWindow.window, nextWakeupTime);
1321 goto Unresponsive;
1322 }
1323
1324 // If the touched window is still working on previous events then keep waiting.
1325 if (! isWindowFinishedWithPreviousInputLocked(touchedWindow.window)) {
1326#if DEBUG_FOCUS
1327 LOGD("Waiting because touched window still processing previous input.");
1328#endif
1329 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1330 NULL, touchedWindow.window, nextWakeupTime);
1331 goto Unresponsive;
1332 }
1333 }
1334 }
1335
1336 // If this is the first pointer going down and the touched window has a wallpaper
1337 // then also add the touched wallpaper windows so they are locked in for the duration
1338 // of the touch gesture.
1339 if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
1340 const InputWindow* foregroundWindow = mTempTouchState.getFirstForegroundWindow();
1341 if (foregroundWindow->hasWallpaper) {
1342 for (size_t i = 0; i < mWindows.size(); i++) {
1343 const InputWindow* window = & mWindows[i];
1344 if (window->layoutParamsType == InputWindow::TYPE_WALLPAPER) {
Jeff Brown19dfc832010-10-05 12:26:23 -07001345 mTempTouchState.addOrUpdateWindow(window,
1346 InputTarget::FLAG_WINDOW_IS_OBSCURED, BitSet32(0));
Jeff Brown01ce2e92010-09-26 22:20:12 -07001347 }
1348 }
1349 }
1350 }
1351
Jeff Brownb88102f2010-09-08 11:49:43 -07001352 // Success! Output targets.
1353 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
Jeff Brownb88102f2010-09-08 11:49:43 -07001354
Jeff Brown01ce2e92010-09-26 22:20:12 -07001355 for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
1356 const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
1357 addWindowTargetLocked(touchedWindow.window, touchedWindow.targetFlags,
1358 touchedWindow.pointerIds);
Jeff Brownb88102f2010-09-08 11:49:43 -07001359 }
1360
Jeff Brown01ce2e92010-09-26 22:20:12 -07001361 // Drop the outside touch window since we will not care about them in the next iteration.
1362 mTempTouchState.removeOutsideTouchWindows();
1363
Jeff Brownb88102f2010-09-08 11:49:43 -07001364Failed:
1365 // Check injection permission once and for all.
1366 if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07001367 if (checkInjectionPermission(NULL, entry->injectionState)) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001368 injectionPermission = INJECTION_PERMISSION_GRANTED;
1369 } else {
1370 injectionPermission = INJECTION_PERMISSION_DENIED;
1371 }
1372 }
1373
1374 // Update final pieces of touch state if the injector had permission.
1375 if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
Jeff Brown95712852011-01-04 19:41:59 -08001376 if (!wrongDevice) {
1377 if (maskedAction == AMOTION_EVENT_ACTION_UP
1378 || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
1379 // All pointers up or canceled.
1380 mTempTouchState.reset();
1381 } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
1382 // First pointer went down.
1383 if (mTouchState.down) {
Jeff Brownb6997262010-10-08 22:31:17 -07001384#if DEBUG_FOCUS
Jeff Brown95712852011-01-04 19:41:59 -08001385 LOGD("Pointer down received while already down.");
Jeff Brownb6997262010-10-08 22:31:17 -07001386#endif
Jeff Brown95712852011-01-04 19:41:59 -08001387 }
1388 } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
1389 // One pointer went up.
1390 if (isSplit) {
1391 int32_t pointerIndex = getMotionEventActionPointerIndex(action);
1392 uint32_t pointerId = entry->pointerIds[pointerIndex];
Jeff Brownb88102f2010-09-08 11:49:43 -07001393
Jeff Brown95712852011-01-04 19:41:59 -08001394 for (size_t i = 0; i < mTempTouchState.windows.size(); ) {
1395 TouchedWindow& touchedWindow = mTempTouchState.windows.editItemAt(i);
1396 if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
1397 touchedWindow.pointerIds.clearBit(pointerId);
1398 if (touchedWindow.pointerIds.isEmpty()) {
1399 mTempTouchState.windows.removeAt(i);
1400 continue;
1401 }
Jeff Brown01ce2e92010-09-26 22:20:12 -07001402 }
Jeff Brown95712852011-01-04 19:41:59 -08001403 i += 1;
Jeff Brown01ce2e92010-09-26 22:20:12 -07001404 }
Jeff Brown01ce2e92010-09-26 22:20:12 -07001405 }
Jeff Brownb88102f2010-09-08 11:49:43 -07001406 }
Jeff Brown01ce2e92010-09-26 22:20:12 -07001407
Jeff Brown95712852011-01-04 19:41:59 -08001408 // Save changes to touch state.
1409 mTouchState.copyFrom(mTempTouchState);
1410 }
Jeff Brownb88102f2010-09-08 11:49:43 -07001411 } else {
Jeff Brown01ce2e92010-09-26 22:20:12 -07001412#if DEBUG_FOCUS
1413 LOGD("Not updating touch focus because injection was denied.");
1414#endif
Jeff Brownb88102f2010-09-08 11:49:43 -07001415 }
1416
1417Unresponsive:
Jeff Brown120a4592010-10-27 18:43:51 -07001418 // Reset temporary touch state to ensure we release unnecessary references to input channels.
1419 mTempTouchState.reset();
1420
Jeff Brown519e0242010-09-15 15:18:56 -07001421 nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
1422 updateDispatchStatisticsLocked(currentTime, entry,
1423 injectionResult, timeSpentWaitingForApplication);
Jeff Brownb88102f2010-09-08 11:49:43 -07001424#if DEBUG_FOCUS
Jeff Brown01ce2e92010-09-26 22:20:12 -07001425 LOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d, "
1426 "timeSpentWaitingForApplication=%0.1fms",
Jeff Brown519e0242010-09-15 15:18:56 -07001427 injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0);
Jeff Brownb88102f2010-09-08 11:49:43 -07001428#endif
1429 return injectionResult;
1430}
1431
Jeff Brown01ce2e92010-09-26 22:20:12 -07001432void InputDispatcher::addWindowTargetLocked(const InputWindow* window, int32_t targetFlags,
1433 BitSet32 pointerIds) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001434 mCurrentInputTargets.push();
1435
1436 InputTarget& target = mCurrentInputTargets.editTop();
1437 target.inputChannel = window->inputChannel;
1438 target.flags = targetFlags;
Jeff Brownb88102f2010-09-08 11:49:43 -07001439 target.xOffset = - window->frameLeft;
1440 target.yOffset = - window->frameTop;
Jeff Brown01ce2e92010-09-26 22:20:12 -07001441 target.pointerIds = pointerIds;
Jeff Brownb88102f2010-09-08 11:49:43 -07001442}
1443
1444void InputDispatcher::addMonitoringTargetsLocked() {
1445 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
1446 mCurrentInputTargets.push();
1447
1448 InputTarget& target = mCurrentInputTargets.editTop();
1449 target.inputChannel = mMonitoringChannels[i];
1450 target.flags = 0;
Jeff Brownb88102f2010-09-08 11:49:43 -07001451 target.xOffset = 0;
1452 target.yOffset = 0;
1453 }
1454}
1455
1456bool InputDispatcher::checkInjectionPermission(const InputWindow* window,
Jeff Brown01ce2e92010-09-26 22:20:12 -07001457 const InjectionState* injectionState) {
1458 if (injectionState
Jeff Brownb6997262010-10-08 22:31:17 -07001459 && (window == NULL || window->ownerUid != injectionState->injectorUid)
1460 && !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
1461 if (window) {
1462 LOGW("Permission denied: injecting event from pid %d uid %d to window "
1463 "with input channel %s owned by uid %d",
1464 injectionState->injectorPid, injectionState->injectorUid,
1465 window->inputChannel->getName().string(),
1466 window->ownerUid);
1467 } else {
1468 LOGW("Permission denied: injecting event from pid %d uid %d",
1469 injectionState->injectorPid, injectionState->injectorUid);
Jeff Brownb88102f2010-09-08 11:49:43 -07001470 }
Jeff Brownb6997262010-10-08 22:31:17 -07001471 return false;
Jeff Brownb88102f2010-09-08 11:49:43 -07001472 }
1473 return true;
1474}
1475
Jeff Brown19dfc832010-10-05 12:26:23 -07001476bool InputDispatcher::isWindowObscuredAtPointLocked(
1477 const InputWindow* window, int32_t x, int32_t y) const {
Jeff Brownb88102f2010-09-08 11:49:43 -07001478 size_t numWindows = mWindows.size();
1479 for (size_t i = 0; i < numWindows; i++) {
1480 const InputWindow* other = & mWindows.itemAt(i);
1481 if (other == window) {
1482 break;
1483 }
Jeff Brown19dfc832010-10-05 12:26:23 -07001484 if (other->visible && ! other->isTrustedOverlay() && other->frameContainsPoint(x, y)) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001485 return true;
1486 }
1487 }
1488 return false;
1489}
1490
Jeff Brown519e0242010-09-15 15:18:56 -07001491bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(const InputWindow* window) {
1492 ssize_t connectionIndex = getConnectionIndexLocked(window->inputChannel);
1493 if (connectionIndex >= 0) {
1494 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
1495 return connection->outboundQueue.isEmpty();
1496 } else {
1497 return true;
1498 }
1499}
1500
1501String8 InputDispatcher::getApplicationWindowLabelLocked(const InputApplication* application,
1502 const InputWindow* window) {
1503 if (application) {
1504 if (window) {
1505 String8 label(application->name);
1506 label.append(" - ");
1507 label.append(window->name);
1508 return label;
1509 } else {
1510 return application->name;
1511 }
1512 } else if (window) {
1513 return window->name;
1514 } else {
1515 return String8("<unknown application or window>");
1516 }
1517}
1518
Jeff Browne2fe69e2010-10-18 13:21:23 -07001519void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
1520 int32_t eventType = POWER_MANAGER_BUTTON_EVENT;
Jeff Brown4d396052010-10-29 21:50:21 -07001521 switch (eventEntry->type) {
1522 case EventEntry::TYPE_MOTION: {
Jeff Browne2fe69e2010-10-18 13:21:23 -07001523 const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
Jeff Brown4d396052010-10-29 21:50:21 -07001524 if (motionEntry->action == AMOTION_EVENT_ACTION_CANCEL) {
1525 return;
1526 }
1527
Jeff Browne2fe69e2010-10-18 13:21:23 -07001528 if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
Joe Onorato1a542c72010-11-08 09:48:20 -08001529 eventType = POWER_MANAGER_TOUCH_EVENT;
Jeff Brown01ce2e92010-09-26 22:20:12 -07001530 }
Jeff Brown4d396052010-10-29 21:50:21 -07001531 break;
1532 }
1533 case EventEntry::TYPE_KEY: {
1534 const KeyEntry* keyEntry = static_cast<const KeyEntry*>(eventEntry);
1535 if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
1536 return;
1537 }
1538 break;
1539 }
Jeff Brown01ce2e92010-09-26 22:20:12 -07001540 }
Jeff Brown01ce2e92010-09-26 22:20:12 -07001541
Jeff Brownb88102f2010-09-08 11:49:43 -07001542 CommandEntry* commandEntry = postCommandLocked(
1543 & InputDispatcher::doPokeUserActivityLockedInterruptible);
Jeff Browne2fe69e2010-10-18 13:21:23 -07001544 commandEntry->eventTime = eventEntry->eventTime;
Jeff Brownb88102f2010-09-08 11:49:43 -07001545 commandEntry->userActivityEventType = eventType;
1546}
1547
Jeff Brown7fbdc842010-06-17 20:52:56 -07001548void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
1549 const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001550 bool resumeWithAppendedMotionSample) {
1551#if DEBUG_DISPATCH_CYCLE
Jeff Brown519e0242010-09-15 15:18:56 -07001552 LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, "
Jeff Brown01ce2e92010-09-26 22:20:12 -07001553 "xOffset=%f, yOffset=%f, "
Jeff Brown83c09682010-12-23 17:50:18 -08001554 "pointerIds=0x%x, "
Jeff Brown01ce2e92010-09-26 22:20:12 -07001555 "resumeWithAppendedMotionSample=%s",
Jeff Brown519e0242010-09-15 15:18:56 -07001556 connection->getInputChannelName(), inputTarget->flags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001557 inputTarget->xOffset, inputTarget->yOffset,
Jeff Brown83c09682010-12-23 17:50:18 -08001558 inputTarget->pointerIds.value,
Jeff Brownb88102f2010-09-08 11:49:43 -07001559 toString(resumeWithAppendedMotionSample));
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001560#endif
1561
Jeff Brown01ce2e92010-09-26 22:20:12 -07001562 // Make sure we are never called for streaming when splitting across multiple windows.
1563 bool isSplit = inputTarget->flags & InputTarget::FLAG_SPLIT;
1564 assert(! (resumeWithAppendedMotionSample && isSplit));
1565
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001566 // Skip this event if the connection status is not normal.
Jeff Brown519e0242010-09-15 15:18:56 -07001567 // We don't want to enqueue additional outbound events if the connection is broken.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001568 if (connection->status != Connection::STATUS_NORMAL) {
Jeff Brownb6997262010-10-08 22:31:17 -07001569#if DEBUG_DISPATCH_CYCLE
1570 LOGD("channel '%s' ~ Dropping event because the channel status is %s",
Jeff Brownb88102f2010-09-08 11:49:43 -07001571 connection->getInputChannelName(), connection->getStatusLabel());
Jeff Brownb6997262010-10-08 22:31:17 -07001572#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001573 return;
1574 }
1575
Jeff Brown01ce2e92010-09-26 22:20:12 -07001576 // Split a motion event if needed.
1577 if (isSplit) {
1578 assert(eventEntry->type == EventEntry::TYPE_MOTION);
1579
1580 MotionEntry* originalMotionEntry = static_cast<MotionEntry*>(eventEntry);
1581 if (inputTarget->pointerIds.count() != originalMotionEntry->pointerCount) {
1582 MotionEntry* splitMotionEntry = splitMotionEvent(
1583 originalMotionEntry, inputTarget->pointerIds);
1584#if DEBUG_FOCUS
1585 LOGD("channel '%s' ~ Split motion event.",
1586 connection->getInputChannelName());
1587 logOutboundMotionDetailsLocked(" ", splitMotionEntry);
1588#endif
1589 eventEntry = splitMotionEntry;
1590 }
1591 }
1592
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001593 // Resume the dispatch cycle with a freshly appended motion sample.
1594 // First we check that the last dispatch entry in the outbound queue is for the same
1595 // motion event to which we appended the motion sample. If we find such a dispatch
1596 // entry, and if it is currently in progress then we try to stream the new sample.
1597 bool wasEmpty = connection->outboundQueue.isEmpty();
1598
1599 if (! wasEmpty && resumeWithAppendedMotionSample) {
1600 DispatchEntry* motionEventDispatchEntry =
1601 connection->findQueuedDispatchEntryForEvent(eventEntry);
1602 if (motionEventDispatchEntry) {
1603 // If the dispatch entry is not in progress, then we must be busy dispatching an
1604 // earlier event. Not a problem, the motion event is on the outbound queue and will
1605 // be dispatched later.
1606 if (! motionEventDispatchEntry->inProgress) {
1607#if DEBUG_BATCHING
1608 LOGD("channel '%s' ~ Not streaming because the motion event has "
1609 "not yet been dispatched. "
1610 "(Waiting for earlier events to be consumed.)",
1611 connection->getInputChannelName());
1612#endif
1613 return;
1614 }
1615
1616 // If the dispatch entry is in progress but it already has a tail of pending
1617 // motion samples, then it must mean that the shared memory buffer filled up.
1618 // Not a problem, when this dispatch cycle is finished, we will eventually start
1619 // a new dispatch cycle to process the tail and that tail includes the newly
1620 // appended motion sample.
1621 if (motionEventDispatchEntry->tailMotionSample) {
1622#if DEBUG_BATCHING
1623 LOGD("channel '%s' ~ Not streaming because no new samples can "
1624 "be appended to the motion event in this dispatch cycle. "
1625 "(Waiting for next dispatch cycle to start.)",
1626 connection->getInputChannelName());
1627#endif
1628 return;
1629 }
1630
1631 // The dispatch entry is in progress and is still potentially open for streaming.
1632 // Try to stream the new motion sample. This might fail if the consumer has already
1633 // consumed the motion event (or if the channel is broken).
Jeff Brown01ce2e92010-09-26 22:20:12 -07001634 MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
1635 MotionSample* appendedMotionSample = motionEntry->lastSample;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001636 status_t status = connection->inputPublisher.appendMotionSample(
1637 appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
1638 if (status == OK) {
1639#if DEBUG_BATCHING
1640 LOGD("channel '%s' ~ Successfully streamed new motion sample.",
1641 connection->getInputChannelName());
1642#endif
1643 return;
1644 }
1645
1646#if DEBUG_BATCHING
1647 if (status == NO_MEMORY) {
1648 LOGD("channel '%s' ~ Could not append motion sample to currently "
1649 "dispatched move event because the shared memory buffer is full. "
1650 "(Waiting for next dispatch cycle to start.)",
1651 connection->getInputChannelName());
1652 } else if (status == status_t(FAILED_TRANSACTION)) {
1653 LOGD("channel '%s' ~ Could not append motion sample to currently "
Jeff Brown349703e2010-06-22 01:27:15 -07001654 "dispatched move event because the event has already been consumed. "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001655 "(Waiting for next dispatch cycle to start.)",
1656 connection->getInputChannelName());
1657 } else {
1658 LOGD("channel '%s' ~ Could not append motion sample to currently "
1659 "dispatched move event due to an error, status=%d. "
1660 "(Waiting for next dispatch cycle to start.)",
1661 connection->getInputChannelName(), status);
1662 }
1663#endif
1664 // Failed to stream. Start a new tail of pending motion samples to dispatch
1665 // in the next cycle.
1666 motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
1667 return;
1668 }
1669 }
1670
1671 // This is a new event.
1672 // Enqueue a new dispatch entry onto the outbound queue for this connection.
Jeff Brownb88102f2010-09-08 11:49:43 -07001673 DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry, // increments ref
Jeff Brown519e0242010-09-15 15:18:56 -07001674 inputTarget->flags, inputTarget->xOffset, inputTarget->yOffset);
1675 if (dispatchEntry->hasForegroundTarget()) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07001676 incrementPendingForegroundDispatchesLocked(eventEntry);
Jeff Brown6ec402b2010-07-28 15:48:59 -07001677 }
1678
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001679 // Handle the case where we could not stream a new motion sample because the consumer has
1680 // already consumed the motion event (otherwise the corresponding dispatch entry would
1681 // still be in the outbound queue for this connection). We set the head motion sample
1682 // to the list starting with the newly appended motion sample.
1683 if (resumeWithAppendedMotionSample) {
1684#if DEBUG_BATCHING
1685 LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
1686 "that cannot be streamed because the motion event has already been consumed.",
1687 connection->getInputChannelName());
1688#endif
1689 MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
1690 dispatchEntry->headMotionSample = appendedMotionSample;
1691 }
1692
1693 // Enqueue the dispatch entry.
1694 connection->outboundQueue.enqueueAtTail(dispatchEntry);
1695
1696 // If the outbound queue was previously empty, start the dispatch cycle going.
1697 if (wasEmpty) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001698 activateConnectionLocked(connection.get());
Jeff Brown519e0242010-09-15 15:18:56 -07001699 startDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001700 }
1701}
1702
Jeff Brown7fbdc842010-06-17 20:52:56 -07001703void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
Jeff Brown519e0242010-09-15 15:18:56 -07001704 const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001705#if DEBUG_DISPATCH_CYCLE
1706 LOGD("channel '%s' ~ startDispatchCycle",
1707 connection->getInputChannelName());
1708#endif
1709
1710 assert(connection->status == Connection::STATUS_NORMAL);
1711 assert(! connection->outboundQueue.isEmpty());
1712
Jeff Brownb88102f2010-09-08 11:49:43 -07001713 DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001714 assert(! dispatchEntry->inProgress);
1715
Jeff Brownb88102f2010-09-08 11:49:43 -07001716 // Mark the dispatch entry as in progress.
1717 dispatchEntry->inProgress = true;
1718
1719 // Update the connection's input state.
Jeff Brown01ce2e92010-09-26 22:20:12 -07001720 EventEntry* eventEntry = dispatchEntry->eventEntry;
1721 InputState::Consistency consistency = connection->inputState.trackEvent(eventEntry);
Jeff Brownb88102f2010-09-08 11:49:43 -07001722
1723#if FILTER_INPUT_EVENTS
1724 // Filter out inconsistent sequences of input events.
1725 // The input system may drop or inject events in a way that could violate implicit
1726 // invariants on input state and potentially cause an application to crash
1727 // or think that a key or pointer is stuck down. Technically we make no guarantees
1728 // of consistency but it would be nice to improve on this where possible.
1729 // XXX: This code is a proof of concept only. Not ready for prime time.
1730 if (consistency == InputState::TOLERABLE) {
1731#if DEBUG_DISPATCH_CYCLE
1732 LOGD("channel '%s' ~ Sending an event that is inconsistent with the connection's "
1733 "current input state but that is likely to be tolerated by the application.",
1734 connection->getInputChannelName());
1735#endif
1736 } else if (consistency == InputState::BROKEN) {
1737 LOGI("channel '%s' ~ Dropping an event that is inconsistent with the connection's "
1738 "current input state and that is likely to cause the application to crash.",
1739 connection->getInputChannelName());
1740 startNextDispatchCycleLocked(currentTime, connection);
1741 return;
1742 }
1743#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001744
1745 // Publish the event.
1746 status_t status;
Jeff Brown01ce2e92010-09-26 22:20:12 -07001747 switch (eventEntry->type) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001748 case EventEntry::TYPE_KEY: {
Jeff Brown01ce2e92010-09-26 22:20:12 -07001749 KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001750
1751 // Apply target flags.
1752 int32_t action = keyEntry->action;
1753 int32_t flags = keyEntry->flags;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001754
1755 // Publish the key event.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001756 status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001757 action, flags, keyEntry->keyCode, keyEntry->scanCode,
1758 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
1759 keyEntry->eventTime);
1760
1761 if (status) {
1762 LOGE("channel '%s' ~ Could not publish key event, "
1763 "status=%d", connection->getInputChannelName(), status);
Jeff Brownb6997262010-10-08 22:31:17 -07001764 abortBrokenDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001765 return;
1766 }
1767 break;
1768 }
1769
1770 case EventEntry::TYPE_MOTION: {
Jeff Brown01ce2e92010-09-26 22:20:12 -07001771 MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001772
1773 // Apply target flags.
1774 int32_t action = motionEntry->action;
Jeff Brown85a31762010-09-01 17:01:00 -07001775 int32_t flags = motionEntry->flags;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001776 if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001777 action = AMOTION_EVENT_ACTION_OUTSIDE;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001778 }
Jeff Brown85a31762010-09-01 17:01:00 -07001779 if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
1780 flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
1781 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001782
1783 // If headMotionSample is non-NULL, then it points to the first new sample that we
1784 // were unable to dispatch during the previous cycle so we resume dispatching from
1785 // that point in the list of motion samples.
1786 // Otherwise, we just start from the first sample of the motion event.
1787 MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
1788 if (! firstMotionSample) {
1789 firstMotionSample = & motionEntry->firstSample;
1790 }
1791
Jeff Brownd3616592010-07-16 17:21:06 -07001792 // Set the X and Y offset depending on the input source.
1793 float xOffset, yOffset;
1794 if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
1795 xOffset = dispatchEntry->xOffset;
1796 yOffset = dispatchEntry->yOffset;
1797 } else {
1798 xOffset = 0.0f;
1799 yOffset = 0.0f;
1800 }
1801
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001802 // Publish the motion event and the first motion sample.
1803 status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
Jeff Brown85a31762010-09-01 17:01:00 -07001804 motionEntry->source, action, flags, motionEntry->edgeFlags, motionEntry->metaState,
Jeff Brownd3616592010-07-16 17:21:06 -07001805 xOffset, yOffset,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001806 motionEntry->xPrecision, motionEntry->yPrecision,
1807 motionEntry->downTime, firstMotionSample->eventTime,
1808 motionEntry->pointerCount, motionEntry->pointerIds,
1809 firstMotionSample->pointerCoords);
1810
1811 if (status) {
1812 LOGE("channel '%s' ~ Could not publish motion event, "
1813 "status=%d", connection->getInputChannelName(), status);
Jeff Brownb6997262010-10-08 22:31:17 -07001814 abortBrokenDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001815 return;
1816 }
1817
1818 // Append additional motion samples.
1819 MotionSample* nextMotionSample = firstMotionSample->next;
1820 for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
1821 status = connection->inputPublisher.appendMotionSample(
1822 nextMotionSample->eventTime, nextMotionSample->pointerCoords);
1823 if (status == NO_MEMORY) {
1824#if DEBUG_DISPATCH_CYCLE
1825 LOGD("channel '%s' ~ Shared memory buffer full. Some motion samples will "
1826 "be sent in the next dispatch cycle.",
1827 connection->getInputChannelName());
1828#endif
1829 break;
1830 }
1831 if (status != OK) {
1832 LOGE("channel '%s' ~ Could not append motion sample "
1833 "for a reason other than out of memory, status=%d",
1834 connection->getInputChannelName(), status);
Jeff Brownb6997262010-10-08 22:31:17 -07001835 abortBrokenDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001836 return;
1837 }
1838 }
1839
1840 // Remember the next motion sample that we could not dispatch, in case we ran out
1841 // of space in the shared memory buffer.
1842 dispatchEntry->tailMotionSample = nextMotionSample;
1843 break;
1844 }
1845
1846 default: {
1847 assert(false);
1848 }
1849 }
1850
1851 // Send the dispatch signal.
1852 status = connection->inputPublisher.sendDispatchSignal();
1853 if (status) {
1854 LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
1855 connection->getInputChannelName(), status);
Jeff Brownb6997262010-10-08 22:31:17 -07001856 abortBrokenDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001857 return;
1858 }
1859
1860 // Record information about the newly started dispatch cycle.
Jeff Brown01ce2e92010-09-26 22:20:12 -07001861 connection->lastEventTime = eventEntry->eventTime;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001862 connection->lastDispatchTime = currentTime;
1863
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001864 // Notify other system components.
1865 onDispatchCycleStartedLocked(currentTime, connection);
1866}
1867
Jeff Brown7fbdc842010-06-17 20:52:56 -07001868void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
Jeff Brown3915bb82010-11-05 15:02:16 -07001869 const sp<Connection>& connection, bool handled) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001870#if DEBUG_DISPATCH_CYCLE
Jeff Brown9c3cda02010-06-15 01:31:58 -07001871 LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
Jeff Brown3915bb82010-11-05 15:02:16 -07001872 "%01.1fms since dispatch, handled=%s",
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001873 connection->getInputChannelName(),
1874 connection->getEventLatencyMillis(currentTime),
Jeff Brown3915bb82010-11-05 15:02:16 -07001875 connection->getDispatchLatencyMillis(currentTime),
1876 toString(handled));
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001877#endif
1878
Jeff Brown9c3cda02010-06-15 01:31:58 -07001879 if (connection->status == Connection::STATUS_BROKEN
1880 || connection->status == Connection::STATUS_ZOMBIE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001881 return;
1882 }
1883
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001884 // Reset the publisher since the event has been consumed.
1885 // We do this now so that the publisher can release some of its internal resources
1886 // while waiting for the next dispatch cycle to begin.
1887 status_t status = connection->inputPublisher.reset();
1888 if (status) {
1889 LOGE("channel '%s' ~ Could not reset publisher, status=%d",
1890 connection->getInputChannelName(), status);
Jeff Brownb6997262010-10-08 22:31:17 -07001891 abortBrokenDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001892 return;
1893 }
1894
Jeff Brown3915bb82010-11-05 15:02:16 -07001895 // Notify other system components and prepare to start the next dispatch cycle.
1896 onDispatchCycleFinishedLocked(currentTime, connection, handled);
Jeff Brownb88102f2010-09-08 11:49:43 -07001897}
1898
1899void InputDispatcher::startNextDispatchCycleLocked(nsecs_t currentTime,
1900 const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001901 // Start the next dispatch cycle for this connection.
1902 while (! connection->outboundQueue.isEmpty()) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001903 DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001904 if (dispatchEntry->inProgress) {
1905 // Finish or resume current event in progress.
1906 if (dispatchEntry->tailMotionSample) {
1907 // We have a tail of undispatched motion samples.
1908 // Reuse the same DispatchEntry and start a new cycle.
1909 dispatchEntry->inProgress = false;
1910 dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
1911 dispatchEntry->tailMotionSample = NULL;
Jeff Brown519e0242010-09-15 15:18:56 -07001912 startDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001913 return;
1914 }
1915 // Finished.
1916 connection->outboundQueue.dequeueAtHead();
Jeff Brown519e0242010-09-15 15:18:56 -07001917 if (dispatchEntry->hasForegroundTarget()) {
1918 decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
Jeff Brown6ec402b2010-07-28 15:48:59 -07001919 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001920 mAllocator.releaseDispatchEntry(dispatchEntry);
1921 } else {
1922 // If the head is not in progress, then we must have already dequeued the in
Jeff Brown519e0242010-09-15 15:18:56 -07001923 // progress event, which means we actually aborted it.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001924 // So just start the next event for this connection.
Jeff Brown519e0242010-09-15 15:18:56 -07001925 startDispatchCycleLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001926 return;
1927 }
1928 }
1929
1930 // Outbound queue is empty, deactivate the connection.
Jeff Brown7fbdc842010-06-17 20:52:56 -07001931 deactivateConnectionLocked(connection.get());
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001932}
1933
Jeff Brownb6997262010-10-08 22:31:17 -07001934void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
1935 const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001936#if DEBUG_DISPATCH_CYCLE
Jeff Brown83c09682010-12-23 17:50:18 -08001937 LOGD("channel '%s' ~ abortBrokenDispatchCycle",
1938 connection->getInputChannelName());
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001939#endif
1940
Jeff Brownb88102f2010-09-08 11:49:43 -07001941 // Clear the outbound queue.
Jeff Brown519e0242010-09-15 15:18:56 -07001942 drainOutboundQueueLocked(connection.get());
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001943
Jeff Brownb6997262010-10-08 22:31:17 -07001944 // The connection appears to be unrecoverably broken.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001945 // Ignore already broken or zombie connections.
Jeff Brownb6997262010-10-08 22:31:17 -07001946 if (connection->status == Connection::STATUS_NORMAL) {
1947 connection->status = Connection::STATUS_BROKEN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001948
Jeff Brownb6997262010-10-08 22:31:17 -07001949 // Notify other system components.
1950 onDispatchCycleBrokenLocked(currentTime, connection);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001951 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001952}
1953
Jeff Brown519e0242010-09-15 15:18:56 -07001954void InputDispatcher::drainOutboundQueueLocked(Connection* connection) {
1955 while (! connection->outboundQueue.isEmpty()) {
1956 DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
1957 if (dispatchEntry->hasForegroundTarget()) {
1958 decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
Jeff Brownb88102f2010-09-08 11:49:43 -07001959 }
1960 mAllocator.releaseDispatchEntry(dispatchEntry);
Jeff Brownb88102f2010-09-08 11:49:43 -07001961 }
1962
Jeff Brown519e0242010-09-15 15:18:56 -07001963 deactivateConnectionLocked(connection);
Jeff Brownb88102f2010-09-08 11:49:43 -07001964}
1965
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001966int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001967 InputDispatcher* d = static_cast<InputDispatcher*>(data);
1968
1969 { // acquire lock
1970 AutoMutex _l(d->mLock);
1971
1972 ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
1973 if (connectionIndex < 0) {
1974 LOGE("Received spurious receive callback for unknown input channel. "
1975 "fd=%d, events=0x%x", receiveFd, events);
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001976 return 0; // remove the callback
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001977 }
1978
Jeff Brown7fbdc842010-06-17 20:52:56 -07001979 nsecs_t currentTime = now();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001980
1981 sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001982 if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001983 LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
1984 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brownb6997262010-10-08 22:31:17 -07001985 d->abortBrokenDispatchCycleLocked(currentTime, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001986 d->runCommandsLockedInterruptible();
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001987 return 0; // remove the callback
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001988 }
1989
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001990 if (! (events & ALOOPER_EVENT_INPUT)) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001991 LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
1992 "events=0x%x", connection->getInputChannelName(), events);
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001993 return 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001994 }
1995
Jeff Brown3915bb82010-11-05 15:02:16 -07001996 bool handled = false;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001997 status_t status = connection->inputPublisher.receiveFinishedSignal(&handled);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001998 if (status) {
1999 LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
2000 connection->getInputChannelName(), status);
Jeff Brownb6997262010-10-08 22:31:17 -07002001 d->abortBrokenDispatchCycleLocked(currentTime, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -07002002 d->runCommandsLockedInterruptible();
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002003 return 0; // remove the callback
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002004 }
2005
Jeff Brown3915bb82010-11-05 15:02:16 -07002006 d->finishDispatchCycleLocked(currentTime, connection, handled);
Jeff Brown9c3cda02010-06-15 01:31:58 -07002007 d->runCommandsLockedInterruptible();
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002008 return 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002009 } // release lock
2010}
2011
Jeff Brownb6997262010-10-08 22:31:17 -07002012void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked(
2013 InputState::CancelationOptions options, const char* reason) {
2014 for (size_t i = 0; i < mConnectionsByReceiveFd.size(); i++) {
2015 synthesizeCancelationEventsForConnectionLocked(
2016 mConnectionsByReceiveFd.valueAt(i), options, reason);
2017 }
2018}
2019
2020void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked(
2021 const sp<InputChannel>& channel, InputState::CancelationOptions options,
2022 const char* reason) {
2023 ssize_t index = getConnectionIndexLocked(channel);
2024 if (index >= 0) {
2025 synthesizeCancelationEventsForConnectionLocked(
2026 mConnectionsByReceiveFd.valueAt(index), options, reason);
2027 }
2028}
2029
2030void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
2031 const sp<Connection>& connection, InputState::CancelationOptions options,
2032 const char* reason) {
2033 nsecs_t currentTime = now();
2034
2035 mTempCancelationEvents.clear();
2036 connection->inputState.synthesizeCancelationEvents(currentTime, & mAllocator,
2037 mTempCancelationEvents, options);
2038
2039 if (! mTempCancelationEvents.isEmpty()
2040 && connection->status != Connection::STATUS_BROKEN) {
2041#if DEBUG_OUTBOUND_EVENT_DETAILS
2042 LOGD("channel '%s' ~ Synthesized %d cancelation events to bring channel back in sync "
2043 "with reality: %s, options=%d.",
2044 connection->getInputChannelName(), mTempCancelationEvents.size(), reason, options);
2045#endif
2046 for (size_t i = 0; i < mTempCancelationEvents.size(); i++) {
2047 EventEntry* cancelationEventEntry = mTempCancelationEvents.itemAt(i);
2048 switch (cancelationEventEntry->type) {
2049 case EventEntry::TYPE_KEY:
2050 logOutboundKeyDetailsLocked("cancel - ",
2051 static_cast<KeyEntry*>(cancelationEventEntry));
2052 break;
2053 case EventEntry::TYPE_MOTION:
2054 logOutboundMotionDetailsLocked("cancel - ",
2055 static_cast<MotionEntry*>(cancelationEventEntry));
2056 break;
2057 }
2058
2059 int32_t xOffset, yOffset;
2060 const InputWindow* window = getWindowLocked(connection->inputChannel);
2061 if (window) {
2062 xOffset = -window->frameLeft;
2063 yOffset = -window->frameTop;
2064 } else {
2065 xOffset = 0;
2066 yOffset = 0;
2067 }
2068
2069 DispatchEntry* cancelationDispatchEntry =
2070 mAllocator.obtainDispatchEntry(cancelationEventEntry, // increments ref
2071 0, xOffset, yOffset);
2072 connection->outboundQueue.enqueueAtTail(cancelationDispatchEntry);
2073
2074 mAllocator.releaseEventEntry(cancelationEventEntry);
2075 }
2076
2077 if (!connection->outboundQueue.headSentinel.next->inProgress) {
2078 startDispatchCycleLocked(currentTime, connection);
2079 }
2080 }
2081}
2082
Jeff Brown01ce2e92010-09-26 22:20:12 -07002083InputDispatcher::MotionEntry*
2084InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds) {
2085 assert(pointerIds.value != 0);
2086
2087 uint32_t splitPointerIndexMap[MAX_POINTERS];
2088 int32_t splitPointerIds[MAX_POINTERS];
2089 PointerCoords splitPointerCoords[MAX_POINTERS];
2090
2091 uint32_t originalPointerCount = originalMotionEntry->pointerCount;
2092 uint32_t splitPointerCount = 0;
2093
2094 for (uint32_t originalPointerIndex = 0; originalPointerIndex < originalPointerCount;
2095 originalPointerIndex++) {
2096 int32_t pointerId = uint32_t(originalMotionEntry->pointerIds[originalPointerIndex]);
2097 if (pointerIds.hasBit(pointerId)) {
2098 splitPointerIndexMap[splitPointerCount] = originalPointerIndex;
2099 splitPointerIds[splitPointerCount] = pointerId;
2100 splitPointerCoords[splitPointerCount] =
2101 originalMotionEntry->firstSample.pointerCoords[originalPointerIndex];
2102 splitPointerCount += 1;
2103 }
2104 }
2105 assert(splitPointerCount == pointerIds.count());
2106
2107 int32_t action = originalMotionEntry->action;
2108 int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
2109 if (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
2110 || maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
2111 int32_t originalPointerIndex = getMotionEventActionPointerIndex(action);
2112 int32_t pointerId = originalMotionEntry->pointerIds[originalPointerIndex];
2113 if (pointerIds.hasBit(pointerId)) {
2114 if (pointerIds.count() == 1) {
2115 // The first/last pointer went down/up.
2116 action = maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
2117 ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Brown9a01d052010-09-27 16:35:11 -07002118 } else {
2119 // A secondary pointer went down/up.
2120 uint32_t splitPointerIndex = 0;
2121 while (pointerId != splitPointerIds[splitPointerIndex]) {
2122 splitPointerIndex += 1;
2123 }
2124 action = maskedAction | (splitPointerIndex
2125 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Jeff Brown01ce2e92010-09-26 22:20:12 -07002126 }
2127 } else {
2128 // An unrelated pointer changed.
2129 action = AMOTION_EVENT_ACTION_MOVE;
2130 }
2131 }
2132
2133 MotionEntry* splitMotionEntry = mAllocator.obtainMotionEntry(
2134 originalMotionEntry->eventTime,
2135 originalMotionEntry->deviceId,
2136 originalMotionEntry->source,
2137 originalMotionEntry->policyFlags,
2138 action,
2139 originalMotionEntry->flags,
2140 originalMotionEntry->metaState,
2141 originalMotionEntry->edgeFlags,
2142 originalMotionEntry->xPrecision,
2143 originalMotionEntry->yPrecision,
2144 originalMotionEntry->downTime,
2145 splitPointerCount, splitPointerIds, splitPointerCoords);
2146
2147 for (MotionSample* originalMotionSample = originalMotionEntry->firstSample.next;
2148 originalMotionSample != NULL; originalMotionSample = originalMotionSample->next) {
2149 for (uint32_t splitPointerIndex = 0; splitPointerIndex < splitPointerCount;
2150 splitPointerIndex++) {
2151 uint32_t originalPointerIndex = splitPointerIndexMap[splitPointerIndex];
2152 splitPointerCoords[splitPointerIndex] =
2153 originalMotionSample->pointerCoords[originalPointerIndex];
2154 }
2155
2156 mAllocator.appendMotionSample(splitMotionEntry, originalMotionSample->eventTime,
2157 splitPointerCoords);
2158 }
2159
2160 return splitMotionEntry;
2161}
2162
Jeff Brown9c3cda02010-06-15 01:31:58 -07002163void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002164#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown9c3cda02010-06-15 01:31:58 -07002165 LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002166#endif
2167
Jeff Brownb88102f2010-09-08 11:49:43 -07002168 bool needWake;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002169 { // acquire lock
2170 AutoMutex _l(mLock);
2171
Jeff Brown7fbdc842010-06-17 20:52:56 -07002172 ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
Jeff Brownb88102f2010-09-08 11:49:43 -07002173 needWake = enqueueInboundEventLocked(newEntry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002174 } // release lock
2175
Jeff Brownb88102f2010-09-08 11:49:43 -07002176 if (needWake) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002177 mLooper->wake();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002178 }
2179}
2180
Jeff Brownc5ed5912010-07-14 18:48:53 -07002181void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002182 uint32_t policyFlags, int32_t action, int32_t flags,
2183 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
2184#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown90655042010-12-02 13:50:46 -08002185 LOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, "
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002186 "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
Jeff Brownc5ed5912010-07-14 18:48:53 -07002187 eventTime, deviceId, source, policyFlags, action, flags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002188 keyCode, scanCode, metaState, downTime);
2189#endif
Jeff Brown01ce2e92010-09-26 22:20:12 -07002190 if (! validateKeyEvent(action)) {
2191 return;
2192 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002193
Jeff Brown1f245102010-11-18 20:53:46 -08002194 if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
2195 policyFlags |= POLICY_FLAG_VIRTUAL;
2196 flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2197 }
2198
Jeff Browne20c9e02010-10-11 14:20:19 -07002199 policyFlags |= POLICY_FLAG_TRUSTED;
Jeff Brown1f245102010-11-18 20:53:46 -08002200
2201 KeyEvent event;
2202 event.initialize(deviceId, source, action, flags, keyCode, scanCode,
2203 metaState, 0, downTime, eventTime);
2204
2205 mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
2206
2207 if (policyFlags & POLICY_FLAG_WOKE_HERE) {
2208 flags |= AKEY_EVENT_FLAG_WOKE_HERE;
2209 }
Jeff Brownb6997262010-10-08 22:31:17 -07002210
Jeff Brownb88102f2010-09-08 11:49:43 -07002211 bool needWake;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002212 { // acquire lock
2213 AutoMutex _l(mLock);
2214
Jeff Brown7fbdc842010-06-17 20:52:56 -07002215 int32_t repeatCount = 0;
2216 KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -07002217 deviceId, source, policyFlags, action, flags, keyCode, scanCode,
Jeff Brown7fbdc842010-06-17 20:52:56 -07002218 metaState, repeatCount, downTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002219
Jeff Brownb88102f2010-09-08 11:49:43 -07002220 needWake = enqueueInboundEventLocked(newEntry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002221 } // release lock
2222
Jeff Brownb88102f2010-09-08 11:49:43 -07002223 if (needWake) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002224 mLooper->wake();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002225 }
2226}
2227
Jeff Brownc5ed5912010-07-14 18:48:53 -07002228void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
Jeff Brown85a31762010-09-01 17:01:00 -07002229 uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t edgeFlags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002230 uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
2231 float xPrecision, float yPrecision, nsecs_t downTime) {
2232#if DEBUG_INBOUND_EVENT_DETAILS
Jeff Brown90655042010-12-02 13:50:46 -08002233 LOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
Jeff Brown85a31762010-09-01 17:01:00 -07002234 "action=0x%x, flags=0x%x, metaState=0x%x, edgeFlags=0x%x, "
2235 "xPrecision=%f, yPrecision=%f, downTime=%lld",
2236 eventTime, deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002237 xPrecision, yPrecision, downTime);
2238 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Brown8d608662010-08-30 03:02:23 -07002239 LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
Jeff Brown85a31762010-09-01 17:01:00 -07002240 "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
Jeff Brown8d608662010-08-30 03:02:23 -07002241 "orientation=%f",
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002242 i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
Jeff Brown8d608662010-08-30 03:02:23 -07002243 pointerCoords[i].pressure, pointerCoords[i].size,
2244 pointerCoords[i].touchMajor, pointerCoords[i].touchMinor,
2245 pointerCoords[i].toolMajor, pointerCoords[i].toolMinor,
2246 pointerCoords[i].orientation);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002247 }
2248#endif
Jeff Brown01ce2e92010-09-26 22:20:12 -07002249 if (! validateMotionEvent(action, pointerCount, pointerIds)) {
2250 return;
2251 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002252
Jeff Browne20c9e02010-10-11 14:20:19 -07002253 policyFlags |= POLICY_FLAG_TRUSTED;
Jeff Brownb6997262010-10-08 22:31:17 -07002254 mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
2255
Jeff Brownb88102f2010-09-08 11:49:43 -07002256 bool needWake;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002257 { // acquire lock
2258 AutoMutex _l(mLock);
2259
2260 // Attempt batching and streaming of move events.
Jeff Brownc5ed5912010-07-14 18:48:53 -07002261 if (action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002262 // BATCHING CASE
2263 //
2264 // Try to append a move sample to the tail of the inbound queue for this device.
2265 // Give up if we encounter a non-move motion event for this device since that
2266 // means we cannot append any new samples until a new motion event has started.
Jeff Brownb88102f2010-09-08 11:49:43 -07002267 for (EventEntry* entry = mInboundQueue.tailSentinel.prev;
2268 entry != & mInboundQueue.headSentinel; entry = entry->prev) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002269 if (entry->type != EventEntry::TYPE_MOTION) {
2270 // Keep looking for motion events.
2271 continue;
2272 }
2273
2274 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
2275 if (motionEntry->deviceId != deviceId) {
2276 // Keep looking for this device.
2277 continue;
2278 }
2279
Jeff Brownc5ed5912010-07-14 18:48:53 -07002280 if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
Jeff Brown7fbdc842010-06-17 20:52:56 -07002281 || motionEntry->pointerCount != pointerCount
2282 || motionEntry->isInjected()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002283 // Last motion event in the queue for this device is not compatible for
2284 // appending new samples. Stop here.
2285 goto NoBatchingOrStreaming;
2286 }
2287
2288 // The last motion event is a move and is compatible for appending.
Jeff Brown9c3cda02010-06-15 01:31:58 -07002289 // Do the batching magic.
Jeff Brown7fbdc842010-06-17 20:52:56 -07002290 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002291#if DEBUG_BATCHING
2292 LOGD("Appended motion sample onto batch for most recent "
2293 "motion event for this device in the inbound queue.");
2294#endif
Jeff Brown9c3cda02010-06-15 01:31:58 -07002295 return; // done!
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002296 }
2297
2298 // STREAMING CASE
2299 //
2300 // There is no pending motion event (of any kind) for this device in the inbound queue.
Jeff Brown519e0242010-09-15 15:18:56 -07002301 // Search the outbound queue for the current foreground targets to find a dispatched
2302 // motion event that is still in progress. If found, then, appen the new sample to
2303 // that event and push it out to all current targets. The logic in
2304 // prepareDispatchCycleLocked takes care of the case where some targets may
2305 // already have consumed the motion event by starting a new dispatch cycle if needed.
Jeff Brown9c3cda02010-06-15 01:31:58 -07002306 if (mCurrentInputTargetsValid) {
Jeff Brown519e0242010-09-15 15:18:56 -07002307 for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
2308 const InputTarget& inputTarget = mCurrentInputTargets[i];
2309 if ((inputTarget.flags & InputTarget::FLAG_FOREGROUND) == 0) {
2310 // Skip non-foreground targets. We only want to stream if there is at
2311 // least one foreground target whose dispatch is still in progress.
2312 continue;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002313 }
Jeff Brown519e0242010-09-15 15:18:56 -07002314
2315 ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
2316 if (connectionIndex < 0) {
2317 // Connection must no longer be valid.
2318 continue;
2319 }
2320
2321 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
2322 if (connection->outboundQueue.isEmpty()) {
2323 // This foreground target has an empty outbound queue.
2324 continue;
2325 }
2326
2327 DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
2328 if (! dispatchEntry->inProgress
Jeff Brown01ce2e92010-09-26 22:20:12 -07002329 || dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION
2330 || dispatchEntry->isSplit()) {
2331 // No motion event is being dispatched, or it is being split across
2332 // windows in which case we cannot stream.
Jeff Brown519e0242010-09-15 15:18:56 -07002333 continue;
2334 }
2335
2336 MotionEntry* motionEntry = static_cast<MotionEntry*>(
2337 dispatchEntry->eventEntry);
2338 if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
2339 || motionEntry->deviceId != deviceId
2340 || motionEntry->pointerCount != pointerCount
2341 || motionEntry->isInjected()) {
2342 // The motion event is not compatible with this move.
2343 continue;
2344 }
2345
2346 // Hurray! This foreground target is currently dispatching a move event
2347 // that we can stream onto. Append the motion sample and resume dispatch.
2348 mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
2349#if DEBUG_BATCHING
2350 LOGD("Appended motion sample onto batch for most recently dispatched "
2351 "motion event for this device in the outbound queues. "
2352 "Attempting to stream the motion sample.");
2353#endif
2354 nsecs_t currentTime = now();
2355 dispatchEventToCurrentInputTargetsLocked(currentTime, motionEntry,
2356 true /*resumeWithAppendedMotionSample*/);
2357
2358 runCommandsLockedInterruptible();
2359 return; // done!
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002360 }
2361 }
2362
2363NoBatchingOrStreaming:;
2364 }
2365
2366 // Just enqueue a new motion event.
Jeff Brown7fbdc842010-06-17 20:52:56 -07002367 MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
Jeff Brown85a31762010-09-01 17:01:00 -07002368 deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -07002369 xPrecision, yPrecision, downTime,
2370 pointerCount, pointerIds, pointerCoords);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002371
Jeff Brownb88102f2010-09-08 11:49:43 -07002372 needWake = enqueueInboundEventLocked(newEntry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002373 } // release lock
2374
Jeff Brownb88102f2010-09-08 11:49:43 -07002375 if (needWake) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002376 mLooper->wake();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002377 }
2378}
2379
Jeff Brownb6997262010-10-08 22:31:17 -07002380void InputDispatcher::notifySwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
2381 uint32_t policyFlags) {
2382#if DEBUG_INBOUND_EVENT_DETAILS
2383 LOGD("notifySwitch - switchCode=%d, switchValue=%d, policyFlags=0x%x",
2384 switchCode, switchValue, policyFlags);
2385#endif
2386
Jeff Browne20c9e02010-10-11 14:20:19 -07002387 policyFlags |= POLICY_FLAG_TRUSTED;
Jeff Brownb6997262010-10-08 22:31:17 -07002388 mPolicy->notifySwitch(when, switchCode, switchValue, policyFlags);
2389}
2390
Jeff Brown7fbdc842010-06-17 20:52:56 -07002391int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
Jeff Brown6ec402b2010-07-28 15:48:59 -07002392 int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07002393#if DEBUG_INBOUND_EVENT_DETAILS
2394 LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
Jeff Brown6ec402b2010-07-28 15:48:59 -07002395 "syncMode=%d, timeoutMillis=%d",
2396 event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002397#endif
2398
2399 nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
Jeff Browne20c9e02010-10-11 14:20:19 -07002400
2401 uint32_t policyFlags = POLICY_FLAG_INJECTED;
2402 if (hasInjectionPermission(injectorPid, injectorUid)) {
2403 policyFlags |= POLICY_FLAG_TRUSTED;
2404 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07002405
Jeff Brownb6997262010-10-08 22:31:17 -07002406 EventEntry* injectedEntry;
2407 switch (event->getType()) {
2408 case AINPUT_EVENT_TYPE_KEY: {
2409 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
2410 int32_t action = keyEvent->getAction();
2411 if (! validateKeyEvent(action)) {
Jeff Brownb88102f2010-09-08 11:49:43 -07002412 return INPUT_EVENT_INJECTION_FAILED;
2413 }
2414
Jeff Brownb6997262010-10-08 22:31:17 -07002415 int32_t flags = keyEvent->getFlags();
Jeff Brown1f245102010-11-18 20:53:46 -08002416 if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) {
2417 policyFlags |= POLICY_FLAG_VIRTUAL;
2418 }
2419
2420 mPolicy->interceptKeyBeforeQueueing(keyEvent, /*byref*/ policyFlags);
2421
2422 if (policyFlags & POLICY_FLAG_WOKE_HERE) {
2423 flags |= AKEY_EVENT_FLAG_WOKE_HERE;
2424 }
Jeff Brown6ec402b2010-07-28 15:48:59 -07002425
Jeff Brownb6997262010-10-08 22:31:17 -07002426 mLock.lock();
Jeff Brown1f245102010-11-18 20:53:46 -08002427 injectedEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
2428 keyEvent->getDeviceId(), keyEvent->getSource(),
2429 policyFlags, action, flags,
2430 keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
Jeff Brownb6997262010-10-08 22:31:17 -07002431 keyEvent->getRepeatCount(), keyEvent->getDownTime());
2432 break;
2433 }
Jeff Brown01ce2e92010-09-26 22:20:12 -07002434
Jeff Brownb6997262010-10-08 22:31:17 -07002435 case AINPUT_EVENT_TYPE_MOTION: {
2436 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
2437 int32_t action = motionEvent->getAction();
2438 size_t pointerCount = motionEvent->getPointerCount();
2439 const int32_t* pointerIds = motionEvent->getPointerIds();
2440 if (! validateMotionEvent(action, pointerCount, pointerIds)) {
2441 return INPUT_EVENT_INJECTION_FAILED;
2442 }
2443
2444 nsecs_t eventTime = motionEvent->getEventTime();
Jeff Browne20c9e02010-10-11 14:20:19 -07002445 mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
Jeff Brownb6997262010-10-08 22:31:17 -07002446
2447 mLock.lock();
2448 const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
2449 const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
2450 MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
2451 motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
2452 action, motionEvent->getFlags(),
2453 motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
2454 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
2455 motionEvent->getDownTime(), uint32_t(pointerCount),
2456 pointerIds, samplePointerCoords);
2457 for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
2458 sampleEventTimes += 1;
2459 samplePointerCoords += pointerCount;
2460 mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
2461 }
2462 injectedEntry = motionEntry;
2463 break;
2464 }
2465
2466 default:
2467 LOGW("Cannot inject event of type %d", event->getType());
2468 return INPUT_EVENT_INJECTION_FAILED;
2469 }
2470
2471 InjectionState* injectionState = mAllocator.obtainInjectionState(injectorPid, injectorUid);
2472 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
2473 injectionState->injectionIsAsync = true;
2474 }
2475
2476 injectionState->refCount += 1;
2477 injectedEntry->injectionState = injectionState;
2478
2479 bool needWake = enqueueInboundEventLocked(injectedEntry);
2480 mLock.unlock();
Jeff Brown7fbdc842010-06-17 20:52:56 -07002481
Jeff Brownb88102f2010-09-08 11:49:43 -07002482 if (needWake) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002483 mLooper->wake();
Jeff Brown7fbdc842010-06-17 20:52:56 -07002484 }
2485
2486 int32_t injectionResult;
2487 { // acquire lock
2488 AutoMutex _l(mLock);
2489
Jeff Brown6ec402b2010-07-28 15:48:59 -07002490 if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
2491 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
2492 } else {
2493 for (;;) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07002494 injectionResult = injectionState->injectionResult;
Jeff Brown6ec402b2010-07-28 15:48:59 -07002495 if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
2496 break;
2497 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07002498
Jeff Brown7fbdc842010-06-17 20:52:56 -07002499 nsecs_t remainingTimeout = endTime - now();
2500 if (remainingTimeout <= 0) {
Jeff Brown6ec402b2010-07-28 15:48:59 -07002501#if DEBUG_INJECTION
2502 LOGD("injectInputEvent - Timed out waiting for injection result "
2503 "to become available.");
2504#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07002505 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
2506 break;
2507 }
2508
Jeff Brown6ec402b2010-07-28 15:48:59 -07002509 mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
2510 }
2511
2512 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
2513 && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07002514 while (injectionState->pendingForegroundDispatches != 0) {
Jeff Brown6ec402b2010-07-28 15:48:59 -07002515#if DEBUG_INJECTION
Jeff Brown519e0242010-09-15 15:18:56 -07002516 LOGD("injectInputEvent - Waiting for %d pending foreground dispatches.",
Jeff Brown01ce2e92010-09-26 22:20:12 -07002517 injectionState->pendingForegroundDispatches);
Jeff Brown6ec402b2010-07-28 15:48:59 -07002518#endif
2519 nsecs_t remainingTimeout = endTime - now();
2520 if (remainingTimeout <= 0) {
2521#if DEBUG_INJECTION
Jeff Brown519e0242010-09-15 15:18:56 -07002522 LOGD("injectInputEvent - Timed out waiting for pending foreground "
Jeff Brown6ec402b2010-07-28 15:48:59 -07002523 "dispatches to finish.");
2524#endif
2525 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
2526 break;
2527 }
2528
2529 mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
2530 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07002531 }
2532 }
2533
Jeff Brown01ce2e92010-09-26 22:20:12 -07002534 mAllocator.releaseInjectionState(injectionState);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002535 } // release lock
2536
Jeff Brown6ec402b2010-07-28 15:48:59 -07002537#if DEBUG_INJECTION
2538 LOGD("injectInputEvent - Finished with result %d. "
2539 "injectorPid=%d, injectorUid=%d",
2540 injectionResult, injectorPid, injectorUid);
2541#endif
2542
Jeff Brown7fbdc842010-06-17 20:52:56 -07002543 return injectionResult;
2544}
2545
Jeff Brownb6997262010-10-08 22:31:17 -07002546bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) {
2547 return injectorUid == 0
2548 || mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
2549}
2550
Jeff Brown7fbdc842010-06-17 20:52:56 -07002551void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07002552 InjectionState* injectionState = entry->injectionState;
2553 if (injectionState) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07002554#if DEBUG_INJECTION
2555 LOGD("Setting input event injection result to %d. "
2556 "injectorPid=%d, injectorUid=%d",
Jeff Brown01ce2e92010-09-26 22:20:12 -07002557 injectionResult, injectionState->injectorPid, injectionState->injectorUid);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002558#endif
2559
Jeff Brown01ce2e92010-09-26 22:20:12 -07002560 if (injectionState->injectionIsAsync) {
Jeff Brown6ec402b2010-07-28 15:48:59 -07002561 // Log the outcome since the injector did not wait for the injection result.
2562 switch (injectionResult) {
2563 case INPUT_EVENT_INJECTION_SUCCEEDED:
2564 LOGV("Asynchronous input event injection succeeded.");
2565 break;
2566 case INPUT_EVENT_INJECTION_FAILED:
2567 LOGW("Asynchronous input event injection failed.");
2568 break;
2569 case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
2570 LOGW("Asynchronous input event injection permission denied.");
2571 break;
2572 case INPUT_EVENT_INJECTION_TIMED_OUT:
2573 LOGW("Asynchronous input event injection timed out.");
2574 break;
2575 }
2576 }
2577
Jeff Brown01ce2e92010-09-26 22:20:12 -07002578 injectionState->injectionResult = injectionResult;
Jeff Brown7fbdc842010-06-17 20:52:56 -07002579 mInjectionResultAvailableCondition.broadcast();
2580 }
2581}
2582
Jeff Brown01ce2e92010-09-26 22:20:12 -07002583void InputDispatcher::incrementPendingForegroundDispatchesLocked(EventEntry* entry) {
2584 InjectionState* injectionState = entry->injectionState;
2585 if (injectionState) {
2586 injectionState->pendingForegroundDispatches += 1;
2587 }
2588}
2589
Jeff Brown519e0242010-09-15 15:18:56 -07002590void InputDispatcher::decrementPendingForegroundDispatchesLocked(EventEntry* entry) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07002591 InjectionState* injectionState = entry->injectionState;
2592 if (injectionState) {
2593 injectionState->pendingForegroundDispatches -= 1;
Jeff Brown6ec402b2010-07-28 15:48:59 -07002594
Jeff Brown01ce2e92010-09-26 22:20:12 -07002595 if (injectionState->pendingForegroundDispatches == 0) {
2596 mInjectionSyncFinishedCondition.broadcast();
2597 }
Jeff Brownb88102f2010-09-08 11:49:43 -07002598 }
2599}
2600
Jeff Brown01ce2e92010-09-26 22:20:12 -07002601const InputWindow* InputDispatcher::getWindowLocked(const sp<InputChannel>& inputChannel) {
2602 for (size_t i = 0; i < mWindows.size(); i++) {
2603 const InputWindow* window = & mWindows[i];
2604 if (window->inputChannel == inputChannel) {
2605 return window;
2606 }
2607 }
2608 return NULL;
2609}
2610
Jeff Brownb88102f2010-09-08 11:49:43 -07002611void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
2612#if DEBUG_FOCUS
2613 LOGD("setInputWindows");
2614#endif
2615 { // acquire lock
2616 AutoMutex _l(mLock);
2617
Jeff Brown01ce2e92010-09-26 22:20:12 -07002618 // Clear old window pointers.
Jeff Brownb6997262010-10-08 22:31:17 -07002619 sp<InputChannel> oldFocusedWindowChannel;
2620 if (mFocusedWindow) {
2621 oldFocusedWindowChannel = mFocusedWindow->inputChannel;
2622 mFocusedWindow = NULL;
2623 }
2624
Jeff Brownb88102f2010-09-08 11:49:43 -07002625 mWindows.clear();
Jeff Brown2a95c2a2010-09-16 12:31:46 -07002626
2627 // Loop over new windows and rebuild the necessary window pointers for
2628 // tracking focus and touch.
Jeff Brownb88102f2010-09-08 11:49:43 -07002629 mWindows.appendVector(inputWindows);
2630
2631 size_t numWindows = mWindows.size();
2632 for (size_t i = 0; i < numWindows; i++) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07002633 const InputWindow* window = & mWindows.itemAt(i);
Jeff Brownb88102f2010-09-08 11:49:43 -07002634 if (window->hasFocus) {
2635 mFocusedWindow = window;
Jeff Brown01ce2e92010-09-26 22:20:12 -07002636 break;
Jeff Brownb88102f2010-09-08 11:49:43 -07002637 }
2638 }
Jeff Brown01ce2e92010-09-26 22:20:12 -07002639
Jeff Brownb6997262010-10-08 22:31:17 -07002640 if (oldFocusedWindowChannel != NULL) {
2641 if (!mFocusedWindow || oldFocusedWindowChannel != mFocusedWindow->inputChannel) {
2642#if DEBUG_FOCUS
2643 LOGD("Focus left window: %s",
2644 oldFocusedWindowChannel->getName().string());
2645#endif
2646 synthesizeCancelationEventsForInputChannelLocked(oldFocusedWindowChannel,
2647 InputState::CANCEL_NON_POINTER_EVENTS, "focus left window");
2648 oldFocusedWindowChannel.clear();
2649 }
2650 }
2651 if (mFocusedWindow && oldFocusedWindowChannel == NULL) {
2652#if DEBUG_FOCUS
2653 LOGD("Focus entered window: %s",
2654 mFocusedWindow->inputChannel->getName().string());
2655#endif
2656 }
2657
Jeff Brown01ce2e92010-09-26 22:20:12 -07002658 for (size_t i = 0; i < mTouchState.windows.size(); ) {
2659 TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i);
2660 const InputWindow* window = getWindowLocked(touchedWindow.channel);
2661 if (window) {
2662 touchedWindow.window = window;
2663 i += 1;
2664 } else {
Jeff Brownb6997262010-10-08 22:31:17 -07002665#if DEBUG_FOCUS
2666 LOGD("Touched window was removed: %s", touchedWindow.channel->getName().string());
2667#endif
Jeff Brownb6997262010-10-08 22:31:17 -07002668 synthesizeCancelationEventsForInputChannelLocked(touchedWindow.channel,
2669 InputState::CANCEL_POINTER_EVENTS, "touched window was removed");
Jeff Brownaf48cae2010-10-15 16:20:51 -07002670 mTouchState.windows.removeAt(i);
Jeff Brown01ce2e92010-09-26 22:20:12 -07002671 }
2672 }
Jeff Brownb88102f2010-09-08 11:49:43 -07002673
Jeff Brownb88102f2010-09-08 11:49:43 -07002674#if DEBUG_FOCUS
Jeff Brownb6997262010-10-08 22:31:17 -07002675 //logDispatchStateLocked();
Jeff Brownb88102f2010-09-08 11:49:43 -07002676#endif
2677 } // release lock
2678
2679 // Wake up poll loop since it may need to make new input dispatching choices.
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002680 mLooper->wake();
Jeff Brownb88102f2010-09-08 11:49:43 -07002681}
2682
2683void InputDispatcher::setFocusedApplication(const InputApplication* inputApplication) {
2684#if DEBUG_FOCUS
2685 LOGD("setFocusedApplication");
2686#endif
2687 { // acquire lock
2688 AutoMutex _l(mLock);
2689
2690 releaseFocusedApplicationLocked();
2691
2692 if (inputApplication) {
2693 mFocusedApplicationStorage = *inputApplication;
2694 mFocusedApplication = & mFocusedApplicationStorage;
2695 }
2696
2697#if DEBUG_FOCUS
Jeff Brownb6997262010-10-08 22:31:17 -07002698 //logDispatchStateLocked();
Jeff Brownb88102f2010-09-08 11:49:43 -07002699#endif
2700 } // release lock
2701
2702 // Wake up poll loop since it may need to make new input dispatching choices.
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002703 mLooper->wake();
Jeff Brownb88102f2010-09-08 11:49:43 -07002704}
2705
2706void InputDispatcher::releaseFocusedApplicationLocked() {
2707 if (mFocusedApplication) {
2708 mFocusedApplication = NULL;
Jeff Brown928e0542011-01-10 11:17:36 -08002709 mFocusedApplicationStorage.inputApplicationHandle.clear();
Jeff Brownb88102f2010-09-08 11:49:43 -07002710 }
2711}
2712
2713void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
2714#if DEBUG_FOCUS
2715 LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
2716#endif
2717
2718 bool changed;
2719 { // acquire lock
2720 AutoMutex _l(mLock);
2721
2722 if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
Jeff Brown120a4592010-10-27 18:43:51 -07002723 if (mDispatchFrozen && !frozen) {
Jeff Brownb88102f2010-09-08 11:49:43 -07002724 resetANRTimeoutsLocked();
2725 }
2726
Jeff Brown120a4592010-10-27 18:43:51 -07002727 if (mDispatchEnabled && !enabled) {
2728 resetAndDropEverythingLocked("dispatcher is being disabled");
2729 }
2730
Jeff Brownb88102f2010-09-08 11:49:43 -07002731 mDispatchEnabled = enabled;
2732 mDispatchFrozen = frozen;
2733 changed = true;
2734 } else {
2735 changed = false;
2736 }
2737
2738#if DEBUG_FOCUS
Jeff Brownb6997262010-10-08 22:31:17 -07002739 //logDispatchStateLocked();
Jeff Brownb88102f2010-09-08 11:49:43 -07002740#endif
2741 } // release lock
2742
2743 if (changed) {
2744 // Wake up poll loop since it may need to make new input dispatching choices.
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002745 mLooper->wake();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002746 }
2747}
2748
Jeff Browne6504122010-09-27 14:52:15 -07002749bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
2750 const sp<InputChannel>& toChannel) {
2751#if DEBUG_FOCUS
2752 LOGD("transferTouchFocus: fromChannel=%s, toChannel=%s",
2753 fromChannel->getName().string(), toChannel->getName().string());
2754#endif
2755 { // acquire lock
2756 AutoMutex _l(mLock);
2757
2758 const InputWindow* fromWindow = getWindowLocked(fromChannel);
2759 const InputWindow* toWindow = getWindowLocked(toChannel);
2760 if (! fromWindow || ! toWindow) {
2761#if DEBUG_FOCUS
2762 LOGD("Cannot transfer focus because from or to window not found.");
2763#endif
2764 return false;
2765 }
2766 if (fromWindow == toWindow) {
2767#if DEBUG_FOCUS
2768 LOGD("Trivial transfer to same window.");
2769#endif
2770 return true;
2771 }
2772
2773 bool found = false;
2774 for (size_t i = 0; i < mTouchState.windows.size(); i++) {
2775 const TouchedWindow& touchedWindow = mTouchState.windows[i];
2776 if (touchedWindow.window == fromWindow) {
2777 int32_t oldTargetFlags = touchedWindow.targetFlags;
2778 BitSet32 pointerIds = touchedWindow.pointerIds;
2779
2780 mTouchState.windows.removeAt(i);
2781
Jeff Brown46e75292010-11-10 16:53:45 -08002782 int32_t newTargetFlags = oldTargetFlags
2783 & (InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_SPLIT);
Jeff Browne6504122010-09-27 14:52:15 -07002784 mTouchState.addOrUpdateWindow(toWindow, newTargetFlags, pointerIds);
2785
2786 found = true;
2787 break;
2788 }
2789 }
2790
2791 if (! found) {
2792#if DEBUG_FOCUS
2793 LOGD("Focus transfer failed because from window did not have focus.");
2794#endif
2795 return false;
2796 }
2797
Jeff Brown9c9f1a32010-10-11 18:32:20 -07002798 ssize_t fromConnectionIndex = getConnectionIndexLocked(fromChannel);
2799 ssize_t toConnectionIndex = getConnectionIndexLocked(toChannel);
2800 if (fromConnectionIndex >= 0 && toConnectionIndex >= 0) {
2801 sp<Connection> fromConnection = mConnectionsByReceiveFd.valueAt(fromConnectionIndex);
2802 sp<Connection> toConnection = mConnectionsByReceiveFd.valueAt(toConnectionIndex);
2803
2804 fromConnection->inputState.copyPointerStateTo(toConnection->inputState);
2805 synthesizeCancelationEventsForConnectionLocked(fromConnection,
2806 InputState::CANCEL_POINTER_EVENTS,
2807 "transferring touch focus from this window to another window");
2808 }
2809
Jeff Browne6504122010-09-27 14:52:15 -07002810#if DEBUG_FOCUS
2811 logDispatchStateLocked();
2812#endif
2813 } // release lock
2814
2815 // Wake up poll loop since it may need to make new input dispatching choices.
2816 mLooper->wake();
2817 return true;
2818}
2819
Jeff Brown120a4592010-10-27 18:43:51 -07002820void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
2821#if DEBUG_FOCUS
2822 LOGD("Resetting and dropping all events (%s).", reason);
2823#endif
2824
2825 synthesizeCancelationEventsForAllConnectionsLocked(InputState::CANCEL_ALL_EVENTS, reason);
2826
2827 resetKeyRepeatLocked();
2828 releasePendingEventLocked();
2829 drainInboundQueueLocked();
2830 resetTargetsLocked();
2831
2832 mTouchState.reset();
2833}
2834
Jeff Brownb88102f2010-09-08 11:49:43 -07002835void InputDispatcher::logDispatchStateLocked() {
2836 String8 dump;
2837 dumpDispatchStateLocked(dump);
Jeff Brown2a95c2a2010-09-16 12:31:46 -07002838
2839 char* text = dump.lockBuffer(dump.size());
2840 char* start = text;
2841 while (*start != '\0') {
2842 char* end = strchr(start, '\n');
2843 if (*end == '\n') {
2844 *(end++) = '\0';
2845 }
2846 LOGD("%s", start);
2847 start = end;
2848 }
Jeff Brownb88102f2010-09-08 11:49:43 -07002849}
2850
2851void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
Jeff Brownf2f487182010-10-01 17:46:21 -07002852 dump.appendFormat(INDENT "DispatchEnabled: %d\n", mDispatchEnabled);
2853 dump.appendFormat(INDENT "DispatchFrozen: %d\n", mDispatchFrozen);
Jeff Brownb88102f2010-09-08 11:49:43 -07002854
2855 if (mFocusedApplication) {
Jeff Brownf2f487182010-10-01 17:46:21 -07002856 dump.appendFormat(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
Jeff Brownb88102f2010-09-08 11:49:43 -07002857 mFocusedApplication->name.string(),
2858 mFocusedApplication->dispatchingTimeout / 1000000.0);
2859 } else {
Jeff Brownf2f487182010-10-01 17:46:21 -07002860 dump.append(INDENT "FocusedApplication: <null>\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002861 }
Jeff Brownf2f487182010-10-01 17:46:21 -07002862 dump.appendFormat(INDENT "FocusedWindow: name='%s'\n",
Jeff Brown2a95c2a2010-09-16 12:31:46 -07002863 mFocusedWindow != NULL ? mFocusedWindow->name.string() : "<null>");
Jeff Brownf2f487182010-10-01 17:46:21 -07002864
2865 dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down));
2866 dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split));
Jeff Brown95712852011-01-04 19:41:59 -08002867 dump.appendFormat(INDENT "TouchDeviceId: %d\n", mTouchState.deviceId);
Jeff Brownf2f487182010-10-01 17:46:21 -07002868 if (!mTouchState.windows.isEmpty()) {
2869 dump.append(INDENT "TouchedWindows:\n");
2870 for (size_t i = 0; i < mTouchState.windows.size(); i++) {
2871 const TouchedWindow& touchedWindow = mTouchState.windows[i];
2872 dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
2873 i, touchedWindow.window->name.string(), touchedWindow.pointerIds.value,
2874 touchedWindow.targetFlags);
2875 }
2876 } else {
2877 dump.append(INDENT "TouchedWindows: <none>\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002878 }
2879
Jeff Brownf2f487182010-10-01 17:46:21 -07002880 if (!mWindows.isEmpty()) {
2881 dump.append(INDENT "Windows:\n");
2882 for (size_t i = 0; i < mWindows.size(); i++) {
2883 const InputWindow& window = mWindows[i];
2884 dump.appendFormat(INDENT2 "%d: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
2885 "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
2886 "frame=[%d,%d][%d,%d], "
2887 "visibleFrame=[%d,%d][%d,%d], "
2888 "touchableArea=[%d,%d][%d,%d], "
2889 "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
2890 i, window.name.string(),
2891 toString(window.paused),
2892 toString(window.hasFocus),
2893 toString(window.hasWallpaper),
2894 toString(window.visible),
2895 toString(window.canReceiveKeys),
2896 window.layoutParamsFlags, window.layoutParamsType,
2897 window.layer,
2898 window.frameLeft, window.frameTop,
2899 window.frameRight, window.frameBottom,
2900 window.visibleFrameLeft, window.visibleFrameTop,
2901 window.visibleFrameRight, window.visibleFrameBottom,
2902 window.touchableAreaLeft, window.touchableAreaTop,
2903 window.touchableAreaRight, window.touchableAreaBottom,
2904 window.ownerPid, window.ownerUid,
2905 window.dispatchingTimeout / 1000000.0);
2906 }
2907 } else {
2908 dump.append(INDENT "Windows: <none>\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002909 }
2910
Jeff Brownf2f487182010-10-01 17:46:21 -07002911 if (!mMonitoringChannels.isEmpty()) {
2912 dump.append(INDENT "MonitoringChannels:\n");
2913 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
2914 const sp<InputChannel>& channel = mMonitoringChannels[i];
2915 dump.appendFormat(INDENT2 "%d: '%s'\n", i, channel->getName().string());
2916 }
2917 } else {
2918 dump.append(INDENT "MonitoringChannels: <none>\n");
2919 }
Jeff Brown519e0242010-09-15 15:18:56 -07002920
Jeff Brownf2f487182010-10-01 17:46:21 -07002921 dump.appendFormat(INDENT "InboundQueue: length=%u\n", mInboundQueue.count());
2922
2923 if (!mActiveConnections.isEmpty()) {
2924 dump.append(INDENT "ActiveConnections:\n");
2925 for (size_t i = 0; i < mActiveConnections.size(); i++) {
2926 const Connection* connection = mActiveConnections[i];
Jeff Brown76860e32010-10-25 17:37:46 -07002927 dump.appendFormat(INDENT2 "%d: '%s', status=%s, outboundQueueLength=%u, "
Jeff Brownb6997262010-10-08 22:31:17 -07002928 "inputState.isNeutral=%s\n",
Jeff Brownf2f487182010-10-01 17:46:21 -07002929 i, connection->getInputChannelName(), connection->getStatusLabel(),
2930 connection->outboundQueue.count(),
Jeff Brownb6997262010-10-08 22:31:17 -07002931 toString(connection->inputState.isNeutral()));
Jeff Brownf2f487182010-10-01 17:46:21 -07002932 }
2933 } else {
2934 dump.append(INDENT "ActiveConnections: <none>\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002935 }
2936
2937 if (isAppSwitchPendingLocked()) {
Jeff Brownf2f487182010-10-01 17:46:21 -07002938 dump.appendFormat(INDENT "AppSwitch: pending, due in %01.1fms\n",
Jeff Brownb88102f2010-09-08 11:49:43 -07002939 (mAppSwitchDueTime - now()) / 1000000.0);
2940 } else {
Jeff Brownf2f487182010-10-01 17:46:21 -07002941 dump.append(INDENT "AppSwitch: not pending\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002942 }
2943}
2944
Jeff Brown928e0542011-01-10 11:17:36 -08002945status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
2946 const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07002947#if DEBUG_REGISTRATION
Jeff Brownb88102f2010-09-08 11:49:43 -07002948 LOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().string(),
2949 toString(monitor));
Jeff Brown9c3cda02010-06-15 01:31:58 -07002950#endif
2951
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002952 { // acquire lock
2953 AutoMutex _l(mLock);
2954
Jeff Brown519e0242010-09-15 15:18:56 -07002955 if (getConnectionIndexLocked(inputChannel) >= 0) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002956 LOGW("Attempted to register already registered input channel '%s'",
2957 inputChannel->getName().string());
2958 return BAD_VALUE;
2959 }
2960
Jeff Brown928e0542011-01-10 11:17:36 -08002961 sp<Connection> connection = new Connection(inputChannel, inputWindowHandle);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002962 status_t status = connection->initialize();
2963 if (status) {
2964 LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
2965 inputChannel->getName().string(), status);
2966 return status;
2967 }
2968
Jeff Brown2cbecea2010-08-17 15:59:26 -07002969 int32_t receiveFd = inputChannel->getReceivePipeFd();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002970 mConnectionsByReceiveFd.add(receiveFd, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -07002971
Jeff Brownb88102f2010-09-08 11:49:43 -07002972 if (monitor) {
2973 mMonitoringChannels.push(inputChannel);
2974 }
2975
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07002976 mLooper->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
Jeff Brown2cbecea2010-08-17 15:59:26 -07002977
Jeff Brown9c3cda02010-06-15 01:31:58 -07002978 runCommandsLockedInterruptible();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002979 } // release lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002980 return OK;
2981}
2982
2983status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07002984#if DEBUG_REGISTRATION
Jeff Brown349703e2010-06-22 01:27:15 -07002985 LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
Jeff Brown9c3cda02010-06-15 01:31:58 -07002986#endif
2987
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002988 { // acquire lock
2989 AutoMutex _l(mLock);
2990
Jeff Brown519e0242010-09-15 15:18:56 -07002991 ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002992 if (connectionIndex < 0) {
2993 LOGW("Attempted to unregister already unregistered input channel '%s'",
2994 inputChannel->getName().string());
2995 return BAD_VALUE;
2996 }
2997
2998 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
2999 mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
3000
3001 connection->status = Connection::STATUS_ZOMBIE;
3002
Jeff Brownb88102f2010-09-08 11:49:43 -07003003 for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
3004 if (mMonitoringChannels[i] == inputChannel) {
3005 mMonitoringChannels.removeAt(i);
3006 break;
3007 }
3008 }
3009
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07003010 mLooper->removeFd(inputChannel->getReceivePipeFd());
Jeff Brown2cbecea2010-08-17 15:59:26 -07003011
Jeff Brown7fbdc842010-06-17 20:52:56 -07003012 nsecs_t currentTime = now();
Jeff Brownb6997262010-10-08 22:31:17 -07003013 abortBrokenDispatchCycleLocked(currentTime, connection);
Jeff Brown9c3cda02010-06-15 01:31:58 -07003014
3015 runCommandsLockedInterruptible();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003016 } // release lock
3017
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003018 // Wake the poll loop because removing the connection may have changed the current
3019 // synchronization state.
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07003020 mLooper->wake();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003021 return OK;
3022}
3023
Jeff Brown519e0242010-09-15 15:18:56 -07003024ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
Jeff Brown2cbecea2010-08-17 15:59:26 -07003025 ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(inputChannel->getReceivePipeFd());
3026 if (connectionIndex >= 0) {
3027 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
3028 if (connection->inputChannel.get() == inputChannel.get()) {
3029 return connectionIndex;
3030 }
3031 }
3032
3033 return -1;
3034}
3035
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003036void InputDispatcher::activateConnectionLocked(Connection* connection) {
3037 for (size_t i = 0; i < mActiveConnections.size(); i++) {
3038 if (mActiveConnections.itemAt(i) == connection) {
3039 return;
3040 }
3041 }
3042 mActiveConnections.add(connection);
3043}
3044
3045void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
3046 for (size_t i = 0; i < mActiveConnections.size(); i++) {
3047 if (mActiveConnections.itemAt(i) == connection) {
3048 mActiveConnections.removeAt(i);
3049 return;
3050 }
3051 }
3052}
3053
Jeff Brown9c3cda02010-06-15 01:31:58 -07003054void InputDispatcher::onDispatchCycleStartedLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07003055 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003056}
3057
Jeff Brown9c3cda02010-06-15 01:31:58 -07003058void InputDispatcher::onDispatchCycleFinishedLocked(
Jeff Brown3915bb82010-11-05 15:02:16 -07003059 nsecs_t currentTime, const sp<Connection>& connection, bool handled) {
3060 CommandEntry* commandEntry = postCommandLocked(
3061 & InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
3062 commandEntry->connection = connection;
3063 commandEntry->handled = handled;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003064}
3065
Jeff Brown9c3cda02010-06-15 01:31:58 -07003066void InputDispatcher::onDispatchCycleBrokenLocked(
Jeff Brown7fbdc842010-06-17 20:52:56 -07003067 nsecs_t currentTime, const sp<Connection>& connection) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003068 LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
3069 connection->getInputChannelName());
3070
Jeff Brown9c3cda02010-06-15 01:31:58 -07003071 CommandEntry* commandEntry = postCommandLocked(
3072 & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
Jeff Brown7fbdc842010-06-17 20:52:56 -07003073 commandEntry->connection = connection;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003074}
3075
Jeff Brown519e0242010-09-15 15:18:56 -07003076void InputDispatcher::onANRLocked(
3077 nsecs_t currentTime, const InputApplication* application, const InputWindow* window,
3078 nsecs_t eventTime, nsecs_t waitStartTime) {
3079 LOGI("Application is not responding: %s. "
3080 "%01.1fms since event, %01.1fms since wait started",
3081 getApplicationWindowLabelLocked(application, window).string(),
3082 (currentTime - eventTime) / 1000000.0,
3083 (currentTime - waitStartTime) / 1000000.0);
3084
3085 CommandEntry* commandEntry = postCommandLocked(
3086 & InputDispatcher::doNotifyANRLockedInterruptible);
3087 if (application) {
Jeff Brown928e0542011-01-10 11:17:36 -08003088 commandEntry->inputApplicationHandle = application->inputApplicationHandle;
Jeff Brown519e0242010-09-15 15:18:56 -07003089 }
3090 if (window) {
Jeff Brown928e0542011-01-10 11:17:36 -08003091 commandEntry->inputWindowHandle = window->inputWindowHandle;
Jeff Brown519e0242010-09-15 15:18:56 -07003092 commandEntry->inputChannel = window->inputChannel;
3093 }
3094}
3095
Jeff Brownb88102f2010-09-08 11:49:43 -07003096void InputDispatcher::doNotifyConfigurationChangedInterruptible(
3097 CommandEntry* commandEntry) {
3098 mLock.unlock();
3099
3100 mPolicy->notifyConfigurationChanged(commandEntry->eventTime);
3101
3102 mLock.lock();
3103}
3104
Jeff Brown9c3cda02010-06-15 01:31:58 -07003105void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
3106 CommandEntry* commandEntry) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07003107 sp<Connection> connection = commandEntry->connection;
Jeff Brown9c3cda02010-06-15 01:31:58 -07003108
Jeff Brown7fbdc842010-06-17 20:52:56 -07003109 if (connection->status != Connection::STATUS_ZOMBIE) {
3110 mLock.unlock();
Jeff Brown9c3cda02010-06-15 01:31:58 -07003111
Jeff Brown928e0542011-01-10 11:17:36 -08003112 mPolicy->notifyInputChannelBroken(connection->inputWindowHandle);
Jeff Brown7fbdc842010-06-17 20:52:56 -07003113
3114 mLock.lock();
3115 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07003116}
3117
Jeff Brown519e0242010-09-15 15:18:56 -07003118void InputDispatcher::doNotifyANRLockedInterruptible(
Jeff Brown9c3cda02010-06-15 01:31:58 -07003119 CommandEntry* commandEntry) {
Jeff Brown519e0242010-09-15 15:18:56 -07003120 mLock.unlock();
Jeff Brown9c3cda02010-06-15 01:31:58 -07003121
Jeff Brown519e0242010-09-15 15:18:56 -07003122 nsecs_t newTimeout = mPolicy->notifyANR(
Jeff Brown928e0542011-01-10 11:17:36 -08003123 commandEntry->inputApplicationHandle, commandEntry->inputWindowHandle);
Jeff Brown9c3cda02010-06-15 01:31:58 -07003124
Jeff Brown519e0242010-09-15 15:18:56 -07003125 mLock.lock();
Jeff Brown7fbdc842010-06-17 20:52:56 -07003126
Jeff Brown519e0242010-09-15 15:18:56 -07003127 resumeAfterTargetsNotReadyTimeoutLocked(newTimeout, commandEntry->inputChannel);
Jeff Brown9c3cda02010-06-15 01:31:58 -07003128}
3129
Jeff Brownb88102f2010-09-08 11:49:43 -07003130void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
3131 CommandEntry* commandEntry) {
3132 KeyEntry* entry = commandEntry->keyEntry;
Jeff Brown1f245102010-11-18 20:53:46 -08003133
3134 KeyEvent event;
3135 initializeKeyEvent(&event, entry);
Jeff Brownb88102f2010-09-08 11:49:43 -07003136
3137 mLock.unlock();
3138
Jeff Brown928e0542011-01-10 11:17:36 -08003139 bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
Jeff Brown1f245102010-11-18 20:53:46 -08003140 &event, entry->policyFlags);
Jeff Brownb88102f2010-09-08 11:49:43 -07003141
3142 mLock.lock();
3143
3144 entry->interceptKeyResult = consumed
3145 ? KeyEntry::INTERCEPT_KEY_RESULT_SKIP
3146 : KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
3147 mAllocator.releaseKeyEntry(entry);
3148}
3149
Jeff Brown3915bb82010-11-05 15:02:16 -07003150void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
3151 CommandEntry* commandEntry) {
3152 sp<Connection> connection = commandEntry->connection;
3153 bool handled = commandEntry->handled;
3154
Jeff Brown49ed71d2010-12-06 17:13:33 -08003155 if (!connection->outboundQueue.isEmpty()) {
Jeff Brown3915bb82010-11-05 15:02:16 -07003156 DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
3157 if (dispatchEntry->inProgress
3158 && dispatchEntry->hasForegroundTarget()
3159 && dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
3160 KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
Jeff Brown49ed71d2010-12-06 17:13:33 -08003161 if (!(keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
3162 if (handled) {
3163 // If the application handled a non-fallback key, then immediately
3164 // cancel all fallback keys previously dispatched to the application.
3165 // This behavior will prevent chording with fallback keys (so they cannot
3166 // be used as modifiers) but it will ensure that fallback keys do not
3167 // get stuck. This takes care of the case where the application does not handle
3168 // the original DOWN so we generate a fallback DOWN but it does handle
3169 // the original UP in which case we would not generate the fallback UP.
3170 synthesizeCancelationEventsForConnectionLocked(connection,
3171 InputState::CANCEL_FALLBACK_EVENTS,
Jeff Brown00045a72010-12-09 18:10:30 -08003172 "application handled a non-fallback event, canceling all fallback events");
Jeff Brown49ed71d2010-12-06 17:13:33 -08003173 } else {
3174 // If the application did not handle a non-fallback key, then ask
3175 // the policy what to do with it. We might generate a fallback key
3176 // event here.
3177 KeyEvent event;
3178 initializeKeyEvent(&event, keyEntry);
Jeff Brown3915bb82010-11-05 15:02:16 -07003179
Jeff Brown49ed71d2010-12-06 17:13:33 -08003180 mLock.unlock();
Jeff Brown3915bb82010-11-05 15:02:16 -07003181
Jeff Brown928e0542011-01-10 11:17:36 -08003182 bool fallback = mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
Jeff Brown49ed71d2010-12-06 17:13:33 -08003183 &event, keyEntry->policyFlags, &event);
Jeff Brown3915bb82010-11-05 15:02:16 -07003184
Jeff Brown49ed71d2010-12-06 17:13:33 -08003185 mLock.lock();
3186
Jeff Brown00045a72010-12-09 18:10:30 -08003187 if (connection->status != Connection::STATUS_NORMAL) {
3188 return;
3189 }
3190
3191 assert(connection->outboundQueue.headSentinel.next == dispatchEntry);
3192
Jeff Brown49ed71d2010-12-06 17:13:33 -08003193 if (fallback) {
3194 // Restart the dispatch cycle using the fallback key.
3195 keyEntry->eventTime = event.getEventTime();
3196 keyEntry->deviceId = event.getDeviceId();
3197 keyEntry->source = event.getSource();
3198 keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
3199 keyEntry->keyCode = event.getKeyCode();
3200 keyEntry->scanCode = event.getScanCode();
3201 keyEntry->metaState = event.getMetaState();
3202 keyEntry->repeatCount = event.getRepeatCount();
3203 keyEntry->downTime = event.getDownTime();
3204 keyEntry->syntheticRepeat = false;
3205
3206 dispatchEntry->inProgress = false;
3207 startDispatchCycleLocked(now(), connection);
3208 return;
3209 }
3210 }
3211 }
Jeff Brown3915bb82010-11-05 15:02:16 -07003212 }
3213 }
3214
3215 startNextDispatchCycleLocked(now(), connection);
3216}
3217
Jeff Brownb88102f2010-09-08 11:49:43 -07003218void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
3219 mLock.unlock();
3220
Jeff Brown01ce2e92010-09-26 22:20:12 -07003221 mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType);
Jeff Brownb88102f2010-09-08 11:49:43 -07003222
3223 mLock.lock();
3224}
3225
Jeff Brown3915bb82010-11-05 15:02:16 -07003226void InputDispatcher::initializeKeyEvent(KeyEvent* event, const KeyEntry* entry) {
3227 event->initialize(entry->deviceId, entry->source, entry->action, entry->flags,
3228 entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
3229 entry->downTime, entry->eventTime);
3230}
3231
Jeff Brown519e0242010-09-15 15:18:56 -07003232void InputDispatcher::updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
3233 int32_t injectionResult, nsecs_t timeSpentWaitingForApplication) {
3234 // TODO Write some statistics about how long we spend waiting.
Jeff Brownb88102f2010-09-08 11:49:43 -07003235}
3236
3237void InputDispatcher::dump(String8& dump) {
Jeff Brownf2f487182010-10-01 17:46:21 -07003238 dump.append("Input Dispatcher State:\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07003239 dumpDispatchStateLocked(dump);
3240}
3241
Jeff Brown9c3cda02010-06-15 01:31:58 -07003242
Jeff Brown519e0242010-09-15 15:18:56 -07003243// --- InputDispatcher::Queue ---
3244
3245template <typename T>
3246uint32_t InputDispatcher::Queue<T>::count() const {
3247 uint32_t result = 0;
3248 for (const T* entry = headSentinel.next; entry != & tailSentinel; entry = entry->next) {
3249 result += 1;
3250 }
3251 return result;
3252}
3253
3254
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003255// --- InputDispatcher::Allocator ---
3256
3257InputDispatcher::Allocator::Allocator() {
3258}
3259
Jeff Brown01ce2e92010-09-26 22:20:12 -07003260InputDispatcher::InjectionState*
3261InputDispatcher::Allocator::obtainInjectionState(int32_t injectorPid, int32_t injectorUid) {
3262 InjectionState* injectionState = mInjectionStatePool.alloc();
3263 injectionState->refCount = 1;
3264 injectionState->injectorPid = injectorPid;
3265 injectionState->injectorUid = injectorUid;
3266 injectionState->injectionIsAsync = false;
3267 injectionState->injectionResult = INPUT_EVENT_INJECTION_PENDING;
3268 injectionState->pendingForegroundDispatches = 0;
3269 return injectionState;
3270}
3271
Jeff Brown7fbdc842010-06-17 20:52:56 -07003272void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
Jeff Brownb6997262010-10-08 22:31:17 -07003273 nsecs_t eventTime, uint32_t policyFlags) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07003274 entry->type = type;
3275 entry->refCount = 1;
3276 entry->dispatchInProgress = false;
Christopher Tatee91a5db2010-06-23 16:50:30 -07003277 entry->eventTime = eventTime;
Jeff Brownb6997262010-10-08 22:31:17 -07003278 entry->policyFlags = policyFlags;
Jeff Brown01ce2e92010-09-26 22:20:12 -07003279 entry->injectionState = NULL;
3280}
3281
3282void InputDispatcher::Allocator::releaseEventEntryInjectionState(EventEntry* entry) {
3283 if (entry->injectionState) {
3284 releaseInjectionState(entry->injectionState);
3285 entry->injectionState = NULL;
3286 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07003287}
3288
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003289InputDispatcher::ConfigurationChangedEntry*
Jeff Brown7fbdc842010-06-17 20:52:56 -07003290InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003291 ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
Jeff Brownb6997262010-10-08 22:31:17 -07003292 initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime, 0);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003293 return entry;
3294}
3295
Jeff Brown7fbdc842010-06-17 20:52:56 -07003296InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
Jeff Brownc5ed5912010-07-14 18:48:53 -07003297 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
Jeff Brown7fbdc842010-06-17 20:52:56 -07003298 int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
3299 int32_t repeatCount, nsecs_t downTime) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003300 KeyEntry* entry = mKeyEntryPool.alloc();
Jeff Brownb6997262010-10-08 22:31:17 -07003301 initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime, policyFlags);
Jeff Brown7fbdc842010-06-17 20:52:56 -07003302
3303 entry->deviceId = deviceId;
Jeff Brownc5ed5912010-07-14 18:48:53 -07003304 entry->source = source;
Jeff Brown7fbdc842010-06-17 20:52:56 -07003305 entry->action = action;
3306 entry->flags = flags;
3307 entry->keyCode = keyCode;
3308 entry->scanCode = scanCode;
3309 entry->metaState = metaState;
3310 entry->repeatCount = repeatCount;
3311 entry->downTime = downTime;
Jeff Brownb88102f2010-09-08 11:49:43 -07003312 entry->syntheticRepeat = false;
3313 entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003314 return entry;
3315}
3316
Jeff Brown7fbdc842010-06-17 20:52:56 -07003317InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
Jeff Brown85a31762010-09-01 17:01:00 -07003318 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
Jeff Brown7fbdc842010-06-17 20:52:56 -07003319 int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
3320 nsecs_t downTime, uint32_t pointerCount,
3321 const int32_t* pointerIds, const PointerCoords* pointerCoords) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003322 MotionEntry* entry = mMotionEntryPool.alloc();
Jeff Brownb6997262010-10-08 22:31:17 -07003323 initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime, policyFlags);
Jeff Brown7fbdc842010-06-17 20:52:56 -07003324
3325 entry->eventTime = eventTime;
3326 entry->deviceId = deviceId;
Jeff Brownc5ed5912010-07-14 18:48:53 -07003327 entry->source = source;
Jeff Brown7fbdc842010-06-17 20:52:56 -07003328 entry->action = action;
Jeff Brown85a31762010-09-01 17:01:00 -07003329 entry->flags = flags;
Jeff Brown7fbdc842010-06-17 20:52:56 -07003330 entry->metaState = metaState;
3331 entry->edgeFlags = edgeFlags;
3332 entry->xPrecision = xPrecision;
3333 entry->yPrecision = yPrecision;
3334 entry->downTime = downTime;
3335 entry->pointerCount = pointerCount;
3336 entry->firstSample.eventTime = eventTime;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003337 entry->firstSample.next = NULL;
Jeff Brown7fbdc842010-06-17 20:52:56 -07003338 entry->lastSample = & entry->firstSample;
3339 for (uint32_t i = 0; i < pointerCount; i++) {
3340 entry->pointerIds[i] = pointerIds[i];
3341 entry->firstSample.pointerCoords[i] = pointerCoords[i];
3342 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003343 return entry;
3344}
3345
3346InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
Jeff Brownb88102f2010-09-08 11:49:43 -07003347 EventEntry* eventEntry,
Jeff Brown519e0242010-09-15 15:18:56 -07003348 int32_t targetFlags, float xOffset, float yOffset) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003349 DispatchEntry* entry = mDispatchEntryPool.alloc();
3350 entry->eventEntry = eventEntry;
3351 eventEntry->refCount += 1;
Jeff Brownb88102f2010-09-08 11:49:43 -07003352 entry->targetFlags = targetFlags;
3353 entry->xOffset = xOffset;
3354 entry->yOffset = yOffset;
Jeff Brownb88102f2010-09-08 11:49:43 -07003355 entry->inProgress = false;
3356 entry->headMotionSample = NULL;
3357 entry->tailMotionSample = NULL;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003358 return entry;
3359}
3360
Jeff Brown9c3cda02010-06-15 01:31:58 -07003361InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
3362 CommandEntry* entry = mCommandEntryPool.alloc();
3363 entry->command = command;
3364 return entry;
3365}
3366
Jeff Brown01ce2e92010-09-26 22:20:12 -07003367void InputDispatcher::Allocator::releaseInjectionState(InjectionState* injectionState) {
3368 injectionState->refCount -= 1;
3369 if (injectionState->refCount == 0) {
3370 mInjectionStatePool.free(injectionState);
3371 } else {
3372 assert(injectionState->refCount > 0);
3373 }
3374}
3375
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003376void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
3377 switch (entry->type) {
3378 case EventEntry::TYPE_CONFIGURATION_CHANGED:
3379 releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
3380 break;
3381 case EventEntry::TYPE_KEY:
3382 releaseKeyEntry(static_cast<KeyEntry*>(entry));
3383 break;
3384 case EventEntry::TYPE_MOTION:
3385 releaseMotionEntry(static_cast<MotionEntry*>(entry));
3386 break;
3387 default:
3388 assert(false);
3389 break;
3390 }
3391}
3392
3393void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
3394 ConfigurationChangedEntry* entry) {
3395 entry->refCount -= 1;
3396 if (entry->refCount == 0) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07003397 releaseEventEntryInjectionState(entry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003398 mConfigurationChangeEntryPool.free(entry);
3399 } else {
3400 assert(entry->refCount > 0);
3401 }
3402}
3403
3404void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
3405 entry->refCount -= 1;
3406 if (entry->refCount == 0) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07003407 releaseEventEntryInjectionState(entry);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003408 mKeyEntryPool.free(entry);
3409 } else {
3410 assert(entry->refCount > 0);
3411 }
3412}
3413
3414void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
3415 entry->refCount -= 1;
3416 if (entry->refCount == 0) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07003417 releaseEventEntryInjectionState(entry);
Jeff Brown9c3cda02010-06-15 01:31:58 -07003418 for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
3419 MotionSample* next = sample->next;
3420 mMotionSamplePool.free(sample);
3421 sample = next;
3422 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003423 mMotionEntryPool.free(entry);
3424 } else {
3425 assert(entry->refCount > 0);
3426 }
3427}
3428
3429void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
3430 releaseEventEntry(entry->eventEntry);
3431 mDispatchEntryPool.free(entry);
3432}
3433
Jeff Brown9c3cda02010-06-15 01:31:58 -07003434void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
3435 mCommandEntryPool.free(entry);
3436}
3437
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003438void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
Jeff Brown7fbdc842010-06-17 20:52:56 -07003439 nsecs_t eventTime, const PointerCoords* pointerCoords) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003440 MotionSample* sample = mMotionSamplePool.alloc();
3441 sample->eventTime = eventTime;
Jeff Brown7fbdc842010-06-17 20:52:56 -07003442 uint32_t pointerCount = motionEntry->pointerCount;
3443 for (uint32_t i = 0; i < pointerCount; i++) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003444 sample->pointerCoords[i] = pointerCoords[i];
3445 }
3446
3447 sample->next = NULL;
3448 motionEntry->lastSample->next = sample;
3449 motionEntry->lastSample = sample;
3450}
3451
Jeff Brown01ce2e92010-09-26 22:20:12 -07003452void InputDispatcher::Allocator::recycleKeyEntry(KeyEntry* keyEntry) {
3453 releaseEventEntryInjectionState(keyEntry);
Jeff Brownb88102f2010-09-08 11:49:43 -07003454
Jeff Brown01ce2e92010-09-26 22:20:12 -07003455 keyEntry->dispatchInProgress = false;
3456 keyEntry->syntheticRepeat = false;
3457 keyEntry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
Jeff Brownb88102f2010-09-08 11:49:43 -07003458}
3459
3460
Jeff Brownae9fc032010-08-18 15:51:08 -07003461// --- InputDispatcher::MotionEntry ---
3462
3463uint32_t InputDispatcher::MotionEntry::countSamples() const {
3464 uint32_t count = 1;
3465 for (MotionSample* sample = firstSample.next; sample != NULL; sample = sample->next) {
3466 count += 1;
3467 }
3468 return count;
3469}
3470
Jeff Brownb88102f2010-09-08 11:49:43 -07003471
3472// --- InputDispatcher::InputState ---
3473
Jeff Brownb6997262010-10-08 22:31:17 -07003474InputDispatcher::InputState::InputState() {
Jeff Brownb88102f2010-09-08 11:49:43 -07003475}
3476
3477InputDispatcher::InputState::~InputState() {
3478}
3479
3480bool InputDispatcher::InputState::isNeutral() const {
3481 return mKeyMementos.isEmpty() && mMotionMementos.isEmpty();
3482}
3483
Jeff Brownb88102f2010-09-08 11:49:43 -07003484InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackEvent(
3485 const EventEntry* entry) {
3486 switch (entry->type) {
3487 case EventEntry::TYPE_KEY:
3488 return trackKey(static_cast<const KeyEntry*>(entry));
3489
3490 case EventEntry::TYPE_MOTION:
3491 return trackMotion(static_cast<const MotionEntry*>(entry));
3492
3493 default:
3494 return CONSISTENT;
3495 }
3496}
3497
3498InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackKey(
3499 const KeyEntry* entry) {
3500 int32_t action = entry->action;
3501 for (size_t i = 0; i < mKeyMementos.size(); i++) {
3502 KeyMemento& memento = mKeyMementos.editItemAt(i);
3503 if (memento.deviceId == entry->deviceId
3504 && memento.source == entry->source
3505 && memento.keyCode == entry->keyCode
3506 && memento.scanCode == entry->scanCode) {
3507 switch (action) {
3508 case AKEY_EVENT_ACTION_UP:
3509 mKeyMementos.removeAt(i);
Jeff Brownb88102f2010-09-08 11:49:43 -07003510 return CONSISTENT;
3511
3512 case AKEY_EVENT_ACTION_DOWN:
3513 return TOLERABLE;
3514
3515 default:
3516 return BROKEN;
3517 }
3518 }
3519 }
3520
3521 switch (action) {
3522 case AKEY_EVENT_ACTION_DOWN: {
3523 mKeyMementos.push();
3524 KeyMemento& memento = mKeyMementos.editTop();
3525 memento.deviceId = entry->deviceId;
3526 memento.source = entry->source;
3527 memento.keyCode = entry->keyCode;
3528 memento.scanCode = entry->scanCode;
Jeff Brown49ed71d2010-12-06 17:13:33 -08003529 memento.flags = entry->flags;
Jeff Brownb88102f2010-09-08 11:49:43 -07003530 memento.downTime = entry->downTime;
3531 return CONSISTENT;
3532 }
3533
3534 default:
3535 return BROKEN;
3536 }
3537}
3538
3539InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackMotion(
3540 const MotionEntry* entry) {
3541 int32_t action = entry->action & AMOTION_EVENT_ACTION_MASK;
3542 for (size_t i = 0; i < mMotionMementos.size(); i++) {
3543 MotionMemento& memento = mMotionMementos.editItemAt(i);
3544 if (memento.deviceId == entry->deviceId
3545 && memento.source == entry->source) {
3546 switch (action) {
3547 case AMOTION_EVENT_ACTION_UP:
3548 case AMOTION_EVENT_ACTION_CANCEL:
3549 mMotionMementos.removeAt(i);
Jeff Brownb88102f2010-09-08 11:49:43 -07003550 return CONSISTENT;
3551
3552 case AMOTION_EVENT_ACTION_DOWN:
3553 return TOLERABLE;
3554
3555 case AMOTION_EVENT_ACTION_POINTER_DOWN:
3556 if (entry->pointerCount == memento.pointerCount + 1) {
3557 memento.setPointers(entry);
3558 return CONSISTENT;
3559 }
3560 return BROKEN;
3561
3562 case AMOTION_EVENT_ACTION_POINTER_UP:
3563 if (entry->pointerCount == memento.pointerCount - 1) {
3564 memento.setPointers(entry);
3565 return CONSISTENT;
3566 }
3567 return BROKEN;
3568
3569 case AMOTION_EVENT_ACTION_MOVE:
3570 if (entry->pointerCount == memento.pointerCount) {
3571 return CONSISTENT;
3572 }
3573 return BROKEN;
3574
3575 default:
3576 return BROKEN;
3577 }
3578 }
3579 }
3580
3581 switch (action) {
3582 case AMOTION_EVENT_ACTION_DOWN: {
3583 mMotionMementos.push();
3584 MotionMemento& memento = mMotionMementos.editTop();
3585 memento.deviceId = entry->deviceId;
3586 memento.source = entry->source;
3587 memento.xPrecision = entry->xPrecision;
3588 memento.yPrecision = entry->yPrecision;
3589 memento.downTime = entry->downTime;
3590 memento.setPointers(entry);
3591 return CONSISTENT;
3592 }
3593
3594 default:
3595 return BROKEN;
3596 }
3597}
3598
3599void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) {
3600 pointerCount = entry->pointerCount;
3601 for (uint32_t i = 0; i < entry->pointerCount; i++) {
3602 pointerIds[i] = entry->pointerIds[i];
3603 pointerCoords[i] = entry->lastSample->pointerCoords[i];
3604 }
3605}
3606
Jeff Brownb6997262010-10-08 22:31:17 -07003607void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime,
3608 Allocator* allocator, Vector<EventEntry*>& outEvents,
3609 CancelationOptions options) {
3610 for (size_t i = 0; i < mKeyMementos.size(); ) {
Jeff Brownb88102f2010-09-08 11:49:43 -07003611 const KeyMemento& memento = mKeyMementos.itemAt(i);
Jeff Brown49ed71d2010-12-06 17:13:33 -08003612 if (shouldCancelKey(memento, options)) {
Jeff Brownb6997262010-10-08 22:31:17 -07003613 outEvents.push(allocator->obtainKeyEntry(currentTime,
3614 memento.deviceId, memento.source, 0,
Jeff Brown49ed71d2010-12-06 17:13:33 -08003615 AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED,
Jeff Brownb6997262010-10-08 22:31:17 -07003616 memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
3617 mKeyMementos.removeAt(i);
3618 } else {
3619 i += 1;
3620 }
Jeff Brownb88102f2010-09-08 11:49:43 -07003621 }
3622
Jeff Browna1160a72010-10-11 18:22:53 -07003623 for (size_t i = 0; i < mMotionMementos.size(); ) {
Jeff Brownb88102f2010-09-08 11:49:43 -07003624 const MotionMemento& memento = mMotionMementos.itemAt(i);
Jeff Brown49ed71d2010-12-06 17:13:33 -08003625 if (shouldCancelMotion(memento, options)) {
Jeff Brownb6997262010-10-08 22:31:17 -07003626 outEvents.push(allocator->obtainMotionEntry(currentTime,
3627 memento.deviceId, memento.source, 0,
3628 AMOTION_EVENT_ACTION_CANCEL, 0, 0, 0,
3629 memento.xPrecision, memento.yPrecision, memento.downTime,
3630 memento.pointerCount, memento.pointerIds, memento.pointerCoords));
3631 mMotionMementos.removeAt(i);
3632 } else {
3633 i += 1;
3634 }
Jeff Brownb88102f2010-09-08 11:49:43 -07003635 }
3636}
3637
3638void InputDispatcher::InputState::clear() {
3639 mKeyMementos.clear();
3640 mMotionMementos.clear();
Jeff Brownb6997262010-10-08 22:31:17 -07003641}
3642
Jeff Brown9c9f1a32010-10-11 18:32:20 -07003643void InputDispatcher::InputState::copyPointerStateTo(InputState& other) const {
3644 for (size_t i = 0; i < mMotionMementos.size(); i++) {
3645 const MotionMemento& memento = mMotionMementos.itemAt(i);
3646 if (memento.source & AINPUT_SOURCE_CLASS_POINTER) {
3647 for (size_t j = 0; j < other.mMotionMementos.size(); ) {
3648 const MotionMemento& otherMemento = other.mMotionMementos.itemAt(j);
3649 if (memento.deviceId == otherMemento.deviceId
3650 && memento.source == otherMemento.source) {
3651 other.mMotionMementos.removeAt(j);
3652 } else {
3653 j += 1;
3654 }
3655 }
3656 other.mMotionMementos.push(memento);
3657 }
3658 }
3659}
3660
Jeff Brown49ed71d2010-12-06 17:13:33 -08003661bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento,
Jeff Brownb6997262010-10-08 22:31:17 -07003662 CancelationOptions options) {
3663 switch (options) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08003664 case CANCEL_ALL_EVENTS:
Jeff Brownb6997262010-10-08 22:31:17 -07003665 case CANCEL_NON_POINTER_EVENTS:
Jeff Brownb6997262010-10-08 22:31:17 -07003666 return true;
Jeff Brown49ed71d2010-12-06 17:13:33 -08003667 case CANCEL_FALLBACK_EVENTS:
3668 return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
3669 default:
3670 return false;
3671 }
3672}
3673
3674bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& memento,
3675 CancelationOptions options) {
3676 switch (options) {
3677 case CANCEL_ALL_EVENTS:
3678 return true;
3679 case CANCEL_POINTER_EVENTS:
3680 return memento.source & AINPUT_SOURCE_CLASS_POINTER;
3681 case CANCEL_NON_POINTER_EVENTS:
3682 return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
3683 default:
3684 return false;
Jeff Brownb6997262010-10-08 22:31:17 -07003685 }
Jeff Brownb88102f2010-09-08 11:49:43 -07003686}
3687
3688
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003689// --- InputDispatcher::Connection ---
3690
Jeff Brown928e0542011-01-10 11:17:36 -08003691InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel,
3692 const sp<InputWindowHandle>& inputWindowHandle) :
3693 status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle),
3694 inputPublisher(inputChannel),
Jeff Brown519e0242010-09-15 15:18:56 -07003695 lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003696}
3697
3698InputDispatcher::Connection::~Connection() {
3699}
3700
3701status_t InputDispatcher::Connection::initialize() {
3702 return inputPublisher.initialize();
3703}
3704
Jeff Brown9c3cda02010-06-15 01:31:58 -07003705const char* InputDispatcher::Connection::getStatusLabel() const {
3706 switch (status) {
3707 case STATUS_NORMAL:
3708 return "NORMAL";
3709
3710 case STATUS_BROKEN:
3711 return "BROKEN";
3712
Jeff Brown9c3cda02010-06-15 01:31:58 -07003713 case STATUS_ZOMBIE:
3714 return "ZOMBIE";
3715
3716 default:
3717 return "UNKNOWN";
3718 }
3719}
3720
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003721InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
3722 const EventEntry* eventEntry) const {
Jeff Brownb88102f2010-09-08 11:49:43 -07003723 for (DispatchEntry* dispatchEntry = outboundQueue.tailSentinel.prev;
3724 dispatchEntry != & outboundQueue.headSentinel; dispatchEntry = dispatchEntry->prev) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003725 if (dispatchEntry->eventEntry == eventEntry) {
3726 return dispatchEntry;
3727 }
3728 }
3729 return NULL;
3730}
3731
Jeff Brownb88102f2010-09-08 11:49:43 -07003732
Jeff Brown9c3cda02010-06-15 01:31:58 -07003733// --- InputDispatcher::CommandEntry ---
3734
Jeff Brownb88102f2010-09-08 11:49:43 -07003735InputDispatcher::CommandEntry::CommandEntry() :
3736 keyEntry(NULL) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07003737}
3738
3739InputDispatcher::CommandEntry::~CommandEntry() {
3740}
3741
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003742
Jeff Brown01ce2e92010-09-26 22:20:12 -07003743// --- InputDispatcher::TouchState ---
3744
3745InputDispatcher::TouchState::TouchState() :
Jeff Brown95712852011-01-04 19:41:59 -08003746 down(false), split(false), deviceId(-1) {
Jeff Brown01ce2e92010-09-26 22:20:12 -07003747}
3748
3749InputDispatcher::TouchState::~TouchState() {
3750}
3751
3752void InputDispatcher::TouchState::reset() {
3753 down = false;
3754 split = false;
Jeff Brown95712852011-01-04 19:41:59 -08003755 deviceId = -1;
Jeff Brown01ce2e92010-09-26 22:20:12 -07003756 windows.clear();
3757}
3758
3759void InputDispatcher::TouchState::copyFrom(const TouchState& other) {
3760 down = other.down;
3761 split = other.split;
Jeff Brown95712852011-01-04 19:41:59 -08003762 deviceId = other.deviceId;
Jeff Brown01ce2e92010-09-26 22:20:12 -07003763 windows.clear();
3764 windows.appendVector(other.windows);
3765}
3766
3767void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window,
3768 int32_t targetFlags, BitSet32 pointerIds) {
3769 if (targetFlags & InputTarget::FLAG_SPLIT) {
3770 split = true;
3771 }
3772
3773 for (size_t i = 0; i < windows.size(); i++) {
3774 TouchedWindow& touchedWindow = windows.editItemAt(i);
3775 if (touchedWindow.window == window) {
3776 touchedWindow.targetFlags |= targetFlags;
3777 touchedWindow.pointerIds.value |= pointerIds.value;
3778 return;
3779 }
3780 }
3781
3782 windows.push();
3783
3784 TouchedWindow& touchedWindow = windows.editTop();
3785 touchedWindow.window = window;
3786 touchedWindow.targetFlags = targetFlags;
3787 touchedWindow.pointerIds = pointerIds;
3788 touchedWindow.channel = window->inputChannel;
3789}
3790
3791void InputDispatcher::TouchState::removeOutsideTouchWindows() {
3792 for (size_t i = 0 ; i < windows.size(); ) {
3793 if (windows[i].targetFlags & InputTarget::FLAG_OUTSIDE) {
3794 windows.removeAt(i);
3795 } else {
3796 i += 1;
3797 }
3798 }
3799}
3800
3801const InputWindow* InputDispatcher::TouchState::getFirstForegroundWindow() {
3802 for (size_t i = 0; i < windows.size(); i++) {
3803 if (windows[i].targetFlags & InputTarget::FLAG_FOREGROUND) {
3804 return windows[i].window;
3805 }
3806 }
3807 return NULL;
3808}
3809
3810
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003811// --- InputDispatcherThread ---
3812
3813InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
3814 Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
3815}
3816
3817InputDispatcherThread::~InputDispatcherThread() {
3818}
3819
3820bool InputDispatcherThread::threadLoop() {
3821 mDispatcher->dispatchOnce();
3822 return true;
3823}
3824
3825} // namespace android