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