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