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