widget/gonk/libui/InputReader.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/widget/gonk/libui/InputReader.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,6511 @@
     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 "InputReader"
    1.21 +
    1.22 +//#define LOG_NDEBUG 0
    1.23 +#include "cutils_log.h"
    1.24 +
    1.25 +// Log debug messages for each raw event received from the EventHub.
    1.26 +#define DEBUG_RAW_EVENTS 0
    1.27 +
    1.28 +// Log debug messages about touch screen filtering hacks.
    1.29 +#define DEBUG_HACKS 0
    1.30 +
    1.31 +// Log debug messages about virtual key processing.
    1.32 +#define DEBUG_VIRTUAL_KEYS 0
    1.33 +
    1.34 +// Log debug messages about pointers.
    1.35 +#define DEBUG_POINTERS 0
    1.36 +
    1.37 +// Log debug messages about pointer assignment calculations.
    1.38 +#define DEBUG_POINTER_ASSIGNMENT 0
    1.39 +
    1.40 +// Log debug messages about gesture detection.
    1.41 +#define DEBUG_GESTURES 0
    1.42 +
    1.43 +// Log debug messages about the vibrator.
    1.44 +#define DEBUG_VIBRATOR 0
    1.45 +
    1.46 +#include "InputReader.h"
    1.47 +
    1.48 +#include "Keyboard.h"
    1.49 +#include "VirtualKeyMap.h"
    1.50 +
    1.51 +#include <stddef.h>
    1.52 +#include <stdlib.h>
    1.53 +#include <unistd.h>
    1.54 +#include <errno.h>
    1.55 +#include <limits.h>
    1.56 +#include <math.h>
    1.57 +
    1.58 +#define INDENT "  "
    1.59 +#define INDENT2 "    "
    1.60 +#define INDENT3 "      "
    1.61 +#define INDENT4 "        "
    1.62 +#define INDENT5 "          "
    1.63 +
    1.64 +namespace android {
    1.65 +
    1.66 +// --- Constants ---
    1.67 +
    1.68 +// Maximum number of slots supported when using the slot-based Multitouch Protocol B.
    1.69 +static const size_t MAX_SLOTS = 32;
    1.70 +
    1.71 +// --- Static Functions ---
    1.72 +
    1.73 +template<typename T>
    1.74 +inline static T abs(const T& value) {
    1.75 +    return value < 0 ? - value : value;
    1.76 +}
    1.77 +
    1.78 +template<typename T>
    1.79 +inline static T min(const T& a, const T& b) {
    1.80 +    return a < b ? a : b;
    1.81 +}
    1.82 +
    1.83 +template<typename T>
    1.84 +inline static void swap(T& a, T& b) {
    1.85 +    T temp = a;
    1.86 +    a = b;
    1.87 +    b = temp;
    1.88 +}
    1.89 +
    1.90 +inline static float avg(float x, float y) {
    1.91 +    return (x + y) / 2;
    1.92 +}
    1.93 +
    1.94 +inline static float distance(float x1, float y1, float x2, float y2) {
    1.95 +    return hypotf(x1 - x2, y1 - y2);
    1.96 +}
    1.97 +
    1.98 +inline static int32_t signExtendNybble(int32_t value) {
    1.99 +    return value >= 8 ? value - 16 : value;
   1.100 +}
   1.101 +
   1.102 +static inline const char* toString(bool value) {
   1.103 +    return value ? "true" : "false";
   1.104 +}
   1.105 +
   1.106 +static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
   1.107 +        const int32_t map[][4], size_t mapSize) {
   1.108 +    if (orientation != DISPLAY_ORIENTATION_0) {
   1.109 +        for (size_t i = 0; i < mapSize; i++) {
   1.110 +            if (value == map[i][0]) {
   1.111 +                return map[i][orientation];
   1.112 +            }
   1.113 +        }
   1.114 +    }
   1.115 +    return value;
   1.116 +}
   1.117 +
   1.118 +static const int32_t keyCodeRotationMap[][4] = {
   1.119 +        // key codes enumerated counter-clockwise with the original (unrotated) key first
   1.120 +        // no rotation,        90 degree rotation,  180 degree rotation, 270 degree rotation
   1.121 +        { AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT },
   1.122 +        { AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN },
   1.123 +        { AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT },
   1.124 +        { AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP },
   1.125 +};
   1.126 +static const size_t keyCodeRotationMapSize =
   1.127 +        sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
   1.128 +
   1.129 +static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
   1.130 +    return rotateValueUsingRotationMap(keyCode, orientation,
   1.131 +            keyCodeRotationMap, keyCodeRotationMapSize);
   1.132 +}
   1.133 +
   1.134 +static void rotateDelta(int32_t orientation, float* deltaX, float* deltaY) {
   1.135 +    float temp;
   1.136 +    switch (orientation) {
   1.137 +    case DISPLAY_ORIENTATION_90:
   1.138 +        temp = *deltaX;
   1.139 +        *deltaX = *deltaY;
   1.140 +        *deltaY = -temp;
   1.141 +        break;
   1.142 +
   1.143 +    case DISPLAY_ORIENTATION_180:
   1.144 +        *deltaX = -*deltaX;
   1.145 +        *deltaY = -*deltaY;
   1.146 +        break;
   1.147 +
   1.148 +    case DISPLAY_ORIENTATION_270:
   1.149 +        temp = *deltaX;
   1.150 +        *deltaX = -*deltaY;
   1.151 +        *deltaY = temp;
   1.152 +        break;
   1.153 +    }
   1.154 +}
   1.155 +
   1.156 +static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
   1.157 +    return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
   1.158 +}
   1.159 +
   1.160 +// Returns true if the pointer should be reported as being down given the specified
   1.161 +// button states.  This determines whether the event is reported as a touch event.
   1.162 +static bool isPointerDown(int32_t buttonState) {
   1.163 +    return buttonState &
   1.164 +            (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY
   1.165 +                    | AMOTION_EVENT_BUTTON_TERTIARY);
   1.166 +}
   1.167 +
   1.168 +static float calculateCommonVector(float a, float b) {
   1.169 +    if (a > 0 && b > 0) {
   1.170 +        return a < b ? a : b;
   1.171 +    } else if (a < 0 && b < 0) {
   1.172 +        return a > b ? a : b;
   1.173 +    } else {
   1.174 +        return 0;
   1.175 +    }
   1.176 +}
   1.177 +
   1.178 +static void synthesizeButtonKey(InputReaderContext* context, int32_t action,
   1.179 +        nsecs_t when, int32_t deviceId, uint32_t source,
   1.180 +        uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState,
   1.181 +        int32_t buttonState, int32_t keyCode) {
   1.182 +    if (
   1.183 +            (action == AKEY_EVENT_ACTION_DOWN
   1.184 +                    && !(lastButtonState & buttonState)
   1.185 +                    && (currentButtonState & buttonState))
   1.186 +            || (action == AKEY_EVENT_ACTION_UP
   1.187 +                    && (lastButtonState & buttonState)
   1.188 +                    && !(currentButtonState & buttonState))) {
   1.189 +        NotifyKeyArgs args(when, deviceId, source, policyFlags,
   1.190 +                action, 0, keyCode, 0, context->getGlobalMetaState(), when);
   1.191 +        context->getListener()->notifyKey(&args);
   1.192 +    }
   1.193 +}
   1.194 +
   1.195 +static void synthesizeButtonKeys(InputReaderContext* context, int32_t action,
   1.196 +        nsecs_t when, int32_t deviceId, uint32_t source,
   1.197 +        uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) {
   1.198 +    synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
   1.199 +            lastButtonState, currentButtonState,
   1.200 +            AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK);
   1.201 +    synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
   1.202 +            lastButtonState, currentButtonState,
   1.203 +            AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD);
   1.204 +}
   1.205 +
   1.206 +
   1.207 +// --- InputReaderConfiguration ---
   1.208 +
   1.209 +bool InputReaderConfiguration::getDisplayInfo(bool external, DisplayViewport* outViewport) const {
   1.210 +    const DisplayViewport& viewport = external ? mExternalDisplay : mInternalDisplay;
   1.211 +    if (viewport.displayId >= 0) {
   1.212 +        *outViewport = viewport;
   1.213 +        return true;
   1.214 +    }
   1.215 +    return false;
   1.216 +}
   1.217 +
   1.218 +void InputReaderConfiguration::setDisplayInfo(bool external, const DisplayViewport& viewport) {
   1.219 +    DisplayViewport& v = external ? mExternalDisplay : mInternalDisplay;
   1.220 +    v = viewport;
   1.221 +}
   1.222 +
   1.223 +
   1.224 +// --- InputReader ---
   1.225 +
   1.226 +InputReader::InputReader(const sp<EventHubInterface>& eventHub,
   1.227 +        const sp<InputReaderPolicyInterface>& policy,
   1.228 +        const sp<InputListenerInterface>& listener) :
   1.229 +        mContext(this), mEventHub(eventHub), mPolicy(policy),
   1.230 +        mGlobalMetaState(0), mGeneration(1),
   1.231 +        mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
   1.232 +        mConfigurationChangesToRefresh(0) {
   1.233 +    mQueuedListener = new QueuedInputListener(listener);
   1.234 +
   1.235 +    { // acquire lock
   1.236 +        AutoMutex _l(mLock);
   1.237 +
   1.238 +        refreshConfigurationLocked(0);
   1.239 +        updateGlobalMetaStateLocked();
   1.240 +    } // release lock
   1.241 +}
   1.242 +
   1.243 +InputReader::~InputReader() {
   1.244 +    for (size_t i = 0; i < mDevices.size(); i++) {
   1.245 +        delete mDevices.valueAt(i);
   1.246 +    }
   1.247 +}
   1.248 +
   1.249 +void InputReader::loopOnce() {
   1.250 +    int32_t oldGeneration;
   1.251 +    int32_t timeoutMillis;
   1.252 +    bool inputDevicesChanged = false;
   1.253 +    Vector<InputDeviceInfo> inputDevices;
   1.254 +    { // acquire lock
   1.255 +        AutoMutex _l(mLock);
   1.256 +
   1.257 +        oldGeneration = mGeneration;
   1.258 +        timeoutMillis = -1;
   1.259 +
   1.260 +        uint32_t changes = mConfigurationChangesToRefresh;
   1.261 +        if (changes) {
   1.262 +            mConfigurationChangesToRefresh = 0;
   1.263 +            timeoutMillis = 0;
   1.264 +            refreshConfigurationLocked(changes);
   1.265 +        } else if (mNextTimeout != LLONG_MAX) {
   1.266 +            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
   1.267 +            timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
   1.268 +        }
   1.269 +    } // release lock
   1.270 +
   1.271 +    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
   1.272 +
   1.273 +    { // acquire lock
   1.274 +        AutoMutex _l(mLock);
   1.275 +        mReaderIsAliveCondition.broadcast();
   1.276 +
   1.277 +        if (count) {
   1.278 +            processEventsLocked(mEventBuffer, count);
   1.279 +        }
   1.280 +
   1.281 +        if (mNextTimeout != LLONG_MAX) {
   1.282 +            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
   1.283 +            if (now >= mNextTimeout) {
   1.284 +#if DEBUG_RAW_EVENTS
   1.285 +                ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
   1.286 +#endif
   1.287 +                mNextTimeout = LLONG_MAX;
   1.288 +                timeoutExpiredLocked(now);
   1.289 +            }
   1.290 +        }
   1.291 +
   1.292 +        if (oldGeneration != mGeneration) {
   1.293 +            inputDevicesChanged = true;
   1.294 +            getInputDevicesLocked(inputDevices);
   1.295 +        }
   1.296 +    } // release lock
   1.297 +
   1.298 +    // Send out a message that the describes the changed input devices.
   1.299 +    if (inputDevicesChanged) {
   1.300 +        mPolicy->notifyInputDevicesChanged(inputDevices);
   1.301 +    }
   1.302 +
   1.303 +    // Flush queued events out to the listener.
   1.304 +    // This must happen outside of the lock because the listener could potentially call
   1.305 +    // back into the InputReader's methods, such as getScanCodeState, or become blocked
   1.306 +    // on another thread similarly waiting to acquire the InputReader lock thereby
   1.307 +    // resulting in a deadlock.  This situation is actually quite plausible because the
   1.308 +    // listener is actually the input dispatcher, which calls into the window manager,
   1.309 +    // which occasionally calls into the input reader.
   1.310 +    mQueuedListener->flush();
   1.311 +}
   1.312 +
   1.313 +void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
   1.314 +    for (const RawEvent* rawEvent = rawEvents; count;) {
   1.315 +        int32_t type = rawEvent->type;
   1.316 +        size_t batchSize = 1;
   1.317 +        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
   1.318 +            int32_t deviceId = rawEvent->deviceId;
   1.319 +            while (batchSize < count) {
   1.320 +                if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
   1.321 +                        || rawEvent[batchSize].deviceId != deviceId) {
   1.322 +                    break;
   1.323 +                }
   1.324 +                batchSize += 1;
   1.325 +            }
   1.326 +#if DEBUG_RAW_EVENTS
   1.327 +            ALOGD("BatchSize: %d Count: %d", batchSize, count);
   1.328 +#endif
   1.329 +            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
   1.330 +        } else {
   1.331 +            switch (rawEvent->type) {
   1.332 +            case EventHubInterface::DEVICE_ADDED:
   1.333 +                addDeviceLocked(rawEvent->when, rawEvent->deviceId);
   1.334 +                break;
   1.335 +            case EventHubInterface::DEVICE_REMOVED:
   1.336 +                removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
   1.337 +                break;
   1.338 +            case EventHubInterface::FINISHED_DEVICE_SCAN:
   1.339 +                handleConfigurationChangedLocked(rawEvent->when);
   1.340 +                break;
   1.341 +            default:
   1.342 +                ALOG_ASSERT(false); // can't happen
   1.343 +                break;
   1.344 +            }
   1.345 +        }
   1.346 +        count -= batchSize;
   1.347 +        rawEvent += batchSize;
   1.348 +    }
   1.349 +}
   1.350 +
   1.351 +void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
   1.352 +    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
   1.353 +    if (deviceIndex >= 0) {
   1.354 +        ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
   1.355 +        return;
   1.356 +    }
   1.357 +
   1.358 +    InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
   1.359 +    uint32_t classes = mEventHub->getDeviceClasses(deviceId);
   1.360 +
   1.361 +    InputDevice* device = createDeviceLocked(deviceId, identifier, classes);
   1.362 +    device->configure(when, &mConfig, 0);
   1.363 +    device->reset(when);
   1.364 +
   1.365 +    if (device->isIgnored()) {
   1.366 +        ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
   1.367 +                identifier.name.string());
   1.368 +    } else {
   1.369 +        ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
   1.370 +                identifier.name.string(), device->getSources());
   1.371 +    }
   1.372 +
   1.373 +    mDevices.add(deviceId, device);
   1.374 +    bumpGenerationLocked();
   1.375 +}
   1.376 +
   1.377 +void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
   1.378 +    InputDevice* device = NULL;
   1.379 +    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
   1.380 +    if (deviceIndex < 0) {
   1.381 +        ALOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
   1.382 +        return;
   1.383 +    }
   1.384 +
   1.385 +    device = mDevices.valueAt(deviceIndex);
   1.386 +    mDevices.removeItemsAt(deviceIndex, 1);
   1.387 +    bumpGenerationLocked();
   1.388 +
   1.389 +    if (device->isIgnored()) {
   1.390 +        ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
   1.391 +                device->getId(), device->getName().string());
   1.392 +    } else {
   1.393 +        ALOGI("Device removed: id=%d, name='%s', sources=0x%08x",
   1.394 +                device->getId(), device->getName().string(), device->getSources());
   1.395 +    }
   1.396 +
   1.397 +    device->reset(when);
   1.398 +    delete device;
   1.399 +}
   1.400 +
   1.401 +InputDevice* InputReader::createDeviceLocked(int32_t deviceId,
   1.402 +        const InputDeviceIdentifier& identifier, uint32_t classes) {
   1.403 +    InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
   1.404 +            identifier, classes);
   1.405 +
   1.406 +    // External devices.
   1.407 +    if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
   1.408 +        device->setExternal(true);
   1.409 +    }
   1.410 +
   1.411 +    // Switch-like devices.
   1.412 +    if (classes & INPUT_DEVICE_CLASS_SWITCH) {
   1.413 +        device->addMapper(new SwitchInputMapper(device));
   1.414 +    }
   1.415 +
   1.416 +    // Vibrator-like devices.
   1.417 +    if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
   1.418 +        device->addMapper(new VibratorInputMapper(device));
   1.419 +    }
   1.420 +
   1.421 +    // Keyboard-like devices.
   1.422 +    uint32_t keyboardSource = 0;
   1.423 +    int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
   1.424 +    if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
   1.425 +        keyboardSource |= AINPUT_SOURCE_KEYBOARD;
   1.426 +    }
   1.427 +    if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
   1.428 +        keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
   1.429 +    }
   1.430 +    if (classes & INPUT_DEVICE_CLASS_DPAD) {
   1.431 +        keyboardSource |= AINPUT_SOURCE_DPAD;
   1.432 +    }
   1.433 +    if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
   1.434 +        keyboardSource |= AINPUT_SOURCE_GAMEPAD;
   1.435 +    }
   1.436 +
   1.437 +    if (keyboardSource != 0) {
   1.438 +        device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
   1.439 +    }
   1.440 +
   1.441 +    // Cursor-like devices.
   1.442 +    if (classes & INPUT_DEVICE_CLASS_CURSOR) {
   1.443 +        device->addMapper(new CursorInputMapper(device));
   1.444 +    }
   1.445 +
   1.446 +    // Touchscreens and touchpad devices.
   1.447 +    if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
   1.448 +        device->addMapper(new MultiTouchInputMapper(device));
   1.449 +    } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
   1.450 +        device->addMapper(new SingleTouchInputMapper(device));
   1.451 +    }
   1.452 +
   1.453 +    // Joystick-like devices.
   1.454 +    if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
   1.455 +        device->addMapper(new JoystickInputMapper(device));
   1.456 +    }
   1.457 +
   1.458 +    return device;
   1.459 +}
   1.460 +
   1.461 +void InputReader::processEventsForDeviceLocked(int32_t deviceId,
   1.462 +        const RawEvent* rawEvents, size_t count) {
   1.463 +    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
   1.464 +    if (deviceIndex < 0) {
   1.465 +        ALOGW("Discarding event for unknown deviceId %d.", deviceId);
   1.466 +        return;
   1.467 +    }
   1.468 +
   1.469 +    InputDevice* device = mDevices.valueAt(deviceIndex);
   1.470 +    if (device->isIgnored()) {
   1.471 +        //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
   1.472 +        return;
   1.473 +    }
   1.474 +
   1.475 +    device->process(rawEvents, count);
   1.476 +}
   1.477 +
   1.478 +void InputReader::timeoutExpiredLocked(nsecs_t when) {
   1.479 +    for (size_t i = 0; i < mDevices.size(); i++) {
   1.480 +        InputDevice* device = mDevices.valueAt(i);
   1.481 +        if (!device->isIgnored()) {
   1.482 +            device->timeoutExpired(when);
   1.483 +        }
   1.484 +    }
   1.485 +}
   1.486 +
   1.487 +void InputReader::handleConfigurationChangedLocked(nsecs_t when) {
   1.488 +    // Reset global meta state because it depends on the list of all configured devices.
   1.489 +    updateGlobalMetaStateLocked();
   1.490 +
   1.491 +    // Enqueue configuration changed.
   1.492 +    NotifyConfigurationChangedArgs args(when);
   1.493 +    mQueuedListener->notifyConfigurationChanged(&args);
   1.494 +}
   1.495 +
   1.496 +void InputReader::refreshConfigurationLocked(uint32_t changes) {
   1.497 +    mPolicy->getReaderConfiguration(&mConfig);
   1.498 +    mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
   1.499 +
   1.500 +    if (changes) {
   1.501 +        ALOGI("Reconfiguring input devices.  changes=0x%08x", changes);
   1.502 +        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
   1.503 +
   1.504 +        if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
   1.505 +            mEventHub->requestReopenDevices();
   1.506 +        } else {
   1.507 +            for (size_t i = 0; i < mDevices.size(); i++) {
   1.508 +                InputDevice* device = mDevices.valueAt(i);
   1.509 +                device->configure(now, &mConfig, changes);
   1.510 +            }
   1.511 +        }
   1.512 +    }
   1.513 +}
   1.514 +
   1.515 +void InputReader::updateGlobalMetaStateLocked() {
   1.516 +    mGlobalMetaState = 0;
   1.517 +
   1.518 +    for (size_t i = 0; i < mDevices.size(); i++) {
   1.519 +        InputDevice* device = mDevices.valueAt(i);
   1.520 +        mGlobalMetaState |= device->getMetaState();
   1.521 +    }
   1.522 +}
   1.523 +
   1.524 +int32_t InputReader::getGlobalMetaStateLocked() {
   1.525 +    return mGlobalMetaState;
   1.526 +}
   1.527 +
   1.528 +void InputReader::disableVirtualKeysUntilLocked(nsecs_t time) {
   1.529 +    mDisableVirtualKeysTimeout = time;
   1.530 +}
   1.531 +
   1.532 +bool InputReader::shouldDropVirtualKeyLocked(nsecs_t now,
   1.533 +        InputDevice* device, int32_t keyCode, int32_t scanCode) {
   1.534 +    if (now < mDisableVirtualKeysTimeout) {
   1.535 +        ALOGI("Dropping virtual key from device %s because virtual keys are "
   1.536 +                "temporarily disabled for the next %0.3fms.  keyCode=%d, scanCode=%d",
   1.537 +                device->getName().string(),
   1.538 +                (mDisableVirtualKeysTimeout - now) * 0.000001,
   1.539 +                keyCode, scanCode);
   1.540 +        return true;
   1.541 +    } else {
   1.542 +        return false;
   1.543 +    }
   1.544 +}
   1.545 +
   1.546 +void InputReader::fadePointerLocked() {
   1.547 +    for (size_t i = 0; i < mDevices.size(); i++) {
   1.548 +        InputDevice* device = mDevices.valueAt(i);
   1.549 +        device->fadePointer();
   1.550 +    }
   1.551 +}
   1.552 +
   1.553 +void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) {
   1.554 +    if (when < mNextTimeout) {
   1.555 +        mNextTimeout = when;
   1.556 +        mEventHub->wake();
   1.557 +    }
   1.558 +}
   1.559 +
   1.560 +int32_t InputReader::bumpGenerationLocked() {
   1.561 +    return ++mGeneration;
   1.562 +}
   1.563 +
   1.564 +void InputReader::getInputDevices(Vector<InputDeviceInfo>& outInputDevices) {
   1.565 +    AutoMutex _l(mLock);
   1.566 +    getInputDevicesLocked(outInputDevices);
   1.567 +}
   1.568 +
   1.569 +void InputReader::getInputDevicesLocked(Vector<InputDeviceInfo>& outInputDevices) {
   1.570 +    outInputDevices.clear();
   1.571 +
   1.572 +    size_t numDevices = mDevices.size();
   1.573 +    for (size_t i = 0; i < numDevices; i++) {
   1.574 +        InputDevice* device = mDevices.valueAt(i);
   1.575 +        if (!device->isIgnored()) {
   1.576 +            outInputDevices.push();
   1.577 +            device->getDeviceInfo(&outInputDevices.editTop());
   1.578 +        }
   1.579 +    }
   1.580 +}
   1.581 +
   1.582 +int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
   1.583 +        int32_t keyCode) {
   1.584 +    AutoMutex _l(mLock);
   1.585 +
   1.586 +    return getStateLocked(deviceId, sourceMask, keyCode, &InputDevice::getKeyCodeState);
   1.587 +}
   1.588 +
   1.589 +int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
   1.590 +        int32_t scanCode) {
   1.591 +    AutoMutex _l(mLock);
   1.592 +
   1.593 +    return getStateLocked(deviceId, sourceMask, scanCode, &InputDevice::getScanCodeState);
   1.594 +}
   1.595 +
   1.596 +int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
   1.597 +    AutoMutex _l(mLock);
   1.598 +
   1.599 +    return getStateLocked(deviceId, sourceMask, switchCode, &InputDevice::getSwitchState);
   1.600 +}
   1.601 +
   1.602 +int32_t InputReader::getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
   1.603 +        GetStateFunc getStateFunc) {
   1.604 +    int32_t result = AKEY_STATE_UNKNOWN;
   1.605 +    if (deviceId >= 0) {
   1.606 +        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
   1.607 +        if (deviceIndex >= 0) {
   1.608 +            InputDevice* device = mDevices.valueAt(deviceIndex);
   1.609 +            if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
   1.610 +                result = (device->*getStateFunc)(sourceMask, code);
   1.611 +            }
   1.612 +        }
   1.613 +    } else {
   1.614 +        size_t numDevices = mDevices.size();
   1.615 +        for (size_t i = 0; i < numDevices; i++) {
   1.616 +            InputDevice* device = mDevices.valueAt(i);
   1.617 +            if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
   1.618 +                // If any device reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
   1.619 +                // value.  Otherwise, return AKEY_STATE_UP as long as one device reports it.
   1.620 +                int32_t currentResult = (device->*getStateFunc)(sourceMask, code);
   1.621 +                if (currentResult >= AKEY_STATE_DOWN) {
   1.622 +                    return currentResult;
   1.623 +                } else if (currentResult == AKEY_STATE_UP) {
   1.624 +                    result = currentResult;
   1.625 +                }
   1.626 +            }
   1.627 +        }
   1.628 +    }
   1.629 +    return result;
   1.630 +}
   1.631 +
   1.632 +bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
   1.633 +        size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
   1.634 +    AutoMutex _l(mLock);
   1.635 +
   1.636 +    memset(outFlags, 0, numCodes);
   1.637 +    return markSupportedKeyCodesLocked(deviceId, sourceMask, numCodes, keyCodes, outFlags);
   1.638 +}
   1.639 +
   1.640 +bool InputReader::markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask,
   1.641 +        size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
   1.642 +    bool result = false;
   1.643 +    if (deviceId >= 0) {
   1.644 +        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
   1.645 +        if (deviceIndex >= 0) {
   1.646 +            InputDevice* device = mDevices.valueAt(deviceIndex);
   1.647 +            if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
   1.648 +                result = device->markSupportedKeyCodes(sourceMask,
   1.649 +                        numCodes, keyCodes, outFlags);
   1.650 +            }
   1.651 +        }
   1.652 +    } else {
   1.653 +        size_t numDevices = mDevices.size();
   1.654 +        for (size_t i = 0; i < numDevices; i++) {
   1.655 +            InputDevice* device = mDevices.valueAt(i);
   1.656 +            if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
   1.657 +                result |= device->markSupportedKeyCodes(sourceMask,
   1.658 +                        numCodes, keyCodes, outFlags);
   1.659 +            }
   1.660 +        }
   1.661 +    }
   1.662 +    return result;
   1.663 +}
   1.664 +
   1.665 +void InputReader::requestRefreshConfiguration(uint32_t changes) {
   1.666 +    AutoMutex _l(mLock);
   1.667 +
   1.668 +    if (changes) {
   1.669 +        bool needWake = !mConfigurationChangesToRefresh;
   1.670 +        mConfigurationChangesToRefresh |= changes;
   1.671 +
   1.672 +        if (needWake) {
   1.673 +            mEventHub->wake();
   1.674 +        }
   1.675 +    }
   1.676 +}
   1.677 +
   1.678 +void InputReader::vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
   1.679 +        ssize_t repeat, int32_t token) {
   1.680 +    AutoMutex _l(mLock);
   1.681 +
   1.682 +    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
   1.683 +    if (deviceIndex >= 0) {
   1.684 +        InputDevice* device = mDevices.valueAt(deviceIndex);
   1.685 +        device->vibrate(pattern, patternSize, repeat, token);
   1.686 +    }
   1.687 +}
   1.688 +
   1.689 +void InputReader::cancelVibrate(int32_t deviceId, int32_t token) {
   1.690 +    AutoMutex _l(mLock);
   1.691 +
   1.692 +    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
   1.693 +    if (deviceIndex >= 0) {
   1.694 +        InputDevice* device = mDevices.valueAt(deviceIndex);
   1.695 +        device->cancelVibrate(token);
   1.696 +    }
   1.697 +}
   1.698 +
   1.699 +void InputReader::dump(String8& dump) {
   1.700 +    AutoMutex _l(mLock);
   1.701 +
   1.702 +    mEventHub->dump(dump);
   1.703 +    dump.append("\n");
   1.704 +
   1.705 +    dump.append("Input Reader State:\n");
   1.706 +
   1.707 +    for (size_t i = 0; i < mDevices.size(); i++) {
   1.708 +        mDevices.valueAt(i)->dump(dump);
   1.709 +    }
   1.710 +
   1.711 +    dump.append(INDENT "Configuration:\n");
   1.712 +    dump.append(INDENT2 "ExcludedDeviceNames: [");
   1.713 +    for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
   1.714 +        if (i != 0) {
   1.715 +            dump.append(", ");
   1.716 +        }
   1.717 +        dump.append(mConfig.excludedDeviceNames.itemAt(i).string());
   1.718 +    }
   1.719 +    dump.append("]\n");
   1.720 +    dump.appendFormat(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
   1.721 +            mConfig.virtualKeyQuietTime * 0.000001f);
   1.722 +
   1.723 +    dump.appendFormat(INDENT2 "PointerVelocityControlParameters: "
   1.724 +            "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
   1.725 +            mConfig.pointerVelocityControlParameters.scale,
   1.726 +            mConfig.pointerVelocityControlParameters.lowThreshold,
   1.727 +            mConfig.pointerVelocityControlParameters.highThreshold,
   1.728 +            mConfig.pointerVelocityControlParameters.acceleration);
   1.729 +
   1.730 +    dump.appendFormat(INDENT2 "WheelVelocityControlParameters: "
   1.731 +            "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
   1.732 +            mConfig.wheelVelocityControlParameters.scale,
   1.733 +            mConfig.wheelVelocityControlParameters.lowThreshold,
   1.734 +            mConfig.wheelVelocityControlParameters.highThreshold,
   1.735 +            mConfig.wheelVelocityControlParameters.acceleration);
   1.736 +
   1.737 +    dump.appendFormat(INDENT2 "PointerGesture:\n");
   1.738 +    dump.appendFormat(INDENT3 "Enabled: %s\n",
   1.739 +            toString(mConfig.pointerGesturesEnabled));
   1.740 +    dump.appendFormat(INDENT3 "QuietInterval: %0.1fms\n",
   1.741 +            mConfig.pointerGestureQuietInterval * 0.000001f);
   1.742 +    dump.appendFormat(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
   1.743 +            mConfig.pointerGestureDragMinSwitchSpeed);
   1.744 +    dump.appendFormat(INDENT3 "TapInterval: %0.1fms\n",
   1.745 +            mConfig.pointerGestureTapInterval * 0.000001f);
   1.746 +    dump.appendFormat(INDENT3 "TapDragInterval: %0.1fms\n",
   1.747 +            mConfig.pointerGestureTapDragInterval * 0.000001f);
   1.748 +    dump.appendFormat(INDENT3 "TapSlop: %0.1fpx\n",
   1.749 +            mConfig.pointerGestureTapSlop);
   1.750 +    dump.appendFormat(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
   1.751 +            mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
   1.752 +    dump.appendFormat(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
   1.753 +            mConfig.pointerGestureMultitouchMinDistance);
   1.754 +    dump.appendFormat(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
   1.755 +            mConfig.pointerGestureSwipeTransitionAngleCosine);
   1.756 +    dump.appendFormat(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
   1.757 +            mConfig.pointerGestureSwipeMaxWidthRatio);
   1.758 +    dump.appendFormat(INDENT3 "MovementSpeedRatio: %0.1f\n",
   1.759 +            mConfig.pointerGestureMovementSpeedRatio);
   1.760 +    dump.appendFormat(INDENT3 "ZoomSpeedRatio: %0.1f\n",
   1.761 +            mConfig.pointerGestureZoomSpeedRatio);
   1.762 +}
   1.763 +
   1.764 +void InputReader::monitor() {
   1.765 +    // Acquire and release the lock to ensure that the reader has not deadlocked.
   1.766 +    mLock.lock();
   1.767 +    mEventHub->wake();
   1.768 +    mReaderIsAliveCondition.wait(mLock);
   1.769 +    mLock.unlock();
   1.770 +
   1.771 +    // Check the EventHub
   1.772 +    mEventHub->monitor();
   1.773 +}
   1.774 +
   1.775 +
   1.776 +// --- InputReader::ContextImpl ---
   1.777 +
   1.778 +InputReader::ContextImpl::ContextImpl(InputReader* reader) :
   1.779 +        mReader(reader) {
   1.780 +}
   1.781 +
   1.782 +void InputReader::ContextImpl::updateGlobalMetaState() {
   1.783 +    // lock is already held by the input loop
   1.784 +    mReader->updateGlobalMetaStateLocked();
   1.785 +}
   1.786 +
   1.787 +int32_t InputReader::ContextImpl::getGlobalMetaState() {
   1.788 +    // lock is already held by the input loop
   1.789 +    return mReader->getGlobalMetaStateLocked();
   1.790 +}
   1.791 +
   1.792 +void InputReader::ContextImpl::disableVirtualKeysUntil(nsecs_t time) {
   1.793 +    // lock is already held by the input loop
   1.794 +    mReader->disableVirtualKeysUntilLocked(time);
   1.795 +}
   1.796 +
   1.797 +bool InputReader::ContextImpl::shouldDropVirtualKey(nsecs_t now,
   1.798 +        InputDevice* device, int32_t keyCode, int32_t scanCode) {
   1.799 +    // lock is already held by the input loop
   1.800 +    return mReader->shouldDropVirtualKeyLocked(now, device, keyCode, scanCode);
   1.801 +}
   1.802 +
   1.803 +void InputReader::ContextImpl::fadePointer() {
   1.804 +    // lock is already held by the input loop
   1.805 +    mReader->fadePointerLocked();
   1.806 +}
   1.807 +
   1.808 +void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) {
   1.809 +    // lock is already held by the input loop
   1.810 +    mReader->requestTimeoutAtTimeLocked(when);
   1.811 +}
   1.812 +
   1.813 +int32_t InputReader::ContextImpl::bumpGeneration() {
   1.814 +    // lock is already held by the input loop
   1.815 +    return mReader->bumpGenerationLocked();
   1.816 +}
   1.817 +
   1.818 +InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() {
   1.819 +    return mReader->mPolicy.get();
   1.820 +}
   1.821 +
   1.822 +InputListenerInterface* InputReader::ContextImpl::getListener() {
   1.823 +    return mReader->mQueuedListener.get();
   1.824 +}
   1.825 +
   1.826 +EventHubInterface* InputReader::ContextImpl::getEventHub() {
   1.827 +    return mReader->mEventHub.get();
   1.828 +}
   1.829 +
   1.830 +
   1.831 +// --- InputReaderThread ---
   1.832 +
   1.833 +InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
   1.834 +        Thread(/*canCallJava*/ true), mReader(reader) {
   1.835 +}
   1.836 +
   1.837 +InputReaderThread::~InputReaderThread() {
   1.838 +}
   1.839 +
   1.840 +bool InputReaderThread::threadLoop() {
   1.841 +    mReader->loopOnce();
   1.842 +    return true;
   1.843 +}
   1.844 +
   1.845 +
   1.846 +// --- InputDevice ---
   1.847 +
   1.848 +InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
   1.849 +        const InputDeviceIdentifier& identifier, uint32_t classes) :
   1.850 +        mContext(context), mId(id), mGeneration(generation),
   1.851 +        mIdentifier(identifier), mClasses(classes),
   1.852 +        mSources(0), mIsExternal(false), mDropUntilNextSync(false) {
   1.853 +}
   1.854 +
   1.855 +InputDevice::~InputDevice() {
   1.856 +    size_t numMappers = mMappers.size();
   1.857 +    for (size_t i = 0; i < numMappers; i++) {
   1.858 +        delete mMappers[i];
   1.859 +    }
   1.860 +    mMappers.clear();
   1.861 +}
   1.862 +
   1.863 +void InputDevice::dump(String8& dump) {
   1.864 +    InputDeviceInfo deviceInfo;
   1.865 +    getDeviceInfo(& deviceInfo);
   1.866 +
   1.867 +    dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
   1.868 +            deviceInfo.getDisplayName().string());
   1.869 +    dump.appendFormat(INDENT2 "Generation: %d\n", mGeneration);
   1.870 +    dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
   1.871 +    dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
   1.872 +    dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
   1.873 +
   1.874 +    const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
   1.875 +    if (!ranges.isEmpty()) {
   1.876 +        dump.append(INDENT2 "Motion Ranges:\n");
   1.877 +        for (size_t i = 0; i < ranges.size(); i++) {
   1.878 +            const InputDeviceInfo::MotionRange& range = ranges.itemAt(i);
   1.879 +            const char* label = getAxisLabel(range.axis);
   1.880 +            char name[32];
   1.881 +            if (label) {
   1.882 +                strncpy(name, label, sizeof(name));
   1.883 +                name[sizeof(name) - 1] = '\0';
   1.884 +            } else {
   1.885 +                snprintf(name, sizeof(name), "%d", range.axis);
   1.886 +            }
   1.887 +            dump.appendFormat(INDENT3 "%s: source=0x%08x, "
   1.888 +                    "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, resolution=%0.3f\n",
   1.889 +                    name, range.source, range.min, range.max, range.flat, range.fuzz,
   1.890 +                    range.resolution);
   1.891 +        }
   1.892 +    }
   1.893 +
   1.894 +    size_t numMappers = mMappers.size();
   1.895 +    for (size_t i = 0; i < numMappers; i++) {
   1.896 +        InputMapper* mapper = mMappers[i];
   1.897 +        mapper->dump(dump);
   1.898 +    }
   1.899 +}
   1.900 +
   1.901 +void InputDevice::addMapper(InputMapper* mapper) {
   1.902 +    mMappers.add(mapper);
   1.903 +}
   1.904 +
   1.905 +void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) {
   1.906 +    mSources = 0;
   1.907 +
   1.908 +    if (!isIgnored()) {
   1.909 +        if (!changes) { // first time only
   1.910 +            mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
   1.911 +        }
   1.912 +
   1.913 +        if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {
   1.914 +            if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
   1.915 +                sp<KeyCharacterMap> keyboardLayout =
   1.916 +                        mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier.descriptor);
   1.917 +                if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) {
   1.918 +                    bumpGeneration();
   1.919 +                }
   1.920 +            }
   1.921 +        }
   1.922 +
   1.923 +        if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
   1.924 +            if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
   1.925 +                String8 alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
   1.926 +                if (mAlias != alias) {
   1.927 +                    mAlias = alias;
   1.928 +                    bumpGeneration();
   1.929 +                }
   1.930 +            }
   1.931 +        }
   1.932 +
   1.933 +        size_t numMappers = mMappers.size();
   1.934 +        for (size_t i = 0; i < numMappers; i++) {
   1.935 +            InputMapper* mapper = mMappers[i];
   1.936 +            mapper->configure(when, config, changes);
   1.937 +            mSources |= mapper->getSources();
   1.938 +        }
   1.939 +    }
   1.940 +}
   1.941 +
   1.942 +void InputDevice::reset(nsecs_t when) {
   1.943 +    size_t numMappers = mMappers.size();
   1.944 +    for (size_t i = 0; i < numMappers; i++) {
   1.945 +        InputMapper* mapper = mMappers[i];
   1.946 +        mapper->reset(when);
   1.947 +    }
   1.948 +
   1.949 +    mContext->updateGlobalMetaState();
   1.950 +
   1.951 +    notifyReset(when);
   1.952 +}
   1.953 +
   1.954 +void InputDevice::process(const RawEvent* rawEvents, size_t count) {
   1.955 +    // Process all of the events in order for each mapper.
   1.956 +    // We cannot simply ask each mapper to process them in bulk because mappers may
   1.957 +    // have side-effects that must be interleaved.  For example, joystick movement events and
   1.958 +    // gamepad button presses are handled by different mappers but they should be dispatched
   1.959 +    // in the order received.
   1.960 +    size_t numMappers = mMappers.size();
   1.961 +    for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
   1.962 +#if DEBUG_RAW_EVENTS
   1.963 +        ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%lld",
   1.964 +                rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,
   1.965 +                rawEvent->when);
   1.966 +#endif
   1.967 +
   1.968 +        if (mDropUntilNextSync) {
   1.969 +            if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
   1.970 +                mDropUntilNextSync = false;
   1.971 +#if DEBUG_RAW_EVENTS
   1.972 +                ALOGD("Recovered from input event buffer overrun.");
   1.973 +#endif
   1.974 +            } else {
   1.975 +#if DEBUG_RAW_EVENTS
   1.976 +                ALOGD("Dropped input event while waiting for next input sync.");
   1.977 +#endif
   1.978 +            }
   1.979 +        } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
   1.980 +            ALOGI("Detected input event buffer overrun for device %s.", getName().string());
   1.981 +            mDropUntilNextSync = true;
   1.982 +            reset(rawEvent->when);
   1.983 +        } else {
   1.984 +            for (size_t i = 0; i < numMappers; i++) {
   1.985 +                InputMapper* mapper = mMappers[i];
   1.986 +                mapper->process(rawEvent);
   1.987 +            }
   1.988 +        }
   1.989 +    }
   1.990 +}
   1.991 +
   1.992 +void InputDevice::timeoutExpired(nsecs_t when) {
   1.993 +    size_t numMappers = mMappers.size();
   1.994 +    for (size_t i = 0; i < numMappers; i++) {
   1.995 +        InputMapper* mapper = mMappers[i];
   1.996 +        mapper->timeoutExpired(when);
   1.997 +    }
   1.998 +}
   1.999 +
  1.1000 +void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
  1.1001 +    outDeviceInfo->initialize(mId, mGeneration, mIdentifier, mAlias, mIsExternal);
  1.1002 +
  1.1003 +    size_t numMappers = mMappers.size();
  1.1004 +    for (size_t i = 0; i < numMappers; i++) {
  1.1005 +        InputMapper* mapper = mMappers[i];
  1.1006 +        mapper->populateDeviceInfo(outDeviceInfo);
  1.1007 +    }
  1.1008 +}
  1.1009 +
  1.1010 +int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
  1.1011 +    return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
  1.1012 +}
  1.1013 +
  1.1014 +int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
  1.1015 +    return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
  1.1016 +}
  1.1017 +
  1.1018 +int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
  1.1019 +    return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
  1.1020 +}
  1.1021 +
  1.1022 +int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
  1.1023 +    int32_t result = AKEY_STATE_UNKNOWN;
  1.1024 +    size_t numMappers = mMappers.size();
  1.1025 +    for (size_t i = 0; i < numMappers; i++) {
  1.1026 +        InputMapper* mapper = mMappers[i];
  1.1027 +        if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
  1.1028 +            // If any mapper reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
  1.1029 +            // value.  Otherwise, return AKEY_STATE_UP as long as one mapper reports it.
  1.1030 +            int32_t currentResult = (mapper->*getStateFunc)(sourceMask, code);
  1.1031 +            if (currentResult >= AKEY_STATE_DOWN) {
  1.1032 +                return currentResult;
  1.1033 +            } else if (currentResult == AKEY_STATE_UP) {
  1.1034 +                result = currentResult;
  1.1035 +            }
  1.1036 +        }
  1.1037 +    }
  1.1038 +    return result;
  1.1039 +}
  1.1040 +
  1.1041 +bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
  1.1042 +        const int32_t* keyCodes, uint8_t* outFlags) {
  1.1043 +    bool result = false;
  1.1044 +    size_t numMappers = mMappers.size();
  1.1045 +    for (size_t i = 0; i < numMappers; i++) {
  1.1046 +        InputMapper* mapper = mMappers[i];
  1.1047 +        if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
  1.1048 +            result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
  1.1049 +        }
  1.1050 +    }
  1.1051 +    return result;
  1.1052 +}
  1.1053 +
  1.1054 +void InputDevice::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
  1.1055 +        int32_t token) {
  1.1056 +    size_t numMappers = mMappers.size();
  1.1057 +    for (size_t i = 0; i < numMappers; i++) {
  1.1058 +        InputMapper* mapper = mMappers[i];
  1.1059 +        mapper->vibrate(pattern, patternSize, repeat, token);
  1.1060 +    }
  1.1061 +}
  1.1062 +
  1.1063 +void InputDevice::cancelVibrate(int32_t token) {
  1.1064 +    size_t numMappers = mMappers.size();
  1.1065 +    for (size_t i = 0; i < numMappers; i++) {
  1.1066 +        InputMapper* mapper = mMappers[i];
  1.1067 +        mapper->cancelVibrate(token);
  1.1068 +    }
  1.1069 +}
  1.1070 +
  1.1071 +int32_t InputDevice::getMetaState() {
  1.1072 +    int32_t result = 0;
  1.1073 +    size_t numMappers = mMappers.size();
  1.1074 +    for (size_t i = 0; i < numMappers; i++) {
  1.1075 +        InputMapper* mapper = mMappers[i];
  1.1076 +        result |= mapper->getMetaState();
  1.1077 +    }
  1.1078 +    return result;
  1.1079 +}
  1.1080 +
  1.1081 +void InputDevice::fadePointer() {
  1.1082 +    size_t numMappers = mMappers.size();
  1.1083 +    for (size_t i = 0; i < numMappers; i++) {
  1.1084 +        InputMapper* mapper = mMappers[i];
  1.1085 +        mapper->fadePointer();
  1.1086 +    }
  1.1087 +}
  1.1088 +
  1.1089 +void InputDevice::bumpGeneration() {
  1.1090 +    mGeneration = mContext->bumpGeneration();
  1.1091 +}
  1.1092 +
  1.1093 +void InputDevice::notifyReset(nsecs_t when) {
  1.1094 +    NotifyDeviceResetArgs args(when, mId);
  1.1095 +    mContext->getListener()->notifyDeviceReset(&args);
  1.1096 +}
  1.1097 +
  1.1098 +
  1.1099 +// --- CursorButtonAccumulator ---
  1.1100 +
  1.1101 +CursorButtonAccumulator::CursorButtonAccumulator() {
  1.1102 +    clearButtons();
  1.1103 +}
  1.1104 +
  1.1105 +void CursorButtonAccumulator::reset(InputDevice* device) {
  1.1106 +    mBtnLeft = device->isKeyPressed(BTN_LEFT);
  1.1107 +    mBtnRight = device->isKeyPressed(BTN_RIGHT);
  1.1108 +    mBtnMiddle = device->isKeyPressed(BTN_MIDDLE);
  1.1109 +    mBtnBack = device->isKeyPressed(BTN_BACK);
  1.1110 +    mBtnSide = device->isKeyPressed(BTN_SIDE);
  1.1111 +    mBtnForward = device->isKeyPressed(BTN_FORWARD);
  1.1112 +    mBtnExtra = device->isKeyPressed(BTN_EXTRA);
  1.1113 +    mBtnTask = device->isKeyPressed(BTN_TASK);
  1.1114 +}
  1.1115 +
  1.1116 +void CursorButtonAccumulator::clearButtons() {
  1.1117 +    mBtnLeft = 0;
  1.1118 +    mBtnRight = 0;
  1.1119 +    mBtnMiddle = 0;
  1.1120 +    mBtnBack = 0;
  1.1121 +    mBtnSide = 0;
  1.1122 +    mBtnForward = 0;
  1.1123 +    mBtnExtra = 0;
  1.1124 +    mBtnTask = 0;
  1.1125 +}
  1.1126 +
  1.1127 +void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
  1.1128 +    if (rawEvent->type == EV_KEY) {
  1.1129 +        switch (rawEvent->code) {
  1.1130 +        case BTN_LEFT:
  1.1131 +            mBtnLeft = rawEvent->value;
  1.1132 +            break;
  1.1133 +        case BTN_RIGHT:
  1.1134 +            mBtnRight = rawEvent->value;
  1.1135 +            break;
  1.1136 +        case BTN_MIDDLE:
  1.1137 +            mBtnMiddle = rawEvent->value;
  1.1138 +            break;
  1.1139 +        case BTN_BACK:
  1.1140 +            mBtnBack = rawEvent->value;
  1.1141 +            break;
  1.1142 +        case BTN_SIDE:
  1.1143 +            mBtnSide = rawEvent->value;
  1.1144 +            break;
  1.1145 +        case BTN_FORWARD:
  1.1146 +            mBtnForward = rawEvent->value;
  1.1147 +            break;
  1.1148 +        case BTN_EXTRA:
  1.1149 +            mBtnExtra = rawEvent->value;
  1.1150 +            break;
  1.1151 +        case BTN_TASK:
  1.1152 +            mBtnTask = rawEvent->value;
  1.1153 +            break;
  1.1154 +        }
  1.1155 +    }
  1.1156 +}
  1.1157 +
  1.1158 +uint32_t CursorButtonAccumulator::getButtonState() const {
  1.1159 +    uint32_t result = 0;
  1.1160 +    if (mBtnLeft) {
  1.1161 +        result |= AMOTION_EVENT_BUTTON_PRIMARY;
  1.1162 +    }
  1.1163 +    if (mBtnRight) {
  1.1164 +        result |= AMOTION_EVENT_BUTTON_SECONDARY;
  1.1165 +    }
  1.1166 +    if (mBtnMiddle) {
  1.1167 +        result |= AMOTION_EVENT_BUTTON_TERTIARY;
  1.1168 +    }
  1.1169 +    if (mBtnBack || mBtnSide) {
  1.1170 +        result |= AMOTION_EVENT_BUTTON_BACK;
  1.1171 +    }
  1.1172 +    if (mBtnForward || mBtnExtra) {
  1.1173 +        result |= AMOTION_EVENT_BUTTON_FORWARD;
  1.1174 +    }
  1.1175 +    return result;
  1.1176 +}
  1.1177 +
  1.1178 +
  1.1179 +// --- CursorMotionAccumulator ---
  1.1180 +
  1.1181 +CursorMotionAccumulator::CursorMotionAccumulator() {
  1.1182 +    clearRelativeAxes();
  1.1183 +}
  1.1184 +
  1.1185 +void CursorMotionAccumulator::reset(InputDevice* device) {
  1.1186 +    clearRelativeAxes();
  1.1187 +}
  1.1188 +
  1.1189 +void CursorMotionAccumulator::clearRelativeAxes() {
  1.1190 +    mRelX = 0;
  1.1191 +    mRelY = 0;
  1.1192 +}
  1.1193 +
  1.1194 +void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
  1.1195 +    if (rawEvent->type == EV_REL) {
  1.1196 +        switch (rawEvent->code) {
  1.1197 +        case REL_X:
  1.1198 +            mRelX = rawEvent->value;
  1.1199 +            break;
  1.1200 +        case REL_Y:
  1.1201 +            mRelY = rawEvent->value;
  1.1202 +            break;
  1.1203 +        }
  1.1204 +    }
  1.1205 +}
  1.1206 +
  1.1207 +void CursorMotionAccumulator::finishSync() {
  1.1208 +    clearRelativeAxes();
  1.1209 +}
  1.1210 +
  1.1211 +
  1.1212 +// --- CursorScrollAccumulator ---
  1.1213 +
  1.1214 +CursorScrollAccumulator::CursorScrollAccumulator() :
  1.1215 +        mHaveRelWheel(false), mHaveRelHWheel(false) {
  1.1216 +    clearRelativeAxes();
  1.1217 +}
  1.1218 +
  1.1219 +void CursorScrollAccumulator::configure(InputDevice* device) {
  1.1220 +    mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
  1.1221 +    mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
  1.1222 +}
  1.1223 +
  1.1224 +void CursorScrollAccumulator::reset(InputDevice* device) {
  1.1225 +    clearRelativeAxes();
  1.1226 +}
  1.1227 +
  1.1228 +void CursorScrollAccumulator::clearRelativeAxes() {
  1.1229 +    mRelWheel = 0;
  1.1230 +    mRelHWheel = 0;
  1.1231 +}
  1.1232 +
  1.1233 +void CursorScrollAccumulator::process(const RawEvent* rawEvent) {
  1.1234 +    if (rawEvent->type == EV_REL) {
  1.1235 +        switch (rawEvent->code) {
  1.1236 +        case REL_WHEEL:
  1.1237 +            mRelWheel = rawEvent->value;
  1.1238 +            break;
  1.1239 +        case REL_HWHEEL:
  1.1240 +            mRelHWheel = rawEvent->value;
  1.1241 +            break;
  1.1242 +        }
  1.1243 +    }
  1.1244 +}
  1.1245 +
  1.1246 +void CursorScrollAccumulator::finishSync() {
  1.1247 +    clearRelativeAxes();
  1.1248 +}
  1.1249 +
  1.1250 +
  1.1251 +// --- TouchButtonAccumulator ---
  1.1252 +
  1.1253 +TouchButtonAccumulator::TouchButtonAccumulator() :
  1.1254 +        mHaveBtnTouch(false), mHaveStylus(false) {
  1.1255 +    clearButtons();
  1.1256 +}
  1.1257 +
  1.1258 +void TouchButtonAccumulator::configure(InputDevice* device) {
  1.1259 +    mHaveBtnTouch = device->hasKey(BTN_TOUCH);
  1.1260 +    mHaveStylus = device->hasKey(BTN_TOOL_PEN)
  1.1261 +            || device->hasKey(BTN_TOOL_RUBBER)
  1.1262 +            || device->hasKey(BTN_TOOL_BRUSH)
  1.1263 +            || device->hasKey(BTN_TOOL_PENCIL)
  1.1264 +            || device->hasKey(BTN_TOOL_AIRBRUSH);
  1.1265 +}
  1.1266 +
  1.1267 +void TouchButtonAccumulator::reset(InputDevice* device) {
  1.1268 +    mBtnTouch = device->isKeyPressed(BTN_TOUCH);
  1.1269 +    mBtnStylus = device->isKeyPressed(BTN_STYLUS);
  1.1270 +    mBtnStylus2 = device->isKeyPressed(BTN_STYLUS);
  1.1271 +    mBtnToolFinger = device->isKeyPressed(BTN_TOOL_FINGER);
  1.1272 +    mBtnToolPen = device->isKeyPressed(BTN_TOOL_PEN);
  1.1273 +    mBtnToolRubber = device->isKeyPressed(BTN_TOOL_RUBBER);
  1.1274 +    mBtnToolBrush = device->isKeyPressed(BTN_TOOL_BRUSH);
  1.1275 +    mBtnToolPencil = device->isKeyPressed(BTN_TOOL_PENCIL);
  1.1276 +    mBtnToolAirbrush = device->isKeyPressed(BTN_TOOL_AIRBRUSH);
  1.1277 +    mBtnToolMouse = device->isKeyPressed(BTN_TOOL_MOUSE);
  1.1278 +    mBtnToolLens = device->isKeyPressed(BTN_TOOL_LENS);
  1.1279 +    mBtnToolDoubleTap = device->isKeyPressed(BTN_TOOL_DOUBLETAP);
  1.1280 +    mBtnToolTripleTap = device->isKeyPressed(BTN_TOOL_TRIPLETAP);
  1.1281 +    mBtnToolQuadTap = device->isKeyPressed(BTN_TOOL_QUADTAP);
  1.1282 +}
  1.1283 +
  1.1284 +void TouchButtonAccumulator::clearButtons() {
  1.1285 +    mBtnTouch = 0;
  1.1286 +    mBtnStylus = 0;
  1.1287 +    mBtnStylus2 = 0;
  1.1288 +    mBtnToolFinger = 0;
  1.1289 +    mBtnToolPen = 0;
  1.1290 +    mBtnToolRubber = 0;
  1.1291 +    mBtnToolBrush = 0;
  1.1292 +    mBtnToolPencil = 0;
  1.1293 +    mBtnToolAirbrush = 0;
  1.1294 +    mBtnToolMouse = 0;
  1.1295 +    mBtnToolLens = 0;
  1.1296 +    mBtnToolDoubleTap = 0;
  1.1297 +    mBtnToolTripleTap = 0;
  1.1298 +    mBtnToolQuadTap = 0;
  1.1299 +}
  1.1300 +
  1.1301 +void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
  1.1302 +    if (rawEvent->type == EV_KEY) {
  1.1303 +        switch (rawEvent->code) {
  1.1304 +        case BTN_TOUCH:
  1.1305 +            mBtnTouch = rawEvent->value;
  1.1306 +            break;
  1.1307 +        case BTN_STYLUS:
  1.1308 +            mBtnStylus = rawEvent->value;
  1.1309 +            break;
  1.1310 +        case BTN_STYLUS2:
  1.1311 +            mBtnStylus2 = rawEvent->value;
  1.1312 +            break;
  1.1313 +        case BTN_TOOL_FINGER:
  1.1314 +            mBtnToolFinger = rawEvent->value;
  1.1315 +            break;
  1.1316 +        case BTN_TOOL_PEN:
  1.1317 +            mBtnToolPen = rawEvent->value;
  1.1318 +            break;
  1.1319 +        case BTN_TOOL_RUBBER:
  1.1320 +            mBtnToolRubber = rawEvent->value;
  1.1321 +            break;
  1.1322 +        case BTN_TOOL_BRUSH:
  1.1323 +            mBtnToolBrush = rawEvent->value;
  1.1324 +            break;
  1.1325 +        case BTN_TOOL_PENCIL:
  1.1326 +            mBtnToolPencil = rawEvent->value;
  1.1327 +            break;
  1.1328 +        case BTN_TOOL_AIRBRUSH:
  1.1329 +            mBtnToolAirbrush = rawEvent->value;
  1.1330 +            break;
  1.1331 +        case BTN_TOOL_MOUSE:
  1.1332 +            mBtnToolMouse = rawEvent->value;
  1.1333 +            break;
  1.1334 +        case BTN_TOOL_LENS:
  1.1335 +            mBtnToolLens = rawEvent->value;
  1.1336 +            break;
  1.1337 +        case BTN_TOOL_DOUBLETAP:
  1.1338 +            mBtnToolDoubleTap = rawEvent->value;
  1.1339 +            break;
  1.1340 +        case BTN_TOOL_TRIPLETAP:
  1.1341 +            mBtnToolTripleTap = rawEvent->value;
  1.1342 +            break;
  1.1343 +        case BTN_TOOL_QUADTAP:
  1.1344 +            mBtnToolQuadTap = rawEvent->value;
  1.1345 +            break;
  1.1346 +        }
  1.1347 +    }
  1.1348 +}
  1.1349 +
  1.1350 +uint32_t TouchButtonAccumulator::getButtonState() const {
  1.1351 +    uint32_t result = 0;
  1.1352 +    if (mBtnStylus) {
  1.1353 +        result |= AMOTION_EVENT_BUTTON_SECONDARY;
  1.1354 +    }
  1.1355 +    if (mBtnStylus2) {
  1.1356 +        result |= AMOTION_EVENT_BUTTON_TERTIARY;
  1.1357 +    }
  1.1358 +    return result;
  1.1359 +}
  1.1360 +
  1.1361 +int32_t TouchButtonAccumulator::getToolType() const {
  1.1362 +    if (mBtnToolMouse || mBtnToolLens) {
  1.1363 +        return AMOTION_EVENT_TOOL_TYPE_MOUSE;
  1.1364 +    }
  1.1365 +    if (mBtnToolRubber) {
  1.1366 +        return AMOTION_EVENT_TOOL_TYPE_ERASER;
  1.1367 +    }
  1.1368 +    if (mBtnToolPen || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush) {
  1.1369 +        return AMOTION_EVENT_TOOL_TYPE_STYLUS;
  1.1370 +    }
  1.1371 +    if (mBtnToolFinger || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap) {
  1.1372 +        return AMOTION_EVENT_TOOL_TYPE_FINGER;
  1.1373 +    }
  1.1374 +    return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
  1.1375 +}
  1.1376 +
  1.1377 +bool TouchButtonAccumulator::isToolActive() const {
  1.1378 +    return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber
  1.1379 +            || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush
  1.1380 +            || mBtnToolMouse || mBtnToolLens
  1.1381 +            || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap;
  1.1382 +}
  1.1383 +
  1.1384 +bool TouchButtonAccumulator::isHovering() const {
  1.1385 +    return mHaveBtnTouch && !mBtnTouch;
  1.1386 +}
  1.1387 +
  1.1388 +bool TouchButtonAccumulator::hasStylus() const {
  1.1389 +    return mHaveStylus;
  1.1390 +}
  1.1391 +
  1.1392 +
  1.1393 +// --- RawPointerAxes ---
  1.1394 +
  1.1395 +RawPointerAxes::RawPointerAxes() {
  1.1396 +    clear();
  1.1397 +}
  1.1398 +
  1.1399 +void RawPointerAxes::clear() {
  1.1400 +    x.clear();
  1.1401 +    y.clear();
  1.1402 +    pressure.clear();
  1.1403 +    touchMajor.clear();
  1.1404 +    touchMinor.clear();
  1.1405 +    toolMajor.clear();
  1.1406 +    toolMinor.clear();
  1.1407 +    orientation.clear();
  1.1408 +    distance.clear();
  1.1409 +    tiltX.clear();
  1.1410 +    tiltY.clear();
  1.1411 +    trackingId.clear();
  1.1412 +    slot.clear();
  1.1413 +}
  1.1414 +
  1.1415 +
  1.1416 +// --- RawPointerData ---
  1.1417 +
  1.1418 +RawPointerData::RawPointerData() {
  1.1419 +    clear();
  1.1420 +}
  1.1421 +
  1.1422 +void RawPointerData::clear() {
  1.1423 +    pointerCount = 0;
  1.1424 +    clearIdBits();
  1.1425 +}
  1.1426 +
  1.1427 +void RawPointerData::copyFrom(const RawPointerData& other) {
  1.1428 +    pointerCount = other.pointerCount;
  1.1429 +    hoveringIdBits = other.hoveringIdBits;
  1.1430 +    touchingIdBits = other.touchingIdBits;
  1.1431 +
  1.1432 +    for (uint32_t i = 0; i < pointerCount; i++) {
  1.1433 +        pointers[i] = other.pointers[i];
  1.1434 +
  1.1435 +        int id = pointers[i].id;
  1.1436 +        idToIndex[id] = other.idToIndex[id];
  1.1437 +    }
  1.1438 +}
  1.1439 +
  1.1440 +void RawPointerData::getCentroidOfTouchingPointers(float* outX, float* outY) const {
  1.1441 +    float x = 0, y = 0;
  1.1442 +    uint32_t count = touchingIdBits.count();
  1.1443 +    if (count) {
  1.1444 +        for (BitSet32 idBits(touchingIdBits); !idBits.isEmpty(); ) {
  1.1445 +            uint32_t id = idBits.clearFirstMarkedBit();
  1.1446 +            const Pointer& pointer = pointerForId(id);
  1.1447 +            x += pointer.x;
  1.1448 +            y += pointer.y;
  1.1449 +        }
  1.1450 +        x /= count;
  1.1451 +        y /= count;
  1.1452 +    }
  1.1453 +    *outX = x;
  1.1454 +    *outY = y;
  1.1455 +}
  1.1456 +
  1.1457 +
  1.1458 +// --- CookedPointerData ---
  1.1459 +
  1.1460 +CookedPointerData::CookedPointerData() {
  1.1461 +    clear();
  1.1462 +}
  1.1463 +
  1.1464 +void CookedPointerData::clear() {
  1.1465 +    pointerCount = 0;
  1.1466 +    hoveringIdBits.clear();
  1.1467 +    touchingIdBits.clear();
  1.1468 +}
  1.1469 +
  1.1470 +void CookedPointerData::copyFrom(const CookedPointerData& other) {
  1.1471 +    pointerCount = other.pointerCount;
  1.1472 +    hoveringIdBits = other.hoveringIdBits;
  1.1473 +    touchingIdBits = other.touchingIdBits;
  1.1474 +
  1.1475 +    for (uint32_t i = 0; i < pointerCount; i++) {
  1.1476 +        pointerProperties[i].copyFrom(other.pointerProperties[i]);
  1.1477 +        pointerCoords[i].copyFrom(other.pointerCoords[i]);
  1.1478 +
  1.1479 +        int id = pointerProperties[i].id;
  1.1480 +        idToIndex[id] = other.idToIndex[id];
  1.1481 +    }
  1.1482 +}
  1.1483 +
  1.1484 +
  1.1485 +// --- SingleTouchMotionAccumulator ---
  1.1486 +
  1.1487 +SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() {
  1.1488 +    clearAbsoluteAxes();
  1.1489 +}
  1.1490 +
  1.1491 +void SingleTouchMotionAccumulator::reset(InputDevice* device) {
  1.1492 +    mAbsX = device->getAbsoluteAxisValue(ABS_X);
  1.1493 +    mAbsY = device->getAbsoluteAxisValue(ABS_Y);
  1.1494 +    mAbsPressure = device->getAbsoluteAxisValue(ABS_PRESSURE);
  1.1495 +    mAbsToolWidth = device->getAbsoluteAxisValue(ABS_TOOL_WIDTH);
  1.1496 +    mAbsDistance = device->getAbsoluteAxisValue(ABS_DISTANCE);
  1.1497 +    mAbsTiltX = device->getAbsoluteAxisValue(ABS_TILT_X);
  1.1498 +    mAbsTiltY = device->getAbsoluteAxisValue(ABS_TILT_Y);
  1.1499 +}
  1.1500 +
  1.1501 +void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
  1.1502 +    mAbsX = 0;
  1.1503 +    mAbsY = 0;
  1.1504 +    mAbsPressure = 0;
  1.1505 +    mAbsToolWidth = 0;
  1.1506 +    mAbsDistance = 0;
  1.1507 +    mAbsTiltX = 0;
  1.1508 +    mAbsTiltY = 0;
  1.1509 +}
  1.1510 +
  1.1511 +void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
  1.1512 +    if (rawEvent->type == EV_ABS) {
  1.1513 +        switch (rawEvent->code) {
  1.1514 +        case ABS_X:
  1.1515 +            mAbsX = rawEvent->value;
  1.1516 +            break;
  1.1517 +        case ABS_Y:
  1.1518 +            mAbsY = rawEvent->value;
  1.1519 +            break;
  1.1520 +        case ABS_PRESSURE:
  1.1521 +            mAbsPressure = rawEvent->value;
  1.1522 +            break;
  1.1523 +        case ABS_TOOL_WIDTH:
  1.1524 +            mAbsToolWidth = rawEvent->value;
  1.1525 +            break;
  1.1526 +        case ABS_DISTANCE:
  1.1527 +            mAbsDistance = rawEvent->value;
  1.1528 +            break;
  1.1529 +        case ABS_TILT_X:
  1.1530 +            mAbsTiltX = rawEvent->value;
  1.1531 +            break;
  1.1532 +        case ABS_TILT_Y:
  1.1533 +            mAbsTiltY = rawEvent->value;
  1.1534 +            break;
  1.1535 +        }
  1.1536 +    }
  1.1537 +}
  1.1538 +
  1.1539 +
  1.1540 +// --- MultiTouchMotionAccumulator ---
  1.1541 +
  1.1542 +MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() :
  1.1543 +        mCurrentSlot(-1), mSlots(NULL), mSlotCount(0), mUsingSlotsProtocol(false),
  1.1544 +        mHaveStylus(false) {
  1.1545 +}
  1.1546 +
  1.1547 +MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
  1.1548 +    delete[] mSlots;
  1.1549 +}
  1.1550 +
  1.1551 +void MultiTouchMotionAccumulator::configure(InputDevice* device,
  1.1552 +        size_t slotCount, bool usingSlotsProtocol) {
  1.1553 +    mSlotCount = slotCount;
  1.1554 +    mUsingSlotsProtocol = usingSlotsProtocol;
  1.1555 +    mHaveStylus = device->hasAbsoluteAxis(ABS_MT_TOOL_TYPE);
  1.1556 +
  1.1557 +    delete[] mSlots;
  1.1558 +    mSlots = new Slot[slotCount];
  1.1559 +}
  1.1560 +
  1.1561 +void MultiTouchMotionAccumulator::reset(InputDevice* device) {
  1.1562 +    // Unfortunately there is no way to read the initial contents of the slots.
  1.1563 +    // So when we reset the accumulator, we must assume they are all zeroes.
  1.1564 +    if (mUsingSlotsProtocol) {
  1.1565 +        // Query the driver for the current slot index and use it as the initial slot
  1.1566 +        // before we start reading events from the device.  It is possible that the
  1.1567 +        // current slot index will not be the same as it was when the first event was
  1.1568 +        // written into the evdev buffer, which means the input mapper could start
  1.1569 +        // out of sync with the initial state of the events in the evdev buffer.
  1.1570 +        // In the extremely unlikely case that this happens, the data from
  1.1571 +        // two slots will be confused until the next ABS_MT_SLOT event is received.
  1.1572 +        // This can cause the touch point to "jump", but at least there will be
  1.1573 +        // no stuck touches.
  1.1574 +        int32_t initialSlot;
  1.1575 +        status_t status = device->getEventHub()->getAbsoluteAxisValue(device->getId(),
  1.1576 +                ABS_MT_SLOT, &initialSlot);
  1.1577 +        if (status) {
  1.1578 +            ALOGD("Could not retrieve current multitouch slot index.  status=%d", status);
  1.1579 +            initialSlot = -1;
  1.1580 +        }
  1.1581 +        clearSlots(initialSlot);
  1.1582 +    } else {
  1.1583 +        clearSlots(-1);
  1.1584 +    }
  1.1585 +}
  1.1586 +
  1.1587 +void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
  1.1588 +    if (mSlots) {
  1.1589 +        for (size_t i = 0; i < mSlotCount; i++) {
  1.1590 +            mSlots[i].clear();
  1.1591 +        }
  1.1592 +    }
  1.1593 +    mCurrentSlot = initialSlot;
  1.1594 +}
  1.1595 +
  1.1596 +void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
  1.1597 +    if (rawEvent->type == EV_ABS) {
  1.1598 +        bool newSlot = false;
  1.1599 +        if (mUsingSlotsProtocol) {
  1.1600 +            if (rawEvent->code == ABS_MT_SLOT) {
  1.1601 +                mCurrentSlot = rawEvent->value;
  1.1602 +                newSlot = true;
  1.1603 +            }
  1.1604 +        } else if (mCurrentSlot < 0) {
  1.1605 +            mCurrentSlot = 0;
  1.1606 +        }
  1.1607 +
  1.1608 +        if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
  1.1609 +#if DEBUG_POINTERS
  1.1610 +            if (newSlot) {
  1.1611 +                ALOGW("MultiTouch device emitted invalid slot index %d but it "
  1.1612 +                        "should be between 0 and %d; ignoring this slot.",
  1.1613 +                        mCurrentSlot, mSlotCount - 1);
  1.1614 +            }
  1.1615 +#endif
  1.1616 +        } else {
  1.1617 +            Slot* slot = &mSlots[mCurrentSlot];
  1.1618 +
  1.1619 +            switch (rawEvent->code) {
  1.1620 +            case ABS_MT_POSITION_X:
  1.1621 +                slot->mInUse = true;
  1.1622 +                slot->mAbsMTPositionX = rawEvent->value;
  1.1623 +                break;
  1.1624 +            case ABS_MT_POSITION_Y:
  1.1625 +                slot->mInUse = true;
  1.1626 +                slot->mAbsMTPositionY = rawEvent->value;
  1.1627 +                break;
  1.1628 +            case ABS_MT_TOUCH_MAJOR:
  1.1629 +                slot->mInUse = true;
  1.1630 +                slot->mAbsMTTouchMajor = rawEvent->value;
  1.1631 +                break;
  1.1632 +            case ABS_MT_TOUCH_MINOR:
  1.1633 +                slot->mInUse = true;
  1.1634 +                slot->mAbsMTTouchMinor = rawEvent->value;
  1.1635 +                slot->mHaveAbsMTTouchMinor = true;
  1.1636 +                break;
  1.1637 +            case ABS_MT_WIDTH_MAJOR:
  1.1638 +                slot->mInUse = true;
  1.1639 +                slot->mAbsMTWidthMajor = rawEvent->value;
  1.1640 +                break;
  1.1641 +            case ABS_MT_WIDTH_MINOR:
  1.1642 +                slot->mInUse = true;
  1.1643 +                slot->mAbsMTWidthMinor = rawEvent->value;
  1.1644 +                slot->mHaveAbsMTWidthMinor = true;
  1.1645 +                break;
  1.1646 +            case ABS_MT_ORIENTATION:
  1.1647 +                slot->mInUse = true;
  1.1648 +                slot->mAbsMTOrientation = rawEvent->value;
  1.1649 +                break;
  1.1650 +            case ABS_MT_TRACKING_ID:
  1.1651 +                if (mUsingSlotsProtocol && rawEvent->value < 0) {
  1.1652 +                    // The slot is no longer in use but it retains its previous contents,
  1.1653 +                    // which may be reused for subsequent touches.
  1.1654 +                    slot->mInUse = false;
  1.1655 +                } else {
  1.1656 +                    slot->mInUse = true;
  1.1657 +                    slot->mAbsMTTrackingId = rawEvent->value;
  1.1658 +                }
  1.1659 +                break;
  1.1660 +            case ABS_MT_PRESSURE:
  1.1661 +                slot->mInUse = true;
  1.1662 +                slot->mAbsMTPressure = rawEvent->value;
  1.1663 +                break;
  1.1664 +            case ABS_MT_DISTANCE:
  1.1665 +                slot->mInUse = true;
  1.1666 +                slot->mAbsMTDistance = rawEvent->value;
  1.1667 +                break;
  1.1668 +            case ABS_MT_TOOL_TYPE:
  1.1669 +                slot->mInUse = true;
  1.1670 +                slot->mAbsMTToolType = rawEvent->value;
  1.1671 +                slot->mHaveAbsMTToolType = true;
  1.1672 +                break;
  1.1673 +            }
  1.1674 +        }
  1.1675 +    } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {
  1.1676 +        // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
  1.1677 +        mCurrentSlot += 1;
  1.1678 +    }
  1.1679 +}
  1.1680 +
  1.1681 +void MultiTouchMotionAccumulator::finishSync() {
  1.1682 +    if (!mUsingSlotsProtocol) {
  1.1683 +        clearSlots(-1);
  1.1684 +    }
  1.1685 +}
  1.1686 +
  1.1687 +bool MultiTouchMotionAccumulator::hasStylus() const {
  1.1688 +    return mHaveStylus;
  1.1689 +}
  1.1690 +
  1.1691 +
  1.1692 +// --- MultiTouchMotionAccumulator::Slot ---
  1.1693 +
  1.1694 +MultiTouchMotionAccumulator::Slot::Slot() {
  1.1695 +    clear();
  1.1696 +}
  1.1697 +
  1.1698 +void MultiTouchMotionAccumulator::Slot::clear() {
  1.1699 +    mInUse = false;
  1.1700 +    mHaveAbsMTTouchMinor = false;
  1.1701 +    mHaveAbsMTWidthMinor = false;
  1.1702 +    mHaveAbsMTToolType = false;
  1.1703 +    mAbsMTPositionX = 0;
  1.1704 +    mAbsMTPositionY = 0;
  1.1705 +    mAbsMTTouchMajor = 0;
  1.1706 +    mAbsMTTouchMinor = 0;
  1.1707 +    mAbsMTWidthMajor = 0;
  1.1708 +    mAbsMTWidthMinor = 0;
  1.1709 +    mAbsMTOrientation = 0;
  1.1710 +    mAbsMTTrackingId = -1;
  1.1711 +    mAbsMTPressure = 0;
  1.1712 +    mAbsMTDistance = 0;
  1.1713 +    mAbsMTToolType = 0;
  1.1714 +}
  1.1715 +
  1.1716 +int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
  1.1717 +    if (mHaveAbsMTToolType) {
  1.1718 +        switch (mAbsMTToolType) {
  1.1719 +        case MT_TOOL_FINGER:
  1.1720 +            return AMOTION_EVENT_TOOL_TYPE_FINGER;
  1.1721 +        case MT_TOOL_PEN:
  1.1722 +            return AMOTION_EVENT_TOOL_TYPE_STYLUS;
  1.1723 +        }
  1.1724 +    }
  1.1725 +    return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
  1.1726 +}
  1.1727 +
  1.1728 +
  1.1729 +// --- InputMapper ---
  1.1730 +
  1.1731 +InputMapper::InputMapper(InputDevice* device) :
  1.1732 +        mDevice(device), mContext(device->getContext()) {
  1.1733 +}
  1.1734 +
  1.1735 +InputMapper::~InputMapper() {
  1.1736 +}
  1.1737 +
  1.1738 +void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
  1.1739 +    info->addSource(getSources());
  1.1740 +}
  1.1741 +
  1.1742 +void InputMapper::dump(String8& dump) {
  1.1743 +}
  1.1744 +
  1.1745 +void InputMapper::configure(nsecs_t when,
  1.1746 +        const InputReaderConfiguration* config, uint32_t changes) {
  1.1747 +}
  1.1748 +
  1.1749 +void InputMapper::reset(nsecs_t when) {
  1.1750 +}
  1.1751 +
  1.1752 +void InputMapper::timeoutExpired(nsecs_t when) {
  1.1753 +}
  1.1754 +
  1.1755 +int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
  1.1756 +    return AKEY_STATE_UNKNOWN;
  1.1757 +}
  1.1758 +
  1.1759 +int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
  1.1760 +    return AKEY_STATE_UNKNOWN;
  1.1761 +}
  1.1762 +
  1.1763 +int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
  1.1764 +    return AKEY_STATE_UNKNOWN;
  1.1765 +}
  1.1766 +
  1.1767 +bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
  1.1768 +        const int32_t* keyCodes, uint8_t* outFlags) {
  1.1769 +    return false;
  1.1770 +}
  1.1771 +
  1.1772 +void InputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
  1.1773 +        int32_t token) {
  1.1774 +}
  1.1775 +
  1.1776 +void InputMapper::cancelVibrate(int32_t token) {
  1.1777 +}
  1.1778 +
  1.1779 +int32_t InputMapper::getMetaState() {
  1.1780 +    return 0;
  1.1781 +}
  1.1782 +
  1.1783 +void InputMapper::fadePointer() {
  1.1784 +}
  1.1785 +
  1.1786 +status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) {
  1.1787 +    return getEventHub()->getAbsoluteAxisInfo(getDeviceId(), axis, axisInfo);
  1.1788 +}
  1.1789 +
  1.1790 +void InputMapper::bumpGeneration() {
  1.1791 +    mDevice->bumpGeneration();
  1.1792 +}
  1.1793 +
  1.1794 +void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
  1.1795 +        const RawAbsoluteAxisInfo& axis, const char* name) {
  1.1796 +    if (axis.valid) {
  1.1797 +        dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d, resolution=%d\n",
  1.1798 +                name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz, axis.resolution);
  1.1799 +    } else {
  1.1800 +        dump.appendFormat(INDENT4 "%s: unknown range\n", name);
  1.1801 +    }
  1.1802 +}
  1.1803 +
  1.1804 +
  1.1805 +// --- SwitchInputMapper ---
  1.1806 +
  1.1807 +SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
  1.1808 +        InputMapper(device), mUpdatedSwitchValues(0), mUpdatedSwitchMask(0) {
  1.1809 +}
  1.1810 +
  1.1811 +SwitchInputMapper::~SwitchInputMapper() {
  1.1812 +}
  1.1813 +
  1.1814 +uint32_t SwitchInputMapper::getSources() {
  1.1815 +    return AINPUT_SOURCE_SWITCH;
  1.1816 +}
  1.1817 +
  1.1818 +void SwitchInputMapper::process(const RawEvent* rawEvent) {
  1.1819 +    switch (rawEvent->type) {
  1.1820 +    case EV_SW:
  1.1821 +        processSwitch(rawEvent->code, rawEvent->value);
  1.1822 +        break;
  1.1823 +
  1.1824 +    case EV_SYN:
  1.1825 +        if (rawEvent->code == SYN_REPORT) {
  1.1826 +            sync(rawEvent->when);
  1.1827 +        }
  1.1828 +    }
  1.1829 +}
  1.1830 +
  1.1831 +void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
  1.1832 +    if (switchCode >= 0 && switchCode < 32) {
  1.1833 +        if (switchValue) {
  1.1834 +            mUpdatedSwitchValues |= 1 << switchCode;
  1.1835 +        }
  1.1836 +        mUpdatedSwitchMask |= 1 << switchCode;
  1.1837 +    }
  1.1838 +}
  1.1839 +
  1.1840 +void SwitchInputMapper::sync(nsecs_t when) {
  1.1841 +    if (mUpdatedSwitchMask) {
  1.1842 +        NotifySwitchArgs args(when, 0, mUpdatedSwitchValues, mUpdatedSwitchMask);
  1.1843 +        getListener()->notifySwitch(&args);
  1.1844 +
  1.1845 +        mUpdatedSwitchValues = 0;
  1.1846 +        mUpdatedSwitchMask = 0;
  1.1847 +    }
  1.1848 +}
  1.1849 +
  1.1850 +int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
  1.1851 +    return getEventHub()->getSwitchState(getDeviceId(), switchCode);
  1.1852 +}
  1.1853 +
  1.1854 +
  1.1855 +// --- VibratorInputMapper ---
  1.1856 +
  1.1857 +VibratorInputMapper::VibratorInputMapper(InputDevice* device) :
  1.1858 +        InputMapper(device), mVibrating(false) {
  1.1859 +}
  1.1860 +
  1.1861 +VibratorInputMapper::~VibratorInputMapper() {
  1.1862 +}
  1.1863 +
  1.1864 +uint32_t VibratorInputMapper::getSources() {
  1.1865 +    return 0;
  1.1866 +}
  1.1867 +
  1.1868 +void VibratorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
  1.1869 +    InputMapper::populateDeviceInfo(info);
  1.1870 +
  1.1871 +    info->setVibrator(true);
  1.1872 +}
  1.1873 +
  1.1874 +void VibratorInputMapper::process(const RawEvent* rawEvent) {
  1.1875 +    // TODO: Handle FF_STATUS, although it does not seem to be widely supported.
  1.1876 +}
  1.1877 +
  1.1878 +void VibratorInputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
  1.1879 +        int32_t token) {
  1.1880 +#if DEBUG_VIBRATOR
  1.1881 +    String8 patternStr;
  1.1882 +    for (size_t i = 0; i < patternSize; i++) {
  1.1883 +        if (i != 0) {
  1.1884 +            patternStr.append(", ");
  1.1885 +        }
  1.1886 +        patternStr.appendFormat("%lld", pattern[i]);
  1.1887 +    }
  1.1888 +    ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%ld, token=%d",
  1.1889 +            getDeviceId(), patternStr.string(), repeat, token);
  1.1890 +#endif
  1.1891 +
  1.1892 +    mVibrating = true;
  1.1893 +    memcpy(mPattern, pattern, patternSize * sizeof(nsecs_t));
  1.1894 +    mPatternSize = patternSize;
  1.1895 +    mRepeat = repeat;
  1.1896 +    mToken = token;
  1.1897 +    mIndex = -1;
  1.1898 +
  1.1899 +    nextStep();
  1.1900 +}
  1.1901 +
  1.1902 +void VibratorInputMapper::cancelVibrate(int32_t token) {
  1.1903 +#if DEBUG_VIBRATOR
  1.1904 +    ALOGD("cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token);
  1.1905 +#endif
  1.1906 +
  1.1907 +    if (mVibrating && mToken == token) {
  1.1908 +        stopVibrating();
  1.1909 +    }
  1.1910 +}
  1.1911 +
  1.1912 +void VibratorInputMapper::timeoutExpired(nsecs_t when) {
  1.1913 +    if (mVibrating) {
  1.1914 +        if (when >= mNextStepTime) {
  1.1915 +            nextStep();
  1.1916 +        } else {
  1.1917 +            getContext()->requestTimeoutAtTime(mNextStepTime);
  1.1918 +        }
  1.1919 +    }
  1.1920 +}
  1.1921 +
  1.1922 +void VibratorInputMapper::nextStep() {
  1.1923 +    mIndex += 1;
  1.1924 +    if (size_t(mIndex) >= mPatternSize) {
  1.1925 +        if (mRepeat < 0) {
  1.1926 +            // We are done.
  1.1927 +            stopVibrating();
  1.1928 +            return;
  1.1929 +        }
  1.1930 +        mIndex = mRepeat;
  1.1931 +    }
  1.1932 +
  1.1933 +    bool vibratorOn = mIndex & 1;
  1.1934 +    nsecs_t duration = mPattern[mIndex];
  1.1935 +    if (vibratorOn) {
  1.1936 +#if DEBUG_VIBRATOR
  1.1937 +        ALOGD("nextStep: sending vibrate deviceId=%d, duration=%lld",
  1.1938 +                getDeviceId(), duration);
  1.1939 +#endif
  1.1940 +        getEventHub()->vibrate(getDeviceId(), duration);
  1.1941 +    } else {
  1.1942 +#if DEBUG_VIBRATOR
  1.1943 +        ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId());
  1.1944 +#endif
  1.1945 +        getEventHub()->cancelVibrate(getDeviceId());
  1.1946 +    }
  1.1947 +    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
  1.1948 +    mNextStepTime = now + duration;
  1.1949 +    getContext()->requestTimeoutAtTime(mNextStepTime);
  1.1950 +#if DEBUG_VIBRATOR
  1.1951 +    ALOGD("nextStep: scheduled timeout in %0.3fms", duration * 0.000001f);
  1.1952 +#endif
  1.1953 +}
  1.1954 +
  1.1955 +void VibratorInputMapper::stopVibrating() {
  1.1956 +    mVibrating = false;
  1.1957 +#if DEBUG_VIBRATOR
  1.1958 +    ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId());
  1.1959 +#endif
  1.1960 +    getEventHub()->cancelVibrate(getDeviceId());
  1.1961 +}
  1.1962 +
  1.1963 +void VibratorInputMapper::dump(String8& dump) {
  1.1964 +    dump.append(INDENT2 "Vibrator Input Mapper:\n");
  1.1965 +    dump.appendFormat(INDENT3 "Vibrating: %s\n", toString(mVibrating));
  1.1966 +}
  1.1967 +
  1.1968 +
  1.1969 +// --- KeyboardInputMapper ---
  1.1970 +
  1.1971 +KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
  1.1972 +        uint32_t source, int32_t keyboardType) :
  1.1973 +        InputMapper(device), mSource(source),
  1.1974 +        mKeyboardType(keyboardType) {
  1.1975 +}
  1.1976 +
  1.1977 +KeyboardInputMapper::~KeyboardInputMapper() {
  1.1978 +}
  1.1979 +
  1.1980 +uint32_t KeyboardInputMapper::getSources() {
  1.1981 +    return mSource;
  1.1982 +}
  1.1983 +
  1.1984 +void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
  1.1985 +    InputMapper::populateDeviceInfo(info);
  1.1986 +
  1.1987 +    info->setKeyboardType(mKeyboardType);
  1.1988 +    info->setKeyCharacterMap(getEventHub()->getKeyCharacterMap(getDeviceId()));
  1.1989 +}
  1.1990 +
  1.1991 +void KeyboardInputMapper::dump(String8& dump) {
  1.1992 +    dump.append(INDENT2 "Keyboard Input Mapper:\n");
  1.1993 +    dumpParameters(dump);
  1.1994 +    dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
  1.1995 +    dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
  1.1996 +    dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mKeyDowns.size());
  1.1997 +    dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mMetaState);
  1.1998 +    dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime);
  1.1999 +}
  1.2000 +
  1.2001 +
  1.2002 +void KeyboardInputMapper::configure(nsecs_t when,
  1.2003 +        const InputReaderConfiguration* config, uint32_t changes) {
  1.2004 +    InputMapper::configure(when, config, changes);
  1.2005 +
  1.2006 +    if (!changes) { // first time only
  1.2007 +        // Configure basic parameters.
  1.2008 +        configureParameters();
  1.2009 +    }
  1.2010 +
  1.2011 +    if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
  1.2012 +        if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
  1.2013 +            DisplayViewport v;
  1.2014 +            if (config->getDisplayInfo(false /*external*/, &v)) {
  1.2015 +                mOrientation = v.orientation;
  1.2016 +            } else {
  1.2017 +                mOrientation = DISPLAY_ORIENTATION_0;
  1.2018 +            }
  1.2019 +        } else {
  1.2020 +            mOrientation = DISPLAY_ORIENTATION_0;
  1.2021 +        }
  1.2022 +    }
  1.2023 +}
  1.2024 +
  1.2025 +void KeyboardInputMapper::configureParameters() {
  1.2026 +    mParameters.orientationAware = false;
  1.2027 +    getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
  1.2028 +            mParameters.orientationAware);
  1.2029 +
  1.2030 +    mParameters.hasAssociatedDisplay = false;
  1.2031 +    if (mParameters.orientationAware) {
  1.2032 +        mParameters.hasAssociatedDisplay = true;
  1.2033 +    }
  1.2034 +}
  1.2035 +
  1.2036 +void KeyboardInputMapper::dumpParameters(String8& dump) {
  1.2037 +    dump.append(INDENT3 "Parameters:\n");
  1.2038 +    dump.appendFormat(INDENT4 "HasAssociatedDisplay: %s\n",
  1.2039 +            toString(mParameters.hasAssociatedDisplay));
  1.2040 +    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
  1.2041 +            toString(mParameters.orientationAware));
  1.2042 +}
  1.2043 +
  1.2044 +void KeyboardInputMapper::reset(nsecs_t when) {
  1.2045 +    mMetaState = AMETA_NONE;
  1.2046 +    mDownTime = 0;
  1.2047 +    mKeyDowns.clear();
  1.2048 +    mCurrentHidUsage = 0;
  1.2049 +
  1.2050 +    resetLedState();
  1.2051 +
  1.2052 +    InputMapper::reset(when);
  1.2053 +}
  1.2054 +
  1.2055 +void KeyboardInputMapper::process(const RawEvent* rawEvent) {
  1.2056 +    switch (rawEvent->type) {
  1.2057 +    case EV_KEY: {
  1.2058 +        int32_t scanCode = rawEvent->code;
  1.2059 +        int32_t usageCode = mCurrentHidUsage;
  1.2060 +        mCurrentHidUsage = 0;
  1.2061 +
  1.2062 +        if (isKeyboardOrGamepadKey(scanCode)) {
  1.2063 +            int32_t keyCode;
  1.2064 +            uint32_t flags;
  1.2065 +            if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) {
  1.2066 +                keyCode = AKEYCODE_UNKNOWN;
  1.2067 +                flags = 0;
  1.2068 +            }
  1.2069 +            processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
  1.2070 +        }
  1.2071 +        break;
  1.2072 +    }
  1.2073 +    case EV_MSC: {
  1.2074 +        if (rawEvent->code == MSC_SCAN) {
  1.2075 +            mCurrentHidUsage = rawEvent->value;
  1.2076 +        }
  1.2077 +        break;
  1.2078 +    }
  1.2079 +    case EV_SYN: {
  1.2080 +        if (rawEvent->code == SYN_REPORT) {
  1.2081 +            mCurrentHidUsage = 0;
  1.2082 +        }
  1.2083 +    }
  1.2084 +    }
  1.2085 +}
  1.2086 +
  1.2087 +bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
  1.2088 +    return scanCode < BTN_MOUSE
  1.2089 +        || scanCode >= KEY_OK
  1.2090 +        || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE)
  1.2091 +        || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
  1.2092 +}
  1.2093 +
  1.2094 +void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
  1.2095 +        int32_t scanCode, uint32_t policyFlags) {
  1.2096 +
  1.2097 +    if (down) {
  1.2098 +        // Rotate key codes according to orientation if needed.
  1.2099 +        if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
  1.2100 +            keyCode = rotateKeyCode(keyCode, mOrientation);
  1.2101 +        }
  1.2102 +
  1.2103 +        // Add key down.
  1.2104 +        ssize_t keyDownIndex = findKeyDown(scanCode);
  1.2105 +        if (keyDownIndex >= 0) {
  1.2106 +            // key repeat, be sure to use same keycode as before in case of rotation
  1.2107 +            keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
  1.2108 +        } else {
  1.2109 +            // key down
  1.2110 +            if ((policyFlags & POLICY_FLAG_VIRTUAL)
  1.2111 +                    && mContext->shouldDropVirtualKey(when,
  1.2112 +                            getDevice(), keyCode, scanCode)) {
  1.2113 +                return;
  1.2114 +            }
  1.2115 +
  1.2116 +            mKeyDowns.push();
  1.2117 +            KeyDown& keyDown = mKeyDowns.editTop();
  1.2118 +            keyDown.keyCode = keyCode;
  1.2119 +            keyDown.scanCode = scanCode;
  1.2120 +        }
  1.2121 +
  1.2122 +        mDownTime = when;
  1.2123 +    } else {
  1.2124 +        // Remove key down.
  1.2125 +        ssize_t keyDownIndex = findKeyDown(scanCode);
  1.2126 +        if (keyDownIndex >= 0) {
  1.2127 +            // key up, be sure to use same keycode as before in case of rotation
  1.2128 +            keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
  1.2129 +            mKeyDowns.removeAt(size_t(keyDownIndex));
  1.2130 +        } else {
  1.2131 +            // key was not actually down
  1.2132 +            ALOGI("Dropping key up from device %s because the key was not down.  "
  1.2133 +                    "keyCode=%d, scanCode=%d",
  1.2134 +                    getDeviceName().string(), keyCode, scanCode);
  1.2135 +            return;
  1.2136 +        }
  1.2137 +    }
  1.2138 +
  1.2139 +    bool metaStateChanged = false;
  1.2140 +    int32_t oldMetaState = mMetaState;
  1.2141 +    int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
  1.2142 +    if (oldMetaState != newMetaState) {
  1.2143 +        mMetaState = newMetaState;
  1.2144 +        metaStateChanged = true;
  1.2145 +        updateLedState(false);
  1.2146 +    }
  1.2147 +
  1.2148 +    nsecs_t downTime = mDownTime;
  1.2149 +
  1.2150 +    // Key down on external an keyboard should wake the device.
  1.2151 +    // We don't do this for internal keyboards to prevent them from waking up in your pocket.
  1.2152 +    // For internal keyboards, the key layout file should specify the policy flags for
  1.2153 +    // each wake key individually.
  1.2154 +    // TODO: Use the input device configuration to control this behavior more finely.
  1.2155 +    if (down && getDevice()->isExternal()
  1.2156 +            && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {
  1.2157 +        policyFlags |= POLICY_FLAG_WAKE_DROPPED;
  1.2158 +    }
  1.2159 +
  1.2160 +    if (metaStateChanged) {
  1.2161 +        getContext()->updateGlobalMetaState();
  1.2162 +    }
  1.2163 +
  1.2164 +    if (down && !isMetaKey(keyCode)) {
  1.2165 +        getContext()->fadePointer();
  1.2166 +    }
  1.2167 +
  1.2168 +    NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
  1.2169 +            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
  1.2170 +            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
  1.2171 +    getListener()->notifyKey(&args);
  1.2172 +}
  1.2173 +
  1.2174 +ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) {
  1.2175 +    size_t n = mKeyDowns.size();
  1.2176 +    for (size_t i = 0; i < n; i++) {
  1.2177 +        if (mKeyDowns[i].scanCode == scanCode) {
  1.2178 +            return i;
  1.2179 +        }
  1.2180 +    }
  1.2181 +    return -1;
  1.2182 +}
  1.2183 +
  1.2184 +int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
  1.2185 +    return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
  1.2186 +}
  1.2187 +
  1.2188 +int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
  1.2189 +    return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
  1.2190 +}
  1.2191 +
  1.2192 +bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
  1.2193 +        const int32_t* keyCodes, uint8_t* outFlags) {
  1.2194 +    return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
  1.2195 +}
  1.2196 +
  1.2197 +int32_t KeyboardInputMapper::getMetaState() {
  1.2198 +    return mMetaState;
  1.2199 +}
  1.2200 +
  1.2201 +void KeyboardInputMapper::resetLedState() {
  1.2202 +    initializeLedState(mCapsLockLedState, LED_CAPSL);
  1.2203 +    initializeLedState(mNumLockLedState, LED_NUML);
  1.2204 +    initializeLedState(mScrollLockLedState, LED_SCROLLL);
  1.2205 +
  1.2206 +    updateLedState(true);
  1.2207 +}
  1.2208 +
  1.2209 +void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
  1.2210 +    ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
  1.2211 +    ledState.on = false;
  1.2212 +}
  1.2213 +
  1.2214 +void KeyboardInputMapper::updateLedState(bool reset) {
  1.2215 +    updateLedStateForModifier(mCapsLockLedState, LED_CAPSL,
  1.2216 +            AMETA_CAPS_LOCK_ON, reset);
  1.2217 +    updateLedStateForModifier(mNumLockLedState, LED_NUML,
  1.2218 +            AMETA_NUM_LOCK_ON, reset);
  1.2219 +    updateLedStateForModifier(mScrollLockLedState, LED_SCROLLL,
  1.2220 +            AMETA_SCROLL_LOCK_ON, reset);
  1.2221 +}
  1.2222 +
  1.2223 +void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState,
  1.2224 +        int32_t led, int32_t modifier, bool reset) {
  1.2225 +    if (ledState.avail) {
  1.2226 +        bool desiredState = (mMetaState & modifier) != 0;
  1.2227 +        if (reset || ledState.on != desiredState) {
  1.2228 +            getEventHub()->setLedState(getDeviceId(), led, desiredState);
  1.2229 +            ledState.on = desiredState;
  1.2230 +        }
  1.2231 +    }
  1.2232 +}
  1.2233 +
  1.2234 +
  1.2235 +// --- CursorInputMapper ---
  1.2236 +
  1.2237 +CursorInputMapper::CursorInputMapper(InputDevice* device) :
  1.2238 +        InputMapper(device) {
  1.2239 +}
  1.2240 +
  1.2241 +CursorInputMapper::~CursorInputMapper() {
  1.2242 +}
  1.2243 +
  1.2244 +uint32_t CursorInputMapper::getSources() {
  1.2245 +    return mSource;
  1.2246 +}
  1.2247 +
  1.2248 +void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
  1.2249 +    InputMapper::populateDeviceInfo(info);
  1.2250 +
  1.2251 +    if (mParameters.mode == Parameters::MODE_POINTER) {
  1.2252 +        float minX, minY, maxX, maxY;
  1.2253 +        if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
  1.2254 +            info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f, 0.0f);
  1.2255 +            info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f, 0.0f);
  1.2256 +        }
  1.2257 +    } else {
  1.2258 +        info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f);
  1.2259 +        info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f);
  1.2260 +    }
  1.2261 +    info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
  1.2262 +
  1.2263 +    if (mCursorScrollAccumulator.haveRelativeVWheel()) {
  1.2264 +        info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
  1.2265 +    }
  1.2266 +    if (mCursorScrollAccumulator.haveRelativeHWheel()) {
  1.2267 +        info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
  1.2268 +    }
  1.2269 +}
  1.2270 +
  1.2271 +void CursorInputMapper::dump(String8& dump) {
  1.2272 +    dump.append(INDENT2 "Cursor Input Mapper:\n");
  1.2273 +    dumpParameters(dump);
  1.2274 +    dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
  1.2275 +    dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
  1.2276 +    dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
  1.2277 +    dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
  1.2278 +    dump.appendFormat(INDENT3 "HaveVWheel: %s\n",
  1.2279 +            toString(mCursorScrollAccumulator.haveRelativeVWheel()));
  1.2280 +    dump.appendFormat(INDENT3 "HaveHWheel: %s\n",
  1.2281 +            toString(mCursorScrollAccumulator.haveRelativeHWheel()));
  1.2282 +    dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
  1.2283 +    dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
  1.2284 +    dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
  1.2285 +    dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
  1.2286 +    dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
  1.2287 +    dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime);
  1.2288 +}
  1.2289 +
  1.2290 +void CursorInputMapper::configure(nsecs_t when,
  1.2291 +        const InputReaderConfiguration* config, uint32_t changes) {
  1.2292 +    InputMapper::configure(when, config, changes);
  1.2293 +
  1.2294 +    if (!changes) { // first time only
  1.2295 +        mCursorScrollAccumulator.configure(getDevice());
  1.2296 +
  1.2297 +        // Configure basic parameters.
  1.2298 +        configureParameters();
  1.2299 +
  1.2300 +        // Configure device mode.
  1.2301 +        switch (mParameters.mode) {
  1.2302 +        case Parameters::MODE_POINTER:
  1.2303 +            mSource = AINPUT_SOURCE_MOUSE;
  1.2304 +            mXPrecision = 1.0f;
  1.2305 +            mYPrecision = 1.0f;
  1.2306 +            mXScale = 1.0f;
  1.2307 +            mYScale = 1.0f;
  1.2308 +            mPointerController = getPolicy()->obtainPointerController(getDeviceId());
  1.2309 +            break;
  1.2310 +        case Parameters::MODE_NAVIGATION:
  1.2311 +            mSource = AINPUT_SOURCE_TRACKBALL;
  1.2312 +            mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
  1.2313 +            mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
  1.2314 +            mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
  1.2315 +            mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
  1.2316 +            break;
  1.2317 +        }
  1.2318 +
  1.2319 +        mVWheelScale = 1.0f;
  1.2320 +        mHWheelScale = 1.0f;
  1.2321 +    }
  1.2322 +
  1.2323 +    if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
  1.2324 +        mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
  1.2325 +        mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
  1.2326 +        mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
  1.2327 +    }
  1.2328 +
  1.2329 +    if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
  1.2330 +        if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
  1.2331 +            DisplayViewport v;
  1.2332 +            if (config->getDisplayInfo(false /*external*/, &v)) {
  1.2333 +                mOrientation = v.orientation;
  1.2334 +            } else {
  1.2335 +                mOrientation = DISPLAY_ORIENTATION_0;
  1.2336 +            }
  1.2337 +        } else {
  1.2338 +            mOrientation = DISPLAY_ORIENTATION_0;
  1.2339 +        }
  1.2340 +        bumpGeneration();
  1.2341 +    }
  1.2342 +}
  1.2343 +
  1.2344 +void CursorInputMapper::configureParameters() {
  1.2345 +    mParameters.mode = Parameters::MODE_POINTER;
  1.2346 +    String8 cursorModeString;
  1.2347 +    if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
  1.2348 +        if (cursorModeString == "navigation") {
  1.2349 +            mParameters.mode = Parameters::MODE_NAVIGATION;
  1.2350 +        } else if (cursorModeString != "pointer" && cursorModeString != "default") {
  1.2351 +            ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
  1.2352 +        }
  1.2353 +    }
  1.2354 +
  1.2355 +    mParameters.orientationAware = false;
  1.2356 +    getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
  1.2357 +            mParameters.orientationAware);
  1.2358 +
  1.2359 +    mParameters.hasAssociatedDisplay = false;
  1.2360 +    if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) {
  1.2361 +        mParameters.hasAssociatedDisplay = true;
  1.2362 +    }
  1.2363 +}
  1.2364 +
  1.2365 +void CursorInputMapper::dumpParameters(String8& dump) {
  1.2366 +    dump.append(INDENT3 "Parameters:\n");
  1.2367 +    dump.appendFormat(INDENT4 "HasAssociatedDisplay: %s\n",
  1.2368 +            toString(mParameters.hasAssociatedDisplay));
  1.2369 +
  1.2370 +    switch (mParameters.mode) {
  1.2371 +    case Parameters::MODE_POINTER:
  1.2372 +        dump.append(INDENT4 "Mode: pointer\n");
  1.2373 +        break;
  1.2374 +    case Parameters::MODE_NAVIGATION:
  1.2375 +        dump.append(INDENT4 "Mode: navigation\n");
  1.2376 +        break;
  1.2377 +    default:
  1.2378 +        ALOG_ASSERT(false);
  1.2379 +    }
  1.2380 +
  1.2381 +    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
  1.2382 +            toString(mParameters.orientationAware));
  1.2383 +}
  1.2384 +
  1.2385 +void CursorInputMapper::reset(nsecs_t when) {
  1.2386 +    mButtonState = 0;
  1.2387 +    mDownTime = 0;
  1.2388 +
  1.2389 +    mPointerVelocityControl.reset();
  1.2390 +    mWheelXVelocityControl.reset();
  1.2391 +    mWheelYVelocityControl.reset();
  1.2392 +
  1.2393 +    mCursorButtonAccumulator.reset(getDevice());
  1.2394 +    mCursorMotionAccumulator.reset(getDevice());
  1.2395 +    mCursorScrollAccumulator.reset(getDevice());
  1.2396 +
  1.2397 +    InputMapper::reset(when);
  1.2398 +}
  1.2399 +
  1.2400 +void CursorInputMapper::process(const RawEvent* rawEvent) {
  1.2401 +    mCursorButtonAccumulator.process(rawEvent);
  1.2402 +    mCursorMotionAccumulator.process(rawEvent);
  1.2403 +    mCursorScrollAccumulator.process(rawEvent);
  1.2404 +
  1.2405 +    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
  1.2406 +        sync(rawEvent->when);
  1.2407 +    }
  1.2408 +}
  1.2409 +
  1.2410 +void CursorInputMapper::sync(nsecs_t when) {
  1.2411 +    int32_t lastButtonState = mButtonState;
  1.2412 +    int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
  1.2413 +    mButtonState = currentButtonState;
  1.2414 +
  1.2415 +    bool wasDown = isPointerDown(lastButtonState);
  1.2416 +    bool down = isPointerDown(currentButtonState);
  1.2417 +    bool downChanged;
  1.2418 +    if (!wasDown && down) {
  1.2419 +        mDownTime = when;
  1.2420 +        downChanged = true;
  1.2421 +    } else if (wasDown && !down) {
  1.2422 +        downChanged = true;
  1.2423 +    } else {
  1.2424 +        downChanged = false;
  1.2425 +    }
  1.2426 +    nsecs_t downTime = mDownTime;
  1.2427 +    bool buttonsChanged = currentButtonState != lastButtonState;
  1.2428 +    bool buttonsPressed = currentButtonState & ~lastButtonState;
  1.2429 +
  1.2430 +    float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
  1.2431 +    float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
  1.2432 +    bool moved = deltaX != 0 || deltaY != 0;
  1.2433 +
  1.2434 +    // Rotate delta according to orientation if needed.
  1.2435 +    if (mParameters.orientationAware && mParameters.hasAssociatedDisplay
  1.2436 +            && (deltaX != 0.0f || deltaY != 0.0f)) {
  1.2437 +        rotateDelta(mOrientation, &deltaX, &deltaY);
  1.2438 +    }
  1.2439 +
  1.2440 +    // Move the pointer.
  1.2441 +    PointerProperties pointerProperties;
  1.2442 +    pointerProperties.clear();
  1.2443 +    pointerProperties.id = 0;
  1.2444 +    pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
  1.2445 +
  1.2446 +    PointerCoords pointerCoords;
  1.2447 +    pointerCoords.clear();
  1.2448 +
  1.2449 +    float vscroll = mCursorScrollAccumulator.getRelativeVWheel();
  1.2450 +    float hscroll = mCursorScrollAccumulator.getRelativeHWheel();
  1.2451 +    bool scrolled = vscroll != 0 || hscroll != 0;
  1.2452 +
  1.2453 +    mWheelYVelocityControl.move(when, NULL, &vscroll);
  1.2454 +    mWheelXVelocityControl.move(when, &hscroll, NULL);
  1.2455 +
  1.2456 +    mPointerVelocityControl.move(when, &deltaX, &deltaY);
  1.2457 +
  1.2458 +    int32_t displayId;
  1.2459 +    if (mPointerController != NULL) {
  1.2460 +        if (moved || scrolled || buttonsChanged) {
  1.2461 +            mPointerController->setPresentation(
  1.2462 +                    PointerControllerInterface::PRESENTATION_POINTER);
  1.2463 +
  1.2464 +            if (moved) {
  1.2465 +                mPointerController->move(deltaX, deltaY);
  1.2466 +            }
  1.2467 +
  1.2468 +            if (buttonsChanged) {
  1.2469 +                mPointerController->setButtonState(currentButtonState);
  1.2470 +            }
  1.2471 +
  1.2472 +            mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
  1.2473 +        }
  1.2474 +
  1.2475 +        float x, y;
  1.2476 +        mPointerController->getPosition(&x, &y);
  1.2477 +        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
  1.2478 +        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
  1.2479 +        displayId = ADISPLAY_ID_DEFAULT;
  1.2480 +    } else {
  1.2481 +        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
  1.2482 +        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
  1.2483 +        displayId = ADISPLAY_ID_NONE;
  1.2484 +    }
  1.2485 +
  1.2486 +    pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
  1.2487 +
  1.2488 +    // Moving an external trackball or mouse should wake the device.
  1.2489 +    // We don't do this for internal cursor devices to prevent them from waking up
  1.2490 +    // the device in your pocket.
  1.2491 +    // TODO: Use the input device configuration to control this behavior more finely.
  1.2492 +    uint32_t policyFlags = 0;
  1.2493 +    if ((buttonsPressed || moved || scrolled) && getDevice()->isExternal()) {
  1.2494 +        policyFlags |= POLICY_FLAG_WAKE_DROPPED;
  1.2495 +    }
  1.2496 +
  1.2497 +    // Synthesize key down from buttons if needed.
  1.2498 +    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
  1.2499 +            policyFlags, lastButtonState, currentButtonState);
  1.2500 +
  1.2501 +    // Send motion event.
  1.2502 +    if (downChanged || moved || scrolled || buttonsChanged) {
  1.2503 +        int32_t metaState = mContext->getGlobalMetaState();
  1.2504 +        int32_t motionEventAction;
  1.2505 +        if (downChanged) {
  1.2506 +            motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
  1.2507 +        } else if (down || mPointerController == NULL) {
  1.2508 +            motionEventAction = AMOTION_EVENT_ACTION_MOVE;
  1.2509 +        } else {
  1.2510 +            motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
  1.2511 +        }
  1.2512 +
  1.2513 +        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
  1.2514 +                motionEventAction, 0, metaState, currentButtonState, 0,
  1.2515 +                displayId, 1, &pointerProperties, &pointerCoords,
  1.2516 +                mXPrecision, mYPrecision, downTime);
  1.2517 +        getListener()->notifyMotion(&args);
  1.2518 +
  1.2519 +        // Send hover move after UP to tell the application that the mouse is hovering now.
  1.2520 +        if (motionEventAction == AMOTION_EVENT_ACTION_UP
  1.2521 +                && mPointerController != NULL) {
  1.2522 +            NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, policyFlags,
  1.2523 +                    AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
  1.2524 +                    metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE,
  1.2525 +                    displayId, 1, &pointerProperties, &pointerCoords,
  1.2526 +                    mXPrecision, mYPrecision, downTime);
  1.2527 +            getListener()->notifyMotion(&hoverArgs);
  1.2528 +        }
  1.2529 +
  1.2530 +        // Send scroll events.
  1.2531 +        if (scrolled) {
  1.2532 +            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
  1.2533 +            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
  1.2534 +
  1.2535 +            NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags,
  1.2536 +                    AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState,
  1.2537 +                    AMOTION_EVENT_EDGE_FLAG_NONE,
  1.2538 +                    displayId, 1, &pointerProperties, &pointerCoords,
  1.2539 +                    mXPrecision, mYPrecision, downTime);
  1.2540 +            getListener()->notifyMotion(&scrollArgs);
  1.2541 +        }
  1.2542 +    }
  1.2543 +
  1.2544 +    // Synthesize key up from buttons if needed.
  1.2545 +    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
  1.2546 +            policyFlags, lastButtonState, currentButtonState);
  1.2547 +
  1.2548 +    mCursorMotionAccumulator.finishSync();
  1.2549 +    mCursorScrollAccumulator.finishSync();
  1.2550 +}
  1.2551 +
  1.2552 +int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
  1.2553 +    if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
  1.2554 +        return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
  1.2555 +    } else {
  1.2556 +        return AKEY_STATE_UNKNOWN;
  1.2557 +    }
  1.2558 +}
  1.2559 +
  1.2560 +void CursorInputMapper::fadePointer() {
  1.2561 +    if (mPointerController != NULL) {
  1.2562 +        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
  1.2563 +    }
  1.2564 +}
  1.2565 +
  1.2566 +
  1.2567 +// --- TouchInputMapper ---
  1.2568 +
  1.2569 +TouchInputMapper::TouchInputMapper(InputDevice* device) :
  1.2570 +        InputMapper(device),
  1.2571 +        mSource(0), mDeviceMode(DEVICE_MODE_DISABLED),
  1.2572 +        mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0),
  1.2573 +        mSurfaceOrientation(DISPLAY_ORIENTATION_0) {
  1.2574 +}
  1.2575 +
  1.2576 +TouchInputMapper::~TouchInputMapper() {
  1.2577 +}
  1.2578 +
  1.2579 +uint32_t TouchInputMapper::getSources() {
  1.2580 +    return mSource;
  1.2581 +}
  1.2582 +
  1.2583 +void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
  1.2584 +    InputMapper::populateDeviceInfo(info);
  1.2585 +
  1.2586 +    if (mDeviceMode != DEVICE_MODE_DISABLED) {
  1.2587 +        info->addMotionRange(mOrientedRanges.x);
  1.2588 +        info->addMotionRange(mOrientedRanges.y);
  1.2589 +        info->addMotionRange(mOrientedRanges.pressure);
  1.2590 +
  1.2591 +        if (mOrientedRanges.haveSize) {
  1.2592 +            info->addMotionRange(mOrientedRanges.size);
  1.2593 +        }
  1.2594 +
  1.2595 +        if (mOrientedRanges.haveTouchSize) {
  1.2596 +            info->addMotionRange(mOrientedRanges.touchMajor);
  1.2597 +            info->addMotionRange(mOrientedRanges.touchMinor);
  1.2598 +        }
  1.2599 +
  1.2600 +        if (mOrientedRanges.haveToolSize) {
  1.2601 +            info->addMotionRange(mOrientedRanges.toolMajor);
  1.2602 +            info->addMotionRange(mOrientedRanges.toolMinor);
  1.2603 +        }
  1.2604 +
  1.2605 +        if (mOrientedRanges.haveOrientation) {
  1.2606 +            info->addMotionRange(mOrientedRanges.orientation);
  1.2607 +        }
  1.2608 +
  1.2609 +        if (mOrientedRanges.haveDistance) {
  1.2610 +            info->addMotionRange(mOrientedRanges.distance);
  1.2611 +        }
  1.2612 +
  1.2613 +        if (mOrientedRanges.haveTilt) {
  1.2614 +            info->addMotionRange(mOrientedRanges.tilt);
  1.2615 +        }
  1.2616 +
  1.2617 +        if (mCursorScrollAccumulator.haveRelativeVWheel()) {
  1.2618 +            info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
  1.2619 +                    0.0f);
  1.2620 +        }
  1.2621 +        if (mCursorScrollAccumulator.haveRelativeHWheel()) {
  1.2622 +            info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
  1.2623 +                    0.0f);
  1.2624 +        }
  1.2625 +        if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
  1.2626 +            const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
  1.2627 +            const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
  1.2628 +            info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_1, mSource, x.min, x.max, x.flat,
  1.2629 +                    x.fuzz, x.resolution);
  1.2630 +            info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_2, mSource, y.min, y.max, y.flat,
  1.2631 +                    y.fuzz, y.resolution);
  1.2632 +            info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_3, mSource, x.min, x.max, x.flat,
  1.2633 +                    x.fuzz, x.resolution);
  1.2634 +            info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_4, mSource, y.min, y.max, y.flat,
  1.2635 +                    y.fuzz, y.resolution);
  1.2636 +        }
  1.2637 +    }
  1.2638 +}
  1.2639 +
  1.2640 +void TouchInputMapper::dump(String8& dump) {
  1.2641 +    dump.append(INDENT2 "Touch Input Mapper:\n");
  1.2642 +    dumpParameters(dump);
  1.2643 +    dumpVirtualKeys(dump);
  1.2644 +    dumpRawPointerAxes(dump);
  1.2645 +    dumpCalibration(dump);
  1.2646 +    dumpSurface(dump);
  1.2647 +
  1.2648 +    dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
  1.2649 +    dump.appendFormat(INDENT4 "XTranslate: %0.3f\n", mXTranslate);
  1.2650 +    dump.appendFormat(INDENT4 "YTranslate: %0.3f\n", mYTranslate);
  1.2651 +    dump.appendFormat(INDENT4 "XScale: %0.3f\n", mXScale);
  1.2652 +    dump.appendFormat(INDENT4 "YScale: %0.3f\n", mYScale);
  1.2653 +    dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mXPrecision);
  1.2654 +    dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mYPrecision);
  1.2655 +    dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale);
  1.2656 +    dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mPressureScale);
  1.2657 +    dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mSizeScale);
  1.2658 +    dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale);
  1.2659 +    dump.appendFormat(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale);
  1.2660 +    dump.appendFormat(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt));
  1.2661 +    dump.appendFormat(INDENT4 "TiltXCenter: %0.3f\n", mTiltXCenter);
  1.2662 +    dump.appendFormat(INDENT4 "TiltXScale: %0.3f\n", mTiltXScale);
  1.2663 +    dump.appendFormat(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter);
  1.2664 +    dump.appendFormat(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale);
  1.2665 +
  1.2666 +    dump.appendFormat(INDENT3 "Last Button State: 0x%08x\n", mLastButtonState);
  1.2667 +
  1.2668 +    dump.appendFormat(INDENT3 "Last Raw Touch: pointerCount=%d\n",
  1.2669 +            mLastRawPointerData.pointerCount);
  1.2670 +    for (uint32_t i = 0; i < mLastRawPointerData.pointerCount; i++) {
  1.2671 +        const RawPointerData::Pointer& pointer = mLastRawPointerData.pointers[i];
  1.2672 +        dump.appendFormat(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
  1.2673 +                "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
  1.2674 +                "orientation=%d, tiltX=%d, tiltY=%d, distance=%d, "
  1.2675 +                "toolType=%d, isHovering=%s\n", i,
  1.2676 +                pointer.id, pointer.x, pointer.y, pointer.pressure,
  1.2677 +                pointer.touchMajor, pointer.touchMinor,
  1.2678 +                pointer.toolMajor, pointer.toolMinor,
  1.2679 +                pointer.orientation, pointer.tiltX, pointer.tiltY, pointer.distance,
  1.2680 +                pointer.toolType, toString(pointer.isHovering));
  1.2681 +    }
  1.2682 +
  1.2683 +    dump.appendFormat(INDENT3 "Last Cooked Touch: pointerCount=%d\n",
  1.2684 +            mLastCookedPointerData.pointerCount);
  1.2685 +    for (uint32_t i = 0; i < mLastCookedPointerData.pointerCount; i++) {
  1.2686 +        const PointerProperties& pointerProperties = mLastCookedPointerData.pointerProperties[i];
  1.2687 +        const PointerCoords& pointerCoords = mLastCookedPointerData.pointerCoords[i];
  1.2688 +        dump.appendFormat(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, "
  1.2689 +                "touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, toolMinor=%0.3f, "
  1.2690 +                "orientation=%0.3f, tilt=%0.3f, distance=%0.3f, "
  1.2691 +                "toolType=%d, isHovering=%s\n", i,
  1.2692 +                pointerProperties.id,
  1.2693 +                pointerCoords.getX(),
  1.2694 +                pointerCoords.getY(),
  1.2695 +                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
  1.2696 +                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
  1.2697 +                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
  1.2698 +                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
  1.2699 +                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
  1.2700 +                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION),
  1.2701 +                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TILT),
  1.2702 +                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE),
  1.2703 +                pointerProperties.toolType,
  1.2704 +                toString(mLastCookedPointerData.isHovering(i)));
  1.2705 +    }
  1.2706 +
  1.2707 +    if (mDeviceMode == DEVICE_MODE_POINTER) {
  1.2708 +        dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n");
  1.2709 +        dump.appendFormat(INDENT4 "XMovementScale: %0.3f\n",
  1.2710 +                mPointerXMovementScale);
  1.2711 +        dump.appendFormat(INDENT4 "YMovementScale: %0.3f\n",
  1.2712 +                mPointerYMovementScale);
  1.2713 +        dump.appendFormat(INDENT4 "XZoomScale: %0.3f\n",
  1.2714 +                mPointerXZoomScale);
  1.2715 +        dump.appendFormat(INDENT4 "YZoomScale: %0.3f\n",
  1.2716 +                mPointerYZoomScale);
  1.2717 +        dump.appendFormat(INDENT4 "MaxSwipeWidth: %f\n",
  1.2718 +                mPointerGestureMaxSwipeWidth);
  1.2719 +    }
  1.2720 +}
  1.2721 +
  1.2722 +void TouchInputMapper::configure(nsecs_t when,
  1.2723 +        const InputReaderConfiguration* config, uint32_t changes) {
  1.2724 +    InputMapper::configure(when, config, changes);
  1.2725 +
  1.2726 +    mConfig = *config;
  1.2727 +
  1.2728 +    if (!changes) { // first time only
  1.2729 +        // Configure basic parameters.
  1.2730 +        configureParameters();
  1.2731 +
  1.2732 +        // Configure common accumulators.
  1.2733 +        mCursorScrollAccumulator.configure(getDevice());
  1.2734 +        mTouchButtonAccumulator.configure(getDevice());
  1.2735 +
  1.2736 +        // Configure absolute axis information.
  1.2737 +        configureRawPointerAxes();
  1.2738 +
  1.2739 +        // Prepare input device calibration.
  1.2740 +        parseCalibration();
  1.2741 +        resolveCalibration();
  1.2742 +    }
  1.2743 +
  1.2744 +    if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
  1.2745 +        // Update pointer speed.
  1.2746 +        mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters);
  1.2747 +        mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
  1.2748 +        mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
  1.2749 +    }
  1.2750 +
  1.2751 +    bool resetNeeded = false;
  1.2752 +    if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO
  1.2753 +            | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT
  1.2754 +            | InputReaderConfiguration::CHANGE_SHOW_TOUCHES))) {
  1.2755 +        // Configure device sources, surface dimensions, orientation and
  1.2756 +        // scaling factors.
  1.2757 +        configureSurface(when, &resetNeeded);
  1.2758 +    }
  1.2759 +
  1.2760 +    if (changes && resetNeeded) {
  1.2761 +        // Send reset, unless this is the first time the device has been configured,
  1.2762 +        // in which case the reader will call reset itself after all mappers are ready.
  1.2763 +        getDevice()->notifyReset(when);
  1.2764 +    }
  1.2765 +}
  1.2766 +
  1.2767 +void TouchInputMapper::configureParameters() {
  1.2768 +    // Use the pointer presentation mode for devices that do not support distinct
  1.2769 +    // multitouch.  The spot-based presentation relies on being able to accurately
  1.2770 +    // locate two or more fingers on the touch pad.
  1.2771 +    mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT)
  1.2772 +            ? Parameters::GESTURE_MODE_POINTER : Parameters::GESTURE_MODE_SPOTS;
  1.2773 +
  1.2774 +    String8 gestureModeString;
  1.2775 +    if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
  1.2776 +            gestureModeString)) {
  1.2777 +        if (gestureModeString == "pointer") {
  1.2778 +            mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER;
  1.2779 +        } else if (gestureModeString == "spots") {
  1.2780 +            mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
  1.2781 +        } else if (gestureModeString != "default") {
  1.2782 +            ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
  1.2783 +        }
  1.2784 +    }
  1.2785 +
  1.2786 +    if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
  1.2787 +        // The device is a touch screen.
  1.2788 +        mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
  1.2789 +    } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) {
  1.2790 +        // The device is a pointing device like a track pad.
  1.2791 +        mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
  1.2792 +    } else if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
  1.2793 +            || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
  1.2794 +        // The device is a cursor device with a touch pad attached.
  1.2795 +        // By default don't use the touch pad to move the pointer.
  1.2796 +        mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
  1.2797 +    } else {
  1.2798 +        // The device is a touch pad of unknown purpose.
  1.2799 +        mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
  1.2800 +    }
  1.2801 +
  1.2802 +    String8 deviceTypeString;
  1.2803 +    if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
  1.2804 +            deviceTypeString)) {
  1.2805 +        if (deviceTypeString == "touchScreen") {
  1.2806 +            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
  1.2807 +        } else if (deviceTypeString == "touchPad") {
  1.2808 +            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
  1.2809 +        } else if (deviceTypeString == "touchNavigation") {
  1.2810 +            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION;
  1.2811 +        } else if (deviceTypeString == "pointer") {
  1.2812 +            mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
  1.2813 +        } else if (deviceTypeString != "default") {
  1.2814 +            ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
  1.2815 +        }
  1.2816 +    }
  1.2817 +
  1.2818 +    mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
  1.2819 +    getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
  1.2820 +            mParameters.orientationAware);
  1.2821 +
  1.2822 +    mParameters.hasAssociatedDisplay = false;
  1.2823 +    mParameters.associatedDisplayIsExternal = false;
  1.2824 +    if (mParameters.orientationAware
  1.2825 +            || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
  1.2826 +            || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
  1.2827 +        mParameters.hasAssociatedDisplay = true;
  1.2828 +        mParameters.associatedDisplayIsExternal =
  1.2829 +                mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
  1.2830 +                        && getDevice()->isExternal();
  1.2831 +    }
  1.2832 +}
  1.2833 +
  1.2834 +void TouchInputMapper::dumpParameters(String8& dump) {
  1.2835 +    dump.append(INDENT3 "Parameters:\n");
  1.2836 +
  1.2837 +    switch (mParameters.gestureMode) {
  1.2838 +    case Parameters::GESTURE_MODE_POINTER:
  1.2839 +        dump.append(INDENT4 "GestureMode: pointer\n");
  1.2840 +        break;
  1.2841 +    case Parameters::GESTURE_MODE_SPOTS:
  1.2842 +        dump.append(INDENT4 "GestureMode: spots\n");
  1.2843 +        break;
  1.2844 +    default:
  1.2845 +        assert(false);
  1.2846 +    }
  1.2847 +
  1.2848 +    switch (mParameters.deviceType) {
  1.2849 +    case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
  1.2850 +        dump.append(INDENT4 "DeviceType: touchScreen\n");
  1.2851 +        break;
  1.2852 +    case Parameters::DEVICE_TYPE_TOUCH_PAD:
  1.2853 +        dump.append(INDENT4 "DeviceType: touchPad\n");
  1.2854 +        break;
  1.2855 +    case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION:
  1.2856 +        dump.append(INDENT4 "DeviceType: touchNavigation\n");
  1.2857 +        break;
  1.2858 +    case Parameters::DEVICE_TYPE_POINTER:
  1.2859 +        dump.append(INDENT4 "DeviceType: pointer\n");
  1.2860 +        break;
  1.2861 +    default:
  1.2862 +        ALOG_ASSERT(false);
  1.2863 +    }
  1.2864 +
  1.2865 +    dump.appendFormat(INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s\n",
  1.2866 +            toString(mParameters.hasAssociatedDisplay),
  1.2867 +            toString(mParameters.associatedDisplayIsExternal));
  1.2868 +    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
  1.2869 +            toString(mParameters.orientationAware));
  1.2870 +}
  1.2871 +
  1.2872 +void TouchInputMapper::configureRawPointerAxes() {
  1.2873 +    mRawPointerAxes.clear();
  1.2874 +}
  1.2875 +
  1.2876 +void TouchInputMapper::dumpRawPointerAxes(String8& dump) {
  1.2877 +    dump.append(INDENT3 "Raw Touch Axes:\n");
  1.2878 +    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.x, "X");
  1.2879 +    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.y, "Y");
  1.2880 +    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.pressure, "Pressure");
  1.2881 +    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMajor, "TouchMajor");
  1.2882 +    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMinor, "TouchMinor");
  1.2883 +    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMajor, "ToolMajor");
  1.2884 +    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMinor, "ToolMinor");
  1.2885 +    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.orientation, "Orientation");
  1.2886 +    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.distance, "Distance");
  1.2887 +    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltX, "TiltX");
  1.2888 +    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltY, "TiltY");
  1.2889 +    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.trackingId, "TrackingId");
  1.2890 +    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot");
  1.2891 +}
  1.2892 +
  1.2893 +void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
  1.2894 +    int32_t oldDeviceMode = mDeviceMode;
  1.2895 +
  1.2896 +    // Determine device mode.
  1.2897 +    if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
  1.2898 +            && mConfig.pointerGesturesEnabled) {
  1.2899 +        mSource = AINPUT_SOURCE_MOUSE;
  1.2900 +        mDeviceMode = DEVICE_MODE_POINTER;
  1.2901 +        if (hasStylus()) {
  1.2902 +            mSource |= AINPUT_SOURCE_STYLUS;
  1.2903 +        }
  1.2904 +    } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
  1.2905 +            && mParameters.hasAssociatedDisplay) {
  1.2906 +        mSource = AINPUT_SOURCE_TOUCHSCREEN;
  1.2907 +        mDeviceMode = DEVICE_MODE_DIRECT;
  1.2908 +        if (hasStylus()) {
  1.2909 +            mSource |= AINPUT_SOURCE_STYLUS;
  1.2910 +        }
  1.2911 +    } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) {
  1.2912 +        mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
  1.2913 +        mDeviceMode = DEVICE_MODE_NAVIGATION;
  1.2914 +    } else {
  1.2915 +        mSource = AINPUT_SOURCE_TOUCHPAD;
  1.2916 +        mDeviceMode = DEVICE_MODE_UNSCALED;
  1.2917 +    }
  1.2918 +
  1.2919 +    // Ensure we have valid X and Y axes.
  1.2920 +    if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
  1.2921 +        ALOGW(INDENT "Touch device '%s' did not report support for X or Y axis!  "
  1.2922 +                "The device will be inoperable.", getDeviceName().string());
  1.2923 +        mDeviceMode = DEVICE_MODE_DISABLED;
  1.2924 +        return;
  1.2925 +    }
  1.2926 +
  1.2927 +    // Raw width and height in the natural orientation.
  1.2928 +    int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
  1.2929 +    int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
  1.2930 +
  1.2931 +    // Get associated display dimensions.
  1.2932 +    bool viewportChanged = false;
  1.2933 +    DisplayViewport newViewport;
  1.2934 +    if (mParameters.hasAssociatedDisplay) {
  1.2935 +        if (!mConfig.getDisplayInfo(mParameters.associatedDisplayIsExternal, &newViewport)) {
  1.2936 +            ALOGI(INDENT "Touch device '%s' could not query the properties of its associated "
  1.2937 +                    "display.  The device will be inoperable until the display size "
  1.2938 +                    "becomes available.",
  1.2939 +                    getDeviceName().string());
  1.2940 +            mDeviceMode = DEVICE_MODE_DISABLED;
  1.2941 +            return;
  1.2942 +        }
  1.2943 +    } else {
  1.2944 +        newViewport.setNonDisplayViewport(rawWidth, rawHeight);
  1.2945 +    }
  1.2946 +    if (mViewport != newViewport) {
  1.2947 +        mViewport = newViewport;
  1.2948 +        viewportChanged = true;
  1.2949 +
  1.2950 +        if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
  1.2951 +            // Convert rotated viewport to natural surface coordinates.
  1.2952 +            int32_t naturalLogicalWidth, naturalLogicalHeight;
  1.2953 +            int32_t naturalPhysicalWidth, naturalPhysicalHeight;
  1.2954 +            int32_t naturalPhysicalLeft, naturalPhysicalTop;
  1.2955 +            int32_t naturalDeviceWidth, naturalDeviceHeight;
  1.2956 +            switch (mViewport.orientation) {
  1.2957 +            case DISPLAY_ORIENTATION_90:
  1.2958 +                naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
  1.2959 +                naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
  1.2960 +                naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
  1.2961 +                naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
  1.2962 +                naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom;
  1.2963 +                naturalPhysicalTop = mViewport.physicalLeft;
  1.2964 +                naturalDeviceWidth = mViewport.deviceHeight;
  1.2965 +                naturalDeviceHeight = mViewport.deviceWidth;
  1.2966 +                break;
  1.2967 +            case DISPLAY_ORIENTATION_180:
  1.2968 +                naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
  1.2969 +                naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
  1.2970 +                naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
  1.2971 +                naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
  1.2972 +                naturalPhysicalLeft = mViewport.deviceWidth - mViewport.physicalRight;
  1.2973 +                naturalPhysicalTop = mViewport.deviceHeight - mViewport.physicalBottom;
  1.2974 +                naturalDeviceWidth = mViewport.deviceWidth;
  1.2975 +                naturalDeviceHeight = mViewport.deviceHeight;
  1.2976 +                break;
  1.2977 +            case DISPLAY_ORIENTATION_270:
  1.2978 +                naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
  1.2979 +                naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
  1.2980 +                naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
  1.2981 +                naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
  1.2982 +                naturalPhysicalLeft = mViewport.physicalTop;
  1.2983 +                naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight;
  1.2984 +                naturalDeviceWidth = mViewport.deviceHeight;
  1.2985 +                naturalDeviceHeight = mViewport.deviceWidth;
  1.2986 +                break;
  1.2987 +            case DISPLAY_ORIENTATION_0:
  1.2988 +            default:
  1.2989 +                naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
  1.2990 +                naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
  1.2991 +                naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
  1.2992 +                naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
  1.2993 +                naturalPhysicalLeft = mViewport.physicalLeft;
  1.2994 +                naturalPhysicalTop = mViewport.physicalTop;
  1.2995 +                naturalDeviceWidth = mViewport.deviceWidth;
  1.2996 +                naturalDeviceHeight = mViewport.deviceHeight;
  1.2997 +                break;
  1.2998 +            }
  1.2999 +
  1.3000 +            mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
  1.3001 +            mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
  1.3002 +            mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth;
  1.3003 +            mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight;
  1.3004 +
  1.3005 +            mSurfaceOrientation = mParameters.orientationAware ?
  1.3006 +                    mViewport.orientation : DISPLAY_ORIENTATION_0;
  1.3007 +        } else {
  1.3008 +            mSurfaceWidth = rawWidth;
  1.3009 +            mSurfaceHeight = rawHeight;
  1.3010 +            mSurfaceLeft = 0;
  1.3011 +            mSurfaceTop = 0;
  1.3012 +            mSurfaceOrientation = DISPLAY_ORIENTATION_0;
  1.3013 +        }
  1.3014 +    }
  1.3015 +
  1.3016 +    // If moving between pointer modes, need to reset some state.
  1.3017 +    bool deviceModeChanged;
  1.3018 +    if (mDeviceMode != oldDeviceMode) {
  1.3019 +        deviceModeChanged = true;
  1.3020 +        mOrientedRanges.clear();
  1.3021 +    }
  1.3022 +
  1.3023 +    // Create pointer controller if needed.
  1.3024 +    if (mDeviceMode == DEVICE_MODE_POINTER ||
  1.3025 +            (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
  1.3026 +        if (mPointerController == NULL) {
  1.3027 +            mPointerController = getPolicy()->obtainPointerController(getDeviceId());
  1.3028 +        }
  1.3029 +    } else {
  1.3030 +        mPointerController.clear();
  1.3031 +    }
  1.3032 +
  1.3033 +    if (viewportChanged || deviceModeChanged) {
  1.3034 +        ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
  1.3035 +                "display id %d",
  1.3036 +                getDeviceId(), getDeviceName().string(), mSurfaceWidth, mSurfaceHeight,
  1.3037 +                mSurfaceOrientation, mDeviceMode, mViewport.displayId);
  1.3038 +
  1.3039 +        // Configure X and Y factors.
  1.3040 +        mXScale = float(mSurfaceWidth) / rawWidth;
  1.3041 +        mYScale = float(mSurfaceHeight) / rawHeight;
  1.3042 +        mXTranslate = -mSurfaceLeft;
  1.3043 +        mYTranslate = -mSurfaceTop;
  1.3044 +        mXPrecision = 1.0f / mXScale;
  1.3045 +        mYPrecision = 1.0f / mYScale;
  1.3046 +
  1.3047 +        mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
  1.3048 +        mOrientedRanges.x.source = mSource;
  1.3049 +        mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
  1.3050 +        mOrientedRanges.y.source = mSource;
  1.3051 +
  1.3052 +        configureVirtualKeys();
  1.3053 +
  1.3054 +        // Scale factor for terms that are not oriented in a particular axis.
  1.3055 +        // If the pixels are square then xScale == yScale otherwise we fake it
  1.3056 +        // by choosing an average.
  1.3057 +        mGeometricScale = avg(mXScale, mYScale);
  1.3058 +
  1.3059 +        // Size of diagonal axis.
  1.3060 +        float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight);
  1.3061 +
  1.3062 +        // Size factors.
  1.3063 +        if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
  1.3064 +            if (mRawPointerAxes.touchMajor.valid
  1.3065 +                    && mRawPointerAxes.touchMajor.maxValue != 0) {
  1.3066 +                mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue;
  1.3067 +            } else if (mRawPointerAxes.toolMajor.valid
  1.3068 +                    && mRawPointerAxes.toolMajor.maxValue != 0) {
  1.3069 +                mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue;
  1.3070 +            } else {
  1.3071 +                mSizeScale = 0.0f;
  1.3072 +            }
  1.3073 +
  1.3074 +            mOrientedRanges.haveTouchSize = true;
  1.3075 +            mOrientedRanges.haveToolSize = true;
  1.3076 +            mOrientedRanges.haveSize = true;
  1.3077 +
  1.3078 +            mOrientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
  1.3079 +            mOrientedRanges.touchMajor.source = mSource;
  1.3080 +            mOrientedRanges.touchMajor.min = 0;
  1.3081 +            mOrientedRanges.touchMajor.max = diagonalSize;
  1.3082 +            mOrientedRanges.touchMajor.flat = 0;
  1.3083 +            mOrientedRanges.touchMajor.fuzz = 0;
  1.3084 +            mOrientedRanges.touchMajor.resolution = 0;
  1.3085 +
  1.3086 +            mOrientedRanges.touchMinor = mOrientedRanges.touchMajor;
  1.3087 +            mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
  1.3088 +
  1.3089 +            mOrientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
  1.3090 +            mOrientedRanges.toolMajor.source = mSource;
  1.3091 +            mOrientedRanges.toolMajor.min = 0;
  1.3092 +            mOrientedRanges.toolMajor.max = diagonalSize;
  1.3093 +            mOrientedRanges.toolMajor.flat = 0;
  1.3094 +            mOrientedRanges.toolMajor.fuzz = 0;
  1.3095 +            mOrientedRanges.toolMajor.resolution = 0;
  1.3096 +
  1.3097 +            mOrientedRanges.toolMinor = mOrientedRanges.toolMajor;
  1.3098 +            mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
  1.3099 +
  1.3100 +            mOrientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
  1.3101 +            mOrientedRanges.size.source = mSource;
  1.3102 +            mOrientedRanges.size.min = 0;
  1.3103 +            mOrientedRanges.size.max = 1.0;
  1.3104 +            mOrientedRanges.size.flat = 0;
  1.3105 +            mOrientedRanges.size.fuzz = 0;
  1.3106 +            mOrientedRanges.size.resolution = 0;
  1.3107 +        } else {
  1.3108 +            mSizeScale = 0.0f;
  1.3109 +        }
  1.3110 +
  1.3111 +        // Pressure factors.
  1.3112 +        mPressureScale = 0;
  1.3113 +        if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
  1.3114 +                || mCalibration.pressureCalibration
  1.3115 +                        == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
  1.3116 +            if (mCalibration.havePressureScale) {
  1.3117 +                mPressureScale = mCalibration.pressureScale;
  1.3118 +            } else if (mRawPointerAxes.pressure.valid
  1.3119 +                    && mRawPointerAxes.pressure.maxValue != 0) {
  1.3120 +                mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue;
  1.3121 +            }
  1.3122 +        }
  1.3123 +
  1.3124 +        mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
  1.3125 +        mOrientedRanges.pressure.source = mSource;
  1.3126 +        mOrientedRanges.pressure.min = 0;
  1.3127 +        mOrientedRanges.pressure.max = 1.0;
  1.3128 +        mOrientedRanges.pressure.flat = 0;
  1.3129 +        mOrientedRanges.pressure.fuzz = 0;
  1.3130 +        mOrientedRanges.pressure.resolution = 0;
  1.3131 +
  1.3132 +        // Tilt
  1.3133 +        mTiltXCenter = 0;
  1.3134 +        mTiltXScale = 0;
  1.3135 +        mTiltYCenter = 0;
  1.3136 +        mTiltYScale = 0;
  1.3137 +        mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid;
  1.3138 +        if (mHaveTilt) {
  1.3139 +            mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue,
  1.3140 +                    mRawPointerAxes.tiltX.maxValue);
  1.3141 +            mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue,
  1.3142 +                    mRawPointerAxes.tiltY.maxValue);
  1.3143 +            mTiltXScale = M_PI / 180;
  1.3144 +            mTiltYScale = M_PI / 180;
  1.3145 +
  1.3146 +            mOrientedRanges.haveTilt = true;
  1.3147 +
  1.3148 +            mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT;
  1.3149 +            mOrientedRanges.tilt.source = mSource;
  1.3150 +            mOrientedRanges.tilt.min = 0;
  1.3151 +            mOrientedRanges.tilt.max = M_PI_2;
  1.3152 +            mOrientedRanges.tilt.flat = 0;
  1.3153 +            mOrientedRanges.tilt.fuzz = 0;
  1.3154 +            mOrientedRanges.tilt.resolution = 0;
  1.3155 +        }
  1.3156 +
  1.3157 +        // Orientation
  1.3158 +        mOrientationScale = 0;
  1.3159 +        if (mHaveTilt) {
  1.3160 +            mOrientedRanges.haveOrientation = true;
  1.3161 +
  1.3162 +            mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
  1.3163 +            mOrientedRanges.orientation.source = mSource;
  1.3164 +            mOrientedRanges.orientation.min = -M_PI;
  1.3165 +            mOrientedRanges.orientation.max = M_PI;
  1.3166 +            mOrientedRanges.orientation.flat = 0;
  1.3167 +            mOrientedRanges.orientation.fuzz = 0;
  1.3168 +            mOrientedRanges.orientation.resolution = 0;
  1.3169 +        } else if (mCalibration.orientationCalibration !=
  1.3170 +                Calibration::ORIENTATION_CALIBRATION_NONE) {
  1.3171 +            if (mCalibration.orientationCalibration
  1.3172 +                    == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
  1.3173 +                if (mRawPointerAxes.orientation.valid) {
  1.3174 +                    if (mRawPointerAxes.orientation.maxValue > 0) {
  1.3175 +                        mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue;
  1.3176 +                    } else if (mRawPointerAxes.orientation.minValue < 0) {
  1.3177 +                        mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue;
  1.3178 +                    } else {
  1.3179 +                        mOrientationScale = 0;
  1.3180 +                    }
  1.3181 +                }
  1.3182 +            }
  1.3183 +
  1.3184 +            mOrientedRanges.haveOrientation = true;
  1.3185 +
  1.3186 +            mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
  1.3187 +            mOrientedRanges.orientation.source = mSource;
  1.3188 +            mOrientedRanges.orientation.min = -M_PI_2;
  1.3189 +            mOrientedRanges.orientation.max = M_PI_2;
  1.3190 +            mOrientedRanges.orientation.flat = 0;
  1.3191 +            mOrientedRanges.orientation.fuzz = 0;
  1.3192 +            mOrientedRanges.orientation.resolution = 0;
  1.3193 +        }
  1.3194 +
  1.3195 +        // Distance
  1.3196 +        mDistanceScale = 0;
  1.3197 +        if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) {
  1.3198 +            if (mCalibration.distanceCalibration
  1.3199 +                    == Calibration::DISTANCE_CALIBRATION_SCALED) {
  1.3200 +                if (mCalibration.haveDistanceScale) {
  1.3201 +                    mDistanceScale = mCalibration.distanceScale;
  1.3202 +                } else {
  1.3203 +                    mDistanceScale = 1.0f;
  1.3204 +                }
  1.3205 +            }
  1.3206 +
  1.3207 +            mOrientedRanges.haveDistance = true;
  1.3208 +
  1.3209 +            mOrientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE;
  1.3210 +            mOrientedRanges.distance.source = mSource;
  1.3211 +            mOrientedRanges.distance.min =
  1.3212 +                    mRawPointerAxes.distance.minValue * mDistanceScale;
  1.3213 +            mOrientedRanges.distance.max =
  1.3214 +                    mRawPointerAxes.distance.maxValue * mDistanceScale;
  1.3215 +            mOrientedRanges.distance.flat = 0;
  1.3216 +            mOrientedRanges.distance.fuzz =
  1.3217 +                    mRawPointerAxes.distance.fuzz * mDistanceScale;
  1.3218 +            mOrientedRanges.distance.resolution = 0;
  1.3219 +        }
  1.3220 +
  1.3221 +        // Compute oriented precision, scales and ranges.
  1.3222 +        // Note that the maximum value reported is an inclusive maximum value so it is one
  1.3223 +        // unit less than the total width or height of surface.
  1.3224 +        switch (mSurfaceOrientation) {
  1.3225 +        case DISPLAY_ORIENTATION_90:
  1.3226 +        case DISPLAY_ORIENTATION_270:
  1.3227 +            mOrientedXPrecision = mYPrecision;
  1.3228 +            mOrientedYPrecision = mXPrecision;
  1.3229 +
  1.3230 +            mOrientedRanges.x.min = mYTranslate;
  1.3231 +            mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1;
  1.3232 +            mOrientedRanges.x.flat = 0;
  1.3233 +            mOrientedRanges.x.fuzz = 0;
  1.3234 +            mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mYScale;
  1.3235 +
  1.3236 +            mOrientedRanges.y.min = mXTranslate;
  1.3237 +            mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1;
  1.3238 +            mOrientedRanges.y.flat = 0;
  1.3239 +            mOrientedRanges.y.fuzz = 0;
  1.3240 +            mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mXScale;
  1.3241 +            break;
  1.3242 +
  1.3243 +        default:
  1.3244 +            mOrientedXPrecision = mXPrecision;
  1.3245 +            mOrientedYPrecision = mYPrecision;
  1.3246 +
  1.3247 +            mOrientedRanges.x.min = mXTranslate;
  1.3248 +            mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1;
  1.3249 +            mOrientedRanges.x.flat = 0;
  1.3250 +            mOrientedRanges.x.fuzz = 0;
  1.3251 +            mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mXScale;
  1.3252 +
  1.3253 +            mOrientedRanges.y.min = mYTranslate;
  1.3254 +            mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1;
  1.3255 +            mOrientedRanges.y.flat = 0;
  1.3256 +            mOrientedRanges.y.fuzz = 0;
  1.3257 +            mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale;
  1.3258 +            break;
  1.3259 +        }
  1.3260 +
  1.3261 +        if (mDeviceMode == DEVICE_MODE_POINTER) {
  1.3262 +            // Compute pointer gesture detection parameters.
  1.3263 +            float rawDiagonal = hypotf(rawWidth, rawHeight);
  1.3264 +            float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight);
  1.3265 +
  1.3266 +            // Scale movements such that one whole swipe of the touch pad covers a
  1.3267 +            // given area relative to the diagonal size of the display when no acceleration
  1.3268 +            // is applied.
  1.3269 +            // Assume that the touch pad has a square aspect ratio such that movements in
  1.3270 +            // X and Y of the same number of raw units cover the same physical distance.
  1.3271 +            mPointerXMovementScale = mConfig.pointerGestureMovementSpeedRatio
  1.3272 +                    * displayDiagonal / rawDiagonal;
  1.3273 +            mPointerYMovementScale = mPointerXMovementScale;
  1.3274 +
  1.3275 +            // Scale zooms to cover a smaller range of the display than movements do.
  1.3276 +            // This value determines the area around the pointer that is affected by freeform
  1.3277 +            // pointer gestures.
  1.3278 +            mPointerXZoomScale = mConfig.pointerGestureZoomSpeedRatio
  1.3279 +                    * displayDiagonal / rawDiagonal;
  1.3280 +            mPointerYZoomScale = mPointerXZoomScale;
  1.3281 +
  1.3282 +            // Max width between pointers to detect a swipe gesture is more than some fraction
  1.3283 +            // of the diagonal axis of the touch pad.  Touches that are wider than this are
  1.3284 +            // translated into freeform gestures.
  1.3285 +            mPointerGestureMaxSwipeWidth =
  1.3286 +                    mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
  1.3287 +
  1.3288 +            // Abort current pointer usages because the state has changed.
  1.3289 +            abortPointerUsage(when, 0 /*policyFlags*/);
  1.3290 +        }
  1.3291 +
  1.3292 +        // Inform the dispatcher about the changes.
  1.3293 +        *outResetNeeded = true;
  1.3294 +        bumpGeneration();
  1.3295 +    }
  1.3296 +}
  1.3297 +
  1.3298 +void TouchInputMapper::dumpSurface(String8& dump) {
  1.3299 +    dump.appendFormat(INDENT3 "Viewport: displayId=%d, orientation=%d, "
  1.3300 +            "logicalFrame=[%d, %d, %d, %d], "
  1.3301 +            "physicalFrame=[%d, %d, %d, %d], "
  1.3302 +            "deviceSize=[%d, %d]\n",
  1.3303 +            mViewport.displayId, mViewport.orientation,
  1.3304 +            mViewport.logicalLeft, mViewport.logicalTop,
  1.3305 +            mViewport.logicalRight, mViewport.logicalBottom,
  1.3306 +            mViewport.physicalLeft, mViewport.physicalTop,
  1.3307 +            mViewport.physicalRight, mViewport.physicalBottom,
  1.3308 +            mViewport.deviceWidth, mViewport.deviceHeight);
  1.3309 +
  1.3310 +    dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
  1.3311 +    dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
  1.3312 +    dump.appendFormat(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
  1.3313 +    dump.appendFormat(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
  1.3314 +    dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
  1.3315 +}
  1.3316 +
  1.3317 +void TouchInputMapper::configureVirtualKeys() {
  1.3318 +    Vector<VirtualKeyDefinition> virtualKeyDefinitions;
  1.3319 +    getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
  1.3320 +
  1.3321 +    mVirtualKeys.clear();
  1.3322 +
  1.3323 +    if (virtualKeyDefinitions.size() == 0) {
  1.3324 +        return;
  1.3325 +    }
  1.3326 +
  1.3327 +    mVirtualKeys.setCapacity(virtualKeyDefinitions.size());
  1.3328 +
  1.3329 +    int32_t touchScreenLeft = mRawPointerAxes.x.minValue;
  1.3330 +    int32_t touchScreenTop = mRawPointerAxes.y.minValue;
  1.3331 +    int32_t touchScreenWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
  1.3332 +    int32_t touchScreenHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
  1.3333 +
  1.3334 +    for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
  1.3335 +        const VirtualKeyDefinition& virtualKeyDefinition =
  1.3336 +                virtualKeyDefinitions[i];
  1.3337 +
  1.3338 +        mVirtualKeys.add();
  1.3339 +        VirtualKey& virtualKey = mVirtualKeys.editTop();
  1.3340 +
  1.3341 +        virtualKey.scanCode = virtualKeyDefinition.scanCode;
  1.3342 +        int32_t keyCode;
  1.3343 +        uint32_t flags;
  1.3344 +        if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, 0, &keyCode, &flags)) {
  1.3345 +            ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
  1.3346 +                    virtualKey.scanCode);
  1.3347 +            mVirtualKeys.pop(); // drop the key
  1.3348 +            continue;
  1.3349 +        }
  1.3350 +
  1.3351 +        virtualKey.keyCode = keyCode;
  1.3352 +        virtualKey.flags = flags;
  1.3353 +
  1.3354 +        // convert the key definition's display coordinates into touch coordinates for a hit box
  1.3355 +        int32_t halfWidth = virtualKeyDefinition.width / 2;
  1.3356 +        int32_t halfHeight = virtualKeyDefinition.height / 2;
  1.3357 +
  1.3358 +        virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
  1.3359 +                * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
  1.3360 +        virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
  1.3361 +                * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
  1.3362 +        virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
  1.3363 +                * touchScreenHeight / mSurfaceHeight + touchScreenTop;
  1.3364 +        virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
  1.3365 +                * touchScreenHeight / mSurfaceHeight + touchScreenTop;
  1.3366 +    }
  1.3367 +}
  1.3368 +
  1.3369 +void TouchInputMapper::dumpVirtualKeys(String8& dump) {
  1.3370 +    if (!mVirtualKeys.isEmpty()) {
  1.3371 +        dump.append(INDENT3 "Virtual Keys:\n");
  1.3372 +
  1.3373 +        for (size_t i = 0; i < mVirtualKeys.size(); i++) {
  1.3374 +            const VirtualKey& virtualKey = mVirtualKeys.itemAt(i);
  1.3375 +            dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
  1.3376 +                    "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
  1.3377 +                    i, virtualKey.scanCode, virtualKey.keyCode,
  1.3378 +                    virtualKey.hitLeft, virtualKey.hitRight,
  1.3379 +                    virtualKey.hitTop, virtualKey.hitBottom);
  1.3380 +        }
  1.3381 +    }
  1.3382 +}
  1.3383 +
  1.3384 +void TouchInputMapper::parseCalibration() {
  1.3385 +    const PropertyMap& in = getDevice()->getConfiguration();
  1.3386 +    Calibration& out = mCalibration;
  1.3387 +
  1.3388 +    // Size
  1.3389 +    out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
  1.3390 +    String8 sizeCalibrationString;
  1.3391 +    if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
  1.3392 +        if (sizeCalibrationString == "none") {
  1.3393 +            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
  1.3394 +        } else if (sizeCalibrationString == "geometric") {
  1.3395 +            out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
  1.3396 +        } else if (sizeCalibrationString == "diameter") {
  1.3397 +            out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER;
  1.3398 +        } else if (sizeCalibrationString == "box") {
  1.3399 +            out.sizeCalibration = Calibration::SIZE_CALIBRATION_BOX;
  1.3400 +        } else if (sizeCalibrationString == "area") {
  1.3401 +            out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA;
  1.3402 +        } else if (sizeCalibrationString != "default") {
  1.3403 +            ALOGW("Invalid value for touch.size.calibration: '%s'",
  1.3404 +                    sizeCalibrationString.string());
  1.3405 +        }
  1.3406 +    }
  1.3407 +
  1.3408 +    out.haveSizeScale = in.tryGetProperty(String8("touch.size.scale"),
  1.3409 +            out.sizeScale);
  1.3410 +    out.haveSizeBias = in.tryGetProperty(String8("touch.size.bias"),
  1.3411 +            out.sizeBias);
  1.3412 +    out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"),
  1.3413 +            out.sizeIsSummed);
  1.3414 +
  1.3415 +    // Pressure
  1.3416 +    out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
  1.3417 +    String8 pressureCalibrationString;
  1.3418 +    if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
  1.3419 +        if (pressureCalibrationString == "none") {
  1.3420 +            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
  1.3421 +        } else if (pressureCalibrationString == "physical") {
  1.3422 +            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
  1.3423 +        } else if (pressureCalibrationString == "amplitude") {
  1.3424 +            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
  1.3425 +        } else if (pressureCalibrationString != "default") {
  1.3426 +            ALOGW("Invalid value for touch.pressure.calibration: '%s'",
  1.3427 +                    pressureCalibrationString.string());
  1.3428 +        }
  1.3429 +    }
  1.3430 +
  1.3431 +    out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
  1.3432 +            out.pressureScale);
  1.3433 +
  1.3434 +    // Orientation
  1.3435 +    out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
  1.3436 +    String8 orientationCalibrationString;
  1.3437 +    if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
  1.3438 +        if (orientationCalibrationString == "none") {
  1.3439 +            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
  1.3440 +        } else if (orientationCalibrationString == "interpolated") {
  1.3441 +            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
  1.3442 +        } else if (orientationCalibrationString == "vector") {
  1.3443 +            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
  1.3444 +        } else if (orientationCalibrationString != "default") {
  1.3445 +            ALOGW("Invalid value for touch.orientation.calibration: '%s'",
  1.3446 +                    orientationCalibrationString.string());
  1.3447 +        }
  1.3448 +    }
  1.3449 +
  1.3450 +    // Distance
  1.3451 +    out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT;
  1.3452 +    String8 distanceCalibrationString;
  1.3453 +    if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
  1.3454 +        if (distanceCalibrationString == "none") {
  1.3455 +            out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
  1.3456 +        } else if (distanceCalibrationString == "scaled") {
  1.3457 +            out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
  1.3458 +        } else if (distanceCalibrationString != "default") {
  1.3459 +            ALOGW("Invalid value for touch.distance.calibration: '%s'",
  1.3460 +                    distanceCalibrationString.string());
  1.3461 +        }
  1.3462 +    }
  1.3463 +
  1.3464 +    out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"),
  1.3465 +            out.distanceScale);
  1.3466 +
  1.3467 +    out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_DEFAULT;
  1.3468 +    String8 coverageCalibrationString;
  1.3469 +    if (in.tryGetProperty(String8("touch.coverage.calibration"), coverageCalibrationString)) {
  1.3470 +        if (coverageCalibrationString == "none") {
  1.3471 +            out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
  1.3472 +        } else if (coverageCalibrationString == "box") {
  1.3473 +            out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_BOX;
  1.3474 +        } else if (coverageCalibrationString != "default") {
  1.3475 +            ALOGW("Invalid value for touch.coverage.calibration: '%s'",
  1.3476 +                    coverageCalibrationString.string());
  1.3477 +        }
  1.3478 +    }
  1.3479 +}
  1.3480 +
  1.3481 +void TouchInputMapper::resolveCalibration() {
  1.3482 +    // Size
  1.3483 +    if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) {
  1.3484 +        if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DEFAULT) {
  1.3485 +            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
  1.3486 +        }
  1.3487 +    } else {
  1.3488 +        mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
  1.3489 +    }
  1.3490 +
  1.3491 +    // Pressure
  1.3492 +    if (mRawPointerAxes.pressure.valid) {
  1.3493 +        if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DEFAULT) {
  1.3494 +            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
  1.3495 +        }
  1.3496 +    } else {
  1.3497 +        mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
  1.3498 +    }
  1.3499 +
  1.3500 +    // Orientation
  1.3501 +    if (mRawPointerAxes.orientation.valid) {
  1.3502 +        if (mCalibration.orientationCalibration == Calibration::ORIENTATION_CALIBRATION_DEFAULT) {
  1.3503 +            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
  1.3504 +        }
  1.3505 +    } else {
  1.3506 +        mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
  1.3507 +    }
  1.3508 +
  1.3509 +    // Distance
  1.3510 +    if (mRawPointerAxes.distance.valid) {
  1.3511 +        if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_DEFAULT) {
  1.3512 +            mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
  1.3513 +        }
  1.3514 +    } else {
  1.3515 +        mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
  1.3516 +    }
  1.3517 +
  1.3518 +    // Coverage
  1.3519 +    if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_DEFAULT) {
  1.3520 +        mCalibration.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
  1.3521 +    }
  1.3522 +}
  1.3523 +
  1.3524 +void TouchInputMapper::dumpCalibration(String8& dump) {
  1.3525 +    dump.append(INDENT3 "Calibration:\n");
  1.3526 +
  1.3527 +    // Size
  1.3528 +    switch (mCalibration.sizeCalibration) {
  1.3529 +    case Calibration::SIZE_CALIBRATION_NONE:
  1.3530 +        dump.append(INDENT4 "touch.size.calibration: none\n");
  1.3531 +        break;
  1.3532 +    case Calibration::SIZE_CALIBRATION_GEOMETRIC:
  1.3533 +        dump.append(INDENT4 "touch.size.calibration: geometric\n");
  1.3534 +        break;
  1.3535 +    case Calibration::SIZE_CALIBRATION_DIAMETER:
  1.3536 +        dump.append(INDENT4 "touch.size.calibration: diameter\n");
  1.3537 +        break;
  1.3538 +    case Calibration::SIZE_CALIBRATION_BOX:
  1.3539 +        dump.append(INDENT4 "touch.size.calibration: box\n");
  1.3540 +        break;
  1.3541 +    case Calibration::SIZE_CALIBRATION_AREA:
  1.3542 +        dump.append(INDENT4 "touch.size.calibration: area\n");
  1.3543 +        break;
  1.3544 +    default:
  1.3545 +        ALOG_ASSERT(false);
  1.3546 +    }
  1.3547 +
  1.3548 +    if (mCalibration.haveSizeScale) {
  1.3549 +        dump.appendFormat(INDENT4 "touch.size.scale: %0.3f\n",
  1.3550 +                mCalibration.sizeScale);
  1.3551 +    }
  1.3552 +
  1.3553 +    if (mCalibration.haveSizeBias) {
  1.3554 +        dump.appendFormat(INDENT4 "touch.size.bias: %0.3f\n",
  1.3555 +                mCalibration.sizeBias);
  1.3556 +    }
  1.3557 +
  1.3558 +    if (mCalibration.haveSizeIsSummed) {
  1.3559 +        dump.appendFormat(INDENT4 "touch.size.isSummed: %s\n",
  1.3560 +                toString(mCalibration.sizeIsSummed));
  1.3561 +    }
  1.3562 +
  1.3563 +    // Pressure
  1.3564 +    switch (mCalibration.pressureCalibration) {
  1.3565 +    case Calibration::PRESSURE_CALIBRATION_NONE:
  1.3566 +        dump.append(INDENT4 "touch.pressure.calibration: none\n");
  1.3567 +        break;
  1.3568 +    case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
  1.3569 +        dump.append(INDENT4 "touch.pressure.calibration: physical\n");
  1.3570 +        break;
  1.3571 +    case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
  1.3572 +        dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
  1.3573 +        break;
  1.3574 +    default:
  1.3575 +        ALOG_ASSERT(false);
  1.3576 +    }
  1.3577 +
  1.3578 +    if (mCalibration.havePressureScale) {
  1.3579 +        dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
  1.3580 +                mCalibration.pressureScale);
  1.3581 +    }
  1.3582 +
  1.3583 +    // Orientation
  1.3584 +    switch (mCalibration.orientationCalibration) {
  1.3585 +    case Calibration::ORIENTATION_CALIBRATION_NONE:
  1.3586 +        dump.append(INDENT4 "touch.orientation.calibration: none\n");
  1.3587 +        break;
  1.3588 +    case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
  1.3589 +        dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
  1.3590 +        break;
  1.3591 +    case Calibration::ORIENTATION_CALIBRATION_VECTOR:
  1.3592 +        dump.append(INDENT4 "touch.orientation.calibration: vector\n");
  1.3593 +        break;
  1.3594 +    default:
  1.3595 +        ALOG_ASSERT(false);
  1.3596 +    }
  1.3597 +
  1.3598 +    // Distance
  1.3599 +    switch (mCalibration.distanceCalibration) {
  1.3600 +    case Calibration::DISTANCE_CALIBRATION_NONE:
  1.3601 +        dump.append(INDENT4 "touch.distance.calibration: none\n");
  1.3602 +        break;
  1.3603 +    case Calibration::DISTANCE_CALIBRATION_SCALED:
  1.3604 +        dump.append(INDENT4 "touch.distance.calibration: scaled\n");
  1.3605 +        break;
  1.3606 +    default:
  1.3607 +        ALOG_ASSERT(false);
  1.3608 +    }
  1.3609 +
  1.3610 +    if (mCalibration.haveDistanceScale) {
  1.3611 +        dump.appendFormat(INDENT4 "touch.distance.scale: %0.3f\n",
  1.3612 +                mCalibration.distanceScale);
  1.3613 +    }
  1.3614 +
  1.3615 +    switch (mCalibration.coverageCalibration) {
  1.3616 +    case Calibration::COVERAGE_CALIBRATION_NONE:
  1.3617 +        dump.append(INDENT4 "touch.coverage.calibration: none\n");
  1.3618 +        break;
  1.3619 +    case Calibration::COVERAGE_CALIBRATION_BOX:
  1.3620 +        dump.append(INDENT4 "touch.coverage.calibration: box\n");
  1.3621 +        break;
  1.3622 +    default:
  1.3623 +        ALOG_ASSERT(false);
  1.3624 +    }
  1.3625 +}
  1.3626 +
  1.3627 +void TouchInputMapper::reset(nsecs_t when) {
  1.3628 +    mCursorButtonAccumulator.reset(getDevice());
  1.3629 +    mCursorScrollAccumulator.reset(getDevice());
  1.3630 +    mTouchButtonAccumulator.reset(getDevice());
  1.3631 +
  1.3632 +    mPointerVelocityControl.reset();
  1.3633 +    mWheelXVelocityControl.reset();
  1.3634 +    mWheelYVelocityControl.reset();
  1.3635 +
  1.3636 +    mCurrentRawPointerData.clear();
  1.3637 +    mLastRawPointerData.clear();
  1.3638 +    mCurrentCookedPointerData.clear();
  1.3639 +    mLastCookedPointerData.clear();
  1.3640 +    mCurrentButtonState = 0;
  1.3641 +    mLastButtonState = 0;
  1.3642 +    mCurrentRawVScroll = 0;
  1.3643 +    mCurrentRawHScroll = 0;
  1.3644 +    mCurrentFingerIdBits.clear();
  1.3645 +    mLastFingerIdBits.clear();
  1.3646 +    mCurrentStylusIdBits.clear();
  1.3647 +    mLastStylusIdBits.clear();
  1.3648 +    mCurrentMouseIdBits.clear();
  1.3649 +    mLastMouseIdBits.clear();
  1.3650 +    mPointerUsage = POINTER_USAGE_NONE;
  1.3651 +    mSentHoverEnter = false;
  1.3652 +    mDownTime = 0;
  1.3653 +
  1.3654 +    mCurrentVirtualKey.down = false;
  1.3655 +
  1.3656 +    mPointerGesture.reset();
  1.3657 +    mPointerSimple.reset();
  1.3658 +
  1.3659 +    if (mPointerController != NULL) {
  1.3660 +        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
  1.3661 +        mPointerController->clearSpots();
  1.3662 +    }
  1.3663 +
  1.3664 +    InputMapper::reset(when);
  1.3665 +}
  1.3666 +
  1.3667 +void TouchInputMapper::process(const RawEvent* rawEvent) {
  1.3668 +    mCursorButtonAccumulator.process(rawEvent);
  1.3669 +    mCursorScrollAccumulator.process(rawEvent);
  1.3670 +    mTouchButtonAccumulator.process(rawEvent);
  1.3671 +
  1.3672 +    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
  1.3673 +        sync(rawEvent->when);
  1.3674 +    }
  1.3675 +}
  1.3676 +
  1.3677 +void TouchInputMapper::sync(nsecs_t when) {
  1.3678 +    // Sync button state.
  1.3679 +    mCurrentButtonState = mTouchButtonAccumulator.getButtonState()
  1.3680 +            | mCursorButtonAccumulator.getButtonState();
  1.3681 +
  1.3682 +    // Sync scroll state.
  1.3683 +    mCurrentRawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
  1.3684 +    mCurrentRawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
  1.3685 +    mCursorScrollAccumulator.finishSync();
  1.3686 +
  1.3687 +    // Sync touch state.
  1.3688 +    bool havePointerIds = true;
  1.3689 +    mCurrentRawPointerData.clear();
  1.3690 +    syncTouch(when, &havePointerIds);
  1.3691 +
  1.3692 +#if DEBUG_RAW_EVENTS
  1.3693 +    if (!havePointerIds) {
  1.3694 +        ALOGD("syncTouch: pointerCount %d -> %d, no pointer ids",
  1.3695 +                mLastRawPointerData.pointerCount,
  1.3696 +                mCurrentRawPointerData.pointerCount);
  1.3697 +    } else {
  1.3698 +        ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
  1.3699 +                "hovering ids 0x%08x -> 0x%08x",
  1.3700 +                mLastRawPointerData.pointerCount,
  1.3701 +                mCurrentRawPointerData.pointerCount,
  1.3702 +                mLastRawPointerData.touchingIdBits.value,
  1.3703 +                mCurrentRawPointerData.touchingIdBits.value,
  1.3704 +                mLastRawPointerData.hoveringIdBits.value,
  1.3705 +                mCurrentRawPointerData.hoveringIdBits.value);
  1.3706 +    }
  1.3707 +#endif
  1.3708 +
  1.3709 +    // Reset state that we will compute below.
  1.3710 +    mCurrentFingerIdBits.clear();
  1.3711 +    mCurrentStylusIdBits.clear();
  1.3712 +    mCurrentMouseIdBits.clear();
  1.3713 +    mCurrentCookedPointerData.clear();
  1.3714 +
  1.3715 +    if (mDeviceMode == DEVICE_MODE_DISABLED) {
  1.3716 +        // Drop all input if the device is disabled.
  1.3717 +        mCurrentRawPointerData.clear();
  1.3718 +        mCurrentButtonState = 0;
  1.3719 +    } else {
  1.3720 +        // Preprocess pointer data.
  1.3721 +        if (!havePointerIds) {
  1.3722 +            assignPointerIds();
  1.3723 +        }
  1.3724 +
  1.3725 +        // Handle policy on initial down or hover events.
  1.3726 +        uint32_t policyFlags = 0;
  1.3727 +        bool initialDown = mLastRawPointerData.pointerCount == 0
  1.3728 +                && mCurrentRawPointerData.pointerCount != 0;
  1.3729 +        bool buttonsPressed = mCurrentButtonState & ~mLastButtonState;
  1.3730 +        if (initialDown || buttonsPressed) {
  1.3731 +            // If this is a touch screen, hide the pointer on an initial down.
  1.3732 +            if (mDeviceMode == DEVICE_MODE_DIRECT) {
  1.3733 +                getContext()->fadePointer();
  1.3734 +            }
  1.3735 +
  1.3736 +            // Initial downs on external touch devices should wake the device.
  1.3737 +            // We don't do this for internal touch screens to prevent them from waking
  1.3738 +            // up in your pocket.
  1.3739 +            // TODO: Use the input device configuration to control this behavior more finely.
  1.3740 +            if (getDevice()->isExternal()) {
  1.3741 +                policyFlags |= POLICY_FLAG_WAKE_DROPPED;
  1.3742 +            }
  1.3743 +        }
  1.3744 +
  1.3745 +        // Synthesize key down from raw buttons if needed.
  1.3746 +        synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
  1.3747 +                policyFlags, mLastButtonState, mCurrentButtonState);
  1.3748 +
  1.3749 +        // Consume raw off-screen touches before cooking pointer data.
  1.3750 +        // If touches are consumed, subsequent code will not receive any pointer data.
  1.3751 +        if (consumeRawTouches(when, policyFlags)) {
  1.3752 +            mCurrentRawPointerData.clear();
  1.3753 +        }
  1.3754 +
  1.3755 +        // Cook pointer data.  This call populates the mCurrentCookedPointerData structure
  1.3756 +        // with cooked pointer data that has the same ids and indices as the raw data.
  1.3757 +        // The following code can use either the raw or cooked data, as needed.
  1.3758 +        cookPointerData();
  1.3759 +
  1.3760 +        // Dispatch the touches either directly or by translation through a pointer on screen.
  1.3761 +        if (mDeviceMode == DEVICE_MODE_POINTER) {
  1.3762 +            for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); !idBits.isEmpty(); ) {
  1.3763 +                uint32_t id = idBits.clearFirstMarkedBit();
  1.3764 +                const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
  1.3765 +                if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
  1.3766 +                        || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
  1.3767 +                    mCurrentStylusIdBits.markBit(id);
  1.3768 +                } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
  1.3769 +                        || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
  1.3770 +                    mCurrentFingerIdBits.markBit(id);
  1.3771 +                } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
  1.3772 +                    mCurrentMouseIdBits.markBit(id);
  1.3773 +                }
  1.3774 +            }
  1.3775 +            for (BitSet32 idBits(mCurrentRawPointerData.hoveringIdBits); !idBits.isEmpty(); ) {
  1.3776 +                uint32_t id = idBits.clearFirstMarkedBit();
  1.3777 +                const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
  1.3778 +                if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
  1.3779 +                        || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
  1.3780 +                    mCurrentStylusIdBits.markBit(id);
  1.3781 +                }
  1.3782 +            }
  1.3783 +
  1.3784 +            // Stylus takes precedence over all tools, then mouse, then finger.
  1.3785 +            PointerUsage pointerUsage = mPointerUsage;
  1.3786 +            if (!mCurrentStylusIdBits.isEmpty()) {
  1.3787 +                mCurrentMouseIdBits.clear();
  1.3788 +                mCurrentFingerIdBits.clear();
  1.3789 +                pointerUsage = POINTER_USAGE_STYLUS;
  1.3790 +            } else if (!mCurrentMouseIdBits.isEmpty()) {
  1.3791 +                mCurrentFingerIdBits.clear();
  1.3792 +                pointerUsage = POINTER_USAGE_MOUSE;
  1.3793 +            } else if (!mCurrentFingerIdBits.isEmpty() || isPointerDown(mCurrentButtonState)) {
  1.3794 +                pointerUsage = POINTER_USAGE_GESTURES;
  1.3795 +            }
  1.3796 +
  1.3797 +            dispatchPointerUsage(when, policyFlags, pointerUsage);
  1.3798 +        } else {
  1.3799 +            if (mDeviceMode == DEVICE_MODE_DIRECT
  1.3800 +                    && mConfig.showTouches && mPointerController != NULL) {
  1.3801 +                mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
  1.3802 +                mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
  1.3803 +
  1.3804 +                mPointerController->setButtonState(mCurrentButtonState);
  1.3805 +                mPointerController->setSpots(mCurrentCookedPointerData.pointerCoords,
  1.3806 +                        mCurrentCookedPointerData.idToIndex,
  1.3807 +                        mCurrentCookedPointerData.touchingIdBits);
  1.3808 +            }
  1.3809 +
  1.3810 +            dispatchHoverExit(when, policyFlags);
  1.3811 +            dispatchTouches(when, policyFlags);
  1.3812 +            dispatchHoverEnterAndMove(when, policyFlags);
  1.3813 +        }
  1.3814 +
  1.3815 +        // Synthesize key up from raw buttons if needed.
  1.3816 +        synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
  1.3817 +                policyFlags, mLastButtonState, mCurrentButtonState);
  1.3818 +    }
  1.3819 +
  1.3820 +    // Copy current touch to last touch in preparation for the next cycle.
  1.3821 +    mLastRawPointerData.copyFrom(mCurrentRawPointerData);
  1.3822 +    mLastCookedPointerData.copyFrom(mCurrentCookedPointerData);
  1.3823 +    mLastButtonState = mCurrentButtonState;
  1.3824 +    mLastFingerIdBits = mCurrentFingerIdBits;
  1.3825 +    mLastStylusIdBits = mCurrentStylusIdBits;
  1.3826 +    mLastMouseIdBits = mCurrentMouseIdBits;
  1.3827 +
  1.3828 +    // Clear some transient state.
  1.3829 +    mCurrentRawVScroll = 0;
  1.3830 +    mCurrentRawHScroll = 0;
  1.3831 +}
  1.3832 +
  1.3833 +void TouchInputMapper::timeoutExpired(nsecs_t when) {
  1.3834 +    if (mDeviceMode == DEVICE_MODE_POINTER) {
  1.3835 +        if (mPointerUsage == POINTER_USAGE_GESTURES) {
  1.3836 +            dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
  1.3837 +        }
  1.3838 +    }
  1.3839 +}
  1.3840 +
  1.3841 +bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) {
  1.3842 +    // Check for release of a virtual key.
  1.3843 +    if (mCurrentVirtualKey.down) {
  1.3844 +        if (mCurrentRawPointerData.touchingIdBits.isEmpty()) {
  1.3845 +            // Pointer went up while virtual key was down.
  1.3846 +            mCurrentVirtualKey.down = false;
  1.3847 +            if (!mCurrentVirtualKey.ignored) {
  1.3848 +#if DEBUG_VIRTUAL_KEYS
  1.3849 +                ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
  1.3850 +                        mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
  1.3851 +#endif
  1.3852 +                dispatchVirtualKey(when, policyFlags,
  1.3853 +                        AKEY_EVENT_ACTION_UP,
  1.3854 +                        AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
  1.3855 +            }
  1.3856 +            return true;
  1.3857 +        }
  1.3858 +
  1.3859 +        if (mCurrentRawPointerData.touchingIdBits.count() == 1) {
  1.3860 +            uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit();
  1.3861 +            const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
  1.3862 +            const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
  1.3863 +            if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) {
  1.3864 +                // Pointer is still within the space of the virtual key.
  1.3865 +                return true;
  1.3866 +            }
  1.3867 +        }
  1.3868 +
  1.3869 +        // Pointer left virtual key area or another pointer also went down.
  1.3870 +        // Send key cancellation but do not consume the touch yet.
  1.3871 +        // This is useful when the user swipes through from the virtual key area
  1.3872 +        // into the main display surface.
  1.3873 +        mCurrentVirtualKey.down = false;
  1.3874 +        if (!mCurrentVirtualKey.ignored) {
  1.3875 +#if DEBUG_VIRTUAL_KEYS
  1.3876 +            ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
  1.3877 +                    mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
  1.3878 +#endif
  1.3879 +            dispatchVirtualKey(when, policyFlags,
  1.3880 +                    AKEY_EVENT_ACTION_UP,
  1.3881 +                    AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
  1.3882 +                            | AKEY_EVENT_FLAG_CANCELED);
  1.3883 +        }
  1.3884 +    }
  1.3885 +
  1.3886 +    if (mLastRawPointerData.touchingIdBits.isEmpty()
  1.3887 +            && !mCurrentRawPointerData.touchingIdBits.isEmpty()) {
  1.3888 +        // Pointer just went down.  Check for virtual key press or off-screen touches.
  1.3889 +        uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit();
  1.3890 +        const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
  1.3891 +        if (!isPointInsideSurface(pointer.x, pointer.y)) {
  1.3892 +            // If exactly one pointer went down, check for virtual key hit.
  1.3893 +            // Otherwise we will drop the entire stroke.
  1.3894 +            if (mCurrentRawPointerData.touchingIdBits.count() == 1) {
  1.3895 +                const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
  1.3896 +                if (virtualKey) {
  1.3897 +                    mCurrentVirtualKey.down = true;
  1.3898 +                    mCurrentVirtualKey.downTime = when;
  1.3899 +                    mCurrentVirtualKey.keyCode = virtualKey->keyCode;
  1.3900 +                    mCurrentVirtualKey.scanCode = virtualKey->scanCode;
  1.3901 +                    mCurrentVirtualKey.ignored = mContext->shouldDropVirtualKey(
  1.3902 +                            when, getDevice(), virtualKey->keyCode, virtualKey->scanCode);
  1.3903 +
  1.3904 +                    if (!mCurrentVirtualKey.ignored) {
  1.3905 +#if DEBUG_VIRTUAL_KEYS
  1.3906 +                        ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
  1.3907 +                                mCurrentVirtualKey.keyCode,
  1.3908 +                                mCurrentVirtualKey.scanCode);
  1.3909 +#endif
  1.3910 +                        dispatchVirtualKey(when, policyFlags,
  1.3911 +                                AKEY_EVENT_ACTION_DOWN,
  1.3912 +                                AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
  1.3913 +                    }
  1.3914 +                }
  1.3915 +            }
  1.3916 +            return true;
  1.3917 +        }
  1.3918 +    }
  1.3919 +
  1.3920 +    // Disable all virtual key touches that happen within a short time interval of the
  1.3921 +    // most recent touch within the screen area.  The idea is to filter out stray
  1.3922 +    // virtual key presses when interacting with the touch screen.
  1.3923 +    //
  1.3924 +    // Problems we're trying to solve:
  1.3925 +    //
  1.3926 +    // 1. While scrolling a list or dragging the window shade, the user swipes down into a
  1.3927 +    //    virtual key area that is implemented by a separate touch panel and accidentally
  1.3928 +    //    triggers a virtual key.
  1.3929 +    //
  1.3930 +    // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
  1.3931 +    //    area and accidentally triggers a virtual key.  This often happens when virtual keys
  1.3932 +    //    are layed out below the screen near to where the on screen keyboard's space bar
  1.3933 +    //    is displayed.
  1.3934 +    if (mConfig.virtualKeyQuietTime > 0 && !mCurrentRawPointerData.touchingIdBits.isEmpty()) {
  1.3935 +        mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime);
  1.3936 +    }
  1.3937 +    return false;
  1.3938 +}
  1.3939 +
  1.3940 +void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
  1.3941 +        int32_t keyEventAction, int32_t keyEventFlags) {
  1.3942 +    int32_t keyCode = mCurrentVirtualKey.keyCode;
  1.3943 +    int32_t scanCode = mCurrentVirtualKey.scanCode;
  1.3944 +    nsecs_t downTime = mCurrentVirtualKey.downTime;
  1.3945 +    int32_t metaState = mContext->getGlobalMetaState();
  1.3946 +    policyFlags |= POLICY_FLAG_VIRTUAL;
  1.3947 +
  1.3948 +    NotifyKeyArgs args(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
  1.3949 +            keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
  1.3950 +    getListener()->notifyKey(&args);
  1.3951 +}
  1.3952 +
  1.3953 +void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
  1.3954 +    BitSet32 currentIdBits = mCurrentCookedPointerData.touchingIdBits;
  1.3955 +    BitSet32 lastIdBits = mLastCookedPointerData.touchingIdBits;
  1.3956 +    int32_t metaState = getContext()->getGlobalMetaState();
  1.3957 +    int32_t buttonState = mCurrentButtonState;
  1.3958 +
  1.3959 +    if (currentIdBits == lastIdBits) {
  1.3960 +        if (!currentIdBits.isEmpty()) {
  1.3961 +            // No pointer id changes so this is a move event.
  1.3962 +            // The listener takes care of batching moves so we don't have to deal with that here.
  1.3963 +            dispatchMotion(when, policyFlags, mSource,
  1.3964 +                    AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState,
  1.3965 +                    AMOTION_EVENT_EDGE_FLAG_NONE,
  1.3966 +                    mCurrentCookedPointerData.pointerProperties,
  1.3967 +                    mCurrentCookedPointerData.pointerCoords,
  1.3968 +                    mCurrentCookedPointerData.idToIndex,
  1.3969 +                    currentIdBits, -1,
  1.3970 +                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
  1.3971 +        }
  1.3972 +    } else {
  1.3973 +        // There may be pointers going up and pointers going down and pointers moving
  1.3974 +        // all at the same time.
  1.3975 +        BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
  1.3976 +        BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
  1.3977 +        BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
  1.3978 +        BitSet32 dispatchedIdBits(lastIdBits.value);
  1.3979 +
  1.3980 +        // Update last coordinates of pointers that have moved so that we observe the new
  1.3981 +        // pointer positions at the same time as other pointers that have just gone up.
  1.3982 +        bool moveNeeded = updateMovedPointers(
  1.3983 +                mCurrentCookedPointerData.pointerProperties,
  1.3984 +                mCurrentCookedPointerData.pointerCoords,
  1.3985 +                mCurrentCookedPointerData.idToIndex,
  1.3986 +                mLastCookedPointerData.pointerProperties,
  1.3987 +                mLastCookedPointerData.pointerCoords,
  1.3988 +                mLastCookedPointerData.idToIndex,
  1.3989 +                moveIdBits);
  1.3990 +        if (buttonState != mLastButtonState) {
  1.3991 +            moveNeeded = true;
  1.3992 +        }
  1.3993 +
  1.3994 +        // Dispatch pointer up events.
  1.3995 +        while (!upIdBits.isEmpty()) {
  1.3996 +            uint32_t upId = upIdBits.clearFirstMarkedBit();
  1.3997 +
  1.3998 +            dispatchMotion(when, policyFlags, mSource,
  1.3999 +                    AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0,
  1.4000 +                    mLastCookedPointerData.pointerProperties,
  1.4001 +                    mLastCookedPointerData.pointerCoords,
  1.4002 +                    mLastCookedPointerData.idToIndex,
  1.4003 +                    dispatchedIdBits, upId,
  1.4004 +                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
  1.4005 +            dispatchedIdBits.clearBit(upId);
  1.4006 +        }
  1.4007 +
  1.4008 +        // Dispatch move events if any of the remaining pointers moved from their old locations.
  1.4009 +        // Although applications receive new locations as part of individual pointer up
  1.4010 +        // events, they do not generally handle them except when presented in a move event.
  1.4011 +        if (moveNeeded) {
  1.4012 +            ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
  1.4013 +            dispatchMotion(when, policyFlags, mSource,
  1.4014 +                    AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0,
  1.4015 +                    mCurrentCookedPointerData.pointerProperties,
  1.4016 +                    mCurrentCookedPointerData.pointerCoords,
  1.4017 +                    mCurrentCookedPointerData.idToIndex,
  1.4018 +                    dispatchedIdBits, -1,
  1.4019 +                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
  1.4020 +        }
  1.4021 +
  1.4022 +        // Dispatch pointer down events using the new pointer locations.
  1.4023 +        while (!downIdBits.isEmpty()) {
  1.4024 +            uint32_t downId = downIdBits.clearFirstMarkedBit();
  1.4025 +            dispatchedIdBits.markBit(downId);
  1.4026 +
  1.4027 +            if (dispatchedIdBits.count() == 1) {
  1.4028 +                // First pointer is going down.  Set down time.
  1.4029 +                mDownTime = when;
  1.4030 +            }
  1.4031 +
  1.4032 +            dispatchMotion(when, policyFlags, mSource,
  1.4033 +                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
  1.4034 +                    mCurrentCookedPointerData.pointerProperties,
  1.4035 +                    mCurrentCookedPointerData.pointerCoords,
  1.4036 +                    mCurrentCookedPointerData.idToIndex,
  1.4037 +                    dispatchedIdBits, downId,
  1.4038 +                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
  1.4039 +        }
  1.4040 +    }
  1.4041 +}
  1.4042 +
  1.4043 +void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) {
  1.4044 +    if (mSentHoverEnter &&
  1.4045 +            (mCurrentCookedPointerData.hoveringIdBits.isEmpty()
  1.4046 +                    || !mCurrentCookedPointerData.touchingIdBits.isEmpty())) {
  1.4047 +        int32_t metaState = getContext()->getGlobalMetaState();
  1.4048 +        dispatchMotion(when, policyFlags, mSource,
  1.4049 +                AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
  1.4050 +                mLastCookedPointerData.pointerProperties,
  1.4051 +                mLastCookedPointerData.pointerCoords,
  1.4052 +                mLastCookedPointerData.idToIndex,
  1.4053 +                mLastCookedPointerData.hoveringIdBits, -1,
  1.4054 +                mOrientedXPrecision, mOrientedYPrecision, mDownTime);
  1.4055 +        mSentHoverEnter = false;
  1.4056 +    }
  1.4057 +}
  1.4058 +
  1.4059 +void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) {
  1.4060 +    if (mCurrentCookedPointerData.touchingIdBits.isEmpty()
  1.4061 +            && !mCurrentCookedPointerData.hoveringIdBits.isEmpty()) {
  1.4062 +        int32_t metaState = getContext()->getGlobalMetaState();
  1.4063 +        if (!mSentHoverEnter) {
  1.4064 +            dispatchMotion(when, policyFlags, mSource,
  1.4065 +                    AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
  1.4066 +                    mCurrentCookedPointerData.pointerProperties,
  1.4067 +                    mCurrentCookedPointerData.pointerCoords,
  1.4068 +                    mCurrentCookedPointerData.idToIndex,
  1.4069 +                    mCurrentCookedPointerData.hoveringIdBits, -1,
  1.4070 +                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
  1.4071 +            mSentHoverEnter = true;
  1.4072 +        }
  1.4073 +
  1.4074 +        dispatchMotion(when, policyFlags, mSource,
  1.4075 +                AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
  1.4076 +                mCurrentCookedPointerData.pointerProperties,
  1.4077 +                mCurrentCookedPointerData.pointerCoords,
  1.4078 +                mCurrentCookedPointerData.idToIndex,
  1.4079 +                mCurrentCookedPointerData.hoveringIdBits, -1,
  1.4080 +                mOrientedXPrecision, mOrientedYPrecision, mDownTime);
  1.4081 +    }
  1.4082 +}
  1.4083 +
  1.4084 +void TouchInputMapper::cookPointerData() {
  1.4085 +    uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount;
  1.4086 +
  1.4087 +    mCurrentCookedPointerData.clear();
  1.4088 +    mCurrentCookedPointerData.pointerCount = currentPointerCount;
  1.4089 +    mCurrentCookedPointerData.hoveringIdBits = mCurrentRawPointerData.hoveringIdBits;
  1.4090 +    mCurrentCookedPointerData.touchingIdBits = mCurrentRawPointerData.touchingIdBits;
  1.4091 +
  1.4092 +    // Walk through the the active pointers and map device coordinates onto
  1.4093 +    // surface coordinates and adjust for display orientation.
  1.4094 +    for (uint32_t i = 0; i < currentPointerCount; i++) {
  1.4095 +        const RawPointerData::Pointer& in = mCurrentRawPointerData.pointers[i];
  1.4096 +
  1.4097 +        // Size
  1.4098 +        float touchMajor, touchMinor, toolMajor, toolMinor, size;
  1.4099 +        switch (mCalibration.sizeCalibration) {
  1.4100 +        case Calibration::SIZE_CALIBRATION_GEOMETRIC:
  1.4101 +        case Calibration::SIZE_CALIBRATION_DIAMETER:
  1.4102 +        case Calibration::SIZE_CALIBRATION_BOX:
  1.4103 +        case Calibration::SIZE_CALIBRATION_AREA:
  1.4104 +            if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
  1.4105 +                touchMajor = in.touchMajor;
  1.4106 +                touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
  1.4107 +                toolMajor = in.toolMajor;
  1.4108 +                toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
  1.4109 +                size = mRawPointerAxes.touchMinor.valid
  1.4110 +                        ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
  1.4111 +            } else if (mRawPointerAxes.touchMajor.valid) {
  1.4112 +                toolMajor = touchMajor = in.touchMajor;
  1.4113 +                toolMinor = touchMinor = mRawPointerAxes.touchMinor.valid
  1.4114 +                        ? in.touchMinor : in.touchMajor;
  1.4115 +                size = mRawPointerAxes.touchMinor.valid
  1.4116 +                        ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
  1.4117 +            } else if (mRawPointerAxes.toolMajor.valid) {
  1.4118 +                touchMajor = toolMajor = in.toolMajor;
  1.4119 +                touchMinor = toolMinor = mRawPointerAxes.toolMinor.valid
  1.4120 +                        ? in.toolMinor : in.toolMajor;
  1.4121 +                size = mRawPointerAxes.toolMinor.valid
  1.4122 +                        ? avg(in.toolMajor, in.toolMinor) : in.toolMajor;
  1.4123 +            } else {
  1.4124 +                ALOG_ASSERT(false, "No touch or tool axes.  "
  1.4125 +                        "Size calibration should have been resolved to NONE.");
  1.4126 +                touchMajor = 0;
  1.4127 +                touchMinor = 0;
  1.4128 +                toolMajor = 0;
  1.4129 +                toolMinor = 0;
  1.4130 +                size = 0;
  1.4131 +            }
  1.4132 +
  1.4133 +            if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) {
  1.4134 +                uint32_t touchingCount = mCurrentRawPointerData.touchingIdBits.count();
  1.4135 +                if (touchingCount > 1) {
  1.4136 +                    touchMajor /= touchingCount;
  1.4137 +                    touchMinor /= touchingCount;
  1.4138 +                    toolMajor /= touchingCount;
  1.4139 +                    toolMinor /= touchingCount;
  1.4140 +                    size /= touchingCount;
  1.4141 +                }
  1.4142 +            }
  1.4143 +
  1.4144 +            if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) {
  1.4145 +                touchMajor *= mGeometricScale;
  1.4146 +                touchMinor *= mGeometricScale;
  1.4147 +                toolMajor *= mGeometricScale;
  1.4148 +                toolMinor *= mGeometricScale;
  1.4149 +            } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) {
  1.4150 +                touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
  1.4151 +                touchMinor = touchMajor;
  1.4152 +                toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
  1.4153 +                toolMinor = toolMajor;
  1.4154 +            } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) {
  1.4155 +                touchMinor = touchMajor;
  1.4156 +                toolMinor = toolMajor;
  1.4157 +            }
  1.4158 +
  1.4159 +            mCalibration.applySizeScaleAndBias(&touchMajor);
  1.4160 +            mCalibration.applySizeScaleAndBias(&touchMinor);
  1.4161 +            mCalibration.applySizeScaleAndBias(&toolMajor);
  1.4162 +            mCalibration.applySizeScaleAndBias(&toolMinor);
  1.4163 +            size *= mSizeScale;
  1.4164 +            break;
  1.4165 +        default:
  1.4166 +            touchMajor = 0;
  1.4167 +            touchMinor = 0;
  1.4168 +            toolMajor = 0;
  1.4169 +            toolMinor = 0;
  1.4170 +            size = 0;
  1.4171 +            break;
  1.4172 +        }
  1.4173 +
  1.4174 +        // Pressure
  1.4175 +        float pressure;
  1.4176 +        switch (mCalibration.pressureCalibration) {
  1.4177 +        case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
  1.4178 +        case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
  1.4179 +            pressure = in.pressure * mPressureScale;
  1.4180 +            break;
  1.4181 +        default:
  1.4182 +            pressure = in.isHovering ? 0 : 1;
  1.4183 +            break;
  1.4184 +        }
  1.4185 +
  1.4186 +        // Tilt and Orientation
  1.4187 +        float tilt;
  1.4188 +        float orientation;
  1.4189 +        if (mHaveTilt) {
  1.4190 +            float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;
  1.4191 +            float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;
  1.4192 +            orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
  1.4193 +            tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
  1.4194 +        } else {
  1.4195 +            tilt = 0;
  1.4196 +
  1.4197 +            switch (mCalibration.orientationCalibration) {
  1.4198 +            case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
  1.4199 +                orientation = in.orientation * mOrientationScale;
  1.4200 +                break;
  1.4201 +            case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
  1.4202 +                int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
  1.4203 +                int32_t c2 = signExtendNybble(in.orientation & 0x0f);
  1.4204 +                if (c1 != 0 || c2 != 0) {
  1.4205 +                    orientation = atan2f(c1, c2) * 0.5f;
  1.4206 +                    float confidence = hypotf(c1, c2);
  1.4207 +                    float scale = 1.0f + confidence / 16.0f;
  1.4208 +                    touchMajor *= scale;
  1.4209 +                    touchMinor /= scale;
  1.4210 +                    toolMajor *= scale;
  1.4211 +                    toolMinor /= scale;
  1.4212 +                } else {
  1.4213 +                    orientation = 0;
  1.4214 +                }
  1.4215 +                break;
  1.4216 +            }
  1.4217 +            default:
  1.4218 +                orientation = 0;
  1.4219 +            }
  1.4220 +        }
  1.4221 +
  1.4222 +        // Distance
  1.4223 +        float distance;
  1.4224 +        switch (mCalibration.distanceCalibration) {
  1.4225 +        case Calibration::DISTANCE_CALIBRATION_SCALED:
  1.4226 +            distance = in.distance * mDistanceScale;
  1.4227 +            break;
  1.4228 +        default:
  1.4229 +            distance = 0;
  1.4230 +        }
  1.4231 +
  1.4232 +        // Coverage
  1.4233 +        int32_t rawLeft, rawTop, rawRight, rawBottom;
  1.4234 +        switch (mCalibration.coverageCalibration) {
  1.4235 +        case Calibration::COVERAGE_CALIBRATION_BOX:
  1.4236 +            rawLeft = (in.toolMinor & 0xffff0000) >> 16;
  1.4237 +            rawRight = in.toolMinor & 0x0000ffff;
  1.4238 +            rawBottom = in.toolMajor & 0x0000ffff;
  1.4239 +            rawTop = (in.toolMajor & 0xffff0000) >> 16;
  1.4240 +            break;
  1.4241 +        default:
  1.4242 +            rawLeft = rawTop = rawRight = rawBottom = 0;
  1.4243 +            break;
  1.4244 +        }
  1.4245 +
  1.4246 +        // X, Y, and the bounding box for coverage information
  1.4247 +        // Adjust coords for surface orientation.
  1.4248 +        float x, y, left, top, right, bottom;
  1.4249 +        switch (mSurfaceOrientation) {
  1.4250 +        case DISPLAY_ORIENTATION_90:
  1.4251 +            x = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
  1.4252 +            y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate;
  1.4253 +            left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
  1.4254 +            right = float(rawBottom- mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
  1.4255 +            bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
  1.4256 +            top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
  1.4257 +            orientation -= M_PI_2;
  1.4258 +            if (orientation < - M_PI_2) {
  1.4259 +                orientation += M_PI;
  1.4260 +            }
  1.4261 +            break;
  1.4262 +        case DISPLAY_ORIENTATION_180:
  1.4263 +            x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate;
  1.4264 +            y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate;
  1.4265 +            left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
  1.4266 +            right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
  1.4267 +            bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
  1.4268 +            top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
  1.4269 +            break;
  1.4270 +        case DISPLAY_ORIENTATION_270:
  1.4271 +            x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate;
  1.4272 +            y = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
  1.4273 +            left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
  1.4274 +            right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
  1.4275 +            bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
  1.4276 +            top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
  1.4277 +            orientation += M_PI_2;
  1.4278 +            if (orientation > M_PI_2) {
  1.4279 +                orientation -= M_PI;
  1.4280 +            }
  1.4281 +            break;
  1.4282 +        default:
  1.4283 +            x = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
  1.4284 +            y = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
  1.4285 +            left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
  1.4286 +            right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
  1.4287 +            bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
  1.4288 +            top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
  1.4289 +            break;
  1.4290 +        }
  1.4291 +
  1.4292 +        // Write output coords.
  1.4293 +        PointerCoords& out = mCurrentCookedPointerData.pointerCoords[i];
  1.4294 +        out.clear();
  1.4295 +        out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
  1.4296 +        out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
  1.4297 +        out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
  1.4298 +        out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
  1.4299 +        out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
  1.4300 +        out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
  1.4301 +        out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
  1.4302 +        out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
  1.4303 +        out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
  1.4304 +        if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
  1.4305 +            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left);
  1.4306 +            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top);
  1.4307 +            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right);
  1.4308 +            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_4, bottom);
  1.4309 +        } else {
  1.4310 +            out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
  1.4311 +            out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
  1.4312 +        }
  1.4313 +
  1.4314 +        // Write output properties.
  1.4315 +        PointerProperties& properties = mCurrentCookedPointerData.pointerProperties[i];
  1.4316 +        uint32_t id = in.id;
  1.4317 +        properties.clear();
  1.4318 +        properties.id = id;
  1.4319 +        properties.toolType = in.toolType;
  1.4320 +
  1.4321 +        // Write id index.
  1.4322 +        mCurrentCookedPointerData.idToIndex[id] = i;
  1.4323 +    }
  1.4324 +}
  1.4325 +
  1.4326 +void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags,
  1.4327 +        PointerUsage pointerUsage) {
  1.4328 +    if (pointerUsage != mPointerUsage) {
  1.4329 +        abortPointerUsage(when, policyFlags);
  1.4330 +        mPointerUsage = pointerUsage;
  1.4331 +    }
  1.4332 +
  1.4333 +    switch (mPointerUsage) {
  1.4334 +    case POINTER_USAGE_GESTURES:
  1.4335 +        dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
  1.4336 +        break;
  1.4337 +    case POINTER_USAGE_STYLUS:
  1.4338 +        dispatchPointerStylus(when, policyFlags);
  1.4339 +        break;
  1.4340 +    case POINTER_USAGE_MOUSE:
  1.4341 +        dispatchPointerMouse(when, policyFlags);
  1.4342 +        break;
  1.4343 +    default:
  1.4344 +        break;
  1.4345 +    }
  1.4346 +}
  1.4347 +
  1.4348 +void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) {
  1.4349 +    switch (mPointerUsage) {
  1.4350 +    case POINTER_USAGE_GESTURES:
  1.4351 +        abortPointerGestures(when, policyFlags);
  1.4352 +        break;
  1.4353 +    case POINTER_USAGE_STYLUS:
  1.4354 +        abortPointerStylus(when, policyFlags);
  1.4355 +        break;
  1.4356 +    case POINTER_USAGE_MOUSE:
  1.4357 +        abortPointerMouse(when, policyFlags);
  1.4358 +        break;
  1.4359 +    default:
  1.4360 +        break;
  1.4361 +    }
  1.4362 +
  1.4363 +    mPointerUsage = POINTER_USAGE_NONE;
  1.4364 +}
  1.4365 +
  1.4366 +void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
  1.4367 +        bool isTimeout) {
  1.4368 +    // Update current gesture coordinates.
  1.4369 +    bool cancelPreviousGesture, finishPreviousGesture;
  1.4370 +    bool sendEvents = preparePointerGestures(when,
  1.4371 +            &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
  1.4372 +    if (!sendEvents) {
  1.4373 +        return;
  1.4374 +    }
  1.4375 +    if (finishPreviousGesture) {
  1.4376 +        cancelPreviousGesture = false;
  1.4377 +    }
  1.4378 +
  1.4379 +    // Update the pointer presentation and spots.
  1.4380 +    if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
  1.4381 +        mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
  1.4382 +        if (finishPreviousGesture || cancelPreviousGesture) {
  1.4383 +            mPointerController->clearSpots();
  1.4384 +        }
  1.4385 +        mPointerController->setSpots(mPointerGesture.currentGestureCoords,
  1.4386 +                mPointerGesture.currentGestureIdToIndex,
  1.4387 +                mPointerGesture.currentGestureIdBits);
  1.4388 +    } else {
  1.4389 +        mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
  1.4390 +    }
  1.4391 +
  1.4392 +    // Show or hide the pointer if needed.
  1.4393 +    switch (mPointerGesture.currentGestureMode) {
  1.4394 +    case PointerGesture::NEUTRAL:
  1.4395 +    case PointerGesture::QUIET:
  1.4396 +        if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
  1.4397 +                && (mPointerGesture.lastGestureMode == PointerGesture::SWIPE
  1.4398 +                        || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)) {
  1.4399 +            // Remind the user of where the pointer is after finishing a gesture with spots.
  1.4400 +            mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
  1.4401 +        }
  1.4402 +        break;
  1.4403 +    case PointerGesture::TAP:
  1.4404 +    case PointerGesture::TAP_DRAG:
  1.4405 +    case PointerGesture::BUTTON_CLICK_OR_DRAG:
  1.4406 +    case PointerGesture::HOVER:
  1.4407 +    case PointerGesture::PRESS:
  1.4408 +        // Unfade the pointer when the current gesture manipulates the
  1.4409 +        // area directly under the pointer.
  1.4410 +        mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
  1.4411 +        break;
  1.4412 +    case PointerGesture::SWIPE:
  1.4413 +    case PointerGesture::FREEFORM:
  1.4414 +        // Fade the pointer when the current gesture manipulates a different
  1.4415 +        // area and there are spots to guide the user experience.
  1.4416 +        if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
  1.4417 +            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
  1.4418 +        } else {
  1.4419 +            mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
  1.4420 +        }
  1.4421 +        break;
  1.4422 +    }
  1.4423 +
  1.4424 +    // Send events!
  1.4425 +    int32_t metaState = getContext()->getGlobalMetaState();
  1.4426 +    int32_t buttonState = mCurrentButtonState;
  1.4427 +
  1.4428 +    // Update last coordinates of pointers that have moved so that we observe the new
  1.4429 +    // pointer positions at the same time as other pointers that have just gone up.
  1.4430 +    bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP
  1.4431 +            || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG
  1.4432 +            || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
  1.4433 +            || mPointerGesture.currentGestureMode == PointerGesture::PRESS
  1.4434 +            || mPointerGesture.currentGestureMode == PointerGesture::SWIPE
  1.4435 +            || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
  1.4436 +    bool moveNeeded = false;
  1.4437 +    if (down && !cancelPreviousGesture && !finishPreviousGesture
  1.4438 +            && !mPointerGesture.lastGestureIdBits.isEmpty()
  1.4439 +            && !mPointerGesture.currentGestureIdBits.isEmpty()) {
  1.4440 +        BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value
  1.4441 +                & mPointerGesture.lastGestureIdBits.value);
  1.4442 +        moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties,
  1.4443 +                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
  1.4444 +                mPointerGesture.lastGestureProperties,
  1.4445 +                mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
  1.4446 +                movedGestureIdBits);
  1.4447 +        if (buttonState != mLastButtonState) {
  1.4448 +            moveNeeded = true;
  1.4449 +        }
  1.4450 +    }
  1.4451 +
  1.4452 +    // Send motion events for all pointers that went up or were canceled.
  1.4453 +    BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
  1.4454 +    if (!dispatchedGestureIdBits.isEmpty()) {
  1.4455 +        if (cancelPreviousGesture) {
  1.4456 +            dispatchMotion(when, policyFlags, mSource,
  1.4457 +                    AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
  1.4458 +                    AMOTION_EVENT_EDGE_FLAG_NONE,
  1.4459 +                    mPointerGesture.lastGestureProperties,
  1.4460 +                    mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
  1.4461 +                    dispatchedGestureIdBits, -1,
  1.4462 +                    0, 0, mPointerGesture.downTime);
  1.4463 +
  1.4464 +            dispatchedGestureIdBits.clear();
  1.4465 +        } else {
  1.4466 +            BitSet32 upGestureIdBits;
  1.4467 +            if (finishPreviousGesture) {
  1.4468 +                upGestureIdBits = dispatchedGestureIdBits;
  1.4469 +            } else {
  1.4470 +                upGestureIdBits.value = dispatchedGestureIdBits.value
  1.4471 +                        & ~mPointerGesture.currentGestureIdBits.value;
  1.4472 +            }
  1.4473 +            while (!upGestureIdBits.isEmpty()) {
  1.4474 +                uint32_t id = upGestureIdBits.clearFirstMarkedBit();
  1.4475 +
  1.4476 +                dispatchMotion(when, policyFlags, mSource,
  1.4477 +                        AMOTION_EVENT_ACTION_POINTER_UP, 0,
  1.4478 +                        metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
  1.4479 +                        mPointerGesture.lastGestureProperties,
  1.4480 +                        mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
  1.4481 +                        dispatchedGestureIdBits, id,
  1.4482 +                        0, 0, mPointerGesture.downTime);
  1.4483 +
  1.4484 +                dispatchedGestureIdBits.clearBit(id);
  1.4485 +            }
  1.4486 +        }
  1.4487 +    }
  1.4488 +
  1.4489 +    // Send motion events for all pointers that moved.
  1.4490 +    if (moveNeeded) {
  1.4491 +        dispatchMotion(when, policyFlags, mSource,
  1.4492 +                AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
  1.4493 +                mPointerGesture.currentGestureProperties,
  1.4494 +                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
  1.4495 +                dispatchedGestureIdBits, -1,
  1.4496 +                0, 0, mPointerGesture.downTime);
  1.4497 +    }
  1.4498 +
  1.4499 +    // Send motion events for all pointers that went down.
  1.4500 +    if (down) {
  1.4501 +        BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value
  1.4502 +                & ~dispatchedGestureIdBits.value);
  1.4503 +        while (!downGestureIdBits.isEmpty()) {
  1.4504 +            uint32_t id = downGestureIdBits.clearFirstMarkedBit();
  1.4505 +            dispatchedGestureIdBits.markBit(id);
  1.4506 +
  1.4507 +            if (dispatchedGestureIdBits.count() == 1) {
  1.4508 +                mPointerGesture.downTime = when;
  1.4509 +            }
  1.4510 +
  1.4511 +            dispatchMotion(when, policyFlags, mSource,
  1.4512 +                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
  1.4513 +                    mPointerGesture.currentGestureProperties,
  1.4514 +                    mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
  1.4515 +                    dispatchedGestureIdBits, id,
  1.4516 +                    0, 0, mPointerGesture.downTime);
  1.4517 +        }
  1.4518 +    }
  1.4519 +
  1.4520 +    // Send motion events for hover.
  1.4521 +    if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
  1.4522 +        dispatchMotion(when, policyFlags, mSource,
  1.4523 +                AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
  1.4524 +                metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
  1.4525 +                mPointerGesture.currentGestureProperties,
  1.4526 +                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
  1.4527 +                mPointerGesture.currentGestureIdBits, -1,
  1.4528 +                0, 0, mPointerGesture.downTime);
  1.4529 +    } else if (dispatchedGestureIdBits.isEmpty()
  1.4530 +            && !mPointerGesture.lastGestureIdBits.isEmpty()) {
  1.4531 +        // Synthesize a hover move event after all pointers go up to indicate that
  1.4532 +        // the pointer is hovering again even if the user is not currently touching
  1.4533 +        // the touch pad.  This ensures that a view will receive a fresh hover enter
  1.4534 +        // event after a tap.
  1.4535 +        float x, y;
  1.4536 +        mPointerController->getPosition(&x, &y);
  1.4537 +
  1.4538 +        PointerProperties pointerProperties;
  1.4539 +        pointerProperties.clear();
  1.4540 +        pointerProperties.id = 0;
  1.4541 +        pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
  1.4542 +
  1.4543 +        PointerCoords pointerCoords;
  1.4544 +        pointerCoords.clear();
  1.4545 +        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
  1.4546 +        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
  1.4547 +
  1.4548 +        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
  1.4549 +                AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
  1.4550 +                metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
  1.4551 +                mViewport.displayId, 1, &pointerProperties, &pointerCoords,
  1.4552 +                0, 0, mPointerGesture.downTime);
  1.4553 +        getListener()->notifyMotion(&args);
  1.4554 +    }
  1.4555 +
  1.4556 +    // Update state.
  1.4557 +    mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
  1.4558 +    if (!down) {
  1.4559 +        mPointerGesture.lastGestureIdBits.clear();
  1.4560 +    } else {
  1.4561 +        mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
  1.4562 +        for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) {
  1.4563 +            uint32_t id = idBits.clearFirstMarkedBit();
  1.4564 +            uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
  1.4565 +            mPointerGesture.lastGestureProperties[index].copyFrom(
  1.4566 +                    mPointerGesture.currentGestureProperties[index]);
  1.4567 +            mPointerGesture.lastGestureCoords[index].copyFrom(
  1.4568 +                    mPointerGesture.currentGestureCoords[index]);
  1.4569 +            mPointerGesture.lastGestureIdToIndex[id] = index;
  1.4570 +        }
  1.4571 +    }
  1.4572 +}
  1.4573 +
  1.4574 +void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) {
  1.4575 +    // Cancel previously dispatches pointers.
  1.4576 +    if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
  1.4577 +        int32_t metaState = getContext()->getGlobalMetaState();
  1.4578 +        int32_t buttonState = mCurrentButtonState;
  1.4579 +        dispatchMotion(when, policyFlags, mSource,
  1.4580 +                AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
  1.4581 +                AMOTION_EVENT_EDGE_FLAG_NONE,
  1.4582 +                mPointerGesture.lastGestureProperties,
  1.4583 +                mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
  1.4584 +                mPointerGesture.lastGestureIdBits, -1,
  1.4585 +                0, 0, mPointerGesture.downTime);
  1.4586 +    }
  1.4587 +
  1.4588 +    // Reset the current pointer gesture.
  1.4589 +    mPointerGesture.reset();
  1.4590 +    mPointerVelocityControl.reset();
  1.4591 +
  1.4592 +    // Remove any current spots.
  1.4593 +    if (mPointerController != NULL) {
  1.4594 +        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
  1.4595 +        mPointerController->clearSpots();
  1.4596 +    }
  1.4597 +}
  1.4598 +
  1.4599 +bool TouchInputMapper::preparePointerGestures(nsecs_t when,
  1.4600 +        bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
  1.4601 +    *outCancelPreviousGesture = false;
  1.4602 +    *outFinishPreviousGesture = false;
  1.4603 +
  1.4604 +    // Handle TAP timeout.
  1.4605 +    if (isTimeout) {
  1.4606 +#if DEBUG_GESTURES
  1.4607 +        ALOGD("Gestures: Processing timeout");
  1.4608 +#endif
  1.4609 +
  1.4610 +        if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
  1.4611 +            if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
  1.4612 +                // The tap/drag timeout has not yet expired.
  1.4613 +                getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime
  1.4614 +                        + mConfig.pointerGestureTapDragInterval);
  1.4615 +            } else {
  1.4616 +                // The tap is finished.
  1.4617 +#if DEBUG_GESTURES
  1.4618 +                ALOGD("Gestures: TAP finished");
  1.4619 +#endif
  1.4620 +                *outFinishPreviousGesture = true;
  1.4621 +
  1.4622 +                mPointerGesture.activeGestureId = -1;
  1.4623 +                mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
  1.4624 +                mPointerGesture.currentGestureIdBits.clear();
  1.4625 +
  1.4626 +                mPointerVelocityControl.reset();
  1.4627 +                return true;
  1.4628 +            }
  1.4629 +        }
  1.4630 +
  1.4631 +        // We did not handle this timeout.
  1.4632 +        return false;
  1.4633 +    }
  1.4634 +
  1.4635 +    const uint32_t currentFingerCount = mCurrentFingerIdBits.count();
  1.4636 +    const uint32_t lastFingerCount = mLastFingerIdBits.count();
  1.4637 +
  1.4638 +    // Update the velocity tracker.
  1.4639 +    {
  1.4640 +        VelocityTracker::Position positions[MAX_POINTERS];
  1.4641 +        uint32_t count = 0;
  1.4642 +        for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); count++) {
  1.4643 +            uint32_t id = idBits.clearFirstMarkedBit();
  1.4644 +            const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
  1.4645 +            positions[count].x = pointer.x * mPointerXMovementScale;
  1.4646 +            positions[count].y = pointer.y * mPointerYMovementScale;
  1.4647 +        }
  1.4648 +        mPointerGesture.velocityTracker.addMovement(when,
  1.4649 +                mCurrentFingerIdBits, positions);
  1.4650 +    }
  1.4651 +
  1.4652 +    // Pick a new active touch id if needed.
  1.4653 +    // Choose an arbitrary pointer that just went down, if there is one.
  1.4654 +    // Otherwise choose an arbitrary remaining pointer.
  1.4655 +    // This guarantees we always have an active touch id when there is at least one pointer.
  1.4656 +    // We keep the same active touch id for as long as possible.
  1.4657 +    bool activeTouchChanged = false;
  1.4658 +    int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
  1.4659 +    int32_t activeTouchId = lastActiveTouchId;
  1.4660 +    if (activeTouchId < 0) {
  1.4661 +        if (!mCurrentFingerIdBits.isEmpty()) {
  1.4662 +            activeTouchChanged = true;
  1.4663 +            activeTouchId = mPointerGesture.activeTouchId =
  1.4664 +                    mCurrentFingerIdBits.firstMarkedBit();
  1.4665 +            mPointerGesture.firstTouchTime = when;
  1.4666 +        }
  1.4667 +    } else if (!mCurrentFingerIdBits.hasBit(activeTouchId)) {
  1.4668 +        activeTouchChanged = true;
  1.4669 +        if (!mCurrentFingerIdBits.isEmpty()) {
  1.4670 +            activeTouchId = mPointerGesture.activeTouchId =
  1.4671 +                    mCurrentFingerIdBits.firstMarkedBit();
  1.4672 +        } else {
  1.4673 +            activeTouchId = mPointerGesture.activeTouchId = -1;
  1.4674 +        }
  1.4675 +    }
  1.4676 +
  1.4677 +    // Determine whether we are in quiet time.
  1.4678 +    bool isQuietTime = false;
  1.4679 +    if (activeTouchId < 0) {
  1.4680 +        mPointerGesture.resetQuietTime();
  1.4681 +    } else {
  1.4682 +        isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval;
  1.4683 +        if (!isQuietTime) {
  1.4684 +            if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
  1.4685 +                    || mPointerGesture.lastGestureMode == PointerGesture::SWIPE
  1.4686 +                    || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)
  1.4687 +                    && currentFingerCount < 2) {
  1.4688 +                // Enter quiet time when exiting swipe or freeform state.
  1.4689 +                // This is to prevent accidentally entering the hover state and flinging the
  1.4690 +                // pointer when finishing a swipe and there is still one pointer left onscreen.
  1.4691 +                isQuietTime = true;
  1.4692 +            } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
  1.4693 +                    && currentFingerCount >= 2
  1.4694 +                    && !isPointerDown(mCurrentButtonState)) {
  1.4695 +                // Enter quiet time when releasing the button and there are still two or more
  1.4696 +                // fingers down.  This may indicate that one finger was used to press the button
  1.4697 +                // but it has not gone up yet.
  1.4698 +                isQuietTime = true;
  1.4699 +            }
  1.4700 +            if (isQuietTime) {
  1.4701 +                mPointerGesture.quietTime = when;
  1.4702 +            }
  1.4703 +        }
  1.4704 +    }
  1.4705 +
  1.4706 +    // Switch states based on button and pointer state.
  1.4707 +    if (isQuietTime) {
  1.4708 +        // Case 1: Quiet time. (QUIET)
  1.4709 +#if DEBUG_GESTURES
  1.4710 +        ALOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime
  1.4711 +                + mConfig.pointerGestureQuietInterval - when) * 0.000001f);
  1.4712 +#endif
  1.4713 +        if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
  1.4714 +            *outFinishPreviousGesture = true;
  1.4715 +        }
  1.4716 +
  1.4717 +        mPointerGesture.activeGestureId = -1;
  1.4718 +        mPointerGesture.currentGestureMode = PointerGesture::QUIET;
  1.4719 +        mPointerGesture.currentGestureIdBits.clear();
  1.4720 +
  1.4721 +        mPointerVelocityControl.reset();
  1.4722 +    } else if (isPointerDown(mCurrentButtonState)) {
  1.4723 +        // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
  1.4724 +        // The pointer follows the active touch point.
  1.4725 +        // Emit DOWN, MOVE, UP events at the pointer location.
  1.4726 +        //
  1.4727 +        // Only the active touch matters; other fingers are ignored.  This policy helps
  1.4728 +        // to handle the case where the user places a second finger on the touch pad
  1.4729 +        // to apply the necessary force to depress an integrated button below the surface.
  1.4730 +        // We don't want the second finger to be delivered to applications.
  1.4731 +        //
  1.4732 +        // For this to work well, we need to make sure to track the pointer that is really
  1.4733 +        // active.  If the user first puts one finger down to click then adds another
  1.4734 +        // finger to drag then the active pointer should switch to the finger that is
  1.4735 +        // being dragged.
  1.4736 +#if DEBUG_GESTURES
  1.4737 +        ALOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
  1.4738 +                "currentFingerCount=%d", activeTouchId, currentFingerCount);
  1.4739 +#endif
  1.4740 +        // Reset state when just starting.
  1.4741 +        if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
  1.4742 +            *outFinishPreviousGesture = true;
  1.4743 +            mPointerGesture.activeGestureId = 0;
  1.4744 +        }
  1.4745 +
  1.4746 +        // Switch pointers if needed.
  1.4747 +        // Find the fastest pointer and follow it.
  1.4748 +        if (activeTouchId >= 0 && currentFingerCount > 1) {
  1.4749 +            int32_t bestId = -1;
  1.4750 +            float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
  1.4751 +            for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); ) {
  1.4752 +                uint32_t id = idBits.clearFirstMarkedBit();
  1.4753 +                float vx, vy;
  1.4754 +                if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
  1.4755 +                    float speed = hypotf(vx, vy);
  1.4756 +                    if (speed > bestSpeed) {
  1.4757 +                        bestId = id;
  1.4758 +                        bestSpeed = speed;
  1.4759 +                    }
  1.4760 +                }
  1.4761 +            }
  1.4762 +            if (bestId >= 0 && bestId != activeTouchId) {
  1.4763 +                mPointerGesture.activeTouchId = activeTouchId = bestId;
  1.4764 +                activeTouchChanged = true;
  1.4765 +#if DEBUG_GESTURES
  1.4766 +                ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
  1.4767 +                        "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
  1.4768 +#endif
  1.4769 +            }
  1.4770 +        }
  1.4771 +
  1.4772 +        if (activeTouchId >= 0 && mLastFingerIdBits.hasBit(activeTouchId)) {
  1.4773 +            const RawPointerData::Pointer& currentPointer =
  1.4774 +                    mCurrentRawPointerData.pointerForId(activeTouchId);
  1.4775 +            const RawPointerData::Pointer& lastPointer =
  1.4776 +                    mLastRawPointerData.pointerForId(activeTouchId);
  1.4777 +            float deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
  1.4778 +            float deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
  1.4779 +
  1.4780 +            rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
  1.4781 +            mPointerVelocityControl.move(when, &deltaX, &deltaY);
  1.4782 +
  1.4783 +            // Move the pointer using a relative motion.
  1.4784 +            // When using spots, the click will occur at the position of the anchor
  1.4785 +            // spot and all other spots will move there.
  1.4786 +            mPointerController->move(deltaX, deltaY);
  1.4787 +        } else {
  1.4788 +            mPointerVelocityControl.reset();
  1.4789 +        }
  1.4790 +
  1.4791 +        float x, y;
  1.4792 +        mPointerController->getPosition(&x, &y);
  1.4793 +
  1.4794 +        mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
  1.4795 +        mPointerGesture.currentGestureIdBits.clear();
  1.4796 +        mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
  1.4797 +        mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
  1.4798 +        mPointerGesture.currentGestureProperties[0].clear();
  1.4799 +        mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
  1.4800 +        mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
  1.4801 +        mPointerGesture.currentGestureCoords[0].clear();
  1.4802 +        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
  1.4803 +        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
  1.4804 +        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
  1.4805 +    } else if (currentFingerCount == 0) {
  1.4806 +        // Case 3. No fingers down and button is not pressed. (NEUTRAL)
  1.4807 +        if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
  1.4808 +            *outFinishPreviousGesture = true;
  1.4809 +        }
  1.4810 +
  1.4811 +        // Watch for taps coming out of HOVER or TAP_DRAG mode.
  1.4812 +        // Checking for taps after TAP_DRAG allows us to detect double-taps.
  1.4813 +        bool tapped = false;
  1.4814 +        if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
  1.4815 +                || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
  1.4816 +                && lastFingerCount == 1) {
  1.4817 +            if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
  1.4818 +                float x, y;
  1.4819 +                mPointerController->getPosition(&x, &y);
  1.4820 +                if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
  1.4821 +                        && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
  1.4822 +#if DEBUG_GESTURES
  1.4823 +                    ALOGD("Gestures: TAP");
  1.4824 +#endif
  1.4825 +
  1.4826 +                    mPointerGesture.tapUpTime = when;
  1.4827 +                    getContext()->requestTimeoutAtTime(when
  1.4828 +                            + mConfig.pointerGestureTapDragInterval);
  1.4829 +
  1.4830 +                    mPointerGesture.activeGestureId = 0;
  1.4831 +                    mPointerGesture.currentGestureMode = PointerGesture::TAP;
  1.4832 +                    mPointerGesture.currentGestureIdBits.clear();
  1.4833 +                    mPointerGesture.currentGestureIdBits.markBit(
  1.4834 +                            mPointerGesture.activeGestureId);
  1.4835 +                    mPointerGesture.currentGestureIdToIndex[
  1.4836 +                            mPointerGesture.activeGestureId] = 0;
  1.4837 +                    mPointerGesture.currentGestureProperties[0].clear();
  1.4838 +                    mPointerGesture.currentGestureProperties[0].id =
  1.4839 +                            mPointerGesture.activeGestureId;
  1.4840 +                    mPointerGesture.currentGestureProperties[0].toolType =
  1.4841 +                            AMOTION_EVENT_TOOL_TYPE_FINGER;
  1.4842 +                    mPointerGesture.currentGestureCoords[0].clear();
  1.4843 +                    mPointerGesture.currentGestureCoords[0].setAxisValue(
  1.4844 +                            AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
  1.4845 +                    mPointerGesture.currentGestureCoords[0].setAxisValue(
  1.4846 +                            AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY);
  1.4847 +                    mPointerGesture.currentGestureCoords[0].setAxisValue(
  1.4848 +                            AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
  1.4849 +
  1.4850 +                    tapped = true;
  1.4851 +                } else {
  1.4852 +#if DEBUG_GESTURES
  1.4853 +                    ALOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f",
  1.4854 +                            x - mPointerGesture.tapX,
  1.4855 +                            y - mPointerGesture.tapY);
  1.4856 +#endif
  1.4857 +                }
  1.4858 +            } else {
  1.4859 +#if DEBUG_GESTURES
  1.4860 +                ALOGD("Gestures: Not a TAP, %0.3fms since down",
  1.4861 +                        (when - mPointerGesture.tapDownTime) * 0.000001f);
  1.4862 +#endif
  1.4863 +            }
  1.4864 +        }
  1.4865 +
  1.4866 +        mPointerVelocityControl.reset();
  1.4867 +
  1.4868 +        if (!tapped) {
  1.4869 +#if DEBUG_GESTURES
  1.4870 +            ALOGD("Gestures: NEUTRAL");
  1.4871 +#endif
  1.4872 +            mPointerGesture.activeGestureId = -1;
  1.4873 +            mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
  1.4874 +            mPointerGesture.currentGestureIdBits.clear();
  1.4875 +        }
  1.4876 +    } else if (currentFingerCount == 1) {
  1.4877 +        // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
  1.4878 +        // The pointer follows the active touch point.
  1.4879 +        // When in HOVER, emit HOVER_MOVE events at the pointer location.
  1.4880 +        // When in TAP_DRAG, emit MOVE events at the pointer location.
  1.4881 +        ALOG_ASSERT(activeTouchId >= 0);
  1.4882 +
  1.4883 +        mPointerGesture.currentGestureMode = PointerGesture::HOVER;
  1.4884 +        if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
  1.4885 +            if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
  1.4886 +                float x, y;
  1.4887 +                mPointerController->getPosition(&x, &y);
  1.4888 +                if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
  1.4889 +                        && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
  1.4890 +                    mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
  1.4891 +                } else {
  1.4892 +#if DEBUG_GESTURES
  1.4893 +                    ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
  1.4894 +                            x - mPointerGesture.tapX,
  1.4895 +                            y - mPointerGesture.tapY);
  1.4896 +#endif
  1.4897 +                }
  1.4898 +            } else {
  1.4899 +#if DEBUG_GESTURES
  1.4900 +                ALOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
  1.4901 +                        (when - mPointerGesture.tapUpTime) * 0.000001f);
  1.4902 +#endif
  1.4903 +            }
  1.4904 +        } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
  1.4905 +            mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
  1.4906 +        }
  1.4907 +
  1.4908 +        if (mLastFingerIdBits.hasBit(activeTouchId)) {
  1.4909 +            const RawPointerData::Pointer& currentPointer =
  1.4910 +                    mCurrentRawPointerData.pointerForId(activeTouchId);
  1.4911 +            const RawPointerData::Pointer& lastPointer =
  1.4912 +                    mLastRawPointerData.pointerForId(activeTouchId);
  1.4913 +            float deltaX = (currentPointer.x - lastPointer.x)
  1.4914 +                    * mPointerXMovementScale;
  1.4915 +            float deltaY = (currentPointer.y - lastPointer.y)
  1.4916 +                    * mPointerYMovementScale;
  1.4917 +
  1.4918 +            rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
  1.4919 +            mPointerVelocityControl.move(when, &deltaX, &deltaY);
  1.4920 +
  1.4921 +            // Move the pointer using a relative motion.
  1.4922 +            // When using spots, the hover or drag will occur at the position of the anchor spot.
  1.4923 +            mPointerController->move(deltaX, deltaY);
  1.4924 +        } else {
  1.4925 +            mPointerVelocityControl.reset();
  1.4926 +        }
  1.4927 +
  1.4928 +        bool down;
  1.4929 +        if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
  1.4930 +#if DEBUG_GESTURES
  1.4931 +            ALOGD("Gestures: TAP_DRAG");
  1.4932 +#endif
  1.4933 +            down = true;
  1.4934 +        } else {
  1.4935 +#if DEBUG_GESTURES
  1.4936 +            ALOGD("Gestures: HOVER");
  1.4937 +#endif
  1.4938 +            if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
  1.4939 +                *outFinishPreviousGesture = true;
  1.4940 +            }
  1.4941 +            mPointerGesture.activeGestureId = 0;
  1.4942 +            down = false;
  1.4943 +        }
  1.4944 +
  1.4945 +        float x, y;
  1.4946 +        mPointerController->getPosition(&x, &y);
  1.4947 +
  1.4948 +        mPointerGesture.currentGestureIdBits.clear();
  1.4949 +        mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
  1.4950 +        mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
  1.4951 +        mPointerGesture.currentGestureProperties[0].clear();
  1.4952 +        mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
  1.4953 +        mPointerGesture.currentGestureProperties[0].toolType =
  1.4954 +                AMOTION_EVENT_TOOL_TYPE_FINGER;
  1.4955 +        mPointerGesture.currentGestureCoords[0].clear();
  1.4956 +        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
  1.4957 +        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
  1.4958 +        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
  1.4959 +                down ? 1.0f : 0.0f);
  1.4960 +
  1.4961 +        if (lastFingerCount == 0 && currentFingerCount != 0) {
  1.4962 +            mPointerGesture.resetTap();
  1.4963 +            mPointerGesture.tapDownTime = when;
  1.4964 +            mPointerGesture.tapX = x;
  1.4965 +            mPointerGesture.tapY = y;
  1.4966 +        }
  1.4967 +    } else {
  1.4968 +        // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
  1.4969 +        // We need to provide feedback for each finger that goes down so we cannot wait
  1.4970 +        // for the fingers to move before deciding what to do.
  1.4971 +        //
  1.4972 +        // The ambiguous case is deciding what to do when there are two fingers down but they
  1.4973 +        // have not moved enough to determine whether they are part of a drag or part of a
  1.4974 +        // freeform gesture, or just a press or long-press at the pointer location.
  1.4975 +        //
  1.4976 +        // When there are two fingers we start with the PRESS hypothesis and we generate a
  1.4977 +        // down at the pointer location.
  1.4978 +        //
  1.4979 +        // When the two fingers move enough or when additional fingers are added, we make
  1.4980 +        // a decision to transition into SWIPE or FREEFORM mode accordingly.
  1.4981 +        ALOG_ASSERT(activeTouchId >= 0);
  1.4982 +
  1.4983 +        bool settled = when >= mPointerGesture.firstTouchTime
  1.4984 +                + mConfig.pointerGestureMultitouchSettleInterval;
  1.4985 +        if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
  1.4986 +                && mPointerGesture.lastGestureMode != PointerGesture::SWIPE
  1.4987 +                && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
  1.4988 +            *outFinishPreviousGesture = true;
  1.4989 +        } else if (!settled && currentFingerCount > lastFingerCount) {
  1.4990 +            // Additional pointers have gone down but not yet settled.
  1.4991 +            // Reset the gesture.
  1.4992 +#if DEBUG_GESTURES
  1.4993 +            ALOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
  1.4994 +                    "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
  1.4995 +                            + mConfig.pointerGestureMultitouchSettleInterval - when)
  1.4996 +                            * 0.000001f);
  1.4997 +#endif
  1.4998 +            *outCancelPreviousGesture = true;
  1.4999 +        } else {
  1.5000 +            // Continue previous gesture.
  1.5001 +            mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
  1.5002 +        }
  1.5003 +
  1.5004 +        if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
  1.5005 +            mPointerGesture.currentGestureMode = PointerGesture::PRESS;
  1.5006 +            mPointerGesture.activeGestureId = 0;
  1.5007 +            mPointerGesture.referenceIdBits.clear();
  1.5008 +            mPointerVelocityControl.reset();
  1.5009 +
  1.5010 +            // Use the centroid and pointer location as the reference points for the gesture.
  1.5011 +#if DEBUG_GESTURES
  1.5012 +            ALOGD("Gestures: Using centroid as reference for MULTITOUCH, "
  1.5013 +                    "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
  1.5014 +                            + mConfig.pointerGestureMultitouchSettleInterval - when)
  1.5015 +                            * 0.000001f);
  1.5016 +#endif
  1.5017 +            mCurrentRawPointerData.getCentroidOfTouchingPointers(
  1.5018 +                    &mPointerGesture.referenceTouchX,
  1.5019 +                    &mPointerGesture.referenceTouchY);
  1.5020 +            mPointerController->getPosition(&mPointerGesture.referenceGestureX,
  1.5021 +                    &mPointerGesture.referenceGestureY);
  1.5022 +        }
  1.5023 +
  1.5024 +        // Clear the reference deltas for fingers not yet included in the reference calculation.
  1.5025 +        for (BitSet32 idBits(mCurrentFingerIdBits.value
  1.5026 +                & ~mPointerGesture.referenceIdBits.value); !idBits.isEmpty(); ) {
  1.5027 +            uint32_t id = idBits.clearFirstMarkedBit();
  1.5028 +            mPointerGesture.referenceDeltas[id].dx = 0;
  1.5029 +            mPointerGesture.referenceDeltas[id].dy = 0;
  1.5030 +        }
  1.5031 +        mPointerGesture.referenceIdBits = mCurrentFingerIdBits;
  1.5032 +
  1.5033 +        // Add delta for all fingers and calculate a common movement delta.
  1.5034 +        float commonDeltaX = 0, commonDeltaY = 0;
  1.5035 +        BitSet32 commonIdBits(mLastFingerIdBits.value
  1.5036 +                & mCurrentFingerIdBits.value);
  1.5037 +        for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
  1.5038 +            bool first = (idBits == commonIdBits);
  1.5039 +            uint32_t id = idBits.clearFirstMarkedBit();
  1.5040 +            const RawPointerData::Pointer& cpd = mCurrentRawPointerData.pointerForId(id);
  1.5041 +            const RawPointerData::Pointer& lpd = mLastRawPointerData.pointerForId(id);
  1.5042 +            PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
  1.5043 +            delta.dx += cpd.x - lpd.x;
  1.5044 +            delta.dy += cpd.y - lpd.y;
  1.5045 +
  1.5046 +            if (first) {
  1.5047 +                commonDeltaX = delta.dx;
  1.5048 +                commonDeltaY = delta.dy;
  1.5049 +            } else {
  1.5050 +                commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
  1.5051 +                commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
  1.5052 +            }
  1.5053 +        }
  1.5054 +
  1.5055 +        // Consider transitions from PRESS to SWIPE or MULTITOUCH.
  1.5056 +        if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
  1.5057 +            float dist[MAX_POINTER_ID + 1];
  1.5058 +            int32_t distOverThreshold = 0;
  1.5059 +            for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
  1.5060 +                uint32_t id = idBits.clearFirstMarkedBit();
  1.5061 +                PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
  1.5062 +                dist[id] = hypotf(delta.dx * mPointerXZoomScale,
  1.5063 +                        delta.dy * mPointerYZoomScale);
  1.5064 +                if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) {
  1.5065 +                    distOverThreshold += 1;
  1.5066 +                }
  1.5067 +            }
  1.5068 +
  1.5069 +            // Only transition when at least two pointers have moved further than
  1.5070 +            // the minimum distance threshold.
  1.5071 +            if (distOverThreshold >= 2) {
  1.5072 +                if (currentFingerCount > 2) {
  1.5073 +                    // There are more than two pointers, switch to FREEFORM.
  1.5074 +#if DEBUG_GESTURES
  1.5075 +                    ALOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
  1.5076 +                            currentFingerCount);
  1.5077 +#endif
  1.5078 +                    *outCancelPreviousGesture = true;
  1.5079 +                    mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
  1.5080 +                } else {
  1.5081 +                    // There are exactly two pointers.
  1.5082 +                    BitSet32 idBits(mCurrentFingerIdBits);
  1.5083 +                    uint32_t id1 = idBits.clearFirstMarkedBit();
  1.5084 +                    uint32_t id2 = idBits.firstMarkedBit();
  1.5085 +                    const RawPointerData::Pointer& p1 = mCurrentRawPointerData.pointerForId(id1);
  1.5086 +                    const RawPointerData::Pointer& p2 = mCurrentRawPointerData.pointerForId(id2);
  1.5087 +                    float mutualDistance = distance(p1.x, p1.y, p2.x, p2.y);
  1.5088 +                    if (mutualDistance > mPointerGestureMaxSwipeWidth) {
  1.5089 +                        // There are two pointers but they are too far apart for a SWIPE,
  1.5090 +                        // switch to FREEFORM.
  1.5091 +#if DEBUG_GESTURES
  1.5092 +                        ALOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
  1.5093 +                                mutualDistance, mPointerGestureMaxSwipeWidth);
  1.5094 +#endif
  1.5095 +                        *outCancelPreviousGesture = true;
  1.5096 +                        mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
  1.5097 +                    } else {
  1.5098 +                        // There are two pointers.  Wait for both pointers to start moving
  1.5099 +                        // before deciding whether this is a SWIPE or FREEFORM gesture.
  1.5100 +                        float dist1 = dist[id1];
  1.5101 +                        float dist2 = dist[id2];
  1.5102 +                        if (dist1 >= mConfig.pointerGestureMultitouchMinDistance
  1.5103 +                                && dist2 >= mConfig.pointerGestureMultitouchMinDistance) {
  1.5104 +                            // Calculate the dot product of the displacement vectors.
  1.5105 +                            // When the vectors are oriented in approximately the same direction,
  1.5106 +                            // the angle betweeen them is near zero and the cosine of the angle
  1.5107 +                            // approches 1.0.  Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
  1.5108 +                            PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
  1.5109 +                            PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
  1.5110 +                            float dx1 = delta1.dx * mPointerXZoomScale;
  1.5111 +                            float dy1 = delta1.dy * mPointerYZoomScale;
  1.5112 +                            float dx2 = delta2.dx * mPointerXZoomScale;
  1.5113 +                            float dy2 = delta2.dy * mPointerYZoomScale;
  1.5114 +                            float dot = dx1 * dx2 + dy1 * dy2;
  1.5115 +                            float cosine = dot / (dist1 * dist2); // denominator always > 0
  1.5116 +                            if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
  1.5117 +                                // Pointers are moving in the same direction.  Switch to SWIPE.
  1.5118 +#if DEBUG_GESTURES
  1.5119 +                                ALOGD("Gestures: PRESS transitioned to SWIPE, "
  1.5120 +                                        "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
  1.5121 +                                        "cosine %0.3f >= %0.3f",
  1.5122 +                                        dist1, mConfig.pointerGestureMultitouchMinDistance,
  1.5123 +                                        dist2, mConfig.pointerGestureMultitouchMinDistance,
  1.5124 +                                        cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
  1.5125 +#endif
  1.5126 +                                mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
  1.5127 +                            } else {
  1.5128 +                                // Pointers are moving in different directions.  Switch to FREEFORM.
  1.5129 +#if DEBUG_GESTURES
  1.5130 +                                ALOGD("Gestures: PRESS transitioned to FREEFORM, "
  1.5131 +                                        "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
  1.5132 +                                        "cosine %0.3f < %0.3f",
  1.5133 +                                        dist1, mConfig.pointerGestureMultitouchMinDistance,
  1.5134 +                                        dist2, mConfig.pointerGestureMultitouchMinDistance,
  1.5135 +                                        cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
  1.5136 +#endif
  1.5137 +                                *outCancelPreviousGesture = true;
  1.5138 +                                mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
  1.5139 +                            }
  1.5140 +                        }
  1.5141 +                    }
  1.5142 +                }
  1.5143 +            }
  1.5144 +        } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
  1.5145 +            // Switch from SWIPE to FREEFORM if additional pointers go down.
  1.5146 +            // Cancel previous gesture.
  1.5147 +            if (currentFingerCount > 2) {
  1.5148 +#if DEBUG_GESTURES
  1.5149 +                ALOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
  1.5150 +                        currentFingerCount);
  1.5151 +#endif
  1.5152 +                *outCancelPreviousGesture = true;
  1.5153 +                mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
  1.5154 +            }
  1.5155 +        }
  1.5156 +
  1.5157 +        // Move the reference points based on the overall group motion of the fingers
  1.5158 +        // except in PRESS mode while waiting for a transition to occur.
  1.5159 +        if (mPointerGesture.currentGestureMode != PointerGesture::PRESS
  1.5160 +                && (commonDeltaX || commonDeltaY)) {
  1.5161 +            for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
  1.5162 +                uint32_t id = idBits.clearFirstMarkedBit();
  1.5163 +                PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
  1.5164 +                delta.dx = 0;
  1.5165 +                delta.dy = 0;
  1.5166 +            }
  1.5167 +
  1.5168 +            mPointerGesture.referenceTouchX += commonDeltaX;
  1.5169 +            mPointerGesture.referenceTouchY += commonDeltaY;
  1.5170 +
  1.5171 +            commonDeltaX *= mPointerXMovementScale;
  1.5172 +            commonDeltaY *= mPointerYMovementScale;
  1.5173 +
  1.5174 +            rotateDelta(mSurfaceOrientation, &commonDeltaX, &commonDeltaY);
  1.5175 +            mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
  1.5176 +
  1.5177 +            mPointerGesture.referenceGestureX += commonDeltaX;
  1.5178 +            mPointerGesture.referenceGestureY += commonDeltaY;
  1.5179 +        }
  1.5180 +
  1.5181 +        // Report gestures.
  1.5182 +        if (mPointerGesture.currentGestureMode == PointerGesture::PRESS
  1.5183 +                || mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
  1.5184 +            // PRESS or SWIPE mode.
  1.5185 +#if DEBUG_GESTURES
  1.5186 +            ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
  1.5187 +                    "activeGestureId=%d, currentTouchPointerCount=%d",
  1.5188 +                    activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
  1.5189 +#endif
  1.5190 +            ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
  1.5191 +
  1.5192 +            mPointerGesture.currentGestureIdBits.clear();
  1.5193 +            mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
  1.5194 +            mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
  1.5195 +            mPointerGesture.currentGestureProperties[0].clear();
  1.5196 +            mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
  1.5197 +            mPointerGesture.currentGestureProperties[0].toolType =
  1.5198 +                    AMOTION_EVENT_TOOL_TYPE_FINGER;
  1.5199 +            mPointerGesture.currentGestureCoords[0].clear();
  1.5200 +            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
  1.5201 +                    mPointerGesture.referenceGestureX);
  1.5202 +            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
  1.5203 +                    mPointerGesture.referenceGestureY);
  1.5204 +            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
  1.5205 +        } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
  1.5206 +            // FREEFORM mode.
  1.5207 +#if DEBUG_GESTURES
  1.5208 +            ALOGD("Gestures: FREEFORM activeTouchId=%d,"
  1.5209 +                    "activeGestureId=%d, currentTouchPointerCount=%d",
  1.5210 +                    activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
  1.5211 +#endif
  1.5212 +            ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
  1.5213 +
  1.5214 +            mPointerGesture.currentGestureIdBits.clear();
  1.5215 +
  1.5216 +            BitSet32 mappedTouchIdBits;
  1.5217 +            BitSet32 usedGestureIdBits;
  1.5218 +            if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
  1.5219 +                // Initially, assign the active gesture id to the active touch point
  1.5220 +                // if there is one.  No other touch id bits are mapped yet.
  1.5221 +                if (!*outCancelPreviousGesture) {
  1.5222 +                    mappedTouchIdBits.markBit(activeTouchId);
  1.5223 +                    usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
  1.5224 +                    mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
  1.5225 +                            mPointerGesture.activeGestureId;
  1.5226 +                } else {
  1.5227 +                    mPointerGesture.activeGestureId = -1;
  1.5228 +                }
  1.5229 +            } else {
  1.5230 +                // Otherwise, assume we mapped all touches from the previous frame.
  1.5231 +                // Reuse all mappings that are still applicable.
  1.5232 +                mappedTouchIdBits.value = mLastFingerIdBits.value
  1.5233 +                        & mCurrentFingerIdBits.value;
  1.5234 +                usedGestureIdBits = mPointerGesture.lastGestureIdBits;
  1.5235 +
  1.5236 +                // Check whether we need to choose a new active gesture id because the
  1.5237 +                // current went went up.
  1.5238 +                for (BitSet32 upTouchIdBits(mLastFingerIdBits.value
  1.5239 +                        & ~mCurrentFingerIdBits.value);
  1.5240 +                        !upTouchIdBits.isEmpty(); ) {
  1.5241 +                    uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit();
  1.5242 +                    uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
  1.5243 +                    if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
  1.5244 +                        mPointerGesture.activeGestureId = -1;
  1.5245 +                        break;
  1.5246 +                    }
  1.5247 +                }
  1.5248 +            }
  1.5249 +
  1.5250 +#if DEBUG_GESTURES
  1.5251 +            ALOGD("Gestures: FREEFORM follow up "
  1.5252 +                    "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
  1.5253 +                    "activeGestureId=%d",
  1.5254 +                    mappedTouchIdBits.value, usedGestureIdBits.value,
  1.5255 +                    mPointerGesture.activeGestureId);
  1.5256 +#endif
  1.5257 +
  1.5258 +            BitSet32 idBits(mCurrentFingerIdBits);
  1.5259 +            for (uint32_t i = 0; i < currentFingerCount; i++) {
  1.5260 +                uint32_t touchId = idBits.clearFirstMarkedBit();
  1.5261 +                uint32_t gestureId;
  1.5262 +                if (!mappedTouchIdBits.hasBit(touchId)) {
  1.5263 +                    gestureId = usedGestureIdBits.markFirstUnmarkedBit();
  1.5264 +                    mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
  1.5265 +#if DEBUG_GESTURES
  1.5266 +                    ALOGD("Gestures: FREEFORM "
  1.5267 +                            "new mapping for touch id %d -> gesture id %d",
  1.5268 +                            touchId, gestureId);
  1.5269 +#endif
  1.5270 +                } else {
  1.5271 +                    gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
  1.5272 +#if DEBUG_GESTURES
  1.5273 +                    ALOGD("Gestures: FREEFORM "
  1.5274 +                            "existing mapping for touch id %d -> gesture id %d",
  1.5275 +                            touchId, gestureId);
  1.5276 +#endif
  1.5277 +                }
  1.5278 +                mPointerGesture.currentGestureIdBits.markBit(gestureId);
  1.5279 +                mPointerGesture.currentGestureIdToIndex[gestureId] = i;
  1.5280 +
  1.5281 +                const RawPointerData::Pointer& pointer =
  1.5282 +                        mCurrentRawPointerData.pointerForId(touchId);
  1.5283 +                float deltaX = (pointer.x - mPointerGesture.referenceTouchX)
  1.5284 +                        * mPointerXZoomScale;
  1.5285 +                float deltaY = (pointer.y - mPointerGesture.referenceTouchY)
  1.5286 +                        * mPointerYZoomScale;
  1.5287 +                rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
  1.5288 +
  1.5289 +                mPointerGesture.currentGestureProperties[i].clear();
  1.5290 +                mPointerGesture.currentGestureProperties[i].id = gestureId;
  1.5291 +                mPointerGesture.currentGestureProperties[i].toolType =
  1.5292 +                        AMOTION_EVENT_TOOL_TYPE_FINGER;
  1.5293 +                mPointerGesture.currentGestureCoords[i].clear();
  1.5294 +                mPointerGesture.currentGestureCoords[i].setAxisValue(
  1.5295 +                        AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX);
  1.5296 +                mPointerGesture.currentGestureCoords[i].setAxisValue(
  1.5297 +                        AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY + deltaY);
  1.5298 +                mPointerGesture.currentGestureCoords[i].setAxisValue(
  1.5299 +                        AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
  1.5300 +            }
  1.5301 +
  1.5302 +            if (mPointerGesture.activeGestureId < 0) {
  1.5303 +                mPointerGesture.activeGestureId =
  1.5304 +                        mPointerGesture.currentGestureIdBits.firstMarkedBit();
  1.5305 +#if DEBUG_GESTURES
  1.5306 +                ALOGD("Gestures: FREEFORM new "
  1.5307 +                        "activeGestureId=%d", mPointerGesture.activeGestureId);
  1.5308 +#endif
  1.5309 +            }
  1.5310 +        }
  1.5311 +    }
  1.5312 +
  1.5313 +    mPointerController->setButtonState(mCurrentButtonState);
  1.5314 +
  1.5315 +#if DEBUG_GESTURES
  1.5316 +    ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
  1.5317 +            "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
  1.5318 +            "lastGestureMode=%d, lastGestureIdBits=0x%08x",
  1.5319 +            toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
  1.5320 +            mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
  1.5321 +            mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
  1.5322 +    for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) {
  1.5323 +        uint32_t id = idBits.clearFirstMarkedBit();
  1.5324 +        uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
  1.5325 +        const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
  1.5326 +        const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
  1.5327 +        ALOGD("  currentGesture[%d]: index=%d, toolType=%d, "
  1.5328 +                "x=%0.3f, y=%0.3f, pressure=%0.3f",
  1.5329 +                id, index, properties.toolType,
  1.5330 +                coords.getAxisValue(AMOTION_EVENT_AXIS_X),
  1.5331 +                coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
  1.5332 +                coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
  1.5333 +    }
  1.5334 +    for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) {
  1.5335 +        uint32_t id = idBits.clearFirstMarkedBit();
  1.5336 +        uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
  1.5337 +        const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
  1.5338 +        const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
  1.5339 +        ALOGD("  lastGesture[%d]: index=%d, toolType=%d, "
  1.5340 +                "x=%0.3f, y=%0.3f, pressure=%0.3f",
  1.5341 +                id, index, properties.toolType,
  1.5342 +                coords.getAxisValue(AMOTION_EVENT_AXIS_X),
  1.5343 +                coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
  1.5344 +                coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
  1.5345 +    }
  1.5346 +#endif
  1.5347 +    return true;
  1.5348 +}
  1.5349 +
  1.5350 +void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) {
  1.5351 +    mPointerSimple.currentCoords.clear();
  1.5352 +    mPointerSimple.currentProperties.clear();
  1.5353 +
  1.5354 +    bool down, hovering;
  1.5355 +    if (!mCurrentStylusIdBits.isEmpty()) {
  1.5356 +        uint32_t id = mCurrentStylusIdBits.firstMarkedBit();
  1.5357 +        uint32_t index = mCurrentCookedPointerData.idToIndex[id];
  1.5358 +        float x = mCurrentCookedPointerData.pointerCoords[index].getX();
  1.5359 +        float y = mCurrentCookedPointerData.pointerCoords[index].getY();
  1.5360 +        mPointerController->setPosition(x, y);
  1.5361 +
  1.5362 +        hovering = mCurrentCookedPointerData.hoveringIdBits.hasBit(id);
  1.5363 +        down = !hovering;
  1.5364 +
  1.5365 +        mPointerController->getPosition(&x, &y);
  1.5366 +        mPointerSimple.currentCoords.copyFrom(mCurrentCookedPointerData.pointerCoords[index]);
  1.5367 +        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
  1.5368 +        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
  1.5369 +        mPointerSimple.currentProperties.id = 0;
  1.5370 +        mPointerSimple.currentProperties.toolType =
  1.5371 +                mCurrentCookedPointerData.pointerProperties[index].toolType;
  1.5372 +    } else {
  1.5373 +        down = false;
  1.5374 +        hovering = false;
  1.5375 +    }
  1.5376 +
  1.5377 +    dispatchPointerSimple(when, policyFlags, down, hovering);
  1.5378 +}
  1.5379 +
  1.5380 +void TouchInputMapper::abortPointerStylus(nsecs_t when, uint32_t policyFlags) {
  1.5381 +    abortPointerSimple(when, policyFlags);
  1.5382 +}
  1.5383 +
  1.5384 +void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) {
  1.5385 +    mPointerSimple.currentCoords.clear();
  1.5386 +    mPointerSimple.currentProperties.clear();
  1.5387 +
  1.5388 +    bool down, hovering;
  1.5389 +    if (!mCurrentMouseIdBits.isEmpty()) {
  1.5390 +        uint32_t id = mCurrentMouseIdBits.firstMarkedBit();
  1.5391 +        uint32_t currentIndex = mCurrentRawPointerData.idToIndex[id];
  1.5392 +        if (mLastMouseIdBits.hasBit(id)) {
  1.5393 +            uint32_t lastIndex = mCurrentRawPointerData.idToIndex[id];
  1.5394 +            float deltaX = (mCurrentRawPointerData.pointers[currentIndex].x
  1.5395 +                    - mLastRawPointerData.pointers[lastIndex].x)
  1.5396 +                    * mPointerXMovementScale;
  1.5397 +            float deltaY = (mCurrentRawPointerData.pointers[currentIndex].y
  1.5398 +                    - mLastRawPointerData.pointers[lastIndex].y)
  1.5399 +                    * mPointerYMovementScale;
  1.5400 +
  1.5401 +            rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
  1.5402 +            mPointerVelocityControl.move(when, &deltaX, &deltaY);
  1.5403 +
  1.5404 +            mPointerController->move(deltaX, deltaY);
  1.5405 +        } else {
  1.5406 +            mPointerVelocityControl.reset();
  1.5407 +        }
  1.5408 +
  1.5409 +        down = isPointerDown(mCurrentButtonState);
  1.5410 +        hovering = !down;
  1.5411 +
  1.5412 +        float x, y;
  1.5413 +        mPointerController->getPosition(&x, &y);
  1.5414 +        mPointerSimple.currentCoords.copyFrom(
  1.5415 +                mCurrentCookedPointerData.pointerCoords[currentIndex]);
  1.5416 +        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
  1.5417 +        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
  1.5418 +        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
  1.5419 +                hovering ? 0.0f : 1.0f);
  1.5420 +        mPointerSimple.currentProperties.id = 0;
  1.5421 +        mPointerSimple.currentProperties.toolType =
  1.5422 +                mCurrentCookedPointerData.pointerProperties[currentIndex].toolType;
  1.5423 +    } else {
  1.5424 +        mPointerVelocityControl.reset();
  1.5425 +
  1.5426 +        down = false;
  1.5427 +        hovering = false;
  1.5428 +    }
  1.5429 +
  1.5430 +    dispatchPointerSimple(when, policyFlags, down, hovering);
  1.5431 +}
  1.5432 +
  1.5433 +void TouchInputMapper::abortPointerMouse(nsecs_t when, uint32_t policyFlags) {
  1.5434 +    abortPointerSimple(when, policyFlags);
  1.5435 +
  1.5436 +    mPointerVelocityControl.reset();
  1.5437 +}
  1.5438 +
  1.5439 +void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
  1.5440 +        bool down, bool hovering) {
  1.5441 +    int32_t metaState = getContext()->getGlobalMetaState();
  1.5442 +
  1.5443 +    if (mPointerController != NULL) {
  1.5444 +        if (down || hovering) {
  1.5445 +            mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
  1.5446 +            mPointerController->clearSpots();
  1.5447 +            mPointerController->setButtonState(mCurrentButtonState);
  1.5448 +            mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
  1.5449 +        } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
  1.5450 +            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
  1.5451 +        }
  1.5452 +    }
  1.5453 +
  1.5454 +    if (mPointerSimple.down && !down) {
  1.5455 +        mPointerSimple.down = false;
  1.5456 +
  1.5457 +        // Send up.
  1.5458 +        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
  1.5459 +                 AMOTION_EVENT_ACTION_UP, 0, metaState, mLastButtonState, 0,
  1.5460 +                 mViewport.displayId,
  1.5461 +                 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
  1.5462 +                 mOrientedXPrecision, mOrientedYPrecision,
  1.5463 +                 mPointerSimple.downTime);
  1.5464 +        getListener()->notifyMotion(&args);
  1.5465 +    }
  1.5466 +
  1.5467 +    if (mPointerSimple.hovering && !hovering) {
  1.5468 +        mPointerSimple.hovering = false;
  1.5469 +
  1.5470 +        // Send hover exit.
  1.5471 +        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
  1.5472 +                AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
  1.5473 +                mViewport.displayId,
  1.5474 +                1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
  1.5475 +                mOrientedXPrecision, mOrientedYPrecision,
  1.5476 +                mPointerSimple.downTime);
  1.5477 +        getListener()->notifyMotion(&args);
  1.5478 +    }
  1.5479 +
  1.5480 +    if (down) {
  1.5481 +        if (!mPointerSimple.down) {
  1.5482 +            mPointerSimple.down = true;
  1.5483 +            mPointerSimple.downTime = when;
  1.5484 +
  1.5485 +            // Send down.
  1.5486 +            NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
  1.5487 +                    AMOTION_EVENT_ACTION_DOWN, 0, metaState, mCurrentButtonState, 0,
  1.5488 +                    mViewport.displayId,
  1.5489 +                    1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
  1.5490 +                    mOrientedXPrecision, mOrientedYPrecision,
  1.5491 +                    mPointerSimple.downTime);
  1.5492 +            getListener()->notifyMotion(&args);
  1.5493 +        }
  1.5494 +
  1.5495 +        // Send move.
  1.5496 +        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
  1.5497 +                AMOTION_EVENT_ACTION_MOVE, 0, metaState, mCurrentButtonState, 0,
  1.5498 +                mViewport.displayId,
  1.5499 +                1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
  1.5500 +                mOrientedXPrecision, mOrientedYPrecision,
  1.5501 +                mPointerSimple.downTime);
  1.5502 +        getListener()->notifyMotion(&args);
  1.5503 +    }
  1.5504 +
  1.5505 +    if (hovering) {
  1.5506 +        if (!mPointerSimple.hovering) {
  1.5507 +            mPointerSimple.hovering = true;
  1.5508 +
  1.5509 +            // Send hover enter.
  1.5510 +            NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
  1.5511 +                    AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
  1.5512 +                    mViewport.displayId,
  1.5513 +                    1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
  1.5514 +                    mOrientedXPrecision, mOrientedYPrecision,
  1.5515 +                    mPointerSimple.downTime);
  1.5516 +            getListener()->notifyMotion(&args);
  1.5517 +        }
  1.5518 +
  1.5519 +        // Send hover move.
  1.5520 +        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
  1.5521 +                AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
  1.5522 +                mViewport.displayId,
  1.5523 +                1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
  1.5524 +                mOrientedXPrecision, mOrientedYPrecision,
  1.5525 +                mPointerSimple.downTime);
  1.5526 +        getListener()->notifyMotion(&args);
  1.5527 +    }
  1.5528 +
  1.5529 +    if (mCurrentRawVScroll || mCurrentRawHScroll) {
  1.5530 +        float vscroll = mCurrentRawVScroll;
  1.5531 +        float hscroll = mCurrentRawHScroll;
  1.5532 +        mWheelYVelocityControl.move(when, NULL, &vscroll);
  1.5533 +        mWheelXVelocityControl.move(when, &hscroll, NULL);
  1.5534 +
  1.5535 +        // Send scroll.
  1.5536 +        PointerCoords pointerCoords;
  1.5537 +        pointerCoords.copyFrom(mPointerSimple.currentCoords);
  1.5538 +        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
  1.5539 +        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
  1.5540 +
  1.5541 +        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
  1.5542 +                AMOTION_EVENT_ACTION_SCROLL, 0, metaState, mCurrentButtonState, 0,
  1.5543 +                mViewport.displayId,
  1.5544 +                1, &mPointerSimple.currentProperties, &pointerCoords,
  1.5545 +                mOrientedXPrecision, mOrientedYPrecision,
  1.5546 +                mPointerSimple.downTime);
  1.5547 +        getListener()->notifyMotion(&args);
  1.5548 +    }
  1.5549 +
  1.5550 +    // Save state.
  1.5551 +    if (down || hovering) {
  1.5552 +        mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords);
  1.5553 +        mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
  1.5554 +    } else {
  1.5555 +        mPointerSimple.reset();
  1.5556 +    }
  1.5557 +}
  1.5558 +
  1.5559 +void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) {
  1.5560 +    mPointerSimple.currentCoords.clear();
  1.5561 +    mPointerSimple.currentProperties.clear();
  1.5562 +
  1.5563 +    dispatchPointerSimple(when, policyFlags, false, false);
  1.5564 +}
  1.5565 +
  1.5566 +void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
  1.5567 +        int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
  1.5568 +        const PointerProperties* properties, const PointerCoords* coords,
  1.5569 +        const uint32_t* idToIndex, BitSet32 idBits,
  1.5570 +        int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {
  1.5571 +    PointerCoords pointerCoords[MAX_POINTERS];
  1.5572 +    PointerProperties pointerProperties[MAX_POINTERS];
  1.5573 +    uint32_t pointerCount = 0;
  1.5574 +    while (!idBits.isEmpty()) {
  1.5575 +        uint32_t id = idBits.clearFirstMarkedBit();
  1.5576 +        uint32_t index = idToIndex[id];
  1.5577 +        pointerProperties[pointerCount].copyFrom(properties[index]);
  1.5578 +        pointerCoords[pointerCount].copyFrom(coords[index]);
  1.5579 +
  1.5580 +        if (changedId >= 0 && id == uint32_t(changedId)) {
  1.5581 +            action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
  1.5582 +        }
  1.5583 +
  1.5584 +        pointerCount += 1;
  1.5585 +    }
  1.5586 +
  1.5587 +    ALOG_ASSERT(pointerCount != 0);
  1.5588 +
  1.5589 +    if (changedId >= 0 && pointerCount == 1) {
  1.5590 +        // Replace initial down and final up action.
  1.5591 +        // We can compare the action without masking off the changed pointer index
  1.5592 +        // because we know the index is 0.
  1.5593 +        if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
  1.5594 +            action = AMOTION_EVENT_ACTION_DOWN;
  1.5595 +        } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
  1.5596 +            action = AMOTION_EVENT_ACTION_UP;
  1.5597 +        } else {
  1.5598 +            // Can't happen.
  1.5599 +            ALOG_ASSERT(false);
  1.5600 +        }
  1.5601 +    }
  1.5602 +
  1.5603 +    NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
  1.5604 +            action, flags, metaState, buttonState, edgeFlags,
  1.5605 +            mViewport.displayId, pointerCount, pointerProperties, pointerCoords,
  1.5606 +            xPrecision, yPrecision, downTime);
  1.5607 +    getListener()->notifyMotion(&args);
  1.5608 +}
  1.5609 +
  1.5610 +bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties,
  1.5611 +        const PointerCoords* inCoords, const uint32_t* inIdToIndex,
  1.5612 +        PointerProperties* outProperties, PointerCoords* outCoords, const uint32_t* outIdToIndex,
  1.5613 +        BitSet32 idBits) const {
  1.5614 +    bool changed = false;
  1.5615 +    while (!idBits.isEmpty()) {
  1.5616 +        uint32_t id = idBits.clearFirstMarkedBit();
  1.5617 +        uint32_t inIndex = inIdToIndex[id];
  1.5618 +        uint32_t outIndex = outIdToIndex[id];
  1.5619 +
  1.5620 +        const PointerProperties& curInProperties = inProperties[inIndex];
  1.5621 +        const PointerCoords& curInCoords = inCoords[inIndex];
  1.5622 +        PointerProperties& curOutProperties = outProperties[outIndex];
  1.5623 +        PointerCoords& curOutCoords = outCoords[outIndex];
  1.5624 +
  1.5625 +        if (curInProperties != curOutProperties) {
  1.5626 +            curOutProperties.copyFrom(curInProperties);
  1.5627 +            changed = true;
  1.5628 +        }
  1.5629 +
  1.5630 +        if (curInCoords != curOutCoords) {
  1.5631 +            curOutCoords.copyFrom(curInCoords);
  1.5632 +            changed = true;
  1.5633 +        }
  1.5634 +    }
  1.5635 +    return changed;
  1.5636 +}
  1.5637 +
  1.5638 +void TouchInputMapper::fadePointer() {
  1.5639 +    if (mPointerController != NULL) {
  1.5640 +        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
  1.5641 +    }
  1.5642 +}
  1.5643 +
  1.5644 +bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
  1.5645 +    return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue
  1.5646 +            && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue;
  1.5647 +}
  1.5648 +
  1.5649 +const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(
  1.5650 +        int32_t x, int32_t y) {
  1.5651 +    size_t numVirtualKeys = mVirtualKeys.size();
  1.5652 +    for (size_t i = 0; i < numVirtualKeys; i++) {
  1.5653 +        const VirtualKey& virtualKey = mVirtualKeys[i];
  1.5654 +
  1.5655 +#if DEBUG_VIRTUAL_KEYS
  1.5656 +        ALOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
  1.5657 +                "left=%d, top=%d, right=%d, bottom=%d",
  1.5658 +                x, y,
  1.5659 +                virtualKey.keyCode, virtualKey.scanCode,
  1.5660 +                virtualKey.hitLeft, virtualKey.hitTop,
  1.5661 +                virtualKey.hitRight, virtualKey.hitBottom);
  1.5662 +#endif
  1.5663 +
  1.5664 +        if (virtualKey.isHit(x, y)) {
  1.5665 +            return & virtualKey;
  1.5666 +        }
  1.5667 +    }
  1.5668 +
  1.5669 +    return NULL;
  1.5670 +}
  1.5671 +
  1.5672 +void TouchInputMapper::assignPointerIds() {
  1.5673 +    uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount;
  1.5674 +    uint32_t lastPointerCount = mLastRawPointerData.pointerCount;
  1.5675 +
  1.5676 +    mCurrentRawPointerData.clearIdBits();
  1.5677 +
  1.5678 +    if (currentPointerCount == 0) {
  1.5679 +        // No pointers to assign.
  1.5680 +        return;
  1.5681 +    }
  1.5682 +
  1.5683 +    if (lastPointerCount == 0) {
  1.5684 +        // All pointers are new.
  1.5685 +        for (uint32_t i = 0; i < currentPointerCount; i++) {
  1.5686 +            uint32_t id = i;
  1.5687 +            mCurrentRawPointerData.pointers[i].id = id;
  1.5688 +            mCurrentRawPointerData.idToIndex[id] = i;
  1.5689 +            mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(i));
  1.5690 +        }
  1.5691 +        return;
  1.5692 +    }
  1.5693 +
  1.5694 +    if (currentPointerCount == 1 && lastPointerCount == 1
  1.5695 +            && mCurrentRawPointerData.pointers[0].toolType
  1.5696 +                    == mLastRawPointerData.pointers[0].toolType) {
  1.5697 +        // Only one pointer and no change in count so it must have the same id as before.
  1.5698 +        uint32_t id = mLastRawPointerData.pointers[0].id;
  1.5699 +        mCurrentRawPointerData.pointers[0].id = id;
  1.5700 +        mCurrentRawPointerData.idToIndex[id] = 0;
  1.5701 +        mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(0));
  1.5702 +        return;
  1.5703 +    }
  1.5704 +
  1.5705 +    // General case.
  1.5706 +    // We build a heap of squared euclidean distances between current and last pointers
  1.5707 +    // associated with the current and last pointer indices.  Then, we find the best
  1.5708 +    // match (by distance) for each current pointer.
  1.5709 +    // The pointers must have the same tool type but it is possible for them to
  1.5710 +    // transition from hovering to touching or vice-versa while retaining the same id.
  1.5711 +    PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
  1.5712 +
  1.5713 +    uint32_t heapSize = 0;
  1.5714 +    for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
  1.5715 +            currentPointerIndex++) {
  1.5716 +        for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
  1.5717 +                lastPointerIndex++) {
  1.5718 +            const RawPointerData::Pointer& currentPointer =
  1.5719 +                    mCurrentRawPointerData.pointers[currentPointerIndex];
  1.5720 +            const RawPointerData::Pointer& lastPointer =
  1.5721 +                    mLastRawPointerData.pointers[lastPointerIndex];
  1.5722 +            if (currentPointer.toolType == lastPointer.toolType) {
  1.5723 +                int64_t deltaX = currentPointer.x - lastPointer.x;
  1.5724 +                int64_t deltaY = currentPointer.y - lastPointer.y;
  1.5725 +
  1.5726 +                uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
  1.5727 +
  1.5728 +                // Insert new element into the heap (sift up).
  1.5729 +                heap[heapSize].currentPointerIndex = currentPointerIndex;
  1.5730 +                heap[heapSize].lastPointerIndex = lastPointerIndex;
  1.5731 +                heap[heapSize].distance = distance;
  1.5732 +                heapSize += 1;
  1.5733 +            }
  1.5734 +        }
  1.5735 +    }
  1.5736 +
  1.5737 +    // Heapify
  1.5738 +    for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
  1.5739 +        startIndex -= 1;
  1.5740 +        for (uint32_t parentIndex = startIndex; ;) {
  1.5741 +            uint32_t childIndex = parentIndex * 2 + 1;
  1.5742 +            if (childIndex >= heapSize) {
  1.5743 +                break;
  1.5744 +            }
  1.5745 +
  1.5746 +            if (childIndex + 1 < heapSize
  1.5747 +                    && heap[childIndex + 1].distance < heap[childIndex].distance) {
  1.5748 +                childIndex += 1;
  1.5749 +            }
  1.5750 +
  1.5751 +            if (heap[parentIndex].distance <= heap[childIndex].distance) {
  1.5752 +                break;
  1.5753 +            }
  1.5754 +
  1.5755 +            swap(heap[parentIndex], heap[childIndex]);
  1.5756 +            parentIndex = childIndex;
  1.5757 +        }
  1.5758 +    }
  1.5759 +
  1.5760 +#if DEBUG_POINTER_ASSIGNMENT
  1.5761 +    ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
  1.5762 +    for (size_t i = 0; i < heapSize; i++) {
  1.5763 +        ALOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
  1.5764 +                i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
  1.5765 +                heap[i].distance);
  1.5766 +    }
  1.5767 +#endif
  1.5768 +
  1.5769 +    // Pull matches out by increasing order of distance.
  1.5770 +    // To avoid reassigning pointers that have already been matched, the loop keeps track
  1.5771 +    // of which last and current pointers have been matched using the matchedXXXBits variables.
  1.5772 +    // It also tracks the used pointer id bits.
  1.5773 +    BitSet32 matchedLastBits(0);
  1.5774 +    BitSet32 matchedCurrentBits(0);
  1.5775 +    BitSet32 usedIdBits(0);
  1.5776 +    bool first = true;
  1.5777 +    for (uint32_t i = min(currentPointerCount, lastPointerCount); heapSize > 0 && i > 0; i--) {
  1.5778 +        while (heapSize > 0) {
  1.5779 +            if (first) {
  1.5780 +                // The first time through the loop, we just consume the root element of
  1.5781 +                // the heap (the one with smallest distance).
  1.5782 +                first = false;
  1.5783 +            } else {
  1.5784 +                // Previous iterations consumed the root element of the heap.
  1.5785 +                // Pop root element off of the heap (sift down).
  1.5786 +                heap[0] = heap[heapSize];
  1.5787 +                for (uint32_t parentIndex = 0; ;) {
  1.5788 +                    uint32_t childIndex = parentIndex * 2 + 1;
  1.5789 +                    if (childIndex >= heapSize) {
  1.5790 +                        break;
  1.5791 +                    }
  1.5792 +
  1.5793 +                    if (childIndex + 1 < heapSize
  1.5794 +                            && heap[childIndex + 1].distance < heap[childIndex].distance) {
  1.5795 +                        childIndex += 1;
  1.5796 +                    }
  1.5797 +
  1.5798 +                    if (heap[parentIndex].distance <= heap[childIndex].distance) {
  1.5799 +                        break;
  1.5800 +                    }
  1.5801 +
  1.5802 +                    swap(heap[parentIndex], heap[childIndex]);
  1.5803 +                    parentIndex = childIndex;
  1.5804 +                }
  1.5805 +
  1.5806 +#if DEBUG_POINTER_ASSIGNMENT
  1.5807 +                ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
  1.5808 +                for (size_t i = 0; i < heapSize; i++) {
  1.5809 +                    ALOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
  1.5810 +                            i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
  1.5811 +                            heap[i].distance);
  1.5812 +                }
  1.5813 +#endif
  1.5814 +            }
  1.5815 +
  1.5816 +            heapSize -= 1;
  1.5817 +
  1.5818 +            uint32_t currentPointerIndex = heap[0].currentPointerIndex;
  1.5819 +            if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
  1.5820 +
  1.5821 +            uint32_t lastPointerIndex = heap[0].lastPointerIndex;
  1.5822 +            if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
  1.5823 +
  1.5824 +            matchedCurrentBits.markBit(currentPointerIndex);
  1.5825 +            matchedLastBits.markBit(lastPointerIndex);
  1.5826 +
  1.5827 +            uint32_t id = mLastRawPointerData.pointers[lastPointerIndex].id;
  1.5828 +            mCurrentRawPointerData.pointers[currentPointerIndex].id = id;
  1.5829 +            mCurrentRawPointerData.idToIndex[id] = currentPointerIndex;
  1.5830 +            mCurrentRawPointerData.markIdBit(id,
  1.5831 +                    mCurrentRawPointerData.isHovering(currentPointerIndex));
  1.5832 +            usedIdBits.markBit(id);
  1.5833 +
  1.5834 +#if DEBUG_POINTER_ASSIGNMENT
  1.5835 +            ALOGD("assignPointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
  1.5836 +                    lastPointerIndex, currentPointerIndex, id, heap[0].distance);
  1.5837 +#endif
  1.5838 +            break;
  1.5839 +        }
  1.5840 +    }
  1.5841 +
  1.5842 +    // Assign fresh ids to pointers that were not matched in the process.
  1.5843 +    for (uint32_t i = currentPointerCount - matchedCurrentBits.count(); i != 0; i--) {
  1.5844 +        uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit();
  1.5845 +        uint32_t id = usedIdBits.markFirstUnmarkedBit();
  1.5846 +
  1.5847 +        mCurrentRawPointerData.pointers[currentPointerIndex].id = id;
  1.5848 +        mCurrentRawPointerData.idToIndex[id] = currentPointerIndex;
  1.5849 +        mCurrentRawPointerData.markIdBit(id,
  1.5850 +                mCurrentRawPointerData.isHovering(currentPointerIndex));
  1.5851 +
  1.5852 +#if DEBUG_POINTER_ASSIGNMENT
  1.5853 +        ALOGD("assignPointerIds - assigned: cur=%d, id=%d",
  1.5854 +                currentPointerIndex, id);
  1.5855 +#endif
  1.5856 +    }
  1.5857 +}
  1.5858 +
  1.5859 +int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
  1.5860 +    if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) {
  1.5861 +        return AKEY_STATE_VIRTUAL;
  1.5862 +    }
  1.5863 +
  1.5864 +    size_t numVirtualKeys = mVirtualKeys.size();
  1.5865 +    for (size_t i = 0; i < numVirtualKeys; i++) {
  1.5866 +        const VirtualKey& virtualKey = mVirtualKeys[i];
  1.5867 +        if (virtualKey.keyCode == keyCode) {
  1.5868 +            return AKEY_STATE_UP;
  1.5869 +        }
  1.5870 +    }
  1.5871 +
  1.5872 +    return AKEY_STATE_UNKNOWN;
  1.5873 +}
  1.5874 +
  1.5875 +int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
  1.5876 +    if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) {
  1.5877 +        return AKEY_STATE_VIRTUAL;
  1.5878 +    }
  1.5879 +
  1.5880 +    size_t numVirtualKeys = mVirtualKeys.size();
  1.5881 +    for (size_t i = 0; i < numVirtualKeys; i++) {
  1.5882 +        const VirtualKey& virtualKey = mVirtualKeys[i];
  1.5883 +        if (virtualKey.scanCode == scanCode) {
  1.5884 +            return AKEY_STATE_UP;
  1.5885 +        }
  1.5886 +    }
  1.5887 +
  1.5888 +    return AKEY_STATE_UNKNOWN;
  1.5889 +}
  1.5890 +
  1.5891 +bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
  1.5892 +        const int32_t* keyCodes, uint8_t* outFlags) {
  1.5893 +    size_t numVirtualKeys = mVirtualKeys.size();
  1.5894 +    for (size_t i = 0; i < numVirtualKeys; i++) {
  1.5895 +        const VirtualKey& virtualKey = mVirtualKeys[i];
  1.5896 +
  1.5897 +        for (size_t i = 0; i < numCodes; i++) {
  1.5898 +            if (virtualKey.keyCode == keyCodes[i]) {
  1.5899 +                outFlags[i] = 1;
  1.5900 +            }
  1.5901 +        }
  1.5902 +    }
  1.5903 +
  1.5904 +    return true;
  1.5905 +}
  1.5906 +
  1.5907 +
  1.5908 +// --- SingleTouchInputMapper ---
  1.5909 +
  1.5910 +SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
  1.5911 +        TouchInputMapper(device) {
  1.5912 +}
  1.5913 +
  1.5914 +SingleTouchInputMapper::~SingleTouchInputMapper() {
  1.5915 +}
  1.5916 +
  1.5917 +void SingleTouchInputMapper::reset(nsecs_t when) {
  1.5918 +    mSingleTouchMotionAccumulator.reset(getDevice());
  1.5919 +
  1.5920 +    TouchInputMapper::reset(when);
  1.5921 +}
  1.5922 +
  1.5923 +void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
  1.5924 +    TouchInputMapper::process(rawEvent);
  1.5925 +
  1.5926 +    mSingleTouchMotionAccumulator.process(rawEvent);
  1.5927 +}
  1.5928 +
  1.5929 +void SingleTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) {
  1.5930 +    if (mTouchButtonAccumulator.isToolActive()) {
  1.5931 +        mCurrentRawPointerData.pointerCount = 1;
  1.5932 +        mCurrentRawPointerData.idToIndex[0] = 0;
  1.5933 +
  1.5934 +        bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
  1.5935 +                && (mTouchButtonAccumulator.isHovering()
  1.5936 +                        || (mRawPointerAxes.pressure.valid
  1.5937 +                                && mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0));
  1.5938 +        mCurrentRawPointerData.markIdBit(0, isHovering);
  1.5939 +
  1.5940 +        RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[0];
  1.5941 +        outPointer.id = 0;
  1.5942 +        outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
  1.5943 +        outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
  1.5944 +        outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
  1.5945 +        outPointer.touchMajor = 0;
  1.5946 +        outPointer.touchMinor = 0;
  1.5947 +        outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
  1.5948 +        outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
  1.5949 +        outPointer.orientation = 0;
  1.5950 +        outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
  1.5951 +        outPointer.tiltX = mSingleTouchMotionAccumulator.getAbsoluteTiltX();
  1.5952 +        outPointer.tiltY = mSingleTouchMotionAccumulator.getAbsoluteTiltY();
  1.5953 +        outPointer.toolType = mTouchButtonAccumulator.getToolType();
  1.5954 +        if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
  1.5955 +            outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
  1.5956 +        }
  1.5957 +        outPointer.isHovering = isHovering;
  1.5958 +    }
  1.5959 +}
  1.5960 +
  1.5961 +void SingleTouchInputMapper::configureRawPointerAxes() {
  1.5962 +    TouchInputMapper::configureRawPointerAxes();
  1.5963 +
  1.5964 +    getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x);
  1.5965 +    getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y);
  1.5966 +    getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure);
  1.5967 +    getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor);
  1.5968 +    getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance);
  1.5969 +    getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX);
  1.5970 +    getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY);
  1.5971 +}
  1.5972 +
  1.5973 +bool SingleTouchInputMapper::hasStylus() const {
  1.5974 +    return mTouchButtonAccumulator.hasStylus();
  1.5975 +}
  1.5976 +
  1.5977 +
  1.5978 +// --- MultiTouchInputMapper ---
  1.5979 +
  1.5980 +MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
  1.5981 +        TouchInputMapper(device) {
  1.5982 +}
  1.5983 +
  1.5984 +MultiTouchInputMapper::~MultiTouchInputMapper() {
  1.5985 +}
  1.5986 +
  1.5987 +void MultiTouchInputMapper::reset(nsecs_t when) {
  1.5988 +    mMultiTouchMotionAccumulator.reset(getDevice());
  1.5989 +
  1.5990 +    mPointerIdBits.clear();
  1.5991 +
  1.5992 +    TouchInputMapper::reset(when);
  1.5993 +}
  1.5994 +
  1.5995 +void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
  1.5996 +    TouchInputMapper::process(rawEvent);
  1.5997 +
  1.5998 +    mMultiTouchMotionAccumulator.process(rawEvent);
  1.5999 +}
  1.6000 +
  1.6001 +void MultiTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) {
  1.6002 +    size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
  1.6003 +    size_t outCount = 0;
  1.6004 +    BitSet32 newPointerIdBits;
  1.6005 +
  1.6006 +    for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
  1.6007 +        const MultiTouchMotionAccumulator::Slot* inSlot =
  1.6008 +                mMultiTouchMotionAccumulator.getSlot(inIndex);
  1.6009 +        if (!inSlot->isInUse()) {
  1.6010 +            continue;
  1.6011 +        }
  1.6012 +
  1.6013 +        if (outCount >= MAX_POINTERS) {
  1.6014 +#if DEBUG_POINTERS
  1.6015 +            ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
  1.6016 +                    "ignoring the rest.",
  1.6017 +                    getDeviceName().string(), MAX_POINTERS);
  1.6018 +#endif
  1.6019 +            break; // too many fingers!
  1.6020 +        }
  1.6021 +
  1.6022 +        RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[outCount];
  1.6023 +        outPointer.x = inSlot->getX();
  1.6024 +        outPointer.y = inSlot->getY();
  1.6025 +        outPointer.pressure = inSlot->getPressure();
  1.6026 +        outPointer.touchMajor = inSlot->getTouchMajor();
  1.6027 +        outPointer.touchMinor = inSlot->getTouchMinor();
  1.6028 +        outPointer.toolMajor = inSlot->getToolMajor();
  1.6029 +        outPointer.toolMinor = inSlot->getToolMinor();
  1.6030 +        outPointer.orientation = inSlot->getOrientation();
  1.6031 +        outPointer.distance = inSlot->getDistance();
  1.6032 +        outPointer.tiltX = 0;
  1.6033 +        outPointer.tiltY = 0;
  1.6034 +
  1.6035 +        outPointer.toolType = inSlot->getToolType();
  1.6036 +        if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
  1.6037 +            outPointer.toolType = mTouchButtonAccumulator.getToolType();
  1.6038 +            if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
  1.6039 +                outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
  1.6040 +            }
  1.6041 +        }
  1.6042 +
  1.6043 +        bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
  1.6044 +                && (mTouchButtonAccumulator.isHovering()
  1.6045 +                        || (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
  1.6046 +        outPointer.isHovering = isHovering;
  1.6047 +
  1.6048 +        // Assign pointer id using tracking id if available.
  1.6049 +        if (*outHavePointerIds) {
  1.6050 +            int32_t trackingId = inSlot->getTrackingId();
  1.6051 +            int32_t id = -1;
  1.6052 +            if (trackingId >= 0) {
  1.6053 +                for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
  1.6054 +                    uint32_t n = idBits.clearFirstMarkedBit();
  1.6055 +                    if (mPointerTrackingIdMap[n] == trackingId) {
  1.6056 +                        id = n;
  1.6057 +                    }
  1.6058 +                }
  1.6059 +
  1.6060 +                if (id < 0 && !mPointerIdBits.isFull()) {
  1.6061 +                    id = mPointerIdBits.markFirstUnmarkedBit();
  1.6062 +                    mPointerTrackingIdMap[id] = trackingId;
  1.6063 +                }
  1.6064 +            }
  1.6065 +            if (id < 0) {
  1.6066 +                *outHavePointerIds = false;
  1.6067 +                mCurrentRawPointerData.clearIdBits();
  1.6068 +                newPointerIdBits.clear();
  1.6069 +            } else {
  1.6070 +                outPointer.id = id;
  1.6071 +                mCurrentRawPointerData.idToIndex[id] = outCount;
  1.6072 +                mCurrentRawPointerData.markIdBit(id, isHovering);
  1.6073 +                newPointerIdBits.markBit(id);
  1.6074 +            }
  1.6075 +        }
  1.6076 +
  1.6077 +        outCount += 1;
  1.6078 +    }
  1.6079 +
  1.6080 +    mCurrentRawPointerData.pointerCount = outCount;
  1.6081 +    mPointerIdBits = newPointerIdBits;
  1.6082 +
  1.6083 +    mMultiTouchMotionAccumulator.finishSync();
  1.6084 +}
  1.6085 +
  1.6086 +void MultiTouchInputMapper::configureRawPointerAxes() {
  1.6087 +    TouchInputMapper::configureRawPointerAxes();
  1.6088 +
  1.6089 +    getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x);
  1.6090 +    getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y);
  1.6091 +    getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor);
  1.6092 +    getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor);
  1.6093 +    getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor);
  1.6094 +    getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor);
  1.6095 +    getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation);
  1.6096 +    getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure);
  1.6097 +    getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance);
  1.6098 +    getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId);
  1.6099 +    getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot);
  1.6100 +
  1.6101 +    if (mRawPointerAxes.trackingId.valid
  1.6102 +            && mRawPointerAxes.slot.valid
  1.6103 +            && mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
  1.6104 +        size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
  1.6105 +        if (slotCount > MAX_SLOTS) {
  1.6106 +            ALOGW("MultiTouch Device %s reported %d slots but the framework "
  1.6107 +                    "only supports a maximum of %d slots at this time.",
  1.6108 +                    getDeviceName().string(), slotCount, MAX_SLOTS);
  1.6109 +            slotCount = MAX_SLOTS;
  1.6110 +        }
  1.6111 +        mMultiTouchMotionAccumulator.configure(getDevice(),
  1.6112 +                slotCount, true /*usingSlotsProtocol*/);
  1.6113 +    } else {
  1.6114 +        mMultiTouchMotionAccumulator.configure(getDevice(),
  1.6115 +                MAX_POINTERS, false /*usingSlotsProtocol*/);
  1.6116 +    }
  1.6117 +}
  1.6118 +
  1.6119 +bool MultiTouchInputMapper::hasStylus() const {
  1.6120 +    return mMultiTouchMotionAccumulator.hasStylus()
  1.6121 +            || mTouchButtonAccumulator.hasStylus();
  1.6122 +}
  1.6123 +
  1.6124 +
  1.6125 +// --- JoystickInputMapper ---
  1.6126 +
  1.6127 +JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
  1.6128 +        InputMapper(device) {
  1.6129 +}
  1.6130 +
  1.6131 +JoystickInputMapper::~JoystickInputMapper() {
  1.6132 +}
  1.6133 +
  1.6134 +uint32_t JoystickInputMapper::getSources() {
  1.6135 +    return AINPUT_SOURCE_JOYSTICK;
  1.6136 +}
  1.6137 +
  1.6138 +void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
  1.6139 +    InputMapper::populateDeviceInfo(info);
  1.6140 +
  1.6141 +    for (size_t i = 0; i < mAxes.size(); i++) {
  1.6142 +        const Axis& axis = mAxes.valueAt(i);
  1.6143 +        addMotionRange(axis.axisInfo.axis, axis, info);
  1.6144 +
  1.6145 +        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
  1.6146 +            addMotionRange(axis.axisInfo.highAxis, axis, info);
  1.6147 +
  1.6148 +        }
  1.6149 +    }
  1.6150 +}
  1.6151 +
  1.6152 +void JoystickInputMapper::addMotionRange(int32_t axisId, const Axis& axis,
  1.6153 +        InputDeviceInfo* info) {
  1.6154 +    info->addMotionRange(axisId, AINPUT_SOURCE_JOYSTICK,
  1.6155 +            axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
  1.6156 +    /* In order to ease the transition for developers from using the old axes
  1.6157 +     * to the newer, more semantically correct axes, we'll continue to register
  1.6158 +     * the old axes as duplicates of their corresponding new ones.  */
  1.6159 +    int32_t compatAxis = getCompatAxis(axisId);
  1.6160 +    if (compatAxis >= 0) {
  1.6161 +        info->addMotionRange(compatAxis, AINPUT_SOURCE_JOYSTICK,
  1.6162 +                axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
  1.6163 +    }
  1.6164 +}
  1.6165 +
  1.6166 +/* A mapping from axes the joystick actually has to the axes that should be
  1.6167 + * artificially created for compatibility purposes.
  1.6168 + * Returns -1 if no compatibility axis is needed. */
  1.6169 +int32_t JoystickInputMapper::getCompatAxis(int32_t axis) {
  1.6170 +    switch(axis) {
  1.6171 +    case AMOTION_EVENT_AXIS_LTRIGGER:
  1.6172 +        return AMOTION_EVENT_AXIS_BRAKE;
  1.6173 +    case AMOTION_EVENT_AXIS_RTRIGGER:
  1.6174 +        return AMOTION_EVENT_AXIS_GAS;
  1.6175 +    }
  1.6176 +    return -1;
  1.6177 +}
  1.6178 +
  1.6179 +void JoystickInputMapper::dump(String8& dump) {
  1.6180 +    dump.append(INDENT2 "Joystick Input Mapper:\n");
  1.6181 +
  1.6182 +    dump.append(INDENT3 "Axes:\n");
  1.6183 +    size_t numAxes = mAxes.size();
  1.6184 +    for (size_t i = 0; i < numAxes; i++) {
  1.6185 +        const Axis& axis = mAxes.valueAt(i);
  1.6186 +        const char* label = getAxisLabel(axis.axisInfo.axis);
  1.6187 +        if (label) {
  1.6188 +            dump.appendFormat(INDENT4 "%s", label);
  1.6189 +        } else {
  1.6190 +            dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis);
  1.6191 +        }
  1.6192 +        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
  1.6193 +            label = getAxisLabel(axis.axisInfo.highAxis);
  1.6194 +            if (label) {
  1.6195 +                dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue);
  1.6196 +            } else {
  1.6197 +                dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis,
  1.6198 +                        axis.axisInfo.splitValue);
  1.6199 +            }
  1.6200 +        } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
  1.6201 +            dump.append(" (invert)");
  1.6202 +        }
  1.6203 +
  1.6204 +        dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f, resolution=%0.5f\n",
  1.6205 +                axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
  1.6206 +        dump.appendFormat(INDENT4 "  scale=%0.5f, offset=%0.5f, "
  1.6207 +                "highScale=%0.5f, highOffset=%0.5f\n",
  1.6208 +                axis.scale, axis.offset, axis.highScale, axis.highOffset);
  1.6209 +        dump.appendFormat(INDENT4 "  rawAxis=%d, rawMin=%d, rawMax=%d, "
  1.6210 +                "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n",
  1.6211 +                mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
  1.6212 +                axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, axis.rawAxisInfo.resolution);
  1.6213 +    }
  1.6214 +}
  1.6215 +
  1.6216 +void JoystickInputMapper::configure(nsecs_t when,
  1.6217 +        const InputReaderConfiguration* config, uint32_t changes) {
  1.6218 +    InputMapper::configure(when, config, changes);
  1.6219 +
  1.6220 +    if (!changes) { // first time only
  1.6221 +        // Collect all axes.
  1.6222 +        for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
  1.6223 +            if (!(getAbsAxisUsage(abs, getDevice()->getClasses())
  1.6224 +                    & INPUT_DEVICE_CLASS_JOYSTICK)) {
  1.6225 +                continue; // axis must be claimed by a different device
  1.6226 +            }
  1.6227 +
  1.6228 +            RawAbsoluteAxisInfo rawAxisInfo;
  1.6229 +            getAbsoluteAxisInfo(abs, &rawAxisInfo);
  1.6230 +            if (rawAxisInfo.valid) {
  1.6231 +                // Map axis.
  1.6232 +                AxisInfo axisInfo;
  1.6233 +                bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
  1.6234 +                if (!explicitlyMapped) {
  1.6235 +                    // Axis is not explicitly mapped, will choose a generic axis later.
  1.6236 +                    axisInfo.mode = AxisInfo::MODE_NORMAL;
  1.6237 +                    axisInfo.axis = -1;
  1.6238 +                }
  1.6239 +
  1.6240 +                // Apply flat override.
  1.6241 +                int32_t rawFlat = axisInfo.flatOverride < 0
  1.6242 +                        ? rawAxisInfo.flat : axisInfo.flatOverride;
  1.6243 +
  1.6244 +                // Calculate scaling factors and limits.
  1.6245 +                Axis axis;
  1.6246 +                if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
  1.6247 +                    float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
  1.6248 +                    float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
  1.6249 +                    axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
  1.6250 +                            scale, 0.0f, highScale, 0.0f,
  1.6251 +                            0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
  1.6252 +                            rawAxisInfo.resolution * scale);
  1.6253 +                } else if (isCenteredAxis(axisInfo.axis)) {
  1.6254 +                    float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
  1.6255 +                    float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
  1.6256 +                    axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
  1.6257 +                            scale, offset, scale, offset,
  1.6258 +                            -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
  1.6259 +                            rawAxisInfo.resolution * scale);
  1.6260 +                } else {
  1.6261 +                    float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
  1.6262 +                    axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
  1.6263 +                            scale, 0.0f, scale, 0.0f,
  1.6264 +                            0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
  1.6265 +                            rawAxisInfo.resolution * scale);
  1.6266 +                }
  1.6267 +
  1.6268 +                // To eliminate noise while the joystick is at rest, filter out small variations
  1.6269 +                // in axis values up front.
  1.6270 +                axis.filter = axis.flat * 0.25f;
  1.6271 +
  1.6272 +                mAxes.add(abs, axis);
  1.6273 +            }
  1.6274 +        }
  1.6275 +
  1.6276 +        // If there are too many axes, start dropping them.
  1.6277 +        // Prefer to keep explicitly mapped axes.
  1.6278 +        if (mAxes.size() > PointerCoords::MAX_AXES) {
  1.6279 +            ALOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
  1.6280 +                    getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
  1.6281 +            pruneAxes(true);
  1.6282 +            pruneAxes(false);
  1.6283 +        }
  1.6284 +
  1.6285 +        // Assign generic axis ids to remaining axes.
  1.6286 +        int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
  1.6287 +        size_t numAxes = mAxes.size();
  1.6288 +        for (size_t i = 0; i < numAxes; i++) {
  1.6289 +            Axis& axis = mAxes.editValueAt(i);
  1.6290 +            if (axis.axisInfo.axis < 0) {
  1.6291 +                while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
  1.6292 +                        && haveAxis(nextGenericAxisId)) {
  1.6293 +                    nextGenericAxisId += 1;
  1.6294 +                }
  1.6295 +
  1.6296 +                if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
  1.6297 +                    axis.axisInfo.axis = nextGenericAxisId;
  1.6298 +                    nextGenericAxisId += 1;
  1.6299 +                } else {
  1.6300 +                    ALOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
  1.6301 +                            "have already been assigned to other axes.",
  1.6302 +                            getDeviceName().string(), mAxes.keyAt(i));
  1.6303 +                    mAxes.removeItemsAt(i--);
  1.6304 +                    numAxes -= 1;
  1.6305 +                }
  1.6306 +            }
  1.6307 +        }
  1.6308 +    }
  1.6309 +}
  1.6310 +
  1.6311 +bool JoystickInputMapper::haveAxis(int32_t axisId) {
  1.6312 +    size_t numAxes = mAxes.size();
  1.6313 +    for (size_t i = 0; i < numAxes; i++) {
  1.6314 +        const Axis& axis = mAxes.valueAt(i);
  1.6315 +        if (axis.axisInfo.axis == axisId
  1.6316 +                || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
  1.6317 +                        && axis.axisInfo.highAxis == axisId)) {
  1.6318 +            return true;
  1.6319 +        }
  1.6320 +    }
  1.6321 +    return false;
  1.6322 +}
  1.6323 +
  1.6324 +void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
  1.6325 +    size_t i = mAxes.size();
  1.6326 +    while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
  1.6327 +        if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
  1.6328 +            continue;
  1.6329 +        }
  1.6330 +        ALOGI("Discarding joystick '%s' axis %d because there are too many axes.",
  1.6331 +                getDeviceName().string(), mAxes.keyAt(i));
  1.6332 +        mAxes.removeItemsAt(i);
  1.6333 +    }
  1.6334 +}
  1.6335 +
  1.6336 +bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
  1.6337 +    switch (axis) {
  1.6338 +    case AMOTION_EVENT_AXIS_X:
  1.6339 +    case AMOTION_EVENT_AXIS_Y:
  1.6340 +    case AMOTION_EVENT_AXIS_Z:
  1.6341 +    case AMOTION_EVENT_AXIS_RX:
  1.6342 +    case AMOTION_EVENT_AXIS_RY:
  1.6343 +    case AMOTION_EVENT_AXIS_RZ:
  1.6344 +    case AMOTION_EVENT_AXIS_HAT_X:
  1.6345 +    case AMOTION_EVENT_AXIS_HAT_Y:
  1.6346 +    case AMOTION_EVENT_AXIS_ORIENTATION:
  1.6347 +    case AMOTION_EVENT_AXIS_RUDDER:
  1.6348 +    case AMOTION_EVENT_AXIS_WHEEL:
  1.6349 +        return true;
  1.6350 +    default:
  1.6351 +        return false;
  1.6352 +    }
  1.6353 +}
  1.6354 +
  1.6355 +void JoystickInputMapper::reset(nsecs_t when) {
  1.6356 +    // Recenter all axes.
  1.6357 +    size_t numAxes = mAxes.size();
  1.6358 +    for (size_t i = 0; i < numAxes; i++) {
  1.6359 +        Axis& axis = mAxes.editValueAt(i);
  1.6360 +        axis.resetValue();
  1.6361 +    }
  1.6362 +
  1.6363 +    InputMapper::reset(when);
  1.6364 +}
  1.6365 +
  1.6366 +void JoystickInputMapper::process(const RawEvent* rawEvent) {
  1.6367 +    switch (rawEvent->type) {
  1.6368 +    case EV_ABS: {
  1.6369 +        ssize_t index = mAxes.indexOfKey(rawEvent->code);
  1.6370 +        if (index >= 0) {
  1.6371 +            Axis& axis = mAxes.editValueAt(index);
  1.6372 +            float newValue, highNewValue;
  1.6373 +            switch (axis.axisInfo.mode) {
  1.6374 +            case AxisInfo::MODE_INVERT:
  1.6375 +                newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
  1.6376 +                        * axis.scale + axis.offset;
  1.6377 +                highNewValue = 0.0f;
  1.6378 +                break;
  1.6379 +            case AxisInfo::MODE_SPLIT:
  1.6380 +                if (rawEvent->value < axis.axisInfo.splitValue) {
  1.6381 +                    newValue = (axis.axisInfo.splitValue - rawEvent->value)
  1.6382 +                            * axis.scale + axis.offset;
  1.6383 +                    highNewValue = 0.0f;
  1.6384 +                } else if (rawEvent->value > axis.axisInfo.splitValue) {
  1.6385 +                    newValue = 0.0f;
  1.6386 +                    highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
  1.6387 +                            * axis.highScale + axis.highOffset;
  1.6388 +                } else {
  1.6389 +                    newValue = 0.0f;
  1.6390 +                    highNewValue = 0.0f;
  1.6391 +                }
  1.6392 +                break;
  1.6393 +            default:
  1.6394 +                newValue = rawEvent->value * axis.scale + axis.offset;
  1.6395 +                highNewValue = 0.0f;
  1.6396 +                break;
  1.6397 +            }
  1.6398 +            axis.newValue = newValue;
  1.6399 +            axis.highNewValue = highNewValue;
  1.6400 +        }
  1.6401 +        break;
  1.6402 +    }
  1.6403 +
  1.6404 +    case EV_SYN:
  1.6405 +        switch (rawEvent->code) {
  1.6406 +        case SYN_REPORT:
  1.6407 +            sync(rawEvent->when, false /*force*/);
  1.6408 +            break;
  1.6409 +        }
  1.6410 +        break;
  1.6411 +    }
  1.6412 +}
  1.6413 +
  1.6414 +void JoystickInputMapper::sync(nsecs_t when, bool force) {
  1.6415 +    if (!filterAxes(force)) {
  1.6416 +        return;
  1.6417 +    }
  1.6418 +
  1.6419 +    int32_t metaState = mContext->getGlobalMetaState();
  1.6420 +    int32_t buttonState = 0;
  1.6421 +
  1.6422 +    PointerProperties pointerProperties;
  1.6423 +    pointerProperties.clear();
  1.6424 +    pointerProperties.id = 0;
  1.6425 +    pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
  1.6426 +
  1.6427 +    PointerCoords pointerCoords;
  1.6428 +    pointerCoords.clear();
  1.6429 +
  1.6430 +    size_t numAxes = mAxes.size();
  1.6431 +    for (size_t i = 0; i < numAxes; i++) {
  1.6432 +        const Axis& axis = mAxes.valueAt(i);
  1.6433 +        setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.axis, axis.currentValue);
  1.6434 +        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
  1.6435 +            setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.highAxis,
  1.6436 +                    axis.highCurrentValue);
  1.6437 +        }
  1.6438 +    }
  1.6439 +
  1.6440 +    // Moving a joystick axis should not wake the device because joysticks can
  1.6441 +    // be fairly noisy even when not in use.  On the other hand, pushing a gamepad
  1.6442 +    // button will likely wake the device.
  1.6443 +    // TODO: Use the input device configuration to control this behavior more finely.
  1.6444 +    uint32_t policyFlags = 0;
  1.6445 +
  1.6446 +    NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
  1.6447 +            AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
  1.6448 +            ADISPLAY_ID_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, 0);
  1.6449 +    getListener()->notifyMotion(&args);
  1.6450 +}
  1.6451 +
  1.6452 +void JoystickInputMapper::setPointerCoordsAxisValue(PointerCoords* pointerCoords,
  1.6453 +        int32_t axis, float value) {
  1.6454 +    pointerCoords->setAxisValue(axis, value);
  1.6455 +    /* In order to ease the transition for developers from using the old axes
  1.6456 +     * to the newer, more semantically correct axes, we'll continue to produce
  1.6457 +     * values for the old axes as mirrors of the value of their corresponding
  1.6458 +     * new axes. */
  1.6459 +    int32_t compatAxis = getCompatAxis(axis);
  1.6460 +    if (compatAxis >= 0) {
  1.6461 +        pointerCoords->setAxisValue(compatAxis, value);
  1.6462 +    }
  1.6463 +}
  1.6464 +
  1.6465 +bool JoystickInputMapper::filterAxes(bool force) {
  1.6466 +    bool atLeastOneSignificantChange = force;
  1.6467 +    size_t numAxes = mAxes.size();
  1.6468 +    for (size_t i = 0; i < numAxes; i++) {
  1.6469 +        Axis& axis = mAxes.editValueAt(i);
  1.6470 +        if (force || hasValueChangedSignificantly(axis.filter,
  1.6471 +                axis.newValue, axis.currentValue, axis.min, axis.max)) {
  1.6472 +            axis.currentValue = axis.newValue;
  1.6473 +            atLeastOneSignificantChange = true;
  1.6474 +        }
  1.6475 +        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
  1.6476 +            if (force || hasValueChangedSignificantly(axis.filter,
  1.6477 +                    axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
  1.6478 +                axis.highCurrentValue = axis.highNewValue;
  1.6479 +                atLeastOneSignificantChange = true;
  1.6480 +            }
  1.6481 +        }
  1.6482 +    }
  1.6483 +    return atLeastOneSignificantChange;
  1.6484 +}
  1.6485 +
  1.6486 +bool JoystickInputMapper::hasValueChangedSignificantly(
  1.6487 +        float filter, float newValue, float currentValue, float min, float max) {
  1.6488 +    if (newValue != currentValue) {
  1.6489 +        // Filter out small changes in value unless the value is converging on the axis
  1.6490 +        // bounds or center point.  This is intended to reduce the amount of information
  1.6491 +        // sent to applications by particularly noisy joysticks (such as PS3).
  1.6492 +        if (fabs(newValue - currentValue) > filter
  1.6493 +                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
  1.6494 +                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
  1.6495 +                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
  1.6496 +            return true;
  1.6497 +        }
  1.6498 +    }
  1.6499 +    return false;
  1.6500 +}
  1.6501 +
  1.6502 +bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
  1.6503 +        float filter, float newValue, float currentValue, float thresholdValue) {
  1.6504 +    float newDistance = fabs(newValue - thresholdValue);
  1.6505 +    if (newDistance < filter) {
  1.6506 +        float oldDistance = fabs(currentValue - thresholdValue);
  1.6507 +        if (newDistance < oldDistance) {
  1.6508 +            return true;
  1.6509 +        }
  1.6510 +    }
  1.6511 +    return false;
  1.6512 +}
  1.6513 +
  1.6514 +} // namespace android

mercurial