InputReader.cpp revision 9ee285afe740ff13d176c9d8430979dfd9575a23
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "InputReader"
18
19//#define LOG_NDEBUG 0
20
21// Log debug messages for each raw event received from the EventHub.
22#define DEBUG_RAW_EVENTS 0
23
24// Log debug messages about touch screen filtering hacks.
25#define DEBUG_HACKS 0
26
27// Log debug messages about virtual key processing.
28#define DEBUG_VIRTUAL_KEYS 0
29
30// Log debug messages about pointers.
31#define DEBUG_POINTERS 0
32
33// Log debug messages about pointer assignment calculations.
34#define DEBUG_POINTER_ASSIGNMENT 0
35
36// Log debug messages about gesture detection.
37#define DEBUG_GESTURES 0
38
39#include "InputReader.h"
40
41#include <cutils/log.h>
42#include <ui/Keyboard.h>
43#include <ui/VirtualKeyMap.h>
44
45#include <stddef.h>
46#include <stdlib.h>
47#include <unistd.h>
48#include <errno.h>
49#include <limits.h>
50#include <math.h>
51
52#define INDENT "  "
53#define INDENT2 "    "
54#define INDENT3 "      "
55#define INDENT4 "        "
56#define INDENT5 "          "
57
58namespace android {
59
60// --- Constants ---
61
62// Maximum number of slots supported when using the slot-based Multitouch Protocol B.
63static const size_t MAX_SLOTS = 32;
64
65// --- Static Functions ---
66
67template<typename T>
68inline static T abs(const T& value) {
69    return value < 0 ? - value : value;
70}
71
72template<typename T>
73inline static T min(const T& a, const T& b) {
74    return a < b ? a : b;
75}
76
77template<typename T>
78inline static void swap(T& a, T& b) {
79    T temp = a;
80    a = b;
81    b = temp;
82}
83
84inline static float avg(float x, float y) {
85    return (x + y) / 2;
86}
87
88inline static float distance(float x1, float y1, float x2, float y2) {
89    return hypotf(x1 - x2, y1 - y2);
90}
91
92inline static int32_t signExtendNybble(int32_t value) {
93    return value >= 8 ? value - 16 : value;
94}
95
96static inline const char* toString(bool value) {
97    return value ? "true" : "false";
98}
99
100static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
101        const int32_t map[][4], size_t mapSize) {
102    if (orientation != DISPLAY_ORIENTATION_0) {
103        for (size_t i = 0; i < mapSize; i++) {
104            if (value == map[i][0]) {
105                return map[i][orientation];
106            }
107        }
108    }
109    return value;
110}
111
112static const int32_t keyCodeRotationMap[][4] = {
113        // key codes enumerated counter-clockwise with the original (unrotated) key first
114        // no rotation,        90 degree rotation,  180 degree rotation, 270 degree rotation
115        { AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT },
116        { AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN },
117        { AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT },
118        { AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP },
119};
120static const size_t keyCodeRotationMapSize =
121        sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
122
123static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
124    return rotateValueUsingRotationMap(keyCode, orientation,
125            keyCodeRotationMap, keyCodeRotationMapSize);
126}
127
128static void rotateDelta(int32_t orientation, float* deltaX, float* deltaY) {
129    float temp;
130    switch (orientation) {
131    case DISPLAY_ORIENTATION_90:
132        temp = *deltaX;
133        *deltaX = *deltaY;
134        *deltaY = -temp;
135        break;
136
137    case DISPLAY_ORIENTATION_180:
138        *deltaX = -*deltaX;
139        *deltaY = -*deltaY;
140        break;
141
142    case DISPLAY_ORIENTATION_270:
143        temp = *deltaX;
144        *deltaX = -*deltaY;
145        *deltaY = temp;
146        break;
147    }
148}
149
150static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
151    return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
152}
153
154// Returns true if the pointer should be reported as being down given the specified
155// button states.  This determines whether the event is reported as a touch event.
156static bool isPointerDown(int32_t buttonState) {
157    return buttonState &
158            (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY
159                    | AMOTION_EVENT_BUTTON_TERTIARY);
160}
161
162static float calculateCommonVector(float a, float b) {
163    if (a > 0 && b > 0) {
164        return a < b ? a : b;
165    } else if (a < 0 && b < 0) {
166        return a > b ? a : b;
167    } else {
168        return 0;
169    }
170}
171
172static void synthesizeButtonKey(InputReaderContext* context, int32_t action,
173        nsecs_t when, int32_t deviceId, uint32_t source,
174        uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState,
175        int32_t buttonState, int32_t keyCode) {
176    if (
177            (action == AKEY_EVENT_ACTION_DOWN
178                    && !(lastButtonState & buttonState)
179                    && (currentButtonState & buttonState))
180            || (action == AKEY_EVENT_ACTION_UP
181                    && (lastButtonState & buttonState)
182                    && !(currentButtonState & buttonState))) {
183        NotifyKeyArgs args(when, deviceId, source, policyFlags,
184                action, 0, keyCode, 0, context->getGlobalMetaState(), when);
185        context->getListener()->notifyKey(&args);
186    }
187}
188
189static void synthesizeButtonKeys(InputReaderContext* context, int32_t action,
190        nsecs_t when, int32_t deviceId, uint32_t source,
191        uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) {
192    synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
193            lastButtonState, currentButtonState,
194            AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK);
195    synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
196            lastButtonState, currentButtonState,
197            AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD);
198}
199
200
201// --- InputReaderConfiguration ---
202
203bool InputReaderConfiguration::getDisplayInfo(int32_t displayId, bool external,
204        int32_t* width, int32_t* height, int32_t* orientation) const {
205    if (displayId == 0) {
206        const DisplayInfo& info = external ? mExternalDisplay : mInternalDisplay;
207        if (info.width > 0 && info.height > 0) {
208            if (width) {
209                *width = info.width;
210            }
211            if (height) {
212                *height = info.height;
213            }
214            if (orientation) {
215                *orientation = info.orientation;
216            }
217            return true;
218        }
219    }
220    return false;
221}
222
223void InputReaderConfiguration::setDisplayInfo(int32_t displayId, bool external,
224        int32_t width, int32_t height, int32_t orientation) {
225    if (displayId == 0) {
226        DisplayInfo& info = external ? mExternalDisplay : mInternalDisplay;
227        info.width = width;
228        info.height = height;
229        info.orientation = orientation;
230    }
231}
232
233
234// --- InputReader ---
235
236InputReader::InputReader(const sp<EventHubInterface>& eventHub,
237        const sp<InputReaderPolicyInterface>& policy,
238        const sp<InputListenerInterface>& listener) :
239        mContext(this), mEventHub(eventHub), mPolicy(policy),
240        mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
241        mConfigurationChangesToRefresh(0) {
242    mQueuedListener = new QueuedInputListener(listener);
243
244    { // acquire lock
245        AutoMutex _l(mLock);
246
247        refreshConfigurationLocked(0);
248        updateGlobalMetaStateLocked();
249        updateInputConfigurationLocked();
250    } // release lock
251}
252
253InputReader::~InputReader() {
254    for (size_t i = 0; i < mDevices.size(); i++) {
255        delete mDevices.valueAt(i);
256    }
257}
258
259void InputReader::loopOnce() {
260    int32_t timeoutMillis;
261    { // acquire lock
262        AutoMutex _l(mLock);
263
264        uint32_t changes = mConfigurationChangesToRefresh;
265        if (changes) {
266            mConfigurationChangesToRefresh = 0;
267            refreshConfigurationLocked(changes);
268        }
269
270        timeoutMillis = -1;
271        if (mNextTimeout != LLONG_MAX) {
272            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
273            timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
274        }
275    } // release lock
276
277    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
278
279    { // acquire lock
280        AutoMutex _l(mLock);
281
282        if (count) {
283            processEventsLocked(mEventBuffer, count);
284        }
285        if (!count || timeoutMillis == 0) {
286            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
287#if DEBUG_RAW_EVENTS
288            LOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
289#endif
290            mNextTimeout = LLONG_MAX;
291            timeoutExpiredLocked(now);
292        }
293    } // release lock
294
295    // Flush queued events out to the listener.
296    // This must happen outside of the lock because the listener could potentially call
297    // back into the InputReader's methods, such as getScanCodeState, or become blocked
298    // on another thread similarly waiting to acquire the InputReader lock thereby
299    // resulting in a deadlock.  This situation is actually quite plausible because the
300    // listener is actually the input dispatcher, which calls into the window manager,
301    // which occasionally calls into the input reader.
302    mQueuedListener->flush();
303}
304
305void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
306    for (const RawEvent* rawEvent = rawEvents; count;) {
307        int32_t type = rawEvent->type;
308        size_t batchSize = 1;
309        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
310            int32_t deviceId = rawEvent->deviceId;
311            while (batchSize < count) {
312                if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
313                        || rawEvent[batchSize].deviceId != deviceId) {
314                    break;
315                }
316                batchSize += 1;
317            }
318#if DEBUG_RAW_EVENTS
319            LOGD("BatchSize: %d Count: %d", batchSize, count);
320#endif
321            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
322        } else {
323            switch (rawEvent->type) {
324            case EventHubInterface::DEVICE_ADDED:
325                addDeviceLocked(rawEvent->when, rawEvent->deviceId);
326                break;
327            case EventHubInterface::DEVICE_REMOVED:
328                removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
329                break;
330            case EventHubInterface::FINISHED_DEVICE_SCAN:
331                handleConfigurationChangedLocked(rawEvent->when);
332                break;
333            default:
334                LOG_ASSERT(false); // can't happen
335                break;
336            }
337        }
338        count -= batchSize;
339        rawEvent += batchSize;
340    }
341}
342
343void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
344    String8 name = mEventHub->getDeviceName(deviceId);
345    uint32_t classes = mEventHub->getDeviceClasses(deviceId);
346
347    InputDevice* device = createDeviceLocked(deviceId, name, classes);
348    device->configure(when, &mConfig, 0);
349    device->reset(when);
350
351    if (device->isIgnored()) {
352        LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
353    } else {
354        LOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
355                device->getSources());
356    }
357
358    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
359    if (deviceIndex < 0) {
360        mDevices.add(deviceId, device);
361    } else {
362        LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
363        delete device;
364        return;
365    }
366}
367
368void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
369    InputDevice* device = NULL;
370    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
371    if (deviceIndex >= 0) {
372        device = mDevices.valueAt(deviceIndex);
373        mDevices.removeItemsAt(deviceIndex, 1);
374    } else {
375        LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
376        return;
377    }
378
379    if (device->isIgnored()) {
380        LOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
381                device->getId(), device->getName().string());
382    } else {
383        LOGI("Device removed: id=%d, name='%s', sources=0x%08x",
384                device->getId(), device->getName().string(), device->getSources());
385    }
386
387    device->reset(when);
388    delete device;
389}
390
391InputDevice* InputReader::createDeviceLocked(int32_t deviceId,
392        const String8& name, uint32_t classes) {
393    InputDevice* device = new InputDevice(&mContext, deviceId, name, classes);
394
395    // External devices.
396    if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
397        device->setExternal(true);
398    }
399
400    // Switch-like devices.
401    if (classes & INPUT_DEVICE_CLASS_SWITCH) {
402        device->addMapper(new SwitchInputMapper(device));
403    }
404
405    // Keyboard-like devices.
406    uint32_t keyboardSource = 0;
407    int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
408    if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
409        keyboardSource |= AINPUT_SOURCE_KEYBOARD;
410    }
411    if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
412        keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
413    }
414    if (classes & INPUT_DEVICE_CLASS_DPAD) {
415        keyboardSource |= AINPUT_SOURCE_DPAD;
416    }
417    if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
418        keyboardSource |= AINPUT_SOURCE_GAMEPAD;
419    }
420
421    if (keyboardSource != 0) {
422        device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
423    }
424
425    // Cursor-like devices.
426    if (classes & INPUT_DEVICE_CLASS_CURSOR) {
427        device->addMapper(new CursorInputMapper(device));
428    }
429
430    // Touchscreens and touchpad devices.
431    if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
432        device->addMapper(new MultiTouchInputMapper(device));
433    } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
434        device->addMapper(new SingleTouchInputMapper(device));
435    }
436
437    // Joystick-like devices.
438    if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
439        device->addMapper(new JoystickInputMapper(device));
440    }
441
442    return device;
443}
444
445void InputReader::processEventsForDeviceLocked(int32_t deviceId,
446        const RawEvent* rawEvents, size_t count) {
447    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
448    if (deviceIndex < 0) {
449        LOGW("Discarding event for unknown deviceId %d.", deviceId);
450        return;
451    }
452
453    InputDevice* device = mDevices.valueAt(deviceIndex);
454    if (device->isIgnored()) {
455        //LOGD("Discarding event for ignored deviceId %d.", deviceId);
456        return;
457    }
458
459    device->process(rawEvents, count);
460}
461
462void InputReader::timeoutExpiredLocked(nsecs_t when) {
463    for (size_t i = 0; i < mDevices.size(); i++) {
464        InputDevice* device = mDevices.valueAt(i);
465        if (!device->isIgnored()) {
466            device->timeoutExpired(when);
467        }
468    }
469}
470
471void InputReader::handleConfigurationChangedLocked(nsecs_t when) {
472    // Reset global meta state because it depends on the list of all configured devices.
473    updateGlobalMetaStateLocked();
474
475    // Update input configuration.
476    updateInputConfigurationLocked();
477
478    // Enqueue configuration changed.
479    NotifyConfigurationChangedArgs args(when);
480    mQueuedListener->notifyConfigurationChanged(&args);
481}
482
483void InputReader::refreshConfigurationLocked(uint32_t changes) {
484    mPolicy->getReaderConfiguration(&mConfig);
485    mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
486
487    if (changes) {
488        LOGI("Reconfiguring input devices.  changes=0x%08x", changes);
489        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
490
491        if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
492            mEventHub->requestReopenDevices();
493        } else {
494            for (size_t i = 0; i < mDevices.size(); i++) {
495                InputDevice* device = mDevices.valueAt(i);
496                device->configure(now, &mConfig, changes);
497            }
498        }
499    }
500}
501
502void InputReader::updateGlobalMetaStateLocked() {
503    mGlobalMetaState = 0;
504
505    for (size_t i = 0; i < mDevices.size(); i++) {
506        InputDevice* device = mDevices.valueAt(i);
507        mGlobalMetaState |= device->getMetaState();
508    }
509}
510
511int32_t InputReader::getGlobalMetaStateLocked() {
512    return mGlobalMetaState;
513}
514
515void InputReader::updateInputConfigurationLocked() {
516    int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
517    int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
518    int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
519    InputDeviceInfo deviceInfo;
520    for (size_t i = 0; i < mDevices.size(); i++) {
521        InputDevice* device = mDevices.valueAt(i);
522        device->getDeviceInfo(& deviceInfo);
523        uint32_t sources = deviceInfo.getSources();
524
525        if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
526            touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
527        }
528        if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
529            navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
530        } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
531            navigationConfig = InputConfiguration::NAVIGATION_DPAD;
532        }
533        if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
534            keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
535        }
536    }
537
538    mInputConfiguration.touchScreen = touchScreenConfig;
539    mInputConfiguration.keyboard = keyboardConfig;
540    mInputConfiguration.navigation = navigationConfig;
541}
542
543void InputReader::disableVirtualKeysUntilLocked(nsecs_t time) {
544    mDisableVirtualKeysTimeout = time;
545}
546
547bool InputReader::shouldDropVirtualKeyLocked(nsecs_t now,
548        InputDevice* device, int32_t keyCode, int32_t scanCode) {
549    if (now < mDisableVirtualKeysTimeout) {
550        LOGI("Dropping virtual key from device %s because virtual keys are "
551                "temporarily disabled for the next %0.3fms.  keyCode=%d, scanCode=%d",
552                device->getName().string(),
553                (mDisableVirtualKeysTimeout - now) * 0.000001,
554                keyCode, scanCode);
555        return true;
556    } else {
557        return false;
558    }
559}
560
561void InputReader::fadePointerLocked() {
562    for (size_t i = 0; i < mDevices.size(); i++) {
563        InputDevice* device = mDevices.valueAt(i);
564        device->fadePointer();
565    }
566}
567
568void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) {
569    if (when < mNextTimeout) {
570        mNextTimeout = when;
571    }
572}
573
574void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
575    AutoMutex _l(mLock);
576
577    *outConfiguration = mInputConfiguration;
578}
579
580status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
581    AutoMutex _l(mLock);
582
583    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
584    if (deviceIndex < 0) {
585        return NAME_NOT_FOUND;
586    }
587
588    InputDevice* device = mDevices.valueAt(deviceIndex);
589    if (device->isIgnored()) {
590        return NAME_NOT_FOUND;
591    }
592
593    device->getDeviceInfo(outDeviceInfo);
594    return OK;
595}
596
597void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
598    AutoMutex _l(mLock);
599
600    outDeviceIds.clear();
601
602    size_t numDevices = mDevices.size();
603    for (size_t i = 0; i < numDevices; i++) {
604        InputDevice* device = mDevices.valueAt(i);
605        if (!device->isIgnored()) {
606            outDeviceIds.add(device->getId());
607        }
608    }
609}
610
611int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
612        int32_t keyCode) {
613    AutoMutex _l(mLock);
614
615    return getStateLocked(deviceId, sourceMask, keyCode, &InputDevice::getKeyCodeState);
616}
617
618int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
619        int32_t scanCode) {
620    AutoMutex _l(mLock);
621
622    return getStateLocked(deviceId, sourceMask, scanCode, &InputDevice::getScanCodeState);
623}
624
625int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
626    AutoMutex _l(mLock);
627
628    return getStateLocked(deviceId, sourceMask, switchCode, &InputDevice::getSwitchState);
629}
630
631int32_t InputReader::getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
632        GetStateFunc getStateFunc) {
633    int32_t result = AKEY_STATE_UNKNOWN;
634    if (deviceId >= 0) {
635        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
636        if (deviceIndex >= 0) {
637            InputDevice* device = mDevices.valueAt(deviceIndex);
638            if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
639                result = (device->*getStateFunc)(sourceMask, code);
640            }
641        }
642    } else {
643        size_t numDevices = mDevices.size();
644        for (size_t i = 0; i < numDevices; i++) {
645            InputDevice* device = mDevices.valueAt(i);
646            if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
647                result = (device->*getStateFunc)(sourceMask, code);
648                if (result >= AKEY_STATE_DOWN) {
649                    return result;
650                }
651            }
652        }
653    }
654    return result;
655}
656
657bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
658        size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
659    AutoMutex _l(mLock);
660
661    memset(outFlags, 0, numCodes);
662    return markSupportedKeyCodesLocked(deviceId, sourceMask, numCodes, keyCodes, outFlags);
663}
664
665bool InputReader::markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask,
666        size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
667    bool result = false;
668    if (deviceId >= 0) {
669        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
670        if (deviceIndex >= 0) {
671            InputDevice* device = mDevices.valueAt(deviceIndex);
672            if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
673                result = device->markSupportedKeyCodes(sourceMask,
674                        numCodes, keyCodes, outFlags);
675            }
676        }
677    } else {
678        size_t numDevices = mDevices.size();
679        for (size_t i = 0; i < numDevices; i++) {
680            InputDevice* device = mDevices.valueAt(i);
681            if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
682                result |= device->markSupportedKeyCodes(sourceMask,
683                        numCodes, keyCodes, outFlags);
684            }
685        }
686    }
687    return result;
688}
689
690void InputReader::requestRefreshConfiguration(uint32_t changes) {
691    AutoMutex _l(mLock);
692
693    if (changes) {
694        bool needWake = !mConfigurationChangesToRefresh;
695        mConfigurationChangesToRefresh |= changes;
696
697        if (needWake) {
698            mEventHub->wake();
699        }
700    }
701}
702
703void InputReader::dump(String8& dump) {
704    AutoMutex _l(mLock);
705
706    mEventHub->dump(dump);
707    dump.append("\n");
708
709    dump.append("Input Reader State:\n");
710
711    for (size_t i = 0; i < mDevices.size(); i++) {
712        mDevices.valueAt(i)->dump(dump);
713    }
714
715    dump.append(INDENT "Configuration:\n");
716    dump.append(INDENT2 "ExcludedDeviceNames: [");
717    for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
718        if (i != 0) {
719            dump.append(", ");
720        }
721        dump.append(mConfig.excludedDeviceNames.itemAt(i).string());
722    }
723    dump.append("]\n");
724    dump.appendFormat(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
725            mConfig.virtualKeyQuietTime * 0.000001f);
726
727    dump.appendFormat(INDENT2 "PointerVelocityControlParameters: "
728            "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
729            mConfig.pointerVelocityControlParameters.scale,
730            mConfig.pointerVelocityControlParameters.lowThreshold,
731            mConfig.pointerVelocityControlParameters.highThreshold,
732            mConfig.pointerVelocityControlParameters.acceleration);
733
734    dump.appendFormat(INDENT2 "WheelVelocityControlParameters: "
735            "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
736            mConfig.wheelVelocityControlParameters.scale,
737            mConfig.wheelVelocityControlParameters.lowThreshold,
738            mConfig.wheelVelocityControlParameters.highThreshold,
739            mConfig.wheelVelocityControlParameters.acceleration);
740
741    dump.appendFormat(INDENT2 "PointerGesture:\n");
742    dump.appendFormat(INDENT3 "Enabled: %s\n",
743            toString(mConfig.pointerGesturesEnabled));
744    dump.appendFormat(INDENT3 "QuietInterval: %0.1fms\n",
745            mConfig.pointerGestureQuietInterval * 0.000001f);
746    dump.appendFormat(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
747            mConfig.pointerGestureDragMinSwitchSpeed);
748    dump.appendFormat(INDENT3 "TapInterval: %0.1fms\n",
749            mConfig.pointerGestureTapInterval * 0.000001f);
750    dump.appendFormat(INDENT3 "TapDragInterval: %0.1fms\n",
751            mConfig.pointerGestureTapDragInterval * 0.000001f);
752    dump.appendFormat(INDENT3 "TapSlop: %0.1fpx\n",
753            mConfig.pointerGestureTapSlop);
754    dump.appendFormat(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
755            mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
756    dump.appendFormat(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
757            mConfig.pointerGestureMultitouchMinDistance);
758    dump.appendFormat(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
759            mConfig.pointerGestureSwipeTransitionAngleCosine);
760    dump.appendFormat(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
761            mConfig.pointerGestureSwipeMaxWidthRatio);
762    dump.appendFormat(INDENT3 "MovementSpeedRatio: %0.1f\n",
763            mConfig.pointerGestureMovementSpeedRatio);
764    dump.appendFormat(INDENT3 "ZoomSpeedRatio: %0.1f\n",
765            mConfig.pointerGestureZoomSpeedRatio);
766}
767
768void InputReader::monitor() {
769    // Acquire and release the lock to ensure that the reader has not deadlocked.
770    mLock.lock();
771    mLock.unlock();
772
773    // Check the EventHub
774    mEventHub->monitor();
775}
776
777
778// --- InputReader::ContextImpl ---
779
780InputReader::ContextImpl::ContextImpl(InputReader* reader) :
781        mReader(reader) {
782}
783
784void InputReader::ContextImpl::updateGlobalMetaState() {
785    // lock is already held by the input loop
786    mReader->updateGlobalMetaStateLocked();
787}
788
789int32_t InputReader::ContextImpl::getGlobalMetaState() {
790    // lock is already held by the input loop
791    return mReader->getGlobalMetaStateLocked();
792}
793
794void InputReader::ContextImpl::disableVirtualKeysUntil(nsecs_t time) {
795    // lock is already held by the input loop
796    mReader->disableVirtualKeysUntilLocked(time);
797}
798
799bool InputReader::ContextImpl::shouldDropVirtualKey(nsecs_t now,
800        InputDevice* device, int32_t keyCode, int32_t scanCode) {
801    // lock is already held by the input loop
802    return mReader->shouldDropVirtualKeyLocked(now, device, keyCode, scanCode);
803}
804
805void InputReader::ContextImpl::fadePointer() {
806    // lock is already held by the input loop
807    mReader->fadePointerLocked();
808}
809
810void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) {
811    // lock is already held by the input loop
812    mReader->requestTimeoutAtTimeLocked(when);
813}
814
815InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() {
816    return mReader->mPolicy.get();
817}
818
819InputListenerInterface* InputReader::ContextImpl::getListener() {
820    return mReader->mQueuedListener.get();
821}
822
823EventHubInterface* InputReader::ContextImpl::getEventHub() {
824    return mReader->mEventHub.get();
825}
826
827
828// --- InputReaderThread ---
829
830InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
831        Thread(/*canCallJava*/ true), mReader(reader) {
832}
833
834InputReaderThread::~InputReaderThread() {
835}
836
837bool InputReaderThread::threadLoop() {
838    mReader->loopOnce();
839    return true;
840}
841
842
843// --- InputDevice ---
844
845InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name,
846        uint32_t classes) :
847        mContext(context), mId(id), mName(name), mClasses(classes),
848        mSources(0), mIsExternal(false), mDropUntilNextSync(false) {
849}
850
851InputDevice::~InputDevice() {
852    size_t numMappers = mMappers.size();
853    for (size_t i = 0; i < numMappers; i++) {
854        delete mMappers[i];
855    }
856    mMappers.clear();
857}
858
859void InputDevice::dump(String8& dump) {
860    InputDeviceInfo deviceInfo;
861    getDeviceInfo(& deviceInfo);
862
863    dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
864            deviceInfo.getName().string());
865    dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
866    dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
867    dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
868
869    const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
870    if (!ranges.isEmpty()) {
871        dump.append(INDENT2 "Motion Ranges:\n");
872        for (size_t i = 0; i < ranges.size(); i++) {
873            const InputDeviceInfo::MotionRange& range = ranges.itemAt(i);
874            const char* label = getAxisLabel(range.axis);
875            char name[32];
876            if (label) {
877                strncpy(name, label, sizeof(name));
878                name[sizeof(name) - 1] = '\0';
879            } else {
880                snprintf(name, sizeof(name), "%d", range.axis);
881            }
882            dump.appendFormat(INDENT3 "%s: source=0x%08x, "
883                    "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
884                    name, range.source, range.min, range.max, range.flat, range.fuzz);
885        }
886    }
887
888    size_t numMappers = mMappers.size();
889    for (size_t i = 0; i < numMappers; i++) {
890        InputMapper* mapper = mMappers[i];
891        mapper->dump(dump);
892    }
893}
894
895void InputDevice::addMapper(InputMapper* mapper) {
896    mMappers.add(mapper);
897}
898
899void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) {
900    mSources = 0;
901
902    if (!isIgnored()) {
903        if (!changes) { // first time only
904            mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
905        }
906
907        size_t numMappers = mMappers.size();
908        for (size_t i = 0; i < numMappers; i++) {
909            InputMapper* mapper = mMappers[i];
910            mapper->configure(when, config, changes);
911            mSources |= mapper->getSources();
912        }
913    }
914}
915
916void InputDevice::reset(nsecs_t when) {
917    size_t numMappers = mMappers.size();
918    for (size_t i = 0; i < numMappers; i++) {
919        InputMapper* mapper = mMappers[i];
920        mapper->reset(when);
921    }
922
923    mContext->updateGlobalMetaState();
924
925    notifyReset(when);
926}
927
928void InputDevice::process(const RawEvent* rawEvents, size_t count) {
929    // Process all of the events in order for each mapper.
930    // We cannot simply ask each mapper to process them in bulk because mappers may
931    // have side-effects that must be interleaved.  For example, joystick movement events and
932    // gamepad button presses are handled by different mappers but they should be dispatched
933    // in the order received.
934    size_t numMappers = mMappers.size();
935    for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
936#if DEBUG_RAW_EVENTS
937        LOGD("Input event: device=%d type=0x%04x scancode=0x%04x "
938                "keycode=0x%04x value=0x%08x flags=0x%08x",
939                rawEvent->deviceId, rawEvent->type, rawEvent->scanCode, rawEvent->keyCode,
940                rawEvent->value, rawEvent->flags);
941#endif
942
943        if (mDropUntilNextSync) {
944            if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
945                mDropUntilNextSync = false;
946#if DEBUG_RAW_EVENTS
947                LOGD("Recovered from input event buffer overrun.");
948#endif
949            } else {
950#if DEBUG_RAW_EVENTS
951                LOGD("Dropped input event while waiting for next input sync.");
952#endif
953            }
954        } else if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_DROPPED) {
955            LOGI("Detected input event buffer overrun for device %s.", mName.string());
956            mDropUntilNextSync = true;
957            reset(rawEvent->when);
958        } else {
959            for (size_t i = 0; i < numMappers; i++) {
960                InputMapper* mapper = mMappers[i];
961                mapper->process(rawEvent);
962            }
963        }
964    }
965}
966
967void InputDevice::timeoutExpired(nsecs_t when) {
968    size_t numMappers = mMappers.size();
969    for (size_t i = 0; i < numMappers; i++) {
970        InputMapper* mapper = mMappers[i];
971        mapper->timeoutExpired(when);
972    }
973}
974
975void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
976    outDeviceInfo->initialize(mId, mName);
977
978    size_t numMappers = mMappers.size();
979    for (size_t i = 0; i < numMappers; i++) {
980        InputMapper* mapper = mMappers[i];
981        mapper->populateDeviceInfo(outDeviceInfo);
982    }
983}
984
985int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
986    return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
987}
988
989int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
990    return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
991}
992
993int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
994    return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
995}
996
997int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
998    int32_t result = AKEY_STATE_UNKNOWN;
999    size_t numMappers = mMappers.size();
1000    for (size_t i = 0; i < numMappers; i++) {
1001        InputMapper* mapper = mMappers[i];
1002        if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
1003            result = (mapper->*getStateFunc)(sourceMask, code);
1004            if (result >= AKEY_STATE_DOWN) {
1005                return result;
1006            }
1007        }
1008    }
1009    return result;
1010}
1011
1012bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1013        const int32_t* keyCodes, uint8_t* outFlags) {
1014    bool result = false;
1015    size_t numMappers = mMappers.size();
1016    for (size_t i = 0; i < numMappers; i++) {
1017        InputMapper* mapper = mMappers[i];
1018        if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
1019            result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
1020        }
1021    }
1022    return result;
1023}
1024
1025int32_t InputDevice::getMetaState() {
1026    int32_t result = 0;
1027    size_t numMappers = mMappers.size();
1028    for (size_t i = 0; i < numMappers; i++) {
1029        InputMapper* mapper = mMappers[i];
1030        result |= mapper->getMetaState();
1031    }
1032    return result;
1033}
1034
1035void InputDevice::fadePointer() {
1036    size_t numMappers = mMappers.size();
1037    for (size_t i = 0; i < numMappers; i++) {
1038        InputMapper* mapper = mMappers[i];
1039        mapper->fadePointer();
1040    }
1041}
1042
1043void InputDevice::notifyReset(nsecs_t when) {
1044    NotifyDeviceResetArgs args(when, mId);
1045    mContext->getListener()->notifyDeviceReset(&args);
1046}
1047
1048
1049// --- CursorButtonAccumulator ---
1050
1051CursorButtonAccumulator::CursorButtonAccumulator() {
1052    clearButtons();
1053}
1054
1055void CursorButtonAccumulator::reset(InputDevice* device) {
1056    mBtnLeft = device->isKeyPressed(BTN_LEFT);
1057    mBtnRight = device->isKeyPressed(BTN_RIGHT);
1058    mBtnMiddle = device->isKeyPressed(BTN_MIDDLE);
1059    mBtnBack = device->isKeyPressed(BTN_BACK);
1060    mBtnSide = device->isKeyPressed(BTN_SIDE);
1061    mBtnForward = device->isKeyPressed(BTN_FORWARD);
1062    mBtnExtra = device->isKeyPressed(BTN_EXTRA);
1063    mBtnTask = device->isKeyPressed(BTN_TASK);
1064}
1065
1066void CursorButtonAccumulator::clearButtons() {
1067    mBtnLeft = 0;
1068    mBtnRight = 0;
1069    mBtnMiddle = 0;
1070    mBtnBack = 0;
1071    mBtnSide = 0;
1072    mBtnForward = 0;
1073    mBtnExtra = 0;
1074    mBtnTask = 0;
1075}
1076
1077void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
1078    if (rawEvent->type == EV_KEY) {
1079        switch (rawEvent->scanCode) {
1080        case BTN_LEFT:
1081            mBtnLeft = rawEvent->value;
1082            break;
1083        case BTN_RIGHT:
1084            mBtnRight = rawEvent->value;
1085            break;
1086        case BTN_MIDDLE:
1087            mBtnMiddle = rawEvent->value;
1088            break;
1089        case BTN_BACK:
1090            mBtnBack = rawEvent->value;
1091            break;
1092        case BTN_SIDE:
1093            mBtnSide = rawEvent->value;
1094            break;
1095        case BTN_FORWARD:
1096            mBtnForward = rawEvent->value;
1097            break;
1098        case BTN_EXTRA:
1099            mBtnExtra = rawEvent->value;
1100            break;
1101        case BTN_TASK:
1102            mBtnTask = rawEvent->value;
1103            break;
1104        }
1105    }
1106}
1107
1108uint32_t CursorButtonAccumulator::getButtonState() const {
1109    uint32_t result = 0;
1110    if (mBtnLeft) {
1111        result |= AMOTION_EVENT_BUTTON_PRIMARY;
1112    }
1113    if (mBtnRight) {
1114        result |= AMOTION_EVENT_BUTTON_SECONDARY;
1115    }
1116    if (mBtnMiddle) {
1117        result |= AMOTION_EVENT_BUTTON_TERTIARY;
1118    }
1119    if (mBtnBack || mBtnSide) {
1120        result |= AMOTION_EVENT_BUTTON_BACK;
1121    }
1122    if (mBtnForward || mBtnExtra) {
1123        result |= AMOTION_EVENT_BUTTON_FORWARD;
1124    }
1125    return result;
1126}
1127
1128
1129// --- CursorMotionAccumulator ---
1130
1131CursorMotionAccumulator::CursorMotionAccumulator() {
1132    clearRelativeAxes();
1133}
1134
1135void CursorMotionAccumulator::reset(InputDevice* device) {
1136    clearRelativeAxes();
1137}
1138
1139void CursorMotionAccumulator::clearRelativeAxes() {
1140    mRelX = 0;
1141    mRelY = 0;
1142}
1143
1144void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
1145    if (rawEvent->type == EV_REL) {
1146        switch (rawEvent->scanCode) {
1147        case REL_X:
1148            mRelX = rawEvent->value;
1149            break;
1150        case REL_Y:
1151            mRelY = rawEvent->value;
1152            break;
1153        }
1154    }
1155}
1156
1157void CursorMotionAccumulator::finishSync() {
1158    clearRelativeAxes();
1159}
1160
1161
1162// --- CursorScrollAccumulator ---
1163
1164CursorScrollAccumulator::CursorScrollAccumulator() :
1165        mHaveRelWheel(false), mHaveRelHWheel(false) {
1166    clearRelativeAxes();
1167}
1168
1169void CursorScrollAccumulator::configure(InputDevice* device) {
1170    mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
1171    mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
1172}
1173
1174void CursorScrollAccumulator::reset(InputDevice* device) {
1175    clearRelativeAxes();
1176}
1177
1178void CursorScrollAccumulator::clearRelativeAxes() {
1179    mRelWheel = 0;
1180    mRelHWheel = 0;
1181}
1182
1183void CursorScrollAccumulator::process(const RawEvent* rawEvent) {
1184    if (rawEvent->type == EV_REL) {
1185        switch (rawEvent->scanCode) {
1186        case REL_WHEEL:
1187            mRelWheel = rawEvent->value;
1188            break;
1189        case REL_HWHEEL:
1190            mRelHWheel = rawEvent->value;
1191            break;
1192        }
1193    }
1194}
1195
1196void CursorScrollAccumulator::finishSync() {
1197    clearRelativeAxes();
1198}
1199
1200
1201// --- TouchButtonAccumulator ---
1202
1203TouchButtonAccumulator::TouchButtonAccumulator() :
1204        mHaveBtnTouch(false) {
1205    clearButtons();
1206}
1207
1208void TouchButtonAccumulator::configure(InputDevice* device) {
1209    mHaveBtnTouch = device->hasKey(BTN_TOUCH);
1210}
1211
1212void TouchButtonAccumulator::reset(InputDevice* device) {
1213    mBtnTouch = device->isKeyPressed(BTN_TOUCH);
1214    mBtnStylus = device->isKeyPressed(BTN_STYLUS);
1215    mBtnStylus2 = device->isKeyPressed(BTN_STYLUS);
1216    mBtnToolFinger = device->isKeyPressed(BTN_TOOL_FINGER);
1217    mBtnToolPen = device->isKeyPressed(BTN_TOOL_PEN);
1218    mBtnToolRubber = device->isKeyPressed(BTN_TOOL_RUBBER);
1219    mBtnToolBrush = device->isKeyPressed(BTN_TOOL_BRUSH);
1220    mBtnToolPencil = device->isKeyPressed(BTN_TOOL_PENCIL);
1221    mBtnToolAirbrush = device->isKeyPressed(BTN_TOOL_AIRBRUSH);
1222    mBtnToolMouse = device->isKeyPressed(BTN_TOOL_MOUSE);
1223    mBtnToolLens = device->isKeyPressed(BTN_TOOL_LENS);
1224    mBtnToolDoubleTap = device->isKeyPressed(BTN_TOOL_DOUBLETAP);
1225    mBtnToolTripleTap = device->isKeyPressed(BTN_TOOL_TRIPLETAP);
1226    mBtnToolQuadTap = device->isKeyPressed(BTN_TOOL_QUADTAP);
1227}
1228
1229void TouchButtonAccumulator::clearButtons() {
1230    mBtnTouch = 0;
1231    mBtnStylus = 0;
1232    mBtnStylus2 = 0;
1233    mBtnToolFinger = 0;
1234    mBtnToolPen = 0;
1235    mBtnToolRubber = 0;
1236    mBtnToolBrush = 0;
1237    mBtnToolPencil = 0;
1238    mBtnToolAirbrush = 0;
1239    mBtnToolMouse = 0;
1240    mBtnToolLens = 0;
1241    mBtnToolDoubleTap = 0;
1242    mBtnToolTripleTap = 0;
1243    mBtnToolQuadTap = 0;
1244}
1245
1246void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
1247    if (rawEvent->type == EV_KEY) {
1248        switch (rawEvent->scanCode) {
1249        case BTN_TOUCH:
1250            mBtnTouch = rawEvent->value;
1251            break;
1252        case BTN_STYLUS:
1253            mBtnStylus = rawEvent->value;
1254            break;
1255        case BTN_STYLUS2:
1256            mBtnStylus2 = rawEvent->value;
1257            break;
1258        case BTN_TOOL_FINGER:
1259            mBtnToolFinger = rawEvent->value;
1260            break;
1261        case BTN_TOOL_PEN:
1262            mBtnToolPen = rawEvent->value;
1263            break;
1264        case BTN_TOOL_RUBBER:
1265            mBtnToolRubber = rawEvent->value;
1266            break;
1267        case BTN_TOOL_BRUSH:
1268            mBtnToolBrush = rawEvent->value;
1269            break;
1270        case BTN_TOOL_PENCIL:
1271            mBtnToolPencil = rawEvent->value;
1272            break;
1273        case BTN_TOOL_AIRBRUSH:
1274            mBtnToolAirbrush = rawEvent->value;
1275            break;
1276        case BTN_TOOL_MOUSE:
1277            mBtnToolMouse = rawEvent->value;
1278            break;
1279        case BTN_TOOL_LENS:
1280            mBtnToolLens = rawEvent->value;
1281            break;
1282        case BTN_TOOL_DOUBLETAP:
1283            mBtnToolDoubleTap = rawEvent->value;
1284            break;
1285        case BTN_TOOL_TRIPLETAP:
1286            mBtnToolTripleTap = rawEvent->value;
1287            break;
1288        case BTN_TOOL_QUADTAP:
1289            mBtnToolQuadTap = rawEvent->value;
1290            break;
1291        }
1292    }
1293}
1294
1295uint32_t TouchButtonAccumulator::getButtonState() const {
1296    uint32_t result = 0;
1297    if (mBtnStylus) {
1298        result |= AMOTION_EVENT_BUTTON_SECONDARY;
1299    }
1300    if (mBtnStylus2) {
1301        result |= AMOTION_EVENT_BUTTON_TERTIARY;
1302    }
1303    return result;
1304}
1305
1306int32_t TouchButtonAccumulator::getToolType() const {
1307    if (mBtnToolMouse || mBtnToolLens) {
1308        return AMOTION_EVENT_TOOL_TYPE_MOUSE;
1309    }
1310    if (mBtnToolRubber) {
1311        return AMOTION_EVENT_TOOL_TYPE_ERASER;
1312    }
1313    if (mBtnToolPen || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush) {
1314        return AMOTION_EVENT_TOOL_TYPE_STYLUS;
1315    }
1316    if (mBtnToolFinger || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap) {
1317        return AMOTION_EVENT_TOOL_TYPE_FINGER;
1318    }
1319    return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
1320}
1321
1322bool TouchButtonAccumulator::isToolActive() const {
1323    return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber
1324            || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush
1325            || mBtnToolMouse || mBtnToolLens
1326            || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap;
1327}
1328
1329bool TouchButtonAccumulator::isHovering() const {
1330    return mHaveBtnTouch && !mBtnTouch;
1331}
1332
1333
1334// --- RawPointerAxes ---
1335
1336RawPointerAxes::RawPointerAxes() {
1337    clear();
1338}
1339
1340void RawPointerAxes::clear() {
1341    x.clear();
1342    y.clear();
1343    pressure.clear();
1344    touchMajor.clear();
1345    touchMinor.clear();
1346    toolMajor.clear();
1347    toolMinor.clear();
1348    orientation.clear();
1349    distance.clear();
1350    tiltX.clear();
1351    tiltY.clear();
1352    trackingId.clear();
1353    slot.clear();
1354}
1355
1356
1357// --- RawPointerData ---
1358
1359RawPointerData::RawPointerData() {
1360    clear();
1361}
1362
1363void RawPointerData::clear() {
1364    pointerCount = 0;
1365    clearIdBits();
1366}
1367
1368void RawPointerData::copyFrom(const RawPointerData& other) {
1369    pointerCount = other.pointerCount;
1370    hoveringIdBits = other.hoveringIdBits;
1371    touchingIdBits = other.touchingIdBits;
1372
1373    for (uint32_t i = 0; i < pointerCount; i++) {
1374        pointers[i] = other.pointers[i];
1375
1376        int id = pointers[i].id;
1377        idToIndex[id] = other.idToIndex[id];
1378    }
1379}
1380
1381void RawPointerData::getCentroidOfTouchingPointers(float* outX, float* outY) const {
1382    float x = 0, y = 0;
1383    uint32_t count = touchingIdBits.count();
1384    if (count) {
1385        for (BitSet32 idBits(touchingIdBits); !idBits.isEmpty(); ) {
1386            uint32_t id = idBits.clearFirstMarkedBit();
1387            const Pointer& pointer = pointerForId(id);
1388            x += pointer.x;
1389            y += pointer.y;
1390        }
1391        x /= count;
1392        y /= count;
1393    }
1394    *outX = x;
1395    *outY = y;
1396}
1397
1398
1399// --- CookedPointerData ---
1400
1401CookedPointerData::CookedPointerData() {
1402    clear();
1403}
1404
1405void CookedPointerData::clear() {
1406    pointerCount = 0;
1407    hoveringIdBits.clear();
1408    touchingIdBits.clear();
1409}
1410
1411void CookedPointerData::copyFrom(const CookedPointerData& other) {
1412    pointerCount = other.pointerCount;
1413    hoveringIdBits = other.hoveringIdBits;
1414    touchingIdBits = other.touchingIdBits;
1415
1416    for (uint32_t i = 0; i < pointerCount; i++) {
1417        pointerProperties[i].copyFrom(other.pointerProperties[i]);
1418        pointerCoords[i].copyFrom(other.pointerCoords[i]);
1419
1420        int id = pointerProperties[i].id;
1421        idToIndex[id] = other.idToIndex[id];
1422    }
1423}
1424
1425
1426// --- SingleTouchMotionAccumulator ---
1427
1428SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() {
1429    clearAbsoluteAxes();
1430}
1431
1432void SingleTouchMotionAccumulator::reset(InputDevice* device) {
1433    mAbsX = device->getAbsoluteAxisValue(ABS_X);
1434    mAbsY = device->getAbsoluteAxisValue(ABS_Y);
1435    mAbsPressure = device->getAbsoluteAxisValue(ABS_PRESSURE);
1436    mAbsToolWidth = device->getAbsoluteAxisValue(ABS_TOOL_WIDTH);
1437    mAbsDistance = device->getAbsoluteAxisValue(ABS_DISTANCE);
1438    mAbsTiltX = device->getAbsoluteAxisValue(ABS_TILT_X);
1439    mAbsTiltY = device->getAbsoluteAxisValue(ABS_TILT_Y);
1440}
1441
1442void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
1443    mAbsX = 0;
1444    mAbsY = 0;
1445    mAbsPressure = 0;
1446    mAbsToolWidth = 0;
1447    mAbsDistance = 0;
1448    mAbsTiltX = 0;
1449    mAbsTiltY = 0;
1450}
1451
1452void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
1453    if (rawEvent->type == EV_ABS) {
1454        switch (rawEvent->scanCode) {
1455        case ABS_X:
1456            mAbsX = rawEvent->value;
1457            break;
1458        case ABS_Y:
1459            mAbsY = rawEvent->value;
1460            break;
1461        case ABS_PRESSURE:
1462            mAbsPressure = rawEvent->value;
1463            break;
1464        case ABS_TOOL_WIDTH:
1465            mAbsToolWidth = rawEvent->value;
1466            break;
1467        case ABS_DISTANCE:
1468            mAbsDistance = rawEvent->value;
1469            break;
1470        case ABS_TILT_X:
1471            mAbsTiltX = rawEvent->value;
1472            break;
1473        case ABS_TILT_Y:
1474            mAbsTiltY = rawEvent->value;
1475            break;
1476        }
1477    }
1478}
1479
1480
1481// --- MultiTouchMotionAccumulator ---
1482
1483MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() :
1484        mCurrentSlot(-1), mSlots(NULL), mSlotCount(0), mUsingSlotsProtocol(false) {
1485}
1486
1487MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
1488    delete[] mSlots;
1489}
1490
1491void MultiTouchMotionAccumulator::configure(size_t slotCount, bool usingSlotsProtocol) {
1492    mSlotCount = slotCount;
1493    mUsingSlotsProtocol = usingSlotsProtocol;
1494
1495    delete[] mSlots;
1496    mSlots = new Slot[slotCount];
1497}
1498
1499void MultiTouchMotionAccumulator::reset(InputDevice* device) {
1500    // Unfortunately there is no way to read the initial contents of the slots.
1501    // So when we reset the accumulator, we must assume they are all zeroes.
1502    if (mUsingSlotsProtocol) {
1503        // Query the driver for the current slot index and use it as the initial slot
1504        // before we start reading events from the device.  It is possible that the
1505        // current slot index will not be the same as it was when the first event was
1506        // written into the evdev buffer, which means the input mapper could start
1507        // out of sync with the initial state of the events in the evdev buffer.
1508        // In the extremely unlikely case that this happens, the data from
1509        // two slots will be confused until the next ABS_MT_SLOT event is received.
1510        // This can cause the touch point to "jump", but at least there will be
1511        // no stuck touches.
1512        int32_t initialSlot;
1513        status_t status = device->getEventHub()->getAbsoluteAxisValue(device->getId(),
1514                ABS_MT_SLOT, &initialSlot);
1515        if (status) {
1516            LOGD("Could not retrieve current multitouch slot index.  status=%d", status);
1517            initialSlot = -1;
1518        }
1519        clearSlots(initialSlot);
1520    } else {
1521        clearSlots(-1);
1522    }
1523}
1524
1525void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
1526    if (mSlots) {
1527        for (size_t i = 0; i < mSlotCount; i++) {
1528            mSlots[i].clear();
1529        }
1530    }
1531    mCurrentSlot = initialSlot;
1532}
1533
1534void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
1535    if (rawEvent->type == EV_ABS) {
1536        bool newSlot = false;
1537        if (mUsingSlotsProtocol) {
1538            if (rawEvent->scanCode == ABS_MT_SLOT) {
1539                mCurrentSlot = rawEvent->value;
1540                newSlot = true;
1541            }
1542        } else if (mCurrentSlot < 0) {
1543            mCurrentSlot = 0;
1544        }
1545
1546        if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
1547#if DEBUG_POINTERS
1548            if (newSlot) {
1549                LOGW("MultiTouch device emitted invalid slot index %d but it "
1550                        "should be between 0 and %d; ignoring this slot.",
1551                        mCurrentSlot, mSlotCount - 1);
1552            }
1553#endif
1554        } else {
1555            Slot* slot = &mSlots[mCurrentSlot];
1556
1557            switch (rawEvent->scanCode) {
1558            case ABS_MT_POSITION_X:
1559                slot->mInUse = true;
1560                slot->mAbsMTPositionX = rawEvent->value;
1561                break;
1562            case ABS_MT_POSITION_Y:
1563                slot->mInUse = true;
1564                slot->mAbsMTPositionY = rawEvent->value;
1565                break;
1566            case ABS_MT_TOUCH_MAJOR:
1567                slot->mInUse = true;
1568                slot->mAbsMTTouchMajor = rawEvent->value;
1569                break;
1570            case ABS_MT_TOUCH_MINOR:
1571                slot->mInUse = true;
1572                slot->mAbsMTTouchMinor = rawEvent->value;
1573                slot->mHaveAbsMTTouchMinor = true;
1574                break;
1575            case ABS_MT_WIDTH_MAJOR:
1576                slot->mInUse = true;
1577                slot->mAbsMTWidthMajor = rawEvent->value;
1578                break;
1579            case ABS_MT_WIDTH_MINOR:
1580                slot->mInUse = true;
1581                slot->mAbsMTWidthMinor = rawEvent->value;
1582                slot->mHaveAbsMTWidthMinor = true;
1583                break;
1584            case ABS_MT_ORIENTATION:
1585                slot->mInUse = true;
1586                slot->mAbsMTOrientation = rawEvent->value;
1587                break;
1588            case ABS_MT_TRACKING_ID:
1589                if (mUsingSlotsProtocol && rawEvent->value < 0) {
1590                    // The slot is no longer in use but it retains its previous contents,
1591                    // which may be reused for subsequent touches.
1592                    slot->mInUse = false;
1593                } else {
1594                    slot->mInUse = true;
1595                    slot->mAbsMTTrackingId = rawEvent->value;
1596                }
1597                break;
1598            case ABS_MT_PRESSURE:
1599                slot->mInUse = true;
1600                slot->mAbsMTPressure = rawEvent->value;
1601                break;
1602            case ABS_MT_DISTANCE:
1603                slot->mInUse = true;
1604                slot->mAbsMTDistance = rawEvent->value;
1605                break;
1606            case ABS_MT_TOOL_TYPE:
1607                slot->mInUse = true;
1608                slot->mAbsMTToolType = rawEvent->value;
1609                slot->mHaveAbsMTToolType = true;
1610                break;
1611            }
1612        }
1613    } else if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_MT_REPORT) {
1614        // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
1615        mCurrentSlot += 1;
1616    }
1617}
1618
1619void MultiTouchMotionAccumulator::finishSync() {
1620    if (!mUsingSlotsProtocol) {
1621        clearSlots(-1);
1622    }
1623}
1624
1625
1626// --- MultiTouchMotionAccumulator::Slot ---
1627
1628MultiTouchMotionAccumulator::Slot::Slot() {
1629    clear();
1630}
1631
1632void MultiTouchMotionAccumulator::Slot::clear() {
1633    mInUse = false;
1634    mHaveAbsMTTouchMinor = false;
1635    mHaveAbsMTWidthMinor = false;
1636    mHaveAbsMTToolType = false;
1637    mAbsMTPositionX = 0;
1638    mAbsMTPositionY = 0;
1639    mAbsMTTouchMajor = 0;
1640    mAbsMTTouchMinor = 0;
1641    mAbsMTWidthMajor = 0;
1642    mAbsMTWidthMinor = 0;
1643    mAbsMTOrientation = 0;
1644    mAbsMTTrackingId = -1;
1645    mAbsMTPressure = 0;
1646    mAbsMTDistance = 0;
1647    mAbsMTToolType = 0;
1648}
1649
1650int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
1651    if (mHaveAbsMTToolType) {
1652        switch (mAbsMTToolType) {
1653        case MT_TOOL_FINGER:
1654            return AMOTION_EVENT_TOOL_TYPE_FINGER;
1655        case MT_TOOL_PEN:
1656            return AMOTION_EVENT_TOOL_TYPE_STYLUS;
1657        }
1658    }
1659    return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
1660}
1661
1662
1663// --- InputMapper ---
1664
1665InputMapper::InputMapper(InputDevice* device) :
1666        mDevice(device), mContext(device->getContext()) {
1667}
1668
1669InputMapper::~InputMapper() {
1670}
1671
1672void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1673    info->addSource(getSources());
1674}
1675
1676void InputMapper::dump(String8& dump) {
1677}
1678
1679void InputMapper::configure(nsecs_t when,
1680        const InputReaderConfiguration* config, uint32_t changes) {
1681}
1682
1683void InputMapper::reset(nsecs_t when) {
1684}
1685
1686void InputMapper::timeoutExpired(nsecs_t when) {
1687}
1688
1689int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1690    return AKEY_STATE_UNKNOWN;
1691}
1692
1693int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1694    return AKEY_STATE_UNKNOWN;
1695}
1696
1697int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1698    return AKEY_STATE_UNKNOWN;
1699}
1700
1701bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1702        const int32_t* keyCodes, uint8_t* outFlags) {
1703    return false;
1704}
1705
1706int32_t InputMapper::getMetaState() {
1707    return 0;
1708}
1709
1710void InputMapper::fadePointer() {
1711}
1712
1713status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) {
1714    return getEventHub()->getAbsoluteAxisInfo(getDeviceId(), axis, axisInfo);
1715}
1716
1717void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
1718        const RawAbsoluteAxisInfo& axis, const char* name) {
1719    if (axis.valid) {
1720        dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d, resolution=%d\n",
1721                name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz, axis.resolution);
1722    } else {
1723        dump.appendFormat(INDENT4 "%s: unknown range\n", name);
1724    }
1725}
1726
1727
1728// --- SwitchInputMapper ---
1729
1730SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
1731        InputMapper(device) {
1732}
1733
1734SwitchInputMapper::~SwitchInputMapper() {
1735}
1736
1737uint32_t SwitchInputMapper::getSources() {
1738    return AINPUT_SOURCE_SWITCH;
1739}
1740
1741void SwitchInputMapper::process(const RawEvent* rawEvent) {
1742    switch (rawEvent->type) {
1743    case EV_SW:
1744        processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
1745        break;
1746    }
1747}
1748
1749void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
1750    NotifySwitchArgs args(when, 0, switchCode, switchValue);
1751    getListener()->notifySwitch(&args);
1752}
1753
1754int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1755    return getEventHub()->getSwitchState(getDeviceId(), switchCode);
1756}
1757
1758
1759// --- KeyboardInputMapper ---
1760
1761KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
1762        uint32_t source, int32_t keyboardType) :
1763        InputMapper(device), mSource(source),
1764        mKeyboardType(keyboardType) {
1765}
1766
1767KeyboardInputMapper::~KeyboardInputMapper() {
1768}
1769
1770uint32_t KeyboardInputMapper::getSources() {
1771    return mSource;
1772}
1773
1774void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1775    InputMapper::populateDeviceInfo(info);
1776
1777    info->setKeyboardType(mKeyboardType);
1778}
1779
1780void KeyboardInputMapper::dump(String8& dump) {
1781    dump.append(INDENT2 "Keyboard Input Mapper:\n");
1782    dumpParameters(dump);
1783    dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
1784    dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
1785    dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mKeyDowns.size());
1786    dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mMetaState);
1787    dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime);
1788}
1789
1790
1791void KeyboardInputMapper::configure(nsecs_t when,
1792        const InputReaderConfiguration* config, uint32_t changes) {
1793    InputMapper::configure(when, config, changes);
1794
1795    if (!changes) { // first time only
1796        // Configure basic parameters.
1797        configureParameters();
1798    }
1799
1800    if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
1801        if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
1802            if (!config->getDisplayInfo(mParameters.associatedDisplayId,
1803                        false /*external*/, NULL, NULL, &mOrientation)) {
1804                mOrientation = DISPLAY_ORIENTATION_0;
1805            }
1806        } else {
1807            mOrientation = DISPLAY_ORIENTATION_0;
1808        }
1809    }
1810}
1811
1812void KeyboardInputMapper::configureParameters() {
1813    mParameters.orientationAware = false;
1814    getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
1815            mParameters.orientationAware);
1816
1817    mParameters.associatedDisplayId = -1;
1818    if (mParameters.orientationAware) {
1819        mParameters.associatedDisplayId = 0;
1820    }
1821}
1822
1823void KeyboardInputMapper::dumpParameters(String8& dump) {
1824    dump.append(INDENT3 "Parameters:\n");
1825    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1826            mParameters.associatedDisplayId);
1827    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1828            toString(mParameters.orientationAware));
1829}
1830
1831void KeyboardInputMapper::reset(nsecs_t when) {
1832    mMetaState = AMETA_NONE;
1833    mDownTime = 0;
1834    mKeyDowns.clear();
1835
1836    resetLedState();
1837
1838    InputMapper::reset(when);
1839}
1840
1841void KeyboardInputMapper::process(const RawEvent* rawEvent) {
1842    switch (rawEvent->type) {
1843    case EV_KEY: {
1844        int32_t scanCode = rawEvent->scanCode;
1845        if (isKeyboardOrGamepadKey(scanCode)) {
1846            processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
1847                    rawEvent->flags);
1848        }
1849        break;
1850    }
1851    }
1852}
1853
1854bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
1855    return scanCode < BTN_MOUSE
1856        || scanCode >= KEY_OK
1857        || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE)
1858        || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
1859}
1860
1861void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
1862        int32_t scanCode, uint32_t policyFlags) {
1863
1864    if (down) {
1865        // Rotate key codes according to orientation if needed.
1866        if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
1867            keyCode = rotateKeyCode(keyCode, mOrientation);
1868        }
1869
1870        // Add key down.
1871        ssize_t keyDownIndex = findKeyDown(scanCode);
1872        if (keyDownIndex >= 0) {
1873            // key repeat, be sure to use same keycode as before in case of rotation
1874            keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
1875        } else {
1876            // key down
1877            if ((policyFlags & POLICY_FLAG_VIRTUAL)
1878                    && mContext->shouldDropVirtualKey(when,
1879                            getDevice(), keyCode, scanCode)) {
1880                return;
1881            }
1882
1883            mKeyDowns.push();
1884            KeyDown& keyDown = mKeyDowns.editTop();
1885            keyDown.keyCode = keyCode;
1886            keyDown.scanCode = scanCode;
1887        }
1888
1889        mDownTime = when;
1890    } else {
1891        // Remove key down.
1892        ssize_t keyDownIndex = findKeyDown(scanCode);
1893        if (keyDownIndex >= 0) {
1894            // key up, be sure to use same keycode as before in case of rotation
1895            keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
1896            mKeyDowns.removeAt(size_t(keyDownIndex));
1897        } else {
1898            // key was not actually down
1899            LOGI("Dropping key up from device %s because the key was not down.  "
1900                    "keyCode=%d, scanCode=%d",
1901                    getDeviceName().string(), keyCode, scanCode);
1902            return;
1903        }
1904    }
1905
1906    bool metaStateChanged = false;
1907    int32_t oldMetaState = mMetaState;
1908    int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
1909    if (oldMetaState != newMetaState) {
1910        mMetaState = newMetaState;
1911        metaStateChanged = true;
1912        updateLedState(false);
1913    }
1914
1915    nsecs_t downTime = mDownTime;
1916
1917    // Key down on external an keyboard should wake the device.
1918    // We don't do this for internal keyboards to prevent them from waking up in your pocket.
1919    // For internal keyboards, the key layout file should specify the policy flags for
1920    // each wake key individually.
1921    // TODO: Use the input device configuration to control this behavior more finely.
1922    if (down && getDevice()->isExternal()
1923            && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {
1924        policyFlags |= POLICY_FLAG_WAKE_DROPPED;
1925    }
1926
1927    if (metaStateChanged) {
1928        getContext()->updateGlobalMetaState();
1929    }
1930
1931    if (down && !isMetaKey(keyCode)) {
1932        getContext()->fadePointer();
1933    }
1934
1935    NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
1936            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
1937            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
1938    getListener()->notifyKey(&args);
1939}
1940
1941ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) {
1942    size_t n = mKeyDowns.size();
1943    for (size_t i = 0; i < n; i++) {
1944        if (mKeyDowns[i].scanCode == scanCode) {
1945            return i;
1946        }
1947    }
1948    return -1;
1949}
1950
1951int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1952    return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
1953}
1954
1955int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1956    return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1957}
1958
1959bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1960        const int32_t* keyCodes, uint8_t* outFlags) {
1961    return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1962}
1963
1964int32_t KeyboardInputMapper::getMetaState() {
1965    return mMetaState;
1966}
1967
1968void KeyboardInputMapper::resetLedState() {
1969    initializeLedState(mCapsLockLedState, LED_CAPSL);
1970    initializeLedState(mNumLockLedState, LED_NUML);
1971    initializeLedState(mScrollLockLedState, LED_SCROLLL);
1972
1973    updateLedState(true);
1974}
1975
1976void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
1977    ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
1978    ledState.on = false;
1979}
1980
1981void KeyboardInputMapper::updateLedState(bool reset) {
1982    updateLedStateForModifier(mCapsLockLedState, LED_CAPSL,
1983            AMETA_CAPS_LOCK_ON, reset);
1984    updateLedStateForModifier(mNumLockLedState, LED_NUML,
1985            AMETA_NUM_LOCK_ON, reset);
1986    updateLedStateForModifier(mScrollLockLedState, LED_SCROLLL,
1987            AMETA_SCROLL_LOCK_ON, reset);
1988}
1989
1990void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState,
1991        int32_t led, int32_t modifier, bool reset) {
1992    if (ledState.avail) {
1993        bool desiredState = (mMetaState & modifier) != 0;
1994        if (reset || ledState.on != desiredState) {
1995            getEventHub()->setLedState(getDeviceId(), led, desiredState);
1996            ledState.on = desiredState;
1997        }
1998    }
1999}
2000
2001
2002// --- CursorInputMapper ---
2003
2004CursorInputMapper::CursorInputMapper(InputDevice* device) :
2005        InputMapper(device) {
2006}
2007
2008CursorInputMapper::~CursorInputMapper() {
2009}
2010
2011uint32_t CursorInputMapper::getSources() {
2012    return mSource;
2013}
2014
2015void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
2016    InputMapper::populateDeviceInfo(info);
2017
2018    if (mParameters.mode == Parameters::MODE_POINTER) {
2019        float minX, minY, maxX, maxY;
2020        if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
2021            info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f);
2022            info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f);
2023        }
2024    } else {
2025        info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale);
2026        info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale);
2027    }
2028    info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f);
2029
2030    if (mCursorScrollAccumulator.haveRelativeVWheel()) {
2031        info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
2032    }
2033    if (mCursorScrollAccumulator.haveRelativeHWheel()) {
2034        info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
2035    }
2036}
2037
2038void CursorInputMapper::dump(String8& dump) {
2039    dump.append(INDENT2 "Cursor Input Mapper:\n");
2040    dumpParameters(dump);
2041    dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
2042    dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
2043    dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
2044    dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
2045    dump.appendFormat(INDENT3 "HaveVWheel: %s\n",
2046            toString(mCursorScrollAccumulator.haveRelativeVWheel()));
2047    dump.appendFormat(INDENT3 "HaveHWheel: %s\n",
2048            toString(mCursorScrollAccumulator.haveRelativeHWheel()));
2049    dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
2050    dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
2051    dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
2052    dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
2053    dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
2054    dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime);
2055}
2056
2057void CursorInputMapper::configure(nsecs_t when,
2058        const InputReaderConfiguration* config, uint32_t changes) {
2059    InputMapper::configure(when, config, changes);
2060
2061    if (!changes) { // first time only
2062        mCursorScrollAccumulator.configure(getDevice());
2063
2064        // Configure basic parameters.
2065        configureParameters();
2066
2067        // Configure device mode.
2068        switch (mParameters.mode) {
2069        case Parameters::MODE_POINTER:
2070            mSource = AINPUT_SOURCE_MOUSE;
2071            mXPrecision = 1.0f;
2072            mYPrecision = 1.0f;
2073            mXScale = 1.0f;
2074            mYScale = 1.0f;
2075            mPointerController = getPolicy()->obtainPointerController(getDeviceId());
2076            break;
2077        case Parameters::MODE_NAVIGATION:
2078            mSource = AINPUT_SOURCE_TRACKBALL;
2079            mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
2080            mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
2081            mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
2082            mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
2083            break;
2084        }
2085
2086        mVWheelScale = 1.0f;
2087        mHWheelScale = 1.0f;
2088    }
2089
2090    if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
2091        mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
2092        mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
2093        mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
2094    }
2095
2096    if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
2097        if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
2098            if (!config->getDisplayInfo(mParameters.associatedDisplayId,
2099                        false /*external*/, NULL, NULL, &mOrientation)) {
2100                mOrientation = DISPLAY_ORIENTATION_0;
2101            }
2102        } else {
2103            mOrientation = DISPLAY_ORIENTATION_0;
2104        }
2105    }
2106}
2107
2108void CursorInputMapper::configureParameters() {
2109    mParameters.mode = Parameters::MODE_POINTER;
2110    String8 cursorModeString;
2111    if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
2112        if (cursorModeString == "navigation") {
2113            mParameters.mode = Parameters::MODE_NAVIGATION;
2114        } else if (cursorModeString != "pointer" && cursorModeString != "default") {
2115            LOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
2116        }
2117    }
2118
2119    mParameters.orientationAware = false;
2120    getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
2121            mParameters.orientationAware);
2122
2123    mParameters.associatedDisplayId = -1;
2124    if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) {
2125        mParameters.associatedDisplayId = 0;
2126    }
2127}
2128
2129void CursorInputMapper::dumpParameters(String8& dump) {
2130    dump.append(INDENT3 "Parameters:\n");
2131    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
2132            mParameters.associatedDisplayId);
2133
2134    switch (mParameters.mode) {
2135    case Parameters::MODE_POINTER:
2136        dump.append(INDENT4 "Mode: pointer\n");
2137        break;
2138    case Parameters::MODE_NAVIGATION:
2139        dump.append(INDENT4 "Mode: navigation\n");
2140        break;
2141    default:
2142        LOG_ASSERT(false);
2143    }
2144
2145    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
2146            toString(mParameters.orientationAware));
2147}
2148
2149void CursorInputMapper::reset(nsecs_t when) {
2150    mButtonState = 0;
2151    mDownTime = 0;
2152
2153    mPointerVelocityControl.reset();
2154    mWheelXVelocityControl.reset();
2155    mWheelYVelocityControl.reset();
2156
2157    mCursorButtonAccumulator.reset(getDevice());
2158    mCursorMotionAccumulator.reset(getDevice());
2159    mCursorScrollAccumulator.reset(getDevice());
2160
2161    InputMapper::reset(when);
2162}
2163
2164void CursorInputMapper::process(const RawEvent* rawEvent) {
2165    mCursorButtonAccumulator.process(rawEvent);
2166    mCursorMotionAccumulator.process(rawEvent);
2167    mCursorScrollAccumulator.process(rawEvent);
2168
2169    if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
2170        sync(rawEvent->when);
2171    }
2172}
2173
2174void CursorInputMapper::sync(nsecs_t when) {
2175    int32_t lastButtonState = mButtonState;
2176    int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
2177    mButtonState = currentButtonState;
2178
2179    bool wasDown = isPointerDown(lastButtonState);
2180    bool down = isPointerDown(currentButtonState);
2181    bool downChanged;
2182    if (!wasDown && down) {
2183        mDownTime = when;
2184        downChanged = true;
2185    } else if (wasDown && !down) {
2186        downChanged = true;
2187    } else {
2188        downChanged = false;
2189    }
2190    nsecs_t downTime = mDownTime;
2191    bool buttonsChanged = currentButtonState != lastButtonState;
2192    bool buttonsPressed = currentButtonState & ~lastButtonState;
2193
2194    float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
2195    float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
2196    bool moved = deltaX != 0 || deltaY != 0;
2197
2198    // Rotate delta according to orientation if needed.
2199    if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
2200            && (deltaX != 0.0f || deltaY != 0.0f)) {
2201        rotateDelta(mOrientation, &deltaX, &deltaY);
2202    }
2203
2204    // Move the pointer.
2205    PointerProperties pointerProperties;
2206    pointerProperties.clear();
2207    pointerProperties.id = 0;
2208    pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
2209
2210    PointerCoords pointerCoords;
2211    pointerCoords.clear();
2212
2213    float vscroll = mCursorScrollAccumulator.getRelativeVWheel();
2214    float hscroll = mCursorScrollAccumulator.getRelativeHWheel();
2215    bool scrolled = vscroll != 0 || hscroll != 0;
2216
2217    mWheelYVelocityControl.move(when, NULL, &vscroll);
2218    mWheelXVelocityControl.move(when, &hscroll, NULL);
2219
2220    mPointerVelocityControl.move(when, &deltaX, &deltaY);
2221
2222    if (mPointerController != NULL) {
2223        if (moved || scrolled || buttonsChanged) {
2224            mPointerController->setPresentation(
2225                    PointerControllerInterface::PRESENTATION_POINTER);
2226
2227            if (moved) {
2228                mPointerController->move(deltaX, deltaY);
2229            }
2230
2231            if (buttonsChanged) {
2232                mPointerController->setButtonState(currentButtonState);
2233            }
2234
2235            mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
2236        }
2237
2238        float x, y;
2239        mPointerController->getPosition(&x, &y);
2240        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
2241        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
2242    } else {
2243        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
2244        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
2245    }
2246
2247    pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
2248
2249    // Moving an external trackball or mouse should wake the device.
2250    // We don't do this for internal cursor devices to prevent them from waking up
2251    // the device in your pocket.
2252    // TODO: Use the input device configuration to control this behavior more finely.
2253    uint32_t policyFlags = 0;
2254    if ((buttonsPressed || moved || scrolled) && getDevice()->isExternal()) {
2255        policyFlags |= POLICY_FLAG_WAKE_DROPPED;
2256    }
2257
2258    // Synthesize key down from buttons if needed.
2259    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
2260            policyFlags, lastButtonState, currentButtonState);
2261
2262    // Send motion event.
2263    if (downChanged || moved || scrolled || buttonsChanged) {
2264        int32_t metaState = mContext->getGlobalMetaState();
2265        int32_t motionEventAction;
2266        if (downChanged) {
2267            motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
2268        } else if (down || mPointerController == NULL) {
2269            motionEventAction = AMOTION_EVENT_ACTION_MOVE;
2270        } else {
2271            motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
2272        }
2273
2274        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
2275                motionEventAction, 0, metaState, currentButtonState, 0,
2276                1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
2277        getListener()->notifyMotion(&args);
2278
2279        // Send hover move after UP to tell the application that the mouse is hovering now.
2280        if (motionEventAction == AMOTION_EVENT_ACTION_UP
2281                && mPointerController != NULL) {
2282            NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, policyFlags,
2283                    AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
2284                    metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE,
2285                    1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
2286            getListener()->notifyMotion(&hoverArgs);
2287        }
2288
2289        // Send scroll events.
2290        if (scrolled) {
2291            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
2292            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
2293
2294            NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags,
2295                    AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState,
2296                    AMOTION_EVENT_EDGE_FLAG_NONE,
2297                    1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
2298            getListener()->notifyMotion(&scrollArgs);
2299        }
2300    }
2301
2302    // Synthesize key up from buttons if needed.
2303    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
2304            policyFlags, lastButtonState, currentButtonState);
2305
2306    mCursorMotionAccumulator.finishSync();
2307    mCursorScrollAccumulator.finishSync();
2308}
2309
2310int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
2311    if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
2312        return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
2313    } else {
2314        return AKEY_STATE_UNKNOWN;
2315    }
2316}
2317
2318void CursorInputMapper::fadePointer() {
2319    if (mPointerController != NULL) {
2320        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
2321    }
2322}
2323
2324
2325// --- TouchInputMapper ---
2326
2327TouchInputMapper::TouchInputMapper(InputDevice* device) :
2328        InputMapper(device),
2329        mSource(0), mDeviceMode(DEVICE_MODE_DISABLED),
2330        mSurfaceOrientation(-1), mSurfaceWidth(-1), mSurfaceHeight(-1) {
2331}
2332
2333TouchInputMapper::~TouchInputMapper() {
2334}
2335
2336uint32_t TouchInputMapper::getSources() {
2337    return mSource;
2338}
2339
2340void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
2341    InputMapper::populateDeviceInfo(info);
2342
2343    if (mDeviceMode != DEVICE_MODE_DISABLED) {
2344        info->addMotionRange(mOrientedRanges.x);
2345        info->addMotionRange(mOrientedRanges.y);
2346        info->addMotionRange(mOrientedRanges.pressure);
2347
2348        if (mOrientedRanges.haveSize) {
2349            info->addMotionRange(mOrientedRanges.size);
2350        }
2351
2352        if (mOrientedRanges.haveTouchSize) {
2353            info->addMotionRange(mOrientedRanges.touchMajor);
2354            info->addMotionRange(mOrientedRanges.touchMinor);
2355        }
2356
2357        if (mOrientedRanges.haveToolSize) {
2358            info->addMotionRange(mOrientedRanges.toolMajor);
2359            info->addMotionRange(mOrientedRanges.toolMinor);
2360        }
2361
2362        if (mOrientedRanges.haveOrientation) {
2363            info->addMotionRange(mOrientedRanges.orientation);
2364        }
2365
2366        if (mOrientedRanges.haveDistance) {
2367            info->addMotionRange(mOrientedRanges.distance);
2368        }
2369
2370        if (mOrientedRanges.haveTilt) {
2371            info->addMotionRange(mOrientedRanges.tilt);
2372        }
2373
2374        if (mCursorScrollAccumulator.haveRelativeVWheel()) {
2375            info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
2376        }
2377        if (mCursorScrollAccumulator.haveRelativeHWheel()) {
2378            info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
2379        }
2380    }
2381}
2382
2383void TouchInputMapper::dump(String8& dump) {
2384    dump.append(INDENT2 "Touch Input Mapper:\n");
2385    dumpParameters(dump);
2386    dumpVirtualKeys(dump);
2387    dumpRawPointerAxes(dump);
2388    dumpCalibration(dump);
2389    dumpSurface(dump);
2390
2391    dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
2392    dump.appendFormat(INDENT4 "XScale: %0.3f\n", mXScale);
2393    dump.appendFormat(INDENT4 "YScale: %0.3f\n", mYScale);
2394    dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mXPrecision);
2395    dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mYPrecision);
2396    dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale);
2397    dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mPressureScale);
2398    dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mSizeScale);
2399    dump.appendFormat(INDENT4 "OrientationCenter: %0.3f\n", mOrientationCenter);
2400    dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale);
2401    dump.appendFormat(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale);
2402    dump.appendFormat(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt));
2403    dump.appendFormat(INDENT4 "TiltXCenter: %0.3f\n", mTiltXCenter);
2404    dump.appendFormat(INDENT4 "TiltXScale: %0.3f\n", mTiltXScale);
2405    dump.appendFormat(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter);
2406    dump.appendFormat(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale);
2407
2408    dump.appendFormat(INDENT3 "Last Button State: 0x%08x\n", mLastButtonState);
2409
2410    dump.appendFormat(INDENT3 "Last Raw Touch: pointerCount=%d\n",
2411            mLastRawPointerData.pointerCount);
2412    for (uint32_t i = 0; i < mLastRawPointerData.pointerCount; i++) {
2413        const RawPointerData::Pointer& pointer = mLastRawPointerData.pointers[i];
2414        dump.appendFormat(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
2415                "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
2416                "orientation=%d, tiltX=%d, tiltY=%d, distance=%d, "
2417                "toolType=%d, isHovering=%s\n", i,
2418                pointer.id, pointer.x, pointer.y, pointer.pressure,
2419                pointer.touchMajor, pointer.touchMinor,
2420                pointer.toolMajor, pointer.toolMinor,
2421                pointer.orientation, pointer.tiltX, pointer.tiltY, pointer.distance,
2422                pointer.toolType, toString(pointer.isHovering));
2423    }
2424
2425    dump.appendFormat(INDENT3 "Last Cooked Touch: pointerCount=%d\n",
2426            mLastCookedPointerData.pointerCount);
2427    for (uint32_t i = 0; i < mLastCookedPointerData.pointerCount; i++) {
2428        const PointerProperties& pointerProperties = mLastCookedPointerData.pointerProperties[i];
2429        const PointerCoords& pointerCoords = mLastCookedPointerData.pointerCoords[i];
2430        dump.appendFormat(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, "
2431                "touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, toolMinor=%0.3f, "
2432                "orientation=%0.3f, tilt=%0.3f, distance=%0.3f, "
2433                "toolType=%d, isHovering=%s\n", i,
2434                pointerProperties.id,
2435                pointerCoords.getX(),
2436                pointerCoords.getY(),
2437                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
2438                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
2439                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
2440                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
2441                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
2442                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION),
2443                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TILT),
2444                pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE),
2445                pointerProperties.toolType,
2446                toString(mLastCookedPointerData.isHovering(i)));
2447    }
2448
2449    if (mDeviceMode == DEVICE_MODE_POINTER) {
2450        dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n");
2451        dump.appendFormat(INDENT4 "XMovementScale: %0.3f\n",
2452                mPointerXMovementScale);
2453        dump.appendFormat(INDENT4 "YMovementScale: %0.3f\n",
2454                mPointerYMovementScale);
2455        dump.appendFormat(INDENT4 "XZoomScale: %0.3f\n",
2456                mPointerXZoomScale);
2457        dump.appendFormat(INDENT4 "YZoomScale: %0.3f\n",
2458                mPointerYZoomScale);
2459        dump.appendFormat(INDENT4 "MaxSwipeWidth: %f\n",
2460                mPointerGestureMaxSwipeWidth);
2461    }
2462}
2463
2464void TouchInputMapper::configure(nsecs_t when,
2465        const InputReaderConfiguration* config, uint32_t changes) {
2466    InputMapper::configure(when, config, changes);
2467
2468    mConfig = *config;
2469
2470    if (!changes) { // first time only
2471        // Configure basic parameters.
2472        configureParameters();
2473
2474        // Configure common accumulators.
2475        mCursorScrollAccumulator.configure(getDevice());
2476        mTouchButtonAccumulator.configure(getDevice());
2477
2478        // Configure absolute axis information.
2479        configureRawPointerAxes();
2480
2481        // Prepare input device calibration.
2482        parseCalibration();
2483        resolveCalibration();
2484    }
2485
2486    if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
2487        // Update pointer speed.
2488        mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters);
2489        mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
2490        mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
2491    }
2492
2493    bool resetNeeded = false;
2494    if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO
2495            | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT
2496            | InputReaderConfiguration::CHANGE_SHOW_TOUCHES))) {
2497        // Configure device sources, surface dimensions, orientation and
2498        // scaling factors.
2499        configureSurface(when, &resetNeeded);
2500    }
2501
2502    if (changes && resetNeeded) {
2503        // Send reset, unless this is the first time the device has been configured,
2504        // in which case the reader will call reset itself after all mappers are ready.
2505        getDevice()->notifyReset(when);
2506    }
2507}
2508
2509void TouchInputMapper::configureParameters() {
2510    // Use the pointer presentation mode for devices that do not support distinct
2511    // multitouch.  The spot-based presentation relies on being able to accurately
2512    // locate two or more fingers on the touch pad.
2513    mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT)
2514            ? Parameters::GESTURE_MODE_POINTER : Parameters::GESTURE_MODE_SPOTS;
2515
2516    String8 gestureModeString;
2517    if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
2518            gestureModeString)) {
2519        if (gestureModeString == "pointer") {
2520            mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER;
2521        } else if (gestureModeString == "spots") {
2522            mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
2523        } else if (gestureModeString != "default") {
2524            LOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
2525        }
2526    }
2527
2528    if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
2529        // The device is a touch screen.
2530        mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
2531    } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) {
2532        // The device is a pointing device like a track pad.
2533        mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
2534    } else if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
2535            || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
2536        // The device is a cursor device with a touch pad attached.
2537        // By default don't use the touch pad to move the pointer.
2538        mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
2539    } else {
2540        // The device is a touch pad of unknown purpose.
2541        mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
2542    }
2543
2544    String8 deviceTypeString;
2545    if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
2546            deviceTypeString)) {
2547        if (deviceTypeString == "touchScreen") {
2548            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
2549        } else if (deviceTypeString == "touchPad") {
2550            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
2551        } else if (deviceTypeString == "pointer") {
2552            mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
2553        } else if (deviceTypeString != "default") {
2554            LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
2555        }
2556    }
2557
2558    mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
2559    getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
2560            mParameters.orientationAware);
2561
2562    mParameters.associatedDisplayId = -1;
2563    mParameters.associatedDisplayIsExternal = false;
2564    if (mParameters.orientationAware
2565            || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
2566            || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
2567        mParameters.associatedDisplayIsExternal =
2568                mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
2569                        && getDevice()->isExternal();
2570        mParameters.associatedDisplayId = 0;
2571    }
2572}
2573
2574void TouchInputMapper::dumpParameters(String8& dump) {
2575    dump.append(INDENT3 "Parameters:\n");
2576
2577    switch (mParameters.gestureMode) {
2578    case Parameters::GESTURE_MODE_POINTER:
2579        dump.append(INDENT4 "GestureMode: pointer\n");
2580        break;
2581    case Parameters::GESTURE_MODE_SPOTS:
2582        dump.append(INDENT4 "GestureMode: spots\n");
2583        break;
2584    default:
2585        assert(false);
2586    }
2587
2588    switch (mParameters.deviceType) {
2589    case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
2590        dump.append(INDENT4 "DeviceType: touchScreen\n");
2591        break;
2592    case Parameters::DEVICE_TYPE_TOUCH_PAD:
2593        dump.append(INDENT4 "DeviceType: touchPad\n");
2594        break;
2595    case Parameters::DEVICE_TYPE_POINTER:
2596        dump.append(INDENT4 "DeviceType: pointer\n");
2597        break;
2598    default:
2599        LOG_ASSERT(false);
2600    }
2601
2602    dump.appendFormat(INDENT4 "AssociatedDisplay: id=%d, isExternal=%s\n",
2603            mParameters.associatedDisplayId, toString(mParameters.associatedDisplayIsExternal));
2604    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
2605            toString(mParameters.orientationAware));
2606}
2607
2608void TouchInputMapper::configureRawPointerAxes() {
2609    mRawPointerAxes.clear();
2610}
2611
2612void TouchInputMapper::dumpRawPointerAxes(String8& dump) {
2613    dump.append(INDENT3 "Raw Touch Axes:\n");
2614    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.x, "X");
2615    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.y, "Y");
2616    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.pressure, "Pressure");
2617    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMajor, "TouchMajor");
2618    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMinor, "TouchMinor");
2619    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMajor, "ToolMajor");
2620    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMinor, "ToolMinor");
2621    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.orientation, "Orientation");
2622    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.distance, "Distance");
2623    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltX, "TiltX");
2624    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltY, "TiltY");
2625    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.trackingId, "TrackingId");
2626    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot");
2627}
2628
2629void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
2630    int32_t oldDeviceMode = mDeviceMode;
2631
2632    // Determine device mode.
2633    if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
2634            && mConfig.pointerGesturesEnabled) {
2635        mSource = AINPUT_SOURCE_MOUSE;
2636        mDeviceMode = DEVICE_MODE_POINTER;
2637    } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
2638            && mParameters.associatedDisplayId >= 0) {
2639        mSource = AINPUT_SOURCE_TOUCHSCREEN;
2640        mDeviceMode = DEVICE_MODE_DIRECT;
2641    } else {
2642        mSource = AINPUT_SOURCE_TOUCHPAD;
2643        mDeviceMode = DEVICE_MODE_UNSCALED;
2644    }
2645
2646    // Ensure we have valid X and Y axes.
2647    if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
2648        LOGW(INDENT "Touch device '%s' did not report support for X or Y axis!  "
2649                "The device will be inoperable.", getDeviceName().string());
2650        mDeviceMode = DEVICE_MODE_DISABLED;
2651        return;
2652    }
2653
2654    // Get associated display dimensions.
2655    if (mParameters.associatedDisplayId >= 0) {
2656        if (!mConfig.getDisplayInfo(mParameters.associatedDisplayId,
2657                mParameters.associatedDisplayIsExternal,
2658                &mAssociatedDisplayWidth, &mAssociatedDisplayHeight,
2659                &mAssociatedDisplayOrientation)) {
2660            LOGI(INDENT "Touch device '%s' could not query the properties of its associated "
2661                    "display %d.  The device will be inoperable until the display size "
2662                    "becomes available.",
2663                    getDeviceName().string(), mParameters.associatedDisplayId);
2664            mDeviceMode = DEVICE_MODE_DISABLED;
2665            return;
2666        }
2667    }
2668
2669    // Configure dimensions.
2670    int32_t width, height, orientation;
2671    if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
2672        width = mAssociatedDisplayWidth;
2673        height = mAssociatedDisplayHeight;
2674        orientation = mParameters.orientationAware ?
2675                mAssociatedDisplayOrientation : DISPLAY_ORIENTATION_0;
2676    } else {
2677        width = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
2678        height = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
2679        orientation = DISPLAY_ORIENTATION_0;
2680    }
2681
2682    // If moving between pointer modes, need to reset some state.
2683    bool deviceModeChanged;
2684    if (mDeviceMode != oldDeviceMode) {
2685        deviceModeChanged = true;
2686        mOrientedRanges.clear();
2687    }
2688
2689    // Create pointer controller if needed.
2690    if (mDeviceMode == DEVICE_MODE_POINTER ||
2691            (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
2692        if (mPointerController == NULL) {
2693            mPointerController = getPolicy()->obtainPointerController(getDeviceId());
2694        }
2695    } else {
2696        mPointerController.clear();
2697    }
2698
2699    bool orientationChanged = mSurfaceOrientation != orientation;
2700    if (orientationChanged) {
2701        mSurfaceOrientation = orientation;
2702    }
2703
2704    bool sizeChanged = mSurfaceWidth != width || mSurfaceHeight != height;
2705    if (sizeChanged || deviceModeChanged) {
2706        LOGI("Device reconfigured: id=%d, name='%s', surface size is now %dx%d, mode is %d",
2707                getDeviceId(), getDeviceName().string(), width, height, mDeviceMode);
2708
2709        mSurfaceWidth = width;
2710        mSurfaceHeight = height;
2711
2712        // Configure X and Y factors.
2713        mXScale = float(width) / (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1);
2714        mYScale = float(height) / (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1);
2715        mXPrecision = 1.0f / mXScale;
2716        mYPrecision = 1.0f / mYScale;
2717
2718        mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
2719        mOrientedRanges.x.source = mSource;
2720        mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
2721        mOrientedRanges.y.source = mSource;
2722
2723        configureVirtualKeys();
2724
2725        // Scale factor for terms that are not oriented in a particular axis.
2726        // If the pixels are square then xScale == yScale otherwise we fake it
2727        // by choosing an average.
2728        mGeometricScale = avg(mXScale, mYScale);
2729
2730        // Size of diagonal axis.
2731        float diagonalSize = hypotf(width, height);
2732
2733        // Size factors.
2734        if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
2735            if (mRawPointerAxes.touchMajor.valid
2736                    && mRawPointerAxes.touchMajor.maxValue != 0) {
2737                mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue;
2738            } else if (mRawPointerAxes.toolMajor.valid
2739                    && mRawPointerAxes.toolMajor.maxValue != 0) {
2740                mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue;
2741            } else {
2742                mSizeScale = 0.0f;
2743            }
2744
2745            mOrientedRanges.haveTouchSize = true;
2746            mOrientedRanges.haveToolSize = true;
2747            mOrientedRanges.haveSize = true;
2748
2749            mOrientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
2750            mOrientedRanges.touchMajor.source = mSource;
2751            mOrientedRanges.touchMajor.min = 0;
2752            mOrientedRanges.touchMajor.max = diagonalSize;
2753            mOrientedRanges.touchMajor.flat = 0;
2754            mOrientedRanges.touchMajor.fuzz = 0;
2755
2756            mOrientedRanges.touchMinor = mOrientedRanges.touchMajor;
2757            mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
2758
2759            mOrientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
2760            mOrientedRanges.toolMajor.source = mSource;
2761            mOrientedRanges.toolMajor.min = 0;
2762            mOrientedRanges.toolMajor.max = diagonalSize;
2763            mOrientedRanges.toolMajor.flat = 0;
2764            mOrientedRanges.toolMajor.fuzz = 0;
2765
2766            mOrientedRanges.toolMinor = mOrientedRanges.toolMajor;
2767            mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
2768
2769            mOrientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
2770            mOrientedRanges.size.source = mSource;
2771            mOrientedRanges.size.min = 0;
2772            mOrientedRanges.size.max = 1.0;
2773            mOrientedRanges.size.flat = 0;
2774            mOrientedRanges.size.fuzz = 0;
2775        } else {
2776            mSizeScale = 0.0f;
2777        }
2778
2779        // Pressure factors.
2780        mPressureScale = 0;
2781        if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
2782                || mCalibration.pressureCalibration
2783                        == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
2784            if (mCalibration.havePressureScale) {
2785                mPressureScale = mCalibration.pressureScale;
2786            } else if (mRawPointerAxes.pressure.valid
2787                    && mRawPointerAxes.pressure.maxValue != 0) {
2788                mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue;
2789            }
2790        }
2791
2792        mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
2793        mOrientedRanges.pressure.source = mSource;
2794        mOrientedRanges.pressure.min = 0;
2795        mOrientedRanges.pressure.max = 1.0;
2796        mOrientedRanges.pressure.flat = 0;
2797        mOrientedRanges.pressure.fuzz = 0;
2798
2799        // Tilt
2800        mTiltXCenter = 0;
2801        mTiltXScale = 0;
2802        mTiltYCenter = 0;
2803        mTiltYScale = 0;
2804        mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid;
2805        if (mHaveTilt) {
2806            mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue,
2807                    mRawPointerAxes.tiltX.maxValue);
2808            mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue,
2809                    mRawPointerAxes.tiltY.maxValue);
2810            mTiltXScale = M_PI / 180;
2811            mTiltYScale = M_PI / 180;
2812
2813            mOrientedRanges.haveTilt = true;
2814
2815            mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT;
2816            mOrientedRanges.tilt.source = mSource;
2817            mOrientedRanges.tilt.min = 0;
2818            mOrientedRanges.tilt.max = M_PI_2;
2819            mOrientedRanges.tilt.flat = 0;
2820            mOrientedRanges.tilt.fuzz = 0;
2821        }
2822
2823        // Orientation
2824        mOrientationCenter = 0;
2825        mOrientationScale = 0;
2826        if (mHaveTilt) {
2827            mOrientedRanges.haveOrientation = true;
2828
2829            mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
2830            mOrientedRanges.orientation.source = mSource;
2831            mOrientedRanges.orientation.min = -M_PI;
2832            mOrientedRanges.orientation.max = M_PI;
2833            mOrientedRanges.orientation.flat = 0;
2834            mOrientedRanges.orientation.fuzz = 0;
2835        } else if (mCalibration.orientationCalibration !=
2836                Calibration::ORIENTATION_CALIBRATION_NONE) {
2837            if (mCalibration.orientationCalibration
2838                    == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
2839                if (mRawPointerAxes.orientation.valid) {
2840                    mOrientationCenter = avg(mRawPointerAxes.orientation.minValue,
2841                            mRawPointerAxes.orientation.maxValue);
2842                    mOrientationScale = M_PI / (mRawPointerAxes.orientation.maxValue -
2843                            mRawPointerAxes.orientation.minValue);
2844                }
2845            }
2846
2847            mOrientedRanges.haveOrientation = true;
2848
2849            mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
2850            mOrientedRanges.orientation.source = mSource;
2851            mOrientedRanges.orientation.min = -M_PI_2;
2852            mOrientedRanges.orientation.max = M_PI_2;
2853            mOrientedRanges.orientation.flat = 0;
2854            mOrientedRanges.orientation.fuzz = 0;
2855        }
2856
2857        // Distance
2858        mDistanceScale = 0;
2859        if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) {
2860            if (mCalibration.distanceCalibration
2861                    == Calibration::DISTANCE_CALIBRATION_SCALED) {
2862                if (mCalibration.haveDistanceScale) {
2863                    mDistanceScale = mCalibration.distanceScale;
2864                } else {
2865                    mDistanceScale = 1.0f;
2866                }
2867            }
2868
2869            mOrientedRanges.haveDistance = true;
2870
2871            mOrientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE;
2872            mOrientedRanges.distance.source = mSource;
2873            mOrientedRanges.distance.min =
2874                    mRawPointerAxes.distance.minValue * mDistanceScale;
2875            mOrientedRanges.distance.max =
2876                    mRawPointerAxes.distance.minValue * mDistanceScale;
2877            mOrientedRanges.distance.flat = 0;
2878            mOrientedRanges.distance.fuzz =
2879                    mRawPointerAxes.distance.fuzz * mDistanceScale;
2880        }
2881    }
2882
2883    if (orientationChanged || sizeChanged || deviceModeChanged) {
2884        // Compute oriented surface dimensions, precision, scales and ranges.
2885        // Note that the maximum value reported is an inclusive maximum value so it is one
2886        // unit less than the total width or height of surface.
2887        switch (mSurfaceOrientation) {
2888        case DISPLAY_ORIENTATION_90:
2889        case DISPLAY_ORIENTATION_270:
2890            mOrientedSurfaceWidth = mSurfaceHeight;
2891            mOrientedSurfaceHeight = mSurfaceWidth;
2892
2893            mOrientedXPrecision = mYPrecision;
2894            mOrientedYPrecision = mXPrecision;
2895
2896            mOrientedRanges.x.min = 0;
2897            mOrientedRanges.x.max = (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue)
2898                    * mYScale;
2899            mOrientedRanges.x.flat = 0;
2900            mOrientedRanges.x.fuzz = mYScale;
2901
2902            mOrientedRanges.y.min = 0;
2903            mOrientedRanges.y.max = (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue)
2904                    * mXScale;
2905            mOrientedRanges.y.flat = 0;
2906            mOrientedRanges.y.fuzz = mXScale;
2907            break;
2908
2909        default:
2910            mOrientedSurfaceWidth = mSurfaceWidth;
2911            mOrientedSurfaceHeight = mSurfaceHeight;
2912
2913            mOrientedXPrecision = mXPrecision;
2914            mOrientedYPrecision = mYPrecision;
2915
2916            mOrientedRanges.x.min = 0;
2917            mOrientedRanges.x.max = (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue)
2918                    * mXScale;
2919            mOrientedRanges.x.flat = 0;
2920            mOrientedRanges.x.fuzz = mXScale;
2921
2922            mOrientedRanges.y.min = 0;
2923            mOrientedRanges.y.max = (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue)
2924                    * mYScale;
2925            mOrientedRanges.y.flat = 0;
2926            mOrientedRanges.y.fuzz = mYScale;
2927            break;
2928        }
2929
2930        // Compute pointer gesture detection parameters.
2931        if (mDeviceMode == DEVICE_MODE_POINTER) {
2932            int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
2933            int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
2934            float rawDiagonal = hypotf(rawWidth, rawHeight);
2935            float displayDiagonal = hypotf(mAssociatedDisplayWidth,
2936                    mAssociatedDisplayHeight);
2937
2938            // Scale movements such that one whole swipe of the touch pad covers a
2939            // given area relative to the diagonal size of the display when no acceleration
2940            // is applied.
2941            // Assume that the touch pad has a square aspect ratio such that movements in
2942            // X and Y of the same number of raw units cover the same physical distance.
2943            mPointerXMovementScale = mConfig.pointerGestureMovementSpeedRatio
2944                    * displayDiagonal / rawDiagonal;
2945            mPointerYMovementScale = mPointerXMovementScale;
2946
2947            // Scale zooms to cover a smaller range of the display than movements do.
2948            // This value determines the area around the pointer that is affected by freeform
2949            // pointer gestures.
2950            mPointerXZoomScale = mConfig.pointerGestureZoomSpeedRatio
2951                    * displayDiagonal / rawDiagonal;
2952            mPointerYZoomScale = mPointerXZoomScale;
2953
2954            // Max width between pointers to detect a swipe gesture is more than some fraction
2955            // of the diagonal axis of the touch pad.  Touches that are wider than this are
2956            // translated into freeform gestures.
2957            mPointerGestureMaxSwipeWidth =
2958                    mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
2959        }
2960
2961        // Abort current pointer usages because the state has changed.
2962        abortPointerUsage(when, 0 /*policyFlags*/);
2963
2964        // Inform the dispatcher about the changes.
2965        *outResetNeeded = true;
2966    }
2967}
2968
2969void TouchInputMapper::dumpSurface(String8& dump) {
2970    dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
2971    dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
2972    dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
2973}
2974
2975void TouchInputMapper::configureVirtualKeys() {
2976    Vector<VirtualKeyDefinition> virtualKeyDefinitions;
2977    getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
2978
2979    mVirtualKeys.clear();
2980
2981    if (virtualKeyDefinitions.size() == 0) {
2982        return;
2983    }
2984
2985    mVirtualKeys.setCapacity(virtualKeyDefinitions.size());
2986
2987    int32_t touchScreenLeft = mRawPointerAxes.x.minValue;
2988    int32_t touchScreenTop = mRawPointerAxes.y.minValue;
2989    int32_t touchScreenWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
2990    int32_t touchScreenHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
2991
2992    for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
2993        const VirtualKeyDefinition& virtualKeyDefinition =
2994                virtualKeyDefinitions[i];
2995
2996        mVirtualKeys.add();
2997        VirtualKey& virtualKey = mVirtualKeys.editTop();
2998
2999        virtualKey.scanCode = virtualKeyDefinition.scanCode;
3000        int32_t keyCode;
3001        uint32_t flags;
3002        if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode,
3003                & keyCode, & flags)) {
3004            LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
3005                    virtualKey.scanCode);
3006            mVirtualKeys.pop(); // drop the key
3007            continue;
3008        }
3009
3010        virtualKey.keyCode = keyCode;
3011        virtualKey.flags = flags;
3012
3013        // convert the key definition's display coordinates into touch coordinates for a hit box
3014        int32_t halfWidth = virtualKeyDefinition.width / 2;
3015        int32_t halfHeight = virtualKeyDefinition.height / 2;
3016
3017        virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
3018                * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
3019        virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
3020                * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
3021        virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
3022                * touchScreenHeight / mSurfaceHeight + touchScreenTop;
3023        virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
3024                * touchScreenHeight / mSurfaceHeight + touchScreenTop;
3025    }
3026}
3027
3028void TouchInputMapper::dumpVirtualKeys(String8& dump) {
3029    if (!mVirtualKeys.isEmpty()) {
3030        dump.append(INDENT3 "Virtual Keys:\n");
3031
3032        for (size_t i = 0; i < mVirtualKeys.size(); i++) {
3033            const VirtualKey& virtualKey = mVirtualKeys.itemAt(i);
3034            dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
3035                    "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
3036                    i, virtualKey.scanCode, virtualKey.keyCode,
3037                    virtualKey.hitLeft, virtualKey.hitRight,
3038                    virtualKey.hitTop, virtualKey.hitBottom);
3039        }
3040    }
3041}
3042
3043void TouchInputMapper::parseCalibration() {
3044    const PropertyMap& in = getDevice()->getConfiguration();
3045    Calibration& out = mCalibration;
3046
3047    // Size
3048    out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
3049    String8 sizeCalibrationString;
3050    if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
3051        if (sizeCalibrationString == "none") {
3052            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
3053        } else if (sizeCalibrationString == "geometric") {
3054            out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
3055        } else if (sizeCalibrationString == "diameter") {
3056            out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER;
3057        } else if (sizeCalibrationString == "area") {
3058            out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA;
3059        } else if (sizeCalibrationString != "default") {
3060            LOGW("Invalid value for touch.size.calibration: '%s'",
3061                    sizeCalibrationString.string());
3062        }
3063    }
3064
3065    out.haveSizeScale = in.tryGetProperty(String8("touch.size.scale"),
3066            out.sizeScale);
3067    out.haveSizeBias = in.tryGetProperty(String8("touch.size.bias"),
3068            out.sizeBias);
3069    out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"),
3070            out.sizeIsSummed);
3071
3072    // Pressure
3073    out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
3074    String8 pressureCalibrationString;
3075    if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
3076        if (pressureCalibrationString == "none") {
3077            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
3078        } else if (pressureCalibrationString == "physical") {
3079            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
3080        } else if (pressureCalibrationString == "amplitude") {
3081            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
3082        } else if (pressureCalibrationString != "default") {
3083            LOGW("Invalid value for touch.pressure.calibration: '%s'",
3084                    pressureCalibrationString.string());
3085        }
3086    }
3087
3088    out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
3089            out.pressureScale);
3090
3091    // Orientation
3092    out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
3093    String8 orientationCalibrationString;
3094    if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
3095        if (orientationCalibrationString == "none") {
3096            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
3097        } else if (orientationCalibrationString == "interpolated") {
3098            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
3099        } else if (orientationCalibrationString == "vector") {
3100            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
3101        } else if (orientationCalibrationString != "default") {
3102            LOGW("Invalid value for touch.orientation.calibration: '%s'",
3103                    orientationCalibrationString.string());
3104        }
3105    }
3106
3107    // Distance
3108    out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT;
3109    String8 distanceCalibrationString;
3110    if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
3111        if (distanceCalibrationString == "none") {
3112            out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
3113        } else if (distanceCalibrationString == "scaled") {
3114            out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
3115        } else if (distanceCalibrationString != "default") {
3116            LOGW("Invalid value for touch.distance.calibration: '%s'",
3117                    distanceCalibrationString.string());
3118        }
3119    }
3120
3121    out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"),
3122            out.distanceScale);
3123}
3124
3125void TouchInputMapper::resolveCalibration() {
3126    // Size
3127    if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) {
3128        if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DEFAULT) {
3129            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
3130        }
3131    } else {
3132        mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
3133    }
3134
3135    // Pressure
3136    if (mRawPointerAxes.pressure.valid) {
3137        if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DEFAULT) {
3138            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
3139        }
3140    } else {
3141        mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
3142    }
3143
3144    // Orientation
3145    if (mRawPointerAxes.orientation.valid) {
3146        if (mCalibration.orientationCalibration == Calibration::ORIENTATION_CALIBRATION_DEFAULT) {
3147            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
3148        }
3149    } else {
3150        mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
3151    }
3152
3153    // Distance
3154    if (mRawPointerAxes.distance.valid) {
3155        if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_DEFAULT) {
3156            mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
3157        }
3158    } else {
3159        mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
3160    }
3161}
3162
3163void TouchInputMapper::dumpCalibration(String8& dump) {
3164    dump.append(INDENT3 "Calibration:\n");
3165
3166    // Size
3167    switch (mCalibration.sizeCalibration) {
3168    case Calibration::SIZE_CALIBRATION_NONE:
3169        dump.append(INDENT4 "touch.size.calibration: none\n");
3170        break;
3171    case Calibration::SIZE_CALIBRATION_GEOMETRIC:
3172        dump.append(INDENT4 "touch.size.calibration: geometric\n");
3173        break;
3174    case Calibration::SIZE_CALIBRATION_DIAMETER:
3175        dump.append(INDENT4 "touch.size.calibration: diameter\n");
3176        break;
3177    case Calibration::SIZE_CALIBRATION_AREA:
3178        dump.append(INDENT4 "touch.size.calibration: area\n");
3179        break;
3180    default:
3181        LOG_ASSERT(false);
3182    }
3183
3184    if (mCalibration.haveSizeScale) {
3185        dump.appendFormat(INDENT4 "touch.size.scale: %0.3f\n",
3186                mCalibration.sizeScale);
3187    }
3188
3189    if (mCalibration.haveSizeBias) {
3190        dump.appendFormat(INDENT4 "touch.size.bias: %0.3f\n",
3191                mCalibration.sizeBias);
3192    }
3193
3194    if (mCalibration.haveSizeIsSummed) {
3195        dump.appendFormat(INDENT4 "touch.size.isSummed: %s\n",
3196                toString(mCalibration.sizeIsSummed));
3197    }
3198
3199    // Pressure
3200    switch (mCalibration.pressureCalibration) {
3201    case Calibration::PRESSURE_CALIBRATION_NONE:
3202        dump.append(INDENT4 "touch.pressure.calibration: none\n");
3203        break;
3204    case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
3205        dump.append(INDENT4 "touch.pressure.calibration: physical\n");
3206        break;
3207    case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
3208        dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
3209        break;
3210    default:
3211        LOG_ASSERT(false);
3212    }
3213
3214    if (mCalibration.havePressureScale) {
3215        dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
3216                mCalibration.pressureScale);
3217    }
3218
3219    // Orientation
3220    switch (mCalibration.orientationCalibration) {
3221    case Calibration::ORIENTATION_CALIBRATION_NONE:
3222        dump.append(INDENT4 "touch.orientation.calibration: none\n");
3223        break;
3224    case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
3225        dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
3226        break;
3227    case Calibration::ORIENTATION_CALIBRATION_VECTOR:
3228        dump.append(INDENT4 "touch.orientation.calibration: vector\n");
3229        break;
3230    default:
3231        LOG_ASSERT(false);
3232    }
3233
3234    // Distance
3235    switch (mCalibration.distanceCalibration) {
3236    case Calibration::DISTANCE_CALIBRATION_NONE:
3237        dump.append(INDENT4 "touch.distance.calibration: none\n");
3238        break;
3239    case Calibration::DISTANCE_CALIBRATION_SCALED:
3240        dump.append(INDENT4 "touch.distance.calibration: scaled\n");
3241        break;
3242    default:
3243        LOG_ASSERT(false);
3244    }
3245
3246    if (mCalibration.haveDistanceScale) {
3247        dump.appendFormat(INDENT4 "touch.distance.scale: %0.3f\n",
3248                mCalibration.distanceScale);
3249    }
3250}
3251
3252void TouchInputMapper::reset(nsecs_t when) {
3253    mCursorButtonAccumulator.reset(getDevice());
3254    mCursorScrollAccumulator.reset(getDevice());
3255    mTouchButtonAccumulator.reset(getDevice());
3256
3257    mPointerVelocityControl.reset();
3258    mWheelXVelocityControl.reset();
3259    mWheelYVelocityControl.reset();
3260
3261    mCurrentRawPointerData.clear();
3262    mLastRawPointerData.clear();
3263    mCurrentCookedPointerData.clear();
3264    mLastCookedPointerData.clear();
3265    mCurrentButtonState = 0;
3266    mLastButtonState = 0;
3267    mCurrentRawVScroll = 0;
3268    mCurrentRawHScroll = 0;
3269    mCurrentFingerIdBits.clear();
3270    mLastFingerIdBits.clear();
3271    mCurrentStylusIdBits.clear();
3272    mLastStylusIdBits.clear();
3273    mCurrentMouseIdBits.clear();
3274    mLastMouseIdBits.clear();
3275    mPointerUsage = POINTER_USAGE_NONE;
3276    mSentHoverEnter = false;
3277    mDownTime = 0;
3278
3279    mCurrentVirtualKey.down = false;
3280
3281    mPointerGesture.reset();
3282    mPointerSimple.reset();
3283
3284    if (mPointerController != NULL) {
3285        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
3286        mPointerController->clearSpots();
3287    }
3288
3289    InputMapper::reset(when);
3290}
3291
3292void TouchInputMapper::process(const RawEvent* rawEvent) {
3293    mCursorButtonAccumulator.process(rawEvent);
3294    mCursorScrollAccumulator.process(rawEvent);
3295    mTouchButtonAccumulator.process(rawEvent);
3296
3297    if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
3298        sync(rawEvent->when);
3299    }
3300}
3301
3302void TouchInputMapper::sync(nsecs_t when) {
3303    // Sync button state.
3304    mCurrentButtonState = mTouchButtonAccumulator.getButtonState()
3305            | mCursorButtonAccumulator.getButtonState();
3306
3307    // Sync scroll state.
3308    mCurrentRawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
3309    mCurrentRawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
3310    mCursorScrollAccumulator.finishSync();
3311
3312    // Sync touch state.
3313    bool havePointerIds = true;
3314    mCurrentRawPointerData.clear();
3315    syncTouch(when, &havePointerIds);
3316
3317#if DEBUG_RAW_EVENTS
3318    if (!havePointerIds) {
3319        LOGD("syncTouch: pointerCount %d -> %d, no pointer ids",
3320                mLastRawPointerData.pointerCount,
3321                mCurrentRawPointerData.pointerCount);
3322    } else {
3323        LOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
3324                "hovering ids 0x%08x -> 0x%08x",
3325                mLastRawPointerData.pointerCount,
3326                mCurrentRawPointerData.pointerCount,
3327                mLastRawPointerData.touchingIdBits.value,
3328                mCurrentRawPointerData.touchingIdBits.value,
3329                mLastRawPointerData.hoveringIdBits.value,
3330                mCurrentRawPointerData.hoveringIdBits.value);
3331    }
3332#endif
3333
3334    // Reset state that we will compute below.
3335    mCurrentFingerIdBits.clear();
3336    mCurrentStylusIdBits.clear();
3337    mCurrentMouseIdBits.clear();
3338    mCurrentCookedPointerData.clear();
3339
3340    if (mDeviceMode == DEVICE_MODE_DISABLED) {
3341        // Drop all input if the device is disabled.
3342        mCurrentRawPointerData.clear();
3343        mCurrentButtonState = 0;
3344    } else {
3345        // Preprocess pointer data.
3346        if (!havePointerIds) {
3347            assignPointerIds();
3348        }
3349
3350        // Handle policy on initial down or hover events.
3351        uint32_t policyFlags = 0;
3352        bool initialDown = mLastRawPointerData.pointerCount == 0
3353                && mCurrentRawPointerData.pointerCount != 0;
3354        bool buttonsPressed = mCurrentButtonState & ~mLastButtonState;
3355        if (initialDown || buttonsPressed) {
3356            // If this is a touch screen, hide the pointer on an initial down.
3357            if (mDeviceMode == DEVICE_MODE_DIRECT) {
3358                getContext()->fadePointer();
3359            }
3360
3361            // Initial downs on external touch devices should wake the device.
3362            // We don't do this for internal touch screens to prevent them from waking
3363            // up in your pocket.
3364            // TODO: Use the input device configuration to control this behavior more finely.
3365            if (getDevice()->isExternal()) {
3366                policyFlags |= POLICY_FLAG_WAKE_DROPPED;
3367            }
3368        }
3369
3370        // Synthesize key down from raw buttons if needed.
3371        synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
3372                policyFlags, mLastButtonState, mCurrentButtonState);
3373
3374        // Consume raw off-screen touches before cooking pointer data.
3375        // If touches are consumed, subsequent code will not receive any pointer data.
3376        if (consumeRawTouches(when, policyFlags)) {
3377            mCurrentRawPointerData.clear();
3378        }
3379
3380        // Cook pointer data.  This call populates the mCurrentCookedPointerData structure
3381        // with cooked pointer data that has the same ids and indices as the raw data.
3382        // The following code can use either the raw or cooked data, as needed.
3383        cookPointerData();
3384
3385        // Dispatch the touches either directly or by translation through a pointer on screen.
3386        if (mDeviceMode == DEVICE_MODE_POINTER) {
3387            for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); !idBits.isEmpty(); ) {
3388                uint32_t id = idBits.clearFirstMarkedBit();
3389                const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
3390                if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
3391                        || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
3392                    mCurrentStylusIdBits.markBit(id);
3393                } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
3394                        || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
3395                    mCurrentFingerIdBits.markBit(id);
3396                } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
3397                    mCurrentMouseIdBits.markBit(id);
3398                }
3399            }
3400            for (BitSet32 idBits(mCurrentRawPointerData.hoveringIdBits); !idBits.isEmpty(); ) {
3401                uint32_t id = idBits.clearFirstMarkedBit();
3402                const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
3403                if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
3404                        || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
3405                    mCurrentStylusIdBits.markBit(id);
3406                }
3407            }
3408
3409            // Stylus takes precedence over all tools, then mouse, then finger.
3410            PointerUsage pointerUsage = mPointerUsage;
3411            if (!mCurrentStylusIdBits.isEmpty()) {
3412                mCurrentMouseIdBits.clear();
3413                mCurrentFingerIdBits.clear();
3414                pointerUsage = POINTER_USAGE_STYLUS;
3415            } else if (!mCurrentMouseIdBits.isEmpty()) {
3416                mCurrentFingerIdBits.clear();
3417                pointerUsage = POINTER_USAGE_MOUSE;
3418            } else if (!mCurrentFingerIdBits.isEmpty() || isPointerDown(mCurrentButtonState)) {
3419                pointerUsage = POINTER_USAGE_GESTURES;
3420            }
3421
3422            dispatchPointerUsage(when, policyFlags, pointerUsage);
3423        } else {
3424            if (mDeviceMode == DEVICE_MODE_DIRECT
3425                    && mConfig.showTouches && mPointerController != NULL) {
3426                mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
3427                mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
3428
3429                mPointerController->setButtonState(mCurrentButtonState);
3430                mPointerController->setSpots(mCurrentCookedPointerData.pointerCoords,
3431                        mCurrentCookedPointerData.idToIndex,
3432                        mCurrentCookedPointerData.touchingIdBits);
3433            }
3434
3435            dispatchHoverExit(when, policyFlags);
3436            dispatchTouches(when, policyFlags);
3437            dispatchHoverEnterAndMove(when, policyFlags);
3438        }
3439
3440        // Synthesize key up from raw buttons if needed.
3441        synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
3442                policyFlags, mLastButtonState, mCurrentButtonState);
3443    }
3444
3445    // Copy current touch to last touch in preparation for the next cycle.
3446    mLastRawPointerData.copyFrom(mCurrentRawPointerData);
3447    mLastCookedPointerData.copyFrom(mCurrentCookedPointerData);
3448    mLastButtonState = mCurrentButtonState;
3449    mLastFingerIdBits = mCurrentFingerIdBits;
3450    mLastStylusIdBits = mCurrentStylusIdBits;
3451    mLastMouseIdBits = mCurrentMouseIdBits;
3452
3453    // Clear some transient state.
3454    mCurrentRawVScroll = 0;
3455    mCurrentRawHScroll = 0;
3456}
3457
3458void TouchInputMapper::timeoutExpired(nsecs_t when) {
3459    if (mDeviceMode == DEVICE_MODE_POINTER) {
3460        if (mPointerUsage == POINTER_USAGE_GESTURES) {
3461            dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
3462        }
3463    }
3464}
3465
3466bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) {
3467    // Check for release of a virtual key.
3468    if (mCurrentVirtualKey.down) {
3469        if (mCurrentRawPointerData.touchingIdBits.isEmpty()) {
3470            // Pointer went up while virtual key was down.
3471            mCurrentVirtualKey.down = false;
3472            if (!mCurrentVirtualKey.ignored) {
3473#if DEBUG_VIRTUAL_KEYS
3474                LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
3475                        mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
3476#endif
3477                dispatchVirtualKey(when, policyFlags,
3478                        AKEY_EVENT_ACTION_UP,
3479                        AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
3480            }
3481            return true;
3482        }
3483
3484        if (mCurrentRawPointerData.touchingIdBits.count() == 1) {
3485            uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit();
3486            const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
3487            const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
3488            if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) {
3489                // Pointer is still within the space of the virtual key.
3490                return true;
3491            }
3492        }
3493
3494        // Pointer left virtual key area or another pointer also went down.
3495        // Send key cancellation but do not consume the touch yet.
3496        // This is useful when the user swipes through from the virtual key area
3497        // into the main display surface.
3498        mCurrentVirtualKey.down = false;
3499        if (!mCurrentVirtualKey.ignored) {
3500#if DEBUG_VIRTUAL_KEYS
3501            LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
3502                    mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
3503#endif
3504            dispatchVirtualKey(when, policyFlags,
3505                    AKEY_EVENT_ACTION_UP,
3506                    AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
3507                            | AKEY_EVENT_FLAG_CANCELED);
3508        }
3509    }
3510
3511    if (mLastRawPointerData.touchingIdBits.isEmpty()
3512            && !mCurrentRawPointerData.touchingIdBits.isEmpty()) {
3513        // Pointer just went down.  Check for virtual key press or off-screen touches.
3514        uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit();
3515        const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
3516        if (!isPointInsideSurface(pointer.x, pointer.y)) {
3517            // If exactly one pointer went down, check for virtual key hit.
3518            // Otherwise we will drop the entire stroke.
3519            if (mCurrentRawPointerData.touchingIdBits.count() == 1) {
3520                const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
3521                if (virtualKey) {
3522                    mCurrentVirtualKey.down = true;
3523                    mCurrentVirtualKey.downTime = when;
3524                    mCurrentVirtualKey.keyCode = virtualKey->keyCode;
3525                    mCurrentVirtualKey.scanCode = virtualKey->scanCode;
3526                    mCurrentVirtualKey.ignored = mContext->shouldDropVirtualKey(
3527                            when, getDevice(), virtualKey->keyCode, virtualKey->scanCode);
3528
3529                    if (!mCurrentVirtualKey.ignored) {
3530#if DEBUG_VIRTUAL_KEYS
3531                        LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
3532                                mCurrentVirtualKey.keyCode,
3533                                mCurrentVirtualKey.scanCode);
3534#endif
3535                        dispatchVirtualKey(when, policyFlags,
3536                                AKEY_EVENT_ACTION_DOWN,
3537                                AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
3538                    }
3539                }
3540            }
3541            return true;
3542        }
3543    }
3544
3545    // Disable all virtual key touches that happen within a short time interval of the
3546    // most recent touch within the screen area.  The idea is to filter out stray
3547    // virtual key presses when interacting with the touch screen.
3548    //
3549    // Problems we're trying to solve:
3550    //
3551    // 1. While scrolling a list or dragging the window shade, the user swipes down into a
3552    //    virtual key area that is implemented by a separate touch panel and accidentally
3553    //    triggers a virtual key.
3554    //
3555    // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
3556    //    area and accidentally triggers a virtual key.  This often happens when virtual keys
3557    //    are layed out below the screen near to where the on screen keyboard's space bar
3558    //    is displayed.
3559    if (mConfig.virtualKeyQuietTime > 0 && !mCurrentRawPointerData.touchingIdBits.isEmpty()) {
3560        mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime);
3561    }
3562    return false;
3563}
3564
3565void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
3566        int32_t keyEventAction, int32_t keyEventFlags) {
3567    int32_t keyCode = mCurrentVirtualKey.keyCode;
3568    int32_t scanCode = mCurrentVirtualKey.scanCode;
3569    nsecs_t downTime = mCurrentVirtualKey.downTime;
3570    int32_t metaState = mContext->getGlobalMetaState();
3571    policyFlags |= POLICY_FLAG_VIRTUAL;
3572
3573    NotifyKeyArgs args(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
3574            keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
3575    getListener()->notifyKey(&args);
3576}
3577
3578void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
3579    BitSet32 currentIdBits = mCurrentCookedPointerData.touchingIdBits;
3580    BitSet32 lastIdBits = mLastCookedPointerData.touchingIdBits;
3581    int32_t metaState = getContext()->getGlobalMetaState();
3582    int32_t buttonState = mCurrentButtonState;
3583
3584    if (currentIdBits == lastIdBits) {
3585        if (!currentIdBits.isEmpty()) {
3586            // No pointer id changes so this is a move event.
3587            // The listener takes care of batching moves so we don't have to deal with that here.
3588            dispatchMotion(when, policyFlags, mSource,
3589                    AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState,
3590                    AMOTION_EVENT_EDGE_FLAG_NONE,
3591                    mCurrentCookedPointerData.pointerProperties,
3592                    mCurrentCookedPointerData.pointerCoords,
3593                    mCurrentCookedPointerData.idToIndex,
3594                    currentIdBits, -1,
3595                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
3596        }
3597    } else {
3598        // There may be pointers going up and pointers going down and pointers moving
3599        // all at the same time.
3600        BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
3601        BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
3602        BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
3603        BitSet32 dispatchedIdBits(lastIdBits.value);
3604
3605        // Update last coordinates of pointers that have moved so that we observe the new
3606        // pointer positions at the same time as other pointers that have just gone up.
3607        bool moveNeeded = updateMovedPointers(
3608                mCurrentCookedPointerData.pointerProperties,
3609                mCurrentCookedPointerData.pointerCoords,
3610                mCurrentCookedPointerData.idToIndex,
3611                mLastCookedPointerData.pointerProperties,
3612                mLastCookedPointerData.pointerCoords,
3613                mLastCookedPointerData.idToIndex,
3614                moveIdBits);
3615        if (buttonState != mLastButtonState) {
3616            moveNeeded = true;
3617        }
3618
3619        // Dispatch pointer up events.
3620        while (!upIdBits.isEmpty()) {
3621            uint32_t upId = upIdBits.clearFirstMarkedBit();
3622
3623            dispatchMotion(when, policyFlags, mSource,
3624                    AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0,
3625                    mLastCookedPointerData.pointerProperties,
3626                    mLastCookedPointerData.pointerCoords,
3627                    mLastCookedPointerData.idToIndex,
3628                    dispatchedIdBits, upId,
3629                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
3630            dispatchedIdBits.clearBit(upId);
3631        }
3632
3633        // Dispatch move events if any of the remaining pointers moved from their old locations.
3634        // Although applications receive new locations as part of individual pointer up
3635        // events, they do not generally handle them except when presented in a move event.
3636        if (moveNeeded) {
3637            LOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
3638            dispatchMotion(when, policyFlags, mSource,
3639                    AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0,
3640                    mCurrentCookedPointerData.pointerProperties,
3641                    mCurrentCookedPointerData.pointerCoords,
3642                    mCurrentCookedPointerData.idToIndex,
3643                    dispatchedIdBits, -1,
3644                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
3645        }
3646
3647        // Dispatch pointer down events using the new pointer locations.
3648        while (!downIdBits.isEmpty()) {
3649            uint32_t downId = downIdBits.clearFirstMarkedBit();
3650            dispatchedIdBits.markBit(downId);
3651
3652            if (dispatchedIdBits.count() == 1) {
3653                // First pointer is going down.  Set down time.
3654                mDownTime = when;
3655            }
3656
3657            dispatchMotion(when, policyFlags, mSource,
3658                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
3659                    mCurrentCookedPointerData.pointerProperties,
3660                    mCurrentCookedPointerData.pointerCoords,
3661                    mCurrentCookedPointerData.idToIndex,
3662                    dispatchedIdBits, downId,
3663                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
3664        }
3665    }
3666}
3667
3668void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) {
3669    if (mSentHoverEnter &&
3670            (mCurrentCookedPointerData.hoveringIdBits.isEmpty()
3671                    || !mCurrentCookedPointerData.touchingIdBits.isEmpty())) {
3672        int32_t metaState = getContext()->getGlobalMetaState();
3673        dispatchMotion(when, policyFlags, mSource,
3674                AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
3675                mLastCookedPointerData.pointerProperties,
3676                mLastCookedPointerData.pointerCoords,
3677                mLastCookedPointerData.idToIndex,
3678                mLastCookedPointerData.hoveringIdBits, -1,
3679                mOrientedXPrecision, mOrientedYPrecision, mDownTime);
3680        mSentHoverEnter = false;
3681    }
3682}
3683
3684void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) {
3685    if (mCurrentCookedPointerData.touchingIdBits.isEmpty()
3686            && !mCurrentCookedPointerData.hoveringIdBits.isEmpty()) {
3687        int32_t metaState = getContext()->getGlobalMetaState();
3688        if (!mSentHoverEnter) {
3689            dispatchMotion(when, policyFlags, mSource,
3690                    AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
3691                    mCurrentCookedPointerData.pointerProperties,
3692                    mCurrentCookedPointerData.pointerCoords,
3693                    mCurrentCookedPointerData.idToIndex,
3694                    mCurrentCookedPointerData.hoveringIdBits, -1,
3695                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
3696            mSentHoverEnter = true;
3697        }
3698
3699        dispatchMotion(when, policyFlags, mSource,
3700                AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
3701                mCurrentCookedPointerData.pointerProperties,
3702                mCurrentCookedPointerData.pointerCoords,
3703                mCurrentCookedPointerData.idToIndex,
3704                mCurrentCookedPointerData.hoveringIdBits, -1,
3705                mOrientedXPrecision, mOrientedYPrecision, mDownTime);
3706    }
3707}
3708
3709void TouchInputMapper::cookPointerData() {
3710    uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount;
3711
3712    mCurrentCookedPointerData.clear();
3713    mCurrentCookedPointerData.pointerCount = currentPointerCount;
3714    mCurrentCookedPointerData.hoveringIdBits = mCurrentRawPointerData.hoveringIdBits;
3715    mCurrentCookedPointerData.touchingIdBits = mCurrentRawPointerData.touchingIdBits;
3716
3717    // Walk through the the active pointers and map device coordinates onto
3718    // surface coordinates and adjust for display orientation.
3719    for (uint32_t i = 0; i < currentPointerCount; i++) {
3720        const RawPointerData::Pointer& in = mCurrentRawPointerData.pointers[i];
3721
3722        // Size
3723        float touchMajor, touchMinor, toolMajor, toolMinor, size;
3724        switch (mCalibration.sizeCalibration) {
3725        case Calibration::SIZE_CALIBRATION_GEOMETRIC:
3726        case Calibration::SIZE_CALIBRATION_DIAMETER:
3727        case Calibration::SIZE_CALIBRATION_AREA:
3728            if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
3729                touchMajor = in.touchMajor;
3730                touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
3731                toolMajor = in.toolMajor;
3732                toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
3733                size = mRawPointerAxes.touchMinor.valid
3734                        ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
3735            } else if (mRawPointerAxes.touchMajor.valid) {
3736                toolMajor = touchMajor = in.touchMajor;
3737                toolMinor = touchMinor = mRawPointerAxes.touchMinor.valid
3738                        ? in.touchMinor : in.touchMajor;
3739                size = mRawPointerAxes.touchMinor.valid
3740                        ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
3741            } else if (mRawPointerAxes.toolMajor.valid) {
3742                touchMajor = toolMajor = in.toolMajor;
3743                touchMinor = toolMinor = mRawPointerAxes.toolMinor.valid
3744                        ? in.toolMinor : in.toolMajor;
3745                size = mRawPointerAxes.toolMinor.valid
3746                        ? avg(in.toolMajor, in.toolMinor) : in.toolMajor;
3747            } else {
3748                LOG_ASSERT(false, "No touch or tool axes.  "
3749                        "Size calibration should have been resolved to NONE.");
3750                touchMajor = 0;
3751                touchMinor = 0;
3752                toolMajor = 0;
3753                toolMinor = 0;
3754                size = 0;
3755            }
3756
3757            if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) {
3758                uint32_t touchingCount = mCurrentRawPointerData.touchingIdBits.count();
3759                if (touchingCount > 1) {
3760                    touchMajor /= touchingCount;
3761                    touchMinor /= touchingCount;
3762                    toolMajor /= touchingCount;
3763                    toolMinor /= touchingCount;
3764                    size /= touchingCount;
3765                }
3766            }
3767
3768            if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) {
3769                touchMajor *= mGeometricScale;
3770                touchMinor *= mGeometricScale;
3771                toolMajor *= mGeometricScale;
3772                toolMinor *= mGeometricScale;
3773            } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) {
3774                touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
3775                touchMinor = touchMajor;
3776                toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
3777                toolMinor = toolMajor;
3778            } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) {
3779                touchMinor = touchMajor;
3780                toolMinor = toolMajor;
3781            }
3782
3783            mCalibration.applySizeScaleAndBias(&touchMajor);
3784            mCalibration.applySizeScaleAndBias(&touchMinor);
3785            mCalibration.applySizeScaleAndBias(&toolMajor);
3786            mCalibration.applySizeScaleAndBias(&toolMinor);
3787            size *= mSizeScale;
3788            break;
3789        default:
3790            touchMajor = 0;
3791            touchMinor = 0;
3792            toolMajor = 0;
3793            toolMinor = 0;
3794            size = 0;
3795            break;
3796        }
3797
3798        // Pressure
3799        float pressure;
3800        switch (mCalibration.pressureCalibration) {
3801        case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
3802        case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
3803            pressure = in.pressure * mPressureScale;
3804            break;
3805        default:
3806            pressure = in.isHovering ? 0 : 1;
3807            break;
3808        }
3809
3810        // Tilt and Orientation
3811        float tilt;
3812        float orientation;
3813        if (mHaveTilt) {
3814            float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;
3815            float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;
3816            orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
3817            tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
3818        } else {
3819            tilt = 0;
3820
3821            switch (mCalibration.orientationCalibration) {
3822            case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
3823                orientation = (in.orientation - mOrientationCenter) * mOrientationScale;
3824                break;
3825            case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
3826                int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
3827                int32_t c2 = signExtendNybble(in.orientation & 0x0f);
3828                if (c1 != 0 || c2 != 0) {
3829                    orientation = atan2f(c1, c2) * 0.5f;
3830                    float confidence = hypotf(c1, c2);
3831                    float scale = 1.0f + confidence / 16.0f;
3832                    touchMajor *= scale;
3833                    touchMinor /= scale;
3834                    toolMajor *= scale;
3835                    toolMinor /= scale;
3836                } else {
3837                    orientation = 0;
3838                }
3839                break;
3840            }
3841            default:
3842                orientation = 0;
3843            }
3844        }
3845
3846        // Distance
3847        float distance;
3848        switch (mCalibration.distanceCalibration) {
3849        case Calibration::DISTANCE_CALIBRATION_SCALED:
3850            distance = in.distance * mDistanceScale;
3851            break;
3852        default:
3853            distance = 0;
3854        }
3855
3856        // X and Y
3857        // Adjust coords for surface orientation.
3858        float x, y;
3859        switch (mSurfaceOrientation) {
3860        case DISPLAY_ORIENTATION_90:
3861            x = float(in.y - mRawPointerAxes.y.minValue) * mYScale;
3862            y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale;
3863            orientation -= M_PI_2;
3864            if (orientation < - M_PI_2) {
3865                orientation += M_PI;
3866            }
3867            break;
3868        case DISPLAY_ORIENTATION_180:
3869            x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale;
3870            y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale;
3871            break;
3872        case DISPLAY_ORIENTATION_270:
3873            x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale;
3874            y = float(in.x - mRawPointerAxes.x.minValue) * mXScale;
3875            orientation += M_PI_2;
3876            if (orientation > M_PI_2) {
3877                orientation -= M_PI;
3878            }
3879            break;
3880        default:
3881            x = float(in.x - mRawPointerAxes.x.minValue) * mXScale;
3882            y = float(in.y - mRawPointerAxes.y.minValue) * mYScale;
3883            break;
3884        }
3885
3886        // Write output coords.
3887        PointerCoords& out = mCurrentCookedPointerData.pointerCoords[i];
3888        out.clear();
3889        out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
3890        out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
3891        out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
3892        out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
3893        out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
3894        out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
3895        out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
3896        out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
3897        out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
3898        out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
3899        out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
3900
3901        // Write output properties.
3902        PointerProperties& properties = mCurrentCookedPointerData.pointerProperties[i];
3903        uint32_t id = in.id;
3904        properties.clear();
3905        properties.id = id;
3906        properties.toolType = in.toolType;
3907
3908        // Write id index.
3909        mCurrentCookedPointerData.idToIndex[id] = i;
3910    }
3911}
3912
3913void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags,
3914        PointerUsage pointerUsage) {
3915    if (pointerUsage != mPointerUsage) {
3916        abortPointerUsage(when, policyFlags);
3917        mPointerUsage = pointerUsage;
3918    }
3919
3920    switch (mPointerUsage) {
3921    case POINTER_USAGE_GESTURES:
3922        dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
3923        break;
3924    case POINTER_USAGE_STYLUS:
3925        dispatchPointerStylus(when, policyFlags);
3926        break;
3927    case POINTER_USAGE_MOUSE:
3928        dispatchPointerMouse(when, policyFlags);
3929        break;
3930    default:
3931        break;
3932    }
3933}
3934
3935void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) {
3936    switch (mPointerUsage) {
3937    case POINTER_USAGE_GESTURES:
3938        abortPointerGestures(when, policyFlags);
3939        break;
3940    case POINTER_USAGE_STYLUS:
3941        abortPointerStylus(when, policyFlags);
3942        break;
3943    case POINTER_USAGE_MOUSE:
3944        abortPointerMouse(when, policyFlags);
3945        break;
3946    default:
3947        break;
3948    }
3949
3950    mPointerUsage = POINTER_USAGE_NONE;
3951}
3952
3953void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
3954        bool isTimeout) {
3955    // Update current gesture coordinates.
3956    bool cancelPreviousGesture, finishPreviousGesture;
3957    bool sendEvents = preparePointerGestures(when,
3958            &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
3959    if (!sendEvents) {
3960        return;
3961    }
3962    if (finishPreviousGesture) {
3963        cancelPreviousGesture = false;
3964    }
3965
3966    // Update the pointer presentation and spots.
3967    if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3968        mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
3969        if (finishPreviousGesture || cancelPreviousGesture) {
3970            mPointerController->clearSpots();
3971        }
3972        mPointerController->setSpots(mPointerGesture.currentGestureCoords,
3973                mPointerGesture.currentGestureIdToIndex,
3974                mPointerGesture.currentGestureIdBits);
3975    } else {
3976        mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
3977    }
3978
3979    // Show or hide the pointer if needed.
3980    switch (mPointerGesture.currentGestureMode) {
3981    case PointerGesture::NEUTRAL:
3982    case PointerGesture::QUIET:
3983        if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
3984                && (mPointerGesture.lastGestureMode == PointerGesture::SWIPE
3985                        || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)) {
3986            // Remind the user of where the pointer is after finishing a gesture with spots.
3987            mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
3988        }
3989        break;
3990    case PointerGesture::TAP:
3991    case PointerGesture::TAP_DRAG:
3992    case PointerGesture::BUTTON_CLICK_OR_DRAG:
3993    case PointerGesture::HOVER:
3994    case PointerGesture::PRESS:
3995        // Unfade the pointer when the current gesture manipulates the
3996        // area directly under the pointer.
3997        mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
3998        break;
3999    case PointerGesture::SWIPE:
4000    case PointerGesture::FREEFORM:
4001        // Fade the pointer when the current gesture manipulates a different
4002        // area and there are spots to guide the user experience.
4003        if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
4004            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
4005        } else {
4006            mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
4007        }
4008        break;
4009    }
4010
4011    // Send events!
4012    int32_t metaState = getContext()->getGlobalMetaState();
4013    int32_t buttonState = mCurrentButtonState;
4014
4015    // Update last coordinates of pointers that have moved so that we observe the new
4016    // pointer positions at the same time as other pointers that have just gone up.
4017    bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP
4018            || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG
4019            || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
4020            || mPointerGesture.currentGestureMode == PointerGesture::PRESS
4021            || mPointerGesture.currentGestureMode == PointerGesture::SWIPE
4022            || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
4023    bool moveNeeded = false;
4024    if (down && !cancelPreviousGesture && !finishPreviousGesture
4025            && !mPointerGesture.lastGestureIdBits.isEmpty()
4026            && !mPointerGesture.currentGestureIdBits.isEmpty()) {
4027        BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value
4028                & mPointerGesture.lastGestureIdBits.value);
4029        moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties,
4030                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
4031                mPointerGesture.lastGestureProperties,
4032                mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
4033                movedGestureIdBits);
4034        if (buttonState != mLastButtonState) {
4035            moveNeeded = true;
4036        }
4037    }
4038
4039    // Send motion events for all pointers that went up or were canceled.
4040    BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
4041    if (!dispatchedGestureIdBits.isEmpty()) {
4042        if (cancelPreviousGesture) {
4043            dispatchMotion(when, policyFlags, mSource,
4044                    AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
4045                    AMOTION_EVENT_EDGE_FLAG_NONE,
4046                    mPointerGesture.lastGestureProperties,
4047                    mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
4048                    dispatchedGestureIdBits, -1,
4049                    0, 0, mPointerGesture.downTime);
4050
4051            dispatchedGestureIdBits.clear();
4052        } else {
4053            BitSet32 upGestureIdBits;
4054            if (finishPreviousGesture) {
4055                upGestureIdBits = dispatchedGestureIdBits;
4056            } else {
4057                upGestureIdBits.value = dispatchedGestureIdBits.value
4058                        & ~mPointerGesture.currentGestureIdBits.value;
4059            }
4060            while (!upGestureIdBits.isEmpty()) {
4061                uint32_t id = upGestureIdBits.clearFirstMarkedBit();
4062
4063                dispatchMotion(when, policyFlags, mSource,
4064                        AMOTION_EVENT_ACTION_POINTER_UP, 0,
4065                        metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
4066                        mPointerGesture.lastGestureProperties,
4067                        mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
4068                        dispatchedGestureIdBits, id,
4069                        0, 0, mPointerGesture.downTime);
4070
4071                dispatchedGestureIdBits.clearBit(id);
4072            }
4073        }
4074    }
4075
4076    // Send motion events for all pointers that moved.
4077    if (moveNeeded) {
4078        dispatchMotion(when, policyFlags, mSource,
4079                AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
4080                mPointerGesture.currentGestureProperties,
4081                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
4082                dispatchedGestureIdBits, -1,
4083                0, 0, mPointerGesture.downTime);
4084    }
4085
4086    // Send motion events for all pointers that went down.
4087    if (down) {
4088        BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value
4089                & ~dispatchedGestureIdBits.value);
4090        while (!downGestureIdBits.isEmpty()) {
4091            uint32_t id = downGestureIdBits.clearFirstMarkedBit();
4092            dispatchedGestureIdBits.markBit(id);
4093
4094            if (dispatchedGestureIdBits.count() == 1) {
4095                mPointerGesture.downTime = when;
4096            }
4097
4098            dispatchMotion(when, policyFlags, mSource,
4099                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
4100                    mPointerGesture.currentGestureProperties,
4101                    mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
4102                    dispatchedGestureIdBits, id,
4103                    0, 0, mPointerGesture.downTime);
4104        }
4105    }
4106
4107    // Send motion events for hover.
4108    if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
4109        dispatchMotion(when, policyFlags, mSource,
4110                AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
4111                metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
4112                mPointerGesture.currentGestureProperties,
4113                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
4114                mPointerGesture.currentGestureIdBits, -1,
4115                0, 0, mPointerGesture.downTime);
4116    } else if (dispatchedGestureIdBits.isEmpty()
4117            && !mPointerGesture.lastGestureIdBits.isEmpty()) {
4118        // Synthesize a hover move event after all pointers go up to indicate that
4119        // the pointer is hovering again even if the user is not currently touching
4120        // the touch pad.  This ensures that a view will receive a fresh hover enter
4121        // event after a tap.
4122        float x, y;
4123        mPointerController->getPosition(&x, &y);
4124
4125        PointerProperties pointerProperties;
4126        pointerProperties.clear();
4127        pointerProperties.id = 0;
4128        pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
4129
4130        PointerCoords pointerCoords;
4131        pointerCoords.clear();
4132        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
4133        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
4134
4135        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
4136                AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
4137                metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
4138                1, &pointerProperties, &pointerCoords, 0, 0, mPointerGesture.downTime);
4139        getListener()->notifyMotion(&args);
4140    }
4141
4142    // Update state.
4143    mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
4144    if (!down) {
4145        mPointerGesture.lastGestureIdBits.clear();
4146    } else {
4147        mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
4148        for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) {
4149            uint32_t id = idBits.clearFirstMarkedBit();
4150            uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
4151            mPointerGesture.lastGestureProperties[index].copyFrom(
4152                    mPointerGesture.currentGestureProperties[index]);
4153            mPointerGesture.lastGestureCoords[index].copyFrom(
4154                    mPointerGesture.currentGestureCoords[index]);
4155            mPointerGesture.lastGestureIdToIndex[id] = index;
4156        }
4157    }
4158}
4159
4160void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) {
4161    // Cancel previously dispatches pointers.
4162    if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
4163        int32_t metaState = getContext()->getGlobalMetaState();
4164        int32_t buttonState = mCurrentButtonState;
4165        dispatchMotion(when, policyFlags, mSource,
4166                AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
4167                AMOTION_EVENT_EDGE_FLAG_NONE,
4168                mPointerGesture.lastGestureProperties,
4169                mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
4170                mPointerGesture.lastGestureIdBits, -1,
4171                0, 0, mPointerGesture.downTime);
4172    }
4173
4174    // Reset the current pointer gesture.
4175    mPointerGesture.reset();
4176    mPointerVelocityControl.reset();
4177
4178    // Remove any current spots.
4179    if (mPointerController != NULL) {
4180        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
4181        mPointerController->clearSpots();
4182    }
4183}
4184
4185bool TouchInputMapper::preparePointerGestures(nsecs_t when,
4186        bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
4187    *outCancelPreviousGesture = false;
4188    *outFinishPreviousGesture = false;
4189
4190    // Handle TAP timeout.
4191    if (isTimeout) {
4192#if DEBUG_GESTURES
4193        LOGD("Gestures: Processing timeout");
4194#endif
4195
4196        if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
4197            if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
4198                // The tap/drag timeout has not yet expired.
4199                getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime
4200                        + mConfig.pointerGestureTapDragInterval);
4201            } else {
4202                // The tap is finished.
4203#if DEBUG_GESTURES
4204                LOGD("Gestures: TAP finished");
4205#endif
4206                *outFinishPreviousGesture = true;
4207
4208                mPointerGesture.activeGestureId = -1;
4209                mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
4210                mPointerGesture.currentGestureIdBits.clear();
4211
4212                mPointerVelocityControl.reset();
4213                return true;
4214            }
4215        }
4216
4217        // We did not handle this timeout.
4218        return false;
4219    }
4220
4221    const uint32_t currentFingerCount = mCurrentFingerIdBits.count();
4222    const uint32_t lastFingerCount = mLastFingerIdBits.count();
4223
4224    // Update the velocity tracker.
4225    {
4226        VelocityTracker::Position positions[MAX_POINTERS];
4227        uint32_t count = 0;
4228        for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); count++) {
4229            uint32_t id = idBits.clearFirstMarkedBit();
4230            const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
4231            positions[count].x = pointer.x * mPointerXMovementScale;
4232            positions[count].y = pointer.y * mPointerYMovementScale;
4233        }
4234        mPointerGesture.velocityTracker.addMovement(when,
4235                mCurrentFingerIdBits, positions);
4236    }
4237
4238    // Pick a new active touch id if needed.
4239    // Choose an arbitrary pointer that just went down, if there is one.
4240    // Otherwise choose an arbitrary remaining pointer.
4241    // This guarantees we always have an active touch id when there is at least one pointer.
4242    // We keep the same active touch id for as long as possible.
4243    bool activeTouchChanged = false;
4244    int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
4245    int32_t activeTouchId = lastActiveTouchId;
4246    if (activeTouchId < 0) {
4247        if (!mCurrentFingerIdBits.isEmpty()) {
4248            activeTouchChanged = true;
4249            activeTouchId = mPointerGesture.activeTouchId =
4250                    mCurrentFingerIdBits.firstMarkedBit();
4251            mPointerGesture.firstTouchTime = when;
4252        }
4253    } else if (!mCurrentFingerIdBits.hasBit(activeTouchId)) {
4254        activeTouchChanged = true;
4255        if (!mCurrentFingerIdBits.isEmpty()) {
4256            activeTouchId = mPointerGesture.activeTouchId =
4257                    mCurrentFingerIdBits.firstMarkedBit();
4258        } else {
4259            activeTouchId = mPointerGesture.activeTouchId = -1;
4260        }
4261    }
4262
4263    // Determine whether we are in quiet time.
4264    bool isQuietTime = false;
4265    if (activeTouchId < 0) {
4266        mPointerGesture.resetQuietTime();
4267    } else {
4268        isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval;
4269        if (!isQuietTime) {
4270            if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
4271                    || mPointerGesture.lastGestureMode == PointerGesture::SWIPE
4272                    || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)
4273                    && currentFingerCount < 2) {
4274                // Enter quiet time when exiting swipe or freeform state.
4275                // This is to prevent accidentally entering the hover state and flinging the
4276                // pointer when finishing a swipe and there is still one pointer left onscreen.
4277                isQuietTime = true;
4278            } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
4279                    && currentFingerCount >= 2
4280                    && !isPointerDown(mCurrentButtonState)) {
4281                // Enter quiet time when releasing the button and there are still two or more
4282                // fingers down.  This may indicate that one finger was used to press the button
4283                // but it has not gone up yet.
4284                isQuietTime = true;
4285            }
4286            if (isQuietTime) {
4287                mPointerGesture.quietTime = when;
4288            }
4289        }
4290    }
4291
4292    // Switch states based on button and pointer state.
4293    if (isQuietTime) {
4294        // Case 1: Quiet time. (QUIET)
4295#if DEBUG_GESTURES
4296        LOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime
4297                + mConfig.pointerGestureQuietInterval - when) * 0.000001f);
4298#endif
4299        if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
4300            *outFinishPreviousGesture = true;
4301        }
4302
4303        mPointerGesture.activeGestureId = -1;
4304        mPointerGesture.currentGestureMode = PointerGesture::QUIET;
4305        mPointerGesture.currentGestureIdBits.clear();
4306
4307        mPointerVelocityControl.reset();
4308    } else if (isPointerDown(mCurrentButtonState)) {
4309        // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
4310        // The pointer follows the active touch point.
4311        // Emit DOWN, MOVE, UP events at the pointer location.
4312        //
4313        // Only the active touch matters; other fingers are ignored.  This policy helps
4314        // to handle the case where the user places a second finger on the touch pad
4315        // to apply the necessary force to depress an integrated button below the surface.
4316        // We don't want the second finger to be delivered to applications.
4317        //
4318        // For this to work well, we need to make sure to track the pointer that is really
4319        // active.  If the user first puts one finger down to click then adds another
4320        // finger to drag then the active pointer should switch to the finger that is
4321        // being dragged.
4322#if DEBUG_GESTURES
4323        LOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
4324                "currentFingerCount=%d", activeTouchId, currentFingerCount);
4325#endif
4326        // Reset state when just starting.
4327        if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
4328            *outFinishPreviousGesture = true;
4329            mPointerGesture.activeGestureId = 0;
4330        }
4331
4332        // Switch pointers if needed.
4333        // Find the fastest pointer and follow it.
4334        if (activeTouchId >= 0 && currentFingerCount > 1) {
4335            int32_t bestId = -1;
4336            float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
4337            for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); ) {
4338                uint32_t id = idBits.clearFirstMarkedBit();
4339                float vx, vy;
4340                if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
4341                    float speed = hypotf(vx, vy);
4342                    if (speed > bestSpeed) {
4343                        bestId = id;
4344                        bestSpeed = speed;
4345                    }
4346                }
4347            }
4348            if (bestId >= 0 && bestId != activeTouchId) {
4349                mPointerGesture.activeTouchId = activeTouchId = bestId;
4350                activeTouchChanged = true;
4351#if DEBUG_GESTURES
4352                LOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
4353                        "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
4354#endif
4355            }
4356        }
4357
4358        if (activeTouchId >= 0 && mLastFingerIdBits.hasBit(activeTouchId)) {
4359            const RawPointerData::Pointer& currentPointer =
4360                    mCurrentRawPointerData.pointerForId(activeTouchId);
4361            const RawPointerData::Pointer& lastPointer =
4362                    mLastRawPointerData.pointerForId(activeTouchId);
4363            float deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
4364            float deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
4365
4366            rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
4367            mPointerVelocityControl.move(when, &deltaX, &deltaY);
4368
4369            // Move the pointer using a relative motion.
4370            // When using spots, the click will occur at the position of the anchor
4371            // spot and all other spots will move there.
4372            mPointerController->move(deltaX, deltaY);
4373        } else {
4374            mPointerVelocityControl.reset();
4375        }
4376
4377        float x, y;
4378        mPointerController->getPosition(&x, &y);
4379
4380        mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
4381        mPointerGesture.currentGestureIdBits.clear();
4382        mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4383        mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
4384        mPointerGesture.currentGestureProperties[0].clear();
4385        mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
4386        mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
4387        mPointerGesture.currentGestureCoords[0].clear();
4388        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
4389        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
4390        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4391    } else if (currentFingerCount == 0) {
4392        // Case 3. No fingers down and button is not pressed. (NEUTRAL)
4393        if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
4394            *outFinishPreviousGesture = true;
4395        }
4396
4397        // Watch for taps coming out of HOVER or TAP_DRAG mode.
4398        // Checking for taps after TAP_DRAG allows us to detect double-taps.
4399        bool tapped = false;
4400        if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
4401                || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
4402                && lastFingerCount == 1) {
4403            if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
4404                float x, y;
4405                mPointerController->getPosition(&x, &y);
4406                if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
4407                        && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
4408#if DEBUG_GESTURES
4409                    LOGD("Gestures: TAP");
4410#endif
4411
4412                    mPointerGesture.tapUpTime = when;
4413                    getContext()->requestTimeoutAtTime(when
4414                            + mConfig.pointerGestureTapDragInterval);
4415
4416                    mPointerGesture.activeGestureId = 0;
4417                    mPointerGesture.currentGestureMode = PointerGesture::TAP;
4418                    mPointerGesture.currentGestureIdBits.clear();
4419                    mPointerGesture.currentGestureIdBits.markBit(
4420                            mPointerGesture.activeGestureId);
4421                    mPointerGesture.currentGestureIdToIndex[
4422                            mPointerGesture.activeGestureId] = 0;
4423                    mPointerGesture.currentGestureProperties[0].clear();
4424                    mPointerGesture.currentGestureProperties[0].id =
4425                            mPointerGesture.activeGestureId;
4426                    mPointerGesture.currentGestureProperties[0].toolType =
4427                            AMOTION_EVENT_TOOL_TYPE_FINGER;
4428                    mPointerGesture.currentGestureCoords[0].clear();
4429                    mPointerGesture.currentGestureCoords[0].setAxisValue(
4430                            AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
4431                    mPointerGesture.currentGestureCoords[0].setAxisValue(
4432                            AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY);
4433                    mPointerGesture.currentGestureCoords[0].setAxisValue(
4434                            AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4435
4436                    tapped = true;
4437                } else {
4438#if DEBUG_GESTURES
4439                    LOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f",
4440                            x - mPointerGesture.tapX,
4441                            y - mPointerGesture.tapY);
4442#endif
4443                }
4444            } else {
4445#if DEBUG_GESTURES
4446                LOGD("Gestures: Not a TAP, %0.3fms since down",
4447                        (when - mPointerGesture.tapDownTime) * 0.000001f);
4448#endif
4449            }
4450        }
4451
4452        mPointerVelocityControl.reset();
4453
4454        if (!tapped) {
4455#if DEBUG_GESTURES
4456            LOGD("Gestures: NEUTRAL");
4457#endif
4458            mPointerGesture.activeGestureId = -1;
4459            mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
4460            mPointerGesture.currentGestureIdBits.clear();
4461        }
4462    } else if (currentFingerCount == 1) {
4463        // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
4464        // The pointer follows the active touch point.
4465        // When in HOVER, emit HOVER_MOVE events at the pointer location.
4466        // When in TAP_DRAG, emit MOVE events at the pointer location.
4467        LOG_ASSERT(activeTouchId >= 0);
4468
4469        mPointerGesture.currentGestureMode = PointerGesture::HOVER;
4470        if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
4471            if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
4472                float x, y;
4473                mPointerController->getPosition(&x, &y);
4474                if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
4475                        && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
4476                    mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
4477                } else {
4478#if DEBUG_GESTURES
4479                    LOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
4480                            x - mPointerGesture.tapX,
4481                            y - mPointerGesture.tapY);
4482#endif
4483                }
4484            } else {
4485#if DEBUG_GESTURES
4486                LOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
4487                        (when - mPointerGesture.tapUpTime) * 0.000001f);
4488#endif
4489            }
4490        } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
4491            mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
4492        }
4493
4494        if (mLastFingerIdBits.hasBit(activeTouchId)) {
4495            const RawPointerData::Pointer& currentPointer =
4496                    mCurrentRawPointerData.pointerForId(activeTouchId);
4497            const RawPointerData::Pointer& lastPointer =
4498                    mLastRawPointerData.pointerForId(activeTouchId);
4499            float deltaX = (currentPointer.x - lastPointer.x)
4500                    * mPointerXMovementScale;
4501            float deltaY = (currentPointer.y - lastPointer.y)
4502                    * mPointerYMovementScale;
4503
4504            rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
4505            mPointerVelocityControl.move(when, &deltaX, &deltaY);
4506
4507            // Move the pointer using a relative motion.
4508            // When using spots, the hover or drag will occur at the position of the anchor spot.
4509            mPointerController->move(deltaX, deltaY);
4510        } else {
4511            mPointerVelocityControl.reset();
4512        }
4513
4514        bool down;
4515        if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
4516#if DEBUG_GESTURES
4517            LOGD("Gestures: TAP_DRAG");
4518#endif
4519            down = true;
4520        } else {
4521#if DEBUG_GESTURES
4522            LOGD("Gestures: HOVER");
4523#endif
4524            if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
4525                *outFinishPreviousGesture = true;
4526            }
4527            mPointerGesture.activeGestureId = 0;
4528            down = false;
4529        }
4530
4531        float x, y;
4532        mPointerController->getPosition(&x, &y);
4533
4534        mPointerGesture.currentGestureIdBits.clear();
4535        mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4536        mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
4537        mPointerGesture.currentGestureProperties[0].clear();
4538        mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
4539        mPointerGesture.currentGestureProperties[0].toolType =
4540                AMOTION_EVENT_TOOL_TYPE_FINGER;
4541        mPointerGesture.currentGestureCoords[0].clear();
4542        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
4543        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
4544        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
4545                down ? 1.0f : 0.0f);
4546
4547        if (lastFingerCount == 0 && currentFingerCount != 0) {
4548            mPointerGesture.resetTap();
4549            mPointerGesture.tapDownTime = when;
4550            mPointerGesture.tapX = x;
4551            mPointerGesture.tapY = y;
4552        }
4553    } else {
4554        // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
4555        // We need to provide feedback for each finger that goes down so we cannot wait
4556        // for the fingers to move before deciding what to do.
4557        //
4558        // The ambiguous case is deciding what to do when there are two fingers down but they
4559        // have not moved enough to determine whether they are part of a drag or part of a
4560        // freeform gesture, or just a press or long-press at the pointer location.
4561        //
4562        // When there are two fingers we start with the PRESS hypothesis and we generate a
4563        // down at the pointer location.
4564        //
4565        // When the two fingers move enough or when additional fingers are added, we make
4566        // a decision to transition into SWIPE or FREEFORM mode accordingly.
4567        LOG_ASSERT(activeTouchId >= 0);
4568
4569        bool settled = when >= mPointerGesture.firstTouchTime
4570                + mConfig.pointerGestureMultitouchSettleInterval;
4571        if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
4572                && mPointerGesture.lastGestureMode != PointerGesture::SWIPE
4573                && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
4574            *outFinishPreviousGesture = true;
4575        } else if (!settled && currentFingerCount > lastFingerCount) {
4576            // Additional pointers have gone down but not yet settled.
4577            // Reset the gesture.
4578#if DEBUG_GESTURES
4579            LOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
4580                    "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
4581                            + mConfig.pointerGestureMultitouchSettleInterval - when)
4582                            * 0.000001f);
4583#endif
4584            *outCancelPreviousGesture = true;
4585        } else {
4586            // Continue previous gesture.
4587            mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
4588        }
4589
4590        if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
4591            mPointerGesture.currentGestureMode = PointerGesture::PRESS;
4592            mPointerGesture.activeGestureId = 0;
4593            mPointerGesture.referenceIdBits.clear();
4594            mPointerVelocityControl.reset();
4595
4596            // Use the centroid and pointer location as the reference points for the gesture.
4597#if DEBUG_GESTURES
4598            LOGD("Gestures: Using centroid as reference for MULTITOUCH, "
4599                    "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
4600                            + mConfig.pointerGestureMultitouchSettleInterval - when)
4601                            * 0.000001f);
4602#endif
4603            mCurrentRawPointerData.getCentroidOfTouchingPointers(
4604                    &mPointerGesture.referenceTouchX,
4605                    &mPointerGesture.referenceTouchY);
4606            mPointerController->getPosition(&mPointerGesture.referenceGestureX,
4607                    &mPointerGesture.referenceGestureY);
4608        }
4609
4610        // Clear the reference deltas for fingers not yet included in the reference calculation.
4611        for (BitSet32 idBits(mCurrentFingerIdBits.value
4612                & ~mPointerGesture.referenceIdBits.value); !idBits.isEmpty(); ) {
4613            uint32_t id = idBits.clearFirstMarkedBit();
4614            mPointerGesture.referenceDeltas[id].dx = 0;
4615            mPointerGesture.referenceDeltas[id].dy = 0;
4616        }
4617        mPointerGesture.referenceIdBits = mCurrentFingerIdBits;
4618
4619        // Add delta for all fingers and calculate a common movement delta.
4620        float commonDeltaX = 0, commonDeltaY = 0;
4621        BitSet32 commonIdBits(mLastFingerIdBits.value
4622                & mCurrentFingerIdBits.value);
4623        for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
4624            bool first = (idBits == commonIdBits);
4625            uint32_t id = idBits.clearFirstMarkedBit();
4626            const RawPointerData::Pointer& cpd = mCurrentRawPointerData.pointerForId(id);
4627            const RawPointerData::Pointer& lpd = mLastRawPointerData.pointerForId(id);
4628            PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
4629            delta.dx += cpd.x - lpd.x;
4630            delta.dy += cpd.y - lpd.y;
4631
4632            if (first) {
4633                commonDeltaX = delta.dx;
4634                commonDeltaY = delta.dy;
4635            } else {
4636                commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
4637                commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
4638            }
4639        }
4640
4641        // Consider transitions from PRESS to SWIPE or MULTITOUCH.
4642        if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
4643            float dist[MAX_POINTER_ID + 1];
4644            int32_t distOverThreshold = 0;
4645            for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
4646                uint32_t id = idBits.clearFirstMarkedBit();
4647                PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
4648                dist[id] = hypotf(delta.dx * mPointerXZoomScale,
4649                        delta.dy * mPointerYZoomScale);
4650                if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) {
4651                    distOverThreshold += 1;
4652                }
4653            }
4654
4655            // Only transition when at least two pointers have moved further than
4656            // the minimum distance threshold.
4657            if (distOverThreshold >= 2) {
4658                if (currentFingerCount > 2) {
4659                    // There are more than two pointers, switch to FREEFORM.
4660#if DEBUG_GESTURES
4661                    LOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
4662                            currentFingerCount);
4663#endif
4664                    *outCancelPreviousGesture = true;
4665                    mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
4666                } else {
4667                    // There are exactly two pointers.
4668                    BitSet32 idBits(mCurrentFingerIdBits);
4669                    uint32_t id1 = idBits.clearFirstMarkedBit();
4670                    uint32_t id2 = idBits.firstMarkedBit();
4671                    const RawPointerData::Pointer& p1 = mCurrentRawPointerData.pointerForId(id1);
4672                    const RawPointerData::Pointer& p2 = mCurrentRawPointerData.pointerForId(id2);
4673                    float mutualDistance = distance(p1.x, p1.y, p2.x, p2.y);
4674                    if (mutualDistance > mPointerGestureMaxSwipeWidth) {
4675                        // There are two pointers but they are too far apart for a SWIPE,
4676                        // switch to FREEFORM.
4677#if DEBUG_GESTURES
4678                        LOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
4679                                mutualDistance, mPointerGestureMaxSwipeWidth);
4680#endif
4681                        *outCancelPreviousGesture = true;
4682                        mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
4683                    } else {
4684                        // There are two pointers.  Wait for both pointers to start moving
4685                        // before deciding whether this is a SWIPE or FREEFORM gesture.
4686                        float dist1 = dist[id1];
4687                        float dist2 = dist[id2];
4688                        if (dist1 >= mConfig.pointerGestureMultitouchMinDistance
4689                                && dist2 >= mConfig.pointerGestureMultitouchMinDistance) {
4690                            // Calculate the dot product of the displacement vectors.
4691                            // When the vectors are oriented in approximately the same direction,
4692                            // the angle betweeen them is near zero and the cosine of the angle
4693                            // approches 1.0.  Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
4694                            PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
4695                            PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
4696                            float dx1 = delta1.dx * mPointerXZoomScale;
4697                            float dy1 = delta1.dy * mPointerYZoomScale;
4698                            float dx2 = delta2.dx * mPointerXZoomScale;
4699                            float dy2 = delta2.dy * mPointerYZoomScale;
4700                            float dot = dx1 * dx2 + dy1 * dy2;
4701                            float cosine = dot / (dist1 * dist2); // denominator always > 0
4702                            if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
4703                                // Pointers are moving in the same direction.  Switch to SWIPE.
4704#if DEBUG_GESTURES
4705                                LOGD("Gestures: PRESS transitioned to SWIPE, "
4706                                        "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
4707                                        "cosine %0.3f >= %0.3f",
4708                                        dist1, mConfig.pointerGestureMultitouchMinDistance,
4709                                        dist2, mConfig.pointerGestureMultitouchMinDistance,
4710                                        cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
4711#endif
4712                                mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
4713                            } else {
4714                                // Pointers are moving in different directions.  Switch to FREEFORM.
4715#if DEBUG_GESTURES
4716                                LOGD("Gestures: PRESS transitioned to FREEFORM, "
4717                                        "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
4718                                        "cosine %0.3f < %0.3f",
4719                                        dist1, mConfig.pointerGestureMultitouchMinDistance,
4720                                        dist2, mConfig.pointerGestureMultitouchMinDistance,
4721                                        cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
4722#endif
4723                                *outCancelPreviousGesture = true;
4724                                mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
4725                            }
4726                        }
4727                    }
4728                }
4729            }
4730        } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
4731            // Switch from SWIPE to FREEFORM if additional pointers go down.
4732            // Cancel previous gesture.
4733            if (currentFingerCount > 2) {
4734#if DEBUG_GESTURES
4735                LOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
4736                        currentFingerCount);
4737#endif
4738                *outCancelPreviousGesture = true;
4739                mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
4740            }
4741        }
4742
4743        // Move the reference points based on the overall group motion of the fingers
4744        // except in PRESS mode while waiting for a transition to occur.
4745        if (mPointerGesture.currentGestureMode != PointerGesture::PRESS
4746                && (commonDeltaX || commonDeltaY)) {
4747            for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
4748                uint32_t id = idBits.clearFirstMarkedBit();
4749                PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
4750                delta.dx = 0;
4751                delta.dy = 0;
4752            }
4753
4754            mPointerGesture.referenceTouchX += commonDeltaX;
4755            mPointerGesture.referenceTouchY += commonDeltaY;
4756
4757            commonDeltaX *= mPointerXMovementScale;
4758            commonDeltaY *= mPointerYMovementScale;
4759
4760            rotateDelta(mSurfaceOrientation, &commonDeltaX, &commonDeltaY);
4761            mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
4762
4763            mPointerGesture.referenceGestureX += commonDeltaX;
4764            mPointerGesture.referenceGestureY += commonDeltaY;
4765        }
4766
4767        // Report gestures.
4768        if (mPointerGesture.currentGestureMode == PointerGesture::PRESS
4769                || mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
4770            // PRESS or SWIPE mode.
4771#if DEBUG_GESTURES
4772            LOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
4773                    "activeGestureId=%d, currentTouchPointerCount=%d",
4774                    activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
4775#endif
4776            LOG_ASSERT(mPointerGesture.activeGestureId >= 0);
4777
4778            mPointerGesture.currentGestureIdBits.clear();
4779            mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4780            mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
4781            mPointerGesture.currentGestureProperties[0].clear();
4782            mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
4783            mPointerGesture.currentGestureProperties[0].toolType =
4784                    AMOTION_EVENT_TOOL_TYPE_FINGER;
4785            mPointerGesture.currentGestureCoords[0].clear();
4786            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
4787                    mPointerGesture.referenceGestureX);
4788            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
4789                    mPointerGesture.referenceGestureY);
4790            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4791        } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
4792            // FREEFORM mode.
4793#if DEBUG_GESTURES
4794            LOGD("Gestures: FREEFORM activeTouchId=%d,"
4795                    "activeGestureId=%d, currentTouchPointerCount=%d",
4796                    activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
4797#endif
4798            LOG_ASSERT(mPointerGesture.activeGestureId >= 0);
4799
4800            mPointerGesture.currentGestureIdBits.clear();
4801
4802            BitSet32 mappedTouchIdBits;
4803            BitSet32 usedGestureIdBits;
4804            if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
4805                // Initially, assign the active gesture id to the active touch point
4806                // if there is one.  No other touch id bits are mapped yet.
4807                if (!*outCancelPreviousGesture) {
4808                    mappedTouchIdBits.markBit(activeTouchId);
4809                    usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
4810                    mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
4811                            mPointerGesture.activeGestureId;
4812                } else {
4813                    mPointerGesture.activeGestureId = -1;
4814                }
4815            } else {
4816                // Otherwise, assume we mapped all touches from the previous frame.
4817                // Reuse all mappings that are still applicable.
4818                mappedTouchIdBits.value = mLastFingerIdBits.value
4819                        & mCurrentFingerIdBits.value;
4820                usedGestureIdBits = mPointerGesture.lastGestureIdBits;
4821
4822                // Check whether we need to choose a new active gesture id because the
4823                // current went went up.
4824                for (BitSet32 upTouchIdBits(mLastFingerIdBits.value
4825                        & ~mCurrentFingerIdBits.value);
4826                        !upTouchIdBits.isEmpty(); ) {
4827                    uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit();
4828                    uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
4829                    if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
4830                        mPointerGesture.activeGestureId = -1;
4831                        break;
4832                    }
4833                }
4834            }
4835
4836#if DEBUG_GESTURES
4837            LOGD("Gestures: FREEFORM follow up "
4838                    "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
4839                    "activeGestureId=%d",
4840                    mappedTouchIdBits.value, usedGestureIdBits.value,
4841                    mPointerGesture.activeGestureId);
4842#endif
4843
4844            BitSet32 idBits(mCurrentFingerIdBits);
4845            for (uint32_t i = 0; i < currentFingerCount; i++) {
4846                uint32_t touchId = idBits.clearFirstMarkedBit();
4847                uint32_t gestureId;
4848                if (!mappedTouchIdBits.hasBit(touchId)) {
4849                    gestureId = usedGestureIdBits.markFirstUnmarkedBit();
4850                    mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
4851#if DEBUG_GESTURES
4852                    LOGD("Gestures: FREEFORM "
4853                            "new mapping for touch id %d -> gesture id %d",
4854                            touchId, gestureId);
4855#endif
4856                } else {
4857                    gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
4858#if DEBUG_GESTURES
4859                    LOGD("Gestures: FREEFORM "
4860                            "existing mapping for touch id %d -> gesture id %d",
4861                            touchId, gestureId);
4862#endif
4863                }
4864                mPointerGesture.currentGestureIdBits.markBit(gestureId);
4865                mPointerGesture.currentGestureIdToIndex[gestureId] = i;
4866
4867                const RawPointerData::Pointer& pointer =
4868                        mCurrentRawPointerData.pointerForId(touchId);
4869                float deltaX = (pointer.x - mPointerGesture.referenceTouchX)
4870                        * mPointerXZoomScale;
4871                float deltaY = (pointer.y - mPointerGesture.referenceTouchY)
4872                        * mPointerYZoomScale;
4873                rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
4874
4875                mPointerGesture.currentGestureProperties[i].clear();
4876                mPointerGesture.currentGestureProperties[i].id = gestureId;
4877                mPointerGesture.currentGestureProperties[i].toolType =
4878                        AMOTION_EVENT_TOOL_TYPE_FINGER;
4879                mPointerGesture.currentGestureCoords[i].clear();
4880                mPointerGesture.currentGestureCoords[i].setAxisValue(
4881                        AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX);
4882                mPointerGesture.currentGestureCoords[i].setAxisValue(
4883                        AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY + deltaY);
4884                mPointerGesture.currentGestureCoords[i].setAxisValue(
4885                        AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4886            }
4887
4888            if (mPointerGesture.activeGestureId < 0) {
4889                mPointerGesture.activeGestureId =
4890                        mPointerGesture.currentGestureIdBits.firstMarkedBit();
4891#if DEBUG_GESTURES
4892                LOGD("Gestures: FREEFORM new "
4893                        "activeGestureId=%d", mPointerGesture.activeGestureId);
4894#endif
4895            }
4896        }
4897    }
4898
4899    mPointerController->setButtonState(mCurrentButtonState);
4900
4901#if DEBUG_GESTURES
4902    LOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
4903            "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
4904            "lastGestureMode=%d, lastGestureIdBits=0x%08x",
4905            toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
4906            mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
4907            mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
4908    for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) {
4909        uint32_t id = idBits.clearFirstMarkedBit();
4910        uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
4911        const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
4912        const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
4913        LOGD("  currentGesture[%d]: index=%d, toolType=%d, "
4914                "x=%0.3f, y=%0.3f, pressure=%0.3f",
4915                id, index, properties.toolType,
4916                coords.getAxisValue(AMOTION_EVENT_AXIS_X),
4917                coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
4918                coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
4919    }
4920    for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) {
4921        uint32_t id = idBits.clearFirstMarkedBit();
4922        uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
4923        const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
4924        const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
4925        LOGD("  lastGesture[%d]: index=%d, toolType=%d, "
4926                "x=%0.3f, y=%0.3f, pressure=%0.3f",
4927                id, index, properties.toolType,
4928                coords.getAxisValue(AMOTION_EVENT_AXIS_X),
4929                coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
4930                coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
4931    }
4932#endif
4933    return true;
4934}
4935
4936void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) {
4937    mPointerSimple.currentCoords.clear();
4938    mPointerSimple.currentProperties.clear();
4939
4940    bool down, hovering;
4941    if (!mCurrentStylusIdBits.isEmpty()) {
4942        uint32_t id = mCurrentStylusIdBits.firstMarkedBit();
4943        uint32_t index = mCurrentCookedPointerData.idToIndex[id];
4944        float x = mCurrentCookedPointerData.pointerCoords[index].getX();
4945        float y = mCurrentCookedPointerData.pointerCoords[index].getY();
4946        mPointerController->setPosition(x, y);
4947
4948        hovering = mCurrentCookedPointerData.hoveringIdBits.hasBit(id);
4949        down = !hovering;
4950
4951        mPointerController->getPosition(&x, &y);
4952        mPointerSimple.currentCoords.copyFrom(mCurrentCookedPointerData.pointerCoords[index]);
4953        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
4954        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
4955        mPointerSimple.currentProperties.id = 0;
4956        mPointerSimple.currentProperties.toolType =
4957                mCurrentCookedPointerData.pointerProperties[index].toolType;
4958    } else {
4959        down = false;
4960        hovering = false;
4961    }
4962
4963    dispatchPointerSimple(when, policyFlags, down, hovering);
4964}
4965
4966void TouchInputMapper::abortPointerStylus(nsecs_t when, uint32_t policyFlags) {
4967    abortPointerSimple(when, policyFlags);
4968}
4969
4970void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) {
4971    mPointerSimple.currentCoords.clear();
4972    mPointerSimple.currentProperties.clear();
4973
4974    bool down, hovering;
4975    if (!mCurrentMouseIdBits.isEmpty()) {
4976        uint32_t id = mCurrentMouseIdBits.firstMarkedBit();
4977        uint32_t currentIndex = mCurrentRawPointerData.idToIndex[id];
4978        if (mLastMouseIdBits.hasBit(id)) {
4979            uint32_t lastIndex = mCurrentRawPointerData.idToIndex[id];
4980            float deltaX = (mCurrentRawPointerData.pointers[currentIndex].x
4981                    - mLastRawPointerData.pointers[lastIndex].x)
4982                    * mPointerXMovementScale;
4983            float deltaY = (mCurrentRawPointerData.pointers[currentIndex].y
4984                    - mLastRawPointerData.pointers[lastIndex].y)
4985                    * mPointerYMovementScale;
4986
4987            rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
4988            mPointerVelocityControl.move(when, &deltaX, &deltaY);
4989
4990            mPointerController->move(deltaX, deltaY);
4991        } else {
4992            mPointerVelocityControl.reset();
4993        }
4994
4995        down = isPointerDown(mCurrentButtonState);
4996        hovering = !down;
4997
4998        float x, y;
4999        mPointerController->getPosition(&x, &y);
5000        mPointerSimple.currentCoords.copyFrom(
5001                mCurrentCookedPointerData.pointerCoords[currentIndex]);
5002        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
5003        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5004        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
5005                hovering ? 0.0f : 1.0f);
5006        mPointerSimple.currentProperties.id = 0;
5007        mPointerSimple.currentProperties.toolType =
5008                mCurrentCookedPointerData.pointerProperties[currentIndex].toolType;
5009    } else {
5010        mPointerVelocityControl.reset();
5011
5012        down = false;
5013        hovering = false;
5014    }
5015
5016    dispatchPointerSimple(when, policyFlags, down, hovering);
5017}
5018
5019void TouchInputMapper::abortPointerMouse(nsecs_t when, uint32_t policyFlags) {
5020    abortPointerSimple(when, policyFlags);
5021
5022    mPointerVelocityControl.reset();
5023}
5024
5025void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
5026        bool down, bool hovering) {
5027    int32_t metaState = getContext()->getGlobalMetaState();
5028
5029    if (mPointerController != NULL) {
5030        if (down || hovering) {
5031            mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
5032            mPointerController->clearSpots();
5033            mPointerController->setButtonState(mCurrentButtonState);
5034            mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
5035        } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
5036            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
5037        }
5038    }
5039
5040    if (mPointerSimple.down && !down) {
5041        mPointerSimple.down = false;
5042
5043        // Send up.
5044        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5045                 AMOTION_EVENT_ACTION_UP, 0, metaState, mLastButtonState, 0,
5046                 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
5047                 mOrientedXPrecision, mOrientedYPrecision,
5048                 mPointerSimple.downTime);
5049        getListener()->notifyMotion(&args);
5050    }
5051
5052    if (mPointerSimple.hovering && !hovering) {
5053        mPointerSimple.hovering = false;
5054
5055        // Send hover exit.
5056        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5057                AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
5058                1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
5059                mOrientedXPrecision, mOrientedYPrecision,
5060                mPointerSimple.downTime);
5061        getListener()->notifyMotion(&args);
5062    }
5063
5064    if (down) {
5065        if (!mPointerSimple.down) {
5066            mPointerSimple.down = true;
5067            mPointerSimple.downTime = when;
5068
5069            // Send down.
5070            NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5071                    AMOTION_EVENT_ACTION_DOWN, 0, metaState, mCurrentButtonState, 0,
5072                    1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
5073                    mOrientedXPrecision, mOrientedYPrecision,
5074                    mPointerSimple.downTime);
5075            getListener()->notifyMotion(&args);
5076        }
5077
5078        // Send move.
5079        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5080                AMOTION_EVENT_ACTION_MOVE, 0, metaState, mCurrentButtonState, 0,
5081                1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
5082                mOrientedXPrecision, mOrientedYPrecision,
5083                mPointerSimple.downTime);
5084        getListener()->notifyMotion(&args);
5085    }
5086
5087    if (hovering) {
5088        if (!mPointerSimple.hovering) {
5089            mPointerSimple.hovering = true;
5090
5091            // Send hover enter.
5092            NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5093                    AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
5094                    1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
5095                    mOrientedXPrecision, mOrientedYPrecision,
5096                    mPointerSimple.downTime);
5097            getListener()->notifyMotion(&args);
5098        }
5099
5100        // Send hover move.
5101        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5102                AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
5103                1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
5104                mOrientedXPrecision, mOrientedYPrecision,
5105                mPointerSimple.downTime);
5106        getListener()->notifyMotion(&args);
5107    }
5108
5109    if (mCurrentRawVScroll || mCurrentRawHScroll) {
5110        float vscroll = mCurrentRawVScroll;
5111        float hscroll = mCurrentRawHScroll;
5112        mWheelYVelocityControl.move(when, NULL, &vscroll);
5113        mWheelXVelocityControl.move(when, &hscroll, NULL);
5114
5115        // Send scroll.
5116        PointerCoords pointerCoords;
5117        pointerCoords.copyFrom(mPointerSimple.currentCoords);
5118        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
5119        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
5120
5121        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5122                AMOTION_EVENT_ACTION_SCROLL, 0, metaState, mCurrentButtonState, 0,
5123                1, &mPointerSimple.currentProperties, &pointerCoords,
5124                mOrientedXPrecision, mOrientedYPrecision,
5125                mPointerSimple.downTime);
5126        getListener()->notifyMotion(&args);
5127    }
5128
5129    // Save state.
5130    if (down || hovering) {
5131        mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords);
5132        mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
5133    } else {
5134        mPointerSimple.reset();
5135    }
5136}
5137
5138void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) {
5139    mPointerSimple.currentCoords.clear();
5140    mPointerSimple.currentProperties.clear();
5141
5142    dispatchPointerSimple(when, policyFlags, false, false);
5143}
5144
5145void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
5146        int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
5147        const PointerProperties* properties, const PointerCoords* coords,
5148        const uint32_t* idToIndex, BitSet32 idBits,
5149        int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {
5150    PointerCoords pointerCoords[MAX_POINTERS];
5151    PointerProperties pointerProperties[MAX_POINTERS];
5152    uint32_t pointerCount = 0;
5153    while (!idBits.isEmpty()) {
5154        uint32_t id = idBits.clearFirstMarkedBit();
5155        uint32_t index = idToIndex[id];
5156        pointerProperties[pointerCount].copyFrom(properties[index]);
5157        pointerCoords[pointerCount].copyFrom(coords[index]);
5158
5159        if (changedId >= 0 && id == uint32_t(changedId)) {
5160            action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
5161        }
5162
5163        pointerCount += 1;
5164    }
5165
5166    LOG_ASSERT(pointerCount != 0);
5167
5168    if (changedId >= 0 && pointerCount == 1) {
5169        // Replace initial down and final up action.
5170        // We can compare the action without masking off the changed pointer index
5171        // because we know the index is 0.
5172        if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
5173            action = AMOTION_EVENT_ACTION_DOWN;
5174        } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
5175            action = AMOTION_EVENT_ACTION_UP;
5176        } else {
5177            // Can't happen.
5178            LOG_ASSERT(false);
5179        }
5180    }
5181
5182    NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
5183            action, flags, metaState, buttonState, edgeFlags,
5184            pointerCount, pointerProperties, pointerCoords, xPrecision, yPrecision, downTime);
5185    getListener()->notifyMotion(&args);
5186}
5187
5188bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties,
5189        const PointerCoords* inCoords, const uint32_t* inIdToIndex,
5190        PointerProperties* outProperties, PointerCoords* outCoords, const uint32_t* outIdToIndex,
5191        BitSet32 idBits) const {
5192    bool changed = false;
5193    while (!idBits.isEmpty()) {
5194        uint32_t id = idBits.clearFirstMarkedBit();
5195        uint32_t inIndex = inIdToIndex[id];
5196        uint32_t outIndex = outIdToIndex[id];
5197
5198        const PointerProperties& curInProperties = inProperties[inIndex];
5199        const PointerCoords& curInCoords = inCoords[inIndex];
5200        PointerProperties& curOutProperties = outProperties[outIndex];
5201        PointerCoords& curOutCoords = outCoords[outIndex];
5202
5203        if (curInProperties != curOutProperties) {
5204            curOutProperties.copyFrom(curInProperties);
5205            changed = true;
5206        }
5207
5208        if (curInCoords != curOutCoords) {
5209            curOutCoords.copyFrom(curInCoords);
5210            changed = true;
5211        }
5212    }
5213    return changed;
5214}
5215
5216void TouchInputMapper::fadePointer() {
5217    if (mPointerController != NULL) {
5218        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
5219    }
5220}
5221
5222bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
5223    return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue
5224            && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue;
5225}
5226
5227const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(
5228        int32_t x, int32_t y) {
5229    size_t numVirtualKeys = mVirtualKeys.size();
5230    for (size_t i = 0; i < numVirtualKeys; i++) {
5231        const VirtualKey& virtualKey = mVirtualKeys[i];
5232
5233#if DEBUG_VIRTUAL_KEYS
5234        LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
5235                "left=%d, top=%d, right=%d, bottom=%d",
5236                x, y,
5237                virtualKey.keyCode, virtualKey.scanCode,
5238                virtualKey.hitLeft, virtualKey.hitTop,
5239                virtualKey.hitRight, virtualKey.hitBottom);
5240#endif
5241
5242        if (virtualKey.isHit(x, y)) {
5243            return & virtualKey;
5244        }
5245    }
5246
5247    return NULL;
5248}
5249
5250void TouchInputMapper::assignPointerIds() {
5251    uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount;
5252    uint32_t lastPointerCount = mLastRawPointerData.pointerCount;
5253
5254    mCurrentRawPointerData.clearIdBits();
5255
5256    if (currentPointerCount == 0) {
5257        // No pointers to assign.
5258        return;
5259    }
5260
5261    if (lastPointerCount == 0) {
5262        // All pointers are new.
5263        for (uint32_t i = 0; i < currentPointerCount; i++) {
5264            uint32_t id = i;
5265            mCurrentRawPointerData.pointers[i].id = id;
5266            mCurrentRawPointerData.idToIndex[id] = i;
5267            mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(i));
5268        }
5269        return;
5270    }
5271
5272    if (currentPointerCount == 1 && lastPointerCount == 1
5273            && mCurrentRawPointerData.pointers[0].toolType
5274                    == mLastRawPointerData.pointers[0].toolType) {
5275        // Only one pointer and no change in count so it must have the same id as before.
5276        uint32_t id = mLastRawPointerData.pointers[0].id;
5277        mCurrentRawPointerData.pointers[0].id = id;
5278        mCurrentRawPointerData.idToIndex[id] = 0;
5279        mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(0));
5280        return;
5281    }
5282
5283    // General case.
5284    // We build a heap of squared euclidean distances between current and last pointers
5285    // associated with the current and last pointer indices.  Then, we find the best
5286    // match (by distance) for each current pointer.
5287    // The pointers must have the same tool type but it is possible for them to
5288    // transition from hovering to touching or vice-versa while retaining the same id.
5289    PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
5290
5291    uint32_t heapSize = 0;
5292    for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
5293            currentPointerIndex++) {
5294        for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
5295                lastPointerIndex++) {
5296            const RawPointerData::Pointer& currentPointer =
5297                    mCurrentRawPointerData.pointers[currentPointerIndex];
5298            const RawPointerData::Pointer& lastPointer =
5299                    mLastRawPointerData.pointers[lastPointerIndex];
5300            if (currentPointer.toolType == lastPointer.toolType) {
5301                int64_t deltaX = currentPointer.x - lastPointer.x;
5302                int64_t deltaY = currentPointer.y - lastPointer.y;
5303
5304                uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
5305
5306                // Insert new element into the heap (sift up).
5307                heap[heapSize].currentPointerIndex = currentPointerIndex;
5308                heap[heapSize].lastPointerIndex = lastPointerIndex;
5309                heap[heapSize].distance = distance;
5310                heapSize += 1;
5311            }
5312        }
5313    }
5314
5315    // Heapify
5316    for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
5317        startIndex -= 1;
5318        for (uint32_t parentIndex = startIndex; ;) {
5319            uint32_t childIndex = parentIndex * 2 + 1;
5320            if (childIndex >= heapSize) {
5321                break;
5322            }
5323
5324            if (childIndex + 1 < heapSize
5325                    && heap[childIndex + 1].distance < heap[childIndex].distance) {
5326                childIndex += 1;
5327            }
5328
5329            if (heap[parentIndex].distance <= heap[childIndex].distance) {
5330                break;
5331            }
5332
5333            swap(heap[parentIndex], heap[childIndex]);
5334            parentIndex = childIndex;
5335        }
5336    }
5337
5338#if DEBUG_POINTER_ASSIGNMENT
5339    LOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
5340    for (size_t i = 0; i < heapSize; i++) {
5341        LOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
5342                i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
5343                heap[i].distance);
5344    }
5345#endif
5346
5347    // Pull matches out by increasing order of distance.
5348    // To avoid reassigning pointers that have already been matched, the loop keeps track
5349    // of which last and current pointers have been matched using the matchedXXXBits variables.
5350    // It also tracks the used pointer id bits.
5351    BitSet32 matchedLastBits(0);
5352    BitSet32 matchedCurrentBits(0);
5353    BitSet32 usedIdBits(0);
5354    bool first = true;
5355    for (uint32_t i = min(currentPointerCount, lastPointerCount); heapSize > 0 && i > 0; i--) {
5356        while (heapSize > 0) {
5357            if (first) {
5358                // The first time through the loop, we just consume the root element of
5359                // the heap (the one with smallest distance).
5360                first = false;
5361            } else {
5362                // Previous iterations consumed the root element of the heap.
5363                // Pop root element off of the heap (sift down).
5364                heap[0] = heap[heapSize];
5365                for (uint32_t parentIndex = 0; ;) {
5366                    uint32_t childIndex = parentIndex * 2 + 1;
5367                    if (childIndex >= heapSize) {
5368                        break;
5369                    }
5370
5371                    if (childIndex + 1 < heapSize
5372                            && heap[childIndex + 1].distance < heap[childIndex].distance) {
5373                        childIndex += 1;
5374                    }
5375
5376                    if (heap[parentIndex].distance <= heap[childIndex].distance) {
5377                        break;
5378                    }
5379
5380                    swap(heap[parentIndex], heap[childIndex]);
5381                    parentIndex = childIndex;
5382                }
5383
5384#if DEBUG_POINTER_ASSIGNMENT
5385                LOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
5386                for (size_t i = 0; i < heapSize; i++) {
5387                    LOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
5388                            i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
5389                            heap[i].distance);
5390                }
5391#endif
5392            }
5393
5394            heapSize -= 1;
5395
5396            uint32_t currentPointerIndex = heap[0].currentPointerIndex;
5397            if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
5398
5399            uint32_t lastPointerIndex = heap[0].lastPointerIndex;
5400            if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
5401
5402            matchedCurrentBits.markBit(currentPointerIndex);
5403            matchedLastBits.markBit(lastPointerIndex);
5404
5405            uint32_t id = mLastRawPointerData.pointers[lastPointerIndex].id;
5406            mCurrentRawPointerData.pointers[currentPointerIndex].id = id;
5407            mCurrentRawPointerData.idToIndex[id] = currentPointerIndex;
5408            mCurrentRawPointerData.markIdBit(id,
5409                    mCurrentRawPointerData.isHovering(currentPointerIndex));
5410            usedIdBits.markBit(id);
5411
5412#if DEBUG_POINTER_ASSIGNMENT
5413            LOGD("assignPointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
5414                    lastPointerIndex, currentPointerIndex, id, heap[0].distance);
5415#endif
5416            break;
5417        }
5418    }
5419
5420    // Assign fresh ids to pointers that were not matched in the process.
5421    for (uint32_t i = currentPointerCount - matchedCurrentBits.count(); i != 0; i--) {
5422        uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit();
5423        uint32_t id = usedIdBits.markFirstUnmarkedBit();
5424
5425        mCurrentRawPointerData.pointers[currentPointerIndex].id = id;
5426        mCurrentRawPointerData.idToIndex[id] = currentPointerIndex;
5427        mCurrentRawPointerData.markIdBit(id,
5428                mCurrentRawPointerData.isHovering(currentPointerIndex));
5429
5430#if DEBUG_POINTER_ASSIGNMENT
5431        LOGD("assignPointerIds - assigned: cur=%d, id=%d",
5432                currentPointerIndex, id);
5433#endif
5434    }
5435}
5436
5437int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
5438    if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) {
5439        return AKEY_STATE_VIRTUAL;
5440    }
5441
5442    size_t numVirtualKeys = mVirtualKeys.size();
5443    for (size_t i = 0; i < numVirtualKeys; i++) {
5444        const VirtualKey& virtualKey = mVirtualKeys[i];
5445        if (virtualKey.keyCode == keyCode) {
5446            return AKEY_STATE_UP;
5447        }
5448    }
5449
5450    return AKEY_STATE_UNKNOWN;
5451}
5452
5453int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
5454    if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) {
5455        return AKEY_STATE_VIRTUAL;
5456    }
5457
5458    size_t numVirtualKeys = mVirtualKeys.size();
5459    for (size_t i = 0; i < numVirtualKeys; i++) {
5460        const VirtualKey& virtualKey = mVirtualKeys[i];
5461        if (virtualKey.scanCode == scanCode) {
5462            return AKEY_STATE_UP;
5463        }
5464    }
5465
5466    return AKEY_STATE_UNKNOWN;
5467}
5468
5469bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
5470        const int32_t* keyCodes, uint8_t* outFlags) {
5471    size_t numVirtualKeys = mVirtualKeys.size();
5472    for (size_t i = 0; i < numVirtualKeys; i++) {
5473        const VirtualKey& virtualKey = mVirtualKeys[i];
5474
5475        for (size_t i = 0; i < numCodes; i++) {
5476            if (virtualKey.keyCode == keyCodes[i]) {
5477                outFlags[i] = 1;
5478            }
5479        }
5480    }
5481
5482    return true;
5483}
5484
5485
5486// --- SingleTouchInputMapper ---
5487
5488SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
5489        TouchInputMapper(device) {
5490}
5491
5492SingleTouchInputMapper::~SingleTouchInputMapper() {
5493}
5494
5495void SingleTouchInputMapper::reset(nsecs_t when) {
5496    mSingleTouchMotionAccumulator.reset(getDevice());
5497
5498    TouchInputMapper::reset(when);
5499}
5500
5501void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
5502    TouchInputMapper::process(rawEvent);
5503
5504    mSingleTouchMotionAccumulator.process(rawEvent);
5505}
5506
5507void SingleTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) {
5508    if (mTouchButtonAccumulator.isToolActive()) {
5509        mCurrentRawPointerData.pointerCount = 1;
5510        mCurrentRawPointerData.idToIndex[0] = 0;
5511
5512        bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
5513                && (mTouchButtonAccumulator.isHovering()
5514                        || (mRawPointerAxes.pressure.valid
5515                                && mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0));
5516        mCurrentRawPointerData.markIdBit(0, isHovering);
5517
5518        RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[0];
5519        outPointer.id = 0;
5520        outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
5521        outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
5522        outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
5523        outPointer.touchMajor = 0;
5524        outPointer.touchMinor = 0;
5525        outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
5526        outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
5527        outPointer.orientation = 0;
5528        outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
5529        outPointer.tiltX = mSingleTouchMotionAccumulator.getAbsoluteTiltX();
5530        outPointer.tiltY = mSingleTouchMotionAccumulator.getAbsoluteTiltY();
5531        outPointer.toolType = mTouchButtonAccumulator.getToolType();
5532        if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
5533            outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
5534        }
5535        outPointer.isHovering = isHovering;
5536    }
5537}
5538
5539void SingleTouchInputMapper::configureRawPointerAxes() {
5540    TouchInputMapper::configureRawPointerAxes();
5541
5542    getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x);
5543    getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y);
5544    getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure);
5545    getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor);
5546    getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance);
5547    getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX);
5548    getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY);
5549}
5550
5551
5552// --- MultiTouchInputMapper ---
5553
5554MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
5555        TouchInputMapper(device) {
5556}
5557
5558MultiTouchInputMapper::~MultiTouchInputMapper() {
5559}
5560
5561void MultiTouchInputMapper::reset(nsecs_t when) {
5562    mMultiTouchMotionAccumulator.reset(getDevice());
5563
5564    mPointerIdBits.clear();
5565
5566    TouchInputMapper::reset(when);
5567}
5568
5569void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
5570    TouchInputMapper::process(rawEvent);
5571
5572    mMultiTouchMotionAccumulator.process(rawEvent);
5573}
5574
5575void MultiTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) {
5576    size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
5577    size_t outCount = 0;
5578    BitSet32 newPointerIdBits;
5579
5580    for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
5581        const MultiTouchMotionAccumulator::Slot* inSlot =
5582                mMultiTouchMotionAccumulator.getSlot(inIndex);
5583        if (!inSlot->isInUse()) {
5584            continue;
5585        }
5586
5587        if (outCount >= MAX_POINTERS) {
5588#if DEBUG_POINTERS
5589            LOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
5590                    "ignoring the rest.",
5591                    getDeviceName().string(), MAX_POINTERS);
5592#endif
5593            break; // too many fingers!
5594        }
5595
5596        RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[outCount];
5597        outPointer.x = inSlot->getX();
5598        outPointer.y = inSlot->getY();
5599        outPointer.pressure = inSlot->getPressure();
5600        outPointer.touchMajor = inSlot->getTouchMajor();
5601        outPointer.touchMinor = inSlot->getTouchMinor();
5602        outPointer.toolMajor = inSlot->getToolMajor();
5603        outPointer.toolMinor = inSlot->getToolMinor();
5604        outPointer.orientation = inSlot->getOrientation();
5605        outPointer.distance = inSlot->getDistance();
5606        outPointer.tiltX = 0;
5607        outPointer.tiltY = 0;
5608
5609        outPointer.toolType = inSlot->getToolType();
5610        if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
5611            outPointer.toolType = mTouchButtonAccumulator.getToolType();
5612            if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
5613                outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
5614            }
5615        }
5616
5617        bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
5618                && (mTouchButtonAccumulator.isHovering()
5619                        || (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
5620        outPointer.isHovering = isHovering;
5621
5622        // Assign pointer id using tracking id if available.
5623        if (*outHavePointerIds) {
5624            int32_t trackingId = inSlot->getTrackingId();
5625            int32_t id = -1;
5626            if (trackingId >= 0) {
5627                for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
5628                    uint32_t n = idBits.clearFirstMarkedBit();
5629                    if (mPointerTrackingIdMap[n] == trackingId) {
5630                        id = n;
5631                    }
5632                }
5633
5634                if (id < 0 && !mPointerIdBits.isFull()) {
5635                    id = mPointerIdBits.markFirstUnmarkedBit();
5636                    mPointerTrackingIdMap[id] = trackingId;
5637                }
5638            }
5639            if (id < 0) {
5640                *outHavePointerIds = false;
5641                mCurrentRawPointerData.clearIdBits();
5642                newPointerIdBits.clear();
5643            } else {
5644                outPointer.id = id;
5645                mCurrentRawPointerData.idToIndex[id] = outCount;
5646                mCurrentRawPointerData.markIdBit(id, isHovering);
5647                newPointerIdBits.markBit(id);
5648            }
5649        }
5650
5651        outCount += 1;
5652    }
5653
5654    mCurrentRawPointerData.pointerCount = outCount;
5655    mPointerIdBits = newPointerIdBits;
5656
5657    mMultiTouchMotionAccumulator.finishSync();
5658}
5659
5660void MultiTouchInputMapper::configureRawPointerAxes() {
5661    TouchInputMapper::configureRawPointerAxes();
5662
5663    getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x);
5664    getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y);
5665    getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor);
5666    getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor);
5667    getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor);
5668    getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor);
5669    getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation);
5670    getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure);
5671    getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance);
5672    getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId);
5673    getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot);
5674
5675    if (mRawPointerAxes.trackingId.valid
5676            && mRawPointerAxes.slot.valid
5677            && mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
5678        size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
5679        if (slotCount > MAX_SLOTS) {
5680            LOGW("MultiTouch Device %s reported %d slots but the framework "
5681                    "only supports a maximum of %d slots at this time.",
5682                    getDeviceName().string(), slotCount, MAX_SLOTS);
5683            slotCount = MAX_SLOTS;
5684        }
5685        mMultiTouchMotionAccumulator.configure(slotCount, true /*usingSlotsProtocol*/);
5686    } else {
5687        mMultiTouchMotionAccumulator.configure(MAX_POINTERS, false /*usingSlotsProtocol*/);
5688    }
5689}
5690
5691
5692// --- JoystickInputMapper ---
5693
5694JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
5695        InputMapper(device) {
5696}
5697
5698JoystickInputMapper::~JoystickInputMapper() {
5699}
5700
5701uint32_t JoystickInputMapper::getSources() {
5702    return AINPUT_SOURCE_JOYSTICK;
5703}
5704
5705void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
5706    InputMapper::populateDeviceInfo(info);
5707
5708    for (size_t i = 0; i < mAxes.size(); i++) {
5709        const Axis& axis = mAxes.valueAt(i);
5710        info->addMotionRange(axis.axisInfo.axis, AINPUT_SOURCE_JOYSTICK,
5711                axis.min, axis.max, axis.flat, axis.fuzz);
5712        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5713            info->addMotionRange(axis.axisInfo.highAxis, AINPUT_SOURCE_JOYSTICK,
5714                    axis.min, axis.max, axis.flat, axis.fuzz);
5715        }
5716    }
5717}
5718
5719void JoystickInputMapper::dump(String8& dump) {
5720    dump.append(INDENT2 "Joystick Input Mapper:\n");
5721
5722    dump.append(INDENT3 "Axes:\n");
5723    size_t numAxes = mAxes.size();
5724    for (size_t i = 0; i < numAxes; i++) {
5725        const Axis& axis = mAxes.valueAt(i);
5726        const char* label = getAxisLabel(axis.axisInfo.axis);
5727        if (label) {
5728            dump.appendFormat(INDENT4 "%s", label);
5729        } else {
5730            dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis);
5731        }
5732        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5733            label = getAxisLabel(axis.axisInfo.highAxis);
5734            if (label) {
5735                dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue);
5736            } else {
5737                dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis,
5738                        axis.axisInfo.splitValue);
5739            }
5740        } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
5741            dump.append(" (invert)");
5742        }
5743
5744        dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f\n",
5745                axis.min, axis.max, axis.flat, axis.fuzz);
5746        dump.appendFormat(INDENT4 "  scale=%0.5f, offset=%0.5f, "
5747                "highScale=%0.5f, highOffset=%0.5f\n",
5748                axis.scale, axis.offset, axis.highScale, axis.highOffset);
5749        dump.appendFormat(INDENT4 "  rawAxis=%d, rawMin=%d, rawMax=%d, "
5750                "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n",
5751                mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
5752                axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, axis.rawAxisInfo.resolution);
5753    }
5754}
5755
5756void JoystickInputMapper::configure(nsecs_t when,
5757        const InputReaderConfiguration* config, uint32_t changes) {
5758    InputMapper::configure(when, config, changes);
5759
5760    if (!changes) { // first time only
5761        // Collect all axes.
5762        for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
5763            if (!(getAbsAxisUsage(abs, getDevice()->getClasses())
5764                    & INPUT_DEVICE_CLASS_JOYSTICK)) {
5765                continue; // axis must be claimed by a different device
5766            }
5767
5768            RawAbsoluteAxisInfo rawAxisInfo;
5769            getAbsoluteAxisInfo(abs, &rawAxisInfo);
5770            if (rawAxisInfo.valid) {
5771                // Map axis.
5772                AxisInfo axisInfo;
5773                bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
5774                if (!explicitlyMapped) {
5775                    // Axis is not explicitly mapped, will choose a generic axis later.
5776                    axisInfo.mode = AxisInfo::MODE_NORMAL;
5777                    axisInfo.axis = -1;
5778                }
5779
5780                // Apply flat override.
5781                int32_t rawFlat = axisInfo.flatOverride < 0
5782                        ? rawAxisInfo.flat : axisInfo.flatOverride;
5783
5784                // Calculate scaling factors and limits.
5785                Axis axis;
5786                if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
5787                    float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
5788                    float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
5789                    axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5790                            scale, 0.0f, highScale, 0.0f,
5791                            0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
5792                } else if (isCenteredAxis(axisInfo.axis)) {
5793                    float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
5794                    float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
5795                    axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5796                            scale, offset, scale, offset,
5797                            -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
5798                } else {
5799                    float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
5800                    axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5801                            scale, 0.0f, scale, 0.0f,
5802                            0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
5803                }
5804
5805                // To eliminate noise while the joystick is at rest, filter out small variations
5806                // in axis values up front.
5807                axis.filter = axis.flat * 0.25f;
5808
5809                mAxes.add(abs, axis);
5810            }
5811        }
5812
5813        // If there are too many axes, start dropping them.
5814        // Prefer to keep explicitly mapped axes.
5815        if (mAxes.size() > PointerCoords::MAX_AXES) {
5816            LOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
5817                    getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
5818            pruneAxes(true);
5819            pruneAxes(false);
5820        }
5821
5822        // Assign generic axis ids to remaining axes.
5823        int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
5824        size_t numAxes = mAxes.size();
5825        for (size_t i = 0; i < numAxes; i++) {
5826            Axis& axis = mAxes.editValueAt(i);
5827            if (axis.axisInfo.axis < 0) {
5828                while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
5829                        && haveAxis(nextGenericAxisId)) {
5830                    nextGenericAxisId += 1;
5831                }
5832
5833                if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
5834                    axis.axisInfo.axis = nextGenericAxisId;
5835                    nextGenericAxisId += 1;
5836                } else {
5837                    LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
5838                            "have already been assigned to other axes.",
5839                            getDeviceName().string(), mAxes.keyAt(i));
5840                    mAxes.removeItemsAt(i--);
5841                    numAxes -= 1;
5842                }
5843            }
5844        }
5845    }
5846}
5847
5848bool JoystickInputMapper::haveAxis(int32_t axisId) {
5849    size_t numAxes = mAxes.size();
5850    for (size_t i = 0; i < numAxes; i++) {
5851        const Axis& axis = mAxes.valueAt(i);
5852        if (axis.axisInfo.axis == axisId
5853                || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
5854                        && axis.axisInfo.highAxis == axisId)) {
5855            return true;
5856        }
5857    }
5858    return false;
5859}
5860
5861void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
5862    size_t i = mAxes.size();
5863    while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
5864        if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
5865            continue;
5866        }
5867        LOGI("Discarding joystick '%s' axis %d because there are too many axes.",
5868                getDeviceName().string(), mAxes.keyAt(i));
5869        mAxes.removeItemsAt(i);
5870    }
5871}
5872
5873bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
5874    switch (axis) {
5875    case AMOTION_EVENT_AXIS_X:
5876    case AMOTION_EVENT_AXIS_Y:
5877    case AMOTION_EVENT_AXIS_Z:
5878    case AMOTION_EVENT_AXIS_RX:
5879    case AMOTION_EVENT_AXIS_RY:
5880    case AMOTION_EVENT_AXIS_RZ:
5881    case AMOTION_EVENT_AXIS_HAT_X:
5882    case AMOTION_EVENT_AXIS_HAT_Y:
5883    case AMOTION_EVENT_AXIS_ORIENTATION:
5884    case AMOTION_EVENT_AXIS_RUDDER:
5885    case AMOTION_EVENT_AXIS_WHEEL:
5886        return true;
5887    default:
5888        return false;
5889    }
5890}
5891
5892void JoystickInputMapper::reset(nsecs_t when) {
5893    // Recenter all axes.
5894    size_t numAxes = mAxes.size();
5895    for (size_t i = 0; i < numAxes; i++) {
5896        Axis& axis = mAxes.editValueAt(i);
5897        axis.resetValue();
5898    }
5899
5900    InputMapper::reset(when);
5901}
5902
5903void JoystickInputMapper::process(const RawEvent* rawEvent) {
5904    switch (rawEvent->type) {
5905    case EV_ABS: {
5906        ssize_t index = mAxes.indexOfKey(rawEvent->scanCode);
5907        if (index >= 0) {
5908            Axis& axis = mAxes.editValueAt(index);
5909            float newValue, highNewValue;
5910            switch (axis.axisInfo.mode) {
5911            case AxisInfo::MODE_INVERT:
5912                newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
5913                        * axis.scale + axis.offset;
5914                highNewValue = 0.0f;
5915                break;
5916            case AxisInfo::MODE_SPLIT:
5917                if (rawEvent->value < axis.axisInfo.splitValue) {
5918                    newValue = (axis.axisInfo.splitValue - rawEvent->value)
5919                            * axis.scale + axis.offset;
5920                    highNewValue = 0.0f;
5921                } else if (rawEvent->value > axis.axisInfo.splitValue) {
5922                    newValue = 0.0f;
5923                    highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
5924                            * axis.highScale + axis.highOffset;
5925                } else {
5926                    newValue = 0.0f;
5927                    highNewValue = 0.0f;
5928                }
5929                break;
5930            default:
5931                newValue = rawEvent->value * axis.scale + axis.offset;
5932                highNewValue = 0.0f;
5933                break;
5934            }
5935            axis.newValue = newValue;
5936            axis.highNewValue = highNewValue;
5937        }
5938        break;
5939    }
5940
5941    case EV_SYN:
5942        switch (rawEvent->scanCode) {
5943        case SYN_REPORT:
5944            sync(rawEvent->when, false /*force*/);
5945            break;
5946        }
5947        break;
5948    }
5949}
5950
5951void JoystickInputMapper::sync(nsecs_t when, bool force) {
5952    if (!filterAxes(force)) {
5953        return;
5954    }
5955
5956    int32_t metaState = mContext->getGlobalMetaState();
5957    int32_t buttonState = 0;
5958
5959    PointerProperties pointerProperties;
5960    pointerProperties.clear();
5961    pointerProperties.id = 0;
5962    pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
5963
5964    PointerCoords pointerCoords;
5965    pointerCoords.clear();
5966
5967    size_t numAxes = mAxes.size();
5968    for (size_t i = 0; i < numAxes; i++) {
5969        const Axis& axis = mAxes.valueAt(i);
5970        pointerCoords.setAxisValue(axis.axisInfo.axis, axis.currentValue);
5971        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5972            pointerCoords.setAxisValue(axis.axisInfo.highAxis, axis.highCurrentValue);
5973        }
5974    }
5975
5976    // Moving a joystick axis should not wake the devide because joysticks can
5977    // be fairly noisy even when not in use.  On the other hand, pushing a gamepad
5978    // button will likely wake the device.
5979    // TODO: Use the input device configuration to control this behavior more finely.
5980    uint32_t policyFlags = 0;
5981
5982    NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
5983            AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
5984            1, &pointerProperties, &pointerCoords, 0, 0, 0);
5985    getListener()->notifyMotion(&args);
5986}
5987
5988bool JoystickInputMapper::filterAxes(bool force) {
5989    bool atLeastOneSignificantChange = force;
5990    size_t numAxes = mAxes.size();
5991    for (size_t i = 0; i < numAxes; i++) {
5992        Axis& axis = mAxes.editValueAt(i);
5993        if (force || hasValueChangedSignificantly(axis.filter,
5994                axis.newValue, axis.currentValue, axis.min, axis.max)) {
5995            axis.currentValue = axis.newValue;
5996            atLeastOneSignificantChange = true;
5997        }
5998        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5999            if (force || hasValueChangedSignificantly(axis.filter,
6000                    axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
6001                axis.highCurrentValue = axis.highNewValue;
6002                atLeastOneSignificantChange = true;
6003            }
6004        }
6005    }
6006    return atLeastOneSignificantChange;
6007}
6008
6009bool JoystickInputMapper::hasValueChangedSignificantly(
6010        float filter, float newValue, float currentValue, float min, float max) {
6011    if (newValue != currentValue) {
6012        // Filter out small changes in value unless the value is converging on the axis
6013        // bounds or center point.  This is intended to reduce the amount of information
6014        // sent to applications by particularly noisy joysticks (such as PS3).
6015        if (fabs(newValue - currentValue) > filter
6016                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
6017                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
6018                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
6019            return true;
6020        }
6021    }
6022    return false;
6023}
6024
6025bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
6026        float filter, float newValue, float currentValue, float thresholdValue) {
6027    float newDistance = fabs(newValue - thresholdValue);
6028    if (newDistance < filter) {
6029        float oldDistance = fabs(currentValue - thresholdValue);
6030        if (newDistance < oldDistance) {
6031            return true;
6032        }
6033    }
6034    return false;
6035}
6036
6037} // namespace android
6038