InputReader.cpp revision 9e8e40cb5f8aeb0702002eee60d1ce394bf699ee
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#include "InputReader.h"
37
38#include <cutils/log.h>
39#include <ui/Keyboard.h>
40#include <ui/VirtualKeyMap.h>
41
42#include <stddef.h>
43#include <stdlib.h>
44#include <unistd.h>
45#include <errno.h>
46#include <limits.h>
47#include <math.h>
48
49#define INDENT "  "
50#define INDENT2 "    "
51#define INDENT3 "      "
52#define INDENT4 "        "
53
54namespace android {
55
56// --- Static Functions ---
57
58template<typename T>
59inline static T abs(const T& value) {
60    return value < 0 ? - value : value;
61}
62
63template<typename T>
64inline static T min(const T& a, const T& b) {
65    return a < b ? a : b;
66}
67
68template<typename T>
69inline static void swap(T& a, T& b) {
70    T temp = a;
71    a = b;
72    b = temp;
73}
74
75inline static float avg(float x, float y) {
76    return (x + y) / 2;
77}
78
79inline static float pythag(float x, float y) {
80    return sqrtf(x * x + y * y);
81}
82
83inline static int32_t signExtendNybble(int32_t value) {
84    return value >= 8 ? value - 16 : value;
85}
86
87static inline const char* toString(bool value) {
88    return value ? "true" : "false";
89}
90
91static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
92        const int32_t map[][4], size_t mapSize) {
93    if (orientation != DISPLAY_ORIENTATION_0) {
94        for (size_t i = 0; i < mapSize; i++) {
95            if (value == map[i][0]) {
96                return map[i][orientation];
97            }
98        }
99    }
100    return value;
101}
102
103static const int32_t keyCodeRotationMap[][4] = {
104        // key codes enumerated counter-clockwise with the original (unrotated) key first
105        // no rotation,        90 degree rotation,  180 degree rotation, 270 degree rotation
106        { AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT },
107        { AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN },
108        { AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT },
109        { AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP },
110};
111static const size_t keyCodeRotationMapSize =
112        sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
113
114int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
115    return rotateValueUsingRotationMap(keyCode, orientation,
116            keyCodeRotationMap, keyCodeRotationMapSize);
117}
118
119static const int32_t edgeFlagRotationMap[][4] = {
120        // edge flags enumerated counter-clockwise with the original (unrotated) edge flag first
121        // no rotation,        90 degree rotation,  180 degree rotation, 270 degree rotation
122        { AMOTION_EVENT_EDGE_FLAG_BOTTOM,   AMOTION_EVENT_EDGE_FLAG_RIGHT,
123                AMOTION_EVENT_EDGE_FLAG_TOP,     AMOTION_EVENT_EDGE_FLAG_LEFT },
124        { AMOTION_EVENT_EDGE_FLAG_RIGHT,  AMOTION_EVENT_EDGE_FLAG_TOP,
125                AMOTION_EVENT_EDGE_FLAG_LEFT,   AMOTION_EVENT_EDGE_FLAG_BOTTOM },
126        { AMOTION_EVENT_EDGE_FLAG_TOP,     AMOTION_EVENT_EDGE_FLAG_LEFT,
127                AMOTION_EVENT_EDGE_FLAG_BOTTOM,   AMOTION_EVENT_EDGE_FLAG_RIGHT },
128        { AMOTION_EVENT_EDGE_FLAG_LEFT,   AMOTION_EVENT_EDGE_FLAG_BOTTOM,
129                AMOTION_EVENT_EDGE_FLAG_RIGHT,  AMOTION_EVENT_EDGE_FLAG_TOP },
130};
131static const size_t edgeFlagRotationMapSize =
132        sizeof(edgeFlagRotationMap) / sizeof(edgeFlagRotationMap[0]);
133
134static int32_t rotateEdgeFlag(int32_t edgeFlag, int32_t orientation) {
135    return rotateValueUsingRotationMap(edgeFlag, orientation,
136            edgeFlagRotationMap, edgeFlagRotationMapSize);
137}
138
139static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
140    return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
141}
142
143
144// --- InputReader ---
145
146InputReader::InputReader(const sp<EventHubInterface>& eventHub,
147        const sp<InputReaderPolicyInterface>& policy,
148        const sp<InputDispatcherInterface>& dispatcher) :
149        mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
150        mGlobalMetaState(0), mDisableVirtualKeysTimeout(-1) {
151    configureExcludedDevices();
152    updateGlobalMetaState();
153    updateInputConfiguration();
154}
155
156InputReader::~InputReader() {
157    for (size_t i = 0; i < mDevices.size(); i++) {
158        delete mDevices.valueAt(i);
159    }
160}
161
162void InputReader::loopOnce() {
163    RawEvent rawEvent;
164    mEventHub->getEvent(& rawEvent);
165
166#if DEBUG_RAW_EVENTS
167    LOGD("Input event: device=%d type=0x%x scancode=%d keycode=%d value=%d",
168            rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
169            rawEvent.value);
170#endif
171
172    process(& rawEvent);
173}
174
175void InputReader::process(const RawEvent* rawEvent) {
176    switch (rawEvent->type) {
177    case EventHubInterface::DEVICE_ADDED:
178        addDevice(rawEvent->deviceId);
179        break;
180
181    case EventHubInterface::DEVICE_REMOVED:
182        removeDevice(rawEvent->deviceId);
183        break;
184
185    case EventHubInterface::FINISHED_DEVICE_SCAN:
186        handleConfigurationChanged(rawEvent->when);
187        break;
188
189    default:
190        consumeEvent(rawEvent);
191        break;
192    }
193}
194
195void InputReader::addDevice(int32_t deviceId) {
196    String8 name = mEventHub->getDeviceName(deviceId);
197    uint32_t classes = mEventHub->getDeviceClasses(deviceId);
198
199    InputDevice* device = createDevice(deviceId, name, classes);
200    device->configure();
201
202    if (device->isIgnored()) {
203        LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
204    } else {
205        LOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
206                device->getSources());
207    }
208
209    bool added = false;
210    { // acquire device registry writer lock
211        RWLock::AutoWLock _wl(mDeviceRegistryLock);
212
213        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
214        if (deviceIndex < 0) {
215            mDevices.add(deviceId, device);
216            added = true;
217        }
218    } // release device registry writer lock
219
220    if (! added) {
221        LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
222        delete device;
223        return;
224    }
225}
226
227void InputReader::removeDevice(int32_t deviceId) {
228    bool removed = false;
229    InputDevice* device = NULL;
230    { // acquire device registry writer lock
231        RWLock::AutoWLock _wl(mDeviceRegistryLock);
232
233        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
234        if (deviceIndex >= 0) {
235            device = mDevices.valueAt(deviceIndex);
236            mDevices.removeItemsAt(deviceIndex, 1);
237            removed = true;
238        }
239    } // release device registry writer lock
240
241    if (! removed) {
242        LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
243        return;
244    }
245
246    if (device->isIgnored()) {
247        LOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
248                device->getId(), device->getName().string());
249    } else {
250        LOGI("Device removed: id=%d, name='%s', sources=0x%08x",
251                device->getId(), device->getName().string(), device->getSources());
252    }
253
254    device->reset();
255
256    delete device;
257}
258
259InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
260    InputDevice* device = new InputDevice(this, deviceId, name);
261
262    // External devices.
263    if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
264        device->setExternal(true);
265    }
266
267    // Switch-like devices.
268    if (classes & INPUT_DEVICE_CLASS_SWITCH) {
269        device->addMapper(new SwitchInputMapper(device));
270    }
271
272    // Keyboard-like devices.
273    uint32_t keyboardSources = 0;
274    int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
275    if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
276        keyboardSources |= AINPUT_SOURCE_KEYBOARD;
277    }
278    if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
279        keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
280    }
281    if (classes & INPUT_DEVICE_CLASS_DPAD) {
282        keyboardSources |= AINPUT_SOURCE_DPAD;
283    }
284    if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
285        keyboardSources |= AINPUT_SOURCE_GAMEPAD;
286    }
287
288    if (keyboardSources != 0) {
289        device->addMapper(new KeyboardInputMapper(device, keyboardSources, keyboardType));
290    }
291
292    // Cursor-like devices.
293    if (classes & INPUT_DEVICE_CLASS_CURSOR) {
294        device->addMapper(new CursorInputMapper(device));
295    }
296
297    // Touchscreens and touchpad devices.
298    if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
299        device->addMapper(new MultiTouchInputMapper(device));
300    } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
301        device->addMapper(new SingleTouchInputMapper(device));
302    }
303
304    // Joystick-like devices.
305    if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
306        device->addMapper(new JoystickInputMapper(device));
307    }
308
309    return device;
310}
311
312void InputReader::consumeEvent(const RawEvent* rawEvent) {
313    int32_t deviceId = rawEvent->deviceId;
314
315    { // acquire device registry reader lock
316        RWLock::AutoRLock _rl(mDeviceRegistryLock);
317
318        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
319        if (deviceIndex < 0) {
320            LOGW("Discarding event for unknown deviceId %d.", deviceId);
321            return;
322        }
323
324        InputDevice* device = mDevices.valueAt(deviceIndex);
325        if (device->isIgnored()) {
326            //LOGD("Discarding event for ignored deviceId %d.", deviceId);
327            return;
328        }
329
330        device->process(rawEvent);
331    } // release device registry reader lock
332}
333
334void InputReader::handleConfigurationChanged(nsecs_t when) {
335    // Reset global meta state because it depends on the list of all configured devices.
336    updateGlobalMetaState();
337
338    // Update input configuration.
339    updateInputConfiguration();
340
341    // Enqueue configuration changed.
342    mDispatcher->notifyConfigurationChanged(when);
343}
344
345void InputReader::configureExcludedDevices() {
346    Vector<String8> excludedDeviceNames;
347    mPolicy->getExcludedDeviceNames(excludedDeviceNames);
348
349    for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
350        mEventHub->addExcludedDevice(excludedDeviceNames[i]);
351    }
352}
353
354void InputReader::updateGlobalMetaState() {
355    { // acquire state lock
356        AutoMutex _l(mStateLock);
357
358        mGlobalMetaState = 0;
359
360        { // acquire device registry reader lock
361            RWLock::AutoRLock _rl(mDeviceRegistryLock);
362
363            for (size_t i = 0; i < mDevices.size(); i++) {
364                InputDevice* device = mDevices.valueAt(i);
365                mGlobalMetaState |= device->getMetaState();
366            }
367        } // release device registry reader lock
368    } // release state lock
369}
370
371int32_t InputReader::getGlobalMetaState() {
372    { // acquire state lock
373        AutoMutex _l(mStateLock);
374
375        return mGlobalMetaState;
376    } // release state lock
377}
378
379void InputReader::updateInputConfiguration() {
380    { // acquire state lock
381        AutoMutex _l(mStateLock);
382
383        int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
384        int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
385        int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
386        { // acquire device registry reader lock
387            RWLock::AutoRLock _rl(mDeviceRegistryLock);
388
389            InputDeviceInfo deviceInfo;
390            for (size_t i = 0; i < mDevices.size(); i++) {
391                InputDevice* device = mDevices.valueAt(i);
392                device->getDeviceInfo(& deviceInfo);
393                uint32_t sources = deviceInfo.getSources();
394
395                if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
396                    touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
397                }
398                if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
399                    navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
400                } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
401                    navigationConfig = InputConfiguration::NAVIGATION_DPAD;
402                }
403                if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
404                    keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
405                }
406            }
407        } // release device registry reader lock
408
409        mInputConfiguration.touchScreen = touchScreenConfig;
410        mInputConfiguration.keyboard = keyboardConfig;
411        mInputConfiguration.navigation = navigationConfig;
412    } // release state lock
413}
414
415void InputReader::disableVirtualKeysUntil(nsecs_t time) {
416    mDisableVirtualKeysTimeout = time;
417}
418
419bool InputReader::shouldDropVirtualKey(nsecs_t now,
420        InputDevice* device, int32_t keyCode, int32_t scanCode) {
421    if (now < mDisableVirtualKeysTimeout) {
422        LOGI("Dropping virtual key from device %s because virtual keys are "
423                "temporarily disabled for the next %0.3fms.  keyCode=%d, scanCode=%d",
424                device->getName().string(),
425                (mDisableVirtualKeysTimeout - now) * 0.000001,
426                keyCode, scanCode);
427        return true;
428    } else {
429        return false;
430    }
431}
432
433void InputReader::fadePointer() {
434    { // acquire device registry reader lock
435        RWLock::AutoRLock _rl(mDeviceRegistryLock);
436
437        for (size_t i = 0; i < mDevices.size(); i++) {
438            InputDevice* device = mDevices.valueAt(i);
439            device->fadePointer();
440        }
441    } // release device registry reader lock
442}
443
444void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
445    { // acquire state lock
446        AutoMutex _l(mStateLock);
447
448        *outConfiguration = mInputConfiguration;
449    } // release state lock
450}
451
452status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
453    { // acquire device registry reader lock
454        RWLock::AutoRLock _rl(mDeviceRegistryLock);
455
456        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
457        if (deviceIndex < 0) {
458            return NAME_NOT_FOUND;
459        }
460
461        InputDevice* device = mDevices.valueAt(deviceIndex);
462        if (device->isIgnored()) {
463            return NAME_NOT_FOUND;
464        }
465
466        device->getDeviceInfo(outDeviceInfo);
467        return OK;
468    } // release device registy reader lock
469}
470
471void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
472    outDeviceIds.clear();
473
474    { // acquire device registry reader lock
475        RWLock::AutoRLock _rl(mDeviceRegistryLock);
476
477        size_t numDevices = mDevices.size();
478        for (size_t i = 0; i < numDevices; i++) {
479            InputDevice* device = mDevices.valueAt(i);
480            if (! device->isIgnored()) {
481                outDeviceIds.add(device->getId());
482            }
483        }
484    } // release device registy reader lock
485}
486
487int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
488        int32_t keyCode) {
489    return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
490}
491
492int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
493        int32_t scanCode) {
494    return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
495}
496
497int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
498    return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
499}
500
501int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
502        GetStateFunc getStateFunc) {
503    { // acquire device registry reader lock
504        RWLock::AutoRLock _rl(mDeviceRegistryLock);
505
506        int32_t result = AKEY_STATE_UNKNOWN;
507        if (deviceId >= 0) {
508            ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
509            if (deviceIndex >= 0) {
510                InputDevice* device = mDevices.valueAt(deviceIndex);
511                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
512                    result = (device->*getStateFunc)(sourceMask, code);
513                }
514            }
515        } else {
516            size_t numDevices = mDevices.size();
517            for (size_t i = 0; i < numDevices; i++) {
518                InputDevice* device = mDevices.valueAt(i);
519                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
520                    result = (device->*getStateFunc)(sourceMask, code);
521                    if (result >= AKEY_STATE_DOWN) {
522                        return result;
523                    }
524                }
525            }
526        }
527        return result;
528    } // release device registy reader lock
529}
530
531bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
532        size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
533    memset(outFlags, 0, numCodes);
534    return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
535}
536
537bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
538        const int32_t* keyCodes, uint8_t* outFlags) {
539    { // acquire device registry reader lock
540        RWLock::AutoRLock _rl(mDeviceRegistryLock);
541        bool result = false;
542        if (deviceId >= 0) {
543            ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
544            if (deviceIndex >= 0) {
545                InputDevice* device = mDevices.valueAt(deviceIndex);
546                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
547                    result = device->markSupportedKeyCodes(sourceMask,
548                            numCodes, keyCodes, outFlags);
549                }
550            }
551        } else {
552            size_t numDevices = mDevices.size();
553            for (size_t i = 0; i < numDevices; i++) {
554                InputDevice* device = mDevices.valueAt(i);
555                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
556                    result |= device->markSupportedKeyCodes(sourceMask,
557                            numCodes, keyCodes, outFlags);
558                }
559            }
560        }
561        return result;
562    } // release device registy reader lock
563}
564
565void InputReader::dump(String8& dump) {
566    mEventHub->dump(dump);
567    dump.append("\n");
568
569    dump.append("Input Reader State:\n");
570
571    { // acquire device registry reader lock
572        RWLock::AutoRLock _rl(mDeviceRegistryLock);
573
574        for (size_t i = 0; i < mDevices.size(); i++) {
575            mDevices.valueAt(i)->dump(dump);
576        }
577    } // release device registy reader lock
578}
579
580
581// --- InputReaderThread ---
582
583InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
584        Thread(/*canCallJava*/ true), mReader(reader) {
585}
586
587InputReaderThread::~InputReaderThread() {
588}
589
590bool InputReaderThread::threadLoop() {
591    mReader->loopOnce();
592    return true;
593}
594
595
596// --- InputDevice ---
597
598InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
599        mContext(context), mId(id), mName(name), mSources(0), mIsExternal(false) {
600}
601
602InputDevice::~InputDevice() {
603    size_t numMappers = mMappers.size();
604    for (size_t i = 0; i < numMappers; i++) {
605        delete mMappers[i];
606    }
607    mMappers.clear();
608}
609
610void InputDevice::dump(String8& dump) {
611    InputDeviceInfo deviceInfo;
612    getDeviceInfo(& deviceInfo);
613
614    dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
615            deviceInfo.getName().string());
616    dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
617    dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
618    dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
619
620    const KeyedVector<int32_t, InputDeviceInfo::MotionRange> ranges = deviceInfo.getMotionRanges();
621    if (!ranges.isEmpty()) {
622        dump.append(INDENT2 "Motion Ranges:\n");
623        for (size_t i = 0; i < ranges.size(); i++) {
624            int32_t axis = ranges.keyAt(i);
625            const char* label = getAxisLabel(axis);
626            char name[32];
627            if (label) {
628                strncpy(name, label, sizeof(name));
629                name[sizeof(name) - 1] = '\0';
630            } else {
631                snprintf(name, sizeof(name), "%d", axis);
632            }
633            const InputDeviceInfo::MotionRange& range = ranges.valueAt(i);
634            dump.appendFormat(INDENT3 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
635                    name, range.min, range.max, range.flat, range.fuzz);
636        }
637    }
638
639    size_t numMappers = mMappers.size();
640    for (size_t i = 0; i < numMappers; i++) {
641        InputMapper* mapper = mMappers[i];
642        mapper->dump(dump);
643    }
644}
645
646void InputDevice::addMapper(InputMapper* mapper) {
647    mMappers.add(mapper);
648}
649
650void InputDevice::configure() {
651    if (! isIgnored()) {
652        mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
653    }
654
655    mSources = 0;
656
657    size_t numMappers = mMappers.size();
658    for (size_t i = 0; i < numMappers; i++) {
659        InputMapper* mapper = mMappers[i];
660        mapper->configure();
661        mSources |= mapper->getSources();
662    }
663}
664
665void InputDevice::reset() {
666    size_t numMappers = mMappers.size();
667    for (size_t i = 0; i < numMappers; i++) {
668        InputMapper* mapper = mMappers[i];
669        mapper->reset();
670    }
671}
672
673void InputDevice::process(const RawEvent* rawEvent) {
674    size_t numMappers = mMappers.size();
675    for (size_t i = 0; i < numMappers; i++) {
676        InputMapper* mapper = mMappers[i];
677        mapper->process(rawEvent);
678    }
679}
680
681void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
682    outDeviceInfo->initialize(mId, mName);
683
684    size_t numMappers = mMappers.size();
685    for (size_t i = 0; i < numMappers; i++) {
686        InputMapper* mapper = mMappers[i];
687        mapper->populateDeviceInfo(outDeviceInfo);
688    }
689}
690
691int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
692    return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
693}
694
695int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
696    return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
697}
698
699int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
700    return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
701}
702
703int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
704    int32_t result = AKEY_STATE_UNKNOWN;
705    size_t numMappers = mMappers.size();
706    for (size_t i = 0; i < numMappers; i++) {
707        InputMapper* mapper = mMappers[i];
708        if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
709            result = (mapper->*getStateFunc)(sourceMask, code);
710            if (result >= AKEY_STATE_DOWN) {
711                return result;
712            }
713        }
714    }
715    return result;
716}
717
718bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
719        const int32_t* keyCodes, uint8_t* outFlags) {
720    bool result = false;
721    size_t numMappers = mMappers.size();
722    for (size_t i = 0; i < numMappers; i++) {
723        InputMapper* mapper = mMappers[i];
724        if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
725            result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
726        }
727    }
728    return result;
729}
730
731int32_t InputDevice::getMetaState() {
732    int32_t result = 0;
733    size_t numMappers = mMappers.size();
734    for (size_t i = 0; i < numMappers; i++) {
735        InputMapper* mapper = mMappers[i];
736        result |= mapper->getMetaState();
737    }
738    return result;
739}
740
741void InputDevice::fadePointer() {
742    size_t numMappers = mMappers.size();
743    for (size_t i = 0; i < numMappers; i++) {
744        InputMapper* mapper = mMappers[i];
745        mapper->fadePointer();
746    }
747}
748
749
750// --- InputMapper ---
751
752InputMapper::InputMapper(InputDevice* device) :
753        mDevice(device), mContext(device->getContext()) {
754}
755
756InputMapper::~InputMapper() {
757}
758
759void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
760    info->addSource(getSources());
761}
762
763void InputMapper::dump(String8& dump) {
764}
765
766void InputMapper::configure() {
767}
768
769void InputMapper::reset() {
770}
771
772int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
773    return AKEY_STATE_UNKNOWN;
774}
775
776int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
777    return AKEY_STATE_UNKNOWN;
778}
779
780int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
781    return AKEY_STATE_UNKNOWN;
782}
783
784bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
785        const int32_t* keyCodes, uint8_t* outFlags) {
786    return false;
787}
788
789int32_t InputMapper::getMetaState() {
790    return 0;
791}
792
793void InputMapper::fadePointer() {
794}
795
796void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
797        const RawAbsoluteAxisInfo& axis, const char* name) {
798    if (axis.valid) {
799        dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
800                name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
801    } else {
802        dump.appendFormat(INDENT4 "%s: unknown range\n", name);
803    }
804}
805
806
807// --- SwitchInputMapper ---
808
809SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
810        InputMapper(device) {
811}
812
813SwitchInputMapper::~SwitchInputMapper() {
814}
815
816uint32_t SwitchInputMapper::getSources() {
817    return AINPUT_SOURCE_SWITCH;
818}
819
820void SwitchInputMapper::process(const RawEvent* rawEvent) {
821    switch (rawEvent->type) {
822    case EV_SW:
823        processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
824        break;
825    }
826}
827
828void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
829    getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
830}
831
832int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
833    return getEventHub()->getSwitchState(getDeviceId(), switchCode);
834}
835
836
837// --- KeyboardInputMapper ---
838
839KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
840        uint32_t sources, int32_t keyboardType) :
841        InputMapper(device), mSources(sources),
842        mKeyboardType(keyboardType) {
843    initializeLocked();
844}
845
846KeyboardInputMapper::~KeyboardInputMapper() {
847}
848
849void KeyboardInputMapper::initializeLocked() {
850    mLocked.metaState = AMETA_NONE;
851    mLocked.downTime = 0;
852}
853
854uint32_t KeyboardInputMapper::getSources() {
855    return mSources;
856}
857
858void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
859    InputMapper::populateDeviceInfo(info);
860
861    info->setKeyboardType(mKeyboardType);
862}
863
864void KeyboardInputMapper::dump(String8& dump) {
865    { // acquire lock
866        AutoMutex _l(mLock);
867        dump.append(INDENT2 "Keyboard Input Mapper:\n");
868        dumpParameters(dump);
869        dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
870        dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
871        dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
872        dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
873    } // release lock
874}
875
876
877void KeyboardInputMapper::configure() {
878    InputMapper::configure();
879
880    // Configure basic parameters.
881    configureParameters();
882
883    // Reset LEDs.
884    {
885        AutoMutex _l(mLock);
886        resetLedStateLocked();
887    }
888}
889
890void KeyboardInputMapper::configureParameters() {
891    mParameters.orientationAware = false;
892    getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
893            mParameters.orientationAware);
894
895    mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
896}
897
898void KeyboardInputMapper::dumpParameters(String8& dump) {
899    dump.append(INDENT3 "Parameters:\n");
900    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
901            mParameters.associatedDisplayId);
902    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
903            toString(mParameters.orientationAware));
904}
905
906void KeyboardInputMapper::reset() {
907    for (;;) {
908        int32_t keyCode, scanCode;
909        { // acquire lock
910            AutoMutex _l(mLock);
911
912            // Synthesize key up event on reset if keys are currently down.
913            if (mLocked.keyDowns.isEmpty()) {
914                initializeLocked();
915                resetLedStateLocked();
916                break; // done
917            }
918
919            const KeyDown& keyDown = mLocked.keyDowns.top();
920            keyCode = keyDown.keyCode;
921            scanCode = keyDown.scanCode;
922        } // release lock
923
924        nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
925        processKey(when, false, keyCode, scanCode, 0);
926    }
927
928    InputMapper::reset();
929    getContext()->updateGlobalMetaState();
930}
931
932void KeyboardInputMapper::process(const RawEvent* rawEvent) {
933    switch (rawEvent->type) {
934    case EV_KEY: {
935        int32_t scanCode = rawEvent->scanCode;
936        if (isKeyboardOrGamepadKey(scanCode)) {
937            processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
938                    rawEvent->flags);
939        }
940        break;
941    }
942    }
943}
944
945bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
946    return scanCode < BTN_MOUSE
947        || scanCode >= KEY_OK
948        || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE)
949        || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
950}
951
952void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
953        int32_t scanCode, uint32_t policyFlags) {
954    int32_t newMetaState;
955    nsecs_t downTime;
956    bool metaStateChanged = false;
957
958    { // acquire lock
959        AutoMutex _l(mLock);
960
961        if (down) {
962            // Rotate key codes according to orientation if needed.
963            // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
964            if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
965                int32_t orientation;
966                if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
967                        NULL, NULL, & orientation)) {
968                    orientation = DISPLAY_ORIENTATION_0;
969                }
970
971                keyCode = rotateKeyCode(keyCode, orientation);
972            }
973
974            // Add key down.
975            ssize_t keyDownIndex = findKeyDownLocked(scanCode);
976            if (keyDownIndex >= 0) {
977                // key repeat, be sure to use same keycode as before in case of rotation
978                keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
979            } else {
980                // key down
981                if ((policyFlags & POLICY_FLAG_VIRTUAL)
982                        && mContext->shouldDropVirtualKey(when,
983                                getDevice(), keyCode, scanCode)) {
984                    return;
985                }
986
987                mLocked.keyDowns.push();
988                KeyDown& keyDown = mLocked.keyDowns.editTop();
989                keyDown.keyCode = keyCode;
990                keyDown.scanCode = scanCode;
991            }
992
993            mLocked.downTime = when;
994        } else {
995            // Remove key down.
996            ssize_t keyDownIndex = findKeyDownLocked(scanCode);
997            if (keyDownIndex >= 0) {
998                // key up, be sure to use same keycode as before in case of rotation
999                keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
1000                mLocked.keyDowns.removeAt(size_t(keyDownIndex));
1001            } else {
1002                // key was not actually down
1003                LOGI("Dropping key up from device %s because the key was not down.  "
1004                        "keyCode=%d, scanCode=%d",
1005                        getDeviceName().string(), keyCode, scanCode);
1006                return;
1007            }
1008        }
1009
1010        int32_t oldMetaState = mLocked.metaState;
1011        newMetaState = updateMetaState(keyCode, down, oldMetaState);
1012        if (oldMetaState != newMetaState) {
1013            mLocked.metaState = newMetaState;
1014            metaStateChanged = true;
1015            updateLedStateLocked(false);
1016        }
1017
1018        downTime = mLocked.downTime;
1019    } // release lock
1020
1021    // Key down on external an keyboard should wake the device.
1022    // We don't do this for internal keyboards to prevent them from waking up in your pocket.
1023    // For internal keyboards, the key layout file should specify the policy flags for
1024    // each wake key individually.
1025    // TODO: Use the input device configuration to control this behavior more finely.
1026    if (down && getDevice()->isExternal()
1027            && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {
1028        policyFlags |= POLICY_FLAG_WAKE_DROPPED;
1029    }
1030
1031    if (metaStateChanged) {
1032        getContext()->updateGlobalMetaState();
1033    }
1034
1035    if (down && !isMetaKey(keyCode)) {
1036        getContext()->fadePointer();
1037    }
1038
1039    getDispatcher()->notifyKey(when, getDeviceId(), mSources, policyFlags,
1040            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
1041            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
1042}
1043
1044ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
1045    size_t n = mLocked.keyDowns.size();
1046    for (size_t i = 0; i < n; i++) {
1047        if (mLocked.keyDowns[i].scanCode == scanCode) {
1048            return i;
1049        }
1050    }
1051    return -1;
1052}
1053
1054int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1055    return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
1056}
1057
1058int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1059    return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1060}
1061
1062bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1063        const int32_t* keyCodes, uint8_t* outFlags) {
1064    return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1065}
1066
1067int32_t KeyboardInputMapper::getMetaState() {
1068    { // acquire lock
1069        AutoMutex _l(mLock);
1070        return mLocked.metaState;
1071    } // release lock
1072}
1073
1074void KeyboardInputMapper::resetLedStateLocked() {
1075    initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
1076    initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
1077    initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
1078
1079    updateLedStateLocked(true);
1080}
1081
1082void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
1083    ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
1084    ledState.on = false;
1085}
1086
1087void KeyboardInputMapper::updateLedStateLocked(bool reset) {
1088    updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
1089            AMETA_CAPS_LOCK_ON, reset);
1090    updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML,
1091            AMETA_NUM_LOCK_ON, reset);
1092    updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL,
1093            AMETA_SCROLL_LOCK_ON, reset);
1094}
1095
1096void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState,
1097        int32_t led, int32_t modifier, bool reset) {
1098    if (ledState.avail) {
1099        bool desiredState = (mLocked.metaState & modifier) != 0;
1100        if (reset || ledState.on != desiredState) {
1101            getEventHub()->setLedState(getDeviceId(), led, desiredState);
1102            ledState.on = desiredState;
1103        }
1104    }
1105}
1106
1107
1108// --- CursorInputMapper ---
1109
1110CursorInputMapper::CursorInputMapper(InputDevice* device) :
1111        InputMapper(device) {
1112    initializeLocked();
1113}
1114
1115CursorInputMapper::~CursorInputMapper() {
1116}
1117
1118uint32_t CursorInputMapper::getSources() {
1119    return mSources;
1120}
1121
1122void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1123    InputMapper::populateDeviceInfo(info);
1124
1125    if (mParameters.mode == Parameters::MODE_POINTER) {
1126        float minX, minY, maxX, maxY;
1127        if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
1128            info->addMotionRange(AMOTION_EVENT_AXIS_X, minX, maxX, 0.0f, 0.0f);
1129            info->addMotionRange(AMOTION_EVENT_AXIS_Y, minY, maxY, 0.0f, 0.0f);
1130        }
1131    } else {
1132        info->addMotionRange(AMOTION_EVENT_AXIS_X, -1.0f, 1.0f, 0.0f, mXScale);
1133        info->addMotionRange(AMOTION_EVENT_AXIS_Y, -1.0f, 1.0f, 0.0f, mYScale);
1134    }
1135    info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, 0.0f, 1.0f, 0.0f, 0.0f);
1136
1137    if (mHaveVWheel) {
1138        info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, -1.0f, 1.0f, 0.0f, 0.0f);
1139    }
1140    if (mHaveHWheel) {
1141        info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, -1.0f, 1.0f, 0.0f, 0.0f);
1142    }
1143}
1144
1145void CursorInputMapper::dump(String8& dump) {
1146    { // acquire lock
1147        AutoMutex _l(mLock);
1148        dump.append(INDENT2 "Cursor Input Mapper:\n");
1149        dumpParameters(dump);
1150        dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
1151        dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
1152        dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1153        dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
1154        dump.appendFormat(INDENT3 "HaveVWheel: %s\n", toString(mHaveVWheel));
1155        dump.appendFormat(INDENT3 "HaveHWheel: %s\n", toString(mHaveHWheel));
1156        dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
1157        dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
1158        dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
1159        dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1160    } // release lock
1161}
1162
1163void CursorInputMapper::configure() {
1164    InputMapper::configure();
1165
1166    // Configure basic parameters.
1167    configureParameters();
1168
1169    // Configure device mode.
1170    switch (mParameters.mode) {
1171    case Parameters::MODE_POINTER:
1172        mSources = AINPUT_SOURCE_MOUSE;
1173        mXPrecision = 1.0f;
1174        mYPrecision = 1.0f;
1175        mXScale = 1.0f;
1176        mYScale = 1.0f;
1177        mPointerController = getPolicy()->obtainPointerController(getDeviceId());
1178        break;
1179    case Parameters::MODE_NAVIGATION:
1180        mSources = AINPUT_SOURCE_TRACKBALL;
1181        mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1182        mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1183        mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1184        mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1185        break;
1186    }
1187
1188    mVWheelScale = 1.0f;
1189    mHWheelScale = 1.0f;
1190
1191    mHaveVWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_WHEEL);
1192    mHaveHWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_HWHEEL);
1193}
1194
1195void CursorInputMapper::configureParameters() {
1196    mParameters.mode = Parameters::MODE_POINTER;
1197    String8 cursorModeString;
1198    if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
1199        if (cursorModeString == "navigation") {
1200            mParameters.mode = Parameters::MODE_NAVIGATION;
1201        } else if (cursorModeString != "pointer" && cursorModeString != "default") {
1202            LOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
1203        }
1204    }
1205
1206    mParameters.orientationAware = false;
1207    getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
1208            mParameters.orientationAware);
1209
1210    mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER
1211            || mParameters.orientationAware ? 0 : -1;
1212}
1213
1214void CursorInputMapper::dumpParameters(String8& dump) {
1215    dump.append(INDENT3 "Parameters:\n");
1216    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1217            mParameters.associatedDisplayId);
1218
1219    switch (mParameters.mode) {
1220    case Parameters::MODE_POINTER:
1221        dump.append(INDENT4 "Mode: pointer\n");
1222        break;
1223    case Parameters::MODE_NAVIGATION:
1224        dump.append(INDENT4 "Mode: navigation\n");
1225        break;
1226    default:
1227        assert(false);
1228    }
1229
1230    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1231            toString(mParameters.orientationAware));
1232}
1233
1234void CursorInputMapper::initializeLocked() {
1235    mAccumulator.clear();
1236
1237    mLocked.down = false;
1238    mLocked.downTime = 0;
1239}
1240
1241void CursorInputMapper::reset() {
1242    for (;;) {
1243        { // acquire lock
1244            AutoMutex _l(mLock);
1245
1246            if (! mLocked.down) {
1247                initializeLocked();
1248                break; // done
1249            }
1250        } // release lock
1251
1252        // Synthesize button up event on reset.
1253        nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
1254        mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
1255        mAccumulator.btnMouse = false;
1256        sync(when);
1257    }
1258
1259    InputMapper::reset();
1260}
1261
1262void CursorInputMapper::process(const RawEvent* rawEvent) {
1263    switch (rawEvent->type) {
1264    case EV_KEY:
1265        switch (rawEvent->scanCode) {
1266        case BTN_LEFT:
1267        case BTN_RIGHT:
1268        case BTN_MIDDLE:
1269        case BTN_SIDE:
1270        case BTN_EXTRA:
1271        case BTN_FORWARD:
1272        case BTN_BACK:
1273        case BTN_TASK:
1274            mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1275            mAccumulator.btnMouse = rawEvent->value != 0;
1276            // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1277            // we need to ensure that we report the up/down promptly.
1278            sync(rawEvent->when);
1279            break;
1280        }
1281        break;
1282
1283    case EV_REL:
1284        switch (rawEvent->scanCode) {
1285        case REL_X:
1286            mAccumulator.fields |= Accumulator::FIELD_REL_X;
1287            mAccumulator.relX = rawEvent->value;
1288            break;
1289        case REL_Y:
1290            mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1291            mAccumulator.relY = rawEvent->value;
1292            break;
1293        case REL_WHEEL:
1294            mAccumulator.fields |= Accumulator::FIELD_REL_WHEEL;
1295            mAccumulator.relWheel = rawEvent->value;
1296            break;
1297        case REL_HWHEEL:
1298            mAccumulator.fields |= Accumulator::FIELD_REL_HWHEEL;
1299            mAccumulator.relHWheel = rawEvent->value;
1300            break;
1301        }
1302        break;
1303
1304    case EV_SYN:
1305        switch (rawEvent->scanCode) {
1306        case SYN_REPORT:
1307            sync(rawEvent->when);
1308            break;
1309        }
1310        break;
1311    }
1312}
1313
1314void CursorInputMapper::sync(nsecs_t when) {
1315    uint32_t fields = mAccumulator.fields;
1316    if (fields == 0) {
1317        return; // no new state changes, so nothing to do
1318    }
1319
1320    int32_t motionEventAction;
1321    int32_t motionEventEdgeFlags;
1322    PointerCoords pointerCoords;
1323    nsecs_t downTime;
1324    float vscroll, hscroll;
1325    { // acquire lock
1326        AutoMutex _l(mLock);
1327
1328        bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1329
1330        if (downChanged) {
1331            if (mAccumulator.btnMouse) {
1332                if (!mLocked.down) {
1333                    mLocked.down = true;
1334                    mLocked.downTime = when;
1335                } else {
1336                    downChanged = false;
1337                }
1338            } else {
1339                if (mLocked.down) {
1340                    mLocked.down = false;
1341                } else {
1342                    downChanged = false;
1343                }
1344            }
1345        }
1346
1347        downTime = mLocked.downTime;
1348        float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1349        float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
1350
1351        if (downChanged) {
1352            motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
1353        } else if (mLocked.down || mPointerController == NULL) {
1354            motionEventAction = AMOTION_EVENT_ACTION_MOVE;
1355        } else {
1356            motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
1357        }
1358
1359        if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
1360                && (deltaX != 0.0f || deltaY != 0.0f)) {
1361            // Rotate motion based on display orientation if needed.
1362            // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1363            int32_t orientation;
1364            if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1365                    NULL, NULL, & orientation)) {
1366                orientation = DISPLAY_ORIENTATION_0;
1367            }
1368
1369            float temp;
1370            switch (orientation) {
1371            case DISPLAY_ORIENTATION_90:
1372                temp = deltaX;
1373                deltaX = deltaY;
1374                deltaY = -temp;
1375                break;
1376
1377            case DISPLAY_ORIENTATION_180:
1378                deltaX = -deltaX;
1379                deltaY = -deltaY;
1380                break;
1381
1382            case DISPLAY_ORIENTATION_270:
1383                temp = deltaX;
1384                deltaX = -deltaY;
1385                deltaY = temp;
1386                break;
1387            }
1388        }
1389
1390        pointerCoords.clear();
1391
1392        motionEventEdgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
1393
1394        if (mPointerController != NULL) {
1395            mPointerController->move(deltaX, deltaY);
1396            if (downChanged) {
1397                mPointerController->setButtonState(mLocked.down ? POINTER_BUTTON_1 : 0);
1398            }
1399            float x, y;
1400            mPointerController->getPosition(&x, &y);
1401            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
1402            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
1403
1404            if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
1405                float minX, minY, maxX, maxY;
1406                if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
1407                    if (x <= minX) {
1408                        motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
1409                    } else if (x >= maxX) {
1410                        motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
1411                    }
1412                    if (y <= minY) {
1413                        motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
1414                    } else if (y >= maxY) {
1415                        motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
1416                    }
1417                }
1418            }
1419        } else {
1420            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
1421            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
1422        }
1423
1424        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, mLocked.down ? 1.0f : 0.0f);
1425
1426        if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) {
1427            vscroll = mAccumulator.relWheel;
1428        } else {
1429            vscroll = 0;
1430        }
1431        if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) {
1432            hscroll = mAccumulator.relHWheel;
1433        } else {
1434            hscroll = 0;
1435        }
1436        if (hscroll != 0 || vscroll != 0) {
1437            mPointerController->unfade();
1438        }
1439    } // release lock
1440
1441    // Moving an external trackball or mouse should wake the device.
1442    // We don't do this for internal cursor devices to prevent them from waking up
1443    // the device in your pocket.
1444    // TODO: Use the input device configuration to control this behavior more finely.
1445    uint32_t policyFlags = 0;
1446    if (getDevice()->isExternal()) {
1447        policyFlags |= POLICY_FLAG_WAKE_DROPPED;
1448    }
1449
1450    int32_t metaState = mContext->getGlobalMetaState();
1451    int32_t pointerId = 0;
1452    getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
1453            motionEventAction, 0, metaState, motionEventEdgeFlags,
1454            1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1455
1456    mAccumulator.clear();
1457
1458    if (vscroll != 0 || hscroll != 0) {
1459        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
1460        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
1461
1462        getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
1463                AMOTION_EVENT_ACTION_SCROLL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1464                1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1465    }
1466}
1467
1468int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1469    if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1470        return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1471    } else {
1472        return AKEY_STATE_UNKNOWN;
1473    }
1474}
1475
1476void CursorInputMapper::fadePointer() {
1477    { // acquire lock
1478        AutoMutex _l(mLock);
1479        mPointerController->fade();
1480    } // release lock
1481}
1482
1483
1484// --- TouchInputMapper ---
1485
1486TouchInputMapper::TouchInputMapper(InputDevice* device) :
1487        InputMapper(device) {
1488    mLocked.surfaceOrientation = -1;
1489    mLocked.surfaceWidth = -1;
1490    mLocked.surfaceHeight = -1;
1491
1492    initializeLocked();
1493}
1494
1495TouchInputMapper::~TouchInputMapper() {
1496}
1497
1498uint32_t TouchInputMapper::getSources() {
1499    return mSources;
1500}
1501
1502void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1503    InputMapper::populateDeviceInfo(info);
1504
1505    { // acquire lock
1506        AutoMutex _l(mLock);
1507
1508        // Ensure surface information is up to date so that orientation changes are
1509        // noticed immediately.
1510        configureSurfaceLocked();
1511
1512        info->addMotionRange(AMOTION_EVENT_AXIS_X, mLocked.orientedRanges.x);
1513        info->addMotionRange(AMOTION_EVENT_AXIS_Y, mLocked.orientedRanges.y);
1514
1515        if (mLocked.orientedRanges.havePressure) {
1516            info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE,
1517                    mLocked.orientedRanges.pressure);
1518        }
1519
1520        if (mLocked.orientedRanges.haveSize) {
1521            info->addMotionRange(AMOTION_EVENT_AXIS_SIZE,
1522                    mLocked.orientedRanges.size);
1523        }
1524
1525        if (mLocked.orientedRanges.haveTouchSize) {
1526            info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MAJOR,
1527                    mLocked.orientedRanges.touchMajor);
1528            info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MINOR,
1529                    mLocked.orientedRanges.touchMinor);
1530        }
1531
1532        if (mLocked.orientedRanges.haveToolSize) {
1533            info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MAJOR,
1534                    mLocked.orientedRanges.toolMajor);
1535            info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MINOR,
1536                    mLocked.orientedRanges.toolMinor);
1537        }
1538
1539        if (mLocked.orientedRanges.haveOrientation) {
1540            info->addMotionRange(AMOTION_EVENT_AXIS_ORIENTATION,
1541                    mLocked.orientedRanges.orientation);
1542        }
1543    } // release lock
1544}
1545
1546void TouchInputMapper::dump(String8& dump) {
1547    { // acquire lock
1548        AutoMutex _l(mLock);
1549        dump.append(INDENT2 "Touch Input Mapper:\n");
1550        dumpParameters(dump);
1551        dumpVirtualKeysLocked(dump);
1552        dumpRawAxes(dump);
1553        dumpCalibration(dump);
1554        dumpSurfaceLocked(dump);
1555        dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
1556        dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
1557        dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
1558        dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
1559        dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
1560        dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
1561        dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
1562        dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
1563        dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
1564        dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
1565        dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
1566        dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
1567        dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale);
1568    } // release lock
1569}
1570
1571void TouchInputMapper::initializeLocked() {
1572    mCurrentTouch.clear();
1573    mLastTouch.clear();
1574    mDownTime = 0;
1575
1576    for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1577        mAveragingTouchFilter.historyStart[i] = 0;
1578        mAveragingTouchFilter.historyEnd[i] = 0;
1579    }
1580
1581    mJumpyTouchFilter.jumpyPointsDropped = 0;
1582
1583    mLocked.currentVirtualKey.down = false;
1584
1585    mLocked.orientedRanges.havePressure = false;
1586    mLocked.orientedRanges.haveSize = false;
1587    mLocked.orientedRanges.haveTouchSize = false;
1588    mLocked.orientedRanges.haveToolSize = false;
1589    mLocked.orientedRanges.haveOrientation = false;
1590}
1591
1592void TouchInputMapper::configure() {
1593    InputMapper::configure();
1594
1595    // Configure basic parameters.
1596    configureParameters();
1597
1598    // Configure sources.
1599    switch (mParameters.deviceType) {
1600    case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1601        mSources = AINPUT_SOURCE_TOUCHSCREEN;
1602        break;
1603    case Parameters::DEVICE_TYPE_TOUCH_PAD:
1604        mSources = AINPUT_SOURCE_TOUCHPAD;
1605        break;
1606    default:
1607        assert(false);
1608    }
1609
1610    // Configure absolute axis information.
1611    configureRawAxes();
1612
1613    // Prepare input device calibration.
1614    parseCalibration();
1615    resolveCalibration();
1616
1617    { // acquire lock
1618        AutoMutex _l(mLock);
1619
1620         // Configure surface dimensions and orientation.
1621        configureSurfaceLocked();
1622    } // release lock
1623}
1624
1625void TouchInputMapper::configureParameters() {
1626    mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1627    mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1628    mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
1629    mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime();
1630
1631    String8 deviceTypeString;
1632    mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
1633    if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
1634            deviceTypeString)) {
1635        if (deviceTypeString == "touchScreen") {
1636            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1637        } else if (deviceTypeString != "touchPad") {
1638            LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
1639        }
1640    }
1641    bool isTouchScreen = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1642
1643    mParameters.orientationAware = isTouchScreen;
1644    getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
1645            mParameters.orientationAware);
1646
1647    mParameters.associatedDisplayId = mParameters.orientationAware || isTouchScreen ? 0 : -1;
1648}
1649
1650void TouchInputMapper::dumpParameters(String8& dump) {
1651    dump.append(INDENT3 "Parameters:\n");
1652
1653    switch (mParameters.deviceType) {
1654    case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1655        dump.append(INDENT4 "DeviceType: touchScreen\n");
1656        break;
1657    case Parameters::DEVICE_TYPE_TOUCH_PAD:
1658        dump.append(INDENT4 "DeviceType: touchPad\n");
1659        break;
1660    default:
1661        assert(false);
1662    }
1663
1664    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1665            mParameters.associatedDisplayId);
1666    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1667            toString(mParameters.orientationAware));
1668
1669    dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
1670            toString(mParameters.useBadTouchFilter));
1671    dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
1672            toString(mParameters.useAveragingTouchFilter));
1673    dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
1674            toString(mParameters.useJumpyTouchFilter));
1675}
1676
1677void TouchInputMapper::configureRawAxes() {
1678    mRawAxes.x.clear();
1679    mRawAxes.y.clear();
1680    mRawAxes.pressure.clear();
1681    mRawAxes.touchMajor.clear();
1682    mRawAxes.touchMinor.clear();
1683    mRawAxes.toolMajor.clear();
1684    mRawAxes.toolMinor.clear();
1685    mRawAxes.orientation.clear();
1686}
1687
1688void TouchInputMapper::dumpRawAxes(String8& dump) {
1689    dump.append(INDENT3 "Raw Axes:\n");
1690    dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X");
1691    dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y");
1692    dumpRawAbsoluteAxisInfo(dump, mRawAxes.pressure, "Pressure");
1693    dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1694    dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1695    dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1696    dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1697    dumpRawAbsoluteAxisInfo(dump, mRawAxes.orientation, "Orientation");
1698}
1699
1700bool TouchInputMapper::configureSurfaceLocked() {
1701    // Ensure we have valid X and Y axes.
1702    if (!mRawAxes.x.valid || !mRawAxes.y.valid) {
1703        LOGW(INDENT "Touch device '%s' did not report support for X or Y axis!  "
1704                "The device will be inoperable.", getDeviceName().string());
1705        return false;
1706    }
1707
1708    // Update orientation and dimensions if needed.
1709    int32_t orientation = DISPLAY_ORIENTATION_0;
1710    int32_t width = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
1711    int32_t height = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
1712
1713    if (mParameters.associatedDisplayId >= 0) {
1714        bool wantSize = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1715        bool wantOrientation = mParameters.orientationAware;
1716
1717        // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1718        if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1719                wantSize ? &width : NULL, wantSize ? &height : NULL,
1720                wantOrientation ? &orientation : NULL)) {
1721            return false;
1722        }
1723    }
1724
1725    bool orientationChanged = mLocked.surfaceOrientation != orientation;
1726    if (orientationChanged) {
1727        mLocked.surfaceOrientation = orientation;
1728    }
1729
1730    bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
1731    if (sizeChanged) {
1732        LOGI("Device reconfigured: id=%d, name='%s', display size is now %dx%d",
1733                getDeviceId(), getDeviceName().string(), width, height);
1734
1735        mLocked.surfaceWidth = width;
1736        mLocked.surfaceHeight = height;
1737
1738        // Configure X and Y factors.
1739        mLocked.xScale = float(width) / (mRawAxes.x.maxValue - mRawAxes.x.minValue + 1);
1740        mLocked.yScale = float(height) / (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1);
1741        mLocked.xPrecision = 1.0f / mLocked.xScale;
1742        mLocked.yPrecision = 1.0f / mLocked.yScale;
1743
1744        configureVirtualKeysLocked();
1745
1746        // Scale factor for terms that are not oriented in a particular axis.
1747        // If the pixels are square then xScale == yScale otherwise we fake it
1748        // by choosing an average.
1749        mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
1750
1751        // Size of diagonal axis.
1752        float diagonalSize = pythag(width, height);
1753
1754        // TouchMajor and TouchMinor factors.
1755        if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
1756            mLocked.orientedRanges.haveTouchSize = true;
1757            mLocked.orientedRanges.touchMajor.min = 0;
1758            mLocked.orientedRanges.touchMajor.max = diagonalSize;
1759            mLocked.orientedRanges.touchMajor.flat = 0;
1760            mLocked.orientedRanges.touchMajor.fuzz = 0;
1761            mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1762        }
1763
1764        // ToolMajor and ToolMinor factors.
1765        mLocked.toolSizeLinearScale = 0;
1766        mLocked.toolSizeLinearBias = 0;
1767        mLocked.toolSizeAreaScale = 0;
1768        mLocked.toolSizeAreaBias = 0;
1769        if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
1770            if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
1771                if (mCalibration.haveToolSizeLinearScale) {
1772                    mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
1773                } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1774                    mLocked.toolSizeLinearScale = float(min(width, height))
1775                            / mRawAxes.toolMajor.maxValue;
1776                }
1777
1778                if (mCalibration.haveToolSizeLinearBias) {
1779                    mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1780                }
1781            } else if (mCalibration.toolSizeCalibration ==
1782                    Calibration::TOOL_SIZE_CALIBRATION_AREA) {
1783                if (mCalibration.haveToolSizeLinearScale) {
1784                    mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
1785                } else {
1786                    mLocked.toolSizeLinearScale = min(width, height);
1787                }
1788
1789                if (mCalibration.haveToolSizeLinearBias) {
1790                    mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1791                }
1792
1793                if (mCalibration.haveToolSizeAreaScale) {
1794                    mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
1795                } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1796                    mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
1797                }
1798
1799                if (mCalibration.haveToolSizeAreaBias) {
1800                    mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
1801                }
1802            }
1803
1804            mLocked.orientedRanges.haveToolSize = true;
1805            mLocked.orientedRanges.toolMajor.min = 0;
1806            mLocked.orientedRanges.toolMajor.max = diagonalSize;
1807            mLocked.orientedRanges.toolMajor.flat = 0;
1808            mLocked.orientedRanges.toolMajor.fuzz = 0;
1809            mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1810        }
1811
1812        // Pressure factors.
1813        mLocked.pressureScale = 0;
1814        if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1815            RawAbsoluteAxisInfo rawPressureAxis;
1816            switch (mCalibration.pressureSource) {
1817            case Calibration::PRESSURE_SOURCE_PRESSURE:
1818                rawPressureAxis = mRawAxes.pressure;
1819                break;
1820            case Calibration::PRESSURE_SOURCE_TOUCH:
1821                rawPressureAxis = mRawAxes.touchMajor;
1822                break;
1823            default:
1824                rawPressureAxis.clear();
1825            }
1826
1827            if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1828                    || mCalibration.pressureCalibration
1829                            == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1830                if (mCalibration.havePressureScale) {
1831                    mLocked.pressureScale = mCalibration.pressureScale;
1832                } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1833                    mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1834                }
1835            }
1836
1837            mLocked.orientedRanges.havePressure = true;
1838            mLocked.orientedRanges.pressure.min = 0;
1839            mLocked.orientedRanges.pressure.max = 1.0;
1840            mLocked.orientedRanges.pressure.flat = 0;
1841            mLocked.orientedRanges.pressure.fuzz = 0;
1842        }
1843
1844        // Size factors.
1845        mLocked.sizeScale = 0;
1846        if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
1847            if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1848                if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1849                    mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1850                }
1851            }
1852
1853            mLocked.orientedRanges.haveSize = true;
1854            mLocked.orientedRanges.size.min = 0;
1855            mLocked.orientedRanges.size.max = 1.0;
1856            mLocked.orientedRanges.size.flat = 0;
1857            mLocked.orientedRanges.size.fuzz = 0;
1858        }
1859
1860        // Orientation
1861        mLocked.orientationScale = 0;
1862        if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
1863            if (mCalibration.orientationCalibration
1864                    == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1865                if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1866                    mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1867                }
1868            }
1869
1870            mLocked.orientedRanges.orientation.min = - M_PI_2;
1871            mLocked.orientedRanges.orientation.max = M_PI_2;
1872            mLocked.orientedRanges.orientation.flat = 0;
1873            mLocked.orientedRanges.orientation.fuzz = 0;
1874        }
1875    }
1876
1877    if (orientationChanged || sizeChanged) {
1878        // Compute oriented surface dimensions, precision, scales and ranges.
1879        // Note that the maximum value reported is an inclusive maximum value so it is one
1880        // unit less than the total width or height of surface.
1881        switch (mLocked.surfaceOrientation) {
1882        case DISPLAY_ORIENTATION_90:
1883        case DISPLAY_ORIENTATION_270:
1884            mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1885            mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1886
1887            mLocked.orientedXPrecision = mLocked.yPrecision;
1888            mLocked.orientedYPrecision = mLocked.xPrecision;
1889
1890            mLocked.orientedRanges.x.min = 0;
1891            mLocked.orientedRanges.x.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue)
1892                    * mLocked.yScale;
1893            mLocked.orientedRanges.x.flat = 0;
1894            mLocked.orientedRanges.x.fuzz = mLocked.yScale;
1895
1896            mLocked.orientedRanges.y.min = 0;
1897            mLocked.orientedRanges.y.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue)
1898                    * mLocked.xScale;
1899            mLocked.orientedRanges.y.flat = 0;
1900            mLocked.orientedRanges.y.fuzz = mLocked.xScale;
1901            break;
1902
1903        default:
1904            mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1905            mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1906
1907            mLocked.orientedXPrecision = mLocked.xPrecision;
1908            mLocked.orientedYPrecision = mLocked.yPrecision;
1909
1910            mLocked.orientedRanges.x.min = 0;
1911            mLocked.orientedRanges.x.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue)
1912                    * mLocked.xScale;
1913            mLocked.orientedRanges.x.flat = 0;
1914            mLocked.orientedRanges.x.fuzz = mLocked.xScale;
1915
1916            mLocked.orientedRanges.y.min = 0;
1917            mLocked.orientedRanges.y.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue)
1918                    * mLocked.yScale;
1919            mLocked.orientedRanges.y.flat = 0;
1920            mLocked.orientedRanges.y.fuzz = mLocked.yScale;
1921            break;
1922        }
1923    }
1924
1925    return true;
1926}
1927
1928void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
1929    dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
1930    dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
1931    dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
1932}
1933
1934void TouchInputMapper::configureVirtualKeysLocked() {
1935    Vector<VirtualKeyDefinition> virtualKeyDefinitions;
1936    getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
1937
1938    mLocked.virtualKeys.clear();
1939
1940    if (virtualKeyDefinitions.size() == 0) {
1941        return;
1942    }
1943
1944    mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1945
1946    int32_t touchScreenLeft = mRawAxes.x.minValue;
1947    int32_t touchScreenTop = mRawAxes.y.minValue;
1948    int32_t touchScreenWidth = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
1949    int32_t touchScreenHeight = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
1950
1951    for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
1952        const VirtualKeyDefinition& virtualKeyDefinition =
1953                virtualKeyDefinitions[i];
1954
1955        mLocked.virtualKeys.add();
1956        VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1957
1958        virtualKey.scanCode = virtualKeyDefinition.scanCode;
1959        int32_t keyCode;
1960        uint32_t flags;
1961        if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode,
1962                & keyCode, & flags)) {
1963            LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1964                    virtualKey.scanCode);
1965            mLocked.virtualKeys.pop(); // drop the key
1966            continue;
1967        }
1968
1969        virtualKey.keyCode = keyCode;
1970        virtualKey.flags = flags;
1971
1972        // convert the key definition's display coordinates into touch coordinates for a hit box
1973        int32_t halfWidth = virtualKeyDefinition.width / 2;
1974        int32_t halfHeight = virtualKeyDefinition.height / 2;
1975
1976        virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1977                * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1978        virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1979                * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1980        virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1981                * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1982        virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1983                * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1984    }
1985}
1986
1987void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
1988    if (!mLocked.virtualKeys.isEmpty()) {
1989        dump.append(INDENT3 "Virtual Keys:\n");
1990
1991        for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
1992            const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
1993            dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
1994                    "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
1995                    i, virtualKey.scanCode, virtualKey.keyCode,
1996                    virtualKey.hitLeft, virtualKey.hitRight,
1997                    virtualKey.hitTop, virtualKey.hitBottom);
1998        }
1999    }
2000}
2001
2002void TouchInputMapper::parseCalibration() {
2003    const PropertyMap& in = getDevice()->getConfiguration();
2004    Calibration& out = mCalibration;
2005
2006    // Touch Size
2007    out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
2008    String8 touchSizeCalibrationString;
2009    if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
2010        if (touchSizeCalibrationString == "none") {
2011            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
2012        } else if (touchSizeCalibrationString == "geometric") {
2013            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
2014        } else if (touchSizeCalibrationString == "pressure") {
2015            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
2016        } else if (touchSizeCalibrationString != "default") {
2017            LOGW("Invalid value for touch.touchSize.calibration: '%s'",
2018                    touchSizeCalibrationString.string());
2019        }
2020    }
2021
2022    // Tool Size
2023    out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
2024    String8 toolSizeCalibrationString;
2025    if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
2026        if (toolSizeCalibrationString == "none") {
2027            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
2028        } else if (toolSizeCalibrationString == "geometric") {
2029            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
2030        } else if (toolSizeCalibrationString == "linear") {
2031            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
2032        } else if (toolSizeCalibrationString == "area") {
2033            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
2034        } else if (toolSizeCalibrationString != "default") {
2035            LOGW("Invalid value for touch.toolSize.calibration: '%s'",
2036                    toolSizeCalibrationString.string());
2037        }
2038    }
2039
2040    out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
2041            out.toolSizeLinearScale);
2042    out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
2043            out.toolSizeLinearBias);
2044    out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
2045            out.toolSizeAreaScale);
2046    out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
2047            out.toolSizeAreaBias);
2048    out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
2049            out.toolSizeIsSummed);
2050
2051    // Pressure
2052    out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
2053    String8 pressureCalibrationString;
2054    if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
2055        if (pressureCalibrationString == "none") {
2056            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2057        } else if (pressureCalibrationString == "physical") {
2058            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
2059        } else if (pressureCalibrationString == "amplitude") {
2060            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2061        } else if (pressureCalibrationString != "default") {
2062            LOGW("Invalid value for touch.pressure.calibration: '%s'",
2063                    pressureCalibrationString.string());
2064        }
2065    }
2066
2067    out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
2068    String8 pressureSourceString;
2069    if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
2070        if (pressureSourceString == "pressure") {
2071            out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2072        } else if (pressureSourceString == "touch") {
2073            out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2074        } else if (pressureSourceString != "default") {
2075            LOGW("Invalid value for touch.pressure.source: '%s'",
2076                    pressureSourceString.string());
2077        }
2078    }
2079
2080    out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
2081            out.pressureScale);
2082
2083    // Size
2084    out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
2085    String8 sizeCalibrationString;
2086    if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
2087        if (sizeCalibrationString == "none") {
2088            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2089        } else if (sizeCalibrationString == "normalized") {
2090            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2091        } else if (sizeCalibrationString != "default") {
2092            LOGW("Invalid value for touch.size.calibration: '%s'",
2093                    sizeCalibrationString.string());
2094        }
2095    }
2096
2097    // Orientation
2098    out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
2099    String8 orientationCalibrationString;
2100    if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
2101        if (orientationCalibrationString == "none") {
2102            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2103        } else if (orientationCalibrationString == "interpolated") {
2104            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2105        } else if (orientationCalibrationString == "vector") {
2106            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
2107        } else if (orientationCalibrationString != "default") {
2108            LOGW("Invalid value for touch.orientation.calibration: '%s'",
2109                    orientationCalibrationString.string());
2110        }
2111    }
2112}
2113
2114void TouchInputMapper::resolveCalibration() {
2115    // Pressure
2116    switch (mCalibration.pressureSource) {
2117    case Calibration::PRESSURE_SOURCE_DEFAULT:
2118        if (mRawAxes.pressure.valid) {
2119            mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2120        } else if (mRawAxes.touchMajor.valid) {
2121            mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2122        }
2123        break;
2124
2125    case Calibration::PRESSURE_SOURCE_PRESSURE:
2126        if (! mRawAxes.pressure.valid) {
2127            LOGW("Calibration property touch.pressure.source is 'pressure' but "
2128                    "the pressure axis is not available.");
2129        }
2130        break;
2131
2132    case Calibration::PRESSURE_SOURCE_TOUCH:
2133        if (! mRawAxes.touchMajor.valid) {
2134            LOGW("Calibration property touch.pressure.source is 'touch' but "
2135                    "the touchMajor axis is not available.");
2136        }
2137        break;
2138
2139    default:
2140        break;
2141    }
2142
2143    switch (mCalibration.pressureCalibration) {
2144    case Calibration::PRESSURE_CALIBRATION_DEFAULT:
2145        if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
2146            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2147        } else {
2148            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2149        }
2150        break;
2151
2152    default:
2153        break;
2154    }
2155
2156    // Tool Size
2157    switch (mCalibration.toolSizeCalibration) {
2158    case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
2159        if (mRawAxes.toolMajor.valid) {
2160            mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
2161        } else {
2162            mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
2163        }
2164        break;
2165
2166    default:
2167        break;
2168    }
2169
2170    // Touch Size
2171    switch (mCalibration.touchSizeCalibration) {
2172    case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
2173        if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
2174                && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2175            mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
2176        } else {
2177            mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
2178        }
2179        break;
2180
2181    default:
2182        break;
2183    }
2184
2185    // Size
2186    switch (mCalibration.sizeCalibration) {
2187    case Calibration::SIZE_CALIBRATION_DEFAULT:
2188        if (mRawAxes.toolMajor.valid) {
2189            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2190        } else {
2191            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2192        }
2193        break;
2194
2195    default:
2196        break;
2197    }
2198
2199    // Orientation
2200    switch (mCalibration.orientationCalibration) {
2201    case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
2202        if (mRawAxes.orientation.valid) {
2203            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2204        } else {
2205            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2206        }
2207        break;
2208
2209    default:
2210        break;
2211    }
2212}
2213
2214void TouchInputMapper::dumpCalibration(String8& dump) {
2215    dump.append(INDENT3 "Calibration:\n");
2216
2217    // Touch Size
2218    switch (mCalibration.touchSizeCalibration) {
2219    case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
2220        dump.append(INDENT4 "touch.touchSize.calibration: none\n");
2221        break;
2222    case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
2223        dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
2224        break;
2225    case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
2226        dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
2227        break;
2228    default:
2229        assert(false);
2230    }
2231
2232    // Tool Size
2233    switch (mCalibration.toolSizeCalibration) {
2234    case Calibration::TOOL_SIZE_CALIBRATION_NONE:
2235        dump.append(INDENT4 "touch.toolSize.calibration: none\n");
2236        break;
2237    case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
2238        dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
2239        break;
2240    case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
2241        dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
2242        break;
2243    case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2244        dump.append(INDENT4 "touch.toolSize.calibration: area\n");
2245        break;
2246    default:
2247        assert(false);
2248    }
2249
2250    if (mCalibration.haveToolSizeLinearScale) {
2251        dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
2252                mCalibration.toolSizeLinearScale);
2253    }
2254
2255    if (mCalibration.haveToolSizeLinearBias) {
2256        dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
2257                mCalibration.toolSizeLinearBias);
2258    }
2259
2260    if (mCalibration.haveToolSizeAreaScale) {
2261        dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
2262                mCalibration.toolSizeAreaScale);
2263    }
2264
2265    if (mCalibration.haveToolSizeAreaBias) {
2266        dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
2267                mCalibration.toolSizeAreaBias);
2268    }
2269
2270    if (mCalibration.haveToolSizeIsSummed) {
2271        dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
2272                toString(mCalibration.toolSizeIsSummed));
2273    }
2274
2275    // Pressure
2276    switch (mCalibration.pressureCalibration) {
2277    case Calibration::PRESSURE_CALIBRATION_NONE:
2278        dump.append(INDENT4 "touch.pressure.calibration: none\n");
2279        break;
2280    case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2281        dump.append(INDENT4 "touch.pressure.calibration: physical\n");
2282        break;
2283    case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2284        dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
2285        break;
2286    default:
2287        assert(false);
2288    }
2289
2290    switch (mCalibration.pressureSource) {
2291    case Calibration::PRESSURE_SOURCE_PRESSURE:
2292        dump.append(INDENT4 "touch.pressure.source: pressure\n");
2293        break;
2294    case Calibration::PRESSURE_SOURCE_TOUCH:
2295        dump.append(INDENT4 "touch.pressure.source: touch\n");
2296        break;
2297    case Calibration::PRESSURE_SOURCE_DEFAULT:
2298        break;
2299    default:
2300        assert(false);
2301    }
2302
2303    if (mCalibration.havePressureScale) {
2304        dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
2305                mCalibration.pressureScale);
2306    }
2307
2308    // Size
2309    switch (mCalibration.sizeCalibration) {
2310    case Calibration::SIZE_CALIBRATION_NONE:
2311        dump.append(INDENT4 "touch.size.calibration: none\n");
2312        break;
2313    case Calibration::SIZE_CALIBRATION_NORMALIZED:
2314        dump.append(INDENT4 "touch.size.calibration: normalized\n");
2315        break;
2316    default:
2317        assert(false);
2318    }
2319
2320    // Orientation
2321    switch (mCalibration.orientationCalibration) {
2322    case Calibration::ORIENTATION_CALIBRATION_NONE:
2323        dump.append(INDENT4 "touch.orientation.calibration: none\n");
2324        break;
2325    case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2326        dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
2327        break;
2328    case Calibration::ORIENTATION_CALIBRATION_VECTOR:
2329        dump.append(INDENT4 "touch.orientation.calibration: vector\n");
2330        break;
2331    default:
2332        assert(false);
2333    }
2334}
2335
2336void TouchInputMapper::reset() {
2337    // Synthesize touch up event if touch is currently down.
2338    // This will also take care of finishing virtual key processing if needed.
2339    if (mLastTouch.pointerCount != 0) {
2340        nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2341        mCurrentTouch.clear();
2342        syncTouch(when, true);
2343    }
2344
2345    { // acquire lock
2346        AutoMutex _l(mLock);
2347        initializeLocked();
2348    } // release lock
2349
2350    InputMapper::reset();
2351}
2352
2353void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
2354    // Preprocess pointer data.
2355    if (mParameters.useBadTouchFilter) {
2356        if (applyBadTouchFilter()) {
2357            havePointerIds = false;
2358        }
2359    }
2360
2361    if (mParameters.useJumpyTouchFilter) {
2362        if (applyJumpyTouchFilter()) {
2363            havePointerIds = false;
2364        }
2365    }
2366
2367    if (! havePointerIds) {
2368        calculatePointerIds();
2369    }
2370
2371    TouchData temp;
2372    TouchData* savedTouch;
2373    if (mParameters.useAveragingTouchFilter) {
2374        temp.copyFrom(mCurrentTouch);
2375        savedTouch = & temp;
2376
2377        applyAveragingTouchFilter();
2378    } else {
2379        savedTouch = & mCurrentTouch;
2380    }
2381
2382    uint32_t policyFlags = 0;
2383    if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
2384        // Hide the pointer on an initial down.
2385        getContext()->fadePointer();
2386
2387        // Initial downs on external touch devices should wake the device.
2388        // We don't do this for internal touch screens to prevent them from waking
2389        // up in your pocket.
2390        // TODO: Use the input device configuration to control this behavior more finely.
2391        if (getDevice()->isExternal()) {
2392            policyFlags |= POLICY_FLAG_WAKE_DROPPED;
2393        }
2394    }
2395
2396    // Process touches and virtual keys.
2397    TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2398    if (touchResult == DISPATCH_TOUCH) {
2399        detectGestures(when);
2400        dispatchTouches(when, policyFlags);
2401    }
2402
2403    // Copy current touch to last touch in preparation for the next cycle.
2404    if (touchResult == DROP_STROKE) {
2405        mLastTouch.clear();
2406    } else {
2407        mLastTouch.copyFrom(*savedTouch);
2408    }
2409}
2410
2411TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2412        nsecs_t when, uint32_t policyFlags) {
2413    int32_t keyEventAction, keyEventFlags;
2414    int32_t keyCode, scanCode, downTime;
2415    TouchResult touchResult;
2416
2417    { // acquire lock
2418        AutoMutex _l(mLock);
2419
2420        // Update surface size and orientation, including virtual key positions.
2421        if (! configureSurfaceLocked()) {
2422            return DROP_STROKE;
2423        }
2424
2425        // Check for virtual key press.
2426        if (mLocked.currentVirtualKey.down) {
2427            if (mCurrentTouch.pointerCount == 0) {
2428                // Pointer went up while virtual key was down.
2429                mLocked.currentVirtualKey.down = false;
2430#if DEBUG_VIRTUAL_KEYS
2431                LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
2432                        mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
2433#endif
2434                keyEventAction = AKEY_EVENT_ACTION_UP;
2435                keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2436                touchResult = SKIP_TOUCH;
2437                goto DispatchVirtualKey;
2438            }
2439
2440            if (mCurrentTouch.pointerCount == 1) {
2441                int32_t x = mCurrentTouch.pointers[0].x;
2442                int32_t y = mCurrentTouch.pointers[0].y;
2443                const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2444                if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
2445                    // Pointer is still within the space of the virtual key.
2446                    return SKIP_TOUCH;
2447                }
2448            }
2449
2450            // Pointer left virtual key area or another pointer also went down.
2451            // Send key cancellation and drop the stroke so subsequent motions will be
2452            // considered fresh downs.  This is useful when the user swipes away from the
2453            // virtual key area into the main display surface.
2454            mLocked.currentVirtualKey.down = false;
2455#if DEBUG_VIRTUAL_KEYS
2456            LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
2457                    mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
2458#endif
2459            keyEventAction = AKEY_EVENT_ACTION_UP;
2460            keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2461                    | AKEY_EVENT_FLAG_CANCELED;
2462
2463            // Check whether the pointer moved inside the display area where we should
2464            // start a new stroke.
2465            int32_t x = mCurrentTouch.pointers[0].x;
2466            int32_t y = mCurrentTouch.pointers[0].y;
2467            if (isPointInsideSurfaceLocked(x, y)) {
2468                mLastTouch.clear();
2469                touchResult = DISPATCH_TOUCH;
2470            } else {
2471                touchResult = DROP_STROKE;
2472            }
2473        } else {
2474            if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2475                // Pointer just went down.  Handle off-screen touches, if needed.
2476                int32_t x = mCurrentTouch.pointers[0].x;
2477                int32_t y = mCurrentTouch.pointers[0].y;
2478                if (! isPointInsideSurfaceLocked(x, y)) {
2479                    // If exactly one pointer went down, check for virtual key hit.
2480                    // Otherwise we will drop the entire stroke.
2481                    if (mCurrentTouch.pointerCount == 1) {
2482                        const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2483                        if (virtualKey) {
2484                            if (mContext->shouldDropVirtualKey(when, getDevice(),
2485                                    virtualKey->keyCode, virtualKey->scanCode)) {
2486                                return DROP_STROKE;
2487                            }
2488
2489                            mLocked.currentVirtualKey.down = true;
2490                            mLocked.currentVirtualKey.downTime = when;
2491                            mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2492                            mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
2493#if DEBUG_VIRTUAL_KEYS
2494                            LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
2495                                    mLocked.currentVirtualKey.keyCode,
2496                                    mLocked.currentVirtualKey.scanCode);
2497#endif
2498                            keyEventAction = AKEY_EVENT_ACTION_DOWN;
2499                            keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2500                                    | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2501                            touchResult = SKIP_TOUCH;
2502                            goto DispatchVirtualKey;
2503                        }
2504                    }
2505                    return DROP_STROKE;
2506                }
2507            }
2508            return DISPATCH_TOUCH;
2509        }
2510
2511    DispatchVirtualKey:
2512        // Collect remaining state needed to dispatch virtual key.
2513        keyCode = mLocked.currentVirtualKey.keyCode;
2514        scanCode = mLocked.currentVirtualKey.scanCode;
2515        downTime = mLocked.currentVirtualKey.downTime;
2516    } // release lock
2517
2518    // Dispatch virtual key.
2519    int32_t metaState = mContext->getGlobalMetaState();
2520    policyFlags |= POLICY_FLAG_VIRTUAL;
2521    getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
2522            keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2523    return touchResult;
2524}
2525
2526void TouchInputMapper::detectGestures(nsecs_t when) {
2527    // Disable all virtual key touches that happen within a short time interval of the
2528    // most recent touch.  The idea is to filter out stray virtual key presses when
2529    // interacting with the touch screen.
2530    //
2531    // Problems we're trying to solve:
2532    //
2533    // 1. While scrolling a list or dragging the window shade, the user swipes down into a
2534    //    virtual key area that is implemented by a separate touch panel and accidentally
2535    //    triggers a virtual key.
2536    //
2537    // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
2538    //    area and accidentally triggers a virtual key.  This often happens when virtual keys
2539    //    are layed out below the screen near to where the on screen keyboard's space bar
2540    //    is displayed.
2541    if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
2542        mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime);
2543    }
2544}
2545
2546void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2547    uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2548    uint32_t lastPointerCount = mLastTouch.pointerCount;
2549    if (currentPointerCount == 0 && lastPointerCount == 0) {
2550        return; // nothing to do!
2551    }
2552
2553    BitSet32 currentIdBits = mCurrentTouch.idBits;
2554    BitSet32 lastIdBits = mLastTouch.idBits;
2555
2556    if (currentIdBits == lastIdBits) {
2557        // No pointer id changes so this is a move event.
2558        // The dispatcher takes care of batching moves so we don't have to deal with that here.
2559        int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
2560        dispatchTouch(when, policyFlags, & mCurrentTouch,
2561                currentIdBits, -1, currentPointerCount, motionEventAction);
2562    } else {
2563        // There may be pointers going up and pointers going down and pointers moving
2564        // all at the same time.
2565        BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2566        BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2567        BitSet32 activeIdBits(lastIdBits.value);
2568        uint32_t pointerCount = lastPointerCount;
2569
2570        // Produce an intermediate representation of the touch data that consists of the
2571        // old location of pointers that have just gone up and the new location of pointers that
2572        // have just moved but omits the location of pointers that have just gone down.
2573        TouchData interimTouch;
2574        interimTouch.copyFrom(mLastTouch);
2575
2576        BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
2577        bool moveNeeded = false;
2578        while (!moveIdBits.isEmpty()) {
2579            uint32_t moveId = moveIdBits.firstMarkedBit();
2580            moveIdBits.clearBit(moveId);
2581
2582            int32_t oldIndex = mLastTouch.idToIndex[moveId];
2583            int32_t newIndex = mCurrentTouch.idToIndex[moveId];
2584            if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
2585                interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
2586                moveNeeded = true;
2587            }
2588        }
2589
2590        // Dispatch pointer up events using the interim pointer locations.
2591        while (!upIdBits.isEmpty()) {
2592            uint32_t upId = upIdBits.firstMarkedBit();
2593            upIdBits.clearBit(upId);
2594            BitSet32 oldActiveIdBits = activeIdBits;
2595            activeIdBits.clearBit(upId);
2596
2597            int32_t motionEventAction;
2598            if (activeIdBits.isEmpty()) {
2599                motionEventAction = AMOTION_EVENT_ACTION_UP;
2600            } else {
2601                motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
2602            }
2603
2604            dispatchTouch(when, policyFlags, &interimTouch,
2605                    oldActiveIdBits, upId, pointerCount, motionEventAction);
2606            pointerCount -= 1;
2607        }
2608
2609        // Dispatch move events if any of the remaining pointers moved from their old locations.
2610        // Although applications receive new locations as part of individual pointer up
2611        // events, they do not generally handle them except when presented in a move event.
2612        if (moveNeeded) {
2613            dispatchTouch(when, policyFlags, &mCurrentTouch,
2614                    activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
2615        }
2616
2617        // Dispatch pointer down events using the new pointer locations.
2618        while (!downIdBits.isEmpty()) {
2619            uint32_t downId = downIdBits.firstMarkedBit();
2620            downIdBits.clearBit(downId);
2621            BitSet32 oldActiveIdBits = activeIdBits;
2622            activeIdBits.markBit(downId);
2623
2624            int32_t motionEventAction;
2625            if (oldActiveIdBits.isEmpty()) {
2626                motionEventAction = AMOTION_EVENT_ACTION_DOWN;
2627                mDownTime = when;
2628            } else {
2629                motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
2630            }
2631
2632            pointerCount += 1;
2633            dispatchTouch(when, policyFlags, &mCurrentTouch,
2634                    activeIdBits, downId, pointerCount, motionEventAction);
2635        }
2636    }
2637}
2638
2639void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
2640        TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
2641        int32_t motionEventAction) {
2642    int32_t pointerIds[MAX_POINTERS];
2643    PointerCoords pointerCoords[MAX_POINTERS];
2644    int32_t motionEventEdgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
2645    float xPrecision, yPrecision;
2646
2647    { // acquire lock
2648        AutoMutex _l(mLock);
2649
2650        // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2651        // display coordinates (PointerCoords) and adjust for display orientation.
2652        for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
2653            uint32_t id = idBits.firstMarkedBit();
2654            idBits.clearBit(id);
2655            uint32_t inIndex = touch->idToIndex[id];
2656
2657            const PointerData& in = touch->pointers[inIndex];
2658
2659            // ToolMajor and ToolMinor
2660            float toolMajor, toolMinor;
2661            switch (mCalibration.toolSizeCalibration) {
2662            case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
2663                toolMajor = in.toolMajor * mLocked.geometricScale;
2664                if (mRawAxes.toolMinor.valid) {
2665                    toolMinor = in.toolMinor * mLocked.geometricScale;
2666                } else {
2667                    toolMinor = toolMajor;
2668                }
2669                break;
2670            case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
2671                toolMajor = in.toolMajor != 0
2672                        ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
2673                        : 0;
2674                if (mRawAxes.toolMinor.valid) {
2675                    toolMinor = in.toolMinor != 0
2676                            ? in.toolMinor * mLocked.toolSizeLinearScale
2677                                    + mLocked.toolSizeLinearBias
2678                            : 0;
2679                } else {
2680                    toolMinor = toolMajor;
2681                }
2682                break;
2683            case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2684                if (in.toolMajor != 0) {
2685                    float diameter = sqrtf(in.toolMajor
2686                            * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
2687                    toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
2688                } else {
2689                    toolMajor = 0;
2690                }
2691                toolMinor = toolMajor;
2692                break;
2693            default:
2694                toolMajor = 0;
2695                toolMinor = 0;
2696                break;
2697            }
2698
2699            if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
2700                toolMajor /= pointerCount;
2701                toolMinor /= pointerCount;
2702            }
2703
2704            // Pressure
2705            float rawPressure;
2706            switch (mCalibration.pressureSource) {
2707            case Calibration::PRESSURE_SOURCE_PRESSURE:
2708                rawPressure = in.pressure;
2709                break;
2710            case Calibration::PRESSURE_SOURCE_TOUCH:
2711                rawPressure = in.touchMajor;
2712                break;
2713            default:
2714                rawPressure = 0;
2715            }
2716
2717            float pressure;
2718            switch (mCalibration.pressureCalibration) {
2719            case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2720            case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2721                pressure = rawPressure * mLocked.pressureScale;
2722                break;
2723            default:
2724                pressure = 1;
2725                break;
2726            }
2727
2728            // TouchMajor and TouchMinor
2729            float touchMajor, touchMinor;
2730            switch (mCalibration.touchSizeCalibration) {
2731            case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
2732                touchMajor = in.touchMajor * mLocked.geometricScale;
2733                if (mRawAxes.touchMinor.valid) {
2734                    touchMinor = in.touchMinor * mLocked.geometricScale;
2735                } else {
2736                    touchMinor = touchMajor;
2737                }
2738                break;
2739            case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
2740                touchMajor = toolMajor * pressure;
2741                touchMinor = toolMinor * pressure;
2742                break;
2743            default:
2744                touchMajor = 0;
2745                touchMinor = 0;
2746                break;
2747            }
2748
2749            if (touchMajor > toolMajor) {
2750                touchMajor = toolMajor;
2751            }
2752            if (touchMinor > toolMinor) {
2753                touchMinor = toolMinor;
2754            }
2755
2756            // Size
2757            float size;
2758            switch (mCalibration.sizeCalibration) {
2759            case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2760                float rawSize = mRawAxes.toolMinor.valid
2761                        ? avg(in.toolMajor, in.toolMinor)
2762                        : in.toolMajor;
2763                size = rawSize * mLocked.sizeScale;
2764                break;
2765            }
2766            default:
2767                size = 0;
2768                break;
2769            }
2770
2771            // Orientation
2772            float orientation;
2773            switch (mCalibration.orientationCalibration) {
2774            case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2775                orientation = in.orientation * mLocked.orientationScale;
2776                break;
2777            case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
2778                int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
2779                int32_t c2 = signExtendNybble(in.orientation & 0x0f);
2780                if (c1 != 0 || c2 != 0) {
2781                    orientation = atan2f(c1, c2) * 0.5f;
2782                    float scale = 1.0f + pythag(c1, c2) / 16.0f;
2783                    touchMajor *= scale;
2784                    touchMinor /= scale;
2785                    toolMajor *= scale;
2786                    toolMinor /= scale;
2787                } else {
2788                    orientation = 0;
2789                }
2790                break;
2791            }
2792            default:
2793                orientation = 0;
2794            }
2795
2796            // X and Y
2797            // Adjust coords for surface orientation.
2798            float x, y;
2799            switch (mLocked.surfaceOrientation) {
2800            case DISPLAY_ORIENTATION_90:
2801                x = float(in.y - mRawAxes.y.minValue) * mLocked.yScale;
2802                y = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale;
2803                orientation -= M_PI_2;
2804                if (orientation < - M_PI_2) {
2805                    orientation += M_PI;
2806                }
2807                break;
2808            case DISPLAY_ORIENTATION_180:
2809                x = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale;
2810                y = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale;
2811                break;
2812            case DISPLAY_ORIENTATION_270:
2813                x = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale;
2814                y = float(in.x - mRawAxes.x.minValue) * mLocked.xScale;
2815                orientation += M_PI_2;
2816                if (orientation > M_PI_2) {
2817                    orientation -= M_PI;
2818                }
2819                break;
2820            default:
2821                x = float(in.x - mRawAxes.x.minValue) * mLocked.xScale;
2822                y = float(in.y - mRawAxes.y.minValue) * mLocked.yScale;
2823                break;
2824            }
2825
2826            // Write output coords.
2827            PointerCoords& out = pointerCoords[outIndex];
2828            out.clear();
2829            out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
2830            out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
2831            out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
2832            out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
2833            out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
2834            out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
2835            out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
2836            out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
2837            out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
2838
2839            pointerIds[outIndex] = int32_t(id);
2840
2841            if (id == changedId) {
2842                motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
2843            }
2844        }
2845
2846        // Check edge flags by looking only at the first pointer since the flags are
2847        // global to the event.
2848        if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
2849            uint32_t inIndex = touch->idToIndex[pointerIds[0]];
2850            const PointerData& in = touch->pointers[inIndex];
2851
2852            if (in.x <= mRawAxes.x.minValue) {
2853                motionEventEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_LEFT,
2854                        mLocked.surfaceOrientation);
2855            } else if (in.x >= mRawAxes.x.maxValue) {
2856                motionEventEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_RIGHT,
2857                        mLocked.surfaceOrientation);
2858            }
2859            if (in.y <= mRawAxes.y.minValue) {
2860                motionEventEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_TOP,
2861                        mLocked.surfaceOrientation);
2862            } else if (in.y >= mRawAxes.y.maxValue) {
2863                motionEventEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_BOTTOM,
2864                        mLocked.surfaceOrientation);
2865            }
2866        }
2867
2868        xPrecision = mLocked.orientedXPrecision;
2869        yPrecision = mLocked.orientedYPrecision;
2870    } // release lock
2871
2872    getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
2873            motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
2874            pointerCount, pointerIds, pointerCoords,
2875            xPrecision, yPrecision, mDownTime);
2876}
2877
2878bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
2879    return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2880            && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
2881}
2882
2883const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2884        int32_t x, int32_t y) {
2885    size_t numVirtualKeys = mLocked.virtualKeys.size();
2886    for (size_t i = 0; i < numVirtualKeys; i++) {
2887        const VirtualKey& virtualKey = mLocked.virtualKeys[i];
2888
2889#if DEBUG_VIRTUAL_KEYS
2890        LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2891                "left=%d, top=%d, right=%d, bottom=%d",
2892                x, y,
2893                virtualKey.keyCode, virtualKey.scanCode,
2894                virtualKey.hitLeft, virtualKey.hitTop,
2895                virtualKey.hitRight, virtualKey.hitBottom);
2896#endif
2897
2898        if (virtualKey.isHit(x, y)) {
2899            return & virtualKey;
2900        }
2901    }
2902
2903    return NULL;
2904}
2905
2906void TouchInputMapper::calculatePointerIds() {
2907    uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2908    uint32_t lastPointerCount = mLastTouch.pointerCount;
2909
2910    if (currentPointerCount == 0) {
2911        // No pointers to assign.
2912        mCurrentTouch.idBits.clear();
2913    } else if (lastPointerCount == 0) {
2914        // All pointers are new.
2915        mCurrentTouch.idBits.clear();
2916        for (uint32_t i = 0; i < currentPointerCount; i++) {
2917            mCurrentTouch.pointers[i].id = i;
2918            mCurrentTouch.idToIndex[i] = i;
2919            mCurrentTouch.idBits.markBit(i);
2920        }
2921    } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2922        // Only one pointer and no change in count so it must have the same id as before.
2923        uint32_t id = mLastTouch.pointers[0].id;
2924        mCurrentTouch.pointers[0].id = id;
2925        mCurrentTouch.idToIndex[id] = 0;
2926        mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2927    } else {
2928        // General case.
2929        // We build a heap of squared euclidean distances between current and last pointers
2930        // associated with the current and last pointer indices.  Then, we find the best
2931        // match (by distance) for each current pointer.
2932        PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2933
2934        uint32_t heapSize = 0;
2935        for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2936                currentPointerIndex++) {
2937            for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2938                    lastPointerIndex++) {
2939                int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2940                        - mLastTouch.pointers[lastPointerIndex].x;
2941                int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2942                        - mLastTouch.pointers[lastPointerIndex].y;
2943
2944                uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2945
2946                // Insert new element into the heap (sift up).
2947                heap[heapSize].currentPointerIndex = currentPointerIndex;
2948                heap[heapSize].lastPointerIndex = lastPointerIndex;
2949                heap[heapSize].distance = distance;
2950                heapSize += 1;
2951            }
2952        }
2953
2954        // Heapify
2955        for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2956            startIndex -= 1;
2957            for (uint32_t parentIndex = startIndex; ;) {
2958                uint32_t childIndex = parentIndex * 2 + 1;
2959                if (childIndex >= heapSize) {
2960                    break;
2961                }
2962
2963                if (childIndex + 1 < heapSize
2964                        && heap[childIndex + 1].distance < heap[childIndex].distance) {
2965                    childIndex += 1;
2966                }
2967
2968                if (heap[parentIndex].distance <= heap[childIndex].distance) {
2969                    break;
2970                }
2971
2972                swap(heap[parentIndex], heap[childIndex]);
2973                parentIndex = childIndex;
2974            }
2975        }
2976
2977#if DEBUG_POINTER_ASSIGNMENT
2978        LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2979        for (size_t i = 0; i < heapSize; i++) {
2980            LOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
2981                    i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2982                    heap[i].distance);
2983        }
2984#endif
2985
2986        // Pull matches out by increasing order of distance.
2987        // To avoid reassigning pointers that have already been matched, the loop keeps track
2988        // of which last and current pointers have been matched using the matchedXXXBits variables.
2989        // It also tracks the used pointer id bits.
2990        BitSet32 matchedLastBits(0);
2991        BitSet32 matchedCurrentBits(0);
2992        BitSet32 usedIdBits(0);
2993        bool first = true;
2994        for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2995            for (;;) {
2996                if (first) {
2997                    // The first time through the loop, we just consume the root element of
2998                    // the heap (the one with smallest distance).
2999                    first = false;
3000                } else {
3001                    // Previous iterations consumed the root element of the heap.
3002                    // Pop root element off of the heap (sift down).
3003                    heapSize -= 1;
3004                    assert(heapSize > 0);
3005
3006                    // Sift down.
3007                    heap[0] = heap[heapSize];
3008                    for (uint32_t parentIndex = 0; ;) {
3009                        uint32_t childIndex = parentIndex * 2 + 1;
3010                        if (childIndex >= heapSize) {
3011                            break;
3012                        }
3013
3014                        if (childIndex + 1 < heapSize
3015                                && heap[childIndex + 1].distance < heap[childIndex].distance) {
3016                            childIndex += 1;
3017                        }
3018
3019                        if (heap[parentIndex].distance <= heap[childIndex].distance) {
3020                            break;
3021                        }
3022
3023                        swap(heap[parentIndex], heap[childIndex]);
3024                        parentIndex = childIndex;
3025                    }
3026
3027#if DEBUG_POINTER_ASSIGNMENT
3028                    LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
3029                    for (size_t i = 0; i < heapSize; i++) {
3030                        LOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
3031                                i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
3032                                heap[i].distance);
3033                    }
3034#endif
3035                }
3036
3037                uint32_t currentPointerIndex = heap[0].currentPointerIndex;
3038                if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
3039
3040                uint32_t lastPointerIndex = heap[0].lastPointerIndex;
3041                if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
3042
3043                matchedCurrentBits.markBit(currentPointerIndex);
3044                matchedLastBits.markBit(lastPointerIndex);
3045
3046                uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
3047                mCurrentTouch.pointers[currentPointerIndex].id = id;
3048                mCurrentTouch.idToIndex[id] = currentPointerIndex;
3049                usedIdBits.markBit(id);
3050
3051#if DEBUG_POINTER_ASSIGNMENT
3052                LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
3053                        lastPointerIndex, currentPointerIndex, id, heap[0].distance);
3054#endif
3055                break;
3056            }
3057        }
3058
3059        // Assign fresh ids to new pointers.
3060        if (currentPointerCount > lastPointerCount) {
3061            for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
3062                uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
3063                uint32_t id = usedIdBits.firstUnmarkedBit();
3064
3065                mCurrentTouch.pointers[currentPointerIndex].id = id;
3066                mCurrentTouch.idToIndex[id] = currentPointerIndex;
3067                usedIdBits.markBit(id);
3068
3069#if DEBUG_POINTER_ASSIGNMENT
3070                LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
3071                        currentPointerIndex, id);
3072#endif
3073
3074                if (--i == 0) break; // done
3075                matchedCurrentBits.markBit(currentPointerIndex);
3076            }
3077        }
3078
3079        // Fix id bits.
3080        mCurrentTouch.idBits = usedIdBits;
3081    }
3082}
3083
3084/* Special hack for devices that have bad screen data: if one of the
3085 * points has moved more than a screen height from the last position,
3086 * then drop it. */
3087bool TouchInputMapper::applyBadTouchFilter() {
3088    uint32_t pointerCount = mCurrentTouch.pointerCount;
3089
3090    // Nothing to do if there are no points.
3091    if (pointerCount == 0) {
3092        return false;
3093    }
3094
3095    // Don't do anything if a finger is going down or up.  We run
3096    // here before assigning pointer IDs, so there isn't a good
3097    // way to do per-finger matching.
3098    if (pointerCount != mLastTouch.pointerCount) {
3099        return false;
3100    }
3101
3102    // We consider a single movement across more than a 7/16 of
3103    // the long size of the screen to be bad.  This was a magic value
3104    // determined by looking at the maximum distance it is feasible
3105    // to actually move in one sample.
3106    int32_t maxDeltaY = (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1) * 7 / 16;
3107
3108    // XXX The original code in InputDevice.java included commented out
3109    //     code for testing the X axis.  Note that when we drop a point
3110    //     we don't actually restore the old X either.  Strange.
3111    //     The old code also tries to track when bad points were previously
3112    //     detected but it turns out that due to the placement of a "break"
3113    //     at the end of the loop, we never set mDroppedBadPoint to true
3114    //     so it is effectively dead code.
3115    // Need to figure out if the old code is busted or just overcomplicated
3116    // but working as intended.
3117
3118    // Look through all new points and see if any are farther than
3119    // acceptable from all previous points.
3120    for (uint32_t i = pointerCount; i-- > 0; ) {
3121        int32_t y = mCurrentTouch.pointers[i].y;
3122        int32_t closestY = INT_MAX;
3123        int32_t closestDeltaY = 0;
3124
3125#if DEBUG_HACKS
3126        LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
3127#endif
3128
3129        for (uint32_t j = pointerCount; j-- > 0; ) {
3130            int32_t lastY = mLastTouch.pointers[j].y;
3131            int32_t deltaY = abs(y - lastY);
3132
3133#if DEBUG_HACKS
3134            LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
3135                    j, lastY, deltaY);
3136#endif
3137
3138            if (deltaY < maxDeltaY) {
3139                goto SkipSufficientlyClosePoint;
3140            }
3141            if (deltaY < closestDeltaY) {
3142                closestDeltaY = deltaY;
3143                closestY = lastY;
3144            }
3145        }
3146
3147        // Must not have found a close enough match.
3148#if DEBUG_HACKS
3149        LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
3150                i, y, closestY, closestDeltaY, maxDeltaY);
3151#endif
3152
3153        mCurrentTouch.pointers[i].y = closestY;
3154        return true; // XXX original code only corrects one point
3155
3156    SkipSufficientlyClosePoint: ;
3157    }
3158
3159    // No change.
3160    return false;
3161}
3162
3163/* Special hack for devices that have bad screen data: drop points where
3164 * the coordinate value for one axis has jumped to the other pointer's location.
3165 */
3166bool TouchInputMapper::applyJumpyTouchFilter() {
3167    uint32_t pointerCount = mCurrentTouch.pointerCount;
3168    if (mLastTouch.pointerCount != pointerCount) {
3169#if DEBUG_HACKS
3170        LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
3171                mLastTouch.pointerCount, pointerCount);
3172        for (uint32_t i = 0; i < pointerCount; i++) {
3173            LOGD("  Pointer %d (%d, %d)", i,
3174                    mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3175        }
3176#endif
3177
3178        if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
3179            if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
3180                // Just drop the first few events going from 1 to 2 pointers.
3181                // They're bad often enough that they're not worth considering.
3182                mCurrentTouch.pointerCount = 1;
3183                mJumpyTouchFilter.jumpyPointsDropped += 1;
3184
3185#if DEBUG_HACKS
3186                LOGD("JumpyTouchFilter: Pointer 2 dropped");
3187#endif
3188                return true;
3189            } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
3190                // The event when we go from 2 -> 1 tends to be messed up too
3191                mCurrentTouch.pointerCount = 2;
3192                mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
3193                mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
3194                mJumpyTouchFilter.jumpyPointsDropped += 1;
3195
3196#if DEBUG_HACKS
3197                for (int32_t i = 0; i < 2; i++) {
3198                    LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
3199                            mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3200                }
3201#endif
3202                return true;
3203            }
3204        }
3205        // Reset jumpy points dropped on other transitions or if limit exceeded.
3206        mJumpyTouchFilter.jumpyPointsDropped = 0;
3207
3208#if DEBUG_HACKS
3209        LOGD("JumpyTouchFilter: Transition - drop limit reset");
3210#endif
3211        return false;
3212    }
3213
3214    // We have the same number of pointers as last time.
3215    // A 'jumpy' point is one where the coordinate value for one axis
3216    // has jumped to the other pointer's location. No need to do anything
3217    // else if we only have one pointer.
3218    if (pointerCount < 2) {
3219        return false;
3220    }
3221
3222    if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
3223        int jumpyEpsilon = (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1) / JUMPY_EPSILON_DIVISOR;
3224
3225        // We only replace the single worst jumpy point as characterized by pointer distance
3226        // in a single axis.
3227        int32_t badPointerIndex = -1;
3228        int32_t badPointerReplacementIndex = -1;
3229        int32_t badPointerDistance = INT_MIN; // distance to be corrected
3230
3231        for (uint32_t i = pointerCount; i-- > 0; ) {
3232            int32_t x = mCurrentTouch.pointers[i].x;
3233            int32_t y = mCurrentTouch.pointers[i].y;
3234
3235#if DEBUG_HACKS
3236            LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
3237#endif
3238
3239            // Check if a touch point is too close to another's coordinates
3240            bool dropX = false, dropY = false;
3241            for (uint32_t j = 0; j < pointerCount; j++) {
3242                if (i == j) {
3243                    continue;
3244                }
3245
3246                if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
3247                    dropX = true;
3248                    break;
3249                }
3250
3251                if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
3252                    dropY = true;
3253                    break;
3254                }
3255            }
3256            if (! dropX && ! dropY) {
3257                continue; // not jumpy
3258            }
3259
3260            // Find a replacement candidate by comparing with older points on the
3261            // complementary (non-jumpy) axis.
3262            int32_t distance = INT_MIN; // distance to be corrected
3263            int32_t replacementIndex = -1;
3264
3265            if (dropX) {
3266                // X looks too close.  Find an older replacement point with a close Y.
3267                int32_t smallestDeltaY = INT_MAX;
3268                for (uint32_t j = 0; j < pointerCount; j++) {
3269                    int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
3270                    if (deltaY < smallestDeltaY) {
3271                        smallestDeltaY = deltaY;
3272                        replacementIndex = j;
3273                    }
3274                }
3275                distance = abs(x - mLastTouch.pointers[replacementIndex].x);
3276            } else {
3277                // Y looks too close.  Find an older replacement point with a close X.
3278                int32_t smallestDeltaX = INT_MAX;
3279                for (uint32_t j = 0; j < pointerCount; j++) {
3280                    int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
3281                    if (deltaX < smallestDeltaX) {
3282                        smallestDeltaX = deltaX;
3283                        replacementIndex = j;
3284                    }
3285                }
3286                distance = abs(y - mLastTouch.pointers[replacementIndex].y);
3287            }
3288
3289            // If replacing this pointer would correct a worse error than the previous ones
3290            // considered, then use this replacement instead.
3291            if (distance > badPointerDistance) {
3292                badPointerIndex = i;
3293                badPointerReplacementIndex = replacementIndex;
3294                badPointerDistance = distance;
3295            }
3296        }
3297
3298        // Correct the jumpy pointer if one was found.
3299        if (badPointerIndex >= 0) {
3300#if DEBUG_HACKS
3301            LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
3302                    badPointerIndex,
3303                    mLastTouch.pointers[badPointerReplacementIndex].x,
3304                    mLastTouch.pointers[badPointerReplacementIndex].y);
3305#endif
3306
3307            mCurrentTouch.pointers[badPointerIndex].x =
3308                    mLastTouch.pointers[badPointerReplacementIndex].x;
3309            mCurrentTouch.pointers[badPointerIndex].y =
3310                    mLastTouch.pointers[badPointerReplacementIndex].y;
3311            mJumpyTouchFilter.jumpyPointsDropped += 1;
3312            return true;
3313        }
3314    }
3315
3316    mJumpyTouchFilter.jumpyPointsDropped = 0;
3317    return false;
3318}
3319
3320/* Special hack for devices that have bad screen data: aggregate and
3321 * compute averages of the coordinate data, to reduce the amount of
3322 * jitter seen by applications. */
3323void TouchInputMapper::applyAveragingTouchFilter() {
3324    for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
3325        uint32_t id = mCurrentTouch.pointers[currentIndex].id;
3326        int32_t x = mCurrentTouch.pointers[currentIndex].x;
3327        int32_t y = mCurrentTouch.pointers[currentIndex].y;
3328        int32_t pressure;
3329        switch (mCalibration.pressureSource) {
3330        case Calibration::PRESSURE_SOURCE_PRESSURE:
3331            pressure = mCurrentTouch.pointers[currentIndex].pressure;
3332            break;
3333        case Calibration::PRESSURE_SOURCE_TOUCH:
3334            pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
3335            break;
3336        default:
3337            pressure = 1;
3338            break;
3339        }
3340
3341        if (mLastTouch.idBits.hasBit(id)) {
3342            // Pointer was down before and is still down now.
3343            // Compute average over history trace.
3344            uint32_t start = mAveragingTouchFilter.historyStart[id];
3345            uint32_t end = mAveragingTouchFilter.historyEnd[id];
3346
3347            int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
3348            int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
3349            uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
3350
3351#if DEBUG_HACKS
3352            LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
3353                    id, distance);
3354#endif
3355
3356            if (distance < AVERAGING_DISTANCE_LIMIT) {
3357                // Increment end index in preparation for recording new historical data.
3358                end += 1;
3359                if (end > AVERAGING_HISTORY_SIZE) {
3360                    end = 0;
3361                }
3362
3363                // If the end index has looped back to the start index then we have filled
3364                // the historical trace up to the desired size so we drop the historical
3365                // data at the start of the trace.
3366                if (end == start) {
3367                    start += 1;
3368                    if (start > AVERAGING_HISTORY_SIZE) {
3369                        start = 0;
3370                    }
3371                }
3372
3373                // Add the raw data to the historical trace.
3374                mAveragingTouchFilter.historyStart[id] = start;
3375                mAveragingTouchFilter.historyEnd[id] = end;
3376                mAveragingTouchFilter.historyData[end].pointers[id].x = x;
3377                mAveragingTouchFilter.historyData[end].pointers[id].y = y;
3378                mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
3379
3380                // Average over all historical positions in the trace by total pressure.
3381                int32_t averagedX = 0;
3382                int32_t averagedY = 0;
3383                int32_t totalPressure = 0;
3384                for (;;) {
3385                    int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
3386                    int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
3387                    int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
3388                            .pointers[id].pressure;
3389
3390                    averagedX += historicalX * historicalPressure;
3391                    averagedY += historicalY * historicalPressure;
3392                    totalPressure += historicalPressure;
3393
3394                    if (start == end) {
3395                        break;
3396                    }
3397
3398                    start += 1;
3399                    if (start > AVERAGING_HISTORY_SIZE) {
3400                        start = 0;
3401                    }
3402                }
3403
3404                if (totalPressure != 0) {
3405                    averagedX /= totalPressure;
3406                    averagedY /= totalPressure;
3407
3408#if DEBUG_HACKS
3409                    LOGD("AveragingTouchFilter: Pointer id %d - "
3410                            "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
3411                            averagedX, averagedY);
3412#endif
3413
3414                    mCurrentTouch.pointers[currentIndex].x = averagedX;
3415                    mCurrentTouch.pointers[currentIndex].y = averagedY;
3416                }
3417            } else {
3418#if DEBUG_HACKS
3419                LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
3420#endif
3421            }
3422        } else {
3423#if DEBUG_HACKS
3424            LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
3425#endif
3426        }
3427
3428        // Reset pointer history.
3429        mAveragingTouchFilter.historyStart[id] = 0;
3430        mAveragingTouchFilter.historyEnd[id] = 0;
3431        mAveragingTouchFilter.historyData[0].pointers[id].x = x;
3432        mAveragingTouchFilter.historyData[0].pointers[id].y = y;
3433        mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
3434    }
3435}
3436
3437int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
3438    { // acquire lock
3439        AutoMutex _l(mLock);
3440
3441        if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
3442            return AKEY_STATE_VIRTUAL;
3443        }
3444
3445        size_t numVirtualKeys = mLocked.virtualKeys.size();
3446        for (size_t i = 0; i < numVirtualKeys; i++) {
3447            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
3448            if (virtualKey.keyCode == keyCode) {
3449                return AKEY_STATE_UP;
3450            }
3451        }
3452    } // release lock
3453
3454    return AKEY_STATE_UNKNOWN;
3455}
3456
3457int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
3458    { // acquire lock
3459        AutoMutex _l(mLock);
3460
3461        if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
3462            return AKEY_STATE_VIRTUAL;
3463        }
3464
3465        size_t numVirtualKeys = mLocked.virtualKeys.size();
3466        for (size_t i = 0; i < numVirtualKeys; i++) {
3467            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
3468            if (virtualKey.scanCode == scanCode) {
3469                return AKEY_STATE_UP;
3470            }
3471        }
3472    } // release lock
3473
3474    return AKEY_STATE_UNKNOWN;
3475}
3476
3477bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3478        const int32_t* keyCodes, uint8_t* outFlags) {
3479    { // acquire lock
3480        AutoMutex _l(mLock);
3481
3482        size_t numVirtualKeys = mLocked.virtualKeys.size();
3483        for (size_t i = 0; i < numVirtualKeys; i++) {
3484            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
3485
3486            for (size_t i = 0; i < numCodes; i++) {
3487                if (virtualKey.keyCode == keyCodes[i]) {
3488                    outFlags[i] = 1;
3489                }
3490            }
3491        }
3492    } // release lock
3493
3494    return true;
3495}
3496
3497
3498// --- SingleTouchInputMapper ---
3499
3500SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
3501        TouchInputMapper(device) {
3502    initialize();
3503}
3504
3505SingleTouchInputMapper::~SingleTouchInputMapper() {
3506}
3507
3508void SingleTouchInputMapper::initialize() {
3509    mAccumulator.clear();
3510
3511    mDown = false;
3512    mX = 0;
3513    mY = 0;
3514    mPressure = 0; // default to 0 for devices that don't report pressure
3515    mToolWidth = 0; // default to 0 for devices that don't report tool width
3516}
3517
3518void SingleTouchInputMapper::reset() {
3519    TouchInputMapper::reset();
3520
3521    initialize();
3522 }
3523
3524void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3525    switch (rawEvent->type) {
3526    case EV_KEY:
3527        switch (rawEvent->scanCode) {
3528        case BTN_TOUCH:
3529            mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3530            mAccumulator.btnTouch = rawEvent->value != 0;
3531            // Don't sync immediately.  Wait until the next SYN_REPORT since we might
3532            // not have received valid position information yet.  This logic assumes that
3533            // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
3534            break;
3535        }
3536        break;
3537
3538    case EV_ABS:
3539        switch (rawEvent->scanCode) {
3540        case ABS_X:
3541            mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3542            mAccumulator.absX = rawEvent->value;
3543            break;
3544        case ABS_Y:
3545            mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3546            mAccumulator.absY = rawEvent->value;
3547            break;
3548        case ABS_PRESSURE:
3549            mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3550            mAccumulator.absPressure = rawEvent->value;
3551            break;
3552        case ABS_TOOL_WIDTH:
3553            mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3554            mAccumulator.absToolWidth = rawEvent->value;
3555            break;
3556        }
3557        break;
3558
3559    case EV_SYN:
3560        switch (rawEvent->scanCode) {
3561        case SYN_REPORT:
3562            sync(rawEvent->when);
3563            break;
3564        }
3565        break;
3566    }
3567}
3568
3569void SingleTouchInputMapper::sync(nsecs_t when) {
3570    uint32_t fields = mAccumulator.fields;
3571    if (fields == 0) {
3572        return; // no new state changes, so nothing to do
3573    }
3574
3575    if (fields & Accumulator::FIELD_BTN_TOUCH) {
3576        mDown = mAccumulator.btnTouch;
3577    }
3578
3579    if (fields & Accumulator::FIELD_ABS_X) {
3580        mX = mAccumulator.absX;
3581    }
3582
3583    if (fields & Accumulator::FIELD_ABS_Y) {
3584        mY = mAccumulator.absY;
3585    }
3586
3587    if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3588        mPressure = mAccumulator.absPressure;
3589    }
3590
3591    if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
3592        mToolWidth = mAccumulator.absToolWidth;
3593    }
3594
3595    mCurrentTouch.clear();
3596
3597    if (mDown) {
3598        mCurrentTouch.pointerCount = 1;
3599        mCurrentTouch.pointers[0].id = 0;
3600        mCurrentTouch.pointers[0].x = mX;
3601        mCurrentTouch.pointers[0].y = mY;
3602        mCurrentTouch.pointers[0].pressure = mPressure;
3603        mCurrentTouch.pointers[0].touchMajor = 0;
3604        mCurrentTouch.pointers[0].touchMinor = 0;
3605        mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3606        mCurrentTouch.pointers[0].toolMinor = mToolWidth;
3607        mCurrentTouch.pointers[0].orientation = 0;
3608        mCurrentTouch.idToIndex[0] = 0;
3609        mCurrentTouch.idBits.markBit(0);
3610    }
3611
3612    syncTouch(when, true);
3613
3614    mAccumulator.clear();
3615}
3616
3617void SingleTouchInputMapper::configureRawAxes() {
3618    TouchInputMapper::configureRawAxes();
3619
3620    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3621    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3622    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3623    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
3624}
3625
3626
3627// --- MultiTouchInputMapper ---
3628
3629MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
3630        TouchInputMapper(device) {
3631    initialize();
3632}
3633
3634MultiTouchInputMapper::~MultiTouchInputMapper() {
3635}
3636
3637void MultiTouchInputMapper::initialize() {
3638    mAccumulator.clear();
3639}
3640
3641void MultiTouchInputMapper::reset() {
3642    TouchInputMapper::reset();
3643
3644    initialize();
3645}
3646
3647void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3648    switch (rawEvent->type) {
3649    case EV_ABS: {
3650        uint32_t pointerIndex = mAccumulator.pointerCount;
3651        Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3652
3653        switch (rawEvent->scanCode) {
3654        case ABS_MT_POSITION_X:
3655            pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3656            pointer->absMTPositionX = rawEvent->value;
3657            break;
3658        case ABS_MT_POSITION_Y:
3659            pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3660            pointer->absMTPositionY = rawEvent->value;
3661            break;
3662        case ABS_MT_TOUCH_MAJOR:
3663            pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3664            pointer->absMTTouchMajor = rawEvent->value;
3665            break;
3666        case ABS_MT_TOUCH_MINOR:
3667            pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3668            pointer->absMTTouchMinor = rawEvent->value;
3669            break;
3670        case ABS_MT_WIDTH_MAJOR:
3671            pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3672            pointer->absMTWidthMajor = rawEvent->value;
3673            break;
3674        case ABS_MT_WIDTH_MINOR:
3675            pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3676            pointer->absMTWidthMinor = rawEvent->value;
3677            break;
3678        case ABS_MT_ORIENTATION:
3679            pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3680            pointer->absMTOrientation = rawEvent->value;
3681            break;
3682        case ABS_MT_TRACKING_ID:
3683            pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3684            pointer->absMTTrackingId = rawEvent->value;
3685            break;
3686        case ABS_MT_PRESSURE:
3687            pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3688            pointer->absMTPressure = rawEvent->value;
3689            break;
3690        }
3691        break;
3692    }
3693
3694    case EV_SYN:
3695        switch (rawEvent->scanCode) {
3696        case SYN_MT_REPORT: {
3697            // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3698            uint32_t pointerIndex = mAccumulator.pointerCount;
3699
3700            if (mAccumulator.pointers[pointerIndex].fields) {
3701                if (pointerIndex == MAX_POINTERS) {
3702                    LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3703                            MAX_POINTERS);
3704                } else {
3705                    pointerIndex += 1;
3706                    mAccumulator.pointerCount = pointerIndex;
3707                }
3708            }
3709
3710            mAccumulator.pointers[pointerIndex].clear();
3711            break;
3712        }
3713
3714        case SYN_REPORT:
3715            sync(rawEvent->when);
3716            break;
3717        }
3718        break;
3719    }
3720}
3721
3722void MultiTouchInputMapper::sync(nsecs_t when) {
3723    static const uint32_t REQUIRED_FIELDS =
3724            Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
3725
3726    uint32_t inCount = mAccumulator.pointerCount;
3727    uint32_t outCount = 0;
3728    bool havePointerIds = true;
3729
3730    mCurrentTouch.clear();
3731
3732    for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
3733        const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3734        uint32_t fields = inPointer.fields;
3735
3736        if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
3737            // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3738            // Drop this finger.
3739            continue;
3740        }
3741
3742        PointerData& outPointer = mCurrentTouch.pointers[outCount];
3743        outPointer.x = inPointer.absMTPositionX;
3744        outPointer.y = inPointer.absMTPositionY;
3745
3746        if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3747            if (inPointer.absMTPressure <= 0) {
3748                // Some devices send sync packets with X / Y but with a 0 pressure to indicate
3749                // a pointer going up.  Drop this finger.
3750                continue;
3751            }
3752            outPointer.pressure = inPointer.absMTPressure;
3753        } else {
3754            // Default pressure to 0 if absent.
3755            outPointer.pressure = 0;
3756        }
3757
3758        if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3759            if (inPointer.absMTTouchMajor <= 0) {
3760                // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3761                // a pointer going up.  Drop this finger.
3762                continue;
3763            }
3764            outPointer.touchMajor = inPointer.absMTTouchMajor;
3765        } else {
3766            // Default touch area to 0 if absent.
3767            outPointer.touchMajor = 0;
3768        }
3769
3770        if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3771            outPointer.touchMinor = inPointer.absMTTouchMinor;
3772        } else {
3773            // Assume touch area is circular.
3774            outPointer.touchMinor = outPointer.touchMajor;
3775        }
3776
3777        if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3778            outPointer.toolMajor = inPointer.absMTWidthMajor;
3779        } else {
3780            // Default tool area to 0 if absent.
3781            outPointer.toolMajor = 0;
3782        }
3783
3784        if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3785            outPointer.toolMinor = inPointer.absMTWidthMinor;
3786        } else {
3787            // Assume tool area is circular.
3788            outPointer.toolMinor = outPointer.toolMajor;
3789        }
3790
3791        if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3792            outPointer.orientation = inPointer.absMTOrientation;
3793        } else {
3794            // Default orientation to vertical if absent.
3795            outPointer.orientation = 0;
3796        }
3797
3798        // Assign pointer id using tracking id if available.
3799        if (havePointerIds) {
3800            if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3801                uint32_t id = uint32_t(inPointer.absMTTrackingId);
3802
3803                if (id > MAX_POINTER_ID) {
3804#if DEBUG_POINTERS
3805                    LOGD("Pointers: Ignoring driver provided pointer id %d because "
3806                            "it is larger than max supported id %d",
3807                            id, MAX_POINTER_ID);
3808#endif
3809                    havePointerIds = false;
3810                }
3811                else {
3812                    outPointer.id = id;
3813                    mCurrentTouch.idToIndex[id] = outCount;
3814                    mCurrentTouch.idBits.markBit(id);
3815                }
3816            } else {
3817                havePointerIds = false;
3818            }
3819        }
3820
3821        outCount += 1;
3822    }
3823
3824    mCurrentTouch.pointerCount = outCount;
3825
3826    syncTouch(when, havePointerIds);
3827
3828    mAccumulator.clear();
3829}
3830
3831void MultiTouchInputMapper::configureRawAxes() {
3832    TouchInputMapper::configureRawAxes();
3833
3834    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3835    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3836    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3837    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3838    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3839    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3840    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3841    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
3842}
3843
3844
3845// --- JoystickInputMapper ---
3846
3847JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
3848        InputMapper(device) {
3849}
3850
3851JoystickInputMapper::~JoystickInputMapper() {
3852}
3853
3854uint32_t JoystickInputMapper::getSources() {
3855    return AINPUT_SOURCE_JOYSTICK;
3856}
3857
3858void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
3859    InputMapper::populateDeviceInfo(info);
3860
3861    for (size_t i = 0; i < mAxes.size(); i++) {
3862        const Axis& axis = mAxes.valueAt(i);
3863        info->addMotionRange(axis.axisInfo.axis, axis.min, axis.max, axis.flat, axis.fuzz);
3864        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
3865            info->addMotionRange(axis.axisInfo.highAxis, axis.min, axis.max, axis.flat, axis.fuzz);
3866        }
3867    }
3868}
3869
3870void JoystickInputMapper::dump(String8& dump) {
3871    dump.append(INDENT2 "Joystick Input Mapper:\n");
3872
3873    dump.append(INDENT3 "Axes:\n");
3874    size_t numAxes = mAxes.size();
3875    for (size_t i = 0; i < numAxes; i++) {
3876        const Axis& axis = mAxes.valueAt(i);
3877        const char* label = getAxisLabel(axis.axisInfo.axis);
3878        if (label) {
3879            dump.appendFormat(INDENT4 "%s", label);
3880        } else {
3881            dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis);
3882        }
3883        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
3884            label = getAxisLabel(axis.axisInfo.highAxis);
3885            if (label) {
3886                dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue);
3887            } else {
3888                dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis,
3889                        axis.axisInfo.splitValue);
3890            }
3891        } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
3892            dump.append(" (invert)");
3893        }
3894
3895        dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f\n",
3896                axis.min, axis.max, axis.flat, axis.fuzz);
3897        dump.appendFormat(INDENT4 "  scale=%0.5f, offset=%0.5f, "
3898                "highScale=%0.5f, highOffset=%0.5f\n",
3899                axis.scale, axis.offset, axis.highScale, axis.highOffset);
3900        dump.appendFormat(INDENT4 "  rawAxis=%d, rawMin=%d, rawMax=%d, rawFlat=%d, rawFuzz=%d\n",
3901                mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
3902                axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz);
3903    }
3904}
3905
3906void JoystickInputMapper::configure() {
3907    InputMapper::configure();
3908
3909    // Collect all axes.
3910    for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
3911        RawAbsoluteAxisInfo rawAxisInfo;
3912        getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo);
3913        if (rawAxisInfo.valid) {
3914            // Map axis.
3915            AxisInfo axisInfo;
3916            bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
3917            if (!explicitlyMapped) {
3918                // Axis is not explicitly mapped, will choose a generic axis later.
3919                axisInfo.mode = AxisInfo::MODE_NORMAL;
3920                axisInfo.axis = -1;
3921            }
3922
3923            // Apply flat override.
3924            int32_t rawFlat = axisInfo.flatOverride < 0
3925                    ? rawAxisInfo.flat : axisInfo.flatOverride;
3926
3927            // Calculate scaling factors and limits.
3928            Axis axis;
3929            if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
3930                float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
3931                float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
3932                axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
3933                        scale, 0.0f, highScale, 0.0f,
3934                        0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
3935            } else if (isCenteredAxis(axisInfo.axis)) {
3936                float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
3937                float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
3938                axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
3939                        scale, offset, scale, offset,
3940                        -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
3941            } else {
3942                float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
3943                axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
3944                        scale, 0.0f, scale, 0.0f,
3945                        0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
3946            }
3947
3948            // To eliminate noise while the joystick is at rest, filter out small variations
3949            // in axis values up front.
3950            axis.filter = axis.flat * 0.25f;
3951
3952            mAxes.add(abs, axis);
3953        }
3954    }
3955
3956    // If there are too many axes, start dropping them.
3957    // Prefer to keep explicitly mapped axes.
3958    if (mAxes.size() > PointerCoords::MAX_AXES) {
3959        LOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
3960                getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
3961        pruneAxes(true);
3962        pruneAxes(false);
3963    }
3964
3965    // Assign generic axis ids to remaining axes.
3966    int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
3967    size_t numAxes = mAxes.size();
3968    for (size_t i = 0; i < numAxes; i++) {
3969        Axis& axis = mAxes.editValueAt(i);
3970        if (axis.axisInfo.axis < 0) {
3971            while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
3972                    && haveAxis(nextGenericAxisId)) {
3973                nextGenericAxisId += 1;
3974            }
3975
3976            if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
3977                axis.axisInfo.axis = nextGenericAxisId;
3978                nextGenericAxisId += 1;
3979            } else {
3980                LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
3981                        "have already been assigned to other axes.",
3982                        getDeviceName().string(), mAxes.keyAt(i));
3983                mAxes.removeItemsAt(i--);
3984                numAxes -= 1;
3985            }
3986        }
3987    }
3988}
3989
3990bool JoystickInputMapper::haveAxis(int32_t axisId) {
3991    size_t numAxes = mAxes.size();
3992    for (size_t i = 0; i < numAxes; i++) {
3993        const Axis& axis = mAxes.valueAt(i);
3994        if (axis.axisInfo.axis == axisId
3995                || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
3996                        && axis.axisInfo.highAxis == axisId)) {
3997            return true;
3998        }
3999    }
4000    return false;
4001}
4002
4003void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
4004    size_t i = mAxes.size();
4005    while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
4006        if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
4007            continue;
4008        }
4009        LOGI("Discarding joystick '%s' axis %d because there are too many axes.",
4010                getDeviceName().string(), mAxes.keyAt(i));
4011        mAxes.removeItemsAt(i);
4012    }
4013}
4014
4015bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
4016    switch (axis) {
4017    case AMOTION_EVENT_AXIS_X:
4018    case AMOTION_EVENT_AXIS_Y:
4019    case AMOTION_EVENT_AXIS_Z:
4020    case AMOTION_EVENT_AXIS_RX:
4021    case AMOTION_EVENT_AXIS_RY:
4022    case AMOTION_EVENT_AXIS_RZ:
4023    case AMOTION_EVENT_AXIS_HAT_X:
4024    case AMOTION_EVENT_AXIS_HAT_Y:
4025    case AMOTION_EVENT_AXIS_ORIENTATION:
4026    case AMOTION_EVENT_AXIS_RUDDER:
4027    case AMOTION_EVENT_AXIS_WHEEL:
4028        return true;
4029    default:
4030        return false;
4031    }
4032}
4033
4034void JoystickInputMapper::reset() {
4035    // Recenter all axes.
4036    nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
4037
4038    size_t numAxes = mAxes.size();
4039    for (size_t i = 0; i < numAxes; i++) {
4040        Axis& axis = mAxes.editValueAt(i);
4041        axis.resetValue();
4042    }
4043
4044    sync(when, true /*force*/);
4045
4046    InputMapper::reset();
4047}
4048
4049void JoystickInputMapper::process(const RawEvent* rawEvent) {
4050    switch (rawEvent->type) {
4051    case EV_ABS: {
4052        ssize_t index = mAxes.indexOfKey(rawEvent->scanCode);
4053        if (index >= 0) {
4054            Axis& axis = mAxes.editValueAt(index);
4055            float newValue, highNewValue;
4056            switch (axis.axisInfo.mode) {
4057            case AxisInfo::MODE_INVERT:
4058                newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
4059                        * axis.scale + axis.offset;
4060                highNewValue = 0.0f;
4061                break;
4062            case AxisInfo::MODE_SPLIT:
4063                if (rawEvent->value < axis.axisInfo.splitValue) {
4064                    newValue = (axis.axisInfo.splitValue - rawEvent->value)
4065                            * axis.scale + axis.offset;
4066                    highNewValue = 0.0f;
4067                } else if (rawEvent->value > axis.axisInfo.splitValue) {
4068                    newValue = 0.0f;
4069                    highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
4070                            * axis.highScale + axis.highOffset;
4071                } else {
4072                    newValue = 0.0f;
4073                    highNewValue = 0.0f;
4074                }
4075                break;
4076            default:
4077                newValue = rawEvent->value * axis.scale + axis.offset;
4078                highNewValue = 0.0f;
4079                break;
4080            }
4081            axis.newValue = newValue;
4082            axis.highNewValue = highNewValue;
4083        }
4084        break;
4085    }
4086
4087    case EV_SYN:
4088        switch (rawEvent->scanCode) {
4089        case SYN_REPORT:
4090            sync(rawEvent->when, false /*force*/);
4091            break;
4092        }
4093        break;
4094    }
4095}
4096
4097void JoystickInputMapper::sync(nsecs_t when, bool force) {
4098    if (!filterAxes(force)) {
4099        return;
4100    }
4101
4102    int32_t metaState = mContext->getGlobalMetaState();
4103
4104    PointerCoords pointerCoords;
4105    pointerCoords.clear();
4106
4107    size_t numAxes = mAxes.size();
4108    for (size_t i = 0; i < numAxes; i++) {
4109        const Axis& axis = mAxes.valueAt(i);
4110        pointerCoords.setAxisValue(axis.axisInfo.axis, axis.currentValue);
4111        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
4112            pointerCoords.setAxisValue(axis.axisInfo.highAxis, axis.highCurrentValue);
4113        }
4114    }
4115
4116    // Moving a joystick axis should not wake the devide because joysticks can
4117    // be fairly noisy even when not in use.  On the other hand, pushing a gamepad
4118    // button will likely wake the device.
4119    // TODO: Use the input device configuration to control this behavior more finely.
4120    uint32_t policyFlags = 0;
4121
4122    int32_t pointerId = 0;
4123    getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
4124            AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
4125            1, &pointerId, &pointerCoords, 0, 0, 0);
4126}
4127
4128bool JoystickInputMapper::filterAxes(bool force) {
4129    bool atLeastOneSignificantChange = force;
4130    size_t numAxes = mAxes.size();
4131    for (size_t i = 0; i < numAxes; i++) {
4132        Axis& axis = mAxes.editValueAt(i);
4133        if (force || hasValueChangedSignificantly(axis.filter,
4134                axis.newValue, axis.currentValue, axis.min, axis.max)) {
4135            axis.currentValue = axis.newValue;
4136            atLeastOneSignificantChange = true;
4137        }
4138        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
4139            if (force || hasValueChangedSignificantly(axis.filter,
4140                    axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
4141                axis.highCurrentValue = axis.highNewValue;
4142                atLeastOneSignificantChange = true;
4143            }
4144        }
4145    }
4146    return atLeastOneSignificantChange;
4147}
4148
4149bool JoystickInputMapper::hasValueChangedSignificantly(
4150        float filter, float newValue, float currentValue, float min, float max) {
4151    if (newValue != currentValue) {
4152        // Filter out small changes in value unless the value is converging on the axis
4153        // bounds or center point.  This is intended to reduce the amount of information
4154        // sent to applications by particularly noisy joysticks (such as PS3).
4155        if (fabs(newValue - currentValue) > filter
4156                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
4157                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
4158                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
4159            return true;
4160        }
4161    }
4162    return false;
4163}
4164
4165bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
4166        float filter, float newValue, float currentValue, float thresholdValue) {
4167    float newDistance = fabs(newValue - thresholdValue);
4168    if (newDistance < filter) {
4169        float oldDistance = fabs(currentValue - thresholdValue);
4170        if (newDistance < oldDistance) {
4171            return true;
4172        }
4173    }
4174    return false;
4175}
4176
4177} // namespace android
4178