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