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