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