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