InputReader.cpp revision 33bbfd2232ea9eaae9a9d87a05a95a430f09bd83
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_LEFT:
1201        case BTN_RIGHT:
1202        case BTN_MIDDLE:
1203        case BTN_SIDE:
1204        case BTN_EXTRA:
1205        case BTN_FORWARD:
1206        case BTN_BACK:
1207        case BTN_TASK:
1208            mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1209            mAccumulator.btnMouse = rawEvent->value != 0;
1210            // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1211            // we need to ensure that we report the up/down promptly.
1212            sync(rawEvent->when);
1213            break;
1214        }
1215        break;
1216
1217    case EV_REL:
1218        switch (rawEvent->scanCode) {
1219        case REL_X:
1220            mAccumulator.fields |= Accumulator::FIELD_REL_X;
1221            mAccumulator.relX = rawEvent->value;
1222            break;
1223        case REL_Y:
1224            mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1225            mAccumulator.relY = rawEvent->value;
1226            break;
1227        case REL_WHEEL:
1228            mAccumulator.fields |= Accumulator::FIELD_REL_WHEEL;
1229            mAccumulator.relWheel = rawEvent->value;
1230            break;
1231        case REL_HWHEEL:
1232            mAccumulator.fields |= Accumulator::FIELD_REL_HWHEEL;
1233            mAccumulator.relHWheel = rawEvent->value;
1234            break;
1235        }
1236        break;
1237
1238    case EV_SYN:
1239        switch (rawEvent->scanCode) {
1240        case SYN_REPORT:
1241            sync(rawEvent->when);
1242            break;
1243        }
1244        break;
1245    }
1246}
1247
1248void CursorInputMapper::sync(nsecs_t when) {
1249    uint32_t fields = mAccumulator.fields;
1250    if (fields == 0) {
1251        return; // no new state changes, so nothing to do
1252    }
1253
1254    int motionEventAction;
1255    PointerCoords pointerCoords;
1256    nsecs_t downTime;
1257    float vscroll, hscroll;
1258    { // acquire lock
1259        AutoMutex _l(mLock);
1260
1261        bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1262
1263        if (downChanged) {
1264            if (mAccumulator.btnMouse) {
1265                if (!mLocked.down) {
1266                    mLocked.down = true;
1267                    mLocked.downTime = when;
1268                } else {
1269                    downChanged = false;
1270                }
1271            } else {
1272                if (mLocked.down) {
1273                    mLocked.down = false;
1274                } else {
1275                    downChanged = false;
1276                }
1277            }
1278        }
1279
1280        downTime = mLocked.downTime;
1281        float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1282        float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
1283
1284        if (downChanged) {
1285            motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
1286        } else if (mLocked.down || mPointerController == NULL) {
1287            motionEventAction = AMOTION_EVENT_ACTION_MOVE;
1288        } else {
1289            motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
1290        }
1291
1292        if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
1293                && (deltaX != 0.0f || deltaY != 0.0f)) {
1294            // Rotate motion based on display orientation if needed.
1295            // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1296            int32_t orientation;
1297            if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1298                    NULL, NULL, & orientation)) {
1299                orientation = DISPLAY_ORIENTATION_0;
1300            }
1301
1302            float temp;
1303            switch (orientation) {
1304            case DISPLAY_ORIENTATION_90:
1305                temp = deltaX;
1306                deltaX = deltaY;
1307                deltaY = -temp;
1308                break;
1309
1310            case DISPLAY_ORIENTATION_180:
1311                deltaX = -deltaX;
1312                deltaY = -deltaY;
1313                break;
1314
1315            case DISPLAY_ORIENTATION_270:
1316                temp = deltaX;
1317                deltaX = -deltaY;
1318                deltaY = temp;
1319                break;
1320            }
1321        }
1322
1323        pointerCoords.clear();
1324
1325        if (mPointerController != NULL) {
1326            mPointerController->move(deltaX, deltaY);
1327            if (downChanged) {
1328                mPointerController->setButtonState(mLocked.down ? POINTER_BUTTON_1 : 0);
1329            }
1330            float x, y;
1331            mPointerController->getPosition(&x, &y);
1332            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
1333            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
1334        } else {
1335            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
1336            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
1337        }
1338
1339        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, mLocked.down ? 1.0f : 0.0f);
1340
1341        if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) {
1342            vscroll = mAccumulator.relWheel;
1343        } else {
1344            vscroll = 0;
1345        }
1346        if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) {
1347            hscroll = mAccumulator.relHWheel;
1348        } else {
1349            hscroll = 0;
1350        }
1351    } // release lock
1352
1353    int32_t metaState = mContext->getGlobalMetaState();
1354    int32_t pointerId = 0;
1355    getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0,
1356            motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1357            1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1358
1359    mAccumulator.clear();
1360
1361    if (vscroll != 0 || hscroll != 0) {
1362        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
1363        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
1364
1365        getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0,
1366                AMOTION_EVENT_ACTION_SCROLL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1367                1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1368    }
1369}
1370
1371int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1372    if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1373        return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1374    } else {
1375        return AKEY_STATE_UNKNOWN;
1376    }
1377}
1378
1379
1380// --- TouchInputMapper ---
1381
1382TouchInputMapper::TouchInputMapper(InputDevice* device) :
1383        InputMapper(device) {
1384    mLocked.surfaceOrientation = -1;
1385    mLocked.surfaceWidth = -1;
1386    mLocked.surfaceHeight = -1;
1387
1388    initializeLocked();
1389}
1390
1391TouchInputMapper::~TouchInputMapper() {
1392}
1393
1394uint32_t TouchInputMapper::getSources() {
1395    return mSources;
1396}
1397
1398void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1399    InputMapper::populateDeviceInfo(info);
1400
1401    { // acquire lock
1402        AutoMutex _l(mLock);
1403
1404        // Ensure surface information is up to date so that orientation changes are
1405        // noticed immediately.
1406        configureSurfaceLocked();
1407
1408        info->addMotionRange(AMOTION_EVENT_AXIS_X, mLocked.orientedRanges.x);
1409        info->addMotionRange(AMOTION_EVENT_AXIS_Y, mLocked.orientedRanges.y);
1410
1411        if (mLocked.orientedRanges.havePressure) {
1412            info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE,
1413                    mLocked.orientedRanges.pressure);
1414        }
1415
1416        if (mLocked.orientedRanges.haveSize) {
1417            info->addMotionRange(AMOTION_EVENT_AXIS_SIZE,
1418                    mLocked.orientedRanges.size);
1419        }
1420
1421        if (mLocked.orientedRanges.haveTouchSize) {
1422            info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MAJOR,
1423                    mLocked.orientedRanges.touchMajor);
1424            info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MINOR,
1425                    mLocked.orientedRanges.touchMinor);
1426        }
1427
1428        if (mLocked.orientedRanges.haveToolSize) {
1429            info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MAJOR,
1430                    mLocked.orientedRanges.toolMajor);
1431            info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MINOR,
1432                    mLocked.orientedRanges.toolMinor);
1433        }
1434
1435        if (mLocked.orientedRanges.haveOrientation) {
1436            info->addMotionRange(AMOTION_EVENT_AXIS_ORIENTATION,
1437                    mLocked.orientedRanges.orientation);
1438        }
1439    } // release lock
1440}
1441
1442void TouchInputMapper::dump(String8& dump) {
1443    { // acquire lock
1444        AutoMutex _l(mLock);
1445        dump.append(INDENT2 "Touch Input Mapper:\n");
1446        dumpParameters(dump);
1447        dumpVirtualKeysLocked(dump);
1448        dumpRawAxes(dump);
1449        dumpCalibration(dump);
1450        dumpSurfaceLocked(dump);
1451        dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
1452        dump.appendFormat(INDENT4 "XOrigin: %d\n", mLocked.xOrigin);
1453        dump.appendFormat(INDENT4 "YOrigin: %d\n", mLocked.yOrigin);
1454        dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
1455        dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
1456        dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
1457        dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
1458        dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
1459        dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
1460        dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
1461        dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
1462        dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
1463        dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
1464        dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
1465        dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale);
1466    } // release lock
1467}
1468
1469void TouchInputMapper::initializeLocked() {
1470    mCurrentTouch.clear();
1471    mLastTouch.clear();
1472    mDownTime = 0;
1473
1474    for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1475        mAveragingTouchFilter.historyStart[i] = 0;
1476        mAveragingTouchFilter.historyEnd[i] = 0;
1477    }
1478
1479    mJumpyTouchFilter.jumpyPointsDropped = 0;
1480
1481    mLocked.currentVirtualKey.down = false;
1482
1483    mLocked.orientedRanges.havePressure = false;
1484    mLocked.orientedRanges.haveSize = false;
1485    mLocked.orientedRanges.haveTouchSize = false;
1486    mLocked.orientedRanges.haveToolSize = false;
1487    mLocked.orientedRanges.haveOrientation = false;
1488}
1489
1490void TouchInputMapper::configure() {
1491    InputMapper::configure();
1492
1493    // Configure basic parameters.
1494    configureParameters();
1495
1496    // Configure sources.
1497    switch (mParameters.deviceType) {
1498    case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1499        mSources = AINPUT_SOURCE_TOUCHSCREEN;
1500        break;
1501    case Parameters::DEVICE_TYPE_TOUCH_PAD:
1502        mSources = AINPUT_SOURCE_TOUCHPAD;
1503        break;
1504    default:
1505        assert(false);
1506    }
1507
1508    // Configure absolute axis information.
1509    configureRawAxes();
1510
1511    // Prepare input device calibration.
1512    parseCalibration();
1513    resolveCalibration();
1514
1515    { // acquire lock
1516        AutoMutex _l(mLock);
1517
1518         // Configure surface dimensions and orientation.
1519        configureSurfaceLocked();
1520    } // release lock
1521}
1522
1523void TouchInputMapper::configureParameters() {
1524    mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1525    mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1526    mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
1527    mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime();
1528
1529    String8 deviceTypeString;
1530    mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
1531    if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
1532            deviceTypeString)) {
1533        if (deviceTypeString == "touchScreen") {
1534            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1535        } else if (deviceTypeString != "touchPad") {
1536            LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
1537        }
1538    }
1539    bool isTouchScreen = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1540
1541    mParameters.orientationAware = isTouchScreen;
1542    getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
1543            mParameters.orientationAware);
1544
1545    mParameters.associatedDisplayId = mParameters.orientationAware || isTouchScreen ? 0 : -1;
1546}
1547
1548void TouchInputMapper::dumpParameters(String8& dump) {
1549    dump.append(INDENT3 "Parameters:\n");
1550
1551    switch (mParameters.deviceType) {
1552    case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1553        dump.append(INDENT4 "DeviceType: touchScreen\n");
1554        break;
1555    case Parameters::DEVICE_TYPE_TOUCH_PAD:
1556        dump.append(INDENT4 "DeviceType: touchPad\n");
1557        break;
1558    default:
1559        assert(false);
1560    }
1561
1562    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1563            mParameters.associatedDisplayId);
1564    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1565            toString(mParameters.orientationAware));
1566
1567    dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
1568            toString(mParameters.useBadTouchFilter));
1569    dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
1570            toString(mParameters.useAveragingTouchFilter));
1571    dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
1572            toString(mParameters.useJumpyTouchFilter));
1573}
1574
1575void TouchInputMapper::configureRawAxes() {
1576    mRawAxes.x.clear();
1577    mRawAxes.y.clear();
1578    mRawAxes.pressure.clear();
1579    mRawAxes.touchMajor.clear();
1580    mRawAxes.touchMinor.clear();
1581    mRawAxes.toolMajor.clear();
1582    mRawAxes.toolMinor.clear();
1583    mRawAxes.orientation.clear();
1584}
1585
1586void TouchInputMapper::dumpRawAxes(String8& dump) {
1587    dump.append(INDENT3 "Raw Axes:\n");
1588    dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X");
1589    dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y");
1590    dumpRawAbsoluteAxisInfo(dump, mRawAxes.pressure, "Pressure");
1591    dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1592    dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1593    dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1594    dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1595    dumpRawAbsoluteAxisInfo(dump, mRawAxes.orientation, "Orientation");
1596}
1597
1598bool TouchInputMapper::configureSurfaceLocked() {
1599    // Update orientation and dimensions if needed.
1600    int32_t orientation = DISPLAY_ORIENTATION_0;
1601    int32_t width = mRawAxes.x.getRange();
1602    int32_t height = mRawAxes.y.getRange();
1603
1604    if (mParameters.associatedDisplayId >= 0) {
1605        bool wantSize = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1606        bool wantOrientation = mParameters.orientationAware;
1607
1608        // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1609        if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1610                wantSize ? &width : NULL, wantSize ? &height : NULL,
1611                wantOrientation ? &orientation : NULL)) {
1612            return false;
1613        }
1614    }
1615
1616    bool orientationChanged = mLocked.surfaceOrientation != orientation;
1617    if (orientationChanged) {
1618        mLocked.surfaceOrientation = orientation;
1619    }
1620
1621    bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
1622    if (sizeChanged) {
1623        LOGI("Device reconfigured: id=%d, name='%s', display size is now %dx%d",
1624                getDeviceId(), getDeviceName().string(), width, height);
1625
1626        mLocked.surfaceWidth = width;
1627        mLocked.surfaceHeight = height;
1628
1629        // Configure X and Y factors.
1630        if (mRawAxes.x.valid && mRawAxes.y.valid) {
1631            mLocked.xOrigin = mCalibration.haveXOrigin
1632                    ? mCalibration.xOrigin
1633                    : mRawAxes.x.minValue;
1634            mLocked.yOrigin = mCalibration.haveYOrigin
1635                    ? mCalibration.yOrigin
1636                    : mRawAxes.y.minValue;
1637            mLocked.xScale = mCalibration.haveXScale
1638                    ? mCalibration.xScale
1639                    : float(width) / mRawAxes.x.getRange();
1640            mLocked.yScale = mCalibration.haveYScale
1641                    ? mCalibration.yScale
1642                    : float(height) / mRawAxes.y.getRange();
1643            mLocked.xPrecision = 1.0f / mLocked.xScale;
1644            mLocked.yPrecision = 1.0f / mLocked.yScale;
1645
1646            configureVirtualKeysLocked();
1647        } else {
1648            LOGW(INDENT "Touch device did not report support for X or Y axis!");
1649            mLocked.xOrigin = 0;
1650            mLocked.yOrigin = 0;
1651            mLocked.xScale = 1.0f;
1652            mLocked.yScale = 1.0f;
1653            mLocked.xPrecision = 1.0f;
1654            mLocked.yPrecision = 1.0f;
1655        }
1656
1657        // Scale factor for terms that are not oriented in a particular axis.
1658        // If the pixels are square then xScale == yScale otherwise we fake it
1659        // by choosing an average.
1660        mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
1661
1662        // Size of diagonal axis.
1663        float diagonalSize = pythag(width, height);
1664
1665        // TouchMajor and TouchMinor factors.
1666        if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
1667            mLocked.orientedRanges.haveTouchSize = true;
1668            mLocked.orientedRanges.touchMajor.min = 0;
1669            mLocked.orientedRanges.touchMajor.max = diagonalSize;
1670            mLocked.orientedRanges.touchMajor.flat = 0;
1671            mLocked.orientedRanges.touchMajor.fuzz = 0;
1672            mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1673        }
1674
1675        // ToolMajor and ToolMinor factors.
1676        mLocked.toolSizeLinearScale = 0;
1677        mLocked.toolSizeLinearBias = 0;
1678        mLocked.toolSizeAreaScale = 0;
1679        mLocked.toolSizeAreaBias = 0;
1680        if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
1681            if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
1682                if (mCalibration.haveToolSizeLinearScale) {
1683                    mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
1684                } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1685                    mLocked.toolSizeLinearScale = float(min(width, height))
1686                            / mRawAxes.toolMajor.maxValue;
1687                }
1688
1689                if (mCalibration.haveToolSizeLinearBias) {
1690                    mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1691                }
1692            } else if (mCalibration.toolSizeCalibration ==
1693                    Calibration::TOOL_SIZE_CALIBRATION_AREA) {
1694                if (mCalibration.haveToolSizeLinearScale) {
1695                    mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
1696                } else {
1697                    mLocked.toolSizeLinearScale = min(width, height);
1698                }
1699
1700                if (mCalibration.haveToolSizeLinearBias) {
1701                    mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1702                }
1703
1704                if (mCalibration.haveToolSizeAreaScale) {
1705                    mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
1706                } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1707                    mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
1708                }
1709
1710                if (mCalibration.haveToolSizeAreaBias) {
1711                    mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
1712                }
1713            }
1714
1715            mLocked.orientedRanges.haveToolSize = true;
1716            mLocked.orientedRanges.toolMajor.min = 0;
1717            mLocked.orientedRanges.toolMajor.max = diagonalSize;
1718            mLocked.orientedRanges.toolMajor.flat = 0;
1719            mLocked.orientedRanges.toolMajor.fuzz = 0;
1720            mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1721        }
1722
1723        // Pressure factors.
1724        mLocked.pressureScale = 0;
1725        if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1726            RawAbsoluteAxisInfo rawPressureAxis;
1727            switch (mCalibration.pressureSource) {
1728            case Calibration::PRESSURE_SOURCE_PRESSURE:
1729                rawPressureAxis = mRawAxes.pressure;
1730                break;
1731            case Calibration::PRESSURE_SOURCE_TOUCH:
1732                rawPressureAxis = mRawAxes.touchMajor;
1733                break;
1734            default:
1735                rawPressureAxis.clear();
1736            }
1737
1738            if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1739                    || mCalibration.pressureCalibration
1740                            == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1741                if (mCalibration.havePressureScale) {
1742                    mLocked.pressureScale = mCalibration.pressureScale;
1743                } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1744                    mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1745                }
1746            }
1747
1748            mLocked.orientedRanges.havePressure = true;
1749            mLocked.orientedRanges.pressure.min = 0;
1750            mLocked.orientedRanges.pressure.max = 1.0;
1751            mLocked.orientedRanges.pressure.flat = 0;
1752            mLocked.orientedRanges.pressure.fuzz = 0;
1753        }
1754
1755        // Size factors.
1756        mLocked.sizeScale = 0;
1757        if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
1758            if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1759                if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1760                    mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1761                }
1762            }
1763
1764            mLocked.orientedRanges.haveSize = true;
1765            mLocked.orientedRanges.size.min = 0;
1766            mLocked.orientedRanges.size.max = 1.0;
1767            mLocked.orientedRanges.size.flat = 0;
1768            mLocked.orientedRanges.size.fuzz = 0;
1769        }
1770
1771        // Orientation
1772        mLocked.orientationScale = 0;
1773        if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
1774            if (mCalibration.orientationCalibration
1775                    == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1776                if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1777                    mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1778                }
1779            }
1780
1781            mLocked.orientedRanges.orientation.min = - M_PI_2;
1782            mLocked.orientedRanges.orientation.max = M_PI_2;
1783            mLocked.orientedRanges.orientation.flat = 0;
1784            mLocked.orientedRanges.orientation.fuzz = 0;
1785        }
1786    }
1787
1788    if (orientationChanged || sizeChanged) {
1789        // Compute oriented surface dimensions, precision, and scales.
1790        float orientedXScale, orientedYScale;
1791        switch (mLocked.surfaceOrientation) {
1792        case DISPLAY_ORIENTATION_90:
1793        case DISPLAY_ORIENTATION_270:
1794            mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1795            mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1796            mLocked.orientedXPrecision = mLocked.yPrecision;
1797            mLocked.orientedYPrecision = mLocked.xPrecision;
1798            orientedXScale = mLocked.yScale;
1799            orientedYScale = mLocked.xScale;
1800            break;
1801        default:
1802            mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1803            mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1804            mLocked.orientedXPrecision = mLocked.xPrecision;
1805            mLocked.orientedYPrecision = mLocked.yPrecision;
1806            orientedXScale = mLocked.xScale;
1807            orientedYScale = mLocked.yScale;
1808            break;
1809        }
1810
1811        // Configure position ranges.
1812        mLocked.orientedRanges.x.min = 0;
1813        mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1814        mLocked.orientedRanges.x.flat = 0;
1815        mLocked.orientedRanges.x.fuzz = orientedXScale;
1816
1817        mLocked.orientedRanges.y.min = 0;
1818        mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1819        mLocked.orientedRanges.y.flat = 0;
1820        mLocked.orientedRanges.y.fuzz = orientedYScale;
1821    }
1822
1823    return true;
1824}
1825
1826void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
1827    dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
1828    dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
1829    dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
1830}
1831
1832void TouchInputMapper::configureVirtualKeysLocked() {
1833    assert(mRawAxes.x.valid && mRawAxes.y.valid);
1834
1835    Vector<VirtualKeyDefinition> virtualKeyDefinitions;
1836    getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
1837
1838    mLocked.virtualKeys.clear();
1839
1840    if (virtualKeyDefinitions.size() == 0) {
1841        return;
1842    }
1843
1844    mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1845
1846    int32_t touchScreenLeft = mRawAxes.x.minValue;
1847    int32_t touchScreenTop = mRawAxes.y.minValue;
1848    int32_t touchScreenWidth = mRawAxes.x.getRange();
1849    int32_t touchScreenHeight = mRawAxes.y.getRange();
1850
1851    for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
1852        const VirtualKeyDefinition& virtualKeyDefinition =
1853                virtualKeyDefinitions[i];
1854
1855        mLocked.virtualKeys.add();
1856        VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1857
1858        virtualKey.scanCode = virtualKeyDefinition.scanCode;
1859        int32_t keyCode;
1860        uint32_t flags;
1861        if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode,
1862                & keyCode, & flags)) {
1863            LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1864                    virtualKey.scanCode);
1865            mLocked.virtualKeys.pop(); // drop the key
1866            continue;
1867        }
1868
1869        virtualKey.keyCode = keyCode;
1870        virtualKey.flags = flags;
1871
1872        // convert the key definition's display coordinates into touch coordinates for a hit box
1873        int32_t halfWidth = virtualKeyDefinition.width / 2;
1874        int32_t halfHeight = virtualKeyDefinition.height / 2;
1875
1876        virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1877                * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1878        virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1879                * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1880        virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1881                * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1882        virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1883                * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1884
1885    }
1886}
1887
1888void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
1889    if (!mLocked.virtualKeys.isEmpty()) {
1890        dump.append(INDENT3 "Virtual Keys:\n");
1891
1892        for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
1893            const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
1894            dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
1895                    "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
1896                    i, virtualKey.scanCode, virtualKey.keyCode,
1897                    virtualKey.hitLeft, virtualKey.hitRight,
1898                    virtualKey.hitTop, virtualKey.hitBottom);
1899        }
1900    }
1901}
1902
1903void TouchInputMapper::parseCalibration() {
1904    const PropertyMap& in = getDevice()->getConfiguration();
1905    Calibration& out = mCalibration;
1906
1907    // Position
1908    out.haveXOrigin = in.tryGetProperty(String8("touch.position.xOrigin"), out.xOrigin);
1909    out.haveYOrigin = in.tryGetProperty(String8("touch.position.yOrigin"), out.yOrigin);
1910    out.haveXScale = in.tryGetProperty(String8("touch.position.xScale"), out.xScale);
1911    out.haveYScale = in.tryGetProperty(String8("touch.position.yScale"), out.yScale);
1912
1913    // Touch Size
1914    out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
1915    String8 touchSizeCalibrationString;
1916    if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
1917        if (touchSizeCalibrationString == "none") {
1918            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
1919        } else if (touchSizeCalibrationString == "geometric") {
1920            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
1921        } else if (touchSizeCalibrationString == "pressure") {
1922            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
1923        } else if (touchSizeCalibrationString != "default") {
1924            LOGW("Invalid value for touch.touchSize.calibration: '%s'",
1925                    touchSizeCalibrationString.string());
1926        }
1927    }
1928
1929    // Tool Size
1930    out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
1931    String8 toolSizeCalibrationString;
1932    if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
1933        if (toolSizeCalibrationString == "none") {
1934            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
1935        } else if (toolSizeCalibrationString == "geometric") {
1936            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
1937        } else if (toolSizeCalibrationString == "linear") {
1938            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
1939        } else if (toolSizeCalibrationString == "area") {
1940            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
1941        } else if (toolSizeCalibrationString != "default") {
1942            LOGW("Invalid value for touch.toolSize.calibration: '%s'",
1943                    toolSizeCalibrationString.string());
1944        }
1945    }
1946
1947    out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
1948            out.toolSizeLinearScale);
1949    out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
1950            out.toolSizeLinearBias);
1951    out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
1952            out.toolSizeAreaScale);
1953    out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
1954            out.toolSizeAreaBias);
1955    out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
1956            out.toolSizeIsSummed);
1957
1958    // Pressure
1959    out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
1960    String8 pressureCalibrationString;
1961    if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
1962        if (pressureCalibrationString == "none") {
1963            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1964        } else if (pressureCalibrationString == "physical") {
1965            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
1966        } else if (pressureCalibrationString == "amplitude") {
1967            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1968        } else if (pressureCalibrationString != "default") {
1969            LOGW("Invalid value for touch.pressure.calibration: '%s'",
1970                    pressureCalibrationString.string());
1971        }
1972    }
1973
1974    out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
1975    String8 pressureSourceString;
1976    if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
1977        if (pressureSourceString == "pressure") {
1978            out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1979        } else if (pressureSourceString == "touch") {
1980            out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1981        } else if (pressureSourceString != "default") {
1982            LOGW("Invalid value for touch.pressure.source: '%s'",
1983                    pressureSourceString.string());
1984        }
1985    }
1986
1987    out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
1988            out.pressureScale);
1989
1990    // Size
1991    out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
1992    String8 sizeCalibrationString;
1993    if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
1994        if (sizeCalibrationString == "none") {
1995            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1996        } else if (sizeCalibrationString == "normalized") {
1997            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1998        } else if (sizeCalibrationString != "default") {
1999            LOGW("Invalid value for touch.size.calibration: '%s'",
2000                    sizeCalibrationString.string());
2001        }
2002    }
2003
2004    // Orientation
2005    out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
2006    String8 orientationCalibrationString;
2007    if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
2008        if (orientationCalibrationString == "none") {
2009            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2010        } else if (orientationCalibrationString == "interpolated") {
2011            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2012        } else if (orientationCalibrationString == "vector") {
2013            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
2014        } else if (orientationCalibrationString != "default") {
2015            LOGW("Invalid value for touch.orientation.calibration: '%s'",
2016                    orientationCalibrationString.string());
2017        }
2018    }
2019}
2020
2021void TouchInputMapper::resolveCalibration() {
2022    // Pressure
2023    switch (mCalibration.pressureSource) {
2024    case Calibration::PRESSURE_SOURCE_DEFAULT:
2025        if (mRawAxes.pressure.valid) {
2026            mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2027        } else if (mRawAxes.touchMajor.valid) {
2028            mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2029        }
2030        break;
2031
2032    case Calibration::PRESSURE_SOURCE_PRESSURE:
2033        if (! mRawAxes.pressure.valid) {
2034            LOGW("Calibration property touch.pressure.source is 'pressure' but "
2035                    "the pressure axis is not available.");
2036        }
2037        break;
2038
2039    case Calibration::PRESSURE_SOURCE_TOUCH:
2040        if (! mRawAxes.touchMajor.valid) {
2041            LOGW("Calibration property touch.pressure.source is 'touch' but "
2042                    "the touchMajor axis is not available.");
2043        }
2044        break;
2045
2046    default:
2047        break;
2048    }
2049
2050    switch (mCalibration.pressureCalibration) {
2051    case Calibration::PRESSURE_CALIBRATION_DEFAULT:
2052        if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
2053            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2054        } else {
2055            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2056        }
2057        break;
2058
2059    default:
2060        break;
2061    }
2062
2063    // Tool Size
2064    switch (mCalibration.toolSizeCalibration) {
2065    case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
2066        if (mRawAxes.toolMajor.valid) {
2067            mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
2068        } else {
2069            mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
2070        }
2071        break;
2072
2073    default:
2074        break;
2075    }
2076
2077    // Touch Size
2078    switch (mCalibration.touchSizeCalibration) {
2079    case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
2080        if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
2081                && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2082            mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
2083        } else {
2084            mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
2085        }
2086        break;
2087
2088    default:
2089        break;
2090    }
2091
2092    // Size
2093    switch (mCalibration.sizeCalibration) {
2094    case Calibration::SIZE_CALIBRATION_DEFAULT:
2095        if (mRawAxes.toolMajor.valid) {
2096            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2097        } else {
2098            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2099        }
2100        break;
2101
2102    default:
2103        break;
2104    }
2105
2106    // Orientation
2107    switch (mCalibration.orientationCalibration) {
2108    case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
2109        if (mRawAxes.orientation.valid) {
2110            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2111        } else {
2112            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2113        }
2114        break;
2115
2116    default:
2117        break;
2118    }
2119}
2120
2121void TouchInputMapper::dumpCalibration(String8& dump) {
2122    dump.append(INDENT3 "Calibration:\n");
2123
2124    // Position
2125    if (mCalibration.haveXOrigin) {
2126        dump.appendFormat(INDENT4 "touch.position.xOrigin: %d\n", mCalibration.xOrigin);
2127    }
2128    if (mCalibration.haveYOrigin) {
2129        dump.appendFormat(INDENT4 "touch.position.yOrigin: %d\n", mCalibration.yOrigin);
2130    }
2131    if (mCalibration.haveXScale) {
2132        dump.appendFormat(INDENT4 "touch.position.xScale: %0.3f\n", mCalibration.xScale);
2133    }
2134    if (mCalibration.haveYScale) {
2135        dump.appendFormat(INDENT4 "touch.position.yScale: %0.3f\n", mCalibration.yScale);
2136    }
2137
2138    // Touch Size
2139    switch (mCalibration.touchSizeCalibration) {
2140    case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
2141        dump.append(INDENT4 "touch.touchSize.calibration: none\n");
2142        break;
2143    case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
2144        dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
2145        break;
2146    case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
2147        dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
2148        break;
2149    default:
2150        assert(false);
2151    }
2152
2153    // Tool Size
2154    switch (mCalibration.toolSizeCalibration) {
2155    case Calibration::TOOL_SIZE_CALIBRATION_NONE:
2156        dump.append(INDENT4 "touch.toolSize.calibration: none\n");
2157        break;
2158    case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
2159        dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
2160        break;
2161    case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
2162        dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
2163        break;
2164    case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2165        dump.append(INDENT4 "touch.toolSize.calibration: area\n");
2166        break;
2167    default:
2168        assert(false);
2169    }
2170
2171    if (mCalibration.haveToolSizeLinearScale) {
2172        dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
2173                mCalibration.toolSizeLinearScale);
2174    }
2175
2176    if (mCalibration.haveToolSizeLinearBias) {
2177        dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
2178                mCalibration.toolSizeLinearBias);
2179    }
2180
2181    if (mCalibration.haveToolSizeAreaScale) {
2182        dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
2183                mCalibration.toolSizeAreaScale);
2184    }
2185
2186    if (mCalibration.haveToolSizeAreaBias) {
2187        dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
2188                mCalibration.toolSizeAreaBias);
2189    }
2190
2191    if (mCalibration.haveToolSizeIsSummed) {
2192        dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
2193                toString(mCalibration.toolSizeIsSummed));
2194    }
2195
2196    // Pressure
2197    switch (mCalibration.pressureCalibration) {
2198    case Calibration::PRESSURE_CALIBRATION_NONE:
2199        dump.append(INDENT4 "touch.pressure.calibration: none\n");
2200        break;
2201    case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2202        dump.append(INDENT4 "touch.pressure.calibration: physical\n");
2203        break;
2204    case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2205        dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
2206        break;
2207    default:
2208        assert(false);
2209    }
2210
2211    switch (mCalibration.pressureSource) {
2212    case Calibration::PRESSURE_SOURCE_PRESSURE:
2213        dump.append(INDENT4 "touch.pressure.source: pressure\n");
2214        break;
2215    case Calibration::PRESSURE_SOURCE_TOUCH:
2216        dump.append(INDENT4 "touch.pressure.source: touch\n");
2217        break;
2218    case Calibration::PRESSURE_SOURCE_DEFAULT:
2219        break;
2220    default:
2221        assert(false);
2222    }
2223
2224    if (mCalibration.havePressureScale) {
2225        dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
2226                mCalibration.pressureScale);
2227    }
2228
2229    // Size
2230    switch (mCalibration.sizeCalibration) {
2231    case Calibration::SIZE_CALIBRATION_NONE:
2232        dump.append(INDENT4 "touch.size.calibration: none\n");
2233        break;
2234    case Calibration::SIZE_CALIBRATION_NORMALIZED:
2235        dump.append(INDENT4 "touch.size.calibration: normalized\n");
2236        break;
2237    default:
2238        assert(false);
2239    }
2240
2241    // Orientation
2242    switch (mCalibration.orientationCalibration) {
2243    case Calibration::ORIENTATION_CALIBRATION_NONE:
2244        dump.append(INDENT4 "touch.orientation.calibration: none\n");
2245        break;
2246    case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2247        dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
2248        break;
2249    case Calibration::ORIENTATION_CALIBRATION_VECTOR:
2250        dump.append(INDENT4 "touch.orientation.calibration: vector\n");
2251        break;
2252    default:
2253        assert(false);
2254    }
2255}
2256
2257void TouchInputMapper::reset() {
2258    // Synthesize touch up event if touch is currently down.
2259    // This will also take care of finishing virtual key processing if needed.
2260    if (mLastTouch.pointerCount != 0) {
2261        nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2262        mCurrentTouch.clear();
2263        syncTouch(when, true);
2264    }
2265
2266    { // acquire lock
2267        AutoMutex _l(mLock);
2268        initializeLocked();
2269    } // release lock
2270
2271    InputMapper::reset();
2272}
2273
2274void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
2275    uint32_t policyFlags = 0;
2276
2277    // Preprocess pointer data.
2278
2279    if (mParameters.useBadTouchFilter) {
2280        if (applyBadTouchFilter()) {
2281            havePointerIds = false;
2282        }
2283    }
2284
2285    if (mParameters.useJumpyTouchFilter) {
2286        if (applyJumpyTouchFilter()) {
2287            havePointerIds = false;
2288        }
2289    }
2290
2291    if (! havePointerIds) {
2292        calculatePointerIds();
2293    }
2294
2295    TouchData temp;
2296    TouchData* savedTouch;
2297    if (mParameters.useAveragingTouchFilter) {
2298        temp.copyFrom(mCurrentTouch);
2299        savedTouch = & temp;
2300
2301        applyAveragingTouchFilter();
2302    } else {
2303        savedTouch = & mCurrentTouch;
2304    }
2305
2306    // Process touches and virtual keys.
2307
2308    TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2309    if (touchResult == DISPATCH_TOUCH) {
2310        detectGestures(when);
2311        dispatchTouches(when, policyFlags);
2312    }
2313
2314    // Copy current touch to last touch in preparation for the next cycle.
2315
2316    if (touchResult == DROP_STROKE) {
2317        mLastTouch.clear();
2318    } else {
2319        mLastTouch.copyFrom(*savedTouch);
2320    }
2321}
2322
2323TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2324        nsecs_t when, uint32_t policyFlags) {
2325    int32_t keyEventAction, keyEventFlags;
2326    int32_t keyCode, scanCode, downTime;
2327    TouchResult touchResult;
2328
2329    { // acquire lock
2330        AutoMutex _l(mLock);
2331
2332        // Update surface size and orientation, including virtual key positions.
2333        if (! configureSurfaceLocked()) {
2334            return DROP_STROKE;
2335        }
2336
2337        // Check for virtual key press.
2338        if (mLocked.currentVirtualKey.down) {
2339            if (mCurrentTouch.pointerCount == 0) {
2340                // Pointer went up while virtual key was down.
2341                mLocked.currentVirtualKey.down = false;
2342#if DEBUG_VIRTUAL_KEYS
2343                LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
2344                        mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
2345#endif
2346                keyEventAction = AKEY_EVENT_ACTION_UP;
2347                keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2348                touchResult = SKIP_TOUCH;
2349                goto DispatchVirtualKey;
2350            }
2351
2352            if (mCurrentTouch.pointerCount == 1) {
2353                int32_t x = mCurrentTouch.pointers[0].x;
2354                int32_t y = mCurrentTouch.pointers[0].y;
2355                const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2356                if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
2357                    // Pointer is still within the space of the virtual key.
2358                    return SKIP_TOUCH;
2359                }
2360            }
2361
2362            // Pointer left virtual key area or another pointer also went down.
2363            // Send key cancellation and drop the stroke so subsequent motions will be
2364            // considered fresh downs.  This is useful when the user swipes away from the
2365            // virtual key area into the main display surface.
2366            mLocked.currentVirtualKey.down = false;
2367#if DEBUG_VIRTUAL_KEYS
2368            LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
2369                    mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
2370#endif
2371            keyEventAction = AKEY_EVENT_ACTION_UP;
2372            keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2373                    | AKEY_EVENT_FLAG_CANCELED;
2374
2375            // Check whether the pointer moved inside the display area where we should
2376            // start a new stroke.
2377            int32_t x = mCurrentTouch.pointers[0].x;
2378            int32_t y = mCurrentTouch.pointers[0].y;
2379            if (isPointInsideSurfaceLocked(x, y)) {
2380                mLastTouch.clear();
2381                touchResult = DISPATCH_TOUCH;
2382            } else {
2383                touchResult = DROP_STROKE;
2384            }
2385        } else {
2386            if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2387                // Pointer just went down.  Handle off-screen touches, if needed.
2388                int32_t x = mCurrentTouch.pointers[0].x;
2389                int32_t y = mCurrentTouch.pointers[0].y;
2390                if (! isPointInsideSurfaceLocked(x, y)) {
2391                    // If exactly one pointer went down, check for virtual key hit.
2392                    // Otherwise we will drop the entire stroke.
2393                    if (mCurrentTouch.pointerCount == 1) {
2394                        const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2395                        if (virtualKey) {
2396                            if (mContext->shouldDropVirtualKey(when, getDevice(),
2397                                    virtualKey->keyCode, virtualKey->scanCode)) {
2398                                return DROP_STROKE;
2399                            }
2400
2401                            mLocked.currentVirtualKey.down = true;
2402                            mLocked.currentVirtualKey.downTime = when;
2403                            mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2404                            mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
2405#if DEBUG_VIRTUAL_KEYS
2406                            LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
2407                                    mLocked.currentVirtualKey.keyCode,
2408                                    mLocked.currentVirtualKey.scanCode);
2409#endif
2410                            keyEventAction = AKEY_EVENT_ACTION_DOWN;
2411                            keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2412                                    | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2413                            touchResult = SKIP_TOUCH;
2414                            goto DispatchVirtualKey;
2415                        }
2416                    }
2417                    return DROP_STROKE;
2418                }
2419            }
2420            return DISPATCH_TOUCH;
2421        }
2422
2423    DispatchVirtualKey:
2424        // Collect remaining state needed to dispatch virtual key.
2425        keyCode = mLocked.currentVirtualKey.keyCode;
2426        scanCode = mLocked.currentVirtualKey.scanCode;
2427        downTime = mLocked.currentVirtualKey.downTime;
2428    } // release lock
2429
2430    // Dispatch virtual key.
2431    int32_t metaState = mContext->getGlobalMetaState();
2432    policyFlags |= POLICY_FLAG_VIRTUAL;
2433    getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
2434            keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2435    return touchResult;
2436}
2437
2438void TouchInputMapper::detectGestures(nsecs_t when) {
2439    // Disable all virtual key touches that happen within a short time interval of the
2440    // most recent touch.  The idea is to filter out stray virtual key presses when
2441    // interacting with the touch screen.
2442    //
2443    // Problems we're trying to solve:
2444    //
2445    // 1. While scrolling a list or dragging the window shade, the user swipes down into a
2446    //    virtual key area that is implemented by a separate touch panel and accidentally
2447    //    triggers a virtual key.
2448    //
2449    // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
2450    //    area and accidentally triggers a virtual key.  This often happens when virtual keys
2451    //    are layed out below the screen near to where the on screen keyboard's space bar
2452    //    is displayed.
2453    if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
2454        mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime);
2455    }
2456}
2457
2458void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2459    uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2460    uint32_t lastPointerCount = mLastTouch.pointerCount;
2461    if (currentPointerCount == 0 && lastPointerCount == 0) {
2462        return; // nothing to do!
2463    }
2464
2465    BitSet32 currentIdBits = mCurrentTouch.idBits;
2466    BitSet32 lastIdBits = mLastTouch.idBits;
2467
2468    if (currentIdBits == lastIdBits) {
2469        // No pointer id changes so this is a move event.
2470        // The dispatcher takes care of batching moves so we don't have to deal with that here.
2471        int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
2472        dispatchTouch(when, policyFlags, & mCurrentTouch,
2473                currentIdBits, -1, currentPointerCount, motionEventAction);
2474    } else {
2475        // There may be pointers going up and pointers going down and pointers moving
2476        // all at the same time.
2477        BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2478        BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2479        BitSet32 activeIdBits(lastIdBits.value);
2480        uint32_t pointerCount = lastPointerCount;
2481
2482        // Produce an intermediate representation of the touch data that consists of the
2483        // old location of pointers that have just gone up and the new location of pointers that
2484        // have just moved but omits the location of pointers that have just gone down.
2485        TouchData interimTouch;
2486        interimTouch.copyFrom(mLastTouch);
2487
2488        BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
2489        bool moveNeeded = false;
2490        while (!moveIdBits.isEmpty()) {
2491            uint32_t moveId = moveIdBits.firstMarkedBit();
2492            moveIdBits.clearBit(moveId);
2493
2494            int32_t oldIndex = mLastTouch.idToIndex[moveId];
2495            int32_t newIndex = mCurrentTouch.idToIndex[moveId];
2496            if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
2497                interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
2498                moveNeeded = true;
2499            }
2500        }
2501
2502        // Dispatch pointer up events using the interim pointer locations.
2503        while (!upIdBits.isEmpty()) {
2504            uint32_t upId = upIdBits.firstMarkedBit();
2505            upIdBits.clearBit(upId);
2506            BitSet32 oldActiveIdBits = activeIdBits;
2507            activeIdBits.clearBit(upId);
2508
2509            int32_t motionEventAction;
2510            if (activeIdBits.isEmpty()) {
2511                motionEventAction = AMOTION_EVENT_ACTION_UP;
2512            } else {
2513                motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
2514            }
2515
2516            dispatchTouch(when, policyFlags, &interimTouch,
2517                    oldActiveIdBits, upId, pointerCount, motionEventAction);
2518            pointerCount -= 1;
2519        }
2520
2521        // Dispatch move events if any of the remaining pointers moved from their old locations.
2522        // Although applications receive new locations as part of individual pointer up
2523        // events, they do not generally handle them except when presented in a move event.
2524        if (moveNeeded) {
2525            dispatchTouch(when, policyFlags, &mCurrentTouch,
2526                    activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
2527        }
2528
2529        // Dispatch pointer down events using the new pointer locations.
2530        while (!downIdBits.isEmpty()) {
2531            uint32_t downId = downIdBits.firstMarkedBit();
2532            downIdBits.clearBit(downId);
2533            BitSet32 oldActiveIdBits = activeIdBits;
2534            activeIdBits.markBit(downId);
2535
2536            int32_t motionEventAction;
2537            if (oldActiveIdBits.isEmpty()) {
2538                motionEventAction = AMOTION_EVENT_ACTION_DOWN;
2539                mDownTime = when;
2540            } else {
2541                motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
2542            }
2543
2544            pointerCount += 1;
2545            dispatchTouch(when, policyFlags, &mCurrentTouch,
2546                    activeIdBits, downId, pointerCount, motionEventAction);
2547        }
2548    }
2549}
2550
2551void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
2552        TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
2553        int32_t motionEventAction) {
2554    int32_t pointerIds[MAX_POINTERS];
2555    PointerCoords pointerCoords[MAX_POINTERS];
2556    int32_t motionEventEdgeFlags = 0;
2557    float xPrecision, yPrecision;
2558
2559    { // acquire lock
2560        AutoMutex _l(mLock);
2561
2562        // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2563        // display coordinates (PointerCoords) and adjust for display orientation.
2564        for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
2565            uint32_t id = idBits.firstMarkedBit();
2566            idBits.clearBit(id);
2567            uint32_t inIndex = touch->idToIndex[id];
2568
2569            const PointerData& in = touch->pointers[inIndex];
2570
2571            // X and Y
2572            float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
2573            float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
2574
2575            // ToolMajor and ToolMinor
2576            float toolMajor, toolMinor;
2577            switch (mCalibration.toolSizeCalibration) {
2578            case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
2579                toolMajor = in.toolMajor * mLocked.geometricScale;
2580                if (mRawAxes.toolMinor.valid) {
2581                    toolMinor = in.toolMinor * mLocked.geometricScale;
2582                } else {
2583                    toolMinor = toolMajor;
2584                }
2585                break;
2586            case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
2587                toolMajor = in.toolMajor != 0
2588                        ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
2589                        : 0;
2590                if (mRawAxes.toolMinor.valid) {
2591                    toolMinor = in.toolMinor != 0
2592                            ? in.toolMinor * mLocked.toolSizeLinearScale
2593                                    + mLocked.toolSizeLinearBias
2594                            : 0;
2595                } else {
2596                    toolMinor = toolMajor;
2597                }
2598                break;
2599            case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2600                if (in.toolMajor != 0) {
2601                    float diameter = sqrtf(in.toolMajor
2602                            * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
2603                    toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
2604                } else {
2605                    toolMajor = 0;
2606                }
2607                toolMinor = toolMajor;
2608                break;
2609            default:
2610                toolMajor = 0;
2611                toolMinor = 0;
2612                break;
2613            }
2614
2615            if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
2616                toolMajor /= pointerCount;
2617                toolMinor /= pointerCount;
2618            }
2619
2620            // Pressure
2621            float rawPressure;
2622            switch (mCalibration.pressureSource) {
2623            case Calibration::PRESSURE_SOURCE_PRESSURE:
2624                rawPressure = in.pressure;
2625                break;
2626            case Calibration::PRESSURE_SOURCE_TOUCH:
2627                rawPressure = in.touchMajor;
2628                break;
2629            default:
2630                rawPressure = 0;
2631            }
2632
2633            float pressure;
2634            switch (mCalibration.pressureCalibration) {
2635            case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2636            case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2637                pressure = rawPressure * mLocked.pressureScale;
2638                break;
2639            default:
2640                pressure = 1;
2641                break;
2642            }
2643
2644            // TouchMajor and TouchMinor
2645            float touchMajor, touchMinor;
2646            switch (mCalibration.touchSizeCalibration) {
2647            case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
2648                touchMajor = in.touchMajor * mLocked.geometricScale;
2649                if (mRawAxes.touchMinor.valid) {
2650                    touchMinor = in.touchMinor * mLocked.geometricScale;
2651                } else {
2652                    touchMinor = touchMajor;
2653                }
2654                break;
2655            case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
2656                touchMajor = toolMajor * pressure;
2657                touchMinor = toolMinor * pressure;
2658                break;
2659            default:
2660                touchMajor = 0;
2661                touchMinor = 0;
2662                break;
2663            }
2664
2665            if (touchMajor > toolMajor) {
2666                touchMajor = toolMajor;
2667            }
2668            if (touchMinor > toolMinor) {
2669                touchMinor = toolMinor;
2670            }
2671
2672            // Size
2673            float size;
2674            switch (mCalibration.sizeCalibration) {
2675            case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2676                float rawSize = mRawAxes.toolMinor.valid
2677                        ? avg(in.toolMajor, in.toolMinor)
2678                        : in.toolMajor;
2679                size = rawSize * mLocked.sizeScale;
2680                break;
2681            }
2682            default:
2683                size = 0;
2684                break;
2685            }
2686
2687            // Orientation
2688            float orientation;
2689            switch (mCalibration.orientationCalibration) {
2690            case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2691                orientation = in.orientation * mLocked.orientationScale;
2692                break;
2693            case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
2694                int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
2695                int32_t c2 = signExtendNybble(in.orientation & 0x0f);
2696                if (c1 != 0 || c2 != 0) {
2697                    orientation = atan2f(c1, c2) * 0.5f;
2698                    float scale = 1.0f + pythag(c1, c2) / 16.0f;
2699                    touchMajor *= scale;
2700                    touchMinor /= scale;
2701                    toolMajor *= scale;
2702                    toolMinor /= scale;
2703                } else {
2704                    orientation = 0;
2705                }
2706                break;
2707            }
2708            default:
2709                orientation = 0;
2710            }
2711
2712            // Adjust coords for orientation.
2713            switch (mLocked.surfaceOrientation) {
2714            case DISPLAY_ORIENTATION_90: {
2715                float xTemp = x;
2716                x = y;
2717                y = mLocked.surfaceWidth - xTemp;
2718                orientation -= M_PI_2;
2719                if (orientation < - M_PI_2) {
2720                    orientation += M_PI;
2721                }
2722                break;
2723            }
2724            case DISPLAY_ORIENTATION_180: {
2725                x = mLocked.surfaceWidth - x;
2726                y = mLocked.surfaceHeight - y;
2727                break;
2728            }
2729            case DISPLAY_ORIENTATION_270: {
2730                float xTemp = x;
2731                x = mLocked.surfaceHeight - y;
2732                y = xTemp;
2733                orientation += M_PI_2;
2734                if (orientation > M_PI_2) {
2735                    orientation -= M_PI;
2736                }
2737                break;
2738            }
2739            }
2740
2741            // Write output coords.
2742            PointerCoords& out = pointerCoords[outIndex];
2743            out.clear();
2744            out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
2745            out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
2746            out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
2747            out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
2748            out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
2749            out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
2750            out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
2751            out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
2752            out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
2753
2754            pointerIds[outIndex] = int32_t(id);
2755
2756            if (id == changedId) {
2757                motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
2758            }
2759        }
2760
2761        // Check edge flags by looking only at the first pointer since the flags are
2762        // global to the event.
2763        if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
2764            float x = pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X);
2765            float y = pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y);
2766
2767            if (x <= 0) {
2768                motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
2769            } else if (x >= mLocked.orientedSurfaceWidth) {
2770                motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
2771            }
2772            if (y <= 0) {
2773                motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
2774            } else if (y >= mLocked.orientedSurfaceHeight) {
2775                motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
2776            }
2777        }
2778
2779        xPrecision = mLocked.orientedXPrecision;
2780        yPrecision = mLocked.orientedYPrecision;
2781    } // release lock
2782
2783    getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
2784            motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
2785            pointerCount, pointerIds, pointerCoords,
2786            xPrecision, yPrecision, mDownTime);
2787}
2788
2789bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
2790    if (mRawAxes.x.valid && mRawAxes.y.valid) {
2791        return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2792                && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
2793    }
2794    return true;
2795}
2796
2797const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2798        int32_t x, int32_t y) {
2799    size_t numVirtualKeys = mLocked.virtualKeys.size();
2800    for (size_t i = 0; i < numVirtualKeys; i++) {
2801        const VirtualKey& virtualKey = mLocked.virtualKeys[i];
2802
2803#if DEBUG_VIRTUAL_KEYS
2804        LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2805                "left=%d, top=%d, right=%d, bottom=%d",
2806                x, y,
2807                virtualKey.keyCode, virtualKey.scanCode,
2808                virtualKey.hitLeft, virtualKey.hitTop,
2809                virtualKey.hitRight, virtualKey.hitBottom);
2810#endif
2811
2812        if (virtualKey.isHit(x, y)) {
2813            return & virtualKey;
2814        }
2815    }
2816
2817    return NULL;
2818}
2819
2820void TouchInputMapper::calculatePointerIds() {
2821    uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2822    uint32_t lastPointerCount = mLastTouch.pointerCount;
2823
2824    if (currentPointerCount == 0) {
2825        // No pointers to assign.
2826        mCurrentTouch.idBits.clear();
2827    } else if (lastPointerCount == 0) {
2828        // All pointers are new.
2829        mCurrentTouch.idBits.clear();
2830        for (uint32_t i = 0; i < currentPointerCount; i++) {
2831            mCurrentTouch.pointers[i].id = i;
2832            mCurrentTouch.idToIndex[i] = i;
2833            mCurrentTouch.idBits.markBit(i);
2834        }
2835    } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2836        // Only one pointer and no change in count so it must have the same id as before.
2837        uint32_t id = mLastTouch.pointers[0].id;
2838        mCurrentTouch.pointers[0].id = id;
2839        mCurrentTouch.idToIndex[id] = 0;
2840        mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2841    } else {
2842        // General case.
2843        // We build a heap of squared euclidean distances between current and last pointers
2844        // associated with the current and last pointer indices.  Then, we find the best
2845        // match (by distance) for each current pointer.
2846        PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2847
2848        uint32_t heapSize = 0;
2849        for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2850                currentPointerIndex++) {
2851            for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2852                    lastPointerIndex++) {
2853                int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2854                        - mLastTouch.pointers[lastPointerIndex].x;
2855                int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2856                        - mLastTouch.pointers[lastPointerIndex].y;
2857
2858                uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2859
2860                // Insert new element into the heap (sift up).
2861                heap[heapSize].currentPointerIndex = currentPointerIndex;
2862                heap[heapSize].lastPointerIndex = lastPointerIndex;
2863                heap[heapSize].distance = distance;
2864                heapSize += 1;
2865            }
2866        }
2867
2868        // Heapify
2869        for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2870            startIndex -= 1;
2871            for (uint32_t parentIndex = startIndex; ;) {
2872                uint32_t childIndex = parentIndex * 2 + 1;
2873                if (childIndex >= heapSize) {
2874                    break;
2875                }
2876
2877                if (childIndex + 1 < heapSize
2878                        && heap[childIndex + 1].distance < heap[childIndex].distance) {
2879                    childIndex += 1;
2880                }
2881
2882                if (heap[parentIndex].distance <= heap[childIndex].distance) {
2883                    break;
2884                }
2885
2886                swap(heap[parentIndex], heap[childIndex]);
2887                parentIndex = childIndex;
2888            }
2889        }
2890
2891#if DEBUG_POINTER_ASSIGNMENT
2892        LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2893        for (size_t i = 0; i < heapSize; i++) {
2894            LOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
2895                    i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2896                    heap[i].distance);
2897        }
2898#endif
2899
2900        // Pull matches out by increasing order of distance.
2901        // To avoid reassigning pointers that have already been matched, the loop keeps track
2902        // of which last and current pointers have been matched using the matchedXXXBits variables.
2903        // It also tracks the used pointer id bits.
2904        BitSet32 matchedLastBits(0);
2905        BitSet32 matchedCurrentBits(0);
2906        BitSet32 usedIdBits(0);
2907        bool first = true;
2908        for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2909            for (;;) {
2910                if (first) {
2911                    // The first time through the loop, we just consume the root element of
2912                    // the heap (the one with smallest distance).
2913                    first = false;
2914                } else {
2915                    // Previous iterations consumed the root element of the heap.
2916                    // Pop root element off of the heap (sift down).
2917                    heapSize -= 1;
2918                    assert(heapSize > 0);
2919
2920                    // Sift down.
2921                    heap[0] = heap[heapSize];
2922                    for (uint32_t parentIndex = 0; ;) {
2923                        uint32_t childIndex = parentIndex * 2 + 1;
2924                        if (childIndex >= heapSize) {
2925                            break;
2926                        }
2927
2928                        if (childIndex + 1 < heapSize
2929                                && heap[childIndex + 1].distance < heap[childIndex].distance) {
2930                            childIndex += 1;
2931                        }
2932
2933                        if (heap[parentIndex].distance <= heap[childIndex].distance) {
2934                            break;
2935                        }
2936
2937                        swap(heap[parentIndex], heap[childIndex]);
2938                        parentIndex = childIndex;
2939                    }
2940
2941#if DEBUG_POINTER_ASSIGNMENT
2942                    LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
2943                    for (size_t i = 0; i < heapSize; i++) {
2944                        LOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
2945                                i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2946                                heap[i].distance);
2947                    }
2948#endif
2949                }
2950
2951                uint32_t currentPointerIndex = heap[0].currentPointerIndex;
2952                if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
2953
2954                uint32_t lastPointerIndex = heap[0].lastPointerIndex;
2955                if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
2956
2957                matchedCurrentBits.markBit(currentPointerIndex);
2958                matchedLastBits.markBit(lastPointerIndex);
2959
2960                uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
2961                mCurrentTouch.pointers[currentPointerIndex].id = id;
2962                mCurrentTouch.idToIndex[id] = currentPointerIndex;
2963                usedIdBits.markBit(id);
2964
2965#if DEBUG_POINTER_ASSIGNMENT
2966                LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
2967                        lastPointerIndex, currentPointerIndex, id, heap[0].distance);
2968#endif
2969                break;
2970            }
2971        }
2972
2973        // Assign fresh ids to new pointers.
2974        if (currentPointerCount > lastPointerCount) {
2975            for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
2976                uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
2977                uint32_t id = usedIdBits.firstUnmarkedBit();
2978
2979                mCurrentTouch.pointers[currentPointerIndex].id = id;
2980                mCurrentTouch.idToIndex[id] = currentPointerIndex;
2981                usedIdBits.markBit(id);
2982
2983#if DEBUG_POINTER_ASSIGNMENT
2984                LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
2985                        currentPointerIndex, id);
2986#endif
2987
2988                if (--i == 0) break; // done
2989                matchedCurrentBits.markBit(currentPointerIndex);
2990            }
2991        }
2992
2993        // Fix id bits.
2994        mCurrentTouch.idBits = usedIdBits;
2995    }
2996}
2997
2998/* Special hack for devices that have bad screen data: if one of the
2999 * points has moved more than a screen height from the last position,
3000 * then drop it. */
3001bool TouchInputMapper::applyBadTouchFilter() {
3002    // This hack requires valid axis parameters.
3003    if (! mRawAxes.y.valid) {
3004        return false;
3005    }
3006
3007    uint32_t pointerCount = mCurrentTouch.pointerCount;
3008
3009    // Nothing to do if there are no points.
3010    if (pointerCount == 0) {
3011        return false;
3012    }
3013
3014    // Don't do anything if a finger is going down or up.  We run
3015    // here before assigning pointer IDs, so there isn't a good
3016    // way to do per-finger matching.
3017    if (pointerCount != mLastTouch.pointerCount) {
3018        return false;
3019    }
3020
3021    // We consider a single movement across more than a 7/16 of
3022    // the long size of the screen to be bad.  This was a magic value
3023    // determined by looking at the maximum distance it is feasible
3024    // to actually move in one sample.
3025    int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
3026
3027    // XXX The original code in InputDevice.java included commented out
3028    //     code for testing the X axis.  Note that when we drop a point
3029    //     we don't actually restore the old X either.  Strange.
3030    //     The old code also tries to track when bad points were previously
3031    //     detected but it turns out that due to the placement of a "break"
3032    //     at the end of the loop, we never set mDroppedBadPoint to true
3033    //     so it is effectively dead code.
3034    // Need to figure out if the old code is busted or just overcomplicated
3035    // but working as intended.
3036
3037    // Look through all new points and see if any are farther than
3038    // acceptable from all previous points.
3039    for (uint32_t i = pointerCount; i-- > 0; ) {
3040        int32_t y = mCurrentTouch.pointers[i].y;
3041        int32_t closestY = INT_MAX;
3042        int32_t closestDeltaY = 0;
3043
3044#if DEBUG_HACKS
3045        LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
3046#endif
3047
3048        for (uint32_t j = pointerCount; j-- > 0; ) {
3049            int32_t lastY = mLastTouch.pointers[j].y;
3050            int32_t deltaY = abs(y - lastY);
3051
3052#if DEBUG_HACKS
3053            LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
3054                    j, lastY, deltaY);
3055#endif
3056
3057            if (deltaY < maxDeltaY) {
3058                goto SkipSufficientlyClosePoint;
3059            }
3060            if (deltaY < closestDeltaY) {
3061                closestDeltaY = deltaY;
3062                closestY = lastY;
3063            }
3064        }
3065
3066        // Must not have found a close enough match.
3067#if DEBUG_HACKS
3068        LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
3069                i, y, closestY, closestDeltaY, maxDeltaY);
3070#endif
3071
3072        mCurrentTouch.pointers[i].y = closestY;
3073        return true; // XXX original code only corrects one point
3074
3075    SkipSufficientlyClosePoint: ;
3076    }
3077
3078    // No change.
3079    return false;
3080}
3081
3082/* Special hack for devices that have bad screen data: drop points where
3083 * the coordinate value for one axis has jumped to the other pointer's location.
3084 */
3085bool TouchInputMapper::applyJumpyTouchFilter() {
3086    // This hack requires valid axis parameters.
3087    if (! mRawAxes.y.valid) {
3088        return false;
3089    }
3090
3091    uint32_t pointerCount = mCurrentTouch.pointerCount;
3092    if (mLastTouch.pointerCount != pointerCount) {
3093#if DEBUG_HACKS
3094        LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
3095                mLastTouch.pointerCount, pointerCount);
3096        for (uint32_t i = 0; i < pointerCount; i++) {
3097            LOGD("  Pointer %d (%d, %d)", i,
3098                    mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3099        }
3100#endif
3101
3102        if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
3103            if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
3104                // Just drop the first few events going from 1 to 2 pointers.
3105                // They're bad often enough that they're not worth considering.
3106                mCurrentTouch.pointerCount = 1;
3107                mJumpyTouchFilter.jumpyPointsDropped += 1;
3108
3109#if DEBUG_HACKS
3110                LOGD("JumpyTouchFilter: Pointer 2 dropped");
3111#endif
3112                return true;
3113            } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
3114                // The event when we go from 2 -> 1 tends to be messed up too
3115                mCurrentTouch.pointerCount = 2;
3116                mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
3117                mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
3118                mJumpyTouchFilter.jumpyPointsDropped += 1;
3119
3120#if DEBUG_HACKS
3121                for (int32_t i = 0; i < 2; i++) {
3122                    LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
3123                            mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3124                }
3125#endif
3126                return true;
3127            }
3128        }
3129        // Reset jumpy points dropped on other transitions or if limit exceeded.
3130        mJumpyTouchFilter.jumpyPointsDropped = 0;
3131
3132#if DEBUG_HACKS
3133        LOGD("JumpyTouchFilter: Transition - drop limit reset");
3134#endif
3135        return false;
3136    }
3137
3138    // We have the same number of pointers as last time.
3139    // A 'jumpy' point is one where the coordinate value for one axis
3140    // has jumped to the other pointer's location. No need to do anything
3141    // else if we only have one pointer.
3142    if (pointerCount < 2) {
3143        return false;
3144    }
3145
3146    if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
3147        int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
3148
3149        // We only replace the single worst jumpy point as characterized by pointer distance
3150        // in a single axis.
3151        int32_t badPointerIndex = -1;
3152        int32_t badPointerReplacementIndex = -1;
3153        int32_t badPointerDistance = INT_MIN; // distance to be corrected
3154
3155        for (uint32_t i = pointerCount; i-- > 0; ) {
3156            int32_t x = mCurrentTouch.pointers[i].x;
3157            int32_t y = mCurrentTouch.pointers[i].y;
3158
3159#if DEBUG_HACKS
3160            LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
3161#endif
3162
3163            // Check if a touch point is too close to another's coordinates
3164            bool dropX = false, dropY = false;
3165            for (uint32_t j = 0; j < pointerCount; j++) {
3166                if (i == j) {
3167                    continue;
3168                }
3169
3170                if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
3171                    dropX = true;
3172                    break;
3173                }
3174
3175                if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
3176                    dropY = true;
3177                    break;
3178                }
3179            }
3180            if (! dropX && ! dropY) {
3181                continue; // not jumpy
3182            }
3183
3184            // Find a replacement candidate by comparing with older points on the
3185            // complementary (non-jumpy) axis.
3186            int32_t distance = INT_MIN; // distance to be corrected
3187            int32_t replacementIndex = -1;
3188
3189            if (dropX) {
3190                // X looks too close.  Find an older replacement point with a close Y.
3191                int32_t smallestDeltaY = INT_MAX;
3192                for (uint32_t j = 0; j < pointerCount; j++) {
3193                    int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
3194                    if (deltaY < smallestDeltaY) {
3195                        smallestDeltaY = deltaY;
3196                        replacementIndex = j;
3197                    }
3198                }
3199                distance = abs(x - mLastTouch.pointers[replacementIndex].x);
3200            } else {
3201                // Y looks too close.  Find an older replacement point with a close X.
3202                int32_t smallestDeltaX = INT_MAX;
3203                for (uint32_t j = 0; j < pointerCount; j++) {
3204                    int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
3205                    if (deltaX < smallestDeltaX) {
3206                        smallestDeltaX = deltaX;
3207                        replacementIndex = j;
3208                    }
3209                }
3210                distance = abs(y - mLastTouch.pointers[replacementIndex].y);
3211            }
3212
3213            // If replacing this pointer would correct a worse error than the previous ones
3214            // considered, then use this replacement instead.
3215            if (distance > badPointerDistance) {
3216                badPointerIndex = i;
3217                badPointerReplacementIndex = replacementIndex;
3218                badPointerDistance = distance;
3219            }
3220        }
3221
3222        // Correct the jumpy pointer if one was found.
3223        if (badPointerIndex >= 0) {
3224#if DEBUG_HACKS
3225            LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
3226                    badPointerIndex,
3227                    mLastTouch.pointers[badPointerReplacementIndex].x,
3228                    mLastTouch.pointers[badPointerReplacementIndex].y);
3229#endif
3230
3231            mCurrentTouch.pointers[badPointerIndex].x =
3232                    mLastTouch.pointers[badPointerReplacementIndex].x;
3233            mCurrentTouch.pointers[badPointerIndex].y =
3234                    mLastTouch.pointers[badPointerReplacementIndex].y;
3235            mJumpyTouchFilter.jumpyPointsDropped += 1;
3236            return true;
3237        }
3238    }
3239
3240    mJumpyTouchFilter.jumpyPointsDropped = 0;
3241    return false;
3242}
3243
3244/* Special hack for devices that have bad screen data: aggregate and
3245 * compute averages of the coordinate data, to reduce the amount of
3246 * jitter seen by applications. */
3247void TouchInputMapper::applyAveragingTouchFilter() {
3248    for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
3249        uint32_t id = mCurrentTouch.pointers[currentIndex].id;
3250        int32_t x = mCurrentTouch.pointers[currentIndex].x;
3251        int32_t y = mCurrentTouch.pointers[currentIndex].y;
3252        int32_t pressure;
3253        switch (mCalibration.pressureSource) {
3254        case Calibration::PRESSURE_SOURCE_PRESSURE:
3255            pressure = mCurrentTouch.pointers[currentIndex].pressure;
3256            break;
3257        case Calibration::PRESSURE_SOURCE_TOUCH:
3258            pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
3259            break;
3260        default:
3261            pressure = 1;
3262            break;
3263        }
3264
3265        if (mLastTouch.idBits.hasBit(id)) {
3266            // Pointer was down before and is still down now.
3267            // Compute average over history trace.
3268            uint32_t start = mAveragingTouchFilter.historyStart[id];
3269            uint32_t end = mAveragingTouchFilter.historyEnd[id];
3270
3271            int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
3272            int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
3273            uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
3274
3275#if DEBUG_HACKS
3276            LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
3277                    id, distance);
3278#endif
3279
3280            if (distance < AVERAGING_DISTANCE_LIMIT) {
3281                // Increment end index in preparation for recording new historical data.
3282                end += 1;
3283                if (end > AVERAGING_HISTORY_SIZE) {
3284                    end = 0;
3285                }
3286
3287                // If the end index has looped back to the start index then we have filled
3288                // the historical trace up to the desired size so we drop the historical
3289                // data at the start of the trace.
3290                if (end == start) {
3291                    start += 1;
3292                    if (start > AVERAGING_HISTORY_SIZE) {
3293                        start = 0;
3294                    }
3295                }
3296
3297                // Add the raw data to the historical trace.
3298                mAveragingTouchFilter.historyStart[id] = start;
3299                mAveragingTouchFilter.historyEnd[id] = end;
3300                mAveragingTouchFilter.historyData[end].pointers[id].x = x;
3301                mAveragingTouchFilter.historyData[end].pointers[id].y = y;
3302                mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
3303
3304                // Average over all historical positions in the trace by total pressure.
3305                int32_t averagedX = 0;
3306                int32_t averagedY = 0;
3307                int32_t totalPressure = 0;
3308                for (;;) {
3309                    int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
3310                    int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
3311                    int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
3312                            .pointers[id].pressure;
3313
3314                    averagedX += historicalX * historicalPressure;
3315                    averagedY += historicalY * historicalPressure;
3316                    totalPressure += historicalPressure;
3317
3318                    if (start == end) {
3319                        break;
3320                    }
3321
3322                    start += 1;
3323                    if (start > AVERAGING_HISTORY_SIZE) {
3324                        start = 0;
3325                    }
3326                }
3327
3328                if (totalPressure != 0) {
3329                    averagedX /= totalPressure;
3330                    averagedY /= totalPressure;
3331
3332#if DEBUG_HACKS
3333                    LOGD("AveragingTouchFilter: Pointer id %d - "
3334                            "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
3335                            averagedX, averagedY);
3336#endif
3337
3338                    mCurrentTouch.pointers[currentIndex].x = averagedX;
3339                    mCurrentTouch.pointers[currentIndex].y = averagedY;
3340                }
3341            } else {
3342#if DEBUG_HACKS
3343                LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
3344#endif
3345            }
3346        } else {
3347#if DEBUG_HACKS
3348            LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
3349#endif
3350        }
3351
3352        // Reset pointer history.
3353        mAveragingTouchFilter.historyStart[id] = 0;
3354        mAveragingTouchFilter.historyEnd[id] = 0;
3355        mAveragingTouchFilter.historyData[0].pointers[id].x = x;
3356        mAveragingTouchFilter.historyData[0].pointers[id].y = y;
3357        mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
3358    }
3359}
3360
3361int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
3362    { // acquire lock
3363        AutoMutex _l(mLock);
3364
3365        if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
3366            return AKEY_STATE_VIRTUAL;
3367        }
3368
3369        size_t numVirtualKeys = mLocked.virtualKeys.size();
3370        for (size_t i = 0; i < numVirtualKeys; i++) {
3371            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
3372            if (virtualKey.keyCode == keyCode) {
3373                return AKEY_STATE_UP;
3374            }
3375        }
3376    } // release lock
3377
3378    return AKEY_STATE_UNKNOWN;
3379}
3380
3381int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
3382    { // acquire lock
3383        AutoMutex _l(mLock);
3384
3385        if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
3386            return AKEY_STATE_VIRTUAL;
3387        }
3388
3389        size_t numVirtualKeys = mLocked.virtualKeys.size();
3390        for (size_t i = 0; i < numVirtualKeys; i++) {
3391            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
3392            if (virtualKey.scanCode == scanCode) {
3393                return AKEY_STATE_UP;
3394            }
3395        }
3396    } // release lock
3397
3398    return AKEY_STATE_UNKNOWN;
3399}
3400
3401bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3402        const int32_t* keyCodes, uint8_t* outFlags) {
3403    { // acquire lock
3404        AutoMutex _l(mLock);
3405
3406        size_t numVirtualKeys = mLocked.virtualKeys.size();
3407        for (size_t i = 0; i < numVirtualKeys; i++) {
3408            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
3409
3410            for (size_t i = 0; i < numCodes; i++) {
3411                if (virtualKey.keyCode == keyCodes[i]) {
3412                    outFlags[i] = 1;
3413                }
3414            }
3415        }
3416    } // release lock
3417
3418    return true;
3419}
3420
3421
3422// --- SingleTouchInputMapper ---
3423
3424SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
3425        TouchInputMapper(device) {
3426    initialize();
3427}
3428
3429SingleTouchInputMapper::~SingleTouchInputMapper() {
3430}
3431
3432void SingleTouchInputMapper::initialize() {
3433    mAccumulator.clear();
3434
3435    mDown = false;
3436    mX = 0;
3437    mY = 0;
3438    mPressure = 0; // default to 0 for devices that don't report pressure
3439    mToolWidth = 0; // default to 0 for devices that don't report tool width
3440}
3441
3442void SingleTouchInputMapper::reset() {
3443    TouchInputMapper::reset();
3444
3445    initialize();
3446 }
3447
3448void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3449    switch (rawEvent->type) {
3450    case EV_KEY:
3451        switch (rawEvent->scanCode) {
3452        case BTN_TOUCH:
3453            mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3454            mAccumulator.btnTouch = rawEvent->value != 0;
3455            // Don't sync immediately.  Wait until the next SYN_REPORT since we might
3456            // not have received valid position information yet.  This logic assumes that
3457            // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
3458            break;
3459        }
3460        break;
3461
3462    case EV_ABS:
3463        switch (rawEvent->scanCode) {
3464        case ABS_X:
3465            mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3466            mAccumulator.absX = rawEvent->value;
3467            break;
3468        case ABS_Y:
3469            mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3470            mAccumulator.absY = rawEvent->value;
3471            break;
3472        case ABS_PRESSURE:
3473            mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3474            mAccumulator.absPressure = rawEvent->value;
3475            break;
3476        case ABS_TOOL_WIDTH:
3477            mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3478            mAccumulator.absToolWidth = rawEvent->value;
3479            break;
3480        }
3481        break;
3482
3483    case EV_SYN:
3484        switch (rawEvent->scanCode) {
3485        case SYN_REPORT:
3486            sync(rawEvent->when);
3487            break;
3488        }
3489        break;
3490    }
3491}
3492
3493void SingleTouchInputMapper::sync(nsecs_t when) {
3494    uint32_t fields = mAccumulator.fields;
3495    if (fields == 0) {
3496        return; // no new state changes, so nothing to do
3497    }
3498
3499    if (fields & Accumulator::FIELD_BTN_TOUCH) {
3500        mDown = mAccumulator.btnTouch;
3501    }
3502
3503    if (fields & Accumulator::FIELD_ABS_X) {
3504        mX = mAccumulator.absX;
3505    }
3506
3507    if (fields & Accumulator::FIELD_ABS_Y) {
3508        mY = mAccumulator.absY;
3509    }
3510
3511    if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3512        mPressure = mAccumulator.absPressure;
3513    }
3514
3515    if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
3516        mToolWidth = mAccumulator.absToolWidth;
3517    }
3518
3519    mCurrentTouch.clear();
3520
3521    if (mDown) {
3522        mCurrentTouch.pointerCount = 1;
3523        mCurrentTouch.pointers[0].id = 0;
3524        mCurrentTouch.pointers[0].x = mX;
3525        mCurrentTouch.pointers[0].y = mY;
3526        mCurrentTouch.pointers[0].pressure = mPressure;
3527        mCurrentTouch.pointers[0].touchMajor = 0;
3528        mCurrentTouch.pointers[0].touchMinor = 0;
3529        mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3530        mCurrentTouch.pointers[0].toolMinor = mToolWidth;
3531        mCurrentTouch.pointers[0].orientation = 0;
3532        mCurrentTouch.idToIndex[0] = 0;
3533        mCurrentTouch.idBits.markBit(0);
3534    }
3535
3536    syncTouch(when, true);
3537
3538    mAccumulator.clear();
3539}
3540
3541void SingleTouchInputMapper::configureRawAxes() {
3542    TouchInputMapper::configureRawAxes();
3543
3544    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3545    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3546    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3547    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
3548}
3549
3550
3551// --- MultiTouchInputMapper ---
3552
3553MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
3554        TouchInputMapper(device) {
3555    initialize();
3556}
3557
3558MultiTouchInputMapper::~MultiTouchInputMapper() {
3559}
3560
3561void MultiTouchInputMapper::initialize() {
3562    mAccumulator.clear();
3563}
3564
3565void MultiTouchInputMapper::reset() {
3566    TouchInputMapper::reset();
3567
3568    initialize();
3569}
3570
3571void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3572    switch (rawEvent->type) {
3573    case EV_ABS: {
3574        uint32_t pointerIndex = mAccumulator.pointerCount;
3575        Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3576
3577        switch (rawEvent->scanCode) {
3578        case ABS_MT_POSITION_X:
3579            pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3580            pointer->absMTPositionX = rawEvent->value;
3581            break;
3582        case ABS_MT_POSITION_Y:
3583            pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3584            pointer->absMTPositionY = rawEvent->value;
3585            break;
3586        case ABS_MT_TOUCH_MAJOR:
3587            pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3588            pointer->absMTTouchMajor = rawEvent->value;
3589            break;
3590        case ABS_MT_TOUCH_MINOR:
3591            pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3592            pointer->absMTTouchMinor = rawEvent->value;
3593            break;
3594        case ABS_MT_WIDTH_MAJOR:
3595            pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3596            pointer->absMTWidthMajor = rawEvent->value;
3597            break;
3598        case ABS_MT_WIDTH_MINOR:
3599            pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3600            pointer->absMTWidthMinor = rawEvent->value;
3601            break;
3602        case ABS_MT_ORIENTATION:
3603            pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3604            pointer->absMTOrientation = rawEvent->value;
3605            break;
3606        case ABS_MT_TRACKING_ID:
3607            pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3608            pointer->absMTTrackingId = rawEvent->value;
3609            break;
3610        case ABS_MT_PRESSURE:
3611            pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3612            pointer->absMTPressure = rawEvent->value;
3613            break;
3614        }
3615        break;
3616    }
3617
3618    case EV_SYN:
3619        switch (rawEvent->scanCode) {
3620        case SYN_MT_REPORT: {
3621            // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3622            uint32_t pointerIndex = mAccumulator.pointerCount;
3623
3624            if (mAccumulator.pointers[pointerIndex].fields) {
3625                if (pointerIndex == MAX_POINTERS) {
3626                    LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3627                            MAX_POINTERS);
3628                } else {
3629                    pointerIndex += 1;
3630                    mAccumulator.pointerCount = pointerIndex;
3631                }
3632            }
3633
3634            mAccumulator.pointers[pointerIndex].clear();
3635            break;
3636        }
3637
3638        case SYN_REPORT:
3639            sync(rawEvent->when);
3640            break;
3641        }
3642        break;
3643    }
3644}
3645
3646void MultiTouchInputMapper::sync(nsecs_t when) {
3647    static const uint32_t REQUIRED_FIELDS =
3648            Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
3649
3650    uint32_t inCount = mAccumulator.pointerCount;
3651    uint32_t outCount = 0;
3652    bool havePointerIds = true;
3653
3654    mCurrentTouch.clear();
3655
3656    for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
3657        const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3658        uint32_t fields = inPointer.fields;
3659
3660        if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
3661            // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3662            // Drop this finger.
3663            continue;
3664        }
3665
3666        PointerData& outPointer = mCurrentTouch.pointers[outCount];
3667        outPointer.x = inPointer.absMTPositionX;
3668        outPointer.y = inPointer.absMTPositionY;
3669
3670        if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3671            if (inPointer.absMTPressure <= 0) {
3672                // Some devices send sync packets with X / Y but with a 0 pressure to indicate
3673                // a pointer going up.  Drop this finger.
3674                continue;
3675            }
3676            outPointer.pressure = inPointer.absMTPressure;
3677        } else {
3678            // Default pressure to 0 if absent.
3679            outPointer.pressure = 0;
3680        }
3681
3682        if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3683            if (inPointer.absMTTouchMajor <= 0) {
3684                // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3685                // a pointer going up.  Drop this finger.
3686                continue;
3687            }
3688            outPointer.touchMajor = inPointer.absMTTouchMajor;
3689        } else {
3690            // Default touch area to 0 if absent.
3691            outPointer.touchMajor = 0;
3692        }
3693
3694        if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3695            outPointer.touchMinor = inPointer.absMTTouchMinor;
3696        } else {
3697            // Assume touch area is circular.
3698            outPointer.touchMinor = outPointer.touchMajor;
3699        }
3700
3701        if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3702            outPointer.toolMajor = inPointer.absMTWidthMajor;
3703        } else {
3704            // Default tool area to 0 if absent.
3705            outPointer.toolMajor = 0;
3706        }
3707
3708        if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3709            outPointer.toolMinor = inPointer.absMTWidthMinor;
3710        } else {
3711            // Assume tool area is circular.
3712            outPointer.toolMinor = outPointer.toolMajor;
3713        }
3714
3715        if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3716            outPointer.orientation = inPointer.absMTOrientation;
3717        } else {
3718            // Default orientation to vertical if absent.
3719            outPointer.orientation = 0;
3720        }
3721
3722        // Assign pointer id using tracking id if available.
3723        if (havePointerIds) {
3724            if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3725                uint32_t id = uint32_t(inPointer.absMTTrackingId);
3726
3727                if (id > MAX_POINTER_ID) {
3728#if DEBUG_POINTERS
3729                    LOGD("Pointers: Ignoring driver provided pointer id %d because "
3730                            "it is larger than max supported id %d",
3731                            id, MAX_POINTER_ID);
3732#endif
3733                    havePointerIds = false;
3734                }
3735                else {
3736                    outPointer.id = id;
3737                    mCurrentTouch.idToIndex[id] = outCount;
3738                    mCurrentTouch.idBits.markBit(id);
3739                }
3740            } else {
3741                havePointerIds = false;
3742            }
3743        }
3744
3745        outCount += 1;
3746    }
3747
3748    mCurrentTouch.pointerCount = outCount;
3749
3750    syncTouch(when, havePointerIds);
3751
3752    mAccumulator.clear();
3753}
3754
3755void MultiTouchInputMapper::configureRawAxes() {
3756    TouchInputMapper::configureRawAxes();
3757
3758    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3759    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3760    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3761    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3762    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3763    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3764    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3765    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
3766}
3767
3768
3769// --- JoystickInputMapper ---
3770
3771JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
3772        InputMapper(device) {
3773}
3774
3775JoystickInputMapper::~JoystickInputMapper() {
3776}
3777
3778uint32_t JoystickInputMapper::getSources() {
3779    return AINPUT_SOURCE_JOYSTICK;
3780}
3781
3782void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
3783    InputMapper::populateDeviceInfo(info);
3784
3785    for (size_t i = 0; i < mAxes.size(); i++) {
3786        const Axis& axis = mAxes.valueAt(i);
3787        info->addMotionRange(axis.axis, axis.min, axis.max, axis.flat, axis.fuzz);
3788    }
3789}
3790
3791void JoystickInputMapper::dump(String8& dump) {
3792    dump.append(INDENT2 "Joystick Input Mapper:\n");
3793
3794    dump.append(INDENT3 "Axes:\n");
3795    size_t numAxes = mAxes.size();
3796    for (size_t i = 0; i < numAxes; i++) {
3797        const Axis& axis = mAxes.valueAt(i);
3798        const char* label = getAxisLabel(axis.axis);
3799        char name[32];
3800        if (label) {
3801            strncpy(name, label, sizeof(name));
3802            name[sizeof(name) - 1] = '\0';
3803        } else {
3804            snprintf(name, sizeof(name), "%d", axis.axis);
3805        }
3806        dump.appendFormat(INDENT4 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, "
3807                "scale=%0.3f, offset=%0.3f\n",
3808                name, axis.min, axis.max, axis.flat, axis.fuzz,
3809                axis.scale, axis.offset);
3810        dump.appendFormat(INDENT4 "  rawAxis=%d, rawMin=%d, rawMax=%d, rawFlat=%d, rawFuzz=%d\n",
3811                mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
3812                axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz);
3813    }
3814}
3815
3816void JoystickInputMapper::configure() {
3817    InputMapper::configure();
3818
3819    // Collect all axes.
3820    for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
3821        RawAbsoluteAxisInfo rawAxisInfo;
3822        getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo);
3823        if (rawAxisInfo.valid) {
3824            int32_t axisId;
3825            bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisId);
3826            if (!explicitlyMapped) {
3827                // Axis is not explicitly mapped, will choose a generic axis later.
3828                axisId = -1;
3829            }
3830
3831            Axis axis;
3832            if (isCenteredAxis(axisId)) {
3833                float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
3834                float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
3835                axis.initialize(rawAxisInfo, axisId, explicitlyMapped,
3836                        scale, offset, -1.0f, 1.0f,
3837                        rawAxisInfo.flat * scale, rawAxisInfo.fuzz * scale);
3838            } else {
3839                float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
3840                axis.initialize(rawAxisInfo, axisId, explicitlyMapped,
3841                        scale, 0.0f, 0.0f, 1.0f,
3842                        rawAxisInfo.flat * scale, rawAxisInfo.fuzz * scale);
3843            }
3844
3845            // To eliminate noise while the joystick is at rest, filter out small variations
3846            // in axis values up front.
3847            axis.filter = axis.flat * 0.25f;
3848
3849            mAxes.add(abs, axis);
3850        }
3851    }
3852
3853    // If there are too many axes, start dropping them.
3854    // Prefer to keep explicitly mapped axes.
3855    if (mAxes.size() > PointerCoords::MAX_AXES) {
3856        LOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
3857                getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
3858        pruneAxes(true);
3859        pruneAxes(false);
3860    }
3861
3862    // Assign generic axis ids to remaining axes.
3863    int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
3864    size_t numAxes = mAxes.size();
3865    for (size_t i = 0; i < numAxes; i++) {
3866        Axis& axis = mAxes.editValueAt(i);
3867        if (axis.axis < 0) {
3868            while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
3869                    && haveAxis(nextGenericAxisId)) {
3870                nextGenericAxisId += 1;
3871            }
3872
3873            if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
3874                axis.axis = nextGenericAxisId;
3875                nextGenericAxisId += 1;
3876            } else {
3877                LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
3878                        "have already been assigned to other axes.",
3879                        getDeviceName().string(), mAxes.keyAt(i));
3880                mAxes.removeItemsAt(i--);
3881                numAxes -= 1;
3882            }
3883        }
3884    }
3885}
3886
3887bool JoystickInputMapper::haveAxis(int32_t axis) {
3888    size_t numAxes = mAxes.size();
3889    for (size_t i = 0; i < numAxes; i++) {
3890        if (mAxes.valueAt(i).axis == axis) {
3891            return true;
3892        }
3893    }
3894    return false;
3895}
3896
3897void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
3898    size_t i = mAxes.size();
3899    while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
3900        if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
3901            continue;
3902        }
3903        LOGI("Discarding joystick '%s' axis %d because there are too many axes.",
3904                getDeviceName().string(), mAxes.keyAt(i));
3905        mAxes.removeItemsAt(i);
3906    }
3907}
3908
3909bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
3910    switch (axis) {
3911    case AMOTION_EVENT_AXIS_X:
3912    case AMOTION_EVENT_AXIS_Y:
3913    case AMOTION_EVENT_AXIS_Z:
3914    case AMOTION_EVENT_AXIS_RX:
3915    case AMOTION_EVENT_AXIS_RY:
3916    case AMOTION_EVENT_AXIS_RZ:
3917    case AMOTION_EVENT_AXIS_HAT_X:
3918    case AMOTION_EVENT_AXIS_HAT_Y:
3919    case AMOTION_EVENT_AXIS_ORIENTATION:
3920        return true;
3921    default:
3922        return false;
3923    }
3924}
3925
3926void JoystickInputMapper::reset() {
3927    // Recenter all axes.
3928    nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
3929
3930    size_t numAxes = mAxes.size();
3931    for (size_t i = 0; i < numAxes; i++) {
3932        Axis& axis = mAxes.editValueAt(i);
3933        axis.newValue = 0;
3934    }
3935
3936    sync(when, true /*force*/);
3937
3938    InputMapper::reset();
3939}
3940
3941void JoystickInputMapper::process(const RawEvent* rawEvent) {
3942    switch (rawEvent->type) {
3943    case EV_ABS: {
3944        ssize_t index = mAxes.indexOfKey(rawEvent->scanCode);
3945        if (index >= 0) {
3946            Axis& axis = mAxes.editValueAt(index);
3947            float newValue = rawEvent->value * axis.scale + axis.offset;
3948            if (newValue != axis.newValue) {
3949                axis.newValue = newValue;
3950            }
3951        }
3952        break;
3953    }
3954
3955    case EV_SYN:
3956        switch (rawEvent->scanCode) {
3957        case SYN_REPORT:
3958            sync(rawEvent->when, false /*force*/);
3959            break;
3960        }
3961        break;
3962    }
3963}
3964
3965void JoystickInputMapper::sync(nsecs_t when, bool force) {
3966    if (!force && !haveAxesChangedSignificantly()) {
3967        return;
3968    }
3969
3970    int32_t metaState = mContext->getGlobalMetaState();
3971
3972    PointerCoords pointerCoords;
3973    pointerCoords.clear();
3974
3975    size_t numAxes = mAxes.size();
3976    for (size_t i = 0; i < numAxes; i++) {
3977        Axis& axis = mAxes.editValueAt(i);
3978        pointerCoords.setAxisValue(axis.axis, axis.newValue);
3979        axis.oldValue = axis.newValue;
3980    }
3981
3982    int32_t pointerId = 0;
3983    getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, 0,
3984            AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
3985            1, &pointerId, &pointerCoords, 0, 0, 0);
3986}
3987
3988bool JoystickInputMapper::haveAxesChangedSignificantly() {
3989    size_t numAxes = mAxes.size();
3990    for (size_t i = 0; i < numAxes; i++) {
3991        const Axis& axis = mAxes.valueAt(i);
3992        if (axis.newValue != axis.oldValue
3993                && fabs(axis.newValue - axis.oldValue) > axis.filter) {
3994            return true;
3995        }
3996    }
3997    return false;
3998}
3999
4000} // namespace android
4001