widget/gonk/libui/InputDispatcher.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/widget/gonk/libui/InputDispatcher.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,4434 @@
     1.4 +/*
     1.5 + * Copyright (C) 2010 The Android Open Source Project
     1.6 + *
     1.7 + * Licensed under the Apache License, Version 2.0 (the "License");
     1.8 + * you may not use this file except in compliance with the License.
     1.9 + * You may obtain a copy of the License at
    1.10 + *
    1.11 + *      http://www.apache.org/licenses/LICENSE-2.0
    1.12 + *
    1.13 + * Unless required by applicable law or agreed to in writing, software
    1.14 + * distributed under the License is distributed on an "AS IS" BASIS,
    1.15 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    1.16 + * See the License for the specific language governing permissions and
    1.17 + * limitations under the License.
    1.18 + */
    1.19 +
    1.20 +#define LOG_TAG "InputDispatcher"
    1.21 +#define ATRACE_TAG ATRACE_TAG_INPUT
    1.22 +
    1.23 +//#define LOG_NDEBUG 0
    1.24 +#include "cutils_log.h"
    1.25 +
    1.26 +// Log detailed debug messages about each inbound event notification to the dispatcher.
    1.27 +#define DEBUG_INBOUND_EVENT_DETAILS 0
    1.28 +
    1.29 +// Log detailed debug messages about each outbound event processed by the dispatcher.
    1.30 +#define DEBUG_OUTBOUND_EVENT_DETAILS 0
    1.31 +
    1.32 +// Log debug messages about the dispatch cycle.
    1.33 +#define DEBUG_DISPATCH_CYCLE 0
    1.34 +
    1.35 +// Log debug messages about registrations.
    1.36 +#define DEBUG_REGISTRATION 0
    1.37 +
    1.38 +// Log debug messages about input event injection.
    1.39 +#define DEBUG_INJECTION 0
    1.40 +
    1.41 +// Log debug messages about input focus tracking.
    1.42 +#define DEBUG_FOCUS 0
    1.43 +
    1.44 +// Log debug messages about the app switch latency optimization.
    1.45 +#define DEBUG_APP_SWITCH 0
    1.46 +
    1.47 +// Log debug messages about hover events.
    1.48 +#define DEBUG_HOVER 0
    1.49 +
    1.50 +#include "InputDispatcher.h"
    1.51 +
    1.52 +#include "Trace.h"
    1.53 +#include "PowerManager.h"
    1.54 +
    1.55 +#include <stddef.h>
    1.56 +#include <unistd.h>
    1.57 +#include <errno.h>
    1.58 +#include <limits.h>
    1.59 +#include <time.h>
    1.60 +
    1.61 +#define INDENT "  "
    1.62 +#define INDENT2 "    "
    1.63 +#define INDENT3 "      "
    1.64 +#define INDENT4 "        "
    1.65 +
    1.66 +namespace android {
    1.67 +
    1.68 +// Default input dispatching timeout if there is no focused application or paused window
    1.69 +// from which to determine an appropriate dispatching timeout.
    1.70 +const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
    1.71 +
    1.72 +// Amount of time to allow for all pending events to be processed when an app switch
    1.73 +// key is on the way.  This is used to preempt input dispatch and drop input events
    1.74 +// when an application takes too long to respond and the user has pressed an app switch key.
    1.75 +const nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
    1.76 +
    1.77 +// Amount of time to allow for an event to be dispatched (measured since its eventTime)
    1.78 +// before considering it stale and dropping it.
    1.79 +const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL; // 10sec
    1.80 +
    1.81 +// Amount of time to allow touch events to be streamed out to a connection before requiring
    1.82 +// that the first event be finished.  This value extends the ANR timeout by the specified
    1.83 +// amount.  For example, if streaming is allowed to get ahead by one second relative to the
    1.84 +// queue of waiting unfinished events, then ANRs will similarly be delayed by one second.
    1.85 +const nsecs_t STREAM_AHEAD_EVENT_TIMEOUT = 500 * 1000000LL; // 0.5sec
    1.86 +
    1.87 +// Log a warning when an event takes longer than this to process, even if an ANR does not occur.
    1.88 +const nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec
    1.89 +
    1.90 +
    1.91 +static inline nsecs_t now() {
    1.92 +    return systemTime(SYSTEM_TIME_MONOTONIC);
    1.93 +}
    1.94 +
    1.95 +static inline const char* toString(bool value) {
    1.96 +    return value ? "true" : "false";
    1.97 +}
    1.98 +
    1.99 +static inline int32_t getMotionEventActionPointerIndex(int32_t action) {
   1.100 +    return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
   1.101 +            >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
   1.102 +}
   1.103 +
   1.104 +static bool isValidKeyAction(int32_t action) {
   1.105 +    switch (action) {
   1.106 +    case AKEY_EVENT_ACTION_DOWN:
   1.107 +    case AKEY_EVENT_ACTION_UP:
   1.108 +        return true;
   1.109 +    default:
   1.110 +        return false;
   1.111 +    }
   1.112 +}
   1.113 +
   1.114 +static bool validateKeyEvent(int32_t action) {
   1.115 +    if (! isValidKeyAction(action)) {
   1.116 +        ALOGE("Key event has invalid action code 0x%x", action);
   1.117 +        return false;
   1.118 +    }
   1.119 +    return true;
   1.120 +}
   1.121 +
   1.122 +static bool isValidMotionAction(int32_t action, size_t pointerCount) {
   1.123 +    switch (action & AMOTION_EVENT_ACTION_MASK) {
   1.124 +    case AMOTION_EVENT_ACTION_DOWN:
   1.125 +    case AMOTION_EVENT_ACTION_UP:
   1.126 +    case AMOTION_EVENT_ACTION_CANCEL:
   1.127 +    case AMOTION_EVENT_ACTION_MOVE:
   1.128 +    case AMOTION_EVENT_ACTION_OUTSIDE:
   1.129 +    case AMOTION_EVENT_ACTION_HOVER_ENTER:
   1.130 +    case AMOTION_EVENT_ACTION_HOVER_MOVE:
   1.131 +    case AMOTION_EVENT_ACTION_HOVER_EXIT:
   1.132 +    case AMOTION_EVENT_ACTION_SCROLL:
   1.133 +        return true;
   1.134 +    case AMOTION_EVENT_ACTION_POINTER_DOWN:
   1.135 +    case AMOTION_EVENT_ACTION_POINTER_UP: {
   1.136 +        int32_t index = getMotionEventActionPointerIndex(action);
   1.137 +        return index >= 0 && size_t(index) < pointerCount;
   1.138 +    }
   1.139 +    default:
   1.140 +        return false;
   1.141 +    }
   1.142 +}
   1.143 +
   1.144 +static bool validateMotionEvent(int32_t action, size_t pointerCount,
   1.145 +        const PointerProperties* pointerProperties) {
   1.146 +    if (! isValidMotionAction(action, pointerCount)) {
   1.147 +        ALOGE("Motion event has invalid action code 0x%x", action);
   1.148 +        return false;
   1.149 +    }
   1.150 +    if (pointerCount < 1 || pointerCount > MAX_POINTERS) {
   1.151 +        ALOGE("Motion event has invalid pointer count %d; value must be between 1 and %d.",
   1.152 +                pointerCount, MAX_POINTERS);
   1.153 +        return false;
   1.154 +    }
   1.155 +    BitSet32 pointerIdBits;
   1.156 +    for (size_t i = 0; i < pointerCount; i++) {
   1.157 +        int32_t id = pointerProperties[i].id;
   1.158 +        if (id < 0 || id > MAX_POINTER_ID) {
   1.159 +            ALOGE("Motion event has invalid pointer id %d; value must be between 0 and %d",
   1.160 +                    id, MAX_POINTER_ID);
   1.161 +            return false;
   1.162 +        }
   1.163 +        if (pointerIdBits.hasBit(id)) {
   1.164 +            ALOGE("Motion event has duplicate pointer id %d", id);
   1.165 +            return false;
   1.166 +        }
   1.167 +        pointerIdBits.markBit(id);
   1.168 +    }
   1.169 +    return true;
   1.170 +}
   1.171 +
   1.172 +static bool isMainDisplay(int32_t displayId) {
   1.173 +    return displayId == ADISPLAY_ID_DEFAULT || displayId == ADISPLAY_ID_NONE;
   1.174 +}
   1.175 +
   1.176 +static void dumpRegion(String8& dump, const SkRegion& region) {
   1.177 +    if (region.isEmpty()) {
   1.178 +        dump.append("<empty>");
   1.179 +        return;
   1.180 +    }
   1.181 +
   1.182 +    bool first = true;
   1.183 +    for (SkRegion::Iterator it(region); !it.done(); it.next()) {
   1.184 +        if (first) {
   1.185 +            first = false;
   1.186 +        } else {
   1.187 +            dump.append("|");
   1.188 +        }
   1.189 +        const SkIRect& rect = it.rect();
   1.190 +        dump.appendFormat("[%d,%d][%d,%d]", rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
   1.191 +    }
   1.192 +}
   1.193 +
   1.194 +
   1.195 +// --- InputDispatcher ---
   1.196 +
   1.197 +InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
   1.198 +    mPolicy(policy),
   1.199 +    mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
   1.200 +    mNextUnblockedEvent(NULL),
   1.201 +    mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
   1.202 +    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
   1.203 +    mLooper = new Looper(false);
   1.204 +
   1.205 +    mKeyRepeatState.lastKeyEntry = NULL;
   1.206 +
   1.207 +    policy->getDispatcherConfiguration(&mConfig);
   1.208 +}
   1.209 +
   1.210 +InputDispatcher::~InputDispatcher() {
   1.211 +    { // acquire lock
   1.212 +        AutoMutex _l(mLock);
   1.213 +
   1.214 +        resetKeyRepeatLocked();
   1.215 +        releasePendingEventLocked();
   1.216 +        drainInboundQueueLocked();
   1.217 +    }
   1.218 +
   1.219 +    while (mConnectionsByFd.size() != 0) {
   1.220 +        unregisterInputChannel(mConnectionsByFd.valueAt(0)->inputChannel);
   1.221 +    }
   1.222 +}
   1.223 +
   1.224 +void InputDispatcher::dispatchOnce() {
   1.225 +    nsecs_t nextWakeupTime = LONG_LONG_MAX;
   1.226 +    { // acquire lock
   1.227 +        AutoMutex _l(mLock);
   1.228 +        mDispatcherIsAliveCondition.broadcast();
   1.229 +
   1.230 +        // Run a dispatch loop if there are no pending commands.
   1.231 +        // The dispatch loop might enqueue commands to run afterwards.
   1.232 +        if (!haveCommandsLocked()) {
   1.233 +            dispatchOnceInnerLocked(&nextWakeupTime);
   1.234 +        }
   1.235 +
   1.236 +        // Run all pending commands if there are any.
   1.237 +        // If any commands were run then force the next poll to wake up immediately.
   1.238 +        if (runCommandsLockedInterruptible()) {
   1.239 +            nextWakeupTime = LONG_LONG_MIN;
   1.240 +        }
   1.241 +    } // release lock
   1.242 +
   1.243 +    // Wait for callback or timeout or wake.  (make sure we round up, not down)
   1.244 +    nsecs_t currentTime = now();
   1.245 +    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
   1.246 +    mLooper->pollOnce(timeoutMillis);
   1.247 +}
   1.248 +
   1.249 +void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
   1.250 +    nsecs_t currentTime = now();
   1.251 +
   1.252 +    // Reset the key repeat timer whenever we disallow key events, even if the next event
   1.253 +    // is not a key.  This is to ensure that we abort a key repeat if the device is just coming
   1.254 +    // out of sleep.
   1.255 +    if (!mPolicy->isKeyRepeatEnabled()) {
   1.256 +        resetKeyRepeatLocked();
   1.257 +    }
   1.258 +
   1.259 +    // If dispatching is frozen, do not process timeouts or try to deliver any new events.
   1.260 +    if (mDispatchFrozen) {
   1.261 +#if DEBUG_FOCUS
   1.262 +        ALOGD("Dispatch frozen.  Waiting some more.");
   1.263 +#endif
   1.264 +        return;
   1.265 +    }
   1.266 +
   1.267 +    // Optimize latency of app switches.
   1.268 +    // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
   1.269 +    // been pressed.  When it expires, we preempt dispatch and drop all other pending events.
   1.270 +    bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
   1.271 +    if (mAppSwitchDueTime < *nextWakeupTime) {
   1.272 +        *nextWakeupTime = mAppSwitchDueTime;
   1.273 +    }
   1.274 +
   1.275 +    // Ready to start a new event.
   1.276 +    // If we don't already have a pending event, go grab one.
   1.277 +    if (! mPendingEvent) {
   1.278 +        if (mInboundQueue.isEmpty()) {
   1.279 +            if (isAppSwitchDue) {
   1.280 +                // The inbound queue is empty so the app switch key we were waiting
   1.281 +                // for will never arrive.  Stop waiting for it.
   1.282 +                resetPendingAppSwitchLocked(false);
   1.283 +                isAppSwitchDue = false;
   1.284 +            }
   1.285 +
   1.286 +            // Synthesize a key repeat if appropriate.
   1.287 +            if (mKeyRepeatState.lastKeyEntry) {
   1.288 +                if (currentTime >= mKeyRepeatState.nextRepeatTime) {
   1.289 +                    mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
   1.290 +                } else {
   1.291 +                    if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
   1.292 +                        *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
   1.293 +                    }
   1.294 +                }
   1.295 +            }
   1.296 +
   1.297 +            // Nothing to do if there is no pending event.
   1.298 +            if (!mPendingEvent) {
   1.299 +                return;
   1.300 +            }
   1.301 +        } else {
   1.302 +            // Inbound queue has at least one entry.
   1.303 +            mPendingEvent = mInboundQueue.dequeueAtHead();
   1.304 +            traceInboundQueueLengthLocked();
   1.305 +        }
   1.306 +
   1.307 +        // Poke user activity for this event.
   1.308 +        if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
   1.309 +            pokeUserActivityLocked(mPendingEvent);
   1.310 +        }
   1.311 +
   1.312 +        // Get ready to dispatch the event.
   1.313 +        resetANRTimeoutsLocked();
   1.314 +    }
   1.315 +
   1.316 +    // Now we have an event to dispatch.
   1.317 +    // All events are eventually dequeued and processed this way, even if we intend to drop them.
   1.318 +    ALOG_ASSERT(mPendingEvent != NULL);
   1.319 +    bool done = false;
   1.320 +    DropReason dropReason = DROP_REASON_NOT_DROPPED;
   1.321 +    if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
   1.322 +        dropReason = DROP_REASON_POLICY;
   1.323 +    } else if (!mDispatchEnabled) {
   1.324 +        dropReason = DROP_REASON_DISABLED;
   1.325 +    }
   1.326 +
   1.327 +    if (mNextUnblockedEvent == mPendingEvent) {
   1.328 +        mNextUnblockedEvent = NULL;
   1.329 +    }
   1.330 +
   1.331 +    switch (mPendingEvent->type) {
   1.332 +    case EventEntry::TYPE_CONFIGURATION_CHANGED: {
   1.333 +        ConfigurationChangedEntry* typedEntry =
   1.334 +                static_cast<ConfigurationChangedEntry*>(mPendingEvent);
   1.335 +        done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
   1.336 +        dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
   1.337 +        break;
   1.338 +    }
   1.339 +
   1.340 +    case EventEntry::TYPE_DEVICE_RESET: {
   1.341 +        DeviceResetEntry* typedEntry =
   1.342 +                static_cast<DeviceResetEntry*>(mPendingEvent);
   1.343 +        done = dispatchDeviceResetLocked(currentTime, typedEntry);
   1.344 +        dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
   1.345 +        break;
   1.346 +    }
   1.347 +
   1.348 +    case EventEntry::TYPE_KEY: {
   1.349 +        KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
   1.350 +        if (isAppSwitchDue) {
   1.351 +            if (isAppSwitchKeyEventLocked(typedEntry)) {
   1.352 +                resetPendingAppSwitchLocked(true);
   1.353 +                isAppSwitchDue = false;
   1.354 +            } else if (dropReason == DROP_REASON_NOT_DROPPED) {
   1.355 +                dropReason = DROP_REASON_APP_SWITCH;
   1.356 +            }
   1.357 +        }
   1.358 +        if (dropReason == DROP_REASON_NOT_DROPPED
   1.359 +                && isStaleEventLocked(currentTime, typedEntry)) {
   1.360 +            dropReason = DROP_REASON_STALE;
   1.361 +        }
   1.362 +        if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
   1.363 +            dropReason = DROP_REASON_BLOCKED;
   1.364 +        }
   1.365 +        done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
   1.366 +        break;
   1.367 +    }
   1.368 +
   1.369 +    case EventEntry::TYPE_MOTION: {
   1.370 +        MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
   1.371 +        if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
   1.372 +            dropReason = DROP_REASON_APP_SWITCH;
   1.373 +        }
   1.374 +        if (dropReason == DROP_REASON_NOT_DROPPED
   1.375 +                && isStaleEventLocked(currentTime, typedEntry)) {
   1.376 +            dropReason = DROP_REASON_STALE;
   1.377 +        }
   1.378 +        if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
   1.379 +            dropReason = DROP_REASON_BLOCKED;
   1.380 +        }
   1.381 +        done = dispatchMotionLocked(currentTime, typedEntry,
   1.382 +                &dropReason, nextWakeupTime);
   1.383 +        break;
   1.384 +    }
   1.385 +
   1.386 +    default:
   1.387 +        ALOG_ASSERT(false);
   1.388 +        break;
   1.389 +    }
   1.390 +
   1.391 +    if (done) {
   1.392 +        if (dropReason != DROP_REASON_NOT_DROPPED) {
   1.393 +            dropInboundEventLocked(mPendingEvent, dropReason);
   1.394 +        }
   1.395 +
   1.396 +        releasePendingEventLocked();
   1.397 +        *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
   1.398 +    }
   1.399 +}
   1.400 +
   1.401 +bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
   1.402 +    bool needWake = mInboundQueue.isEmpty();
   1.403 +    mInboundQueue.enqueueAtTail(entry);
   1.404 +    traceInboundQueueLengthLocked();
   1.405 +
   1.406 +    switch (entry->type) {
   1.407 +    case EventEntry::TYPE_KEY: {
   1.408 +        // Optimize app switch latency.
   1.409 +        // If the application takes too long to catch up then we drop all events preceding
   1.410 +        // the app switch key.
   1.411 +        KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
   1.412 +        if (isAppSwitchKeyEventLocked(keyEntry)) {
   1.413 +            if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
   1.414 +                mAppSwitchSawKeyDown = true;
   1.415 +            } else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
   1.416 +                if (mAppSwitchSawKeyDown) {
   1.417 +#if DEBUG_APP_SWITCH
   1.418 +                    ALOGD("App switch is pending!");
   1.419 +#endif
   1.420 +                    mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
   1.421 +                    mAppSwitchSawKeyDown = false;
   1.422 +                    needWake = true;
   1.423 +                }
   1.424 +            }
   1.425 +        }
   1.426 +        break;
   1.427 +    }
   1.428 +
   1.429 +    case EventEntry::TYPE_MOTION: {
   1.430 +        // Optimize case where the current application is unresponsive and the user
   1.431 +        // decides to touch a window in a different application.
   1.432 +        // If the application takes too long to catch up then we drop all events preceding
   1.433 +        // the touch into the other window.
   1.434 +        MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
   1.435 +        if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN
   1.436 +                && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
   1.437 +                && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY
   1.438 +                && mInputTargetWaitApplicationHandle != NULL) {
   1.439 +            int32_t displayId = motionEntry->displayId;
   1.440 +            int32_t x = int32_t(motionEntry->pointerCoords[0].
   1.441 +                    getAxisValue(AMOTION_EVENT_AXIS_X));
   1.442 +            int32_t y = int32_t(motionEntry->pointerCoords[0].
   1.443 +                    getAxisValue(AMOTION_EVENT_AXIS_Y));
   1.444 +            sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y);
   1.445 +            if (touchedWindowHandle != NULL
   1.446 +                    && touchedWindowHandle->inputApplicationHandle
   1.447 +                            != mInputTargetWaitApplicationHandle) {
   1.448 +                // User touched a different application than the one we are waiting on.
   1.449 +                // Flag the event, and start pruning the input queue.
   1.450 +                mNextUnblockedEvent = motionEntry;
   1.451 +                needWake = true;
   1.452 +            }
   1.453 +        }
   1.454 +        break;
   1.455 +    }
   1.456 +    }
   1.457 +
   1.458 +    return needWake;
   1.459 +}
   1.460 +
   1.461 +sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId,
   1.462 +        int32_t x, int32_t y) {
   1.463 +    // Traverse windows from front to back to find touched window.
   1.464 +    size_t numWindows = mWindowHandles.size();
   1.465 +    for (size_t i = 0; i < numWindows; i++) {
   1.466 +        sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
   1.467 +        const InputWindowInfo* windowInfo = windowHandle->getInfo();
   1.468 +        if (windowInfo->displayId == displayId) {
   1.469 +            int32_t flags = windowInfo->layoutParamsFlags;
   1.470 +
   1.471 +            if (windowInfo->visible) {
   1.472 +                if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
   1.473 +                    bool isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE
   1.474 +                            | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
   1.475 +                    if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
   1.476 +                        // Found window.
   1.477 +                        return windowHandle;
   1.478 +                    }
   1.479 +                }
   1.480 +            }
   1.481 +
   1.482 +            if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) {
   1.483 +                // Error window is on top but not visible, so touch is dropped.
   1.484 +                return NULL;
   1.485 +            }
   1.486 +        }
   1.487 +    }
   1.488 +    return NULL;
   1.489 +}
   1.490 +
   1.491 +void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
   1.492 +    const char* reason;
   1.493 +    switch (dropReason) {
   1.494 +    case DROP_REASON_POLICY:
   1.495 +#if DEBUG_INBOUND_EVENT_DETAILS
   1.496 +        ALOGD("Dropped event because policy consumed it.");
   1.497 +#endif
   1.498 +        reason = "inbound event was dropped because the policy consumed it";
   1.499 +        break;
   1.500 +    case DROP_REASON_DISABLED:
   1.501 +        ALOGI("Dropped event because input dispatch is disabled.");
   1.502 +        reason = "inbound event was dropped because input dispatch is disabled";
   1.503 +        break;
   1.504 +    case DROP_REASON_APP_SWITCH:
   1.505 +        ALOGI("Dropped event because of pending overdue app switch.");
   1.506 +        reason = "inbound event was dropped because of pending overdue app switch";
   1.507 +        break;
   1.508 +    case DROP_REASON_BLOCKED:
   1.509 +        ALOGI("Dropped event because the current application is not responding and the user "
   1.510 +                "has started interacting with a different application.");
   1.511 +        reason = "inbound event was dropped because the current application is not responding "
   1.512 +                "and the user has started interacting with a different application";
   1.513 +        break;
   1.514 +    case DROP_REASON_STALE:
   1.515 +        ALOGI("Dropped event because it is stale.");
   1.516 +        reason = "inbound event was dropped because it is stale";
   1.517 +        break;
   1.518 +    default:
   1.519 +        ALOG_ASSERT(false);
   1.520 +        return;
   1.521 +    }
   1.522 +
   1.523 +    switch (entry->type) {
   1.524 +    case EventEntry::TYPE_KEY: {
   1.525 +        CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, reason);
   1.526 +        synthesizeCancelationEventsForAllConnectionsLocked(options);
   1.527 +        break;
   1.528 +    }
   1.529 +    case EventEntry::TYPE_MOTION: {
   1.530 +        MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
   1.531 +        if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
   1.532 +            CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, reason);
   1.533 +            synthesizeCancelationEventsForAllConnectionsLocked(options);
   1.534 +        } else {
   1.535 +            CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, reason);
   1.536 +            synthesizeCancelationEventsForAllConnectionsLocked(options);
   1.537 +        }
   1.538 +        break;
   1.539 +    }
   1.540 +    }
   1.541 +}
   1.542 +
   1.543 +bool InputDispatcher::isAppSwitchKeyCode(int32_t keyCode) {
   1.544 +    return keyCode == AKEYCODE_HOME
   1.545 +            || keyCode == AKEYCODE_ENDCALL
   1.546 +            || keyCode == AKEYCODE_APP_SWITCH;
   1.547 +}
   1.548 +
   1.549 +bool InputDispatcher::isAppSwitchKeyEventLocked(KeyEntry* keyEntry) {
   1.550 +    return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
   1.551 +            && isAppSwitchKeyCode(keyEntry->keyCode)
   1.552 +            && (keyEntry->policyFlags & POLICY_FLAG_TRUSTED)
   1.553 +            && (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
   1.554 +}
   1.555 +
   1.556 +bool InputDispatcher::isAppSwitchPendingLocked() {
   1.557 +    return mAppSwitchDueTime != LONG_LONG_MAX;
   1.558 +}
   1.559 +
   1.560 +void InputDispatcher::resetPendingAppSwitchLocked(bool handled) {
   1.561 +    mAppSwitchDueTime = LONG_LONG_MAX;
   1.562 +
   1.563 +#if DEBUG_APP_SWITCH
   1.564 +    if (handled) {
   1.565 +        ALOGD("App switch has arrived.");
   1.566 +    } else {
   1.567 +        ALOGD("App switch was abandoned.");
   1.568 +    }
   1.569 +#endif
   1.570 +}
   1.571 +
   1.572 +bool InputDispatcher::isStaleEventLocked(nsecs_t currentTime, EventEntry* entry) {
   1.573 +    return currentTime - entry->eventTime >= STALE_EVENT_TIMEOUT;
   1.574 +}
   1.575 +
   1.576 +bool InputDispatcher::haveCommandsLocked() const {
   1.577 +    return !mCommandQueue.isEmpty();
   1.578 +}
   1.579 +
   1.580 +bool InputDispatcher::runCommandsLockedInterruptible() {
   1.581 +    if (mCommandQueue.isEmpty()) {
   1.582 +        return false;
   1.583 +    }
   1.584 +
   1.585 +    do {
   1.586 +        CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
   1.587 +
   1.588 +        Command command = commandEntry->command;
   1.589 +        (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
   1.590 +
   1.591 +        commandEntry->connection.clear();
   1.592 +        delete commandEntry;
   1.593 +    } while (! mCommandQueue.isEmpty());
   1.594 +    return true;
   1.595 +}
   1.596 +
   1.597 +InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
   1.598 +    CommandEntry* commandEntry = new CommandEntry(command);
   1.599 +    mCommandQueue.enqueueAtTail(commandEntry);
   1.600 +    return commandEntry;
   1.601 +}
   1.602 +
   1.603 +void InputDispatcher::drainInboundQueueLocked() {
   1.604 +    while (! mInboundQueue.isEmpty()) {
   1.605 +        EventEntry* entry = mInboundQueue.dequeueAtHead();
   1.606 +        releaseInboundEventLocked(entry);
   1.607 +    }
   1.608 +    traceInboundQueueLengthLocked();
   1.609 +}
   1.610 +
   1.611 +void InputDispatcher::releasePendingEventLocked() {
   1.612 +    if (mPendingEvent) {
   1.613 +        resetANRTimeoutsLocked();
   1.614 +        releaseInboundEventLocked(mPendingEvent);
   1.615 +        mPendingEvent = NULL;
   1.616 +    }
   1.617 +}
   1.618 +
   1.619 +void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) {
   1.620 +    InjectionState* injectionState = entry->injectionState;
   1.621 +    if (injectionState && injectionState->injectionResult == INPUT_EVENT_INJECTION_PENDING) {
   1.622 +#if DEBUG_DISPATCH_CYCLE
   1.623 +        ALOGD("Injected inbound event was dropped.");
   1.624 +#endif
   1.625 +        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
   1.626 +    }
   1.627 +    if (entry == mNextUnblockedEvent) {
   1.628 +        mNextUnblockedEvent = NULL;
   1.629 +    }
   1.630 +    entry->release();
   1.631 +}
   1.632 +
   1.633 +void InputDispatcher::resetKeyRepeatLocked() {
   1.634 +    if (mKeyRepeatState.lastKeyEntry) {
   1.635 +        mKeyRepeatState.lastKeyEntry->release();
   1.636 +        mKeyRepeatState.lastKeyEntry = NULL;
   1.637 +    }
   1.638 +}
   1.639 +
   1.640 +InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(nsecs_t currentTime) {
   1.641 +    KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
   1.642 +
   1.643 +    // Reuse the repeated key entry if it is otherwise unreferenced.
   1.644 +    uint32_t policyFlags = (entry->policyFlags & POLICY_FLAG_RAW_MASK)
   1.645 +            | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED;
   1.646 +    if (entry->refCount == 1) {
   1.647 +        entry->recycle();
   1.648 +        entry->eventTime = currentTime;
   1.649 +        entry->policyFlags = policyFlags;
   1.650 +        entry->repeatCount += 1;
   1.651 +    } else {
   1.652 +        KeyEntry* newEntry = new KeyEntry(currentTime,
   1.653 +                entry->deviceId, entry->source, policyFlags,
   1.654 +                entry->action, entry->flags, entry->keyCode, entry->scanCode,
   1.655 +                entry->metaState, entry->repeatCount + 1, entry->downTime);
   1.656 +
   1.657 +        mKeyRepeatState.lastKeyEntry = newEntry;
   1.658 +        entry->release();
   1.659 +
   1.660 +        entry = newEntry;
   1.661 +    }
   1.662 +    entry->syntheticRepeat = true;
   1.663 +
   1.664 +    // Increment reference count since we keep a reference to the event in
   1.665 +    // mKeyRepeatState.lastKeyEntry in addition to the one we return.
   1.666 +    entry->refCount += 1;
   1.667 +
   1.668 +    mKeyRepeatState.nextRepeatTime = currentTime + mConfig.keyRepeatDelay;
   1.669 +    return entry;
   1.670 +}
   1.671 +
   1.672 +bool InputDispatcher::dispatchConfigurationChangedLocked(
   1.673 +        nsecs_t currentTime, ConfigurationChangedEntry* entry) {
   1.674 +#if DEBUG_OUTBOUND_EVENT_DETAILS
   1.675 +    ALOGD("dispatchConfigurationChanged - eventTime=%lld", entry->eventTime);
   1.676 +#endif
   1.677 +
   1.678 +    // Reset key repeating in case a keyboard device was added or removed or something.
   1.679 +    resetKeyRepeatLocked();
   1.680 +
   1.681 +    // Enqueue a command to run outside the lock to tell the policy that the configuration changed.
   1.682 +    CommandEntry* commandEntry = postCommandLocked(
   1.683 +            & InputDispatcher::doNotifyConfigurationChangedInterruptible);
   1.684 +    commandEntry->eventTime = entry->eventTime;
   1.685 +    return true;
   1.686 +}
   1.687 +
   1.688 +bool InputDispatcher::dispatchDeviceResetLocked(
   1.689 +        nsecs_t currentTime, DeviceResetEntry* entry) {
   1.690 +#if DEBUG_OUTBOUND_EVENT_DETAILS
   1.691 +    ALOGD("dispatchDeviceReset - eventTime=%lld, deviceId=%d", entry->eventTime, entry->deviceId);
   1.692 +#endif
   1.693 +
   1.694 +    CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS,
   1.695 +            "device was reset");
   1.696 +    options.deviceId = entry->deviceId;
   1.697 +    synthesizeCancelationEventsForAllConnectionsLocked(options);
   1.698 +    return true;
   1.699 +}
   1.700 +
   1.701 +bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
   1.702 +        DropReason* dropReason, nsecs_t* nextWakeupTime) {
   1.703 +    // Preprocessing.
   1.704 +    if (! entry->dispatchInProgress) {
   1.705 +        if (entry->repeatCount == 0
   1.706 +                && entry->action == AKEY_EVENT_ACTION_DOWN
   1.707 +                && (entry->policyFlags & POLICY_FLAG_TRUSTED)
   1.708 +                && (!(entry->policyFlags & POLICY_FLAG_DISABLE_KEY_REPEAT))) {
   1.709 +            if (mKeyRepeatState.lastKeyEntry
   1.710 +                    && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
   1.711 +                // We have seen two identical key downs in a row which indicates that the device
   1.712 +                // driver is automatically generating key repeats itself.  We take note of the
   1.713 +                // repeat here, but we disable our own next key repeat timer since it is clear that
   1.714 +                // we will not need to synthesize key repeats ourselves.
   1.715 +                entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
   1.716 +                resetKeyRepeatLocked();
   1.717 +                mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
   1.718 +            } else {
   1.719 +                // Not a repeat.  Save key down state in case we do see a repeat later.
   1.720 +                resetKeyRepeatLocked();
   1.721 +                mKeyRepeatState.nextRepeatTime = entry->eventTime + mConfig.keyRepeatTimeout;
   1.722 +            }
   1.723 +            mKeyRepeatState.lastKeyEntry = entry;
   1.724 +            entry->refCount += 1;
   1.725 +        } else if (! entry->syntheticRepeat) {
   1.726 +            resetKeyRepeatLocked();
   1.727 +        }
   1.728 +
   1.729 +        if (entry->repeatCount == 1) {
   1.730 +            entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
   1.731 +        } else {
   1.732 +            entry->flags &= ~AKEY_EVENT_FLAG_LONG_PRESS;
   1.733 +        }
   1.734 +
   1.735 +        entry->dispatchInProgress = true;
   1.736 +
   1.737 +        logOutboundKeyDetailsLocked("dispatchKey - ", entry);
   1.738 +    }
   1.739 +
   1.740 +    // Handle case where the policy asked us to try again later last time.
   1.741 +    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) {
   1.742 +        if (currentTime < entry->interceptKeyWakeupTime) {
   1.743 +            if (entry->interceptKeyWakeupTime < *nextWakeupTime) {
   1.744 +                *nextWakeupTime = entry->interceptKeyWakeupTime;
   1.745 +            }
   1.746 +            return false; // wait until next wakeup
   1.747 +        }
   1.748 +        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
   1.749 +        entry->interceptKeyWakeupTime = 0;
   1.750 +    }
   1.751 +
   1.752 +    // Give the policy a chance to intercept the key.
   1.753 +    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
   1.754 +        if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
   1.755 +            CommandEntry* commandEntry = postCommandLocked(
   1.756 +                    & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
   1.757 +            if (mFocusedWindowHandle != NULL) {
   1.758 +                commandEntry->inputWindowHandle = mFocusedWindowHandle;
   1.759 +            }
   1.760 +            commandEntry->keyEntry = entry;
   1.761 +            entry->refCount += 1;
   1.762 +            return false; // wait for the command to run
   1.763 +        } else {
   1.764 +            entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
   1.765 +        }
   1.766 +    } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
   1.767 +        if (*dropReason == DROP_REASON_NOT_DROPPED) {
   1.768 +            *dropReason = DROP_REASON_POLICY;
   1.769 +        }
   1.770 +    }
   1.771 +
   1.772 +    // Clean up if dropping the event.
   1.773 +    if (*dropReason != DROP_REASON_NOT_DROPPED) {
   1.774 +        setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
   1.775 +                ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
   1.776 +        return true;
   1.777 +    }
   1.778 +
   1.779 +    // Identify targets.
   1.780 +    Vector<InputTarget> inputTargets;
   1.781 +    int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
   1.782 +            entry, inputTargets, nextWakeupTime);
   1.783 +    if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
   1.784 +        return false;
   1.785 +    }
   1.786 +
   1.787 +    setInjectionResultLocked(entry, injectionResult);
   1.788 +    if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
   1.789 +        return true;
   1.790 +    }
   1.791 +
   1.792 +    addMonitoringTargetsLocked(inputTargets);
   1.793 +
   1.794 +    // Dispatch the key.
   1.795 +    dispatchEventLocked(currentTime, entry, inputTargets);
   1.796 +    return true;
   1.797 +}
   1.798 +
   1.799 +void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry) {
   1.800 +#if DEBUG_OUTBOUND_EVENT_DETAILS
   1.801 +    ALOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
   1.802 +            "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
   1.803 +            "repeatCount=%d, downTime=%lld",
   1.804 +            prefix,
   1.805 +            entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
   1.806 +            entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
   1.807 +            entry->repeatCount, entry->downTime);
   1.808 +#endif
   1.809 +}
   1.810 +
   1.811 +bool InputDispatcher::dispatchMotionLocked(
   1.812 +        nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
   1.813 +    // Preprocessing.
   1.814 +    if (! entry->dispatchInProgress) {
   1.815 +        entry->dispatchInProgress = true;
   1.816 +
   1.817 +        logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
   1.818 +    }
   1.819 +
   1.820 +    // Clean up if dropping the event.
   1.821 +    if (*dropReason != DROP_REASON_NOT_DROPPED) {
   1.822 +        setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
   1.823 +                ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
   1.824 +        return true;
   1.825 +    }
   1.826 +
   1.827 +    bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
   1.828 +
   1.829 +    // Identify targets.
   1.830 +    Vector<InputTarget> inputTargets;
   1.831 +
   1.832 +    bool conflictingPointerActions = false;
   1.833 +    int32_t injectionResult;
   1.834 +    if (isPointerEvent) {
   1.835 +        // Pointer event.  (eg. touchscreen)
   1.836 +        injectionResult = findTouchedWindowTargetsLocked(currentTime,
   1.837 +                entry, inputTargets, nextWakeupTime, &conflictingPointerActions);
   1.838 +    } else {
   1.839 +        // Non touch event.  (eg. trackball)
   1.840 +        injectionResult = findFocusedWindowTargetsLocked(currentTime,
   1.841 +                entry, inputTargets, nextWakeupTime);
   1.842 +    }
   1.843 +    if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
   1.844 +        return false;
   1.845 +    }
   1.846 +
   1.847 +    setInjectionResultLocked(entry, injectionResult);
   1.848 +    if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
   1.849 +        return true;
   1.850 +    }
   1.851 +
   1.852 +    // TODO: support sending secondary display events to input monitors
   1.853 +    if (isMainDisplay(entry->displayId)) {
   1.854 +        addMonitoringTargetsLocked(inputTargets);
   1.855 +    }
   1.856 +
   1.857 +    // Dispatch the motion.
   1.858 +    if (conflictingPointerActions) {
   1.859 +        CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
   1.860 +                "conflicting pointer actions");
   1.861 +        synthesizeCancelationEventsForAllConnectionsLocked(options);
   1.862 +    }
   1.863 +    dispatchEventLocked(currentTime, entry, inputTargets);
   1.864 +    return true;
   1.865 +}
   1.866 +
   1.867 +
   1.868 +void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) {
   1.869 +#if DEBUG_OUTBOUND_EVENT_DETAILS
   1.870 +    ALOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
   1.871 +            "action=0x%x, flags=0x%x, "
   1.872 +            "metaState=0x%x, buttonState=0x%x, "
   1.873 +            "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
   1.874 +            prefix,
   1.875 +            entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
   1.876 +            entry->action, entry->flags,
   1.877 +            entry->metaState, entry->buttonState,
   1.878 +            entry->edgeFlags, entry->xPrecision, entry->yPrecision,
   1.879 +            entry->downTime);
   1.880 +
   1.881 +    for (uint32_t i = 0; i < entry->pointerCount; i++) {
   1.882 +        ALOGD("  Pointer %d: id=%d, toolType=%d, "
   1.883 +                "x=%f, y=%f, pressure=%f, size=%f, "
   1.884 +                "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
   1.885 +                "orientation=%f",
   1.886 +                i, entry->pointerProperties[i].id,
   1.887 +                entry->pointerProperties[i].toolType,
   1.888 +                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
   1.889 +                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
   1.890 +                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
   1.891 +                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
   1.892 +                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
   1.893 +                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
   1.894 +                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
   1.895 +                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
   1.896 +                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
   1.897 +    }
   1.898 +#endif
   1.899 +}
   1.900 +
   1.901 +void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
   1.902 +        EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {
   1.903 +#if DEBUG_DISPATCH_CYCLE
   1.904 +    ALOGD("dispatchEventToCurrentInputTargets");
   1.905 +#endif
   1.906 +
   1.907 +    ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
   1.908 +
   1.909 +    pokeUserActivityLocked(eventEntry);
   1.910 +
   1.911 +    for (size_t i = 0; i < inputTargets.size(); i++) {
   1.912 +        const InputTarget& inputTarget = inputTargets.itemAt(i);
   1.913 +
   1.914 +        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
   1.915 +        if (connectionIndex >= 0) {
   1.916 +            sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
   1.917 +            prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
   1.918 +        } else {
   1.919 +#if DEBUG_FOCUS
   1.920 +            ALOGD("Dropping event delivery to target with channel '%s' because it "
   1.921 +                    "is no longer registered with the input dispatcher.",
   1.922 +                    inputTarget.inputChannel->getName().string());
   1.923 +#endif
   1.924 +        }
   1.925 +    }
   1.926 +}
   1.927 +
   1.928 +int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
   1.929 +        const EventEntry* entry,
   1.930 +        const sp<InputApplicationHandle>& applicationHandle,
   1.931 +        const sp<InputWindowHandle>& windowHandle,
   1.932 +        nsecs_t* nextWakeupTime, const char* reason) {
   1.933 +    if (applicationHandle == NULL && windowHandle == NULL) {
   1.934 +        if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
   1.935 +#if DEBUG_FOCUS
   1.936 +            ALOGD("Waiting for system to become ready for input.  Reason: %s", reason);
   1.937 +#endif
   1.938 +            mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
   1.939 +            mInputTargetWaitStartTime = currentTime;
   1.940 +            mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
   1.941 +            mInputTargetWaitTimeoutExpired = false;
   1.942 +            mInputTargetWaitApplicationHandle.clear();
   1.943 +        }
   1.944 +    } else {
   1.945 +        if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
   1.946 +#if DEBUG_FOCUS
   1.947 +            ALOGD("Waiting for application to become ready for input: %s.  Reason: %s",
   1.948 +                    getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(),
   1.949 +                    reason);
   1.950 +#endif
   1.951 +            nsecs_t timeout;
   1.952 +            if (windowHandle != NULL) {
   1.953 +                timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
   1.954 +            } else if (applicationHandle != NULL) {
   1.955 +                timeout = applicationHandle->getDispatchingTimeout(
   1.956 +                        DEFAULT_INPUT_DISPATCHING_TIMEOUT);
   1.957 +            } else {
   1.958 +                timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
   1.959 +            }
   1.960 +
   1.961 +            mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
   1.962 +            mInputTargetWaitStartTime = currentTime;
   1.963 +            mInputTargetWaitTimeoutTime = currentTime + timeout;
   1.964 +            mInputTargetWaitTimeoutExpired = false;
   1.965 +            mInputTargetWaitApplicationHandle.clear();
   1.966 +
   1.967 +            if (windowHandle != NULL) {
   1.968 +                mInputTargetWaitApplicationHandle = windowHandle->inputApplicationHandle;
   1.969 +            }
   1.970 +            if (mInputTargetWaitApplicationHandle == NULL && applicationHandle != NULL) {
   1.971 +                mInputTargetWaitApplicationHandle = applicationHandle;
   1.972 +            }
   1.973 +        }
   1.974 +    }
   1.975 +
   1.976 +    if (mInputTargetWaitTimeoutExpired) {
   1.977 +        return INPUT_EVENT_INJECTION_TIMED_OUT;
   1.978 +    }
   1.979 +
   1.980 +    if (currentTime >= mInputTargetWaitTimeoutTime) {
   1.981 +        onANRLocked(currentTime, applicationHandle, windowHandle,
   1.982 +                entry->eventTime, mInputTargetWaitStartTime, reason);
   1.983 +
   1.984 +        // Force poll loop to wake up immediately on next iteration once we get the
   1.985 +        // ANR response back from the policy.
   1.986 +        *nextWakeupTime = LONG_LONG_MIN;
   1.987 +        return INPUT_EVENT_INJECTION_PENDING;
   1.988 +    } else {
   1.989 +        // Force poll loop to wake up when timeout is due.
   1.990 +        if (mInputTargetWaitTimeoutTime < *nextWakeupTime) {
   1.991 +            *nextWakeupTime = mInputTargetWaitTimeoutTime;
   1.992 +        }
   1.993 +        return INPUT_EVENT_INJECTION_PENDING;
   1.994 +    }
   1.995 +}
   1.996 +
   1.997 +void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
   1.998 +        const sp<InputChannel>& inputChannel) {
   1.999 +    if (newTimeout > 0) {
  1.1000 +        // Extend the timeout.
  1.1001 +        mInputTargetWaitTimeoutTime = now() + newTimeout;
  1.1002 +    } else {
  1.1003 +        // Give up.
  1.1004 +        mInputTargetWaitTimeoutExpired = true;
  1.1005 +
  1.1006 +        // Input state will not be realistic.  Mark it out of sync.
  1.1007 +        if (inputChannel.get()) {
  1.1008 +            ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
  1.1009 +            if (connectionIndex >= 0) {
  1.1010 +                sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
  1.1011 +                sp<InputWindowHandle> windowHandle = connection->inputWindowHandle;
  1.1012 +
  1.1013 +                if (windowHandle != NULL) {
  1.1014 +                    mTouchState.removeWindow(windowHandle);
  1.1015 +                }
  1.1016 +
  1.1017 +                if (connection->status == Connection::STATUS_NORMAL) {
  1.1018 +                    CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS,
  1.1019 +                            "application not responding");
  1.1020 +                    synthesizeCancelationEventsForConnectionLocked(connection, options);
  1.1021 +                }
  1.1022 +            }
  1.1023 +        }
  1.1024 +    }
  1.1025 +}
  1.1026 +
  1.1027 +nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(
  1.1028 +        nsecs_t currentTime) {
  1.1029 +    if (mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
  1.1030 +        return currentTime - mInputTargetWaitStartTime;
  1.1031 +    }
  1.1032 +    return 0;
  1.1033 +}
  1.1034 +
  1.1035 +void InputDispatcher::resetANRTimeoutsLocked() {
  1.1036 +#if DEBUG_FOCUS
  1.1037 +        ALOGD("Resetting ANR timeouts.");
  1.1038 +#endif
  1.1039 +
  1.1040 +    // Reset input target wait timeout.
  1.1041 +    mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
  1.1042 +    mInputTargetWaitApplicationHandle.clear();
  1.1043 +}
  1.1044 +
  1.1045 +int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
  1.1046 +        const EventEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) {
  1.1047 +    int32_t injectionResult;
  1.1048 +
  1.1049 +    // If there is no currently focused window and no focused application
  1.1050 +    // then drop the event.
  1.1051 +    if (mFocusedWindowHandle == NULL) {
  1.1052 +        if (mFocusedApplicationHandle != NULL) {
  1.1053 +            injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
  1.1054 +                    mFocusedApplicationHandle, NULL, nextWakeupTime,
  1.1055 +                    "Waiting because no window has focus but there is a "
  1.1056 +                    "focused application that may eventually add a window "
  1.1057 +                    "when it finishes starting up.");
  1.1058 +            goto Unresponsive;
  1.1059 +        }
  1.1060 +
  1.1061 +        ALOGI("Dropping event because there is no focused window or focused application.");
  1.1062 +        injectionResult = INPUT_EVENT_INJECTION_FAILED;
  1.1063 +        goto Failed;
  1.1064 +    }
  1.1065 +
  1.1066 +    // Check permissions.
  1.1067 +    if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) {
  1.1068 +        injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
  1.1069 +        goto Failed;
  1.1070 +    }
  1.1071 +
  1.1072 +    // If the currently focused window is paused then keep waiting.
  1.1073 +    if (mFocusedWindowHandle->getInfo()->paused) {
  1.1074 +        injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
  1.1075 +                mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime,
  1.1076 +                "Waiting because the focused window is paused.");
  1.1077 +        goto Unresponsive;
  1.1078 +    }
  1.1079 +
  1.1080 +    // If the currently focused window is still working on previous events then keep waiting.
  1.1081 +    if (!isWindowReadyForMoreInputLocked(currentTime, mFocusedWindowHandle, entry)) {
  1.1082 +        injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
  1.1083 +                mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime,
  1.1084 +                "Waiting because the focused window has not finished "
  1.1085 +                "processing the input events that were previously delivered to it.");
  1.1086 +        goto Unresponsive;
  1.1087 +    }
  1.1088 +
  1.1089 +    // Success!  Output targets.
  1.1090 +    injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
  1.1091 +    addWindowTargetLocked(mFocusedWindowHandle,
  1.1092 +            InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0),
  1.1093 +            inputTargets);
  1.1094 +
  1.1095 +    // Done.
  1.1096 +Failed:
  1.1097 +Unresponsive:
  1.1098 +    nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
  1.1099 +    updateDispatchStatisticsLocked(currentTime, entry,
  1.1100 +            injectionResult, timeSpentWaitingForApplication);
  1.1101 +#if DEBUG_FOCUS
  1.1102 +    ALOGD("findFocusedWindow finished: injectionResult=%d, "
  1.1103 +            "timeSpentWaitingForApplication=%0.1fms",
  1.1104 +            injectionResult, timeSpentWaitingForApplication / 1000000.0);
  1.1105 +#endif
  1.1106 +    return injectionResult;
  1.1107 +}
  1.1108 +
  1.1109 +int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
  1.1110 +        const MotionEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,
  1.1111 +        bool* outConflictingPointerActions) {
  1.1112 +    enum InjectionPermission {
  1.1113 +        INJECTION_PERMISSION_UNKNOWN,
  1.1114 +        INJECTION_PERMISSION_GRANTED,
  1.1115 +        INJECTION_PERMISSION_DENIED
  1.1116 +    };
  1.1117 +
  1.1118 +    nsecs_t startTime = now();
  1.1119 +
  1.1120 +    // For security reasons, we defer updating the touch state until we are sure that
  1.1121 +    // event injection will be allowed.
  1.1122 +    //
  1.1123 +    // FIXME In the original code, screenWasOff could never be set to true.
  1.1124 +    //       The reason is that the POLICY_FLAG_WOKE_HERE
  1.1125 +    //       and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
  1.1126 +    //       EV_KEY, EV_REL and EV_ABS events.  As it happens, the touch event was
  1.1127 +    //       actually enqueued using the policyFlags that appeared in the final EV_SYN
  1.1128 +    //       events upon which no preprocessing took place.  So policyFlags was always 0.
  1.1129 +    //       In the new native input dispatcher we're a bit more careful about event
  1.1130 +    //       preprocessing so the touches we receive can actually have non-zero policyFlags.
  1.1131 +    //       Unfortunately we obtain undesirable behavior.
  1.1132 +    //
  1.1133 +    //       Here's what happens:
  1.1134 +    //
  1.1135 +    //       When the device dims in anticipation of going to sleep, touches
  1.1136 +    //       in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
  1.1137 +    //       the device to brighten and reset the user activity timer.
  1.1138 +    //       Touches on other windows (such as the launcher window)
  1.1139 +    //       are dropped.  Then after a moment, the device goes to sleep.  Oops.
  1.1140 +    //
  1.1141 +    //       Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
  1.1142 +    //       instead of POLICY_FLAG_WOKE_HERE...
  1.1143 +    //
  1.1144 +    bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
  1.1145 +
  1.1146 +    int32_t displayId = entry->displayId;
  1.1147 +    int32_t action = entry->action;
  1.1148 +    int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
  1.1149 +
  1.1150 +    // Update the touch state as needed based on the properties of the touch event.
  1.1151 +    int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING;
  1.1152 +    InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
  1.1153 +    sp<InputWindowHandle> newHoverWindowHandle;
  1.1154 +
  1.1155 +    bool isSplit = mTouchState.split;
  1.1156 +    bool switchedDevice = mTouchState.deviceId >= 0 && mTouchState.displayId >= 0
  1.1157 +            && (mTouchState.deviceId != entry->deviceId
  1.1158 +                    || mTouchState.source != entry->source
  1.1159 +                    || mTouchState.displayId != displayId);
  1.1160 +    bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
  1.1161 +            || maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
  1.1162 +            || maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT);
  1.1163 +    bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN
  1.1164 +            || maskedAction == AMOTION_EVENT_ACTION_SCROLL
  1.1165 +            || isHoverAction);
  1.1166 +    bool wrongDevice = false;
  1.1167 +    if (newGesture) {
  1.1168 +        bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
  1.1169 +        if (switchedDevice && mTouchState.down && !down) {
  1.1170 +#if DEBUG_FOCUS
  1.1171 +            ALOGD("Dropping event because a pointer for a different device is already down.");
  1.1172 +#endif
  1.1173 +            mTempTouchState.copyFrom(mTouchState);
  1.1174 +            injectionResult = INPUT_EVENT_INJECTION_FAILED;
  1.1175 +            switchedDevice = false;
  1.1176 +            wrongDevice = true;
  1.1177 +            goto Failed;
  1.1178 +        }
  1.1179 +        mTempTouchState.reset();
  1.1180 +        mTempTouchState.down = down;
  1.1181 +        mTempTouchState.deviceId = entry->deviceId;
  1.1182 +        mTempTouchState.source = entry->source;
  1.1183 +        mTempTouchState.displayId = displayId;
  1.1184 +        isSplit = false;
  1.1185 +    } else {
  1.1186 +        mTempTouchState.copyFrom(mTouchState);
  1.1187 +    }
  1.1188 +
  1.1189 +    if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
  1.1190 +        /* Case 1: New splittable pointer going down, or need target for hover or scroll. */
  1.1191 +
  1.1192 +        int32_t pointerIndex = getMotionEventActionPointerIndex(action);
  1.1193 +        int32_t x = int32_t(entry->pointerCoords[pointerIndex].
  1.1194 +                getAxisValue(AMOTION_EVENT_AXIS_X));
  1.1195 +        int32_t y = int32_t(entry->pointerCoords[pointerIndex].
  1.1196 +                getAxisValue(AMOTION_EVENT_AXIS_Y));
  1.1197 +        sp<InputWindowHandle> newTouchedWindowHandle;
  1.1198 +        sp<InputWindowHandle> topErrorWindowHandle;
  1.1199 +        bool isTouchModal = false;
  1.1200 +
  1.1201 +        // Traverse windows from front to back to find touched window and outside targets.
  1.1202 +        size_t numWindows = mWindowHandles.size();
  1.1203 +        for (size_t i = 0; i < numWindows; i++) {
  1.1204 +            sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
  1.1205 +            const InputWindowInfo* windowInfo = windowHandle->getInfo();
  1.1206 +            if (windowInfo->displayId != displayId) {
  1.1207 +                continue; // wrong display
  1.1208 +            }
  1.1209 +
  1.1210 +            int32_t flags = windowInfo->layoutParamsFlags;
  1.1211 +            if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) {
  1.1212 +                if (topErrorWindowHandle == NULL) {
  1.1213 +                    topErrorWindowHandle = windowHandle;
  1.1214 +                }
  1.1215 +            }
  1.1216 +
  1.1217 +            if (windowInfo->visible) {
  1.1218 +                if (! (flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
  1.1219 +                    isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE
  1.1220 +                            | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
  1.1221 +                    if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
  1.1222 +                        if (! screenWasOff
  1.1223 +                                || (flags & InputWindowInfo::FLAG_TOUCHABLE_WHEN_WAKING)) {
  1.1224 +                            newTouchedWindowHandle = windowHandle;
  1.1225 +                        }
  1.1226 +                        break; // found touched window, exit window loop
  1.1227 +                    }
  1.1228 +                }
  1.1229 +
  1.1230 +                if (maskedAction == AMOTION_EVENT_ACTION_DOWN
  1.1231 +                        && (flags & InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH)) {
  1.1232 +                    int32_t outsideTargetFlags = InputTarget::FLAG_DISPATCH_AS_OUTSIDE;
  1.1233 +                    if (isWindowObscuredAtPointLocked(windowHandle, x, y)) {
  1.1234 +                        outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
  1.1235 +                    }
  1.1236 +
  1.1237 +                    mTempTouchState.addOrUpdateWindow(
  1.1238 +                            windowHandle, outsideTargetFlags, BitSet32(0));
  1.1239 +                }
  1.1240 +            }
  1.1241 +        }
  1.1242 +
  1.1243 +        // If there is an error window but it is not taking focus (typically because
  1.1244 +        // it is invisible) then wait for it.  Any other focused window may in
  1.1245 +        // fact be in ANR state.
  1.1246 +        if (topErrorWindowHandle != NULL && newTouchedWindowHandle != topErrorWindowHandle) {
  1.1247 +            injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
  1.1248 +                    NULL, NULL, nextWakeupTime,
  1.1249 +                    "Waiting because a system error window is about to be displayed.");
  1.1250 +            injectionPermission = INJECTION_PERMISSION_UNKNOWN;
  1.1251 +            goto Unresponsive;
  1.1252 +        }
  1.1253 +
  1.1254 +        // Figure out whether splitting will be allowed for this window.
  1.1255 +        if (newTouchedWindowHandle != NULL
  1.1256 +                && newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
  1.1257 +            // New window supports splitting.
  1.1258 +            isSplit = true;
  1.1259 +        } else if (isSplit) {
  1.1260 +            // New window does not support splitting but we have already split events.
  1.1261 +            // Ignore the new window.
  1.1262 +            newTouchedWindowHandle = NULL;
  1.1263 +        }
  1.1264 +
  1.1265 +        // Handle the case where we did not find a window.
  1.1266 +        if (newTouchedWindowHandle == NULL) {
  1.1267 +            // Try to assign the pointer to the first foreground window we find, if there is one.
  1.1268 +            newTouchedWindowHandle = mTempTouchState.getFirstForegroundWindowHandle();
  1.1269 +            if (newTouchedWindowHandle == NULL) {
  1.1270 +                // There is no touched window.  If this is an initial down event
  1.1271 +                // then wait for a window to appear that will handle the touch.  This is
  1.1272 +                // to ensure that we report an ANR in the case where an application has started
  1.1273 +                // but not yet put up a window and the user is starting to get impatient.
  1.1274 +                if (maskedAction == AMOTION_EVENT_ACTION_DOWN
  1.1275 +                        && mFocusedApplicationHandle != NULL) {
  1.1276 +                    injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
  1.1277 +                            mFocusedApplicationHandle, NULL, nextWakeupTime,
  1.1278 +                            "Waiting because there is no touchable window that can "
  1.1279 +                            "handle the event but there is focused application that may "
  1.1280 +                            "eventually add a new window when it finishes starting up.");
  1.1281 +                    goto Unresponsive;
  1.1282 +                }
  1.1283 +
  1.1284 +                ALOGI("Dropping event because there is no touched window.");
  1.1285 +                injectionResult = INPUT_EVENT_INJECTION_FAILED;
  1.1286 +                goto Failed;
  1.1287 +            }
  1.1288 +        }
  1.1289 +
  1.1290 +        // Set target flags.
  1.1291 +        int32_t targetFlags = InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS;
  1.1292 +        if (isSplit) {
  1.1293 +            targetFlags |= InputTarget::FLAG_SPLIT;
  1.1294 +        }
  1.1295 +        if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
  1.1296 +            targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
  1.1297 +        }
  1.1298 +
  1.1299 +        // Update hover state.
  1.1300 +        if (isHoverAction) {
  1.1301 +            newHoverWindowHandle = newTouchedWindowHandle;
  1.1302 +        } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
  1.1303 +            newHoverWindowHandle = mLastHoverWindowHandle;
  1.1304 +        }
  1.1305 +
  1.1306 +        // Update the temporary touch state.
  1.1307 +        BitSet32 pointerIds;
  1.1308 +        if (isSplit) {
  1.1309 +            uint32_t pointerId = entry->pointerProperties[pointerIndex].id;
  1.1310 +            pointerIds.markBit(pointerId);
  1.1311 +        }
  1.1312 +        mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
  1.1313 +    } else {
  1.1314 +        /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */
  1.1315 +
  1.1316 +        // If the pointer is not currently down, then ignore the event.
  1.1317 +        if (! mTempTouchState.down) {
  1.1318 +#if DEBUG_FOCUS
  1.1319 +            ALOGD("Dropping event because the pointer is not down or we previously "
  1.1320 +                    "dropped the pointer down event.");
  1.1321 +#endif
  1.1322 +            injectionResult = INPUT_EVENT_INJECTION_FAILED;
  1.1323 +            goto Failed;
  1.1324 +        }
  1.1325 +
  1.1326 +        // Check whether touches should slip outside of the current foreground window.
  1.1327 +        if (maskedAction == AMOTION_EVENT_ACTION_MOVE
  1.1328 +                && entry->pointerCount == 1
  1.1329 +                && mTempTouchState.isSlippery()) {
  1.1330 +            int32_t x = int32_t(entry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
  1.1331 +            int32_t y = int32_t(entry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
  1.1332 +
  1.1333 +            sp<InputWindowHandle> oldTouchedWindowHandle =
  1.1334 +                    mTempTouchState.getFirstForegroundWindowHandle();
  1.1335 +            sp<InputWindowHandle> newTouchedWindowHandle =
  1.1336 +                    findTouchedWindowAtLocked(displayId, x, y);
  1.1337 +            if (oldTouchedWindowHandle != newTouchedWindowHandle
  1.1338 +                    && newTouchedWindowHandle != NULL) {
  1.1339 +#if DEBUG_FOCUS
  1.1340 +                ALOGD("Touch is slipping out of window %s into window %s.",
  1.1341 +                        oldTouchedWindowHandle->getName().string(),
  1.1342 +                        newTouchedWindowHandle->getName().string());
  1.1343 +#endif
  1.1344 +                // Make a slippery exit from the old window.
  1.1345 +                mTempTouchState.addOrUpdateWindow(oldTouchedWindowHandle,
  1.1346 +                        InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT, BitSet32(0));
  1.1347 +
  1.1348 +                // Make a slippery entrance into the new window.
  1.1349 +                if (newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
  1.1350 +                    isSplit = true;
  1.1351 +                }
  1.1352 +
  1.1353 +                int32_t targetFlags = InputTarget::FLAG_FOREGROUND
  1.1354 +                        | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER;
  1.1355 +                if (isSplit) {
  1.1356 +                    targetFlags |= InputTarget::FLAG_SPLIT;
  1.1357 +                }
  1.1358 +                if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
  1.1359 +                    targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
  1.1360 +                }
  1.1361 +
  1.1362 +                BitSet32 pointerIds;
  1.1363 +                if (isSplit) {
  1.1364 +                    pointerIds.markBit(entry->pointerProperties[0].id);
  1.1365 +                }
  1.1366 +                mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
  1.1367 +            }
  1.1368 +        }
  1.1369 +    }
  1.1370 +
  1.1371 +    if (newHoverWindowHandle != mLastHoverWindowHandle) {
  1.1372 +        // Let the previous window know that the hover sequence is over.
  1.1373 +        if (mLastHoverWindowHandle != NULL) {
  1.1374 +#if DEBUG_HOVER
  1.1375 +            ALOGD("Sending hover exit event to window %s.",
  1.1376 +                    mLastHoverWindowHandle->getName().string());
  1.1377 +#endif
  1.1378 +            mTempTouchState.addOrUpdateWindow(mLastHoverWindowHandle,
  1.1379 +                    InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT, BitSet32(0));
  1.1380 +        }
  1.1381 +
  1.1382 +        // Let the new window know that the hover sequence is starting.
  1.1383 +        if (newHoverWindowHandle != NULL) {
  1.1384 +#if DEBUG_HOVER
  1.1385 +            ALOGD("Sending hover enter event to window %s.",
  1.1386 +                    newHoverWindowHandle->getName().string());
  1.1387 +#endif
  1.1388 +            mTempTouchState.addOrUpdateWindow(newHoverWindowHandle,
  1.1389 +                    InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER, BitSet32(0));
  1.1390 +        }
  1.1391 +    }
  1.1392 +
  1.1393 +    // Check permission to inject into all touched foreground windows and ensure there
  1.1394 +    // is at least one touched foreground window.
  1.1395 +    {
  1.1396 +        bool haveForegroundWindow = false;
  1.1397 +        for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
  1.1398 +            const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
  1.1399 +            if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
  1.1400 +                haveForegroundWindow = true;
  1.1401 +                if (! checkInjectionPermission(touchedWindow.windowHandle,
  1.1402 +                        entry->injectionState)) {
  1.1403 +                    injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
  1.1404 +                    injectionPermission = INJECTION_PERMISSION_DENIED;
  1.1405 +                    goto Failed;
  1.1406 +                }
  1.1407 +            }
  1.1408 +        }
  1.1409 +        if (! haveForegroundWindow) {
  1.1410 +#if DEBUG_FOCUS
  1.1411 +            ALOGD("Dropping event because there is no touched foreground window to receive it.");
  1.1412 +#endif
  1.1413 +            injectionResult = INPUT_EVENT_INJECTION_FAILED;
  1.1414 +            goto Failed;
  1.1415 +        }
  1.1416 +
  1.1417 +        // Permission granted to injection into all touched foreground windows.
  1.1418 +        injectionPermission = INJECTION_PERMISSION_GRANTED;
  1.1419 +    }
  1.1420 +
  1.1421 +    // Check whether windows listening for outside touches are owned by the same UID. If it is
  1.1422 +    // set the policy flag that we will not reveal coordinate information to this window.
  1.1423 +    if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
  1.1424 +        sp<InputWindowHandle> foregroundWindowHandle =
  1.1425 +                mTempTouchState.getFirstForegroundWindowHandle();
  1.1426 +        const int32_t foregroundWindowUid = foregroundWindowHandle->getInfo()->ownerUid;
  1.1427 +        for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
  1.1428 +            const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
  1.1429 +            if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
  1.1430 +                sp<InputWindowHandle> inputWindowHandle = touchedWindow.windowHandle;
  1.1431 +                if (inputWindowHandle->getInfo()->ownerUid != foregroundWindowUid) {
  1.1432 +                    mTempTouchState.addOrUpdateWindow(inputWindowHandle,
  1.1433 +                            InputTarget::FLAG_ZERO_COORDS, BitSet32(0));
  1.1434 +                }
  1.1435 +            }
  1.1436 +        }
  1.1437 +    }
  1.1438 +
  1.1439 +    // Ensure all touched foreground windows are ready for new input.
  1.1440 +    for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
  1.1441 +        const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
  1.1442 +        if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
  1.1443 +            // If the touched window is paused then keep waiting.
  1.1444 +            if (touchedWindow.windowHandle->getInfo()->paused) {
  1.1445 +                injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
  1.1446 +                        NULL, touchedWindow.windowHandle, nextWakeupTime,
  1.1447 +                        "Waiting because the touched window is paused.");
  1.1448 +                goto Unresponsive;
  1.1449 +            }
  1.1450 +
  1.1451 +            // If the touched window is still working on previous events then keep waiting.
  1.1452 +            if (!isWindowReadyForMoreInputLocked(currentTime, touchedWindow.windowHandle, entry)) {
  1.1453 +                injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
  1.1454 +                        NULL, touchedWindow.windowHandle, nextWakeupTime,
  1.1455 +                        "Waiting because the touched window has not finished "
  1.1456 +                        "processing the input events that were previously delivered to it.");
  1.1457 +                goto Unresponsive;
  1.1458 +            }
  1.1459 +        }
  1.1460 +    }
  1.1461 +
  1.1462 +    // If this is the first pointer going down and the touched window has a wallpaper
  1.1463 +    // then also add the touched wallpaper windows so they are locked in for the duration
  1.1464 +    // of the touch gesture.
  1.1465 +    // We do not collect wallpapers during HOVER_MOVE or SCROLL because the wallpaper
  1.1466 +    // engine only supports touch events.  We would need to add a mechanism similar
  1.1467 +    // to View.onGenericMotionEvent to enable wallpapers to handle these events.
  1.1468 +    if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
  1.1469 +        sp<InputWindowHandle> foregroundWindowHandle =
  1.1470 +                mTempTouchState.getFirstForegroundWindowHandle();
  1.1471 +        if (foregroundWindowHandle->getInfo()->hasWallpaper) {
  1.1472 +            for (size_t i = 0; i < mWindowHandles.size(); i++) {
  1.1473 +                sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
  1.1474 +                const InputWindowInfo* info = windowHandle->getInfo();
  1.1475 +                if (info->displayId == displayId
  1.1476 +                        && windowHandle->getInfo()->layoutParamsType
  1.1477 +                                == InputWindowInfo::TYPE_WALLPAPER) {
  1.1478 +                    mTempTouchState.addOrUpdateWindow(windowHandle,
  1.1479 +                            InputTarget::FLAG_WINDOW_IS_OBSCURED
  1.1480 +                                    | InputTarget::FLAG_DISPATCH_AS_IS,
  1.1481 +                            BitSet32(0));
  1.1482 +                }
  1.1483 +            }
  1.1484 +        }
  1.1485 +    }
  1.1486 +
  1.1487 +    // Success!  Output targets.
  1.1488 +    injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
  1.1489 +
  1.1490 +    for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
  1.1491 +        const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
  1.1492 +        addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
  1.1493 +                touchedWindow.pointerIds, inputTargets);
  1.1494 +    }
  1.1495 +
  1.1496 +    // Drop the outside or hover touch windows since we will not care about them
  1.1497 +    // in the next iteration.
  1.1498 +    mTempTouchState.filterNonAsIsTouchWindows();
  1.1499 +
  1.1500 +Failed:
  1.1501 +    // Check injection permission once and for all.
  1.1502 +    if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
  1.1503 +        if (checkInjectionPermission(NULL, entry->injectionState)) {
  1.1504 +            injectionPermission = INJECTION_PERMISSION_GRANTED;
  1.1505 +        } else {
  1.1506 +            injectionPermission = INJECTION_PERMISSION_DENIED;
  1.1507 +        }
  1.1508 +    }
  1.1509 +
  1.1510 +    // Update final pieces of touch state if the injector had permission.
  1.1511 +    if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
  1.1512 +        if (!wrongDevice) {
  1.1513 +            if (switchedDevice) {
  1.1514 +#if DEBUG_FOCUS
  1.1515 +                ALOGD("Conflicting pointer actions: Switched to a different device.");
  1.1516 +#endif
  1.1517 +                *outConflictingPointerActions = true;
  1.1518 +            }
  1.1519 +
  1.1520 +            if (isHoverAction) {
  1.1521 +                // Started hovering, therefore no longer down.
  1.1522 +                if (mTouchState.down) {
  1.1523 +#if DEBUG_FOCUS
  1.1524 +                    ALOGD("Conflicting pointer actions: Hover received while pointer was down.");
  1.1525 +#endif
  1.1526 +                    *outConflictingPointerActions = true;
  1.1527 +                }
  1.1528 +                mTouchState.reset();
  1.1529 +                if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
  1.1530 +                        || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
  1.1531 +                    mTouchState.deviceId = entry->deviceId;
  1.1532 +                    mTouchState.source = entry->source;
  1.1533 +                    mTouchState.displayId = displayId;
  1.1534 +                }
  1.1535 +            } else if (maskedAction == AMOTION_EVENT_ACTION_UP
  1.1536 +                    || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
  1.1537 +                // All pointers up or canceled.
  1.1538 +                mTouchState.reset();
  1.1539 +            } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
  1.1540 +                // First pointer went down.
  1.1541 +                if (mTouchState.down) {
  1.1542 +#if DEBUG_FOCUS
  1.1543 +                    ALOGD("Conflicting pointer actions: Down received while already down.");
  1.1544 +#endif
  1.1545 +                    *outConflictingPointerActions = true;
  1.1546 +                }
  1.1547 +                mTouchState.copyFrom(mTempTouchState);
  1.1548 +            } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
  1.1549 +                // One pointer went up.
  1.1550 +                if (isSplit) {
  1.1551 +                    int32_t pointerIndex = getMotionEventActionPointerIndex(action);
  1.1552 +                    uint32_t pointerId = entry->pointerProperties[pointerIndex].id;
  1.1553 +
  1.1554 +                    for (size_t i = 0; i < mTempTouchState.windows.size(); ) {
  1.1555 +                        TouchedWindow& touchedWindow = mTempTouchState.windows.editItemAt(i);
  1.1556 +                        if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
  1.1557 +                            touchedWindow.pointerIds.clearBit(pointerId);
  1.1558 +                            if (touchedWindow.pointerIds.isEmpty()) {
  1.1559 +                                mTempTouchState.windows.removeAt(i);
  1.1560 +                                continue;
  1.1561 +                            }
  1.1562 +                        }
  1.1563 +                        i += 1;
  1.1564 +                    }
  1.1565 +                }
  1.1566 +                mTouchState.copyFrom(mTempTouchState);
  1.1567 +            } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
  1.1568 +                // Discard temporary touch state since it was only valid for this action.
  1.1569 +            } else {
  1.1570 +                // Save changes to touch state as-is for all other actions.
  1.1571 +                mTouchState.copyFrom(mTempTouchState);
  1.1572 +            }
  1.1573 +
  1.1574 +            // Update hover state.
  1.1575 +            mLastHoverWindowHandle = newHoverWindowHandle;
  1.1576 +        }
  1.1577 +    } else {
  1.1578 +#if DEBUG_FOCUS
  1.1579 +        ALOGD("Not updating touch focus because injection was denied.");
  1.1580 +#endif
  1.1581 +    }
  1.1582 +
  1.1583 +Unresponsive:
  1.1584 +    // Reset temporary touch state to ensure we release unnecessary references to input channels.
  1.1585 +    mTempTouchState.reset();
  1.1586 +
  1.1587 +    nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
  1.1588 +    updateDispatchStatisticsLocked(currentTime, entry,
  1.1589 +            injectionResult, timeSpentWaitingForApplication);
  1.1590 +#if DEBUG_FOCUS
  1.1591 +    ALOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d, "
  1.1592 +            "timeSpentWaitingForApplication=%0.1fms",
  1.1593 +            injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0);
  1.1594 +#endif
  1.1595 +    return injectionResult;
  1.1596 +}
  1.1597 +
  1.1598 +void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
  1.1599 +        int32_t targetFlags, BitSet32 pointerIds, Vector<InputTarget>& inputTargets) {
  1.1600 +    inputTargets.push();
  1.1601 +
  1.1602 +    const InputWindowInfo* windowInfo = windowHandle->getInfo();
  1.1603 +    InputTarget& target = inputTargets.editTop();
  1.1604 +    target.inputChannel = windowInfo->inputChannel;
  1.1605 +    target.flags = targetFlags;
  1.1606 +    target.xOffset = - windowInfo->frameLeft;
  1.1607 +    target.yOffset = - windowInfo->frameTop;
  1.1608 +    target.scaleFactor = windowInfo->scaleFactor;
  1.1609 +    target.pointerIds = pointerIds;
  1.1610 +}
  1.1611 +
  1.1612 +void InputDispatcher::addMonitoringTargetsLocked(Vector<InputTarget>& inputTargets) {
  1.1613 +    for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
  1.1614 +        inputTargets.push();
  1.1615 +
  1.1616 +        InputTarget& target = inputTargets.editTop();
  1.1617 +        target.inputChannel = mMonitoringChannels[i];
  1.1618 +        target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
  1.1619 +        target.xOffset = 0;
  1.1620 +        target.yOffset = 0;
  1.1621 +        target.pointerIds.clear();
  1.1622 +        target.scaleFactor = 1.0f;
  1.1623 +    }
  1.1624 +}
  1.1625 +
  1.1626 +bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
  1.1627 +        const InjectionState* injectionState) {
  1.1628 +    if (injectionState
  1.1629 +            && (windowHandle == NULL
  1.1630 +                    || windowHandle->getInfo()->ownerUid != injectionState->injectorUid)
  1.1631 +            && !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
  1.1632 +        if (windowHandle != NULL) {
  1.1633 +            ALOGW("Permission denied: injecting event from pid %d uid %d to window %s "
  1.1634 +                    "owned by uid %d",
  1.1635 +                    injectionState->injectorPid, injectionState->injectorUid,
  1.1636 +                    windowHandle->getName().string(),
  1.1637 +                    windowHandle->getInfo()->ownerUid);
  1.1638 +        } else {
  1.1639 +            ALOGW("Permission denied: injecting event from pid %d uid %d",
  1.1640 +                    injectionState->injectorPid, injectionState->injectorUid);
  1.1641 +        }
  1.1642 +        return false;
  1.1643 +    }
  1.1644 +    return true;
  1.1645 +}
  1.1646 +
  1.1647 +bool InputDispatcher::isWindowObscuredAtPointLocked(
  1.1648 +        const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const {
  1.1649 +    int32_t displayId = windowHandle->getInfo()->displayId;
  1.1650 +    size_t numWindows = mWindowHandles.size();
  1.1651 +    for (size_t i = 0; i < numWindows; i++) {
  1.1652 +        sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
  1.1653 +        if (otherHandle == windowHandle) {
  1.1654 +            break;
  1.1655 +        }
  1.1656 +
  1.1657 +        const InputWindowInfo* otherInfo = otherHandle->getInfo();
  1.1658 +        if (otherInfo->displayId == displayId
  1.1659 +                && otherInfo->visible && !otherInfo->isTrustedOverlay()
  1.1660 +                && otherInfo->frameContainsPoint(x, y)) {
  1.1661 +            return true;
  1.1662 +        }
  1.1663 +    }
  1.1664 +    return false;
  1.1665 +}
  1.1666 +
  1.1667 +bool InputDispatcher::isWindowReadyForMoreInputLocked(nsecs_t currentTime,
  1.1668 +        const sp<InputWindowHandle>& windowHandle, const EventEntry* eventEntry) {
  1.1669 +    ssize_t connectionIndex = getConnectionIndexLocked(windowHandle->getInputChannel());
  1.1670 +    if (connectionIndex >= 0) {
  1.1671 +        sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
  1.1672 +        if (connection->inputPublisherBlocked) {
  1.1673 +            return false;
  1.1674 +        }
  1.1675 +        if (eventEntry->type == EventEntry::TYPE_KEY) {
  1.1676 +            // If the event is a key event, then we must wait for all previous events to
  1.1677 +            // complete before delivering it because previous events may have the
  1.1678 +            // side-effect of transferring focus to a different window and we want to
  1.1679 +            // ensure that the following keys are sent to the new window.
  1.1680 +            //
  1.1681 +            // Suppose the user touches a button in a window then immediately presses "A".
  1.1682 +            // If the button causes a pop-up window to appear then we want to ensure that
  1.1683 +            // the "A" key is delivered to the new pop-up window.  This is because users
  1.1684 +            // often anticipate pending UI changes when typing on a keyboard.
  1.1685 +            // To obtain this behavior, we must serialize key events with respect to all
  1.1686 +            // prior input events.
  1.1687 +            return connection->outboundQueue.isEmpty()
  1.1688 +                    && connection->waitQueue.isEmpty();
  1.1689 +        }
  1.1690 +        // Touch events can always be sent to a window immediately because the user intended
  1.1691 +        // to touch whatever was visible at the time.  Even if focus changes or a new
  1.1692 +        // window appears moments later, the touch event was meant to be delivered to
  1.1693 +        // whatever window happened to be on screen at the time.
  1.1694 +        //
  1.1695 +        // Generic motion events, such as trackball or joystick events are a little trickier.
  1.1696 +        // Like key events, generic motion events are delivered to the focused window.
  1.1697 +        // Unlike key events, generic motion events don't tend to transfer focus to other
  1.1698 +        // windows and it is not important for them to be serialized.  So we prefer to deliver
  1.1699 +        // generic motion events as soon as possible to improve efficiency and reduce lag
  1.1700 +        // through batching.
  1.1701 +        //
  1.1702 +        // The one case where we pause input event delivery is when the wait queue is piling
  1.1703 +        // up with lots of events because the application is not responding.
  1.1704 +        // This condition ensures that ANRs are detected reliably.
  1.1705 +        if (!connection->waitQueue.isEmpty()
  1.1706 +                && currentTime >= connection->waitQueue.head->eventEntry->eventTime
  1.1707 +                        + STREAM_AHEAD_EVENT_TIMEOUT) {
  1.1708 +            return false;
  1.1709 +        }
  1.1710 +    }
  1.1711 +    return true;
  1.1712 +}
  1.1713 +
  1.1714 +String8 InputDispatcher::getApplicationWindowLabelLocked(
  1.1715 +        const sp<InputApplicationHandle>& applicationHandle,
  1.1716 +        const sp<InputWindowHandle>& windowHandle) {
  1.1717 +    if (applicationHandle != NULL) {
  1.1718 +        if (windowHandle != NULL) {
  1.1719 +            String8 label(applicationHandle->getName());
  1.1720 +            label.append(" - ");
  1.1721 +            label.append(windowHandle->getName());
  1.1722 +            return label;
  1.1723 +        } else {
  1.1724 +            return applicationHandle->getName();
  1.1725 +        }
  1.1726 +    } else if (windowHandle != NULL) {
  1.1727 +        return windowHandle->getName();
  1.1728 +    } else {
  1.1729 +        return String8("<unknown application or window>");
  1.1730 +    }
  1.1731 +}
  1.1732 +
  1.1733 +void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
  1.1734 +    if (mFocusedWindowHandle != NULL) {
  1.1735 +        const InputWindowInfo* info = mFocusedWindowHandle->getInfo();
  1.1736 +        if (info->inputFeatures & InputWindowInfo::INPUT_FEATURE_DISABLE_USER_ACTIVITY) {
  1.1737 +#if DEBUG_DISPATCH_CYCLE
  1.1738 +            ALOGD("Not poking user activity: disabled by window '%s'.", info->name.string());
  1.1739 +#endif
  1.1740 +            return;
  1.1741 +        }
  1.1742 +    }
  1.1743 +
  1.1744 +    int32_t eventType = USER_ACTIVITY_EVENT_OTHER;
  1.1745 +    switch (eventEntry->type) {
  1.1746 +    case EventEntry::TYPE_MOTION: {
  1.1747 +        const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
  1.1748 +        if (motionEntry->action == AMOTION_EVENT_ACTION_CANCEL) {
  1.1749 +            return;
  1.1750 +        }
  1.1751 +
  1.1752 +        if (MotionEvent::isTouchEvent(motionEntry->source, motionEntry->action)) {
  1.1753 +            eventType = USER_ACTIVITY_EVENT_TOUCH;
  1.1754 +        }
  1.1755 +        break;
  1.1756 +    }
  1.1757 +    case EventEntry::TYPE_KEY: {
  1.1758 +        const KeyEntry* keyEntry = static_cast<const KeyEntry*>(eventEntry);
  1.1759 +        if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
  1.1760 +            return;
  1.1761 +        }
  1.1762 +        eventType = USER_ACTIVITY_EVENT_BUTTON;
  1.1763 +        break;
  1.1764 +    }
  1.1765 +    }
  1.1766 +
  1.1767 +    CommandEntry* commandEntry = postCommandLocked(
  1.1768 +            & InputDispatcher::doPokeUserActivityLockedInterruptible);
  1.1769 +    commandEntry->eventTime = eventEntry->eventTime;
  1.1770 +    commandEntry->userActivityEventType = eventType;
  1.1771 +}
  1.1772 +
  1.1773 +void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
  1.1774 +        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
  1.1775 +#if DEBUG_DISPATCH_CYCLE
  1.1776 +    ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, "
  1.1777 +            "xOffset=%f, yOffset=%f, scaleFactor=%f, "
  1.1778 +            "pointerIds=0x%x",
  1.1779 +            connection->getInputChannelName(), inputTarget->flags,
  1.1780 +            inputTarget->xOffset, inputTarget->yOffset,
  1.1781 +            inputTarget->scaleFactor, inputTarget->pointerIds.value);
  1.1782 +#endif
  1.1783 +
  1.1784 +    // Skip this event if the connection status is not normal.
  1.1785 +    // We don't want to enqueue additional outbound events if the connection is broken.
  1.1786 +    if (connection->status != Connection::STATUS_NORMAL) {
  1.1787 +#if DEBUG_DISPATCH_CYCLE
  1.1788 +        ALOGD("channel '%s' ~ Dropping event because the channel status is %s",
  1.1789 +                connection->getInputChannelName(), connection->getStatusLabel());
  1.1790 +#endif
  1.1791 +        return;
  1.1792 +    }
  1.1793 +
  1.1794 +    // Split a motion event if needed.
  1.1795 +    if (inputTarget->flags & InputTarget::FLAG_SPLIT) {
  1.1796 +        ALOG_ASSERT(eventEntry->type == EventEntry::TYPE_MOTION);
  1.1797 +
  1.1798 +        MotionEntry* originalMotionEntry = static_cast<MotionEntry*>(eventEntry);
  1.1799 +        if (inputTarget->pointerIds.count() != originalMotionEntry->pointerCount) {
  1.1800 +            MotionEntry* splitMotionEntry = splitMotionEvent(
  1.1801 +                    originalMotionEntry, inputTarget->pointerIds);
  1.1802 +            if (!splitMotionEntry) {
  1.1803 +                return; // split event was dropped
  1.1804 +            }
  1.1805 +#if DEBUG_FOCUS
  1.1806 +            ALOGD("channel '%s' ~ Split motion event.",
  1.1807 +                    connection->getInputChannelName());
  1.1808 +            logOutboundMotionDetailsLocked("  ", splitMotionEntry);
  1.1809 +#endif
  1.1810 +            enqueueDispatchEntriesLocked(currentTime, connection,
  1.1811 +                    splitMotionEntry, inputTarget);
  1.1812 +            splitMotionEntry->release();
  1.1813 +            return;
  1.1814 +        }
  1.1815 +    }
  1.1816 +
  1.1817 +    // Not splitting.  Enqueue dispatch entries for the event as is.
  1.1818 +    enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
  1.1819 +}
  1.1820 +
  1.1821 +void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
  1.1822 +        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
  1.1823 +    bool wasEmpty = connection->outboundQueue.isEmpty();
  1.1824 +
  1.1825 +    // Enqueue dispatch entries for the requested modes.
  1.1826 +    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
  1.1827 +            InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
  1.1828 +    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
  1.1829 +            InputTarget::FLAG_DISPATCH_AS_OUTSIDE);
  1.1830 +    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
  1.1831 +            InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
  1.1832 +    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
  1.1833 +            InputTarget::FLAG_DISPATCH_AS_IS);
  1.1834 +    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
  1.1835 +            InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
  1.1836 +    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
  1.1837 +            InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
  1.1838 +
  1.1839 +    // If the outbound queue was previously empty, start the dispatch cycle going.
  1.1840 +    if (wasEmpty && !connection->outboundQueue.isEmpty()) {
  1.1841 +        startDispatchCycleLocked(currentTime, connection);
  1.1842 +    }
  1.1843 +}
  1.1844 +
  1.1845 +void InputDispatcher::enqueueDispatchEntryLocked(
  1.1846 +        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
  1.1847 +        int32_t dispatchMode) {
  1.1848 +    int32_t inputTargetFlags = inputTarget->flags;
  1.1849 +    if (!(inputTargetFlags & dispatchMode)) {
  1.1850 +        return;
  1.1851 +    }
  1.1852 +    inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode;
  1.1853 +
  1.1854 +    // This is a new event.
  1.1855 +    // Enqueue a new dispatch entry onto the outbound queue for this connection.
  1.1856 +    DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments ref
  1.1857 +            inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset,
  1.1858 +            inputTarget->scaleFactor);
  1.1859 +
  1.1860 +    // Apply target flags and update the connection's input state.
  1.1861 +    switch (eventEntry->type) {
  1.1862 +    case EventEntry::TYPE_KEY: {
  1.1863 +        KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
  1.1864 +        dispatchEntry->resolvedAction = keyEntry->action;
  1.1865 +        dispatchEntry->resolvedFlags = keyEntry->flags;
  1.1866 +
  1.1867 +        if (!connection->inputState.trackKey(keyEntry,
  1.1868 +                dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
  1.1869 +#if DEBUG_DISPATCH_CYCLE
  1.1870 +            ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event",
  1.1871 +                    connection->getInputChannelName());
  1.1872 +#endif
  1.1873 +            delete dispatchEntry;
  1.1874 +            return; // skip the inconsistent event
  1.1875 +        }
  1.1876 +        break;
  1.1877 +    }
  1.1878 +
  1.1879 +    case EventEntry::TYPE_MOTION: {
  1.1880 +        MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
  1.1881 +        if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
  1.1882 +            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
  1.1883 +        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) {
  1.1884 +            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
  1.1885 +        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) {
  1.1886 +            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
  1.1887 +        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
  1.1888 +            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
  1.1889 +        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) {
  1.1890 +            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_DOWN;
  1.1891 +        } else {
  1.1892 +            dispatchEntry->resolvedAction = motionEntry->action;
  1.1893 +        }
  1.1894 +        if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
  1.1895 +                && !connection->inputState.isHovering(
  1.1896 +                        motionEntry->deviceId, motionEntry->source, motionEntry->displayId)) {
  1.1897 +#if DEBUG_DISPATCH_CYCLE
  1.1898 +        ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover enter event",
  1.1899 +                connection->getInputChannelName());
  1.1900 +#endif
  1.1901 +            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
  1.1902 +        }
  1.1903 +
  1.1904 +        dispatchEntry->resolvedFlags = motionEntry->flags;
  1.1905 +        if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
  1.1906 +            dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
  1.1907 +        }
  1.1908 +
  1.1909 +        if (!connection->inputState.trackMotion(motionEntry,
  1.1910 +                dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
  1.1911 +#if DEBUG_DISPATCH_CYCLE
  1.1912 +            ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent motion event",
  1.1913 +                    connection->getInputChannelName());
  1.1914 +#endif
  1.1915 +            delete dispatchEntry;
  1.1916 +            return; // skip the inconsistent event
  1.1917 +        }
  1.1918 +        break;
  1.1919 +    }
  1.1920 +    }
  1.1921 +
  1.1922 +    // Remember that we are waiting for this dispatch to complete.
  1.1923 +    if (dispatchEntry->hasForegroundTarget()) {
  1.1924 +        incrementPendingForegroundDispatchesLocked(eventEntry);
  1.1925 +    }
  1.1926 +
  1.1927 +    // Enqueue the dispatch entry.
  1.1928 +    connection->outboundQueue.enqueueAtTail(dispatchEntry);
  1.1929 +    traceOutboundQueueLengthLocked(connection);
  1.1930 +}
  1.1931 +
  1.1932 +void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
  1.1933 +        const sp<Connection>& connection) {
  1.1934 +#if DEBUG_DISPATCH_CYCLE
  1.1935 +    ALOGD("channel '%s' ~ startDispatchCycle",
  1.1936 +            connection->getInputChannelName());
  1.1937 +#endif
  1.1938 +
  1.1939 +    while (connection->status == Connection::STATUS_NORMAL
  1.1940 +            && !connection->outboundQueue.isEmpty()) {
  1.1941 +        DispatchEntry* dispatchEntry = connection->outboundQueue.head;
  1.1942 +        dispatchEntry->deliveryTime = currentTime;
  1.1943 +
  1.1944 +        // Publish the event.
  1.1945 +        status_t status;
  1.1946 +        EventEntry* eventEntry = dispatchEntry->eventEntry;
  1.1947 +        switch (eventEntry->type) {
  1.1948 +        case EventEntry::TYPE_KEY: {
  1.1949 +            KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
  1.1950 +
  1.1951 +            // Publish the key event.
  1.1952 +            status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,
  1.1953 +                    keyEntry->deviceId, keyEntry->source,
  1.1954 +                    dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
  1.1955 +                    keyEntry->keyCode, keyEntry->scanCode,
  1.1956 +                    keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
  1.1957 +                    keyEntry->eventTime);
  1.1958 +            break;
  1.1959 +        }
  1.1960 +
  1.1961 +        case EventEntry::TYPE_MOTION: {
  1.1962 +            MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
  1.1963 +
  1.1964 +            PointerCoords scaledCoords[MAX_POINTERS];
  1.1965 +            const PointerCoords* usingCoords = motionEntry->pointerCoords;
  1.1966 +
  1.1967 +            // Set the X and Y offset depending on the input source.
  1.1968 +            float xOffset, yOffset, scaleFactor;
  1.1969 +            if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
  1.1970 +                    && !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
  1.1971 +                scaleFactor = dispatchEntry->scaleFactor;
  1.1972 +                xOffset = dispatchEntry->xOffset * scaleFactor;
  1.1973 +                yOffset = dispatchEntry->yOffset * scaleFactor;
  1.1974 +                if (scaleFactor != 1.0f) {
  1.1975 +                    for (size_t i = 0; i < motionEntry->pointerCount; i++) {
  1.1976 +                        scaledCoords[i] = motionEntry->pointerCoords[i];
  1.1977 +                        scaledCoords[i].scale(scaleFactor);
  1.1978 +                    }
  1.1979 +                    usingCoords = scaledCoords;
  1.1980 +                }
  1.1981 +            } else {
  1.1982 +                xOffset = 0.0f;
  1.1983 +                yOffset = 0.0f;
  1.1984 +                scaleFactor = 1.0f;
  1.1985 +
  1.1986 +                // We don't want the dispatch target to know.
  1.1987 +                if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
  1.1988 +                    for (size_t i = 0; i < motionEntry->pointerCount; i++) {
  1.1989 +                        scaledCoords[i].clear();
  1.1990 +                    }
  1.1991 +                    usingCoords = scaledCoords;
  1.1992 +                }
  1.1993 +            }
  1.1994 +
  1.1995 +            // Publish the motion event.
  1.1996 +            status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
  1.1997 +                    motionEntry->deviceId, motionEntry->source,
  1.1998 +                    dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
  1.1999 +                    motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState,
  1.2000 +                    xOffset, yOffset,
  1.2001 +                    motionEntry->xPrecision, motionEntry->yPrecision,
  1.2002 +                    motionEntry->downTime, motionEntry->eventTime,
  1.2003 +                    motionEntry->pointerCount, motionEntry->pointerProperties,
  1.2004 +                    usingCoords);
  1.2005 +            break;
  1.2006 +        }
  1.2007 +
  1.2008 +        default:
  1.2009 +            ALOG_ASSERT(false);
  1.2010 +            return;
  1.2011 +        }
  1.2012 +
  1.2013 +        // Check the result.
  1.2014 +        if (status) {
  1.2015 +            if (status == WOULD_BLOCK) {
  1.2016 +                if (connection->waitQueue.isEmpty()) {
  1.2017 +                    ALOGE("channel '%s' ~ Could not publish event because the pipe is full. "
  1.2018 +                            "This is unexpected because the wait queue is empty, so the pipe "
  1.2019 +                            "should be empty and we shouldn't have any problems writing an "
  1.2020 +                            "event to it, status=%d", connection->getInputChannelName(), status);
  1.2021 +                    abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
  1.2022 +                } else {
  1.2023 +                    // Pipe is full and we are waiting for the app to finish process some events
  1.2024 +                    // before sending more events to it.
  1.2025 +#if DEBUG_DISPATCH_CYCLE
  1.2026 +                    ALOGD("channel '%s' ~ Could not publish event because the pipe is full, "
  1.2027 +                            "waiting for the application to catch up",
  1.2028 +                            connection->getInputChannelName());
  1.2029 +#endif
  1.2030 +                    connection->inputPublisherBlocked = true;
  1.2031 +                }
  1.2032 +            } else {
  1.2033 +                ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "
  1.2034 +                        "status=%d", connection->getInputChannelName(), status);
  1.2035 +                abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
  1.2036 +            }
  1.2037 +            return;
  1.2038 +        }
  1.2039 +
  1.2040 +        // Re-enqueue the event on the wait queue.
  1.2041 +        connection->outboundQueue.dequeue(dispatchEntry);
  1.2042 +        traceOutboundQueueLengthLocked(connection);
  1.2043 +        connection->waitQueue.enqueueAtTail(dispatchEntry);
  1.2044 +        traceWaitQueueLengthLocked(connection);
  1.2045 +    }
  1.2046 +}
  1.2047 +
  1.2048 +void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
  1.2049 +        const sp<Connection>& connection, uint32_t seq, bool handled) {
  1.2050 +#if DEBUG_DISPATCH_CYCLE
  1.2051 +    ALOGD("channel '%s' ~ finishDispatchCycle - seq=%u, handled=%s",
  1.2052 +            connection->getInputChannelName(), seq, toString(handled));
  1.2053 +#endif
  1.2054 +
  1.2055 +    connection->inputPublisherBlocked = false;
  1.2056 +
  1.2057 +    if (connection->status == Connection::STATUS_BROKEN
  1.2058 +            || connection->status == Connection::STATUS_ZOMBIE) {
  1.2059 +        return;
  1.2060 +    }
  1.2061 +
  1.2062 +    // Notify other system components and prepare to start the next dispatch cycle.
  1.2063 +    onDispatchCycleFinishedLocked(currentTime, connection, seq, handled);
  1.2064 +}
  1.2065 +
  1.2066 +void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
  1.2067 +        const sp<Connection>& connection, bool notify) {
  1.2068 +#if DEBUG_DISPATCH_CYCLE
  1.2069 +    ALOGD("channel '%s' ~ abortBrokenDispatchCycle - notify=%s",
  1.2070 +            connection->getInputChannelName(), toString(notify));
  1.2071 +#endif
  1.2072 +
  1.2073 +    // Clear the dispatch queues.
  1.2074 +    drainDispatchQueueLocked(&connection->outboundQueue);
  1.2075 +    traceOutboundQueueLengthLocked(connection);
  1.2076 +    drainDispatchQueueLocked(&connection->waitQueue);
  1.2077 +    traceWaitQueueLengthLocked(connection);
  1.2078 +
  1.2079 +    // The connection appears to be unrecoverably broken.
  1.2080 +    // Ignore already broken or zombie connections.
  1.2081 +    if (connection->status == Connection::STATUS_NORMAL) {
  1.2082 +        connection->status = Connection::STATUS_BROKEN;
  1.2083 +
  1.2084 +        if (notify) {
  1.2085 +            // Notify other system components.
  1.2086 +            onDispatchCycleBrokenLocked(currentTime, connection);
  1.2087 +        }
  1.2088 +    }
  1.2089 +}
  1.2090 +
  1.2091 +void InputDispatcher::drainDispatchQueueLocked(Queue<DispatchEntry>* queue) {
  1.2092 +    while (!queue->isEmpty()) {
  1.2093 +        DispatchEntry* dispatchEntry = queue->dequeueAtHead();
  1.2094 +        releaseDispatchEntryLocked(dispatchEntry);
  1.2095 +    }
  1.2096 +}
  1.2097 +
  1.2098 +void InputDispatcher::releaseDispatchEntryLocked(DispatchEntry* dispatchEntry) {
  1.2099 +    if (dispatchEntry->hasForegroundTarget()) {
  1.2100 +        decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
  1.2101 +    }
  1.2102 +    delete dispatchEntry;
  1.2103 +}
  1.2104 +
  1.2105 +int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
  1.2106 +    InputDispatcher* d = static_cast<InputDispatcher*>(data);
  1.2107 +
  1.2108 +    { // acquire lock
  1.2109 +        AutoMutex _l(d->mLock);
  1.2110 +
  1.2111 +        ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);
  1.2112 +        if (connectionIndex < 0) {
  1.2113 +            ALOGE("Received spurious receive callback for unknown input channel.  "
  1.2114 +                    "fd=%d, events=0x%x", fd, events);
  1.2115 +            return 0; // remove the callback
  1.2116 +        }
  1.2117 +
  1.2118 +        bool notify;
  1.2119 +        sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex);
  1.2120 +        if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {
  1.2121 +            if (!(events & ALOOPER_EVENT_INPUT)) {
  1.2122 +                ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
  1.2123 +                        "events=0x%x", connection->getInputChannelName(), events);
  1.2124 +                return 1;
  1.2125 +            }
  1.2126 +
  1.2127 +            nsecs_t currentTime = now();
  1.2128 +            bool gotOne = false;
  1.2129 +            status_t status;
  1.2130 +            for (;;) {
  1.2131 +                uint32_t seq;
  1.2132 +                bool handled;
  1.2133 +                status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);
  1.2134 +                if (status) {
  1.2135 +                    break;
  1.2136 +                }
  1.2137 +                d->finishDispatchCycleLocked(currentTime, connection, seq, handled);
  1.2138 +                gotOne = true;
  1.2139 +            }
  1.2140 +            if (gotOne) {
  1.2141 +                d->runCommandsLockedInterruptible();
  1.2142 +                if (status == WOULD_BLOCK) {
  1.2143 +                    return 1;
  1.2144 +                }
  1.2145 +            }
  1.2146 +
  1.2147 +            notify = status != DEAD_OBJECT || !connection->monitor;
  1.2148 +            if (notify) {
  1.2149 +                ALOGE("channel '%s' ~ Failed to receive finished signal.  status=%d",
  1.2150 +                        connection->getInputChannelName(), status);
  1.2151 +            }
  1.2152 +        } else {
  1.2153 +            // Monitor channels are never explicitly unregistered.
  1.2154 +            // We do it automatically when the remote endpoint is closed so don't warn
  1.2155 +            // about them.
  1.2156 +            notify = !connection->monitor;
  1.2157 +            if (notify) {
  1.2158 +                ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred.  "
  1.2159 +                        "events=0x%x", connection->getInputChannelName(), events);
  1.2160 +            }
  1.2161 +        }
  1.2162 +
  1.2163 +        // Unregister the channel.
  1.2164 +        d->unregisterInputChannelLocked(connection->inputChannel, notify);
  1.2165 +        return 0; // remove the callback
  1.2166 +    } // release lock
  1.2167 +}
  1.2168 +
  1.2169 +void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked(
  1.2170 +        const CancelationOptions& options) {
  1.2171 +    for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
  1.2172 +        synthesizeCancelationEventsForConnectionLocked(
  1.2173 +                mConnectionsByFd.valueAt(i), options);
  1.2174 +    }
  1.2175 +}
  1.2176 +
  1.2177 +void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked(
  1.2178 +        const sp<InputChannel>& channel, const CancelationOptions& options) {
  1.2179 +    ssize_t index = getConnectionIndexLocked(channel);
  1.2180 +    if (index >= 0) {
  1.2181 +        synthesizeCancelationEventsForConnectionLocked(
  1.2182 +                mConnectionsByFd.valueAt(index), options);
  1.2183 +    }
  1.2184 +}
  1.2185 +
  1.2186 +void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
  1.2187 +        const sp<Connection>& connection, const CancelationOptions& options) {
  1.2188 +    if (connection->status == Connection::STATUS_BROKEN) {
  1.2189 +        return;
  1.2190 +    }
  1.2191 +
  1.2192 +    nsecs_t currentTime = now();
  1.2193 +
  1.2194 +    Vector<EventEntry*> cancelationEvents;
  1.2195 +    connection->inputState.synthesizeCancelationEvents(currentTime,
  1.2196 +            cancelationEvents, options);
  1.2197 +
  1.2198 +    if (!cancelationEvents.isEmpty()) {
  1.2199 +#if DEBUG_OUTBOUND_EVENT_DETAILS
  1.2200 +        ALOGD("channel '%s' ~ Synthesized %d cancelation events to bring channel back in sync "
  1.2201 +                "with reality: %s, mode=%d.",
  1.2202 +                connection->getInputChannelName(), cancelationEvents.size(),
  1.2203 +                options.reason, options.mode);
  1.2204 +#endif
  1.2205 +        for (size_t i = 0; i < cancelationEvents.size(); i++) {
  1.2206 +            EventEntry* cancelationEventEntry = cancelationEvents.itemAt(i);
  1.2207 +            switch (cancelationEventEntry->type) {
  1.2208 +            case EventEntry::TYPE_KEY:
  1.2209 +                logOutboundKeyDetailsLocked("cancel - ",
  1.2210 +                        static_cast<KeyEntry*>(cancelationEventEntry));
  1.2211 +                break;
  1.2212 +            case EventEntry::TYPE_MOTION:
  1.2213 +                logOutboundMotionDetailsLocked("cancel - ",
  1.2214 +                        static_cast<MotionEntry*>(cancelationEventEntry));
  1.2215 +                break;
  1.2216 +            }
  1.2217 +
  1.2218 +            InputTarget target;
  1.2219 +            sp<InputWindowHandle> windowHandle = getWindowHandleLocked(connection->inputChannel);
  1.2220 +            if (windowHandle != NULL) {
  1.2221 +                const InputWindowInfo* windowInfo = windowHandle->getInfo();
  1.2222 +                target.xOffset = -windowInfo->frameLeft;
  1.2223 +                target.yOffset = -windowInfo->frameTop;
  1.2224 +                target.scaleFactor = windowInfo->scaleFactor;
  1.2225 +            } else {
  1.2226 +                target.xOffset = 0;
  1.2227 +                target.yOffset = 0;
  1.2228 +                target.scaleFactor = 1.0f;
  1.2229 +            }
  1.2230 +            target.inputChannel = connection->inputChannel;
  1.2231 +            target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
  1.2232 +
  1.2233 +            enqueueDispatchEntryLocked(connection, cancelationEventEntry, // increments ref
  1.2234 +                    &target, InputTarget::FLAG_DISPATCH_AS_IS);
  1.2235 +
  1.2236 +            cancelationEventEntry->release();
  1.2237 +        }
  1.2238 +
  1.2239 +        startDispatchCycleLocked(currentTime, connection);
  1.2240 +    }
  1.2241 +}
  1.2242 +
  1.2243 +InputDispatcher::MotionEntry*
  1.2244 +InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds) {
  1.2245 +    ALOG_ASSERT(pointerIds.value != 0);
  1.2246 +
  1.2247 +    uint32_t splitPointerIndexMap[MAX_POINTERS];
  1.2248 +    PointerProperties splitPointerProperties[MAX_POINTERS];
  1.2249 +    PointerCoords splitPointerCoords[MAX_POINTERS];
  1.2250 +
  1.2251 +    uint32_t originalPointerCount = originalMotionEntry->pointerCount;
  1.2252 +    uint32_t splitPointerCount = 0;
  1.2253 +
  1.2254 +    for (uint32_t originalPointerIndex = 0; originalPointerIndex < originalPointerCount;
  1.2255 +            originalPointerIndex++) {
  1.2256 +        const PointerProperties& pointerProperties =
  1.2257 +                originalMotionEntry->pointerProperties[originalPointerIndex];
  1.2258 +        uint32_t pointerId = uint32_t(pointerProperties.id);
  1.2259 +        if (pointerIds.hasBit(pointerId)) {
  1.2260 +            splitPointerIndexMap[splitPointerCount] = originalPointerIndex;
  1.2261 +            splitPointerProperties[splitPointerCount].copyFrom(pointerProperties);
  1.2262 +            splitPointerCoords[splitPointerCount].copyFrom(
  1.2263 +                    originalMotionEntry->pointerCoords[originalPointerIndex]);
  1.2264 +            splitPointerCount += 1;
  1.2265 +        }
  1.2266 +    }
  1.2267 +
  1.2268 +    if (splitPointerCount != pointerIds.count()) {
  1.2269 +        // This is bad.  We are missing some of the pointers that we expected to deliver.
  1.2270 +        // Most likely this indicates that we received an ACTION_MOVE events that has
  1.2271 +        // different pointer ids than we expected based on the previous ACTION_DOWN
  1.2272 +        // or ACTION_POINTER_DOWN events that caused us to decide to split the pointers
  1.2273 +        // in this way.
  1.2274 +        ALOGW("Dropping split motion event because the pointer count is %d but "
  1.2275 +                "we expected there to be %d pointers.  This probably means we received "
  1.2276 +                "a broken sequence of pointer ids from the input device.",
  1.2277 +                splitPointerCount, pointerIds.count());
  1.2278 +        return NULL;
  1.2279 +    }
  1.2280 +
  1.2281 +    int32_t action = originalMotionEntry->action;
  1.2282 +    int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
  1.2283 +    if (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
  1.2284 +            || maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
  1.2285 +        int32_t originalPointerIndex = getMotionEventActionPointerIndex(action);
  1.2286 +        const PointerProperties& pointerProperties =
  1.2287 +                originalMotionEntry->pointerProperties[originalPointerIndex];
  1.2288 +        uint32_t pointerId = uint32_t(pointerProperties.id);
  1.2289 +        if (pointerIds.hasBit(pointerId)) {
  1.2290 +            if (pointerIds.count() == 1) {
  1.2291 +                // The first/last pointer went down/up.
  1.2292 +                action = maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
  1.2293 +                        ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
  1.2294 +            } else {
  1.2295 +                // A secondary pointer went down/up.
  1.2296 +                uint32_t splitPointerIndex = 0;
  1.2297 +                while (pointerId != uint32_t(splitPointerProperties[splitPointerIndex].id)) {
  1.2298 +                    splitPointerIndex += 1;
  1.2299 +                }
  1.2300 +                action = maskedAction | (splitPointerIndex
  1.2301 +                        << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
  1.2302 +            }
  1.2303 +        } else {
  1.2304 +            // An unrelated pointer changed.
  1.2305 +            action = AMOTION_EVENT_ACTION_MOVE;
  1.2306 +        }
  1.2307 +    }
  1.2308 +
  1.2309 +    MotionEntry* splitMotionEntry = new MotionEntry(
  1.2310 +            originalMotionEntry->eventTime,
  1.2311 +            originalMotionEntry->deviceId,
  1.2312 +            originalMotionEntry->source,
  1.2313 +            originalMotionEntry->policyFlags,
  1.2314 +            action,
  1.2315 +            originalMotionEntry->flags,
  1.2316 +            originalMotionEntry->metaState,
  1.2317 +            originalMotionEntry->buttonState,
  1.2318 +            originalMotionEntry->edgeFlags,
  1.2319 +            originalMotionEntry->xPrecision,
  1.2320 +            originalMotionEntry->yPrecision,
  1.2321 +            originalMotionEntry->downTime,
  1.2322 +            originalMotionEntry->displayId,
  1.2323 +            splitPointerCount, splitPointerProperties, splitPointerCoords);
  1.2324 +
  1.2325 +    if (originalMotionEntry->injectionState) {
  1.2326 +        splitMotionEntry->injectionState = originalMotionEntry->injectionState;
  1.2327 +        splitMotionEntry->injectionState->refCount += 1;
  1.2328 +    }
  1.2329 +
  1.2330 +    return splitMotionEntry;
  1.2331 +}
  1.2332 +
  1.2333 +void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
  1.2334 +#if DEBUG_INBOUND_EVENT_DETAILS
  1.2335 +    ALOGD("notifyConfigurationChanged - eventTime=%lld", args->eventTime);
  1.2336 +#endif
  1.2337 +
  1.2338 +    bool needWake;
  1.2339 +    { // acquire lock
  1.2340 +        AutoMutex _l(mLock);
  1.2341 +
  1.2342 +        ConfigurationChangedEntry* newEntry = new ConfigurationChangedEntry(args->eventTime);
  1.2343 +        needWake = enqueueInboundEventLocked(newEntry);
  1.2344 +    } // release lock
  1.2345 +
  1.2346 +    if (needWake) {
  1.2347 +        mLooper->wake();
  1.2348 +    }
  1.2349 +}
  1.2350 +
  1.2351 +void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
  1.2352 +#if DEBUG_INBOUND_EVENT_DETAILS
  1.2353 +    ALOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, "
  1.2354 +            "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
  1.2355 +            args->eventTime, args->deviceId, args->source, args->policyFlags,
  1.2356 +            args->action, args->flags, args->keyCode, args->scanCode,
  1.2357 +            args->metaState, args->downTime);
  1.2358 +#endif
  1.2359 +    if (!validateKeyEvent(args->action)) {
  1.2360 +        return;
  1.2361 +    }
  1.2362 +
  1.2363 +    uint32_t policyFlags = args->policyFlags;
  1.2364 +    int32_t flags = args->flags;
  1.2365 +    int32_t metaState = args->metaState;
  1.2366 +    if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
  1.2367 +        policyFlags |= POLICY_FLAG_VIRTUAL;
  1.2368 +        flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
  1.2369 +    }
  1.2370 +    if (policyFlags & POLICY_FLAG_ALT) {
  1.2371 +        metaState |= AMETA_ALT_ON | AMETA_ALT_LEFT_ON;
  1.2372 +    }
  1.2373 +    if (policyFlags & POLICY_FLAG_ALT_GR) {
  1.2374 +        metaState |= AMETA_ALT_ON | AMETA_ALT_RIGHT_ON;
  1.2375 +    }
  1.2376 +    if (policyFlags & POLICY_FLAG_SHIFT) {
  1.2377 +        metaState |= AMETA_SHIFT_ON | AMETA_SHIFT_LEFT_ON;
  1.2378 +    }
  1.2379 +    if (policyFlags & POLICY_FLAG_CAPS_LOCK) {
  1.2380 +        metaState |= AMETA_CAPS_LOCK_ON;
  1.2381 +    }
  1.2382 +    if (policyFlags & POLICY_FLAG_FUNCTION) {
  1.2383 +        metaState |= AMETA_FUNCTION_ON;
  1.2384 +    }
  1.2385 +
  1.2386 +    policyFlags |= POLICY_FLAG_TRUSTED;
  1.2387 +
  1.2388 +    KeyEvent event;
  1.2389 +    event.initialize(args->deviceId, args->source, args->action,
  1.2390 +            flags, args->keyCode, args->scanCode, metaState, 0,
  1.2391 +            args->downTime, args->eventTime);
  1.2392 +
  1.2393 +    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
  1.2394 +
  1.2395 +    if (policyFlags & POLICY_FLAG_WOKE_HERE) {
  1.2396 +        flags |= AKEY_EVENT_FLAG_WOKE_HERE;
  1.2397 +    }
  1.2398 +
  1.2399 +    bool needWake;
  1.2400 +    { // acquire lock
  1.2401 +        mLock.lock();
  1.2402 +
  1.2403 +        if (shouldSendKeyToInputFilterLocked(args)) {
  1.2404 +            mLock.unlock();
  1.2405 +
  1.2406 +            policyFlags |= POLICY_FLAG_FILTERED;
  1.2407 +            if (!mPolicy->filterInputEvent(&event, policyFlags)) {
  1.2408 +                return; // event was consumed by the filter
  1.2409 +            }
  1.2410 +
  1.2411 +            mLock.lock();
  1.2412 +        }
  1.2413 +
  1.2414 +        int32_t repeatCount = 0;
  1.2415 +        KeyEntry* newEntry = new KeyEntry(args->eventTime,
  1.2416 +                args->deviceId, args->source, policyFlags,
  1.2417 +                args->action, flags, args->keyCode, args->scanCode,
  1.2418 +                metaState, repeatCount, args->downTime);
  1.2419 +
  1.2420 +        needWake = enqueueInboundEventLocked(newEntry);
  1.2421 +        mLock.unlock();
  1.2422 +    } // release lock
  1.2423 +
  1.2424 +    if (needWake) {
  1.2425 +        mLooper->wake();
  1.2426 +    }
  1.2427 +}
  1.2428 +
  1.2429 +bool InputDispatcher::shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) {
  1.2430 +    return mInputFilterEnabled;
  1.2431 +}
  1.2432 +
  1.2433 +void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
  1.2434 +#if DEBUG_INBOUND_EVENT_DETAILS
  1.2435 +    ALOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
  1.2436 +            "action=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, edgeFlags=0x%x, "
  1.2437 +            "xPrecision=%f, yPrecision=%f, downTime=%lld",
  1.2438 +            args->eventTime, args->deviceId, args->source, args->policyFlags,
  1.2439 +            args->action, args->flags, args->metaState, args->buttonState,
  1.2440 +            args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime);
  1.2441 +    for (uint32_t i = 0; i < args->pointerCount; i++) {
  1.2442 +        ALOGD("  Pointer %d: id=%d, toolType=%d, "
  1.2443 +                "x=%f, y=%f, pressure=%f, size=%f, "
  1.2444 +                "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
  1.2445 +                "orientation=%f",
  1.2446 +                i, args->pointerProperties[i].id,
  1.2447 +                args->pointerProperties[i].toolType,
  1.2448 +                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
  1.2449 +                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
  1.2450 +                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
  1.2451 +                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
  1.2452 +                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
  1.2453 +                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
  1.2454 +                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
  1.2455 +                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
  1.2456 +                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
  1.2457 +    }
  1.2458 +#endif
  1.2459 +    if (!validateMotionEvent(args->action, args->pointerCount, args->pointerProperties)) {
  1.2460 +        return;
  1.2461 +    }
  1.2462 +
  1.2463 +    uint32_t policyFlags = args->policyFlags;
  1.2464 +    policyFlags |= POLICY_FLAG_TRUSTED;
  1.2465 +    mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags);
  1.2466 +
  1.2467 +    bool needWake;
  1.2468 +    { // acquire lock
  1.2469 +        mLock.lock();
  1.2470 +
  1.2471 +        if (shouldSendMotionToInputFilterLocked(args)) {
  1.2472 +            mLock.unlock();
  1.2473 +
  1.2474 +            MotionEvent event;
  1.2475 +            event.initialize(args->deviceId, args->source, args->action, args->flags,
  1.2476 +                    args->edgeFlags, args->metaState, args->buttonState, 0, 0,
  1.2477 +                    args->xPrecision, args->yPrecision,
  1.2478 +                    args->downTime, args->eventTime,
  1.2479 +                    args->pointerCount, args->pointerProperties, args->pointerCoords);
  1.2480 +
  1.2481 +            policyFlags |= POLICY_FLAG_FILTERED;
  1.2482 +            if (!mPolicy->filterInputEvent(&event, policyFlags)) {
  1.2483 +                return; // event was consumed by the filter
  1.2484 +            }
  1.2485 +
  1.2486 +            mLock.lock();
  1.2487 +        }
  1.2488 +
  1.2489 +        // Just enqueue a new motion event.
  1.2490 +        MotionEntry* newEntry = new MotionEntry(args->eventTime,
  1.2491 +                args->deviceId, args->source, policyFlags,
  1.2492 +                args->action, args->flags, args->metaState, args->buttonState,
  1.2493 +                args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
  1.2494 +                args->displayId,
  1.2495 +                args->pointerCount, args->pointerProperties, args->pointerCoords);
  1.2496 +
  1.2497 +        needWake = enqueueInboundEventLocked(newEntry);
  1.2498 +        mLock.unlock();
  1.2499 +    } // release lock
  1.2500 +
  1.2501 +    if (needWake) {
  1.2502 +        mLooper->wake();
  1.2503 +    }
  1.2504 +}
  1.2505 +
  1.2506 +bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) {
  1.2507 +    // TODO: support sending secondary display events to input filter
  1.2508 +    return mInputFilterEnabled && isMainDisplay(args->displayId);
  1.2509 +}
  1.2510 +
  1.2511 +void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) {
  1.2512 +#if DEBUG_INBOUND_EVENT_DETAILS
  1.2513 +    ALOGD("notifySwitch - eventTime=%lld, policyFlags=0x%x, switchValues=0x%08x, switchMask=0x%08x",
  1.2514 +            args->eventTime, args->policyFlags,
  1.2515 +            args->switchValues, args->switchMask);
  1.2516 +#endif
  1.2517 +
  1.2518 +    uint32_t policyFlags = args->policyFlags;
  1.2519 +    policyFlags |= POLICY_FLAG_TRUSTED;
  1.2520 +    mPolicy->notifySwitch(args->eventTime,
  1.2521 +            args->switchValues, args->switchMask, policyFlags);
  1.2522 +}
  1.2523 +
  1.2524 +void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
  1.2525 +#if DEBUG_INBOUND_EVENT_DETAILS
  1.2526 +    ALOGD("notifyDeviceReset - eventTime=%lld, deviceId=%d",
  1.2527 +            args->eventTime, args->deviceId);
  1.2528 +#endif
  1.2529 +
  1.2530 +    bool needWake;
  1.2531 +    { // acquire lock
  1.2532 +        AutoMutex _l(mLock);
  1.2533 +
  1.2534 +        DeviceResetEntry* newEntry = new DeviceResetEntry(args->eventTime, args->deviceId);
  1.2535 +        needWake = enqueueInboundEventLocked(newEntry);
  1.2536 +    } // release lock
  1.2537 +
  1.2538 +    if (needWake) {
  1.2539 +        mLooper->wake();
  1.2540 +    }
  1.2541 +}
  1.2542 +
  1.2543 +int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
  1.2544 +        int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
  1.2545 +        uint32_t policyFlags) {
  1.2546 +#if DEBUG_INBOUND_EVENT_DETAILS
  1.2547 +    ALOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
  1.2548 +            "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x",
  1.2549 +            event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags);
  1.2550 +#endif
  1.2551 +
  1.2552 +    nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
  1.2553 +
  1.2554 +    policyFlags |= POLICY_FLAG_INJECTED;
  1.2555 +    if (hasInjectionPermission(injectorPid, injectorUid)) {
  1.2556 +        policyFlags |= POLICY_FLAG_TRUSTED;
  1.2557 +    }
  1.2558 +
  1.2559 +    EventEntry* firstInjectedEntry;
  1.2560 +    EventEntry* lastInjectedEntry;
  1.2561 +    switch (event->getType()) {
  1.2562 +    case AINPUT_EVENT_TYPE_KEY: {
  1.2563 +        const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
  1.2564 +        int32_t action = keyEvent->getAction();
  1.2565 +        if (! validateKeyEvent(action)) {
  1.2566 +            return INPUT_EVENT_INJECTION_FAILED;
  1.2567 +        }
  1.2568 +
  1.2569 +        int32_t flags = keyEvent->getFlags();
  1.2570 +        if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) {
  1.2571 +            policyFlags |= POLICY_FLAG_VIRTUAL;
  1.2572 +        }
  1.2573 +
  1.2574 +        if (!(policyFlags & POLICY_FLAG_FILTERED)) {
  1.2575 +            mPolicy->interceptKeyBeforeQueueing(keyEvent, /*byref*/ policyFlags);
  1.2576 +        }
  1.2577 +
  1.2578 +        if (policyFlags & POLICY_FLAG_WOKE_HERE) {
  1.2579 +            flags |= AKEY_EVENT_FLAG_WOKE_HERE;
  1.2580 +        }
  1.2581 +
  1.2582 +        mLock.lock();
  1.2583 +        firstInjectedEntry = new KeyEntry(keyEvent->getEventTime(),
  1.2584 +                keyEvent->getDeviceId(), keyEvent->getSource(),
  1.2585 +                policyFlags, action, flags,
  1.2586 +                keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
  1.2587 +                keyEvent->getRepeatCount(), keyEvent->getDownTime());
  1.2588 +        lastInjectedEntry = firstInjectedEntry;
  1.2589 +        break;
  1.2590 +    }
  1.2591 +
  1.2592 +    case AINPUT_EVENT_TYPE_MOTION: {
  1.2593 +        const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
  1.2594 +        int32_t displayId = ADISPLAY_ID_DEFAULT;
  1.2595 +        int32_t action = motionEvent->getAction();
  1.2596 +        size_t pointerCount = motionEvent->getPointerCount();
  1.2597 +        const PointerProperties* pointerProperties = motionEvent->getPointerProperties();
  1.2598 +        if (! validateMotionEvent(action, pointerCount, pointerProperties)) {
  1.2599 +            return INPUT_EVENT_INJECTION_FAILED;
  1.2600 +        }
  1.2601 +
  1.2602 +        if (!(policyFlags & POLICY_FLAG_FILTERED)) {
  1.2603 +            nsecs_t eventTime = motionEvent->getEventTime();
  1.2604 +            mPolicy->interceptMotionBeforeQueueing(eventTime, /*byref*/ policyFlags);
  1.2605 +        }
  1.2606 +
  1.2607 +        mLock.lock();
  1.2608 +        const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
  1.2609 +        const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
  1.2610 +        firstInjectedEntry = new MotionEntry(*sampleEventTimes,
  1.2611 +                motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
  1.2612 +                action, motionEvent->getFlags(),
  1.2613 +                motionEvent->getMetaState(), motionEvent->getButtonState(),
  1.2614 +                motionEvent->getEdgeFlags(),
  1.2615 +                motionEvent->getXPrecision(), motionEvent->getYPrecision(),
  1.2616 +                motionEvent->getDownTime(), displayId,
  1.2617 +                uint32_t(pointerCount), pointerProperties, samplePointerCoords);
  1.2618 +        lastInjectedEntry = firstInjectedEntry;
  1.2619 +        for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
  1.2620 +            sampleEventTimes += 1;
  1.2621 +            samplePointerCoords += pointerCount;
  1.2622 +            MotionEntry* nextInjectedEntry = new MotionEntry(*sampleEventTimes,
  1.2623 +                    motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
  1.2624 +                    action, motionEvent->getFlags(),
  1.2625 +                    motionEvent->getMetaState(), motionEvent->getButtonState(),
  1.2626 +                    motionEvent->getEdgeFlags(),
  1.2627 +                    motionEvent->getXPrecision(), motionEvent->getYPrecision(),
  1.2628 +                    motionEvent->getDownTime(), displayId,
  1.2629 +                    uint32_t(pointerCount), pointerProperties, samplePointerCoords);
  1.2630 +            lastInjectedEntry->next = nextInjectedEntry;
  1.2631 +            lastInjectedEntry = nextInjectedEntry;
  1.2632 +        }
  1.2633 +        break;
  1.2634 +    }
  1.2635 +
  1.2636 +    default:
  1.2637 +        ALOGW("Cannot inject event of type %d", event->getType());
  1.2638 +        return INPUT_EVENT_INJECTION_FAILED;
  1.2639 +    }
  1.2640 +
  1.2641 +    InjectionState* injectionState = new InjectionState(injectorPid, injectorUid);
  1.2642 +    if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
  1.2643 +        injectionState->injectionIsAsync = true;
  1.2644 +    }
  1.2645 +
  1.2646 +    injectionState->refCount += 1;
  1.2647 +    lastInjectedEntry->injectionState = injectionState;
  1.2648 +
  1.2649 +    bool needWake = false;
  1.2650 +    for (EventEntry* entry = firstInjectedEntry; entry != NULL; ) {
  1.2651 +        EventEntry* nextEntry = entry->next;
  1.2652 +        needWake |= enqueueInboundEventLocked(entry);
  1.2653 +        entry = nextEntry;
  1.2654 +    }
  1.2655 +
  1.2656 +    mLock.unlock();
  1.2657 +
  1.2658 +    if (needWake) {
  1.2659 +        mLooper->wake();
  1.2660 +    }
  1.2661 +
  1.2662 +    int32_t injectionResult;
  1.2663 +    { // acquire lock
  1.2664 +        AutoMutex _l(mLock);
  1.2665 +
  1.2666 +        if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
  1.2667 +            injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
  1.2668 +        } else {
  1.2669 +            for (;;) {
  1.2670 +                injectionResult = injectionState->injectionResult;
  1.2671 +                if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
  1.2672 +                    break;
  1.2673 +                }
  1.2674 +
  1.2675 +                nsecs_t remainingTimeout = endTime - now();
  1.2676 +                if (remainingTimeout <= 0) {
  1.2677 +#if DEBUG_INJECTION
  1.2678 +                    ALOGD("injectInputEvent - Timed out waiting for injection result "
  1.2679 +                            "to become available.");
  1.2680 +#endif
  1.2681 +                    injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
  1.2682 +                    break;
  1.2683 +                }
  1.2684 +
  1.2685 +                mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
  1.2686 +            }
  1.2687 +
  1.2688 +            if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
  1.2689 +                    && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
  1.2690 +                while (injectionState->pendingForegroundDispatches != 0) {
  1.2691 +#if DEBUG_INJECTION
  1.2692 +                    ALOGD("injectInputEvent - Waiting for %d pending foreground dispatches.",
  1.2693 +                            injectionState->pendingForegroundDispatches);
  1.2694 +#endif
  1.2695 +                    nsecs_t remainingTimeout = endTime - now();
  1.2696 +                    if (remainingTimeout <= 0) {
  1.2697 +#if DEBUG_INJECTION
  1.2698 +                    ALOGD("injectInputEvent - Timed out waiting for pending foreground "
  1.2699 +                            "dispatches to finish.");
  1.2700 +#endif
  1.2701 +                        injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
  1.2702 +                        break;
  1.2703 +                    }
  1.2704 +
  1.2705 +                    mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
  1.2706 +                }
  1.2707 +            }
  1.2708 +        }
  1.2709 +
  1.2710 +        injectionState->release();
  1.2711 +    } // release lock
  1.2712 +
  1.2713 +#if DEBUG_INJECTION
  1.2714 +    ALOGD("injectInputEvent - Finished with result %d.  "
  1.2715 +            "injectorPid=%d, injectorUid=%d",
  1.2716 +            injectionResult, injectorPid, injectorUid);
  1.2717 +#endif
  1.2718 +
  1.2719 +    return injectionResult;
  1.2720 +}
  1.2721 +
  1.2722 +bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) {
  1.2723 +    return injectorUid == 0
  1.2724 +            || mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
  1.2725 +}
  1.2726 +
  1.2727 +void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
  1.2728 +    InjectionState* injectionState = entry->injectionState;
  1.2729 +    if (injectionState) {
  1.2730 +#if DEBUG_INJECTION
  1.2731 +        ALOGD("Setting input event injection result to %d.  "
  1.2732 +                "injectorPid=%d, injectorUid=%d",
  1.2733 +                 injectionResult, injectionState->injectorPid, injectionState->injectorUid);
  1.2734 +#endif
  1.2735 +
  1.2736 +        if (injectionState->injectionIsAsync
  1.2737 +                && !(entry->policyFlags & POLICY_FLAG_FILTERED)) {
  1.2738 +            // Log the outcome since the injector did not wait for the injection result.
  1.2739 +            switch (injectionResult) {
  1.2740 +            case INPUT_EVENT_INJECTION_SUCCEEDED:
  1.2741 +                ALOGV("Asynchronous input event injection succeeded.");
  1.2742 +                break;
  1.2743 +            case INPUT_EVENT_INJECTION_FAILED:
  1.2744 +                ALOGW("Asynchronous input event injection failed.");
  1.2745 +                break;
  1.2746 +            case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
  1.2747 +                ALOGW("Asynchronous input event injection permission denied.");
  1.2748 +                break;
  1.2749 +            case INPUT_EVENT_INJECTION_TIMED_OUT:
  1.2750 +                ALOGW("Asynchronous input event injection timed out.");
  1.2751 +                break;
  1.2752 +            }
  1.2753 +        }
  1.2754 +
  1.2755 +        injectionState->injectionResult = injectionResult;
  1.2756 +        mInjectionResultAvailableCondition.broadcast();
  1.2757 +    }
  1.2758 +}
  1.2759 +
  1.2760 +void InputDispatcher::incrementPendingForegroundDispatchesLocked(EventEntry* entry) {
  1.2761 +    InjectionState* injectionState = entry->injectionState;
  1.2762 +    if (injectionState) {
  1.2763 +        injectionState->pendingForegroundDispatches += 1;
  1.2764 +    }
  1.2765 +}
  1.2766 +
  1.2767 +void InputDispatcher::decrementPendingForegroundDispatchesLocked(EventEntry* entry) {
  1.2768 +    InjectionState* injectionState = entry->injectionState;
  1.2769 +    if (injectionState) {
  1.2770 +        injectionState->pendingForegroundDispatches -= 1;
  1.2771 +
  1.2772 +        if (injectionState->pendingForegroundDispatches == 0) {
  1.2773 +            mInjectionSyncFinishedCondition.broadcast();
  1.2774 +        }
  1.2775 +    }
  1.2776 +}
  1.2777 +
  1.2778 +sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
  1.2779 +        const sp<InputChannel>& inputChannel) const {
  1.2780 +    size_t numWindows = mWindowHandles.size();
  1.2781 +    for (size_t i = 0; i < numWindows; i++) {
  1.2782 +        const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
  1.2783 +        if (windowHandle->getInputChannel() == inputChannel) {
  1.2784 +            return windowHandle;
  1.2785 +        }
  1.2786 +    }
  1.2787 +    return NULL;
  1.2788 +}
  1.2789 +
  1.2790 +bool InputDispatcher::hasWindowHandleLocked(
  1.2791 +        const sp<InputWindowHandle>& windowHandle) const {
  1.2792 +    size_t numWindows = mWindowHandles.size();
  1.2793 +    for (size_t i = 0; i < numWindows; i++) {
  1.2794 +        if (mWindowHandles.itemAt(i) == windowHandle) {
  1.2795 +            return true;
  1.2796 +        }
  1.2797 +    }
  1.2798 +    return false;
  1.2799 +}
  1.2800 +
  1.2801 +void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
  1.2802 +#if DEBUG_FOCUS
  1.2803 +    ALOGD("setInputWindows");
  1.2804 +#endif
  1.2805 +    { // acquire lock
  1.2806 +        AutoMutex _l(mLock);
  1.2807 +
  1.2808 +        Vector<sp<InputWindowHandle> > oldWindowHandles = mWindowHandles;
  1.2809 +        mWindowHandles = inputWindowHandles;
  1.2810 +
  1.2811 +        sp<InputWindowHandle> newFocusedWindowHandle;
  1.2812 +        bool foundHoveredWindow = false;
  1.2813 +        for (size_t i = 0; i < mWindowHandles.size(); i++) {
  1.2814 +            const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
  1.2815 +            if (!windowHandle->updateInfo() || windowHandle->getInputChannel() == NULL) {
  1.2816 +                mWindowHandles.removeAt(i--);
  1.2817 +                continue;
  1.2818 +            }
  1.2819 +            if (windowHandle->getInfo()->hasFocus) {
  1.2820 +                newFocusedWindowHandle = windowHandle;
  1.2821 +            }
  1.2822 +            if (windowHandle == mLastHoverWindowHandle) {
  1.2823 +                foundHoveredWindow = true;
  1.2824 +            }
  1.2825 +        }
  1.2826 +
  1.2827 +        if (!foundHoveredWindow) {
  1.2828 +            mLastHoverWindowHandle = NULL;
  1.2829 +        }
  1.2830 +
  1.2831 +        if (mFocusedWindowHandle != newFocusedWindowHandle) {
  1.2832 +            if (mFocusedWindowHandle != NULL) {
  1.2833 +#if DEBUG_FOCUS
  1.2834 +                ALOGD("Focus left window: %s",
  1.2835 +                        mFocusedWindowHandle->getName().string());
  1.2836 +#endif
  1.2837 +                sp<InputChannel> focusedInputChannel = mFocusedWindowHandle->getInputChannel();
  1.2838 +                if (focusedInputChannel != NULL) {
  1.2839 +                    CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
  1.2840 +                            "focus left window");
  1.2841 +                    synthesizeCancelationEventsForInputChannelLocked(
  1.2842 +                            focusedInputChannel, options);
  1.2843 +                }
  1.2844 +            }
  1.2845 +            if (newFocusedWindowHandle != NULL) {
  1.2846 +#if DEBUG_FOCUS
  1.2847 +                ALOGD("Focus entered window: %s",
  1.2848 +                        newFocusedWindowHandle->getName().string());
  1.2849 +#endif
  1.2850 +            }
  1.2851 +            mFocusedWindowHandle = newFocusedWindowHandle;
  1.2852 +        }
  1.2853 +
  1.2854 +        for (size_t i = 0; i < mTouchState.windows.size(); i++) {
  1.2855 +            TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i);
  1.2856 +            if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
  1.2857 +#if DEBUG_FOCUS
  1.2858 +                ALOGD("Touched window was removed: %s",
  1.2859 +                        touchedWindow.windowHandle->getName().string());
  1.2860 +#endif
  1.2861 +                sp<InputChannel> touchedInputChannel =
  1.2862 +                        touchedWindow.windowHandle->getInputChannel();
  1.2863 +                if (touchedInputChannel != NULL) {
  1.2864 +                    CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
  1.2865 +                            "touched window was removed");
  1.2866 +                    synthesizeCancelationEventsForInputChannelLocked(
  1.2867 +                            touchedInputChannel, options);
  1.2868 +                }
  1.2869 +                mTouchState.windows.removeAt(i--);
  1.2870 +            }
  1.2871 +        }
  1.2872 +
  1.2873 +        // Release information for windows that are no longer present.
  1.2874 +        // This ensures that unused input channels are released promptly.
  1.2875 +        // Otherwise, they might stick around until the window handle is destroyed
  1.2876 +        // which might not happen until the next GC.
  1.2877 +        for (size_t i = 0; i < oldWindowHandles.size(); i++) {
  1.2878 +            const sp<InputWindowHandle>& oldWindowHandle = oldWindowHandles.itemAt(i);
  1.2879 +            if (!hasWindowHandleLocked(oldWindowHandle)) {
  1.2880 +#if DEBUG_FOCUS
  1.2881 +                ALOGD("Window went away: %s", oldWindowHandle->getName().string());
  1.2882 +#endif
  1.2883 +                oldWindowHandle->releaseInfo();
  1.2884 +            }
  1.2885 +        }
  1.2886 +    } // release lock
  1.2887 +
  1.2888 +    // Wake up poll loop since it may need to make new input dispatching choices.
  1.2889 +    mLooper->wake();
  1.2890 +}
  1.2891 +
  1.2892 +void InputDispatcher::setFocusedApplication(
  1.2893 +        const sp<InputApplicationHandle>& inputApplicationHandle) {
  1.2894 +#if DEBUG_FOCUS
  1.2895 +    ALOGD("setFocusedApplication");
  1.2896 +#endif
  1.2897 +    { // acquire lock
  1.2898 +        AutoMutex _l(mLock);
  1.2899 +
  1.2900 +        if (inputApplicationHandle != NULL && inputApplicationHandle->updateInfo()) {
  1.2901 +            if (mFocusedApplicationHandle != inputApplicationHandle) {
  1.2902 +                if (mFocusedApplicationHandle != NULL) {
  1.2903 +                    resetANRTimeoutsLocked();
  1.2904 +                    mFocusedApplicationHandle->releaseInfo();
  1.2905 +                }
  1.2906 +                mFocusedApplicationHandle = inputApplicationHandle;
  1.2907 +            }
  1.2908 +        } else if (mFocusedApplicationHandle != NULL) {
  1.2909 +            resetANRTimeoutsLocked();
  1.2910 +            mFocusedApplicationHandle->releaseInfo();
  1.2911 +            mFocusedApplicationHandle.clear();
  1.2912 +        }
  1.2913 +
  1.2914 +#if DEBUG_FOCUS
  1.2915 +        //logDispatchStateLocked();
  1.2916 +#endif
  1.2917 +    } // release lock
  1.2918 +
  1.2919 +    // Wake up poll loop since it may need to make new input dispatching choices.
  1.2920 +    mLooper->wake();
  1.2921 +}
  1.2922 +
  1.2923 +void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
  1.2924 +#if DEBUG_FOCUS
  1.2925 +    ALOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
  1.2926 +#endif
  1.2927 +
  1.2928 +    bool changed;
  1.2929 +    { // acquire lock
  1.2930 +        AutoMutex _l(mLock);
  1.2931 +
  1.2932 +        if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
  1.2933 +            if (mDispatchFrozen && !frozen) {
  1.2934 +                resetANRTimeoutsLocked();
  1.2935 +            }
  1.2936 +
  1.2937 +            if (mDispatchEnabled && !enabled) {
  1.2938 +                resetAndDropEverythingLocked("dispatcher is being disabled");
  1.2939 +            }
  1.2940 +
  1.2941 +            mDispatchEnabled = enabled;
  1.2942 +            mDispatchFrozen = frozen;
  1.2943 +            changed = true;
  1.2944 +        } else {
  1.2945 +            changed = false;
  1.2946 +        }
  1.2947 +
  1.2948 +#if DEBUG_FOCUS
  1.2949 +        //logDispatchStateLocked();
  1.2950 +#endif
  1.2951 +    } // release lock
  1.2952 +
  1.2953 +    if (changed) {
  1.2954 +        // Wake up poll loop since it may need to make new input dispatching choices.
  1.2955 +        mLooper->wake();
  1.2956 +    }
  1.2957 +}
  1.2958 +
  1.2959 +void InputDispatcher::setInputFilterEnabled(bool enabled) {
  1.2960 +#if DEBUG_FOCUS
  1.2961 +    ALOGD("setInputFilterEnabled: enabled=%d", enabled);
  1.2962 +#endif
  1.2963 +
  1.2964 +    { // acquire lock
  1.2965 +        AutoMutex _l(mLock);
  1.2966 +
  1.2967 +        if (mInputFilterEnabled == enabled) {
  1.2968 +            return;
  1.2969 +        }
  1.2970 +
  1.2971 +        mInputFilterEnabled = enabled;
  1.2972 +        resetAndDropEverythingLocked("input filter is being enabled or disabled");
  1.2973 +    } // release lock
  1.2974 +
  1.2975 +    // Wake up poll loop since there might be work to do to drop everything.
  1.2976 +    mLooper->wake();
  1.2977 +}
  1.2978 +
  1.2979 +bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
  1.2980 +        const sp<InputChannel>& toChannel) {
  1.2981 +#if DEBUG_FOCUS
  1.2982 +    ALOGD("transferTouchFocus: fromChannel=%s, toChannel=%s",
  1.2983 +            fromChannel->getName().string(), toChannel->getName().string());
  1.2984 +#endif
  1.2985 +    { // acquire lock
  1.2986 +        AutoMutex _l(mLock);
  1.2987 +
  1.2988 +        sp<InputWindowHandle> fromWindowHandle = getWindowHandleLocked(fromChannel);
  1.2989 +        sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(toChannel);
  1.2990 +        if (fromWindowHandle == NULL || toWindowHandle == NULL) {
  1.2991 +#if DEBUG_FOCUS
  1.2992 +            ALOGD("Cannot transfer focus because from or to window not found.");
  1.2993 +#endif
  1.2994 +            return false;
  1.2995 +        }
  1.2996 +        if (fromWindowHandle == toWindowHandle) {
  1.2997 +#if DEBUG_FOCUS
  1.2998 +            ALOGD("Trivial transfer to same window.");
  1.2999 +#endif
  1.3000 +            return true;
  1.3001 +        }
  1.3002 +        if (fromWindowHandle->getInfo()->displayId != toWindowHandle->getInfo()->displayId) {
  1.3003 +#if DEBUG_FOCUS
  1.3004 +            ALOGD("Cannot transfer focus because windows are on different displays.");
  1.3005 +#endif
  1.3006 +            return false;
  1.3007 +        }
  1.3008 +
  1.3009 +        bool found = false;
  1.3010 +        for (size_t i = 0; i < mTouchState.windows.size(); i++) {
  1.3011 +            const TouchedWindow& touchedWindow = mTouchState.windows[i];
  1.3012 +            if (touchedWindow.windowHandle == fromWindowHandle) {
  1.3013 +                int32_t oldTargetFlags = touchedWindow.targetFlags;
  1.3014 +                BitSet32 pointerIds = touchedWindow.pointerIds;
  1.3015 +
  1.3016 +                mTouchState.windows.removeAt(i);
  1.3017 +
  1.3018 +                int32_t newTargetFlags = oldTargetFlags
  1.3019 +                        & (InputTarget::FLAG_FOREGROUND
  1.3020 +                                | InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS);
  1.3021 +                mTouchState.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds);
  1.3022 +
  1.3023 +                found = true;
  1.3024 +                break;
  1.3025 +            }
  1.3026 +        }
  1.3027 +
  1.3028 +        if (! found) {
  1.3029 +#if DEBUG_FOCUS
  1.3030 +            ALOGD("Focus transfer failed because from window did not have focus.");
  1.3031 +#endif
  1.3032 +            return false;
  1.3033 +        }
  1.3034 +
  1.3035 +        ssize_t fromConnectionIndex = getConnectionIndexLocked(fromChannel);
  1.3036 +        ssize_t toConnectionIndex = getConnectionIndexLocked(toChannel);
  1.3037 +        if (fromConnectionIndex >= 0 && toConnectionIndex >= 0) {
  1.3038 +            sp<Connection> fromConnection = mConnectionsByFd.valueAt(fromConnectionIndex);
  1.3039 +            sp<Connection> toConnection = mConnectionsByFd.valueAt(toConnectionIndex);
  1.3040 +
  1.3041 +            fromConnection->inputState.copyPointerStateTo(toConnection->inputState);
  1.3042 +            CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
  1.3043 +                    "transferring touch focus from this window to another window");
  1.3044 +            synthesizeCancelationEventsForConnectionLocked(fromConnection, options);
  1.3045 +        }
  1.3046 +
  1.3047 +#if DEBUG_FOCUS
  1.3048 +        logDispatchStateLocked();
  1.3049 +#endif
  1.3050 +    } // release lock
  1.3051 +
  1.3052 +    // Wake up poll loop since it may need to make new input dispatching choices.
  1.3053 +    mLooper->wake();
  1.3054 +    return true;
  1.3055 +}
  1.3056 +
  1.3057 +void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
  1.3058 +#if DEBUG_FOCUS
  1.3059 +    ALOGD("Resetting and dropping all events (%s).", reason);
  1.3060 +#endif
  1.3061 +
  1.3062 +    CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS, reason);
  1.3063 +    synthesizeCancelationEventsForAllConnectionsLocked(options);
  1.3064 +
  1.3065 +    resetKeyRepeatLocked();
  1.3066 +    releasePendingEventLocked();
  1.3067 +    drainInboundQueueLocked();
  1.3068 +    resetANRTimeoutsLocked();
  1.3069 +
  1.3070 +    mTouchState.reset();
  1.3071 +    mLastHoverWindowHandle.clear();
  1.3072 +}
  1.3073 +
  1.3074 +void InputDispatcher::logDispatchStateLocked() {
  1.3075 +    String8 dump;
  1.3076 +    dumpDispatchStateLocked(dump);
  1.3077 +
  1.3078 +    char* text = dump.lockBuffer(dump.size());
  1.3079 +    char* start = text;
  1.3080 +    while (*start != '\0') {
  1.3081 +        char* end = strchr(start, '\n');
  1.3082 +        if (*end == '\n') {
  1.3083 +            *(end++) = '\0';
  1.3084 +        }
  1.3085 +        ALOGD("%s", start);
  1.3086 +        start = end;
  1.3087 +    }
  1.3088 +}
  1.3089 +
  1.3090 +void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
  1.3091 +    dump.appendFormat(INDENT "DispatchEnabled: %d\n", mDispatchEnabled);
  1.3092 +    dump.appendFormat(INDENT "DispatchFrozen: %d\n", mDispatchFrozen);
  1.3093 +
  1.3094 +    if (mFocusedApplicationHandle != NULL) {
  1.3095 +        dump.appendFormat(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
  1.3096 +                mFocusedApplicationHandle->getName().string(),
  1.3097 +                mFocusedApplicationHandle->getDispatchingTimeout(
  1.3098 +                        DEFAULT_INPUT_DISPATCHING_TIMEOUT) / 1000000.0);
  1.3099 +    } else {
  1.3100 +        dump.append(INDENT "FocusedApplication: <null>\n");
  1.3101 +    }
  1.3102 +    dump.appendFormat(INDENT "FocusedWindow: name='%s'\n",
  1.3103 +            mFocusedWindowHandle != NULL ? mFocusedWindowHandle->getName().string() : "<null>");
  1.3104 +
  1.3105 +    dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down));
  1.3106 +    dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split));
  1.3107 +    dump.appendFormat(INDENT "TouchDeviceId: %d\n", mTouchState.deviceId);
  1.3108 +    dump.appendFormat(INDENT "TouchSource: 0x%08x\n", mTouchState.source);
  1.3109 +    dump.appendFormat(INDENT "TouchDisplayId: %d\n", mTouchState.displayId);
  1.3110 +    if (!mTouchState.windows.isEmpty()) {
  1.3111 +        dump.append(INDENT "TouchedWindows:\n");
  1.3112 +        for (size_t i = 0; i < mTouchState.windows.size(); i++) {
  1.3113 +            const TouchedWindow& touchedWindow = mTouchState.windows[i];
  1.3114 +            dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
  1.3115 +                    i, touchedWindow.windowHandle->getName().string(),
  1.3116 +                    touchedWindow.pointerIds.value,
  1.3117 +                    touchedWindow.targetFlags);
  1.3118 +        }
  1.3119 +    } else {
  1.3120 +        dump.append(INDENT "TouchedWindows: <none>\n");
  1.3121 +    }
  1.3122 +
  1.3123 +    if (!mWindowHandles.isEmpty()) {
  1.3124 +        dump.append(INDENT "Windows:\n");
  1.3125 +        for (size_t i = 0; i < mWindowHandles.size(); i++) {
  1.3126 +            const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
  1.3127 +            const InputWindowInfo* windowInfo = windowHandle->getInfo();
  1.3128 +
  1.3129 +            dump.appendFormat(INDENT2 "%d: name='%s', displayId=%d, "
  1.3130 +                    "paused=%s, hasFocus=%s, hasWallpaper=%s, "
  1.3131 +                    "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
  1.3132 +                    "frame=[%d,%d][%d,%d], scale=%f, "
  1.3133 +                    "touchableRegion=",
  1.3134 +                    i, windowInfo->name.string(), windowInfo->displayId,
  1.3135 +                    toString(windowInfo->paused),
  1.3136 +                    toString(windowInfo->hasFocus),
  1.3137 +                    toString(windowInfo->hasWallpaper),
  1.3138 +                    toString(windowInfo->visible),
  1.3139 +                    toString(windowInfo->canReceiveKeys),
  1.3140 +                    windowInfo->layoutParamsFlags, windowInfo->layoutParamsType,
  1.3141 +                    windowInfo->layer,
  1.3142 +                    windowInfo->frameLeft, windowInfo->frameTop,
  1.3143 +                    windowInfo->frameRight, windowInfo->frameBottom,
  1.3144 +                    windowInfo->scaleFactor);
  1.3145 +            dumpRegion(dump, windowInfo->touchableRegion);
  1.3146 +            dump.appendFormat(", inputFeatures=0x%08x", windowInfo->inputFeatures);
  1.3147 +            dump.appendFormat(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
  1.3148 +                    windowInfo->ownerPid, windowInfo->ownerUid,
  1.3149 +                    windowInfo->dispatchingTimeout / 1000000.0);
  1.3150 +        }
  1.3151 +    } else {
  1.3152 +        dump.append(INDENT "Windows: <none>\n");
  1.3153 +    }
  1.3154 +
  1.3155 +    if (!mMonitoringChannels.isEmpty()) {
  1.3156 +        dump.append(INDENT "MonitoringChannels:\n");
  1.3157 +        for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
  1.3158 +            const sp<InputChannel>& channel = mMonitoringChannels[i];
  1.3159 +            dump.appendFormat(INDENT2 "%d: '%s'\n", i, channel->getName().string());
  1.3160 +        }
  1.3161 +    } else {
  1.3162 +        dump.append(INDENT "MonitoringChannels: <none>\n");
  1.3163 +    }
  1.3164 +
  1.3165 +    nsecs_t currentTime = now();
  1.3166 +
  1.3167 +    if (!mInboundQueue.isEmpty()) {
  1.3168 +        dump.appendFormat(INDENT "InboundQueue: length=%u\n", mInboundQueue.count());
  1.3169 +        for (EventEntry* entry = mInboundQueue.head; entry; entry = entry->next) {
  1.3170 +            dump.append(INDENT2);
  1.3171 +            entry->appendDescription(dump);
  1.3172 +            dump.appendFormat(", age=%0.1fms\n",
  1.3173 +                    (currentTime - entry->eventTime) * 0.000001f);
  1.3174 +        }
  1.3175 +    } else {
  1.3176 +        dump.append(INDENT "InboundQueue: <empty>\n");
  1.3177 +    }
  1.3178 +
  1.3179 +    if (!mConnectionsByFd.isEmpty()) {
  1.3180 +        dump.append(INDENT "Connections:\n");
  1.3181 +        for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
  1.3182 +            const sp<Connection>& connection = mConnectionsByFd.valueAt(i);
  1.3183 +            dump.appendFormat(INDENT2 "%d: channelName='%s', windowName='%s', "
  1.3184 +                    "status=%s, monitor=%s, inputPublisherBlocked=%s\n",
  1.3185 +                    i, connection->getInputChannelName(), connection->getWindowName(),
  1.3186 +                    connection->getStatusLabel(), toString(connection->monitor),
  1.3187 +                    toString(connection->inputPublisherBlocked));
  1.3188 +
  1.3189 +            if (!connection->outboundQueue.isEmpty()) {
  1.3190 +                dump.appendFormat(INDENT3 "OutboundQueue: length=%u\n",
  1.3191 +                        connection->outboundQueue.count());
  1.3192 +                for (DispatchEntry* entry = connection->outboundQueue.head; entry;
  1.3193 +                        entry = entry->next) {
  1.3194 +                    dump.append(INDENT4);
  1.3195 +                    entry->eventEntry->appendDescription(dump);
  1.3196 +                    dump.appendFormat(", targetFlags=0x%08x, resolvedAction=%d, age=%0.1fms\n",
  1.3197 +                            entry->targetFlags, entry->resolvedAction,
  1.3198 +                            (currentTime - entry->eventEntry->eventTime) * 0.000001f);
  1.3199 +                }
  1.3200 +            } else {
  1.3201 +                dump.append(INDENT3 "OutboundQueue: <empty>\n");
  1.3202 +            }
  1.3203 +
  1.3204 +            if (!connection->waitQueue.isEmpty()) {
  1.3205 +                dump.appendFormat(INDENT3 "WaitQueue: length=%u\n",
  1.3206 +                        connection->waitQueue.count());
  1.3207 +                for (DispatchEntry* entry = connection->waitQueue.head; entry;
  1.3208 +                        entry = entry->next) {
  1.3209 +                    dump.append(INDENT4);
  1.3210 +                    entry->eventEntry->appendDescription(dump);
  1.3211 +                    dump.appendFormat(", targetFlags=0x%08x, resolvedAction=%d, "
  1.3212 +                            "age=%0.1fms, wait=%0.1fms\n",
  1.3213 +                            entry->targetFlags, entry->resolvedAction,
  1.3214 +                            (currentTime - entry->eventEntry->eventTime) * 0.000001f,
  1.3215 +                            (currentTime - entry->deliveryTime) * 0.000001f);
  1.3216 +                }
  1.3217 +            } else {
  1.3218 +                dump.append(INDENT3 "WaitQueue: <empty>\n");
  1.3219 +            }
  1.3220 +        }
  1.3221 +    } else {
  1.3222 +        dump.append(INDENT "Connections: <none>\n");
  1.3223 +    }
  1.3224 +
  1.3225 +    if (isAppSwitchPendingLocked()) {
  1.3226 +        dump.appendFormat(INDENT "AppSwitch: pending, due in %0.1fms\n",
  1.3227 +                (mAppSwitchDueTime - now()) / 1000000.0);
  1.3228 +    } else {
  1.3229 +        dump.append(INDENT "AppSwitch: not pending\n");
  1.3230 +    }
  1.3231 +
  1.3232 +    dump.append(INDENT "Configuration:\n");
  1.3233 +    dump.appendFormat(INDENT2 "KeyRepeatDelay: %0.1fms\n",
  1.3234 +            mConfig.keyRepeatDelay * 0.000001f);
  1.3235 +    dump.appendFormat(INDENT2 "KeyRepeatTimeout: %0.1fms\n",
  1.3236 +            mConfig.keyRepeatTimeout * 0.000001f);
  1.3237 +}
  1.3238 +
  1.3239 +status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
  1.3240 +        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
  1.3241 +#if DEBUG_REGISTRATION
  1.3242 +    ALOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().string(),
  1.3243 +            toString(monitor));
  1.3244 +#endif
  1.3245 +
  1.3246 +    { // acquire lock
  1.3247 +        AutoMutex _l(mLock);
  1.3248 +
  1.3249 +        if (getConnectionIndexLocked(inputChannel) >= 0) {
  1.3250 +            ALOGW("Attempted to register already registered input channel '%s'",
  1.3251 +                    inputChannel->getName().string());
  1.3252 +            return BAD_VALUE;
  1.3253 +        }
  1.3254 +
  1.3255 +        sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);
  1.3256 +
  1.3257 +        int fd = inputChannel->getFd();
  1.3258 +        mConnectionsByFd.add(fd, connection);
  1.3259 +
  1.3260 +        if (monitor) {
  1.3261 +            mMonitoringChannels.push(inputChannel);
  1.3262 +        }
  1.3263 +
  1.3264 +        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
  1.3265 +    } // release lock
  1.3266 +
  1.3267 +    // Wake the looper because some connections have changed.
  1.3268 +    mLooper->wake();
  1.3269 +    return OK;
  1.3270 +}
  1.3271 +
  1.3272 +status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
  1.3273 +#if DEBUG_REGISTRATION
  1.3274 +    ALOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
  1.3275 +#endif
  1.3276 +
  1.3277 +    { // acquire lock
  1.3278 +        AutoMutex _l(mLock);
  1.3279 +
  1.3280 +        status_t status = unregisterInputChannelLocked(inputChannel, false /*notify*/);
  1.3281 +        if (status) {
  1.3282 +            return status;
  1.3283 +        }
  1.3284 +    } // release lock
  1.3285 +
  1.3286 +    // Wake the poll loop because removing the connection may have changed the current
  1.3287 +    // synchronization state.
  1.3288 +    mLooper->wake();
  1.3289 +    return OK;
  1.3290 +}
  1.3291 +
  1.3292 +status_t InputDispatcher::unregisterInputChannelLocked(const sp<InputChannel>& inputChannel,
  1.3293 +        bool notify) {
  1.3294 +    ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
  1.3295 +    if (connectionIndex < 0) {
  1.3296 +        ALOGW("Attempted to unregister already unregistered input channel '%s'",
  1.3297 +                inputChannel->getName().string());
  1.3298 +        return BAD_VALUE;
  1.3299 +    }
  1.3300 +
  1.3301 +    sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
  1.3302 +    mConnectionsByFd.removeItemsAt(connectionIndex);
  1.3303 +
  1.3304 +    if (connection->monitor) {
  1.3305 +        removeMonitorChannelLocked(inputChannel);
  1.3306 +    }
  1.3307 +
  1.3308 +    mLooper->removeFd(inputChannel->getFd());
  1.3309 +
  1.3310 +    nsecs_t currentTime = now();
  1.3311 +    abortBrokenDispatchCycleLocked(currentTime, connection, notify);
  1.3312 +
  1.3313 +    connection->status = Connection::STATUS_ZOMBIE;
  1.3314 +    return OK;
  1.3315 +}
  1.3316 +
  1.3317 +void InputDispatcher::removeMonitorChannelLocked(const sp<InputChannel>& inputChannel) {
  1.3318 +    for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
  1.3319 +         if (mMonitoringChannels[i] == inputChannel) {
  1.3320 +             mMonitoringChannels.removeAt(i);
  1.3321 +             break;
  1.3322 +         }
  1.3323 +    }
  1.3324 +}
  1.3325 +
  1.3326 +ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
  1.3327 +    ssize_t connectionIndex = mConnectionsByFd.indexOfKey(inputChannel->getFd());
  1.3328 +    if (connectionIndex >= 0) {
  1.3329 +        sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
  1.3330 +        if (connection->inputChannel.get() == inputChannel.get()) {
  1.3331 +            return connectionIndex;
  1.3332 +        }
  1.3333 +    }
  1.3334 +
  1.3335 +    return -1;
  1.3336 +}
  1.3337 +
  1.3338 +void InputDispatcher::onDispatchCycleFinishedLocked(
  1.3339 +        nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled) {
  1.3340 +    CommandEntry* commandEntry = postCommandLocked(
  1.3341 +            & InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
  1.3342 +    commandEntry->connection = connection;
  1.3343 +    commandEntry->eventTime = currentTime;
  1.3344 +    commandEntry->seq = seq;
  1.3345 +    commandEntry->handled = handled;
  1.3346 +}
  1.3347 +
  1.3348 +void InputDispatcher::onDispatchCycleBrokenLocked(
  1.3349 +        nsecs_t currentTime, const sp<Connection>& connection) {
  1.3350 +    ALOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
  1.3351 +            connection->getInputChannelName());
  1.3352 +
  1.3353 +    CommandEntry* commandEntry = postCommandLocked(
  1.3354 +            & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
  1.3355 +    commandEntry->connection = connection;
  1.3356 +}
  1.3357 +
  1.3358 +void InputDispatcher::onANRLocked(
  1.3359 +        nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
  1.3360 +        const sp<InputWindowHandle>& windowHandle,
  1.3361 +        nsecs_t eventTime, nsecs_t waitStartTime, const char* reason) {
  1.3362 +    float dispatchLatency = (currentTime - eventTime) * 0.000001f;
  1.3363 +    float waitDuration = (currentTime - waitStartTime) * 0.000001f;
  1.3364 +    ALOGI("Application is not responding: %s.  "
  1.3365 +            "It has been %0.1fms since event, %0.1fms since wait started.  Reason: %s",
  1.3366 +            getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(),
  1.3367 +            dispatchLatency, waitDuration, reason);
  1.3368 +
  1.3369 +    // Capture a record of the InputDispatcher state at the time of the ANR.
  1.3370 +    time_t t = time(NULL);
  1.3371 +    struct tm tm;
  1.3372 +    localtime_r(&t, &tm);
  1.3373 +    char timestr[64];
  1.3374 +    strftime(timestr, sizeof(timestr), "%F %T", &tm);
  1.3375 +    mLastANRState.clear();
  1.3376 +    mLastANRState.append(INDENT "ANR:\n");
  1.3377 +    mLastANRState.appendFormat(INDENT2 "Time: %s\n", timestr);
  1.3378 +    mLastANRState.appendFormat(INDENT2 "Window: %s\n",
  1.3379 +            getApplicationWindowLabelLocked(applicationHandle, windowHandle).string());
  1.3380 +    mLastANRState.appendFormat(INDENT2 "DispatchLatency: %0.1fms\n", dispatchLatency);
  1.3381 +    mLastANRState.appendFormat(INDENT2 "WaitDuration: %0.1fms\n", waitDuration);
  1.3382 +    mLastANRState.appendFormat(INDENT2 "Reason: %s\n", reason);
  1.3383 +    dumpDispatchStateLocked(mLastANRState);
  1.3384 +
  1.3385 +    CommandEntry* commandEntry = postCommandLocked(
  1.3386 +            & InputDispatcher::doNotifyANRLockedInterruptible);
  1.3387 +    commandEntry->inputApplicationHandle = applicationHandle;
  1.3388 +    commandEntry->inputWindowHandle = windowHandle;
  1.3389 +}
  1.3390 +
  1.3391 +void InputDispatcher::doNotifyConfigurationChangedInterruptible(
  1.3392 +        CommandEntry* commandEntry) {
  1.3393 +    mLock.unlock();
  1.3394 +
  1.3395 +    mPolicy->notifyConfigurationChanged(commandEntry->eventTime);
  1.3396 +
  1.3397 +    mLock.lock();
  1.3398 +}
  1.3399 +
  1.3400 +void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
  1.3401 +        CommandEntry* commandEntry) {
  1.3402 +    sp<Connection> connection = commandEntry->connection;
  1.3403 +
  1.3404 +    if (connection->status != Connection::STATUS_ZOMBIE) {
  1.3405 +        mLock.unlock();
  1.3406 +
  1.3407 +        mPolicy->notifyInputChannelBroken(connection->inputWindowHandle);
  1.3408 +
  1.3409 +        mLock.lock();
  1.3410 +    }
  1.3411 +}
  1.3412 +
  1.3413 +void InputDispatcher::doNotifyANRLockedInterruptible(
  1.3414 +        CommandEntry* commandEntry) {
  1.3415 +    mLock.unlock();
  1.3416 +
  1.3417 +    nsecs_t newTimeout = mPolicy->notifyANR(
  1.3418 +            commandEntry->inputApplicationHandle, commandEntry->inputWindowHandle);
  1.3419 +
  1.3420 +    mLock.lock();
  1.3421 +
  1.3422 +    resumeAfterTargetsNotReadyTimeoutLocked(newTimeout,
  1.3423 +            commandEntry->inputWindowHandle != NULL
  1.3424 +                    ? commandEntry->inputWindowHandle->getInputChannel() : NULL);
  1.3425 +}
  1.3426 +
  1.3427 +void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
  1.3428 +        CommandEntry* commandEntry) {
  1.3429 +    KeyEntry* entry = commandEntry->keyEntry;
  1.3430 +
  1.3431 +    KeyEvent event;
  1.3432 +    initializeKeyEvent(&event, entry);
  1.3433 +
  1.3434 +    mLock.unlock();
  1.3435 +
  1.3436 +    nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
  1.3437 +            &event, entry->policyFlags);
  1.3438 +
  1.3439 +    mLock.lock();
  1.3440 +
  1.3441 +    if (delay < 0) {
  1.3442 +        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP;
  1.3443 +    } else if (!delay) {
  1.3444 +        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
  1.3445 +    } else {
  1.3446 +        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;
  1.3447 +        entry->interceptKeyWakeupTime = now() + delay;
  1.3448 +    }
  1.3449 +    entry->release();
  1.3450 +}
  1.3451 +
  1.3452 +void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
  1.3453 +        CommandEntry* commandEntry) {
  1.3454 +    sp<Connection> connection = commandEntry->connection;
  1.3455 +    nsecs_t finishTime = commandEntry->eventTime;
  1.3456 +    uint32_t seq = commandEntry->seq;
  1.3457 +    bool handled = commandEntry->handled;
  1.3458 +
  1.3459 +    // Handle post-event policy actions.
  1.3460 +    DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq);
  1.3461 +    if (dispatchEntry) {
  1.3462 +        nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime;
  1.3463 +        if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
  1.3464 +            String8 msg;
  1.3465 +            msg.appendFormat("Window '%s' spent %0.1fms processing the last input event: ",
  1.3466 +                    connection->getWindowName(), eventDuration * 0.000001f);
  1.3467 +            dispatchEntry->eventEntry->appendDescription(msg);
  1.3468 +            ALOGI("%s", msg.string());
  1.3469 +        }
  1.3470 +
  1.3471 +        bool restartEvent;
  1.3472 +        if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
  1.3473 +            KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
  1.3474 +            restartEvent = afterKeyEventLockedInterruptible(connection,
  1.3475 +                    dispatchEntry, keyEntry, handled);
  1.3476 +        } else if (dispatchEntry->eventEntry->type == EventEntry::TYPE_MOTION) {
  1.3477 +            MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
  1.3478 +            restartEvent = afterMotionEventLockedInterruptible(connection,
  1.3479 +                    dispatchEntry, motionEntry, handled);
  1.3480 +        } else {
  1.3481 +            restartEvent = false;
  1.3482 +        }
  1.3483 +
  1.3484 +        // Dequeue the event and start the next cycle.
  1.3485 +        // Note that because the lock might have been released, it is possible that the
  1.3486 +        // contents of the wait queue to have been drained, so we need to double-check
  1.3487 +        // a few things.
  1.3488 +        if (dispatchEntry == connection->findWaitQueueEntry(seq)) {
  1.3489 +            connection->waitQueue.dequeue(dispatchEntry);
  1.3490 +            traceWaitQueueLengthLocked(connection);
  1.3491 +            if (restartEvent && connection->status == Connection::STATUS_NORMAL) {
  1.3492 +                connection->outboundQueue.enqueueAtHead(dispatchEntry);
  1.3493 +                traceOutboundQueueLengthLocked(connection);
  1.3494 +            } else {
  1.3495 +                releaseDispatchEntryLocked(dispatchEntry);
  1.3496 +            }
  1.3497 +        }
  1.3498 +
  1.3499 +        // Start the next dispatch cycle for this connection.
  1.3500 +        startDispatchCycleLocked(now(), connection);
  1.3501 +    }
  1.3502 +}
  1.3503 +
  1.3504 +bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection,
  1.3505 +        DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled) {
  1.3506 +    if (!(keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
  1.3507 +        // Get the fallback key state.
  1.3508 +        // Clear it out after dispatching the UP.
  1.3509 +        int32_t originalKeyCode = keyEntry->keyCode;
  1.3510 +        int32_t fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode);
  1.3511 +        if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
  1.3512 +            connection->inputState.removeFallbackKey(originalKeyCode);
  1.3513 +        }
  1.3514 +
  1.3515 +        if (handled || !dispatchEntry->hasForegroundTarget()) {
  1.3516 +            // If the application handles the original key for which we previously
  1.3517 +            // generated a fallback or if the window is not a foreground window,
  1.3518 +            // then cancel the associated fallback key, if any.
  1.3519 +            if (fallbackKeyCode != -1) {
  1.3520 +                // Dispatch the unhandled key to the policy with the cancel flag.
  1.3521 +#if DEBUG_OUTBOUND_EVENT_DETAILS
  1.3522 +                ALOGD("Unhandled key event: Asking policy to cancel fallback action.  "
  1.3523 +                        "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
  1.3524 +                        keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount,
  1.3525 +                        keyEntry->policyFlags);
  1.3526 +#endif
  1.3527 +                KeyEvent event;
  1.3528 +                initializeKeyEvent(&event, keyEntry);
  1.3529 +                event.setFlags(event.getFlags() | AKEY_EVENT_FLAG_CANCELED);
  1.3530 +
  1.3531 +                mLock.unlock();
  1.3532 +
  1.3533 +                mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
  1.3534 +                        &event, keyEntry->policyFlags, &event);
  1.3535 +
  1.3536 +                mLock.lock();
  1.3537 +
  1.3538 +                // Cancel the fallback key.
  1.3539 +                if (fallbackKeyCode != AKEYCODE_UNKNOWN) {
  1.3540 +                    CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
  1.3541 +                            "application handled the original non-fallback key "
  1.3542 +                            "or is no longer a foreground target, "
  1.3543 +                            "canceling previously dispatched fallback key");
  1.3544 +                    options.keyCode = fallbackKeyCode;
  1.3545 +                    synthesizeCancelationEventsForConnectionLocked(connection, options);
  1.3546 +                }
  1.3547 +                connection->inputState.removeFallbackKey(originalKeyCode);
  1.3548 +            }
  1.3549 +        } else {
  1.3550 +            // If the application did not handle a non-fallback key, first check
  1.3551 +            // that we are in a good state to perform unhandled key event processing
  1.3552 +            // Then ask the policy what to do with it.
  1.3553 +            bool initialDown = keyEntry->action == AKEY_EVENT_ACTION_DOWN
  1.3554 +                    && keyEntry->repeatCount == 0;
  1.3555 +            if (fallbackKeyCode == -1 && !initialDown) {
  1.3556 +#if DEBUG_OUTBOUND_EVENT_DETAILS
  1.3557 +                ALOGD("Unhandled key event: Skipping unhandled key event processing "
  1.3558 +                        "since this is not an initial down.  "
  1.3559 +                        "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
  1.3560 +                        originalKeyCode, keyEntry->action, keyEntry->repeatCount,
  1.3561 +                        keyEntry->policyFlags);
  1.3562 +#endif
  1.3563 +                return false;
  1.3564 +            }
  1.3565 +
  1.3566 +            // Dispatch the unhandled key to the policy.
  1.3567 +#if DEBUG_OUTBOUND_EVENT_DETAILS
  1.3568 +            ALOGD("Unhandled key event: Asking policy to perform fallback action.  "
  1.3569 +                    "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
  1.3570 +                    keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount,
  1.3571 +                    keyEntry->policyFlags);
  1.3572 +#endif
  1.3573 +            KeyEvent event;
  1.3574 +            initializeKeyEvent(&event, keyEntry);
  1.3575 +
  1.3576 +            mLock.unlock();
  1.3577 +
  1.3578 +            bool fallback = mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
  1.3579 +                    &event, keyEntry->policyFlags, &event);
  1.3580 +
  1.3581 +            mLock.lock();
  1.3582 +
  1.3583 +            if (connection->status != Connection::STATUS_NORMAL) {
  1.3584 +                connection->inputState.removeFallbackKey(originalKeyCode);
  1.3585 +                return false;
  1.3586 +            }
  1.3587 +
  1.3588 +            // Latch the fallback keycode for this key on an initial down.
  1.3589 +            // The fallback keycode cannot change at any other point in the lifecycle.
  1.3590 +            if (initialDown) {
  1.3591 +                if (fallback) {
  1.3592 +                    fallbackKeyCode = event.getKeyCode();
  1.3593 +                } else {
  1.3594 +                    fallbackKeyCode = AKEYCODE_UNKNOWN;
  1.3595 +                }
  1.3596 +                connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode);
  1.3597 +            }
  1.3598 +
  1.3599 +            ALOG_ASSERT(fallbackKeyCode != -1);
  1.3600 +
  1.3601 +            // Cancel the fallback key if the policy decides not to send it anymore.
  1.3602 +            // We will continue to dispatch the key to the policy but we will no
  1.3603 +            // longer dispatch a fallback key to the application.
  1.3604 +            if (fallbackKeyCode != AKEYCODE_UNKNOWN
  1.3605 +                    && (!fallback || fallbackKeyCode != event.getKeyCode())) {
  1.3606 +#if DEBUG_OUTBOUND_EVENT_DETAILS
  1.3607 +                if (fallback) {
  1.3608 +                    ALOGD("Unhandled key event: Policy requested to send key %d"
  1.3609 +                            "as a fallback for %d, but on the DOWN it had requested "
  1.3610 +                            "to send %d instead.  Fallback canceled.",
  1.3611 +                            event.getKeyCode(), originalKeyCode, fallbackKeyCode);
  1.3612 +                } else {
  1.3613 +                    ALOGD("Unhandled key event: Policy did not request fallback for %d, "
  1.3614 +                            "but on the DOWN it had requested to send %d.  "
  1.3615 +                            "Fallback canceled.",
  1.3616 +                            originalKeyCode, fallbackKeyCode);
  1.3617 +                }
  1.3618 +#endif
  1.3619 +
  1.3620 +                CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
  1.3621 +                        "canceling fallback, policy no longer desires it");
  1.3622 +                options.keyCode = fallbackKeyCode;
  1.3623 +                synthesizeCancelationEventsForConnectionLocked(connection, options);
  1.3624 +
  1.3625 +                fallback = false;
  1.3626 +                fallbackKeyCode = AKEYCODE_UNKNOWN;
  1.3627 +                if (keyEntry->action != AKEY_EVENT_ACTION_UP) {
  1.3628 +                    connection->inputState.setFallbackKey(originalKeyCode,
  1.3629 +                            fallbackKeyCode);
  1.3630 +                }
  1.3631 +            }
  1.3632 +
  1.3633 +#if DEBUG_OUTBOUND_EVENT_DETAILS
  1.3634 +            {
  1.3635 +                String8 msg;
  1.3636 +                const KeyedVector<int32_t, int32_t>& fallbackKeys =
  1.3637 +                        connection->inputState.getFallbackKeys();
  1.3638 +                for (size_t i = 0; i < fallbackKeys.size(); i++) {
  1.3639 +                    msg.appendFormat(", %d->%d", fallbackKeys.keyAt(i),
  1.3640 +                            fallbackKeys.valueAt(i));
  1.3641 +                }
  1.3642 +                ALOGD("Unhandled key event: %d currently tracked fallback keys%s.",
  1.3643 +                        fallbackKeys.size(), msg.string());
  1.3644 +            }
  1.3645 +#endif
  1.3646 +
  1.3647 +            if (fallback) {
  1.3648 +                // Restart the dispatch cycle using the fallback key.
  1.3649 +                keyEntry->eventTime = event.getEventTime();
  1.3650 +                keyEntry->deviceId = event.getDeviceId();
  1.3651 +                keyEntry->source = event.getSource();
  1.3652 +                keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
  1.3653 +                keyEntry->keyCode = fallbackKeyCode;
  1.3654 +                keyEntry->scanCode = event.getScanCode();
  1.3655 +                keyEntry->metaState = event.getMetaState();
  1.3656 +                keyEntry->repeatCount = event.getRepeatCount();
  1.3657 +                keyEntry->downTime = event.getDownTime();
  1.3658 +                keyEntry->syntheticRepeat = false;
  1.3659 +
  1.3660 +#if DEBUG_OUTBOUND_EVENT_DETAILS
  1.3661 +                ALOGD("Unhandled key event: Dispatching fallback key.  "
  1.3662 +                        "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
  1.3663 +                        originalKeyCode, fallbackKeyCode, keyEntry->metaState);
  1.3664 +#endif
  1.3665 +                return true; // restart the event
  1.3666 +            } else {
  1.3667 +#if DEBUG_OUTBOUND_EVENT_DETAILS
  1.3668 +                ALOGD("Unhandled key event: No fallback key.");
  1.3669 +#endif
  1.3670 +            }
  1.3671 +        }
  1.3672 +    }
  1.3673 +    return false;
  1.3674 +}
  1.3675 +
  1.3676 +bool InputDispatcher::afterMotionEventLockedInterruptible(const sp<Connection>& connection,
  1.3677 +        DispatchEntry* dispatchEntry, MotionEntry* motionEntry, bool handled) {
  1.3678 +    return false;
  1.3679 +}
  1.3680 +
  1.3681 +void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
  1.3682 +    mLock.unlock();
  1.3683 +
  1.3684 +    mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType);
  1.3685 +
  1.3686 +    mLock.lock();
  1.3687 +}
  1.3688 +
  1.3689 +void InputDispatcher::initializeKeyEvent(KeyEvent* event, const KeyEntry* entry) {
  1.3690 +    event->initialize(entry->deviceId, entry->source, entry->action, entry->flags,
  1.3691 +            entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
  1.3692 +            entry->downTime, entry->eventTime);
  1.3693 +}
  1.3694 +
  1.3695 +void InputDispatcher::updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
  1.3696 +        int32_t injectionResult, nsecs_t timeSpentWaitingForApplication) {
  1.3697 +    // TODO Write some statistics about how long we spend waiting.
  1.3698 +}
  1.3699 +
  1.3700 +void InputDispatcher::traceInboundQueueLengthLocked() {
  1.3701 +#ifdef HAVE_ANDROID_OS
  1.3702 +    if (ATRACE_ENABLED()) {
  1.3703 +        ATRACE_INT("iq", mInboundQueue.count());
  1.3704 +    }
  1.3705 +#endif
  1.3706 +}
  1.3707 +
  1.3708 +void InputDispatcher::traceOutboundQueueLengthLocked(const sp<Connection>& connection) {
  1.3709 +#ifdef HAVE_ANDROID_OS
  1.3710 +    if (ATRACE_ENABLED()) {
  1.3711 +        char counterName[40];
  1.3712 +        snprintf(counterName, sizeof(counterName), "oq:%s", connection->getWindowName());
  1.3713 +        ATRACE_INT(counterName, connection->outboundQueue.count());
  1.3714 +    }
  1.3715 +#endif
  1.3716 +}
  1.3717 +
  1.3718 +void InputDispatcher::traceWaitQueueLengthLocked(const sp<Connection>& connection) {
  1.3719 +#ifdef HAVE_ANDROID_OS
  1.3720 +    if (ATRACE_ENABLED()) {
  1.3721 +        char counterName[40];
  1.3722 +        snprintf(counterName, sizeof(counterName), "wq:%s", connection->getWindowName());
  1.3723 +        ATRACE_INT(counterName, connection->waitQueue.count());
  1.3724 +    }
  1.3725 +#endif
  1.3726 +}
  1.3727 +
  1.3728 +void InputDispatcher::dump(String8& dump) {
  1.3729 +    AutoMutex _l(mLock);
  1.3730 +
  1.3731 +    dump.append("Input Dispatcher State:\n");
  1.3732 +    dumpDispatchStateLocked(dump);
  1.3733 +
  1.3734 +    if (!mLastANRState.isEmpty()) {
  1.3735 +        dump.append("\nInput Dispatcher State at time of last ANR:\n");
  1.3736 +        dump.append(mLastANRState);
  1.3737 +    }
  1.3738 +}
  1.3739 +
  1.3740 +void InputDispatcher::monitor() {
  1.3741 +    // Acquire and release the lock to ensure that the dispatcher has not deadlocked.
  1.3742 +    mLock.lock();
  1.3743 +    mLooper->wake();
  1.3744 +    mDispatcherIsAliveCondition.wait(mLock);
  1.3745 +    mLock.unlock();
  1.3746 +}
  1.3747 +
  1.3748 +
  1.3749 +// --- InputDispatcher::Queue ---
  1.3750 +
  1.3751 +template <typename T>
  1.3752 +uint32_t InputDispatcher::Queue<T>::count() const {
  1.3753 +    uint32_t result = 0;
  1.3754 +    for (const T* entry = head; entry; entry = entry->next) {
  1.3755 +        result += 1;
  1.3756 +    }
  1.3757 +    return result;
  1.3758 +}
  1.3759 +
  1.3760 +
  1.3761 +// --- InputDispatcher::InjectionState ---
  1.3762 +
  1.3763 +InputDispatcher::InjectionState::InjectionState(int32_t injectorPid, int32_t injectorUid) :
  1.3764 +        refCount(1),
  1.3765 +        injectorPid(injectorPid), injectorUid(injectorUid),
  1.3766 +        injectionResult(INPUT_EVENT_INJECTION_PENDING), injectionIsAsync(false),
  1.3767 +        pendingForegroundDispatches(0) {
  1.3768 +}
  1.3769 +
  1.3770 +InputDispatcher::InjectionState::~InjectionState() {
  1.3771 +}
  1.3772 +
  1.3773 +void InputDispatcher::InjectionState::release() {
  1.3774 +    refCount -= 1;
  1.3775 +    if (refCount == 0) {
  1.3776 +        delete this;
  1.3777 +    } else {
  1.3778 +        ALOG_ASSERT(refCount > 0);
  1.3779 +    }
  1.3780 +}
  1.3781 +
  1.3782 +
  1.3783 +// --- InputDispatcher::EventEntry ---
  1.3784 +
  1.3785 +InputDispatcher::EventEntry::EventEntry(int32_t type, nsecs_t eventTime, uint32_t policyFlags) :
  1.3786 +        refCount(1), type(type), eventTime(eventTime), policyFlags(policyFlags),
  1.3787 +        injectionState(NULL), dispatchInProgress(false) {
  1.3788 +}
  1.3789 +
  1.3790 +InputDispatcher::EventEntry::~EventEntry() {
  1.3791 +    releaseInjectionState();
  1.3792 +}
  1.3793 +
  1.3794 +void InputDispatcher::EventEntry::release() {
  1.3795 +    refCount -= 1;
  1.3796 +    if (refCount == 0) {
  1.3797 +        delete this;
  1.3798 +    } else {
  1.3799 +        ALOG_ASSERT(refCount > 0);
  1.3800 +    }
  1.3801 +}
  1.3802 +
  1.3803 +void InputDispatcher::EventEntry::releaseInjectionState() {
  1.3804 +    if (injectionState) {
  1.3805 +        injectionState->release();
  1.3806 +        injectionState = NULL;
  1.3807 +    }
  1.3808 +}
  1.3809 +
  1.3810 +
  1.3811 +// --- InputDispatcher::ConfigurationChangedEntry ---
  1.3812 +
  1.3813 +InputDispatcher::ConfigurationChangedEntry::ConfigurationChangedEntry(nsecs_t eventTime) :
  1.3814 +        EventEntry(TYPE_CONFIGURATION_CHANGED, eventTime, 0) {
  1.3815 +}
  1.3816 +
  1.3817 +InputDispatcher::ConfigurationChangedEntry::~ConfigurationChangedEntry() {
  1.3818 +}
  1.3819 +
  1.3820 +void InputDispatcher::ConfigurationChangedEntry::appendDescription(String8& msg) const {
  1.3821 +    msg.append("ConfigurationChangedEvent()");
  1.3822 +}
  1.3823 +
  1.3824 +
  1.3825 +// --- InputDispatcher::DeviceResetEntry ---
  1.3826 +
  1.3827 +InputDispatcher::DeviceResetEntry::DeviceResetEntry(nsecs_t eventTime, int32_t deviceId) :
  1.3828 +        EventEntry(TYPE_DEVICE_RESET, eventTime, 0),
  1.3829 +        deviceId(deviceId) {
  1.3830 +}
  1.3831 +
  1.3832 +InputDispatcher::DeviceResetEntry::~DeviceResetEntry() {
  1.3833 +}
  1.3834 +
  1.3835 +void InputDispatcher::DeviceResetEntry::appendDescription(String8& msg) const {
  1.3836 +    msg.appendFormat("DeviceResetEvent(deviceId=%d)", deviceId);
  1.3837 +}
  1.3838 +
  1.3839 +
  1.3840 +// --- InputDispatcher::KeyEntry ---
  1.3841 +
  1.3842 +InputDispatcher::KeyEntry::KeyEntry(nsecs_t eventTime,
  1.3843 +        int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action,
  1.3844 +        int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
  1.3845 +        int32_t repeatCount, nsecs_t downTime) :
  1.3846 +        EventEntry(TYPE_KEY, eventTime, policyFlags),
  1.3847 +        deviceId(deviceId), source(source), action(action), flags(flags),
  1.3848 +        keyCode(keyCode), scanCode(scanCode), metaState(metaState),
  1.3849 +        repeatCount(repeatCount), downTime(downTime),
  1.3850 +        syntheticRepeat(false), interceptKeyResult(KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN),
  1.3851 +        interceptKeyWakeupTime(0) {
  1.3852 +}
  1.3853 +
  1.3854 +InputDispatcher::KeyEntry::~KeyEntry() {
  1.3855 +}
  1.3856 +
  1.3857 +void InputDispatcher::KeyEntry::appendDescription(String8& msg) const {
  1.3858 +    msg.appendFormat("KeyEvent(action=%d, deviceId=%d, source=0x%08x)",
  1.3859 +            action, deviceId, source);
  1.3860 +}
  1.3861 +
  1.3862 +void InputDispatcher::KeyEntry::recycle() {
  1.3863 +    releaseInjectionState();
  1.3864 +
  1.3865 +    dispatchInProgress = false;
  1.3866 +    syntheticRepeat = false;
  1.3867 +    interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
  1.3868 +    interceptKeyWakeupTime = 0;
  1.3869 +}
  1.3870 +
  1.3871 +
  1.3872 +// --- InputDispatcher::MotionEntry ---
  1.3873 +
  1.3874 +InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime,
  1.3875 +        int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
  1.3876 +        int32_t metaState, int32_t buttonState,
  1.3877 +        int32_t edgeFlags, float xPrecision, float yPrecision,
  1.3878 +        nsecs_t downTime, int32_t displayId, uint32_t pointerCount,
  1.3879 +        const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) :
  1.3880 +        EventEntry(TYPE_MOTION, eventTime, policyFlags),
  1.3881 +        eventTime(eventTime),
  1.3882 +        deviceId(deviceId), source(source), action(action), flags(flags),
  1.3883 +        metaState(metaState), buttonState(buttonState), edgeFlags(edgeFlags),
  1.3884 +        xPrecision(xPrecision), yPrecision(yPrecision),
  1.3885 +        downTime(downTime), displayId(displayId), pointerCount(pointerCount) {
  1.3886 +    for (uint32_t i = 0; i < pointerCount; i++) {
  1.3887 +        this->pointerProperties[i].copyFrom(pointerProperties[i]);
  1.3888 +        this->pointerCoords[i].copyFrom(pointerCoords[i]);
  1.3889 +    }
  1.3890 +}
  1.3891 +
  1.3892 +InputDispatcher::MotionEntry::~MotionEntry() {
  1.3893 +}
  1.3894 +
  1.3895 +void InputDispatcher::MotionEntry::appendDescription(String8& msg) const {
  1.3896 +    msg.appendFormat("MotionEvent(action=%d, deviceId=%d, source=0x%08x, displayId=%d)",
  1.3897 +            action, deviceId, source, displayId);
  1.3898 +}
  1.3899 +
  1.3900 +
  1.3901 +// --- InputDispatcher::DispatchEntry ---
  1.3902 +
  1.3903 +volatile int32_t InputDispatcher::DispatchEntry::sNextSeqAtomic;
  1.3904 +
  1.3905 +InputDispatcher::DispatchEntry::DispatchEntry(EventEntry* eventEntry,
  1.3906 +        int32_t targetFlags, float xOffset, float yOffset, float scaleFactor) :
  1.3907 +        seq(nextSeq()),
  1.3908 +        eventEntry(eventEntry), targetFlags(targetFlags),
  1.3909 +        xOffset(xOffset), yOffset(yOffset), scaleFactor(scaleFactor),
  1.3910 +        deliveryTime(0), resolvedAction(0), resolvedFlags(0) {
  1.3911 +    eventEntry->refCount += 1;
  1.3912 +}
  1.3913 +
  1.3914 +InputDispatcher::DispatchEntry::~DispatchEntry() {
  1.3915 +    eventEntry->release();
  1.3916 +}
  1.3917 +
  1.3918 +uint32_t InputDispatcher::DispatchEntry::nextSeq() {
  1.3919 +    // Sequence number 0 is reserved and will never be returned.
  1.3920 +    uint32_t seq;
  1.3921 +    do {
  1.3922 +        seq = android_atomic_inc(&sNextSeqAtomic);
  1.3923 +    } while (!seq);
  1.3924 +    return seq;
  1.3925 +}
  1.3926 +
  1.3927 +
  1.3928 +// --- InputDispatcher::InputState ---
  1.3929 +
  1.3930 +InputDispatcher::InputState::InputState() {
  1.3931 +}
  1.3932 +
  1.3933 +InputDispatcher::InputState::~InputState() {
  1.3934 +}
  1.3935 +
  1.3936 +bool InputDispatcher::InputState::isNeutral() const {
  1.3937 +    return mKeyMementos.isEmpty() && mMotionMementos.isEmpty();
  1.3938 +}
  1.3939 +
  1.3940 +bool InputDispatcher::InputState::isHovering(int32_t deviceId, uint32_t source,
  1.3941 +        int32_t displayId) const {
  1.3942 +    for (size_t i = 0; i < mMotionMementos.size(); i++) {
  1.3943 +        const MotionMemento& memento = mMotionMementos.itemAt(i);
  1.3944 +        if (memento.deviceId == deviceId
  1.3945 +                && memento.source == source
  1.3946 +                && memento.displayId == displayId
  1.3947 +                && memento.hovering) {
  1.3948 +            return true;
  1.3949 +        }
  1.3950 +    }
  1.3951 +    return false;
  1.3952 +}
  1.3953 +
  1.3954 +bool InputDispatcher::InputState::trackKey(const KeyEntry* entry,
  1.3955 +        int32_t action, int32_t flags) {
  1.3956 +    switch (action) {
  1.3957 +    case AKEY_EVENT_ACTION_UP: {
  1.3958 +        if (entry->flags & AKEY_EVENT_FLAG_FALLBACK) {
  1.3959 +            for (size_t i = 0; i < mFallbackKeys.size(); ) {
  1.3960 +                if (mFallbackKeys.valueAt(i) == entry->keyCode) {
  1.3961 +                    mFallbackKeys.removeItemsAt(i);
  1.3962 +                } else {
  1.3963 +                    i += 1;
  1.3964 +                }
  1.3965 +            }
  1.3966 +        }
  1.3967 +        ssize_t index = findKeyMemento(entry);
  1.3968 +        if (index >= 0) {
  1.3969 +            mKeyMementos.removeAt(index);
  1.3970 +            return true;
  1.3971 +        }
  1.3972 +        /* FIXME: We can't just drop the key up event because that prevents creating
  1.3973 +         * popup windows that are automatically shown when a key is held and then
  1.3974 +         * dismissed when the key is released.  The problem is that the popup will
  1.3975 +         * not have received the original key down, so the key up will be considered
  1.3976 +         * to be inconsistent with its observed state.  We could perhaps handle this
  1.3977 +         * by synthesizing a key down but that will cause other problems.
  1.3978 +         *
  1.3979 +         * So for now, allow inconsistent key up events to be dispatched.
  1.3980 +         *
  1.3981 +#if DEBUG_OUTBOUND_EVENT_DETAILS
  1.3982 +        ALOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, "
  1.3983 +                "keyCode=%d, scanCode=%d",
  1.3984 +                entry->deviceId, entry->source, entry->keyCode, entry->scanCode);
  1.3985 +#endif
  1.3986 +        return false;
  1.3987 +        */
  1.3988 +        return true;
  1.3989 +    }
  1.3990 +
  1.3991 +    case AKEY_EVENT_ACTION_DOWN: {
  1.3992 +        ssize_t index = findKeyMemento(entry);
  1.3993 +        if (index >= 0) {
  1.3994 +            mKeyMementos.removeAt(index);
  1.3995 +        }
  1.3996 +        addKeyMemento(entry, flags);
  1.3997 +        return true;
  1.3998 +    }
  1.3999 +
  1.4000 +    default:
  1.4001 +        return true;
  1.4002 +    }
  1.4003 +}
  1.4004 +
  1.4005 +bool InputDispatcher::InputState::trackMotion(const MotionEntry* entry,
  1.4006 +        int32_t action, int32_t flags) {
  1.4007 +    int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK;
  1.4008 +    switch (actionMasked) {
  1.4009 +    case AMOTION_EVENT_ACTION_UP:
  1.4010 +    case AMOTION_EVENT_ACTION_CANCEL: {
  1.4011 +        ssize_t index = findMotionMemento(entry, false /*hovering*/);
  1.4012 +        if (index >= 0) {
  1.4013 +            mMotionMementos.removeAt(index);
  1.4014 +            return true;
  1.4015 +        }
  1.4016 +#if DEBUG_OUTBOUND_EVENT_DETAILS
  1.4017 +        ALOGD("Dropping inconsistent motion up or cancel event: deviceId=%d, source=%08x, "
  1.4018 +                "actionMasked=%d",
  1.4019 +                entry->deviceId, entry->source, actionMasked);
  1.4020 +#endif
  1.4021 +        return false;
  1.4022 +    }
  1.4023 +
  1.4024 +    case AMOTION_EVENT_ACTION_DOWN: {
  1.4025 +        ssize_t index = findMotionMemento(entry, false /*hovering*/);
  1.4026 +        if (index >= 0) {
  1.4027 +            mMotionMementos.removeAt(index);
  1.4028 +        }
  1.4029 +        addMotionMemento(entry, flags, false /*hovering*/);
  1.4030 +        return true;
  1.4031 +    }
  1.4032 +
  1.4033 +    case AMOTION_EVENT_ACTION_POINTER_UP:
  1.4034 +    case AMOTION_EVENT_ACTION_POINTER_DOWN:
  1.4035 +    case AMOTION_EVENT_ACTION_MOVE: {
  1.4036 +        ssize_t index = findMotionMemento(entry, false /*hovering*/);
  1.4037 +        if (index >= 0) {
  1.4038 +            MotionMemento& memento = mMotionMementos.editItemAt(index);
  1.4039 +            memento.setPointers(entry);
  1.4040 +            return true;
  1.4041 +        }
  1.4042 +        if (actionMasked == AMOTION_EVENT_ACTION_MOVE
  1.4043 +                && (entry->source & (AINPUT_SOURCE_CLASS_JOYSTICK
  1.4044 +                        | AINPUT_SOURCE_CLASS_NAVIGATION))) {
  1.4045 +            // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
  1.4046 +            return true;
  1.4047 +        }
  1.4048 +#if DEBUG_OUTBOUND_EVENT_DETAILS
  1.4049 +        ALOGD("Dropping inconsistent motion pointer up/down or move event: "
  1.4050 +                "deviceId=%d, source=%08x, actionMasked=%d",
  1.4051 +                entry->deviceId, entry->source, actionMasked);
  1.4052 +#endif
  1.4053 +        return false;
  1.4054 +    }
  1.4055 +
  1.4056 +    case AMOTION_EVENT_ACTION_HOVER_EXIT: {
  1.4057 +        ssize_t index = findMotionMemento(entry, true /*hovering*/);
  1.4058 +        if (index >= 0) {
  1.4059 +            mMotionMementos.removeAt(index);
  1.4060 +            return true;
  1.4061 +        }
  1.4062 +#if DEBUG_OUTBOUND_EVENT_DETAILS
  1.4063 +        ALOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x",
  1.4064 +                entry->deviceId, entry->source);
  1.4065 +#endif
  1.4066 +        return false;
  1.4067 +    }
  1.4068 +
  1.4069 +    case AMOTION_EVENT_ACTION_HOVER_ENTER:
  1.4070 +    case AMOTION_EVENT_ACTION_HOVER_MOVE: {
  1.4071 +        ssize_t index = findMotionMemento(entry, true /*hovering*/);
  1.4072 +        if (index >= 0) {
  1.4073 +            mMotionMementos.removeAt(index);
  1.4074 +        }
  1.4075 +        addMotionMemento(entry, flags, true /*hovering*/);
  1.4076 +        return true;
  1.4077 +    }
  1.4078 +
  1.4079 +    default:
  1.4080 +        return true;
  1.4081 +    }
  1.4082 +}
  1.4083 +
  1.4084 +ssize_t InputDispatcher::InputState::findKeyMemento(const KeyEntry* entry) const {
  1.4085 +    for (size_t i = 0; i < mKeyMementos.size(); i++) {
  1.4086 +        const KeyMemento& memento = mKeyMementos.itemAt(i);
  1.4087 +        if (memento.deviceId == entry->deviceId
  1.4088 +                && memento.source == entry->source
  1.4089 +                && memento.keyCode == entry->keyCode
  1.4090 +                && memento.scanCode == entry->scanCode) {
  1.4091 +            return i;
  1.4092 +        }
  1.4093 +    }
  1.4094 +    return -1;
  1.4095 +}
  1.4096 +
  1.4097 +ssize_t InputDispatcher::InputState::findMotionMemento(const MotionEntry* entry,
  1.4098 +        bool hovering) const {
  1.4099 +    for (size_t i = 0; i < mMotionMementos.size(); i++) {
  1.4100 +        const MotionMemento& memento = mMotionMementos.itemAt(i);
  1.4101 +        if (memento.deviceId == entry->deviceId
  1.4102 +                && memento.source == entry->source
  1.4103 +                && memento.displayId == entry->displayId
  1.4104 +                && memento.hovering == hovering) {
  1.4105 +            return i;
  1.4106 +        }
  1.4107 +    }
  1.4108 +    return -1;
  1.4109 +}
  1.4110 +
  1.4111 +void InputDispatcher::InputState::addKeyMemento(const KeyEntry* entry, int32_t flags) {
  1.4112 +    mKeyMementos.push();
  1.4113 +    KeyMemento& memento = mKeyMementos.editTop();
  1.4114 +    memento.deviceId = entry->deviceId;
  1.4115 +    memento.source = entry->source;
  1.4116 +    memento.keyCode = entry->keyCode;
  1.4117 +    memento.scanCode = entry->scanCode;
  1.4118 +    memento.metaState = entry->metaState;
  1.4119 +    memento.flags = flags;
  1.4120 +    memento.downTime = entry->downTime;
  1.4121 +    memento.policyFlags = entry->policyFlags;
  1.4122 +}
  1.4123 +
  1.4124 +void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry,
  1.4125 +        int32_t flags, bool hovering) {
  1.4126 +    mMotionMementos.push();
  1.4127 +    MotionMemento& memento = mMotionMementos.editTop();
  1.4128 +    memento.deviceId = entry->deviceId;
  1.4129 +    memento.source = entry->source;
  1.4130 +    memento.flags = flags;
  1.4131 +    memento.xPrecision = entry->xPrecision;
  1.4132 +    memento.yPrecision = entry->yPrecision;
  1.4133 +    memento.downTime = entry->downTime;
  1.4134 +    memento.displayId = entry->displayId;
  1.4135 +    memento.setPointers(entry);
  1.4136 +    memento.hovering = hovering;
  1.4137 +    memento.policyFlags = entry->policyFlags;
  1.4138 +}
  1.4139 +
  1.4140 +void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) {
  1.4141 +    pointerCount = entry->pointerCount;
  1.4142 +    for (uint32_t i = 0; i < entry->pointerCount; i++) {
  1.4143 +        pointerProperties[i].copyFrom(entry->pointerProperties[i]);
  1.4144 +        pointerCoords[i].copyFrom(entry->pointerCoords[i]);
  1.4145 +    }
  1.4146 +}
  1.4147 +
  1.4148 +void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime,
  1.4149 +        Vector<EventEntry*>& outEvents, const CancelationOptions& options) {
  1.4150 +    for (size_t i = 0; i < mKeyMementos.size(); i++) {
  1.4151 +        const KeyMemento& memento = mKeyMementos.itemAt(i);
  1.4152 +        if (shouldCancelKey(memento, options)) {
  1.4153 +            outEvents.push(new KeyEntry(currentTime,
  1.4154 +                    memento.deviceId, memento.source, memento.policyFlags,
  1.4155 +                    AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED,
  1.4156 +                    memento.keyCode, memento.scanCode, memento.metaState, 0, memento.downTime));
  1.4157 +        }
  1.4158 +    }
  1.4159 +
  1.4160 +    for (size_t i = 0; i < mMotionMementos.size(); i++) {
  1.4161 +        const MotionMemento& memento = mMotionMementos.itemAt(i);
  1.4162 +        if (shouldCancelMotion(memento, options)) {
  1.4163 +            outEvents.push(new MotionEntry(currentTime,
  1.4164 +                    memento.deviceId, memento.source, memento.policyFlags,
  1.4165 +                    memento.hovering
  1.4166 +                            ? AMOTION_EVENT_ACTION_HOVER_EXIT
  1.4167 +                            : AMOTION_EVENT_ACTION_CANCEL,
  1.4168 +                    memento.flags, 0, 0, 0,
  1.4169 +                    memento.xPrecision, memento.yPrecision, memento.downTime,
  1.4170 +                    memento.displayId,
  1.4171 +                    memento.pointerCount, memento.pointerProperties, memento.pointerCoords));
  1.4172 +        }
  1.4173 +    }
  1.4174 +}
  1.4175 +
  1.4176 +void InputDispatcher::InputState::clear() {
  1.4177 +    mKeyMementos.clear();
  1.4178 +    mMotionMementos.clear();
  1.4179 +    mFallbackKeys.clear();
  1.4180 +}
  1.4181 +
  1.4182 +void InputDispatcher::InputState::copyPointerStateTo(InputState& other) const {
  1.4183 +    for (size_t i = 0; i < mMotionMementos.size(); i++) {
  1.4184 +        const MotionMemento& memento = mMotionMementos.itemAt(i);
  1.4185 +        if (memento.source & AINPUT_SOURCE_CLASS_POINTER) {
  1.4186 +            for (size_t j = 0; j < other.mMotionMementos.size(); ) {
  1.4187 +                const MotionMemento& otherMemento = other.mMotionMementos.itemAt(j);
  1.4188 +                if (memento.deviceId == otherMemento.deviceId
  1.4189 +                        && memento.source == otherMemento.source
  1.4190 +                        && memento.displayId == otherMemento.displayId) {
  1.4191 +                    other.mMotionMementos.removeAt(j);
  1.4192 +                } else {
  1.4193 +                    j += 1;
  1.4194 +                }
  1.4195 +            }
  1.4196 +            other.mMotionMementos.push(memento);
  1.4197 +        }
  1.4198 +    }
  1.4199 +}
  1.4200 +
  1.4201 +int32_t InputDispatcher::InputState::getFallbackKey(int32_t originalKeyCode) {
  1.4202 +    ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
  1.4203 +    return index >= 0 ? mFallbackKeys.valueAt(index) : -1;
  1.4204 +}
  1.4205 +
  1.4206 +void InputDispatcher::InputState::setFallbackKey(int32_t originalKeyCode,
  1.4207 +        int32_t fallbackKeyCode) {
  1.4208 +    ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
  1.4209 +    if (index >= 0) {
  1.4210 +        mFallbackKeys.replaceValueAt(index, fallbackKeyCode);
  1.4211 +    } else {
  1.4212 +        mFallbackKeys.add(originalKeyCode, fallbackKeyCode);
  1.4213 +    }
  1.4214 +}
  1.4215 +
  1.4216 +void InputDispatcher::InputState::removeFallbackKey(int32_t originalKeyCode) {
  1.4217 +    mFallbackKeys.removeItem(originalKeyCode);
  1.4218 +}
  1.4219 +
  1.4220 +bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento,
  1.4221 +        const CancelationOptions& options) {
  1.4222 +    if (options.keyCode != -1 && memento.keyCode != options.keyCode) {
  1.4223 +        return false;
  1.4224 +    }
  1.4225 +
  1.4226 +    if (options.deviceId != -1 && memento.deviceId != options.deviceId) {
  1.4227 +        return false;
  1.4228 +    }
  1.4229 +
  1.4230 +    switch (options.mode) {
  1.4231 +    case CancelationOptions::CANCEL_ALL_EVENTS:
  1.4232 +    case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
  1.4233 +        return true;
  1.4234 +    case CancelationOptions::CANCEL_FALLBACK_EVENTS:
  1.4235 +        return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
  1.4236 +    default:
  1.4237 +        return false;
  1.4238 +    }
  1.4239 +}
  1.4240 +
  1.4241 +bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& memento,
  1.4242 +        const CancelationOptions& options) {
  1.4243 +    if (options.deviceId != -1 && memento.deviceId != options.deviceId) {
  1.4244 +        return false;
  1.4245 +    }
  1.4246 +
  1.4247 +    switch (options.mode) {
  1.4248 +    case CancelationOptions::CANCEL_ALL_EVENTS:
  1.4249 +        return true;
  1.4250 +    case CancelationOptions::CANCEL_POINTER_EVENTS:
  1.4251 +        return memento.source & AINPUT_SOURCE_CLASS_POINTER;
  1.4252 +    case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
  1.4253 +        return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
  1.4254 +    default:
  1.4255 +        return false;
  1.4256 +    }
  1.4257 +}
  1.4258 +
  1.4259 +
  1.4260 +// --- InputDispatcher::Connection ---
  1.4261 +
  1.4262 +InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel,
  1.4263 +        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) :
  1.4264 +        status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle),
  1.4265 +        monitor(monitor),
  1.4266 +        inputPublisher(inputChannel), inputPublisherBlocked(false) {
  1.4267 +}
  1.4268 +
  1.4269 +InputDispatcher::Connection::~Connection() {
  1.4270 +}
  1.4271 +
  1.4272 +const char* InputDispatcher::Connection::getWindowName() const {
  1.4273 +    if (inputWindowHandle != NULL) {
  1.4274 +        return inputWindowHandle->getName().string();
  1.4275 +    }
  1.4276 +    if (monitor) {
  1.4277 +        return "monitor";
  1.4278 +    }
  1.4279 +    return "?";
  1.4280 +}
  1.4281 +
  1.4282 +const char* InputDispatcher::Connection::getStatusLabel() const {
  1.4283 +    switch (status) {
  1.4284 +    case STATUS_NORMAL:
  1.4285 +        return "NORMAL";
  1.4286 +
  1.4287 +    case STATUS_BROKEN:
  1.4288 +        return "BROKEN";
  1.4289 +
  1.4290 +    case STATUS_ZOMBIE:
  1.4291 +        return "ZOMBIE";
  1.4292 +
  1.4293 +    default:
  1.4294 +        return "UNKNOWN";
  1.4295 +    }
  1.4296 +}
  1.4297 +
  1.4298 +InputDispatcher::DispatchEntry* InputDispatcher::Connection::findWaitQueueEntry(uint32_t seq) {
  1.4299 +    for (DispatchEntry* entry = waitQueue.head; entry != NULL; entry = entry->next) {
  1.4300 +        if (entry->seq == seq) {
  1.4301 +            return entry;
  1.4302 +        }
  1.4303 +    }
  1.4304 +    return NULL;
  1.4305 +}
  1.4306 +
  1.4307 +
  1.4308 +// --- InputDispatcher::CommandEntry ---
  1.4309 +
  1.4310 +InputDispatcher::CommandEntry::CommandEntry(Command command) :
  1.4311 +    command(command), eventTime(0), keyEntry(NULL), userActivityEventType(0),
  1.4312 +    seq(0), handled(false) {
  1.4313 +}
  1.4314 +
  1.4315 +InputDispatcher::CommandEntry::~CommandEntry() {
  1.4316 +}
  1.4317 +
  1.4318 +
  1.4319 +// --- InputDispatcher::TouchState ---
  1.4320 +
  1.4321 +InputDispatcher::TouchState::TouchState() :
  1.4322 +    down(false), split(false), deviceId(-1), source(0), displayId(-1) {
  1.4323 +}
  1.4324 +
  1.4325 +InputDispatcher::TouchState::~TouchState() {
  1.4326 +}
  1.4327 +
  1.4328 +void InputDispatcher::TouchState::reset() {
  1.4329 +    down = false;
  1.4330 +    split = false;
  1.4331 +    deviceId = -1;
  1.4332 +    source = 0;
  1.4333 +    displayId = -1;
  1.4334 +    windows.clear();
  1.4335 +}
  1.4336 +
  1.4337 +void InputDispatcher::TouchState::copyFrom(const TouchState& other) {
  1.4338 +    down = other.down;
  1.4339 +    split = other.split;
  1.4340 +    deviceId = other.deviceId;
  1.4341 +    source = other.source;
  1.4342 +    displayId = other.displayId;
  1.4343 +    windows = other.windows;
  1.4344 +}
  1.4345 +
  1.4346 +void InputDispatcher::TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
  1.4347 +        int32_t targetFlags, BitSet32 pointerIds) {
  1.4348 +    if (targetFlags & InputTarget::FLAG_SPLIT) {
  1.4349 +        split = true;
  1.4350 +    }
  1.4351 +
  1.4352 +    for (size_t i = 0; i < windows.size(); i++) {
  1.4353 +        TouchedWindow& touchedWindow = windows.editItemAt(i);
  1.4354 +        if (touchedWindow.windowHandle == windowHandle) {
  1.4355 +            touchedWindow.targetFlags |= targetFlags;
  1.4356 +            if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
  1.4357 +                touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS;
  1.4358 +            }
  1.4359 +            touchedWindow.pointerIds.value |= pointerIds.value;
  1.4360 +            return;
  1.4361 +        }
  1.4362 +    }
  1.4363 +
  1.4364 +    windows.push();
  1.4365 +
  1.4366 +    TouchedWindow& touchedWindow = windows.editTop();
  1.4367 +    touchedWindow.windowHandle = windowHandle;
  1.4368 +    touchedWindow.targetFlags = targetFlags;
  1.4369 +    touchedWindow.pointerIds = pointerIds;
  1.4370 +}
  1.4371 +
  1.4372 +void InputDispatcher::TouchState::removeWindow(const sp<InputWindowHandle>& windowHandle) {
  1.4373 +    for (size_t i = 0; i < windows.size(); i++) {
  1.4374 +        if (windows.itemAt(i).windowHandle == windowHandle) {
  1.4375 +            windows.removeAt(i);
  1.4376 +            return;
  1.4377 +        }
  1.4378 +    }
  1.4379 +}
  1.4380 +
  1.4381 +void InputDispatcher::TouchState::filterNonAsIsTouchWindows() {
  1.4382 +    for (size_t i = 0 ; i < windows.size(); ) {
  1.4383 +        TouchedWindow& window = windows.editItemAt(i);
  1.4384 +        if (window.targetFlags & (InputTarget::FLAG_DISPATCH_AS_IS
  1.4385 +                | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) {
  1.4386 +            window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK;
  1.4387 +            window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS;
  1.4388 +            i += 1;
  1.4389 +        } else {
  1.4390 +            windows.removeAt(i);
  1.4391 +        }
  1.4392 +    }
  1.4393 +}
  1.4394 +
  1.4395 +sp<InputWindowHandle> InputDispatcher::TouchState::getFirstForegroundWindowHandle() const {
  1.4396 +    for (size_t i = 0; i < windows.size(); i++) {
  1.4397 +        const TouchedWindow& window = windows.itemAt(i);
  1.4398 +        if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
  1.4399 +            return window.windowHandle;
  1.4400 +        }
  1.4401 +    }
  1.4402 +    return NULL;
  1.4403 +}
  1.4404 +
  1.4405 +bool InputDispatcher::TouchState::isSlippery() const {
  1.4406 +    // Must have exactly one foreground window.
  1.4407 +    bool haveSlipperyForegroundWindow = false;
  1.4408 +    for (size_t i = 0; i < windows.size(); i++) {
  1.4409 +        const TouchedWindow& window = windows.itemAt(i);
  1.4410 +        if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
  1.4411 +            if (haveSlipperyForegroundWindow
  1.4412 +                    || !(window.windowHandle->getInfo()->layoutParamsFlags
  1.4413 +                            & InputWindowInfo::FLAG_SLIPPERY)) {
  1.4414 +                return false;
  1.4415 +            }
  1.4416 +            haveSlipperyForegroundWindow = true;
  1.4417 +        }
  1.4418 +    }
  1.4419 +    return haveSlipperyForegroundWindow;
  1.4420 +}
  1.4421 +
  1.4422 +
  1.4423 +// --- InputDispatcherThread ---
  1.4424 +
  1.4425 +InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
  1.4426 +        Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
  1.4427 +}
  1.4428 +
  1.4429 +InputDispatcherThread::~InputDispatcherThread() {
  1.4430 +}
  1.4431 +
  1.4432 +bool InputDispatcherThread::threadLoop() {
  1.4433 +    mDispatcher->dispatchOnce();
  1.4434 +    return true;
  1.4435 +}
  1.4436 +
  1.4437 +} // namespace android

mercurial