InputReader.cpp revision aba321aa6f1be57beac70bd540812eea1c8262c5
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// Log debug messages about gesture detection.
37#define DEBUG_GESTURES 0
38
39#include "InputReader.h"
40
41#include <cutils/log.h>
42#include <ui/Keyboard.h>
43#include <ui/VirtualKeyMap.h>
44
45#include <stddef.h>
46#include <stdlib.h>
47#include <unistd.h>
48#include <errno.h>
49#include <limits.h>
50#include <math.h>
51
52#define INDENT "  "
53#define INDENT2 "    "
54#define INDENT3 "      "
55#define INDENT4 "        "
56#define INDENT5 "          "
57
58namespace android {
59
60// --- Constants ---
61
62// Maximum number of slots supported when using the slot-based Multitouch Protocol B.
63static const size_t MAX_SLOTS = 32;
64
65// --- Static Functions ---
66
67template<typename T>
68inline static T abs(const T& value) {
69    return value < 0 ? - value : value;
70}
71
72template<typename T>
73inline static T min(const T& a, const T& b) {
74    return a < b ? a : b;
75}
76
77template<typename T>
78inline static void swap(T& a, T& b) {
79    T temp = a;
80    a = b;
81    b = temp;
82}
83
84inline static float avg(float x, float y) {
85    return (x + y) / 2;
86}
87
88inline static float distance(float x1, float y1, float x2, float y2) {
89    return hypotf(x1 - x2, y1 - y2);
90}
91
92inline static int32_t signExtendNybble(int32_t value) {
93    return value >= 8 ? value - 16 : value;
94}
95
96static inline const char* toString(bool value) {
97    return value ? "true" : "false";
98}
99
100static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
101        const int32_t map[][4], size_t mapSize) {
102    if (orientation != DISPLAY_ORIENTATION_0) {
103        for (size_t i = 0; i < mapSize; i++) {
104            if (value == map[i][0]) {
105                return map[i][orientation];
106            }
107        }
108    }
109    return value;
110}
111
112static const int32_t keyCodeRotationMap[][4] = {
113        // key codes enumerated counter-clockwise with the original (unrotated) key first
114        // no rotation,        90 degree rotation,  180 degree rotation, 270 degree rotation
115        { AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT },
116        { AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN },
117        { AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT },
118        { AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP },
119};
120static const size_t keyCodeRotationMapSize =
121        sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
122
123int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
124    return rotateValueUsingRotationMap(keyCode, orientation,
125            keyCodeRotationMap, keyCodeRotationMapSize);
126}
127
128static const int32_t edgeFlagRotationMap[][4] = {
129        // edge flags enumerated counter-clockwise with the original (unrotated) edge flag first
130        // no rotation,        90 degree rotation,  180 degree rotation, 270 degree rotation
131        { AMOTION_EVENT_EDGE_FLAG_BOTTOM,   AMOTION_EVENT_EDGE_FLAG_RIGHT,
132                AMOTION_EVENT_EDGE_FLAG_TOP,     AMOTION_EVENT_EDGE_FLAG_LEFT },
133        { AMOTION_EVENT_EDGE_FLAG_RIGHT,  AMOTION_EVENT_EDGE_FLAG_TOP,
134                AMOTION_EVENT_EDGE_FLAG_LEFT,   AMOTION_EVENT_EDGE_FLAG_BOTTOM },
135        { AMOTION_EVENT_EDGE_FLAG_TOP,     AMOTION_EVENT_EDGE_FLAG_LEFT,
136                AMOTION_EVENT_EDGE_FLAG_BOTTOM,   AMOTION_EVENT_EDGE_FLAG_RIGHT },
137        { AMOTION_EVENT_EDGE_FLAG_LEFT,   AMOTION_EVENT_EDGE_FLAG_BOTTOM,
138                AMOTION_EVENT_EDGE_FLAG_RIGHT,  AMOTION_EVENT_EDGE_FLAG_TOP },
139};
140static const size_t edgeFlagRotationMapSize =
141        sizeof(edgeFlagRotationMap) / sizeof(edgeFlagRotationMap[0]);
142
143static int32_t rotateEdgeFlag(int32_t edgeFlag, int32_t orientation) {
144    return rotateValueUsingRotationMap(edgeFlag, orientation,
145            edgeFlagRotationMap, edgeFlagRotationMapSize);
146}
147
148static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
149    return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
150}
151
152static uint32_t getButtonStateForScanCode(int32_t scanCode) {
153    // Currently all buttons are mapped to the primary button.
154    switch (scanCode) {
155    case BTN_LEFT:
156        return AMOTION_EVENT_BUTTON_PRIMARY;
157    case BTN_RIGHT:
158    case BTN_STYLUS:
159        return AMOTION_EVENT_BUTTON_SECONDARY;
160    case BTN_MIDDLE:
161    case BTN_STYLUS2:
162        return AMOTION_EVENT_BUTTON_TERTIARY;
163    case BTN_SIDE:
164        return AMOTION_EVENT_BUTTON_BACK;
165    case BTN_FORWARD:
166    case BTN_EXTRA:
167        return AMOTION_EVENT_BUTTON_FORWARD;
168    case BTN_BACK:
169        return AMOTION_EVENT_BUTTON_BACK;
170    case BTN_TASK:
171    default:
172        return 0;
173    }
174}
175
176// Returns true if the pointer should be reported as being down given the specified
177// button states.  This determines whether the event is reported as a touch event.
178static bool isPointerDown(int32_t buttonState) {
179    return buttonState &
180            (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY
181                    | AMOTION_EVENT_BUTTON_TERTIARY);
182}
183
184static int32_t calculateEdgeFlagsUsingPointerBounds(
185        const sp<PointerControllerInterface>& pointerController, float x, float y) {
186    int32_t edgeFlags = 0;
187    float minX, minY, maxX, maxY;
188    if (pointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
189        if (x <= minX) {
190            edgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
191        } else if (x >= maxX) {
192            edgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
193        }
194        if (y <= minY) {
195            edgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
196        } else if (y >= maxY) {
197            edgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
198        }
199    }
200    return edgeFlags;
201}
202
203static float calculateCommonVector(float a, float b) {
204    if (a > 0 && b > 0) {
205        return a < b ? a : b;
206    } else if (a < 0 && b < 0) {
207        return a > b ? a : b;
208    } else {
209        return 0;
210    }
211}
212
213static void synthesizeButtonKey(InputReaderContext* context, int32_t action,
214        nsecs_t when, int32_t deviceId, uint32_t source,
215        uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState,
216        int32_t buttonState, int32_t keyCode) {
217    if (
218            (action == AKEY_EVENT_ACTION_DOWN
219                    && !(lastButtonState & buttonState)
220                    && (currentButtonState & buttonState))
221            || (action == AKEY_EVENT_ACTION_UP
222                    && (lastButtonState & buttonState)
223                    && !(currentButtonState & buttonState))) {
224        context->getDispatcher()->notifyKey(when, deviceId, source, policyFlags,
225                action, 0, keyCode, 0, context->getGlobalMetaState(), when);
226    }
227}
228
229static void synthesizeButtonKeys(InputReaderContext* context, int32_t action,
230        nsecs_t when, int32_t deviceId, uint32_t source,
231        uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) {
232    synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
233            lastButtonState, currentButtonState,
234            AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK);
235    synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
236            lastButtonState, currentButtonState,
237            AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD);
238}
239
240
241// --- InputReader ---
242
243InputReader::InputReader(const sp<EventHubInterface>& eventHub,
244        const sp<InputReaderPolicyInterface>& policy,
245        const sp<InputDispatcherInterface>& dispatcher) :
246        mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
247        mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
248        mConfigurationChangesToRefresh(0) {
249    refreshConfiguration(0);
250    updateGlobalMetaState();
251    updateInputConfiguration();
252}
253
254InputReader::~InputReader() {
255    for (size_t i = 0; i < mDevices.size(); i++) {
256        delete mDevices.valueAt(i);
257    }
258}
259
260void InputReader::loopOnce() {
261    uint32_t changes;
262    { // acquire lock
263        AutoMutex _l(mStateLock);
264
265        changes = mConfigurationChangesToRefresh;
266        mConfigurationChangesToRefresh = 0;
267    } // release lock
268
269    if (changes) {
270        refreshConfiguration(changes);
271    }
272
273    int32_t timeoutMillis = -1;
274    if (mNextTimeout != LLONG_MAX) {
275        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
276        timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
277    }
278
279    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
280    if (count) {
281        processEvents(mEventBuffer, count);
282    }
283    if (!count || timeoutMillis == 0) {
284        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
285#if DEBUG_RAW_EVENTS
286        LOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
287#endif
288        mNextTimeout = LLONG_MAX;
289        timeoutExpired(now);
290    }
291}
292
293void InputReader::processEvents(const RawEvent* rawEvents, size_t count) {
294    for (const RawEvent* rawEvent = rawEvents; count;) {
295        int32_t type = rawEvent->type;
296        size_t batchSize = 1;
297        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
298            int32_t deviceId = rawEvent->deviceId;
299            while (batchSize < count) {
300                if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
301                        || rawEvent[batchSize].deviceId != deviceId) {
302                    break;
303                }
304                batchSize += 1;
305            }
306#if DEBUG_RAW_EVENTS
307            LOGD("BatchSize: %d Count: %d", batchSize, count);
308#endif
309            processEventsForDevice(deviceId, rawEvent, batchSize);
310        } else {
311            switch (rawEvent->type) {
312            case EventHubInterface::DEVICE_ADDED:
313                addDevice(rawEvent->deviceId);
314                break;
315            case EventHubInterface::DEVICE_REMOVED:
316                removeDevice(rawEvent->deviceId);
317                break;
318            case EventHubInterface::FINISHED_DEVICE_SCAN:
319                handleConfigurationChanged(rawEvent->when);
320                break;
321            default:
322                LOG_ASSERT(false); // can't happen
323                break;
324            }
325        }
326        count -= batchSize;
327        rawEvent += batchSize;
328    }
329}
330
331void InputReader::addDevice(int32_t deviceId) {
332    String8 name = mEventHub->getDeviceName(deviceId);
333    uint32_t classes = mEventHub->getDeviceClasses(deviceId);
334
335    InputDevice* device = createDevice(deviceId, name, classes);
336    device->configure(&mConfig, 0);
337
338    if (device->isIgnored()) {
339        LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
340    } else {
341        LOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
342                device->getSources());
343    }
344
345    bool added = false;
346    { // acquire device registry writer lock
347        RWLock::AutoWLock _wl(mDeviceRegistryLock);
348
349        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
350        if (deviceIndex < 0) {
351            mDevices.add(deviceId, device);
352            added = true;
353        }
354    } // release device registry writer lock
355
356    if (! added) {
357        LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
358        delete device;
359        return;
360    }
361}
362
363void InputReader::removeDevice(int32_t deviceId) {
364    bool removed = false;
365    InputDevice* device = NULL;
366    { // acquire device registry writer lock
367        RWLock::AutoWLock _wl(mDeviceRegistryLock);
368
369        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
370        if (deviceIndex >= 0) {
371            device = mDevices.valueAt(deviceIndex);
372            mDevices.removeItemsAt(deviceIndex, 1);
373            removed = true;
374        }
375    } // release device registry writer lock
376
377    if (! removed) {
378        LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
379        return;
380    }
381
382    if (device->isIgnored()) {
383        LOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
384                device->getId(), device->getName().string());
385    } else {
386        LOGI("Device removed: id=%d, name='%s', sources=0x%08x",
387                device->getId(), device->getName().string(), device->getSources());
388    }
389
390    device->reset();
391
392    delete device;
393}
394
395InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
396    InputDevice* device = new InputDevice(this, deviceId, name);
397
398    // External devices.
399    if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
400        device->setExternal(true);
401    }
402
403    // Switch-like devices.
404    if (classes & INPUT_DEVICE_CLASS_SWITCH) {
405        device->addMapper(new SwitchInputMapper(device));
406    }
407
408    // Keyboard-like devices.
409    uint32_t keyboardSource = 0;
410    int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
411    if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
412        keyboardSource |= AINPUT_SOURCE_KEYBOARD;
413    }
414    if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
415        keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
416    }
417    if (classes & INPUT_DEVICE_CLASS_DPAD) {
418        keyboardSource |= AINPUT_SOURCE_DPAD;
419    }
420    if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
421        keyboardSource |= AINPUT_SOURCE_GAMEPAD;
422    }
423
424    if (keyboardSource != 0) {
425        device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
426    }
427
428    // Cursor-like devices.
429    if (classes & INPUT_DEVICE_CLASS_CURSOR) {
430        device->addMapper(new CursorInputMapper(device));
431    }
432
433    // Touchscreens and touchpad devices.
434    if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
435        device->addMapper(new MultiTouchInputMapper(device));
436    } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
437        device->addMapper(new SingleTouchInputMapper(device));
438    }
439
440    // Joystick-like devices.
441    if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
442        device->addMapper(new JoystickInputMapper(device));
443    }
444
445    return device;
446}
447
448void InputReader::processEventsForDevice(int32_t deviceId,
449        const RawEvent* rawEvents, size_t count) {
450    { // acquire device registry reader lock
451        RWLock::AutoRLock _rl(mDeviceRegistryLock);
452
453        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
454        if (deviceIndex < 0) {
455            LOGW("Discarding event for unknown deviceId %d.", deviceId);
456            return;
457        }
458
459        InputDevice* device = mDevices.valueAt(deviceIndex);
460        if (device->isIgnored()) {
461            //LOGD("Discarding event for ignored deviceId %d.", deviceId);
462            return;
463        }
464
465        device->process(rawEvents, count);
466    } // release device registry reader lock
467}
468
469void InputReader::timeoutExpired(nsecs_t when) {
470    { // acquire device registry reader lock
471        RWLock::AutoRLock _rl(mDeviceRegistryLock);
472
473        for (size_t i = 0; i < mDevices.size(); i++) {
474            InputDevice* device = mDevices.valueAt(i);
475            if (!device->isIgnored()) {
476                device->timeoutExpired(when);
477            }
478        }
479    } // release device registry reader lock
480}
481
482void InputReader::handleConfigurationChanged(nsecs_t when) {
483    // Reset global meta state because it depends on the list of all configured devices.
484    updateGlobalMetaState();
485
486    // Update input configuration.
487    updateInputConfiguration();
488
489    // Enqueue configuration changed.
490    mDispatcher->notifyConfigurationChanged(when);
491}
492
493void InputReader::refreshConfiguration(uint32_t changes) {
494    mPolicy->getReaderConfiguration(&mConfig);
495    mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
496
497    if (changes) {
498        LOGI("Reconfiguring input devices.  changes=0x%08x", changes);
499
500        if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
501            mEventHub->requestReopenDevices();
502        } else {
503            { // acquire device registry reader lock
504                RWLock::AutoRLock _rl(mDeviceRegistryLock);
505
506                for (size_t i = 0; i < mDevices.size(); i++) {
507                    InputDevice* device = mDevices.valueAt(i);
508                    device->configure(&mConfig, changes);
509                }
510            } // release device registry reader lock
511        }
512    }
513}
514
515void InputReader::updateGlobalMetaState() {
516    { // acquire state lock
517        AutoMutex _l(mStateLock);
518
519        mGlobalMetaState = 0;
520
521        { // acquire device registry reader lock
522            RWLock::AutoRLock _rl(mDeviceRegistryLock);
523
524            for (size_t i = 0; i < mDevices.size(); i++) {
525                InputDevice* device = mDevices.valueAt(i);
526                mGlobalMetaState |= device->getMetaState();
527            }
528        } // release device registry reader lock
529    } // release state lock
530}
531
532int32_t InputReader::getGlobalMetaState() {
533    { // acquire state lock
534        AutoMutex _l(mStateLock);
535
536        return mGlobalMetaState;
537    } // release state lock
538}
539
540void InputReader::updateInputConfiguration() {
541    { // acquire state lock
542        AutoMutex _l(mStateLock);
543
544        int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
545        int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
546        int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
547        { // acquire device registry reader lock
548            RWLock::AutoRLock _rl(mDeviceRegistryLock);
549
550            InputDeviceInfo deviceInfo;
551            for (size_t i = 0; i < mDevices.size(); i++) {
552                InputDevice* device = mDevices.valueAt(i);
553                device->getDeviceInfo(& deviceInfo);
554                uint32_t sources = deviceInfo.getSources();
555
556                if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
557                    touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
558                }
559                if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
560                    navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
561                } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
562                    navigationConfig = InputConfiguration::NAVIGATION_DPAD;
563                }
564                if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
565                    keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
566                }
567            }
568        } // release device registry reader lock
569
570        mInputConfiguration.touchScreen = touchScreenConfig;
571        mInputConfiguration.keyboard = keyboardConfig;
572        mInputConfiguration.navigation = navigationConfig;
573    } // release state lock
574}
575
576void InputReader::disableVirtualKeysUntil(nsecs_t time) {
577    mDisableVirtualKeysTimeout = time;
578}
579
580bool InputReader::shouldDropVirtualKey(nsecs_t now,
581        InputDevice* device, int32_t keyCode, int32_t scanCode) {
582    if (now < mDisableVirtualKeysTimeout) {
583        LOGI("Dropping virtual key from device %s because virtual keys are "
584                "temporarily disabled for the next %0.3fms.  keyCode=%d, scanCode=%d",
585                device->getName().string(),
586                (mDisableVirtualKeysTimeout - now) * 0.000001,
587                keyCode, scanCode);
588        return true;
589    } else {
590        return false;
591    }
592}
593
594void InputReader::fadePointer() {
595    { // acquire device registry reader lock
596        RWLock::AutoRLock _rl(mDeviceRegistryLock);
597
598        for (size_t i = 0; i < mDevices.size(); i++) {
599            InputDevice* device = mDevices.valueAt(i);
600            device->fadePointer();
601        }
602    } // release device registry reader lock
603}
604
605void InputReader::requestTimeoutAtTime(nsecs_t when) {
606    if (when < mNextTimeout) {
607        mNextTimeout = when;
608    }
609}
610
611void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
612    { // acquire state lock
613        AutoMutex _l(mStateLock);
614
615        *outConfiguration = mInputConfiguration;
616    } // release state lock
617}
618
619status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
620    { // acquire device registry reader lock
621        RWLock::AutoRLock _rl(mDeviceRegistryLock);
622
623        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
624        if (deviceIndex < 0) {
625            return NAME_NOT_FOUND;
626        }
627
628        InputDevice* device = mDevices.valueAt(deviceIndex);
629        if (device->isIgnored()) {
630            return NAME_NOT_FOUND;
631        }
632
633        device->getDeviceInfo(outDeviceInfo);
634        return OK;
635    } // release device registy reader lock
636}
637
638void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
639    outDeviceIds.clear();
640
641    { // acquire device registry reader lock
642        RWLock::AutoRLock _rl(mDeviceRegistryLock);
643
644        size_t numDevices = mDevices.size();
645        for (size_t i = 0; i < numDevices; i++) {
646            InputDevice* device = mDevices.valueAt(i);
647            if (! device->isIgnored()) {
648                outDeviceIds.add(device->getId());
649            }
650        }
651    } // release device registy reader lock
652}
653
654int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
655        int32_t keyCode) {
656    return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
657}
658
659int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
660        int32_t scanCode) {
661    return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
662}
663
664int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
665    return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
666}
667
668int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
669        GetStateFunc getStateFunc) {
670    { // acquire device registry reader lock
671        RWLock::AutoRLock _rl(mDeviceRegistryLock);
672
673        int32_t result = AKEY_STATE_UNKNOWN;
674        if (deviceId >= 0) {
675            ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
676            if (deviceIndex >= 0) {
677                InputDevice* device = mDevices.valueAt(deviceIndex);
678                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
679                    result = (device->*getStateFunc)(sourceMask, code);
680                }
681            }
682        } else {
683            size_t numDevices = mDevices.size();
684            for (size_t i = 0; i < numDevices; i++) {
685                InputDevice* device = mDevices.valueAt(i);
686                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
687                    result = (device->*getStateFunc)(sourceMask, code);
688                    if (result >= AKEY_STATE_DOWN) {
689                        return result;
690                    }
691                }
692            }
693        }
694        return result;
695    } // release device registy reader lock
696}
697
698bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
699        size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
700    memset(outFlags, 0, numCodes);
701    return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
702}
703
704bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
705        const int32_t* keyCodes, uint8_t* outFlags) {
706    { // acquire device registry reader lock
707        RWLock::AutoRLock _rl(mDeviceRegistryLock);
708        bool result = false;
709        if (deviceId >= 0) {
710            ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
711            if (deviceIndex >= 0) {
712                InputDevice* device = mDevices.valueAt(deviceIndex);
713                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
714                    result = device->markSupportedKeyCodes(sourceMask,
715                            numCodes, keyCodes, outFlags);
716                }
717            }
718        } else {
719            size_t numDevices = mDevices.size();
720            for (size_t i = 0; i < numDevices; i++) {
721                InputDevice* device = mDevices.valueAt(i);
722                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
723                    result |= device->markSupportedKeyCodes(sourceMask,
724                            numCodes, keyCodes, outFlags);
725                }
726            }
727        }
728        return result;
729    } // release device registy reader lock
730}
731
732void InputReader::requestRefreshConfiguration(uint32_t changes) {
733    if (changes) {
734        bool needWake;
735        { // acquire lock
736            AutoMutex _l(mStateLock);
737
738            needWake = !mConfigurationChangesToRefresh;
739            mConfigurationChangesToRefresh |= changes;
740        } // release lock
741
742        if (needWake) {
743            mEventHub->wake();
744        }
745    }
746}
747
748void InputReader::dump(String8& dump) {
749    mEventHub->dump(dump);
750    dump.append("\n");
751
752    dump.append("Input Reader State:\n");
753
754    { // acquire device registry reader lock
755        RWLock::AutoRLock _rl(mDeviceRegistryLock);
756
757        for (size_t i = 0; i < mDevices.size(); i++) {
758            mDevices.valueAt(i)->dump(dump);
759        }
760    } // release device registy reader lock
761
762    dump.append(INDENT "Configuration:\n");
763    dump.append(INDENT2 "ExcludedDeviceNames: [");
764    for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
765        if (i != 0) {
766            dump.append(", ");
767        }
768        dump.append(mConfig.excludedDeviceNames.itemAt(i).string());
769    }
770    dump.append("]\n");
771    dump.appendFormat(INDENT2 "FilterTouchEvents: %s\n",
772            toString(mConfig.filterTouchEvents));
773    dump.appendFormat(INDENT2 "FilterJumpyTouchEvents: %s\n",
774            toString(mConfig.filterJumpyTouchEvents));
775    dump.appendFormat(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
776            mConfig.virtualKeyQuietTime * 0.000001f);
777
778    dump.appendFormat(INDENT2 "PointerVelocityControlParameters: "
779            "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
780            mConfig.pointerVelocityControlParameters.scale,
781            mConfig.pointerVelocityControlParameters.lowThreshold,
782            mConfig.pointerVelocityControlParameters.highThreshold,
783            mConfig.pointerVelocityControlParameters.acceleration);
784
785    dump.appendFormat(INDENT2 "WheelVelocityControlParameters: "
786            "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
787            mConfig.wheelVelocityControlParameters.scale,
788            mConfig.wheelVelocityControlParameters.lowThreshold,
789            mConfig.wheelVelocityControlParameters.highThreshold,
790            mConfig.wheelVelocityControlParameters.acceleration);
791
792    dump.appendFormat(INDENT2 "PointerGesture:\n");
793    dump.appendFormat(INDENT3 "Enabled: %s\n",
794            toString(mConfig.pointerGesturesEnabled));
795    dump.appendFormat(INDENT3 "QuietInterval: %0.1fms\n",
796            mConfig.pointerGestureQuietInterval * 0.000001f);
797    dump.appendFormat(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
798            mConfig.pointerGestureDragMinSwitchSpeed);
799    dump.appendFormat(INDENT3 "TapInterval: %0.1fms\n",
800            mConfig.pointerGestureTapInterval * 0.000001f);
801    dump.appendFormat(INDENT3 "TapDragInterval: %0.1fms\n",
802            mConfig.pointerGestureTapDragInterval * 0.000001f);
803    dump.appendFormat(INDENT3 "TapSlop: %0.1fpx\n",
804            mConfig.pointerGestureTapSlop);
805    dump.appendFormat(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
806            mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
807    dump.appendFormat(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
808            mConfig.pointerGestureMultitouchMinDistance);
809    dump.appendFormat(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
810            mConfig.pointerGestureSwipeTransitionAngleCosine);
811    dump.appendFormat(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
812            mConfig.pointerGestureSwipeMaxWidthRatio);
813    dump.appendFormat(INDENT3 "MovementSpeedRatio: %0.1f\n",
814            mConfig.pointerGestureMovementSpeedRatio);
815    dump.appendFormat(INDENT3 "ZoomSpeedRatio: %0.1f\n",
816            mConfig.pointerGestureZoomSpeedRatio);
817}
818
819
820// --- InputReaderThread ---
821
822InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
823        Thread(/*canCallJava*/ true), mReader(reader) {
824}
825
826InputReaderThread::~InputReaderThread() {
827}
828
829bool InputReaderThread::threadLoop() {
830    mReader->loopOnce();
831    return true;
832}
833
834
835// --- InputDevice ---
836
837InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
838        mContext(context), mId(id), mName(name), mSources(0),
839        mIsExternal(false), mDropUntilNextSync(false) {
840}
841
842InputDevice::~InputDevice() {
843    size_t numMappers = mMappers.size();
844    for (size_t i = 0; i < numMappers; i++) {
845        delete mMappers[i];
846    }
847    mMappers.clear();
848}
849
850void InputDevice::dump(String8& dump) {
851    InputDeviceInfo deviceInfo;
852    getDeviceInfo(& deviceInfo);
853
854    dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
855            deviceInfo.getName().string());
856    dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
857    dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
858    dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
859
860    const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
861    if (!ranges.isEmpty()) {
862        dump.append(INDENT2 "Motion Ranges:\n");
863        for (size_t i = 0; i < ranges.size(); i++) {
864            const InputDeviceInfo::MotionRange& range = ranges.itemAt(i);
865            const char* label = getAxisLabel(range.axis);
866            char name[32];
867            if (label) {
868                strncpy(name, label, sizeof(name));
869                name[sizeof(name) - 1] = '\0';
870            } else {
871                snprintf(name, sizeof(name), "%d", range.axis);
872            }
873            dump.appendFormat(INDENT3 "%s: source=0x%08x, "
874                    "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
875                    name, range.source, range.min, range.max, range.flat, range.fuzz);
876        }
877    }
878
879    size_t numMappers = mMappers.size();
880    for (size_t i = 0; i < numMappers; i++) {
881        InputMapper* mapper = mMappers[i];
882        mapper->dump(dump);
883    }
884}
885
886void InputDevice::addMapper(InputMapper* mapper) {
887    mMappers.add(mapper);
888}
889
890void InputDevice::configure(const InputReaderConfiguration* config, uint32_t changes) {
891    mSources = 0;
892
893    if (!isIgnored()) {
894        if (!changes) { // first time only
895            mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
896        }
897
898        size_t numMappers = mMappers.size();
899        for (size_t i = 0; i < numMappers; i++) {
900            InputMapper* mapper = mMappers[i];
901            mapper->configure(config, changes);
902            mSources |= mapper->getSources();
903        }
904    }
905}
906
907void InputDevice::reset() {
908    size_t numMappers = mMappers.size();
909    for (size_t i = 0; i < numMappers; i++) {
910        InputMapper* mapper = mMappers[i];
911        mapper->reset();
912    }
913}
914
915void InputDevice::process(const RawEvent* rawEvents, size_t count) {
916    // Process all of the events in order for each mapper.
917    // We cannot simply ask each mapper to process them in bulk because mappers may
918    // have side-effects that must be interleaved.  For example, joystick movement events and
919    // gamepad button presses are handled by different mappers but they should be dispatched
920    // in the order received.
921    size_t numMappers = mMappers.size();
922    for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
923#if DEBUG_RAW_EVENTS
924        LOGD("Input event: device=%d type=0x%04x scancode=0x%04x "
925                "keycode=0x%04x value=0x%04x flags=0x%08x",
926                rawEvent->deviceId, rawEvent->type, rawEvent->scanCode, rawEvent->keyCode,
927                rawEvent->value, rawEvent->flags);
928#endif
929
930        if (mDropUntilNextSync) {
931            if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
932                mDropUntilNextSync = false;
933#if DEBUG_RAW_EVENTS
934                LOGD("Recovered from input event buffer overrun.");
935#endif
936            } else {
937#if DEBUG_RAW_EVENTS
938                LOGD("Dropped input event while waiting for next input sync.");
939#endif
940            }
941        } else if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_DROPPED) {
942            LOGI("Detected input event buffer overrun for device %s.", mName.string());
943            mDropUntilNextSync = true;
944            reset();
945        } else {
946            for (size_t i = 0; i < numMappers; i++) {
947                InputMapper* mapper = mMappers[i];
948                mapper->process(rawEvent);
949            }
950        }
951    }
952}
953
954void InputDevice::timeoutExpired(nsecs_t when) {
955    size_t numMappers = mMappers.size();
956    for (size_t i = 0; i < numMappers; i++) {
957        InputMapper* mapper = mMappers[i];
958        mapper->timeoutExpired(when);
959    }
960}
961
962void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
963    outDeviceInfo->initialize(mId, mName);
964
965    size_t numMappers = mMappers.size();
966    for (size_t i = 0; i < numMappers; i++) {
967        InputMapper* mapper = mMappers[i];
968        mapper->populateDeviceInfo(outDeviceInfo);
969    }
970}
971
972int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
973    return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
974}
975
976int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
977    return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
978}
979
980int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
981    return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
982}
983
984int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
985    int32_t result = AKEY_STATE_UNKNOWN;
986    size_t numMappers = mMappers.size();
987    for (size_t i = 0; i < numMappers; i++) {
988        InputMapper* mapper = mMappers[i];
989        if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
990            result = (mapper->*getStateFunc)(sourceMask, code);
991            if (result >= AKEY_STATE_DOWN) {
992                return result;
993            }
994        }
995    }
996    return result;
997}
998
999bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1000        const int32_t* keyCodes, uint8_t* outFlags) {
1001    bool result = false;
1002    size_t numMappers = mMappers.size();
1003    for (size_t i = 0; i < numMappers; i++) {
1004        InputMapper* mapper = mMappers[i];
1005        if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
1006            result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
1007        }
1008    }
1009    return result;
1010}
1011
1012int32_t InputDevice::getMetaState() {
1013    int32_t result = 0;
1014    size_t numMappers = mMappers.size();
1015    for (size_t i = 0; i < numMappers; i++) {
1016        InputMapper* mapper = mMappers[i];
1017        result |= mapper->getMetaState();
1018    }
1019    return result;
1020}
1021
1022void InputDevice::fadePointer() {
1023    size_t numMappers = mMappers.size();
1024    for (size_t i = 0; i < numMappers; i++) {
1025        InputMapper* mapper = mMappers[i];
1026        mapper->fadePointer();
1027    }
1028}
1029
1030
1031// --- InputMapper ---
1032
1033InputMapper::InputMapper(InputDevice* device) :
1034        mDevice(device), mContext(device->getContext()) {
1035}
1036
1037InputMapper::~InputMapper() {
1038}
1039
1040void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1041    info->addSource(getSources());
1042}
1043
1044void InputMapper::dump(String8& dump) {
1045}
1046
1047void InputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) {
1048}
1049
1050void InputMapper::reset() {
1051}
1052
1053void InputMapper::timeoutExpired(nsecs_t when) {
1054}
1055
1056int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1057    return AKEY_STATE_UNKNOWN;
1058}
1059
1060int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1061    return AKEY_STATE_UNKNOWN;
1062}
1063
1064int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1065    return AKEY_STATE_UNKNOWN;
1066}
1067
1068bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1069        const int32_t* keyCodes, uint8_t* outFlags) {
1070    return false;
1071}
1072
1073int32_t InputMapper::getMetaState() {
1074    return 0;
1075}
1076
1077void InputMapper::fadePointer() {
1078}
1079
1080void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
1081        const RawAbsoluteAxisInfo& axis, const char* name) {
1082    if (axis.valid) {
1083        dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d, resolution=%d\n",
1084                name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz, axis.resolution);
1085    } else {
1086        dump.appendFormat(INDENT4 "%s: unknown range\n", name);
1087    }
1088}
1089
1090
1091// --- SwitchInputMapper ---
1092
1093SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
1094        InputMapper(device) {
1095}
1096
1097SwitchInputMapper::~SwitchInputMapper() {
1098}
1099
1100uint32_t SwitchInputMapper::getSources() {
1101    return AINPUT_SOURCE_SWITCH;
1102}
1103
1104void SwitchInputMapper::process(const RawEvent* rawEvent) {
1105    switch (rawEvent->type) {
1106    case EV_SW:
1107        processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
1108        break;
1109    }
1110}
1111
1112void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
1113    getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
1114}
1115
1116int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1117    return getEventHub()->getSwitchState(getDeviceId(), switchCode);
1118}
1119
1120
1121// --- KeyboardInputMapper ---
1122
1123KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
1124        uint32_t source, int32_t keyboardType) :
1125        InputMapper(device), mSource(source),
1126        mKeyboardType(keyboardType) {
1127    initializeLocked();
1128}
1129
1130KeyboardInputMapper::~KeyboardInputMapper() {
1131}
1132
1133void KeyboardInputMapper::initializeLocked() {
1134    mLocked.metaState = AMETA_NONE;
1135    mLocked.downTime = 0;
1136}
1137
1138uint32_t KeyboardInputMapper::getSources() {
1139    return mSource;
1140}
1141
1142void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1143    InputMapper::populateDeviceInfo(info);
1144
1145    info->setKeyboardType(mKeyboardType);
1146}
1147
1148void KeyboardInputMapper::dump(String8& dump) {
1149    { // acquire lock
1150        AutoMutex _l(mLock);
1151        dump.append(INDENT2 "Keyboard Input Mapper:\n");
1152        dumpParameters(dump);
1153        dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
1154        dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
1155        dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
1156        dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1157    } // release lock
1158}
1159
1160
1161void KeyboardInputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) {
1162    InputMapper::configure(config, changes);
1163
1164    if (!changes) { // first time only
1165        // Configure basic parameters.
1166        configureParameters();
1167
1168        // Reset LEDs.
1169        {
1170            AutoMutex _l(mLock);
1171            resetLedStateLocked();
1172        }
1173    }
1174}
1175
1176void KeyboardInputMapper::configureParameters() {
1177    mParameters.orientationAware = false;
1178    getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
1179            mParameters.orientationAware);
1180
1181    mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
1182}
1183
1184void KeyboardInputMapper::dumpParameters(String8& dump) {
1185    dump.append(INDENT3 "Parameters:\n");
1186    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1187            mParameters.associatedDisplayId);
1188    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1189            toString(mParameters.orientationAware));
1190}
1191
1192void KeyboardInputMapper::reset() {
1193    for (;;) {
1194        int32_t keyCode, scanCode;
1195        { // acquire lock
1196            AutoMutex _l(mLock);
1197
1198            // Synthesize key up event on reset if keys are currently down.
1199            if (mLocked.keyDowns.isEmpty()) {
1200                initializeLocked();
1201                resetLedStateLocked();
1202                break; // done
1203            }
1204
1205            const KeyDown& keyDown = mLocked.keyDowns.top();
1206            keyCode = keyDown.keyCode;
1207            scanCode = keyDown.scanCode;
1208        } // release lock
1209
1210        nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
1211        processKey(when, false, keyCode, scanCode, 0);
1212    }
1213
1214    InputMapper::reset();
1215    getContext()->updateGlobalMetaState();
1216}
1217
1218void KeyboardInputMapper::process(const RawEvent* rawEvent) {
1219    switch (rawEvent->type) {
1220    case EV_KEY: {
1221        int32_t scanCode = rawEvent->scanCode;
1222        if (isKeyboardOrGamepadKey(scanCode)) {
1223            processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
1224                    rawEvent->flags);
1225        }
1226        break;
1227    }
1228    }
1229}
1230
1231bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
1232    return scanCode < BTN_MOUSE
1233        || scanCode >= KEY_OK
1234        || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE)
1235        || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
1236}
1237
1238void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
1239        int32_t scanCode, uint32_t policyFlags) {
1240    int32_t newMetaState;
1241    nsecs_t downTime;
1242    bool metaStateChanged = false;
1243
1244    { // acquire lock
1245        AutoMutex _l(mLock);
1246
1247        if (down) {
1248            // Rotate key codes according to orientation if needed.
1249            // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1250            if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
1251                int32_t orientation;
1252                if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1253                        NULL, NULL, & orientation)) {
1254                    orientation = DISPLAY_ORIENTATION_0;
1255                }
1256
1257                keyCode = rotateKeyCode(keyCode, orientation);
1258            }
1259
1260            // Add key down.
1261            ssize_t keyDownIndex = findKeyDownLocked(scanCode);
1262            if (keyDownIndex >= 0) {
1263                // key repeat, be sure to use same keycode as before in case of rotation
1264                keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
1265            } else {
1266                // key down
1267                if ((policyFlags & POLICY_FLAG_VIRTUAL)
1268                        && mContext->shouldDropVirtualKey(when,
1269                                getDevice(), keyCode, scanCode)) {
1270                    return;
1271                }
1272
1273                mLocked.keyDowns.push();
1274                KeyDown& keyDown = mLocked.keyDowns.editTop();
1275                keyDown.keyCode = keyCode;
1276                keyDown.scanCode = scanCode;
1277            }
1278
1279            mLocked.downTime = when;
1280        } else {
1281            // Remove key down.
1282            ssize_t keyDownIndex = findKeyDownLocked(scanCode);
1283            if (keyDownIndex >= 0) {
1284                // key up, be sure to use same keycode as before in case of rotation
1285                keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
1286                mLocked.keyDowns.removeAt(size_t(keyDownIndex));
1287            } else {
1288                // key was not actually down
1289                LOGI("Dropping key up from device %s because the key was not down.  "
1290                        "keyCode=%d, scanCode=%d",
1291                        getDeviceName().string(), keyCode, scanCode);
1292                return;
1293            }
1294        }
1295
1296        int32_t oldMetaState = mLocked.metaState;
1297        newMetaState = updateMetaState(keyCode, down, oldMetaState);
1298        if (oldMetaState != newMetaState) {
1299            mLocked.metaState = newMetaState;
1300            metaStateChanged = true;
1301            updateLedStateLocked(false);
1302        }
1303
1304        downTime = mLocked.downTime;
1305    } // release lock
1306
1307    // Key down on external an keyboard should wake the device.
1308    // We don't do this for internal keyboards to prevent them from waking up in your pocket.
1309    // For internal keyboards, the key layout file should specify the policy flags for
1310    // each wake key individually.
1311    // TODO: Use the input device configuration to control this behavior more finely.
1312    if (down && getDevice()->isExternal()
1313            && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {
1314        policyFlags |= POLICY_FLAG_WAKE_DROPPED;
1315    }
1316
1317    if (metaStateChanged) {
1318        getContext()->updateGlobalMetaState();
1319    }
1320
1321    if (down && !isMetaKey(keyCode)) {
1322        getContext()->fadePointer();
1323    }
1324
1325    getDispatcher()->notifyKey(when, getDeviceId(), mSource, policyFlags,
1326            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
1327            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
1328}
1329
1330ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
1331    size_t n = mLocked.keyDowns.size();
1332    for (size_t i = 0; i < n; i++) {
1333        if (mLocked.keyDowns[i].scanCode == scanCode) {
1334            return i;
1335        }
1336    }
1337    return -1;
1338}
1339
1340int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1341    return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
1342}
1343
1344int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1345    return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1346}
1347
1348bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1349        const int32_t* keyCodes, uint8_t* outFlags) {
1350    return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1351}
1352
1353int32_t KeyboardInputMapper::getMetaState() {
1354    { // acquire lock
1355        AutoMutex _l(mLock);
1356        return mLocked.metaState;
1357    } // release lock
1358}
1359
1360void KeyboardInputMapper::resetLedStateLocked() {
1361    initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
1362    initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
1363    initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
1364
1365    updateLedStateLocked(true);
1366}
1367
1368void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
1369    ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
1370    ledState.on = false;
1371}
1372
1373void KeyboardInputMapper::updateLedStateLocked(bool reset) {
1374    updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
1375            AMETA_CAPS_LOCK_ON, reset);
1376    updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML,
1377            AMETA_NUM_LOCK_ON, reset);
1378    updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL,
1379            AMETA_SCROLL_LOCK_ON, reset);
1380}
1381
1382void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState,
1383        int32_t led, int32_t modifier, bool reset) {
1384    if (ledState.avail) {
1385        bool desiredState = (mLocked.metaState & modifier) != 0;
1386        if (reset || ledState.on != desiredState) {
1387            getEventHub()->setLedState(getDeviceId(), led, desiredState);
1388            ledState.on = desiredState;
1389        }
1390    }
1391}
1392
1393
1394// --- CursorInputMapper ---
1395
1396CursorInputMapper::CursorInputMapper(InputDevice* device) :
1397        InputMapper(device) {
1398    initializeLocked();
1399}
1400
1401CursorInputMapper::~CursorInputMapper() {
1402}
1403
1404uint32_t CursorInputMapper::getSources() {
1405    return mSource;
1406}
1407
1408void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1409    InputMapper::populateDeviceInfo(info);
1410
1411    if (mParameters.mode == Parameters::MODE_POINTER) {
1412        float minX, minY, maxX, maxY;
1413        if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
1414            info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f);
1415            info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f);
1416        }
1417    } else {
1418        info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale);
1419        info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale);
1420    }
1421    info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f);
1422
1423    if (mHaveVWheel) {
1424        info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
1425    }
1426    if (mHaveHWheel) {
1427        info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
1428    }
1429}
1430
1431void CursorInputMapper::dump(String8& dump) {
1432    { // acquire lock
1433        AutoMutex _l(mLock);
1434        dump.append(INDENT2 "Cursor Input Mapper:\n");
1435        dumpParameters(dump);
1436        dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
1437        dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
1438        dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1439        dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
1440        dump.appendFormat(INDENT3 "HaveVWheel: %s\n", toString(mHaveVWheel));
1441        dump.appendFormat(INDENT3 "HaveHWheel: %s\n", toString(mHaveHWheel));
1442        dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
1443        dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
1444        dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mLocked.buttonState);
1445        dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mLocked.buttonState)));
1446        dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1447    } // release lock
1448}
1449
1450void CursorInputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) {
1451    InputMapper::configure(config, changes);
1452
1453    if (!changes) { // first time only
1454        // Configure basic parameters.
1455        configureParameters();
1456
1457        // Configure device mode.
1458        switch (mParameters.mode) {
1459        case Parameters::MODE_POINTER:
1460            mSource = AINPUT_SOURCE_MOUSE;
1461            mXPrecision = 1.0f;
1462            mYPrecision = 1.0f;
1463            mXScale = 1.0f;
1464            mYScale = 1.0f;
1465            mPointerController = getPolicy()->obtainPointerController(getDeviceId());
1466            break;
1467        case Parameters::MODE_NAVIGATION:
1468            mSource = AINPUT_SOURCE_TRACKBALL;
1469            mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1470            mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1471            mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1472            mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1473            break;
1474        }
1475
1476        mVWheelScale = 1.0f;
1477        mHWheelScale = 1.0f;
1478
1479        mHaveVWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_WHEEL);
1480        mHaveHWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_HWHEEL);
1481    }
1482
1483    if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
1484        mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
1485        mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
1486        mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
1487    }
1488}
1489
1490void CursorInputMapper::configureParameters() {
1491    mParameters.mode = Parameters::MODE_POINTER;
1492    String8 cursorModeString;
1493    if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
1494        if (cursorModeString == "navigation") {
1495            mParameters.mode = Parameters::MODE_NAVIGATION;
1496        } else if (cursorModeString != "pointer" && cursorModeString != "default") {
1497            LOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
1498        }
1499    }
1500
1501    mParameters.orientationAware = false;
1502    getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
1503            mParameters.orientationAware);
1504
1505    mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER
1506            || mParameters.orientationAware ? 0 : -1;
1507}
1508
1509void CursorInputMapper::dumpParameters(String8& dump) {
1510    dump.append(INDENT3 "Parameters:\n");
1511    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1512            mParameters.associatedDisplayId);
1513
1514    switch (mParameters.mode) {
1515    case Parameters::MODE_POINTER:
1516        dump.append(INDENT4 "Mode: pointer\n");
1517        break;
1518    case Parameters::MODE_NAVIGATION:
1519        dump.append(INDENT4 "Mode: navigation\n");
1520        break;
1521    default:
1522        LOG_ASSERT(false);
1523    }
1524
1525    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1526            toString(mParameters.orientationAware));
1527}
1528
1529void CursorInputMapper::initializeLocked() {
1530    mAccumulator.clear();
1531
1532    mLocked.buttonState = 0;
1533    mLocked.downTime = 0;
1534}
1535
1536void CursorInputMapper::reset() {
1537    for (;;) {
1538        int32_t buttonState;
1539        { // acquire lock
1540            AutoMutex _l(mLock);
1541
1542            buttonState = mLocked.buttonState;
1543            if (!buttonState) {
1544                initializeLocked();
1545                break; // done
1546            }
1547        } // release lock
1548
1549        // Reset velocity.
1550        mPointerVelocityControl.reset();
1551        mWheelXVelocityControl.reset();
1552        mWheelYVelocityControl.reset();
1553
1554        // Synthesize button up event on reset.
1555        nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
1556        mAccumulator.clear();
1557        mAccumulator.buttonDown = 0;
1558        mAccumulator.buttonUp = buttonState;
1559        mAccumulator.fields = Accumulator::FIELD_BUTTONS;
1560        sync(when);
1561    }
1562
1563    InputMapper::reset();
1564}
1565
1566void CursorInputMapper::process(const RawEvent* rawEvent) {
1567    switch (rawEvent->type) {
1568    case EV_KEY: {
1569        int32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
1570        if (buttonState) {
1571            if (rawEvent->value) {
1572                mAccumulator.buttonDown = buttonState;
1573                mAccumulator.buttonUp = 0;
1574            } else {
1575                mAccumulator.buttonDown = 0;
1576                mAccumulator.buttonUp = buttonState;
1577            }
1578            mAccumulator.fields |= Accumulator::FIELD_BUTTONS;
1579
1580            // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1581            // we need to ensure that we report the up/down promptly.
1582            sync(rawEvent->when);
1583            break;
1584        }
1585        break;
1586    }
1587
1588    case EV_REL:
1589        switch (rawEvent->scanCode) {
1590        case REL_X:
1591            mAccumulator.fields |= Accumulator::FIELD_REL_X;
1592            mAccumulator.relX = rawEvent->value;
1593            break;
1594        case REL_Y:
1595            mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1596            mAccumulator.relY = rawEvent->value;
1597            break;
1598        case REL_WHEEL:
1599            mAccumulator.fields |= Accumulator::FIELD_REL_WHEEL;
1600            mAccumulator.relWheel = rawEvent->value;
1601            break;
1602        case REL_HWHEEL:
1603            mAccumulator.fields |= Accumulator::FIELD_REL_HWHEEL;
1604            mAccumulator.relHWheel = rawEvent->value;
1605            break;
1606        }
1607        break;
1608
1609    case EV_SYN:
1610        switch (rawEvent->scanCode) {
1611        case SYN_REPORT:
1612            sync(rawEvent->when);
1613            break;
1614        }
1615        break;
1616    }
1617}
1618
1619void CursorInputMapper::sync(nsecs_t when) {
1620    uint32_t fields = mAccumulator.fields;
1621    if (fields == 0) {
1622        return; // no new state changes, so nothing to do
1623    }
1624
1625    int32_t motionEventAction;
1626    int32_t motionEventEdgeFlags;
1627    int32_t lastButtonState, currentButtonState;
1628    PointerProperties pointerProperties;
1629    PointerCoords pointerCoords;
1630    nsecs_t downTime;
1631    float vscroll, hscroll;
1632    { // acquire lock
1633        AutoMutex _l(mLock);
1634
1635        lastButtonState = mLocked.buttonState;
1636
1637        bool down, downChanged;
1638        bool wasDown = isPointerDown(mLocked.buttonState);
1639        bool buttonsChanged = fields & Accumulator::FIELD_BUTTONS;
1640        if (buttonsChanged) {
1641            mLocked.buttonState = (mLocked.buttonState | mAccumulator.buttonDown)
1642                    & ~mAccumulator.buttonUp;
1643
1644            down = isPointerDown(mLocked.buttonState);
1645
1646            if (!wasDown && down) {
1647                mLocked.downTime = when;
1648                downChanged = true;
1649            } else if (wasDown && !down) {
1650                downChanged = true;
1651            } else {
1652                downChanged = false;
1653            }
1654        } else {
1655            down = wasDown;
1656            downChanged = false;
1657        }
1658
1659        currentButtonState = mLocked.buttonState;
1660
1661        downTime = mLocked.downTime;
1662        float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1663        float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
1664
1665        if (downChanged) {
1666            motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
1667        } else if (down || mPointerController == NULL) {
1668            motionEventAction = AMOTION_EVENT_ACTION_MOVE;
1669        } else {
1670            motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
1671        }
1672
1673        if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
1674                && (deltaX != 0.0f || deltaY != 0.0f)) {
1675            // Rotate motion based on display orientation if needed.
1676            // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1677            int32_t orientation;
1678            if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1679                    NULL, NULL, & orientation)) {
1680                orientation = DISPLAY_ORIENTATION_0;
1681            }
1682
1683            float temp;
1684            switch (orientation) {
1685            case DISPLAY_ORIENTATION_90:
1686                temp = deltaX;
1687                deltaX = deltaY;
1688                deltaY = -temp;
1689                break;
1690
1691            case DISPLAY_ORIENTATION_180:
1692                deltaX = -deltaX;
1693                deltaY = -deltaY;
1694                break;
1695
1696            case DISPLAY_ORIENTATION_270:
1697                temp = deltaX;
1698                deltaX = -deltaY;
1699                deltaY = temp;
1700                break;
1701            }
1702        }
1703
1704        motionEventEdgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
1705
1706        pointerProperties.clear();
1707        pointerProperties.id = 0;
1708        pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
1709
1710        pointerCoords.clear();
1711
1712        if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) {
1713            vscroll = mAccumulator.relWheel;
1714        } else {
1715            vscroll = 0;
1716        }
1717        mWheelYVelocityControl.move(when, NULL, &vscroll);
1718
1719        if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) {
1720            hscroll = mAccumulator.relHWheel;
1721        } else {
1722            hscroll = 0;
1723        }
1724        mWheelXVelocityControl.move(when, &hscroll, NULL);
1725
1726        mPointerVelocityControl.move(when, &deltaX, &deltaY);
1727
1728        if (mPointerController != NULL) {
1729            if (deltaX != 0 || deltaY != 0 || vscroll != 0 || hscroll != 0
1730                    || buttonsChanged) {
1731                mPointerController->setPresentation(
1732                        PointerControllerInterface::PRESENTATION_POINTER);
1733
1734                if (deltaX != 0 || deltaY != 0) {
1735                    mPointerController->move(deltaX, deltaY);
1736                }
1737
1738                if (buttonsChanged) {
1739                    mPointerController->setButtonState(mLocked.buttonState);
1740                }
1741
1742                mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
1743            }
1744
1745            float x, y;
1746            mPointerController->getPosition(&x, &y);
1747            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
1748            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
1749
1750            if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
1751                motionEventEdgeFlags = calculateEdgeFlagsUsingPointerBounds(
1752                        mPointerController, x, y);
1753            }
1754        } else {
1755            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
1756            pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
1757        }
1758
1759        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
1760    } // release lock
1761
1762    // Moving an external trackball or mouse should wake the device.
1763    // We don't do this for internal cursor devices to prevent them from waking up
1764    // the device in your pocket.
1765    // TODO: Use the input device configuration to control this behavior more finely.
1766    uint32_t policyFlags = 0;
1767    if (getDevice()->isExternal()) {
1768        policyFlags |= POLICY_FLAG_WAKE_DROPPED;
1769    }
1770
1771    // Synthesize key down from buttons if needed.
1772    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
1773            policyFlags, lastButtonState, currentButtonState);
1774
1775    // Send motion event.
1776    int32_t metaState = mContext->getGlobalMetaState();
1777    getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags,
1778            motionEventAction, 0, metaState, currentButtonState, motionEventEdgeFlags,
1779            1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
1780
1781    // Send hover move after UP to tell the application that the mouse is hovering now.
1782    if (motionEventAction == AMOTION_EVENT_ACTION_UP
1783            && mPointerController != NULL) {
1784        getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags,
1785                AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
1786                metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE,
1787                1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
1788    }
1789
1790    // Send scroll events.
1791    if (vscroll != 0 || hscroll != 0) {
1792        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
1793        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
1794
1795        getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags,
1796                AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState,
1797                AMOTION_EVENT_EDGE_FLAG_NONE,
1798                1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
1799    }
1800
1801    // Synthesize key up from buttons if needed.
1802    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
1803            policyFlags, lastButtonState, currentButtonState);
1804
1805    mAccumulator.clear();
1806}
1807
1808int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1809    if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1810        return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1811    } else {
1812        return AKEY_STATE_UNKNOWN;
1813    }
1814}
1815
1816void CursorInputMapper::fadePointer() {
1817    { // acquire lock
1818        AutoMutex _l(mLock);
1819        if (mPointerController != NULL) {
1820            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
1821        }
1822    } // release lock
1823}
1824
1825
1826// --- TouchInputMapper ---
1827
1828TouchInputMapper::TouchInputMapper(InputDevice* device) :
1829        InputMapper(device) {
1830    mLocked.surfaceOrientation = -1;
1831    mLocked.surfaceWidth = -1;
1832    mLocked.surfaceHeight = -1;
1833
1834    initializeLocked();
1835}
1836
1837TouchInputMapper::~TouchInputMapper() {
1838}
1839
1840uint32_t TouchInputMapper::getSources() {
1841    return mTouchSource | mPointerSource;
1842}
1843
1844void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1845    InputMapper::populateDeviceInfo(info);
1846
1847    { // acquire lock
1848        AutoMutex _l(mLock);
1849
1850        // Ensure surface information is up to date so that orientation changes are
1851        // noticed immediately.
1852        if (!configureSurfaceLocked()) {
1853            return;
1854        }
1855
1856        info->addMotionRange(mLocked.orientedRanges.x);
1857        info->addMotionRange(mLocked.orientedRanges.y);
1858
1859        if (mLocked.orientedRanges.havePressure) {
1860            info->addMotionRange(mLocked.orientedRanges.pressure);
1861        }
1862
1863        if (mLocked.orientedRanges.haveSize) {
1864            info->addMotionRange(mLocked.orientedRanges.size);
1865        }
1866
1867        if (mLocked.orientedRanges.haveTouchSize) {
1868            info->addMotionRange(mLocked.orientedRanges.touchMajor);
1869            info->addMotionRange(mLocked.orientedRanges.touchMinor);
1870        }
1871
1872        if (mLocked.orientedRanges.haveToolSize) {
1873            info->addMotionRange(mLocked.orientedRanges.toolMajor);
1874            info->addMotionRange(mLocked.orientedRanges.toolMinor);
1875        }
1876
1877        if (mLocked.orientedRanges.haveOrientation) {
1878            info->addMotionRange(mLocked.orientedRanges.orientation);
1879        }
1880
1881        if (mLocked.orientedRanges.haveDistance) {
1882            info->addMotionRange(mLocked.orientedRanges.distance);
1883        }
1884
1885        if (mPointerController != NULL) {
1886            float minX, minY, maxX, maxY;
1887            if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
1888                info->addMotionRange(AMOTION_EVENT_AXIS_X, mPointerSource,
1889                        minX, maxX, 0.0f, 0.0f);
1890                info->addMotionRange(AMOTION_EVENT_AXIS_Y, mPointerSource,
1891                        minY, maxY, 0.0f, 0.0f);
1892            }
1893            info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mPointerSource,
1894                    0.0f, 1.0f, 0.0f, 0.0f);
1895        }
1896    } // release lock
1897}
1898
1899void TouchInputMapper::dump(String8& dump) {
1900    { // acquire lock
1901        AutoMutex _l(mLock);
1902        dump.append(INDENT2 "Touch Input Mapper:\n");
1903        dumpParameters(dump);
1904        dumpVirtualKeysLocked(dump);
1905        dumpRawAxes(dump);
1906        dumpCalibration(dump);
1907        dumpSurfaceLocked(dump);
1908
1909        dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
1910        dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
1911        dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
1912        dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
1913        dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
1914        dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
1915        dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
1916        dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
1917        dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
1918        dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
1919        dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
1920        dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
1921        dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mLocked.orientationScale);
1922        dump.appendFormat(INDENT4 "DistanceScale: %0.3f\n", mLocked.distanceScale);
1923
1924        dump.appendFormat(INDENT3 "Last Touch:\n");
1925        dump.appendFormat(INDENT4 "Button State: 0x%08x\n", mLastTouch.buttonState);
1926        dump.appendFormat(INDENT4 "Pointer Count: %d\n", mLastTouch.pointerCount);
1927        for (uint32_t i = 0; i < mLastTouch.pointerCount; i++) {
1928            const PointerData& pointer = mLastTouch.pointers[i];
1929            dump.appendFormat(INDENT5 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
1930                    "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
1931                    "orientation=%d, distance=%d, isStylus=%s\n", i,
1932                    pointer.id, pointer.x, pointer.y, pointer.pressure,
1933                    pointer.touchMajor, pointer.touchMinor, pointer.toolMajor, pointer.toolMinor,
1934                    pointer.orientation, pointer.distance, toString(pointer.isStylus));
1935        }
1936
1937        if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
1938            dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n");
1939            dump.appendFormat(INDENT4 "XMovementScale: %0.3f\n",
1940                    mLocked.pointerGestureXMovementScale);
1941            dump.appendFormat(INDENT4 "YMovementScale: %0.3f\n",
1942                    mLocked.pointerGestureYMovementScale);
1943            dump.appendFormat(INDENT4 "XZoomScale: %0.3f\n",
1944                    mLocked.pointerGestureXZoomScale);
1945            dump.appendFormat(INDENT4 "YZoomScale: %0.3f\n",
1946                    mLocked.pointerGestureYZoomScale);
1947            dump.appendFormat(INDENT4 "MaxSwipeWidth: %f\n",
1948                    mLocked.pointerGestureMaxSwipeWidth);
1949        }
1950    } // release lock
1951}
1952
1953void TouchInputMapper::initializeLocked() {
1954    mCurrentTouch.clear();
1955    mLastTouch.clear();
1956    mDownTime = 0;
1957
1958    for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1959        mAveragingTouchFilter.historyStart[i] = 0;
1960        mAveragingTouchFilter.historyEnd[i] = 0;
1961    }
1962
1963    mJumpyTouchFilter.jumpyPointsDropped = 0;
1964
1965    mLocked.currentVirtualKey.down = false;
1966
1967    mLocked.orientedRanges.havePressure = false;
1968    mLocked.orientedRanges.haveSize = false;
1969    mLocked.orientedRanges.haveTouchSize = false;
1970    mLocked.orientedRanges.haveToolSize = false;
1971    mLocked.orientedRanges.haveOrientation = false;
1972    mLocked.orientedRanges.haveDistance = false;
1973
1974    mPointerGesture.reset();
1975}
1976
1977void TouchInputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) {
1978    InputMapper::configure(config, changes);
1979
1980    mConfig = *config;
1981
1982    if (!changes) { // first time only
1983        // Configure basic parameters.
1984        configureParameters();
1985
1986        // Configure sources.
1987        switch (mParameters.deviceType) {
1988        case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1989            mTouchSource = AINPUT_SOURCE_TOUCHSCREEN;
1990            mPointerSource = 0;
1991            break;
1992        case Parameters::DEVICE_TYPE_TOUCH_PAD:
1993            mTouchSource = AINPUT_SOURCE_TOUCHPAD;
1994            mPointerSource = 0;
1995            break;
1996        case Parameters::DEVICE_TYPE_POINTER:
1997            mTouchSource = AINPUT_SOURCE_TOUCHPAD;
1998            mPointerSource = AINPUT_SOURCE_MOUSE;
1999            break;
2000        default:
2001            LOG_ASSERT(false);
2002        }
2003
2004        // Configure absolute axis information.
2005        configureRawAxes();
2006
2007        // Prepare input device calibration.
2008        parseCalibration();
2009        resolveCalibration();
2010
2011        { // acquire lock
2012            AutoMutex _l(mLock);
2013
2014             // Configure surface dimensions and orientation.
2015            configureSurfaceLocked();
2016        } // release lock
2017    }
2018
2019    if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
2020        mPointerGesture.pointerVelocityControl.setParameters(
2021                mConfig.pointerVelocityControlParameters);
2022    }
2023
2024    if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT)) {
2025        // Reset the touch screen when pointer gesture enablement changes.
2026        reset();
2027    }
2028}
2029
2030void TouchInputMapper::configureParameters() {
2031    mParameters.useBadTouchFilter = mConfig.filterTouchEvents;
2032    mParameters.useAveragingTouchFilter = mConfig.filterTouchEvents;
2033    mParameters.useJumpyTouchFilter = mConfig.filterJumpyTouchEvents;
2034
2035    // Use the pointer presentation mode for devices that do not support distinct
2036    // multitouch.  The spot-based presentation relies on being able to accurately
2037    // locate two or more fingers on the touch pad.
2038    mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT)
2039            ? Parameters::GESTURE_MODE_POINTER : Parameters::GESTURE_MODE_SPOTS;
2040
2041    String8 gestureModeString;
2042    if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
2043            gestureModeString)) {
2044        if (gestureModeString == "pointer") {
2045            mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER;
2046        } else if (gestureModeString == "spots") {
2047            mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
2048        } else if (gestureModeString != "default") {
2049            LOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
2050        }
2051    }
2052
2053    if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
2054            || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
2055        // The device is a cursor device with a touch pad attached.
2056        // By default don't use the touch pad to move the pointer.
2057        mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
2058    } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) {
2059        // The device is a pointing device like a track pad.
2060        mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
2061    } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
2062        // The device is a touch screen.
2063        mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
2064    } else {
2065        // The device is a touch pad of unknown purpose.
2066        mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
2067    }
2068
2069    String8 deviceTypeString;
2070    if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
2071            deviceTypeString)) {
2072        if (deviceTypeString == "touchScreen") {
2073            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
2074        } else if (deviceTypeString == "touchPad") {
2075            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
2076        } else if (deviceTypeString == "pointer") {
2077            mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
2078        } else if (deviceTypeString != "default") {
2079            LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
2080        }
2081    }
2082
2083    mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
2084    getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
2085            mParameters.orientationAware);
2086
2087    mParameters.associatedDisplayId = mParameters.orientationAware
2088            || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
2089            || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
2090            ? 0 : -1;
2091}
2092
2093void TouchInputMapper::dumpParameters(String8& dump) {
2094    dump.append(INDENT3 "Parameters:\n");
2095
2096    switch (mParameters.gestureMode) {
2097    case Parameters::GESTURE_MODE_POINTER:
2098        dump.append(INDENT4 "GestureMode: pointer\n");
2099        break;
2100    case Parameters::GESTURE_MODE_SPOTS:
2101        dump.append(INDENT4 "GestureMode: spots\n");
2102        break;
2103    default:
2104        assert(false);
2105    }
2106
2107    switch (mParameters.deviceType) {
2108    case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
2109        dump.append(INDENT4 "DeviceType: touchScreen\n");
2110        break;
2111    case Parameters::DEVICE_TYPE_TOUCH_PAD:
2112        dump.append(INDENT4 "DeviceType: touchPad\n");
2113        break;
2114    case Parameters::DEVICE_TYPE_POINTER:
2115        dump.append(INDENT4 "DeviceType: pointer\n");
2116        break;
2117    default:
2118        LOG_ASSERT(false);
2119    }
2120
2121    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
2122            mParameters.associatedDisplayId);
2123    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
2124            toString(mParameters.orientationAware));
2125
2126    dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
2127            toString(mParameters.useBadTouchFilter));
2128    dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
2129            toString(mParameters.useAveragingTouchFilter));
2130    dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
2131            toString(mParameters.useJumpyTouchFilter));
2132}
2133
2134void TouchInputMapper::configureRawAxes() {
2135    mRawAxes.x.clear();
2136    mRawAxes.y.clear();
2137    mRawAxes.pressure.clear();
2138    mRawAxes.touchMajor.clear();
2139    mRawAxes.touchMinor.clear();
2140    mRawAxes.toolMajor.clear();
2141    mRawAxes.toolMinor.clear();
2142    mRawAxes.orientation.clear();
2143    mRawAxes.distance.clear();
2144    mRawAxes.trackingId.clear();
2145    mRawAxes.slot.clear();
2146}
2147
2148void TouchInputMapper::dumpRawAxes(String8& dump) {
2149    dump.append(INDENT3 "Raw Axes:\n");
2150    dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X");
2151    dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y");
2152    dumpRawAbsoluteAxisInfo(dump, mRawAxes.pressure, "Pressure");
2153    dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
2154    dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
2155    dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
2156    dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
2157    dumpRawAbsoluteAxisInfo(dump, mRawAxes.orientation, "Orientation");
2158    dumpRawAbsoluteAxisInfo(dump, mRawAxes.distance, "Distance");
2159    dumpRawAbsoluteAxisInfo(dump, mRawAxes.trackingId, "TrackingId");
2160    dumpRawAbsoluteAxisInfo(dump, mRawAxes.slot, "Slot");
2161}
2162
2163bool TouchInputMapper::configureSurfaceLocked() {
2164    // Ensure we have valid X and Y axes.
2165    if (!mRawAxes.x.valid || !mRawAxes.y.valid) {
2166        LOGW(INDENT "Touch device '%s' did not report support for X or Y axis!  "
2167                "The device will be inoperable.", getDeviceName().string());
2168        return false;
2169    }
2170
2171    // Update orientation and dimensions if needed.
2172    int32_t orientation = DISPLAY_ORIENTATION_0;
2173    int32_t width = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
2174    int32_t height = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
2175
2176    if (mParameters.associatedDisplayId >= 0) {
2177        // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
2178        if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
2179                &mLocked.associatedDisplayWidth, &mLocked.associatedDisplayHeight,
2180                &mLocked.associatedDisplayOrientation)) {
2181            return false;
2182        }
2183
2184        // A touch screen inherits the dimensions of the display.
2185        if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
2186            width = mLocked.associatedDisplayWidth;
2187            height = mLocked.associatedDisplayHeight;
2188        }
2189
2190        // The device inherits the orientation of the display if it is orientation aware.
2191        if (mParameters.orientationAware) {
2192            orientation = mLocked.associatedDisplayOrientation;
2193        }
2194    }
2195
2196    if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
2197            && mPointerController == NULL) {
2198        mPointerController = getPolicy()->obtainPointerController(getDeviceId());
2199    }
2200
2201    bool orientationChanged = mLocked.surfaceOrientation != orientation;
2202    if (orientationChanged) {
2203        mLocked.surfaceOrientation = orientation;
2204    }
2205
2206    bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
2207    if (sizeChanged) {
2208        LOGI("Device reconfigured: id=%d, name='%s', surface size is now %dx%d",
2209                getDeviceId(), getDeviceName().string(), width, height);
2210
2211        mLocked.surfaceWidth = width;
2212        mLocked.surfaceHeight = height;
2213
2214        // Configure X and Y factors.
2215        mLocked.xScale = float(width) / (mRawAxes.x.maxValue - mRawAxes.x.minValue + 1);
2216        mLocked.yScale = float(height) / (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1);
2217        mLocked.xPrecision = 1.0f / mLocked.xScale;
2218        mLocked.yPrecision = 1.0f / mLocked.yScale;
2219
2220        mLocked.orientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
2221        mLocked.orientedRanges.x.source = mTouchSource;
2222        mLocked.orientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
2223        mLocked.orientedRanges.y.source = mTouchSource;
2224
2225        configureVirtualKeysLocked();
2226
2227        // Scale factor for terms that are not oriented in a particular axis.
2228        // If the pixels are square then xScale == yScale otherwise we fake it
2229        // by choosing an average.
2230        mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
2231
2232        // Size of diagonal axis.
2233        float diagonalSize = hypotf(width, height);
2234
2235        // TouchMajor and TouchMinor factors.
2236        if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
2237            mLocked.orientedRanges.haveTouchSize = true;
2238
2239            mLocked.orientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
2240            mLocked.orientedRanges.touchMajor.source = mTouchSource;
2241            mLocked.orientedRanges.touchMajor.min = 0;
2242            mLocked.orientedRanges.touchMajor.max = diagonalSize;
2243            mLocked.orientedRanges.touchMajor.flat = 0;
2244            mLocked.orientedRanges.touchMajor.fuzz = 0;
2245
2246            mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
2247            mLocked.orientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
2248        }
2249
2250        // ToolMajor and ToolMinor factors.
2251        mLocked.toolSizeLinearScale = 0;
2252        mLocked.toolSizeLinearBias = 0;
2253        mLocked.toolSizeAreaScale = 0;
2254        mLocked.toolSizeAreaBias = 0;
2255        if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2256            if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
2257                if (mCalibration.haveToolSizeLinearScale) {
2258                    mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
2259                } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
2260                    mLocked.toolSizeLinearScale = float(min(width, height))
2261                            / mRawAxes.toolMajor.maxValue;
2262                }
2263
2264                if (mCalibration.haveToolSizeLinearBias) {
2265                    mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
2266                }
2267            } else if (mCalibration.toolSizeCalibration ==
2268                    Calibration::TOOL_SIZE_CALIBRATION_AREA) {
2269                if (mCalibration.haveToolSizeLinearScale) {
2270                    mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
2271                } else {
2272                    mLocked.toolSizeLinearScale = min(width, height);
2273                }
2274
2275                if (mCalibration.haveToolSizeLinearBias) {
2276                    mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
2277                }
2278
2279                if (mCalibration.haveToolSizeAreaScale) {
2280                    mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
2281                } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
2282                    mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
2283                }
2284
2285                if (mCalibration.haveToolSizeAreaBias) {
2286                    mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
2287                }
2288            }
2289
2290            mLocked.orientedRanges.haveToolSize = true;
2291
2292            mLocked.orientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
2293            mLocked.orientedRanges.toolMajor.source = mTouchSource;
2294            mLocked.orientedRanges.toolMajor.min = 0;
2295            mLocked.orientedRanges.toolMajor.max = diagonalSize;
2296            mLocked.orientedRanges.toolMajor.flat = 0;
2297            mLocked.orientedRanges.toolMajor.fuzz = 0;
2298
2299            mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
2300            mLocked.orientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
2301        }
2302
2303        // Pressure factors.
2304        mLocked.pressureScale = 0;
2305        if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
2306            RawAbsoluteAxisInfo rawPressureAxis;
2307            switch (mCalibration.pressureSource) {
2308            case Calibration::PRESSURE_SOURCE_PRESSURE:
2309                rawPressureAxis = mRawAxes.pressure;
2310                break;
2311            case Calibration::PRESSURE_SOURCE_TOUCH:
2312                rawPressureAxis = mRawAxes.touchMajor;
2313                break;
2314            default:
2315                rawPressureAxis.clear();
2316            }
2317
2318            if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
2319                    || mCalibration.pressureCalibration
2320                            == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
2321                if (mCalibration.havePressureScale) {
2322                    mLocked.pressureScale = mCalibration.pressureScale;
2323                } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
2324                    mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
2325                }
2326            }
2327
2328            mLocked.orientedRanges.havePressure = true;
2329
2330            mLocked.orientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
2331            mLocked.orientedRanges.pressure.source = mTouchSource;
2332            mLocked.orientedRanges.pressure.min = 0;
2333            mLocked.orientedRanges.pressure.max = 1.0;
2334            mLocked.orientedRanges.pressure.flat = 0;
2335            mLocked.orientedRanges.pressure.fuzz = 0;
2336        }
2337
2338        // Size factors.
2339        mLocked.sizeScale = 0;
2340        if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
2341            if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
2342                if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
2343                    mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
2344                }
2345            }
2346
2347            mLocked.orientedRanges.haveSize = true;
2348
2349            mLocked.orientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
2350            mLocked.orientedRanges.size.source = mTouchSource;
2351            mLocked.orientedRanges.size.min = 0;
2352            mLocked.orientedRanges.size.max = 1.0;
2353            mLocked.orientedRanges.size.flat = 0;
2354            mLocked.orientedRanges.size.fuzz = 0;
2355        }
2356
2357        // Orientation
2358        mLocked.orientationScale = 0;
2359        if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
2360            if (mCalibration.orientationCalibration
2361                    == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
2362                if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
2363                    mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
2364                }
2365            }
2366
2367            mLocked.orientedRanges.haveOrientation = true;
2368
2369            mLocked.orientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
2370            mLocked.orientedRanges.orientation.source = mTouchSource;
2371            mLocked.orientedRanges.orientation.min = - M_PI_2;
2372            mLocked.orientedRanges.orientation.max = M_PI_2;
2373            mLocked.orientedRanges.orientation.flat = 0;
2374            mLocked.orientedRanges.orientation.fuzz = 0;
2375        }
2376
2377        // Distance
2378        mLocked.distanceScale = 0;
2379        if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) {
2380            if (mCalibration.distanceCalibration
2381                    == Calibration::DISTANCE_CALIBRATION_SCALED) {
2382                if (mCalibration.haveDistanceScale) {
2383                    mLocked.distanceScale = mCalibration.distanceScale;
2384                } else {
2385                    mLocked.distanceScale = 1.0f;
2386                }
2387            }
2388
2389            mLocked.orientedRanges.haveDistance = true;
2390
2391            mLocked.orientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE;
2392            mLocked.orientedRanges.distance.source = mTouchSource;
2393            mLocked.orientedRanges.distance.min =
2394                    mRawAxes.distance.minValue * mLocked.distanceScale;
2395            mLocked.orientedRanges.distance.max =
2396                    mRawAxes.distance.minValue * mLocked.distanceScale;
2397            mLocked.orientedRanges.distance.flat = 0;
2398            mLocked.orientedRanges.distance.fuzz =
2399                    mRawAxes.distance.fuzz * mLocked.distanceScale;
2400        }
2401    }
2402
2403    if (orientationChanged || sizeChanged) {
2404        // Compute oriented surface dimensions, precision, scales and ranges.
2405        // Note that the maximum value reported is an inclusive maximum value so it is one
2406        // unit less than the total width or height of surface.
2407        switch (mLocked.surfaceOrientation) {
2408        case DISPLAY_ORIENTATION_90:
2409        case DISPLAY_ORIENTATION_270:
2410            mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
2411            mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
2412
2413            mLocked.orientedXPrecision = mLocked.yPrecision;
2414            mLocked.orientedYPrecision = mLocked.xPrecision;
2415
2416            mLocked.orientedRanges.x.min = 0;
2417            mLocked.orientedRanges.x.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue)
2418                    * mLocked.yScale;
2419            mLocked.orientedRanges.x.flat = 0;
2420            mLocked.orientedRanges.x.fuzz = mLocked.yScale;
2421
2422            mLocked.orientedRanges.y.min = 0;
2423            mLocked.orientedRanges.y.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue)
2424                    * mLocked.xScale;
2425            mLocked.orientedRanges.y.flat = 0;
2426            mLocked.orientedRanges.y.fuzz = mLocked.xScale;
2427            break;
2428
2429        default:
2430            mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
2431            mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
2432
2433            mLocked.orientedXPrecision = mLocked.xPrecision;
2434            mLocked.orientedYPrecision = mLocked.yPrecision;
2435
2436            mLocked.orientedRanges.x.min = 0;
2437            mLocked.orientedRanges.x.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue)
2438                    * mLocked.xScale;
2439            mLocked.orientedRanges.x.flat = 0;
2440            mLocked.orientedRanges.x.fuzz = mLocked.xScale;
2441
2442            mLocked.orientedRanges.y.min = 0;
2443            mLocked.orientedRanges.y.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue)
2444                    * mLocked.yScale;
2445            mLocked.orientedRanges.y.flat = 0;
2446            mLocked.orientedRanges.y.fuzz = mLocked.yScale;
2447            break;
2448        }
2449
2450        // Compute pointer gesture detection parameters.
2451        // TODO: These factors should not be hardcoded.
2452        if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
2453            int32_t rawWidth = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
2454            int32_t rawHeight = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
2455            float rawDiagonal = hypotf(rawWidth, rawHeight);
2456            float displayDiagonal = hypotf(mLocked.associatedDisplayWidth,
2457                    mLocked.associatedDisplayHeight);
2458
2459            // Scale movements such that one whole swipe of the touch pad covers a
2460            // given area relative to the diagonal size of the display when no acceleration
2461            // is applied.
2462            // Assume that the touch pad has a square aspect ratio such that movements in
2463            // X and Y of the same number of raw units cover the same physical distance.
2464            mLocked.pointerGestureXMovementScale = mConfig.pointerGestureMovementSpeedRatio
2465                    * displayDiagonal / rawDiagonal;
2466            mLocked.pointerGestureYMovementScale = mLocked.pointerGestureXMovementScale;
2467
2468            // Scale zooms to cover a smaller range of the display than movements do.
2469            // This value determines the area around the pointer that is affected by freeform
2470            // pointer gestures.
2471            mLocked.pointerGestureXZoomScale = mConfig.pointerGestureZoomSpeedRatio
2472                    * displayDiagonal / rawDiagonal;
2473            mLocked.pointerGestureYZoomScale = mLocked.pointerGestureXZoomScale;
2474
2475            // Max width between pointers to detect a swipe gesture is more than some fraction
2476            // of the diagonal axis of the touch pad.  Touches that are wider than this are
2477            // translated into freeform gestures.
2478            mLocked.pointerGestureMaxSwipeWidth =
2479                    mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
2480
2481            // Reset the current pointer gesture.
2482            mPointerGesture.reset();
2483
2484            // Remove any current spots.
2485            if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
2486                mPointerController->clearSpots();
2487            }
2488        }
2489    }
2490
2491    return true;
2492}
2493
2494void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
2495    dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
2496    dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
2497    dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
2498}
2499
2500void TouchInputMapper::configureVirtualKeysLocked() {
2501    Vector<VirtualKeyDefinition> virtualKeyDefinitions;
2502    getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
2503
2504    mLocked.virtualKeys.clear();
2505
2506    if (virtualKeyDefinitions.size() == 0) {
2507        return;
2508    }
2509
2510    mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
2511
2512    int32_t touchScreenLeft = mRawAxes.x.minValue;
2513    int32_t touchScreenTop = mRawAxes.y.minValue;
2514    int32_t touchScreenWidth = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
2515    int32_t touchScreenHeight = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
2516
2517    for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
2518        const VirtualKeyDefinition& virtualKeyDefinition =
2519                virtualKeyDefinitions[i];
2520
2521        mLocked.virtualKeys.add();
2522        VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
2523
2524        virtualKey.scanCode = virtualKeyDefinition.scanCode;
2525        int32_t keyCode;
2526        uint32_t flags;
2527        if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode,
2528                & keyCode, & flags)) {
2529            LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
2530                    virtualKey.scanCode);
2531            mLocked.virtualKeys.pop(); // drop the key
2532            continue;
2533        }
2534
2535        virtualKey.keyCode = keyCode;
2536        virtualKey.flags = flags;
2537
2538        // convert the key definition's display coordinates into touch coordinates for a hit box
2539        int32_t halfWidth = virtualKeyDefinition.width / 2;
2540        int32_t halfHeight = virtualKeyDefinition.height / 2;
2541
2542        virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
2543                * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
2544        virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
2545                * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
2546        virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
2547                * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
2548        virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
2549                * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
2550    }
2551}
2552
2553void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
2554    if (!mLocked.virtualKeys.isEmpty()) {
2555        dump.append(INDENT3 "Virtual Keys:\n");
2556
2557        for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
2558            const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
2559            dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
2560                    "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
2561                    i, virtualKey.scanCode, virtualKey.keyCode,
2562                    virtualKey.hitLeft, virtualKey.hitRight,
2563                    virtualKey.hitTop, virtualKey.hitBottom);
2564        }
2565    }
2566}
2567
2568void TouchInputMapper::parseCalibration() {
2569    const PropertyMap& in = getDevice()->getConfiguration();
2570    Calibration& out = mCalibration;
2571
2572    // Touch Size
2573    out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
2574    String8 touchSizeCalibrationString;
2575    if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
2576        if (touchSizeCalibrationString == "none") {
2577            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
2578        } else if (touchSizeCalibrationString == "geometric") {
2579            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
2580        } else if (touchSizeCalibrationString == "pressure") {
2581            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
2582        } else if (touchSizeCalibrationString != "default") {
2583            LOGW("Invalid value for touch.touchSize.calibration: '%s'",
2584                    touchSizeCalibrationString.string());
2585        }
2586    }
2587
2588    // Tool Size
2589    out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
2590    String8 toolSizeCalibrationString;
2591    if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
2592        if (toolSizeCalibrationString == "none") {
2593            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
2594        } else if (toolSizeCalibrationString == "geometric") {
2595            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
2596        } else if (toolSizeCalibrationString == "linear") {
2597            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
2598        } else if (toolSizeCalibrationString == "area") {
2599            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
2600        } else if (toolSizeCalibrationString != "default") {
2601            LOGW("Invalid value for touch.toolSize.calibration: '%s'",
2602                    toolSizeCalibrationString.string());
2603        }
2604    }
2605
2606    out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
2607            out.toolSizeLinearScale);
2608    out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
2609            out.toolSizeLinearBias);
2610    out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
2611            out.toolSizeAreaScale);
2612    out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
2613            out.toolSizeAreaBias);
2614    out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
2615            out.toolSizeIsSummed);
2616
2617    // Pressure
2618    out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
2619    String8 pressureCalibrationString;
2620    if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
2621        if (pressureCalibrationString == "none") {
2622            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2623        } else if (pressureCalibrationString == "physical") {
2624            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
2625        } else if (pressureCalibrationString == "amplitude") {
2626            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2627        } else if (pressureCalibrationString != "default") {
2628            LOGW("Invalid value for touch.pressure.calibration: '%s'",
2629                    pressureCalibrationString.string());
2630        }
2631    }
2632
2633    out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
2634    String8 pressureSourceString;
2635    if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
2636        if (pressureSourceString == "pressure") {
2637            out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2638        } else if (pressureSourceString == "touch") {
2639            out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2640        } else if (pressureSourceString != "default") {
2641            LOGW("Invalid value for touch.pressure.source: '%s'",
2642                    pressureSourceString.string());
2643        }
2644    }
2645
2646    out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
2647            out.pressureScale);
2648
2649    // Size
2650    out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
2651    String8 sizeCalibrationString;
2652    if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
2653        if (sizeCalibrationString == "none") {
2654            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2655        } else if (sizeCalibrationString == "normalized") {
2656            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2657        } else if (sizeCalibrationString != "default") {
2658            LOGW("Invalid value for touch.size.calibration: '%s'",
2659                    sizeCalibrationString.string());
2660        }
2661    }
2662
2663    // Orientation
2664    out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
2665    String8 orientationCalibrationString;
2666    if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
2667        if (orientationCalibrationString == "none") {
2668            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2669        } else if (orientationCalibrationString == "interpolated") {
2670            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2671        } else if (orientationCalibrationString == "vector") {
2672            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
2673        } else if (orientationCalibrationString != "default") {
2674            LOGW("Invalid value for touch.orientation.calibration: '%s'",
2675                    orientationCalibrationString.string());
2676        }
2677    }
2678
2679    // Distance
2680    out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT;
2681    String8 distanceCalibrationString;
2682    if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
2683        if (distanceCalibrationString == "none") {
2684            out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
2685        } else if (distanceCalibrationString == "scaled") {
2686            out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
2687        } else if (distanceCalibrationString != "default") {
2688            LOGW("Invalid value for touch.distance.calibration: '%s'",
2689                    distanceCalibrationString.string());
2690        }
2691    }
2692
2693    out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"),
2694            out.distanceScale);
2695}
2696
2697void TouchInputMapper::resolveCalibration() {
2698    // Pressure
2699    switch (mCalibration.pressureSource) {
2700    case Calibration::PRESSURE_SOURCE_DEFAULT:
2701        if (mRawAxes.pressure.valid) {
2702            mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2703        } else if (mRawAxes.touchMajor.valid) {
2704            mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2705        }
2706        break;
2707
2708    case Calibration::PRESSURE_SOURCE_PRESSURE:
2709        if (! mRawAxes.pressure.valid) {
2710            LOGW("Calibration property touch.pressure.source is 'pressure' but "
2711                    "the pressure axis is not available.");
2712        }
2713        break;
2714
2715    case Calibration::PRESSURE_SOURCE_TOUCH:
2716        if (! mRawAxes.touchMajor.valid) {
2717            LOGW("Calibration property touch.pressure.source is 'touch' but "
2718                    "the touchMajor axis is not available.");
2719        }
2720        break;
2721
2722    default:
2723        break;
2724    }
2725
2726    switch (mCalibration.pressureCalibration) {
2727    case Calibration::PRESSURE_CALIBRATION_DEFAULT:
2728        if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
2729            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2730        } else {
2731            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2732        }
2733        break;
2734
2735    default:
2736        break;
2737    }
2738
2739    // Tool Size
2740    switch (mCalibration.toolSizeCalibration) {
2741    case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
2742        if (mRawAxes.toolMajor.valid) {
2743            mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
2744        } else {
2745            mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
2746        }
2747        break;
2748
2749    default:
2750        break;
2751    }
2752
2753    // Touch Size
2754    switch (mCalibration.touchSizeCalibration) {
2755    case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
2756        if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
2757                && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2758            mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
2759        } else {
2760            mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
2761        }
2762        break;
2763
2764    default:
2765        break;
2766    }
2767
2768    // Size
2769    switch (mCalibration.sizeCalibration) {
2770    case Calibration::SIZE_CALIBRATION_DEFAULT:
2771        if (mRawAxes.toolMajor.valid) {
2772            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2773        } else {
2774            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2775        }
2776        break;
2777
2778    default:
2779        break;
2780    }
2781
2782    // Orientation
2783    switch (mCalibration.orientationCalibration) {
2784    case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
2785        if (mRawAxes.orientation.valid) {
2786            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2787        } else {
2788            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2789        }
2790        break;
2791
2792    default:
2793        break;
2794    }
2795
2796    // Distance
2797    switch (mCalibration.distanceCalibration) {
2798    case Calibration::DISTANCE_CALIBRATION_DEFAULT:
2799        if (mRawAxes.distance.valid) {
2800            mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
2801        } else {
2802            mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
2803        }
2804        break;
2805
2806    default:
2807        break;
2808    }
2809}
2810
2811void TouchInputMapper::dumpCalibration(String8& dump) {
2812    dump.append(INDENT3 "Calibration:\n");
2813
2814    // Touch Size
2815    switch (mCalibration.touchSizeCalibration) {
2816    case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
2817        dump.append(INDENT4 "touch.touchSize.calibration: none\n");
2818        break;
2819    case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
2820        dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
2821        break;
2822    case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
2823        dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
2824        break;
2825    default:
2826        LOG_ASSERT(false);
2827    }
2828
2829    // Tool Size
2830    switch (mCalibration.toolSizeCalibration) {
2831    case Calibration::TOOL_SIZE_CALIBRATION_NONE:
2832        dump.append(INDENT4 "touch.toolSize.calibration: none\n");
2833        break;
2834    case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
2835        dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
2836        break;
2837    case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
2838        dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
2839        break;
2840    case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2841        dump.append(INDENT4 "touch.toolSize.calibration: area\n");
2842        break;
2843    default:
2844        LOG_ASSERT(false);
2845    }
2846
2847    if (mCalibration.haveToolSizeLinearScale) {
2848        dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
2849                mCalibration.toolSizeLinearScale);
2850    }
2851
2852    if (mCalibration.haveToolSizeLinearBias) {
2853        dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
2854                mCalibration.toolSizeLinearBias);
2855    }
2856
2857    if (mCalibration.haveToolSizeAreaScale) {
2858        dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
2859                mCalibration.toolSizeAreaScale);
2860    }
2861
2862    if (mCalibration.haveToolSizeAreaBias) {
2863        dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
2864                mCalibration.toolSizeAreaBias);
2865    }
2866
2867    if (mCalibration.haveToolSizeIsSummed) {
2868        dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
2869                toString(mCalibration.toolSizeIsSummed));
2870    }
2871
2872    // Pressure
2873    switch (mCalibration.pressureCalibration) {
2874    case Calibration::PRESSURE_CALIBRATION_NONE:
2875        dump.append(INDENT4 "touch.pressure.calibration: none\n");
2876        break;
2877    case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2878        dump.append(INDENT4 "touch.pressure.calibration: physical\n");
2879        break;
2880    case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2881        dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
2882        break;
2883    default:
2884        LOG_ASSERT(false);
2885    }
2886
2887    switch (mCalibration.pressureSource) {
2888    case Calibration::PRESSURE_SOURCE_PRESSURE:
2889        dump.append(INDENT4 "touch.pressure.source: pressure\n");
2890        break;
2891    case Calibration::PRESSURE_SOURCE_TOUCH:
2892        dump.append(INDENT4 "touch.pressure.source: touch\n");
2893        break;
2894    case Calibration::PRESSURE_SOURCE_DEFAULT:
2895        break;
2896    default:
2897        LOG_ASSERT(false);
2898    }
2899
2900    if (mCalibration.havePressureScale) {
2901        dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
2902                mCalibration.pressureScale);
2903    }
2904
2905    // Size
2906    switch (mCalibration.sizeCalibration) {
2907    case Calibration::SIZE_CALIBRATION_NONE:
2908        dump.append(INDENT4 "touch.size.calibration: none\n");
2909        break;
2910    case Calibration::SIZE_CALIBRATION_NORMALIZED:
2911        dump.append(INDENT4 "touch.size.calibration: normalized\n");
2912        break;
2913    default:
2914        LOG_ASSERT(false);
2915    }
2916
2917    // Orientation
2918    switch (mCalibration.orientationCalibration) {
2919    case Calibration::ORIENTATION_CALIBRATION_NONE:
2920        dump.append(INDENT4 "touch.orientation.calibration: none\n");
2921        break;
2922    case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2923        dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
2924        break;
2925    case Calibration::ORIENTATION_CALIBRATION_VECTOR:
2926        dump.append(INDENT4 "touch.orientation.calibration: vector\n");
2927        break;
2928    default:
2929        LOG_ASSERT(false);
2930    }
2931
2932    // Distance
2933    switch (mCalibration.distanceCalibration) {
2934    case Calibration::DISTANCE_CALIBRATION_NONE:
2935        dump.append(INDENT4 "touch.distance.calibration: none\n");
2936        break;
2937    case Calibration::DISTANCE_CALIBRATION_SCALED:
2938        dump.append(INDENT4 "touch.distance.calibration: scaled\n");
2939        break;
2940    default:
2941        LOG_ASSERT(false);
2942    }
2943
2944    if (mCalibration.haveDistanceScale) {
2945        dump.appendFormat(INDENT4 "touch.distance.scale: %0.3f\n",
2946                mCalibration.distanceScale);
2947    }
2948}
2949
2950void TouchInputMapper::reset() {
2951    // Synthesize touch up event if touch is currently down.
2952    // This will also take care of finishing virtual key processing if needed.
2953    if (mLastTouch.pointerCount != 0) {
2954        nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2955        mCurrentTouch.clear();
2956        syncTouch(when, true);
2957    }
2958
2959    { // acquire lock
2960        AutoMutex _l(mLock);
2961        initializeLocked();
2962
2963        if (mPointerController != NULL
2964                && mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
2965            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
2966            mPointerController->clearSpots();
2967        }
2968    } // release lock
2969
2970    InputMapper::reset();
2971}
2972
2973void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
2974#if DEBUG_RAW_EVENTS
2975    if (!havePointerIds) {
2976        LOGD("syncTouch: pointerCount=%d, no pointer ids", mCurrentTouch.pointerCount);
2977    } else {
2978        LOGD("syncTouch: pointerCount=%d, up=0x%08x, down=0x%08x, move=0x%08x, "
2979                "last=0x%08x, current=0x%08x", mCurrentTouch.pointerCount,
2980                mLastTouch.idBits.value & ~mCurrentTouch.idBits.value,
2981                mCurrentTouch.idBits.value & ~mLastTouch.idBits.value,
2982                mLastTouch.idBits.value & mCurrentTouch.idBits.value,
2983                mLastTouch.idBits.value, mCurrentTouch.idBits.value);
2984    }
2985#endif
2986
2987    // Preprocess pointer data.
2988    if (mParameters.useBadTouchFilter) {
2989        if (applyBadTouchFilter()) {
2990            havePointerIds = false;
2991        }
2992    }
2993
2994    if (mParameters.useJumpyTouchFilter) {
2995        if (applyJumpyTouchFilter()) {
2996            havePointerIds = false;
2997        }
2998    }
2999
3000    if (!havePointerIds) {
3001        calculatePointerIds();
3002    }
3003
3004    TouchData temp;
3005    TouchData* savedTouch;
3006    if (mParameters.useAveragingTouchFilter) {
3007        temp.copyFrom(mCurrentTouch);
3008        savedTouch = & temp;
3009
3010        applyAveragingTouchFilter();
3011    } else {
3012        savedTouch = & mCurrentTouch;
3013    }
3014
3015    uint32_t policyFlags = 0;
3016    if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
3017        if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
3018            // If this is a touch screen, hide the pointer on an initial down.
3019            getContext()->fadePointer();
3020        }
3021
3022        // Initial downs on external touch devices should wake the device.
3023        // We don't do this for internal touch screens to prevent them from waking
3024        // up in your pocket.
3025        // TODO: Use the input device configuration to control this behavior more finely.
3026        if (getDevice()->isExternal()) {
3027            policyFlags |= POLICY_FLAG_WAKE_DROPPED;
3028        }
3029    }
3030
3031    // Synthesize key down from buttons if needed.
3032    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mTouchSource,
3033            policyFlags, mLastTouch.buttonState, mCurrentTouch.buttonState);
3034
3035    // Send motion events.
3036    TouchResult touchResult;
3037    if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount == 0
3038            && mLastTouch.buttonState == mCurrentTouch.buttonState) {
3039        // Drop spurious syncs.
3040        touchResult = DROP_STROKE;
3041    } else {
3042        // Process touches and virtual keys.
3043        touchResult = consumeOffScreenTouches(when, policyFlags);
3044        if (touchResult == DISPATCH_TOUCH) {
3045            suppressSwipeOntoVirtualKeys(when);
3046            if (mPointerController != NULL && mConfig.pointerGesturesEnabled) {
3047                dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
3048            }
3049            dispatchTouches(when, policyFlags);
3050        }
3051    }
3052
3053    // Synthesize key up from buttons if needed.
3054    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mTouchSource,
3055            policyFlags, mLastTouch.buttonState, mCurrentTouch.buttonState);
3056
3057    // Copy current touch to last touch in preparation for the next cycle.
3058    // Keep the button state so we can track edge-triggered button state changes.
3059    if (touchResult == DROP_STROKE) {
3060        mLastTouch.clear();
3061        mLastTouch.buttonState = savedTouch->buttonState;
3062    } else {
3063        mLastTouch.copyFrom(*savedTouch);
3064    }
3065}
3066
3067void TouchInputMapper::timeoutExpired(nsecs_t when) {
3068    if (mPointerController != NULL) {
3069        dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
3070    }
3071}
3072
3073TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
3074        nsecs_t when, uint32_t policyFlags) {
3075    int32_t keyEventAction, keyEventFlags;
3076    int32_t keyCode, scanCode, downTime;
3077    TouchResult touchResult;
3078
3079    { // acquire lock
3080        AutoMutex _l(mLock);
3081
3082        // Update surface size and orientation, including virtual key positions.
3083        if (! configureSurfaceLocked()) {
3084            return DROP_STROKE;
3085        }
3086
3087        // Check for virtual key press.
3088        if (mLocked.currentVirtualKey.down) {
3089            if (mCurrentTouch.pointerCount == 0) {
3090                // Pointer went up while virtual key was down.
3091                mLocked.currentVirtualKey.down = false;
3092#if DEBUG_VIRTUAL_KEYS
3093                LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
3094                        mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
3095#endif
3096                keyEventAction = AKEY_EVENT_ACTION_UP;
3097                keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
3098                touchResult = SKIP_TOUCH;
3099                goto DispatchVirtualKey;
3100            }
3101
3102            if (mCurrentTouch.pointerCount == 1) {
3103                int32_t x = mCurrentTouch.pointers[0].x;
3104                int32_t y = mCurrentTouch.pointers[0].y;
3105                const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
3106                if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
3107                    // Pointer is still within the space of the virtual key.
3108                    return SKIP_TOUCH;
3109                }
3110            }
3111
3112            // Pointer left virtual key area or another pointer also went down.
3113            // Send key cancellation and drop the stroke so subsequent motions will be
3114            // considered fresh downs.  This is useful when the user swipes away from the
3115            // virtual key area into the main display surface.
3116            mLocked.currentVirtualKey.down = false;
3117#if DEBUG_VIRTUAL_KEYS
3118            LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
3119                    mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
3120#endif
3121            keyEventAction = AKEY_EVENT_ACTION_UP;
3122            keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
3123                    | AKEY_EVENT_FLAG_CANCELED;
3124
3125            // Check whether the pointer moved inside the display area where we should
3126            // start a new stroke.
3127            int32_t x = mCurrentTouch.pointers[0].x;
3128            int32_t y = mCurrentTouch.pointers[0].y;
3129            if (isPointInsideSurfaceLocked(x, y)) {
3130                mLastTouch.clear();
3131                touchResult = DISPATCH_TOUCH;
3132            } else {
3133                touchResult = DROP_STROKE;
3134            }
3135        } else {
3136            if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
3137                // Pointer just went down.  Handle off-screen touches, if needed.
3138                int32_t x = mCurrentTouch.pointers[0].x;
3139                int32_t y = mCurrentTouch.pointers[0].y;
3140                if (! isPointInsideSurfaceLocked(x, y)) {
3141                    // If exactly one pointer went down, check for virtual key hit.
3142                    // Otherwise we will drop the entire stroke.
3143                    if (mCurrentTouch.pointerCount == 1) {
3144                        const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
3145                        if (virtualKey) {
3146                            if (mContext->shouldDropVirtualKey(when, getDevice(),
3147                                    virtualKey->keyCode, virtualKey->scanCode)) {
3148                                return DROP_STROKE;
3149                            }
3150
3151                            mLocked.currentVirtualKey.down = true;
3152                            mLocked.currentVirtualKey.downTime = when;
3153                            mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
3154                            mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
3155#if DEBUG_VIRTUAL_KEYS
3156                            LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
3157                                    mLocked.currentVirtualKey.keyCode,
3158                                    mLocked.currentVirtualKey.scanCode);
3159#endif
3160                            keyEventAction = AKEY_EVENT_ACTION_DOWN;
3161                            keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
3162                                    | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
3163                            touchResult = SKIP_TOUCH;
3164                            goto DispatchVirtualKey;
3165                        }
3166                    }
3167                    return DROP_STROKE;
3168                }
3169            }
3170            return DISPATCH_TOUCH;
3171        }
3172
3173    DispatchVirtualKey:
3174        // Collect remaining state needed to dispatch virtual key.
3175        keyCode = mLocked.currentVirtualKey.keyCode;
3176        scanCode = mLocked.currentVirtualKey.scanCode;
3177        downTime = mLocked.currentVirtualKey.downTime;
3178    } // release lock
3179
3180    // Dispatch virtual key.
3181    int32_t metaState = mContext->getGlobalMetaState();
3182    policyFlags |= POLICY_FLAG_VIRTUAL;
3183    getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
3184            keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
3185    return touchResult;
3186}
3187
3188void TouchInputMapper::suppressSwipeOntoVirtualKeys(nsecs_t when) {
3189    // Disable all virtual key touches that happen within a short time interval of the
3190    // most recent touch.  The idea is to filter out stray virtual key presses when
3191    // interacting with the touch screen.
3192    //
3193    // Problems we're trying to solve:
3194    //
3195    // 1. While scrolling a list or dragging the window shade, the user swipes down into a
3196    //    virtual key area that is implemented by a separate touch panel and accidentally
3197    //    triggers a virtual key.
3198    //
3199    // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
3200    //    area and accidentally triggers a virtual key.  This often happens when virtual keys
3201    //    are layed out below the screen near to where the on screen keyboard's space bar
3202    //    is displayed.
3203    if (mConfig.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
3204        mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime);
3205    }
3206}
3207
3208void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
3209    uint32_t currentPointerCount = mCurrentTouch.pointerCount;
3210    uint32_t lastPointerCount = mLastTouch.pointerCount;
3211    if (currentPointerCount == 0 && lastPointerCount == 0) {
3212        return; // nothing to do!
3213    }
3214
3215    // Update current touch coordinates.
3216    int32_t edgeFlags;
3217    float xPrecision, yPrecision;
3218    prepareTouches(&edgeFlags, &xPrecision, &yPrecision);
3219
3220    // Dispatch motions.
3221    BitSet32 currentIdBits = mCurrentTouch.idBits;
3222    BitSet32 lastIdBits = mLastTouch.idBits;
3223    int32_t metaState = getContext()->getGlobalMetaState();
3224    int32_t buttonState = mCurrentTouch.buttonState;
3225
3226    if (currentIdBits == lastIdBits) {
3227        // No pointer id changes so this is a move event.
3228        // The dispatcher takes care of batching moves so we don't have to deal with that here.
3229        dispatchMotion(when, policyFlags, mTouchSource,
3230                AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState,
3231                AMOTION_EVENT_EDGE_FLAG_NONE,
3232                mCurrentTouchProperties, mCurrentTouchCoords,
3233                mCurrentTouch.idToIndex, currentIdBits, -1,
3234                xPrecision, yPrecision, mDownTime);
3235    } else {
3236        // There may be pointers going up and pointers going down and pointers moving
3237        // all at the same time.
3238        BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
3239        BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
3240        BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
3241        BitSet32 dispatchedIdBits(lastIdBits.value);
3242
3243        // Update last coordinates of pointers that have moved so that we observe the new
3244        // pointer positions at the same time as other pointers that have just gone up.
3245        bool moveNeeded = updateMovedPointers(
3246                mCurrentTouchProperties, mCurrentTouchCoords, mCurrentTouch.idToIndex,
3247                mLastTouchProperties, mLastTouchCoords, mLastTouch.idToIndex,
3248                moveIdBits);
3249        if (buttonState != mLastTouch.buttonState) {
3250            moveNeeded = true;
3251        }
3252
3253        // Dispatch pointer up events.
3254        while (!upIdBits.isEmpty()) {
3255            uint32_t upId = upIdBits.firstMarkedBit();
3256            upIdBits.clearBit(upId);
3257
3258            dispatchMotion(when, policyFlags, mTouchSource,
3259                    AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0,
3260                    mLastTouchProperties, mLastTouchCoords,
3261                    mLastTouch.idToIndex, dispatchedIdBits, upId,
3262                    xPrecision, yPrecision, mDownTime);
3263            dispatchedIdBits.clearBit(upId);
3264        }
3265
3266        // Dispatch move events if any of the remaining pointers moved from their old locations.
3267        // Although applications receive new locations as part of individual pointer up
3268        // events, they do not generally handle them except when presented in a move event.
3269        if (moveNeeded) {
3270            LOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
3271            dispatchMotion(when, policyFlags, mTouchSource,
3272                    AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0,
3273                    mCurrentTouchProperties, mCurrentTouchCoords,
3274                    mCurrentTouch.idToIndex, dispatchedIdBits, -1,
3275                    xPrecision, yPrecision, mDownTime);
3276        }
3277
3278        // Dispatch pointer down events using the new pointer locations.
3279        while (!downIdBits.isEmpty()) {
3280            uint32_t downId = downIdBits.firstMarkedBit();
3281            downIdBits.clearBit(downId);
3282            dispatchedIdBits.markBit(downId);
3283
3284            if (dispatchedIdBits.count() == 1) {
3285                // First pointer is going down.  Set down time.
3286                mDownTime = when;
3287            } else {
3288                // Only send edge flags with first pointer down.
3289                edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
3290            }
3291
3292            dispatchMotion(when, policyFlags, mTouchSource,
3293                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, edgeFlags,
3294                    mCurrentTouchProperties, mCurrentTouchCoords,
3295                    mCurrentTouch.idToIndex, dispatchedIdBits, downId,
3296                    xPrecision, yPrecision, mDownTime);
3297        }
3298    }
3299
3300    // Update state for next time.
3301    for (uint32_t i = 0; i < currentPointerCount; i++) {
3302        mLastTouchProperties[i].copyFrom(mCurrentTouchProperties[i]);
3303        mLastTouchCoords[i].copyFrom(mCurrentTouchCoords[i]);
3304    }
3305}
3306
3307void TouchInputMapper::prepareTouches(int32_t* outEdgeFlags,
3308        float* outXPrecision, float* outYPrecision) {
3309    uint32_t currentPointerCount = mCurrentTouch.pointerCount;
3310    uint32_t lastPointerCount = mLastTouch.pointerCount;
3311
3312    AutoMutex _l(mLock);
3313
3314    // Walk through the the active pointers and map touch screen coordinates (TouchData) into
3315    // display or surface coordinates (PointerCoords) and adjust for display orientation.
3316    for (uint32_t i = 0; i < currentPointerCount; i++) {
3317        const PointerData& in = mCurrentTouch.pointers[i];
3318
3319        // ToolMajor and ToolMinor
3320        float toolMajor, toolMinor;
3321        switch (mCalibration.toolSizeCalibration) {
3322        case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
3323            toolMajor = in.toolMajor * mLocked.geometricScale;
3324            if (mRawAxes.toolMinor.valid) {
3325                toolMinor = in.toolMinor * mLocked.geometricScale;
3326            } else {
3327                toolMinor = toolMajor;
3328            }
3329            break;
3330        case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
3331            toolMajor = in.toolMajor != 0
3332                    ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
3333                    : 0;
3334            if (mRawAxes.toolMinor.valid) {
3335                toolMinor = in.toolMinor != 0
3336                        ? in.toolMinor * mLocked.toolSizeLinearScale
3337                                + mLocked.toolSizeLinearBias
3338                        : 0;
3339            } else {
3340                toolMinor = toolMajor;
3341            }
3342            break;
3343        case Calibration::TOOL_SIZE_CALIBRATION_AREA:
3344            if (in.toolMajor != 0) {
3345                float diameter = sqrtf(in.toolMajor
3346                        * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
3347                toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
3348            } else {
3349                toolMajor = 0;
3350            }
3351            toolMinor = toolMajor;
3352            break;
3353        default:
3354            toolMajor = 0;
3355            toolMinor = 0;
3356            break;
3357        }
3358
3359        if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
3360            toolMajor /= currentPointerCount;
3361            toolMinor /= currentPointerCount;
3362        }
3363
3364        // Pressure
3365        float rawPressure;
3366        switch (mCalibration.pressureSource) {
3367        case Calibration::PRESSURE_SOURCE_PRESSURE:
3368            rawPressure = in.pressure;
3369            break;
3370        case Calibration::PRESSURE_SOURCE_TOUCH:
3371            rawPressure = in.touchMajor;
3372            break;
3373        default:
3374            rawPressure = 0;
3375        }
3376
3377        float pressure;
3378        switch (mCalibration.pressureCalibration) {
3379        case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
3380        case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
3381            pressure = rawPressure * mLocked.pressureScale;
3382            break;
3383        default:
3384            pressure = 1;
3385            break;
3386        }
3387
3388        // TouchMajor and TouchMinor
3389        float touchMajor, touchMinor;
3390        switch (mCalibration.touchSizeCalibration) {
3391        case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
3392            touchMajor = in.touchMajor * mLocked.geometricScale;
3393            if (mRawAxes.touchMinor.valid) {
3394                touchMinor = in.touchMinor * mLocked.geometricScale;
3395            } else {
3396                touchMinor = touchMajor;
3397            }
3398            break;
3399        case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
3400            touchMajor = toolMajor * pressure;
3401            touchMinor = toolMinor * pressure;
3402            break;
3403        default:
3404            touchMajor = 0;
3405            touchMinor = 0;
3406            break;
3407        }
3408
3409        if (touchMajor > toolMajor) {
3410            touchMajor = toolMajor;
3411        }
3412        if (touchMinor > toolMinor) {
3413            touchMinor = toolMinor;
3414        }
3415
3416        // Size
3417        float size;
3418        switch (mCalibration.sizeCalibration) {
3419        case Calibration::SIZE_CALIBRATION_NORMALIZED: {
3420            float rawSize = mRawAxes.toolMinor.valid
3421                    ? avg(in.toolMajor, in.toolMinor)
3422                    : in.toolMajor;
3423            size = rawSize * mLocked.sizeScale;
3424            break;
3425        }
3426        default:
3427            size = 0;
3428            break;
3429        }
3430
3431        // Orientation
3432        float orientation;
3433        switch (mCalibration.orientationCalibration) {
3434        case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
3435            orientation = in.orientation * mLocked.orientationScale;
3436            break;
3437        case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
3438            int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
3439            int32_t c2 = signExtendNybble(in.orientation & 0x0f);
3440            if (c1 != 0 || c2 != 0) {
3441                orientation = atan2f(c1, c2) * 0.5f;
3442                float scale = 1.0f + hypotf(c1, c2) / 16.0f;
3443                touchMajor *= scale;
3444                touchMinor /= scale;
3445                toolMajor *= scale;
3446                toolMinor /= scale;
3447            } else {
3448                orientation = 0;
3449            }
3450            break;
3451        }
3452        default:
3453            orientation = 0;
3454        }
3455
3456        // Distance
3457        float distance;
3458        switch (mCalibration.distanceCalibration) {
3459        case Calibration::DISTANCE_CALIBRATION_SCALED:
3460            distance = in.distance * mLocked.distanceScale;
3461            break;
3462        default:
3463            distance = 0;
3464        }
3465
3466        // X and Y
3467        // Adjust coords for surface orientation.
3468        float x, y;
3469        switch (mLocked.surfaceOrientation) {
3470        case DISPLAY_ORIENTATION_90:
3471            x = float(in.y - mRawAxes.y.minValue) * mLocked.yScale;
3472            y = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale;
3473            orientation -= M_PI_2;
3474            if (orientation < - M_PI_2) {
3475                orientation += M_PI;
3476            }
3477            break;
3478        case DISPLAY_ORIENTATION_180:
3479            x = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale;
3480            y = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale;
3481            break;
3482        case DISPLAY_ORIENTATION_270:
3483            x = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale;
3484            y = float(in.x - mRawAxes.x.minValue) * mLocked.xScale;
3485            orientation += M_PI_2;
3486            if (orientation > M_PI_2) {
3487                orientation -= M_PI;
3488            }
3489            break;
3490        default:
3491            x = float(in.x - mRawAxes.x.minValue) * mLocked.xScale;
3492            y = float(in.y - mRawAxes.y.minValue) * mLocked.yScale;
3493            break;
3494        }
3495
3496        // Write output coords.
3497        PointerCoords& out = mCurrentTouchCoords[i];
3498        out.clear();
3499        out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
3500        out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
3501        out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
3502        out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
3503        out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
3504        out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
3505        out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
3506        out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
3507        out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
3508        if (distance != 0) {
3509            out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
3510        }
3511
3512        // Write output properties.
3513        PointerProperties& properties = mCurrentTouchProperties[i];
3514        properties.clear();
3515        properties.id = mCurrentTouch.pointers[i].id;
3516        properties.toolType = getTouchToolType(mCurrentTouch.pointers[i].isStylus);
3517    }
3518
3519    // Check edge flags by looking only at the first pointer since the flags are
3520    // global to the event.
3521    *outEdgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
3522    if (lastPointerCount == 0 && currentPointerCount > 0) {
3523        const PointerData& in = mCurrentTouch.pointers[0];
3524
3525        if (in.x <= mRawAxes.x.minValue) {
3526            *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_LEFT,
3527                    mLocked.surfaceOrientation);
3528        } else if (in.x >= mRawAxes.x.maxValue) {
3529            *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_RIGHT,
3530                    mLocked.surfaceOrientation);
3531        }
3532        if (in.y <= mRawAxes.y.minValue) {
3533            *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_TOP,
3534                    mLocked.surfaceOrientation);
3535        } else if (in.y >= mRawAxes.y.maxValue) {
3536            *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_BOTTOM,
3537                    mLocked.surfaceOrientation);
3538        }
3539    }
3540
3541    *outXPrecision = mLocked.orientedXPrecision;
3542    *outYPrecision = mLocked.orientedYPrecision;
3543}
3544
3545void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
3546        bool isTimeout) {
3547    // Update current gesture coordinates.
3548    bool cancelPreviousGesture, finishPreviousGesture;
3549    bool sendEvents = preparePointerGestures(when,
3550            &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
3551    if (!sendEvents) {
3552        return;
3553    }
3554    if (finishPreviousGesture) {
3555        cancelPreviousGesture = false;
3556    }
3557
3558    // Update the pointer presentation and spots.
3559    if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3560        mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
3561        if (finishPreviousGesture || cancelPreviousGesture) {
3562            mPointerController->clearSpots();
3563        }
3564        mPointerController->setSpots(mPointerGesture.currentGestureCoords,
3565                mPointerGesture.currentGestureIdToIndex,
3566                mPointerGesture.currentGestureIdBits);
3567    } else {
3568        mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
3569    }
3570
3571    // Show or hide the pointer if needed.
3572    switch (mPointerGesture.currentGestureMode) {
3573    case PointerGesture::NEUTRAL:
3574    case PointerGesture::QUIET:
3575        if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
3576                && (mPointerGesture.lastGestureMode == PointerGesture::SWIPE
3577                        || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)) {
3578            // Remind the user of where the pointer is after finishing a gesture with spots.
3579            mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
3580        }
3581        break;
3582    case PointerGesture::TAP:
3583    case PointerGesture::TAP_DRAG:
3584    case PointerGesture::BUTTON_CLICK_OR_DRAG:
3585    case PointerGesture::HOVER:
3586    case PointerGesture::PRESS:
3587        // Unfade the pointer when the current gesture manipulates the
3588        // area directly under the pointer.
3589        mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
3590        break;
3591    case PointerGesture::SWIPE:
3592    case PointerGesture::FREEFORM:
3593        // Fade the pointer when the current gesture manipulates a different
3594        // area and there are spots to guide the user experience.
3595        if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3596            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
3597        } else {
3598            mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
3599        }
3600        break;
3601    }
3602
3603    // Send events!
3604    int32_t metaState = getContext()->getGlobalMetaState();
3605    int32_t buttonState = mCurrentTouch.buttonState;
3606
3607    // Update last coordinates of pointers that have moved so that we observe the new
3608    // pointer positions at the same time as other pointers that have just gone up.
3609    bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP
3610            || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG
3611            || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
3612            || mPointerGesture.currentGestureMode == PointerGesture::PRESS
3613            || mPointerGesture.currentGestureMode == PointerGesture::SWIPE
3614            || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
3615    bool moveNeeded = false;
3616    if (down && !cancelPreviousGesture && !finishPreviousGesture
3617            && !mPointerGesture.lastGestureIdBits.isEmpty()
3618            && !mPointerGesture.currentGestureIdBits.isEmpty()) {
3619        BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value
3620                & mPointerGesture.lastGestureIdBits.value);
3621        moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties,
3622                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3623                mPointerGesture.lastGestureProperties,
3624                mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
3625                movedGestureIdBits);
3626        if (buttonState != mLastTouch.buttonState) {
3627            moveNeeded = true;
3628        }
3629    }
3630
3631    // Send motion events for all pointers that went up or were canceled.
3632    BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
3633    if (!dispatchedGestureIdBits.isEmpty()) {
3634        if (cancelPreviousGesture) {
3635            dispatchMotion(when, policyFlags, mPointerSource,
3636                    AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
3637                    AMOTION_EVENT_EDGE_FLAG_NONE,
3638                    mPointerGesture.lastGestureProperties,
3639                    mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
3640                    dispatchedGestureIdBits, -1,
3641                    0, 0, mPointerGesture.downTime);
3642
3643            dispatchedGestureIdBits.clear();
3644        } else {
3645            BitSet32 upGestureIdBits;
3646            if (finishPreviousGesture) {
3647                upGestureIdBits = dispatchedGestureIdBits;
3648            } else {
3649                upGestureIdBits.value = dispatchedGestureIdBits.value
3650                        & ~mPointerGesture.currentGestureIdBits.value;
3651            }
3652            while (!upGestureIdBits.isEmpty()) {
3653                uint32_t id = upGestureIdBits.firstMarkedBit();
3654                upGestureIdBits.clearBit(id);
3655
3656                dispatchMotion(when, policyFlags, mPointerSource,
3657                        AMOTION_EVENT_ACTION_POINTER_UP, 0,
3658                        metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
3659                        mPointerGesture.lastGestureProperties,
3660                        mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
3661                        dispatchedGestureIdBits, id,
3662                        0, 0, mPointerGesture.downTime);
3663
3664                dispatchedGestureIdBits.clearBit(id);
3665            }
3666        }
3667    }
3668
3669    // Send motion events for all pointers that moved.
3670    if (moveNeeded) {
3671        dispatchMotion(when, policyFlags, mPointerSource,
3672                AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
3673                mPointerGesture.currentGestureProperties,
3674                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3675                dispatchedGestureIdBits, -1,
3676                0, 0, mPointerGesture.downTime);
3677    }
3678
3679    // Send motion events for all pointers that went down.
3680    if (down) {
3681        BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value
3682                & ~dispatchedGestureIdBits.value);
3683        while (!downGestureIdBits.isEmpty()) {
3684            uint32_t id = downGestureIdBits.firstMarkedBit();
3685            downGestureIdBits.clearBit(id);
3686            dispatchedGestureIdBits.markBit(id);
3687
3688            int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
3689            if (dispatchedGestureIdBits.count() == 1) {
3690                // First pointer is going down.  Calculate edge flags and set down time.
3691                uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
3692                const PointerCoords& downCoords = mPointerGesture.currentGestureCoords[index];
3693                edgeFlags = calculateEdgeFlagsUsingPointerBounds(mPointerController,
3694                        downCoords.getAxisValue(AMOTION_EVENT_AXIS_X),
3695                        downCoords.getAxisValue(AMOTION_EVENT_AXIS_Y));
3696                mPointerGesture.downTime = when;
3697            }
3698
3699            dispatchMotion(when, policyFlags, mPointerSource,
3700                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, edgeFlags,
3701                    mPointerGesture.currentGestureProperties,
3702                    mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3703                    dispatchedGestureIdBits, id,
3704                    0, 0, mPointerGesture.downTime);
3705        }
3706    }
3707
3708    // Send motion events for hover.
3709    if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
3710        dispatchMotion(when, policyFlags, mPointerSource,
3711                AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
3712                metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
3713                mPointerGesture.currentGestureProperties,
3714                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3715                mPointerGesture.currentGestureIdBits, -1,
3716                0, 0, mPointerGesture.downTime);
3717    } else if (dispatchedGestureIdBits.isEmpty()
3718            && !mPointerGesture.lastGestureIdBits.isEmpty()) {
3719        // Synthesize a hover move event after all pointers go up to indicate that
3720        // the pointer is hovering again even if the user is not currently touching
3721        // the touch pad.  This ensures that a view will receive a fresh hover enter
3722        // event after a tap.
3723        float x, y;
3724        mPointerController->getPosition(&x, &y);
3725
3726        PointerProperties pointerProperties;
3727        pointerProperties.clear();
3728        pointerProperties.id = 0;
3729        pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
3730
3731        PointerCoords pointerCoords;
3732        pointerCoords.clear();
3733        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
3734        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
3735
3736        getDispatcher()->notifyMotion(when, getDeviceId(), mPointerSource, policyFlags,
3737                AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
3738                metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
3739                1, &pointerProperties, &pointerCoords, 0, 0, mPointerGesture.downTime);
3740    }
3741
3742    // Update state.
3743    mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
3744    if (!down) {
3745        mPointerGesture.lastGestureIdBits.clear();
3746    } else {
3747        mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
3748        for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) {
3749            uint32_t id = idBits.firstMarkedBit();
3750            idBits.clearBit(id);
3751            uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
3752            mPointerGesture.lastGestureProperties[index].copyFrom(
3753                    mPointerGesture.currentGestureProperties[index]);
3754            mPointerGesture.lastGestureCoords[index].copyFrom(
3755                    mPointerGesture.currentGestureCoords[index]);
3756            mPointerGesture.lastGestureIdToIndex[id] = index;
3757        }
3758    }
3759}
3760
3761bool TouchInputMapper::preparePointerGestures(nsecs_t when,
3762        bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
3763    *outCancelPreviousGesture = false;
3764    *outFinishPreviousGesture = false;
3765
3766    AutoMutex _l(mLock);
3767
3768    // Handle TAP timeout.
3769    if (isTimeout) {
3770#if DEBUG_GESTURES
3771        LOGD("Gestures: Processing timeout");
3772#endif
3773
3774        if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
3775            if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
3776                // The tap/drag timeout has not yet expired.
3777                getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime
3778                        + mConfig.pointerGestureTapDragInterval);
3779            } else {
3780                // The tap is finished.
3781#if DEBUG_GESTURES
3782                LOGD("Gestures: TAP finished");
3783#endif
3784                *outFinishPreviousGesture = true;
3785
3786                mPointerGesture.activeGestureId = -1;
3787                mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
3788                mPointerGesture.currentGestureIdBits.clear();
3789
3790                mPointerGesture.pointerVelocityControl.reset();
3791                return true;
3792            }
3793        }
3794
3795        // We did not handle this timeout.
3796        return false;
3797    }
3798
3799    // Update the velocity tracker.
3800    {
3801        VelocityTracker::Position positions[MAX_POINTERS];
3802        uint32_t count = 0;
3803        for (BitSet32 idBits(mCurrentTouch.idBits); !idBits.isEmpty(); count++) {
3804            uint32_t id = idBits.firstMarkedBit();
3805            idBits.clearBit(id);
3806            uint32_t index = mCurrentTouch.idToIndex[id];
3807            positions[count].x = mCurrentTouch.pointers[index].x
3808                    * mLocked.pointerGestureXMovementScale;
3809            positions[count].y = mCurrentTouch.pointers[index].y
3810                    * mLocked.pointerGestureYMovementScale;
3811        }
3812        mPointerGesture.velocityTracker.addMovement(when, mCurrentTouch.idBits, positions);
3813    }
3814
3815    // Pick a new active touch id if needed.
3816    // Choose an arbitrary pointer that just went down, if there is one.
3817    // Otherwise choose an arbitrary remaining pointer.
3818    // This guarantees we always have an active touch id when there is at least one pointer.
3819    // We keep the same active touch id for as long as possible.
3820    bool activeTouchChanged = false;
3821    int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
3822    int32_t activeTouchId = lastActiveTouchId;
3823    if (activeTouchId < 0) {
3824        if (!mCurrentTouch.idBits.isEmpty()) {
3825            activeTouchChanged = true;
3826            activeTouchId = mPointerGesture.activeTouchId = mCurrentTouch.idBits.firstMarkedBit();
3827            mPointerGesture.firstTouchTime = when;
3828        }
3829    } else if (!mCurrentTouch.idBits.hasBit(activeTouchId)) {
3830        activeTouchChanged = true;
3831        if (!mCurrentTouch.idBits.isEmpty()) {
3832            activeTouchId = mPointerGesture.activeTouchId = mCurrentTouch.idBits.firstMarkedBit();
3833        } else {
3834            activeTouchId = mPointerGesture.activeTouchId = -1;
3835        }
3836    }
3837
3838    // Determine whether we are in quiet time.
3839    bool isQuietTime = false;
3840    if (activeTouchId < 0) {
3841        mPointerGesture.resetQuietTime();
3842    } else {
3843        isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval;
3844        if (!isQuietTime) {
3845            if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
3846                    || mPointerGesture.lastGestureMode == PointerGesture::SWIPE
3847                    || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)
3848                    && mCurrentTouch.pointerCount < 2) {
3849                // Enter quiet time when exiting swipe or freeform state.
3850                // This is to prevent accidentally entering the hover state and flinging the
3851                // pointer when finishing a swipe and there is still one pointer left onscreen.
3852                isQuietTime = true;
3853            } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
3854                    && mCurrentTouch.pointerCount >= 2
3855                    && !isPointerDown(mCurrentTouch.buttonState)) {
3856                // Enter quiet time when releasing the button and there are still two or more
3857                // fingers down.  This may indicate that one finger was used to press the button
3858                // but it has not gone up yet.
3859                isQuietTime = true;
3860            }
3861            if (isQuietTime) {
3862                mPointerGesture.quietTime = when;
3863            }
3864        }
3865    }
3866
3867    // Switch states based on button and pointer state.
3868    if (isQuietTime) {
3869        // Case 1: Quiet time. (QUIET)
3870#if DEBUG_GESTURES
3871        LOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime
3872                + mConfig.pointerGestureQuietInterval - when) * 0.000001f);
3873#endif
3874        if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
3875            *outFinishPreviousGesture = true;
3876        }
3877
3878        mPointerGesture.activeGestureId = -1;
3879        mPointerGesture.currentGestureMode = PointerGesture::QUIET;
3880        mPointerGesture.currentGestureIdBits.clear();
3881
3882        mPointerGesture.pointerVelocityControl.reset();
3883    } else if (isPointerDown(mCurrentTouch.buttonState)) {
3884        // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
3885        // The pointer follows the active touch point.
3886        // Emit DOWN, MOVE, UP events at the pointer location.
3887        //
3888        // Only the active touch matters; other fingers are ignored.  This policy helps
3889        // to handle the case where the user places a second finger on the touch pad
3890        // to apply the necessary force to depress an integrated button below the surface.
3891        // We don't want the second finger to be delivered to applications.
3892        //
3893        // For this to work well, we need to make sure to track the pointer that is really
3894        // active.  If the user first puts one finger down to click then adds another
3895        // finger to drag then the active pointer should switch to the finger that is
3896        // being dragged.
3897#if DEBUG_GESTURES
3898        LOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
3899                "currentTouchPointerCount=%d", activeTouchId, mCurrentTouch.pointerCount);
3900#endif
3901        // Reset state when just starting.
3902        if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
3903            *outFinishPreviousGesture = true;
3904            mPointerGesture.activeGestureId = 0;
3905        }
3906
3907        // Switch pointers if needed.
3908        // Find the fastest pointer and follow it.
3909        if (activeTouchId >= 0 && mCurrentTouch.pointerCount > 1) {
3910            int32_t bestId = -1;
3911            float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
3912            for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
3913                uint32_t id = mCurrentTouch.pointers[i].id;
3914                float vx, vy;
3915                if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
3916                    float speed = hypotf(vx, vy);
3917                    if (speed > bestSpeed) {
3918                        bestId = id;
3919                        bestSpeed = speed;
3920                    }
3921                }
3922            }
3923            if (bestId >= 0 && bestId != activeTouchId) {
3924                mPointerGesture.activeTouchId = activeTouchId = bestId;
3925                activeTouchChanged = true;
3926#if DEBUG_GESTURES
3927                LOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
3928                        "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
3929#endif
3930            }
3931        }
3932
3933        if (activeTouchId >= 0 && mLastTouch.idBits.hasBit(activeTouchId)) {
3934            const PointerData& currentPointer =
3935                    mCurrentTouch.pointers[mCurrentTouch.idToIndex[activeTouchId]];
3936            const PointerData& lastPointer =
3937                    mLastTouch.pointers[mLastTouch.idToIndex[activeTouchId]];
3938            float deltaX = (currentPointer.x - lastPointer.x)
3939                    * mLocked.pointerGestureXMovementScale;
3940            float deltaY = (currentPointer.y - lastPointer.y)
3941                    * mLocked.pointerGestureYMovementScale;
3942
3943            mPointerGesture.pointerVelocityControl.move(when, &deltaX, &deltaY);
3944
3945            // Move the pointer using a relative motion.
3946            // When using spots, the click will occur at the position of the anchor
3947            // spot and all other spots will move there.
3948            mPointerController->move(deltaX, deltaY);
3949        } else {
3950            mPointerGesture.pointerVelocityControl.reset();
3951        }
3952
3953        float x, y;
3954        mPointerController->getPosition(&x, &y);
3955
3956        mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
3957        mPointerGesture.currentGestureIdBits.clear();
3958        mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
3959        mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
3960        mPointerGesture.currentGestureProperties[0].clear();
3961        mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
3962        mPointerGesture.currentGestureProperties[0].toolType =
3963                AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
3964        mPointerGesture.currentGestureCoords[0].clear();
3965        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
3966        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
3967        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
3968    } else if (mCurrentTouch.pointerCount == 0) {
3969        // Case 3. No fingers down and button is not pressed. (NEUTRAL)
3970        if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
3971            *outFinishPreviousGesture = true;
3972        }
3973
3974        // Watch for taps coming out of HOVER or TAP_DRAG mode.
3975        // Checking for taps after TAP_DRAG allows us to detect double-taps.
3976        bool tapped = false;
3977        if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
3978                || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
3979                && mLastTouch.pointerCount == 1) {
3980            if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
3981                float x, y;
3982                mPointerController->getPosition(&x, &y);
3983                if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
3984                        && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
3985#if DEBUG_GESTURES
3986                    LOGD("Gestures: TAP");
3987#endif
3988
3989                    mPointerGesture.tapUpTime = when;
3990                    getContext()->requestTimeoutAtTime(when
3991                            + mConfig.pointerGestureTapDragInterval);
3992
3993                    mPointerGesture.activeGestureId = 0;
3994                    mPointerGesture.currentGestureMode = PointerGesture::TAP;
3995                    mPointerGesture.currentGestureIdBits.clear();
3996                    mPointerGesture.currentGestureIdBits.markBit(
3997                            mPointerGesture.activeGestureId);
3998                    mPointerGesture.currentGestureIdToIndex[
3999                            mPointerGesture.activeGestureId] = 0;
4000                    mPointerGesture.currentGestureProperties[0].clear();
4001                    mPointerGesture.currentGestureProperties[0].id =
4002                            mPointerGesture.activeGestureId;
4003                    mPointerGesture.currentGestureProperties[0].toolType =
4004                            AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
4005                    mPointerGesture.currentGestureCoords[0].clear();
4006                    mPointerGesture.currentGestureCoords[0].setAxisValue(
4007                            AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
4008                    mPointerGesture.currentGestureCoords[0].setAxisValue(
4009                            AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY);
4010                    mPointerGesture.currentGestureCoords[0].setAxisValue(
4011                            AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4012
4013                    tapped = true;
4014                } else {
4015#if DEBUG_GESTURES
4016                    LOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f",
4017                            x - mPointerGesture.tapX,
4018                            y - mPointerGesture.tapY);
4019#endif
4020                }
4021            } else {
4022#if DEBUG_GESTURES
4023                LOGD("Gestures: Not a TAP, %0.3fms since down",
4024                        (when - mPointerGesture.tapDownTime) * 0.000001f);
4025#endif
4026            }
4027        }
4028
4029        mPointerGesture.pointerVelocityControl.reset();
4030
4031        if (!tapped) {
4032#if DEBUG_GESTURES
4033            LOGD("Gestures: NEUTRAL");
4034#endif
4035            mPointerGesture.activeGestureId = -1;
4036            mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
4037            mPointerGesture.currentGestureIdBits.clear();
4038        }
4039    } else if (mCurrentTouch.pointerCount == 1) {
4040        // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
4041        // The pointer follows the active touch point.
4042        // When in HOVER, emit HOVER_MOVE events at the pointer location.
4043        // When in TAP_DRAG, emit MOVE events at the pointer location.
4044        LOG_ASSERT(activeTouchId >= 0);
4045
4046        mPointerGesture.currentGestureMode = PointerGesture::HOVER;
4047        if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
4048            if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
4049                float x, y;
4050                mPointerController->getPosition(&x, &y);
4051                if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
4052                        && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
4053                    mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
4054                } else {
4055#if DEBUG_GESTURES
4056                    LOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
4057                            x - mPointerGesture.tapX,
4058                            y - mPointerGesture.tapY);
4059#endif
4060                }
4061            } else {
4062#if DEBUG_GESTURES
4063                LOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
4064                        (when - mPointerGesture.tapUpTime) * 0.000001f);
4065#endif
4066            }
4067        } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
4068            mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
4069        }
4070
4071        if (mLastTouch.idBits.hasBit(activeTouchId)) {
4072            const PointerData& currentPointer =
4073                    mCurrentTouch.pointers[mCurrentTouch.idToIndex[activeTouchId]];
4074            const PointerData& lastPointer =
4075                    mLastTouch.pointers[mLastTouch.idToIndex[activeTouchId]];
4076            float deltaX = (currentPointer.x - lastPointer.x)
4077                    * mLocked.pointerGestureXMovementScale;
4078            float deltaY = (currentPointer.y - lastPointer.y)
4079                    * mLocked.pointerGestureYMovementScale;
4080
4081            mPointerGesture.pointerVelocityControl.move(when, &deltaX, &deltaY);
4082
4083            // Move the pointer using a relative motion.
4084            // When using spots, the hover or drag will occur at the position of the anchor spot.
4085            mPointerController->move(deltaX, deltaY);
4086        } else {
4087            mPointerGesture.pointerVelocityControl.reset();
4088        }
4089
4090        bool down;
4091        if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
4092#if DEBUG_GESTURES
4093            LOGD("Gestures: TAP_DRAG");
4094#endif
4095            down = true;
4096        } else {
4097#if DEBUG_GESTURES
4098            LOGD("Gestures: HOVER");
4099#endif
4100            if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
4101                *outFinishPreviousGesture = true;
4102            }
4103            mPointerGesture.activeGestureId = 0;
4104            down = false;
4105        }
4106
4107        float x, y;
4108        mPointerController->getPosition(&x, &y);
4109
4110        mPointerGesture.currentGestureIdBits.clear();
4111        mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4112        mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
4113        mPointerGesture.currentGestureProperties[0].clear();
4114        mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
4115        mPointerGesture.currentGestureProperties[0].toolType =
4116                AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
4117        mPointerGesture.currentGestureCoords[0].clear();
4118        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
4119        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
4120        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
4121                down ? 1.0f : 0.0f);
4122
4123        if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
4124            mPointerGesture.resetTap();
4125            mPointerGesture.tapDownTime = when;
4126            mPointerGesture.tapX = x;
4127            mPointerGesture.tapY = y;
4128        }
4129    } else {
4130        // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
4131        // We need to provide feedback for each finger that goes down so we cannot wait
4132        // for the fingers to move before deciding what to do.
4133        //
4134        // The ambiguous case is deciding what to do when there are two fingers down but they
4135        // have not moved enough to determine whether they are part of a drag or part of a
4136        // freeform gesture, or just a press or long-press at the pointer location.
4137        //
4138        // When there are two fingers we start with the PRESS hypothesis and we generate a
4139        // down at the pointer location.
4140        //
4141        // When the two fingers move enough or when additional fingers are added, we make
4142        // a decision to transition into SWIPE or FREEFORM mode accordingly.
4143        LOG_ASSERT(activeTouchId >= 0);
4144
4145        bool settled = when >= mPointerGesture.firstTouchTime
4146                + mConfig.pointerGestureMultitouchSettleInterval;
4147        if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
4148                && mPointerGesture.lastGestureMode != PointerGesture::SWIPE
4149                && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
4150            *outFinishPreviousGesture = true;
4151        } else if (!settled && mCurrentTouch.pointerCount > mLastTouch.pointerCount) {
4152            // Additional pointers have gone down but not yet settled.
4153            // Reset the gesture.
4154#if DEBUG_GESTURES
4155            LOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
4156                    "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
4157                            + mConfig.pointerGestureMultitouchSettleInterval - when)
4158                            * 0.000001f);
4159#endif
4160            *outCancelPreviousGesture = true;
4161        } else {
4162            // Continue previous gesture.
4163            mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
4164        }
4165
4166        if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
4167            mPointerGesture.currentGestureMode = PointerGesture::PRESS;
4168            mPointerGesture.activeGestureId = 0;
4169            mPointerGesture.referenceIdBits.clear();
4170            mPointerGesture.pointerVelocityControl.reset();
4171
4172            // Use the centroid and pointer location as the reference points for the gesture.
4173#if DEBUG_GESTURES
4174            LOGD("Gestures: Using centroid as reference for MULTITOUCH, "
4175                    "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
4176                            + mConfig.pointerGestureMultitouchSettleInterval - when)
4177                            * 0.000001f);
4178#endif
4179            mCurrentTouch.getCentroid(&mPointerGesture.referenceTouchX,
4180                    &mPointerGesture.referenceTouchY);
4181            mPointerController->getPosition(&mPointerGesture.referenceGestureX,
4182                    &mPointerGesture.referenceGestureY);
4183        }
4184
4185        // Clear the reference deltas for fingers not yet included in the reference calculation.
4186        for (BitSet32 idBits(mCurrentTouch.idBits.value & ~mPointerGesture.referenceIdBits.value);
4187                !idBits.isEmpty(); ) {
4188            uint32_t id = idBits.firstMarkedBit();
4189            idBits.clearBit(id);
4190
4191            mPointerGesture.referenceDeltas[id].dx = 0;
4192            mPointerGesture.referenceDeltas[id].dy = 0;
4193        }
4194        mPointerGesture.referenceIdBits = mCurrentTouch.idBits;
4195
4196        // Add delta for all fingers and calculate a common movement delta.
4197        float commonDeltaX = 0, commonDeltaY = 0;
4198        BitSet32 commonIdBits(mLastTouch.idBits.value & mCurrentTouch.idBits.value);
4199        for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
4200            bool first = (idBits == commonIdBits);
4201            uint32_t id = idBits.firstMarkedBit();
4202            idBits.clearBit(id);
4203
4204            const PointerData& cpd = mCurrentTouch.pointers[mCurrentTouch.idToIndex[id]];
4205            const PointerData& lpd = mLastTouch.pointers[mLastTouch.idToIndex[id]];
4206            PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
4207            delta.dx += cpd.x - lpd.x;
4208            delta.dy += cpd.y - lpd.y;
4209
4210            if (first) {
4211                commonDeltaX = delta.dx;
4212                commonDeltaY = delta.dy;
4213            } else {
4214                commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
4215                commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
4216            }
4217        }
4218
4219        // Consider transitions from PRESS to SWIPE or MULTITOUCH.
4220        if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
4221            float dist[MAX_POINTER_ID + 1];
4222            int32_t distOverThreshold = 0;
4223            for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
4224                uint32_t id = idBits.firstMarkedBit();
4225                idBits.clearBit(id);
4226
4227                PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
4228                dist[id] = hypotf(delta.dx * mLocked.pointerGestureXZoomScale,
4229                        delta.dy * mLocked.pointerGestureYZoomScale);
4230                if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) {
4231                    distOverThreshold += 1;
4232                }
4233            }
4234
4235            // Only transition when at least two pointers have moved further than
4236            // the minimum distance threshold.
4237            if (distOverThreshold >= 2) {
4238                float d;
4239                if (mCurrentTouch.pointerCount > 2) {
4240                    // There are more than two pointers, switch to FREEFORM.
4241#if DEBUG_GESTURES
4242                    LOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
4243                            mCurrentTouch.pointerCount);
4244#endif
4245                    *outCancelPreviousGesture = true;
4246                    mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
4247                } else if (((d = distance(
4248                        mCurrentTouch.pointers[0].x, mCurrentTouch.pointers[0].y,
4249                        mCurrentTouch.pointers[1].x, mCurrentTouch.pointers[1].y))
4250                                > mLocked.pointerGestureMaxSwipeWidth)) {
4251                    // There are two pointers but they are too far apart for a SWIPE,
4252                    // switch to FREEFORM.
4253#if DEBUG_GESTURES
4254                    LOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
4255                            d, mLocked.pointerGestureMaxSwipeWidth);
4256#endif
4257                    *outCancelPreviousGesture = true;
4258                    mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
4259                } else {
4260                    // There are two pointers.  Wait for both pointers to start moving
4261                    // before deciding whether this is a SWIPE or FREEFORM gesture.
4262                    uint32_t id1 = mCurrentTouch.pointers[0].id;
4263                    uint32_t id2 = mCurrentTouch.pointers[1].id;
4264                    float dist1 = dist[id1];
4265                    float dist2 = dist[id2];
4266                    if (dist1 >= mConfig.pointerGestureMultitouchMinDistance
4267                            && dist2 >= mConfig.pointerGestureMultitouchMinDistance) {
4268                        // Calculate the dot product of the displacement vectors.
4269                        // When the vectors are oriented in approximately the same direction,
4270                        // the angle betweeen them is near zero and the cosine of the angle
4271                        // approches 1.0.  Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
4272                        PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
4273                        PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
4274                        float dx1 = delta1.dx * mLocked.pointerGestureXZoomScale;
4275                        float dy1 = delta1.dy * mLocked.pointerGestureYZoomScale;
4276                        float dx2 = delta2.dx * mLocked.pointerGestureXZoomScale;
4277                        float dy2 = delta2.dy * mLocked.pointerGestureYZoomScale;
4278                        float dot = dx1 * dx2 + dy1 * dy2;
4279                        float cosine = dot / (dist1 * dist2); // denominator always > 0
4280                        if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
4281                            // Pointers are moving in the same direction.  Switch to SWIPE.
4282#if DEBUG_GESTURES
4283                            LOGD("Gestures: PRESS transitioned to SWIPE, "
4284                                    "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
4285                                    "cosine %0.3f >= %0.3f",
4286                                    dist1, mConfig.pointerGestureMultitouchMinDistance,
4287                                    dist2, mConfig.pointerGestureMultitouchMinDistance,
4288                                    cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
4289#endif
4290                            mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
4291                        } else {
4292                            // Pointers are moving in different directions.  Switch to FREEFORM.
4293#if DEBUG_GESTURES
4294                            LOGD("Gestures: PRESS transitioned to FREEFORM, "
4295                                    "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
4296                                    "cosine %0.3f < %0.3f",
4297                                    dist1, mConfig.pointerGestureMultitouchMinDistance,
4298                                    dist2, mConfig.pointerGestureMultitouchMinDistance,
4299                                    cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
4300#endif
4301                            *outCancelPreviousGesture = true;
4302                            mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
4303                        }
4304                    }
4305                }
4306            }
4307        } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
4308            // Switch from SWIPE to FREEFORM if additional pointers go down.
4309            // Cancel previous gesture.
4310            if (mCurrentTouch.pointerCount > 2) {
4311#if DEBUG_GESTURES
4312                LOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
4313                        mCurrentTouch.pointerCount);
4314#endif
4315                *outCancelPreviousGesture = true;
4316                mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
4317            }
4318        }
4319
4320        // Move the reference points based on the overall group motion of the fingers
4321        // except in PRESS mode while waiting for a transition to occur.
4322        if (mPointerGesture.currentGestureMode != PointerGesture::PRESS
4323                && (commonDeltaX || commonDeltaY)) {
4324            for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
4325                uint32_t id = idBits.firstMarkedBit();
4326                idBits.clearBit(id);
4327
4328                PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
4329                delta.dx = 0;
4330                delta.dy = 0;
4331            }
4332
4333            mPointerGesture.referenceTouchX += commonDeltaX;
4334            mPointerGesture.referenceTouchY += commonDeltaY;
4335
4336            commonDeltaX *= mLocked.pointerGestureXMovementScale;
4337            commonDeltaY *= mLocked.pointerGestureYMovementScale;
4338            mPointerGesture.pointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
4339
4340            mPointerGesture.referenceGestureX += commonDeltaX;
4341            mPointerGesture.referenceGestureY += commonDeltaY;
4342        }
4343
4344        // Report gestures.
4345        if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
4346            // PRESS mode.
4347#if DEBUG_GESTURES
4348            LOGD("Gestures: PRESS activeTouchId=%d,"
4349                    "activeGestureId=%d, currentTouchPointerCount=%d",
4350                    activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount);
4351#endif
4352            LOG_ASSERT(mPointerGesture.activeGestureId >= 0);
4353
4354            mPointerGesture.currentGestureIdBits.clear();
4355            mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4356            mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
4357            mPointerGesture.currentGestureProperties[0].clear();
4358            mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
4359            mPointerGesture.currentGestureProperties[0].toolType =
4360                    AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
4361            mPointerGesture.currentGestureCoords[0].clear();
4362            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
4363                    mPointerGesture.referenceGestureX);
4364            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
4365                    mPointerGesture.referenceGestureY);
4366            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4367        } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
4368            // SWIPE mode.
4369#if DEBUG_GESTURES
4370            LOGD("Gestures: SWIPE activeTouchId=%d,"
4371                    "activeGestureId=%d, currentTouchPointerCount=%d",
4372                    activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount);
4373#endif
4374            LOG_ASSERT(mPointerGesture.activeGestureId >= 0);
4375
4376            mPointerGesture.currentGestureIdBits.clear();
4377            mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4378            mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
4379            mPointerGesture.currentGestureProperties[0].clear();
4380            mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
4381            mPointerGesture.currentGestureProperties[0].toolType =
4382                    AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
4383            mPointerGesture.currentGestureCoords[0].clear();
4384            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
4385                    mPointerGesture.referenceGestureX);
4386            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
4387                    mPointerGesture.referenceGestureY);
4388            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4389        } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
4390            // FREEFORM mode.
4391#if DEBUG_GESTURES
4392            LOGD("Gestures: FREEFORM activeTouchId=%d,"
4393                    "activeGestureId=%d, currentTouchPointerCount=%d",
4394                    activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount);
4395#endif
4396            LOG_ASSERT(mPointerGesture.activeGestureId >= 0);
4397
4398            mPointerGesture.currentGestureIdBits.clear();
4399
4400            BitSet32 mappedTouchIdBits;
4401            BitSet32 usedGestureIdBits;
4402            if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
4403                // Initially, assign the active gesture id to the active touch point
4404                // if there is one.  No other touch id bits are mapped yet.
4405                if (!*outCancelPreviousGesture) {
4406                    mappedTouchIdBits.markBit(activeTouchId);
4407                    usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
4408                    mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
4409                            mPointerGesture.activeGestureId;
4410                } else {
4411                    mPointerGesture.activeGestureId = -1;
4412                }
4413            } else {
4414                // Otherwise, assume we mapped all touches from the previous frame.
4415                // Reuse all mappings that are still applicable.
4416                mappedTouchIdBits.value = mLastTouch.idBits.value & mCurrentTouch.idBits.value;
4417                usedGestureIdBits = mPointerGesture.lastGestureIdBits;
4418
4419                // Check whether we need to choose a new active gesture id because the
4420                // current went went up.
4421                for (BitSet32 upTouchIdBits(mLastTouch.idBits.value & ~mCurrentTouch.idBits.value);
4422                        !upTouchIdBits.isEmpty(); ) {
4423                    uint32_t upTouchId = upTouchIdBits.firstMarkedBit();
4424                    upTouchIdBits.clearBit(upTouchId);
4425                    uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
4426                    if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
4427                        mPointerGesture.activeGestureId = -1;
4428                        break;
4429                    }
4430                }
4431            }
4432
4433#if DEBUG_GESTURES
4434            LOGD("Gestures: FREEFORM follow up "
4435                    "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
4436                    "activeGestureId=%d",
4437                    mappedTouchIdBits.value, usedGestureIdBits.value,
4438                    mPointerGesture.activeGestureId);
4439#endif
4440
4441            for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
4442                uint32_t touchId = mCurrentTouch.pointers[i].id;
4443                uint32_t gestureId;
4444                if (!mappedTouchIdBits.hasBit(touchId)) {
4445                    gestureId = usedGestureIdBits.firstUnmarkedBit();
4446                    usedGestureIdBits.markBit(gestureId);
4447                    mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
4448#if DEBUG_GESTURES
4449                    LOGD("Gestures: FREEFORM "
4450                            "new mapping for touch id %d -> gesture id %d",
4451                            touchId, gestureId);
4452#endif
4453                } else {
4454                    gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
4455#if DEBUG_GESTURES
4456                    LOGD("Gestures: FREEFORM "
4457                            "existing mapping for touch id %d -> gesture id %d",
4458                            touchId, gestureId);
4459#endif
4460                }
4461                mPointerGesture.currentGestureIdBits.markBit(gestureId);
4462                mPointerGesture.currentGestureIdToIndex[gestureId] = i;
4463
4464                float x = (mCurrentTouch.pointers[i].x - mPointerGesture.referenceTouchX)
4465                        * mLocked.pointerGestureXZoomScale + mPointerGesture.referenceGestureX;
4466                float y = (mCurrentTouch.pointers[i].y - mPointerGesture.referenceTouchY)
4467                        * mLocked.pointerGestureYZoomScale + mPointerGesture.referenceGestureY;
4468
4469                mPointerGesture.currentGestureProperties[i].clear();
4470                mPointerGesture.currentGestureProperties[i].id = gestureId;
4471                mPointerGesture.currentGestureProperties[i].toolType =
4472                        AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
4473                mPointerGesture.currentGestureCoords[i].clear();
4474                mPointerGesture.currentGestureCoords[i].setAxisValue(
4475                        AMOTION_EVENT_AXIS_X, x);
4476                mPointerGesture.currentGestureCoords[i].setAxisValue(
4477                        AMOTION_EVENT_AXIS_Y, y);
4478                mPointerGesture.currentGestureCoords[i].setAxisValue(
4479                        AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4480            }
4481
4482            if (mPointerGesture.activeGestureId < 0) {
4483                mPointerGesture.activeGestureId =
4484                        mPointerGesture.currentGestureIdBits.firstMarkedBit();
4485#if DEBUG_GESTURES
4486                LOGD("Gestures: FREEFORM new "
4487                        "activeGestureId=%d", mPointerGesture.activeGestureId);
4488#endif
4489            }
4490        }
4491    }
4492
4493    mPointerController->setButtonState(mCurrentTouch.buttonState);
4494
4495#if DEBUG_GESTURES
4496    LOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
4497            "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
4498            "lastGestureMode=%d, lastGestureIdBits=0x%08x",
4499            toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
4500            mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
4501            mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
4502    for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) {
4503        uint32_t id = idBits.firstMarkedBit();
4504        idBits.clearBit(id);
4505        uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
4506        const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
4507        const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
4508        LOGD("  currentGesture[%d]: index=%d, toolType=%d, "
4509                "x=%0.3f, y=%0.3f, pressure=%0.3f",
4510                id, index, properties.toolType,
4511                coords.getAxisValue(AMOTION_EVENT_AXIS_X),
4512                coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
4513                coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
4514    }
4515    for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) {
4516        uint32_t id = idBits.firstMarkedBit();
4517        idBits.clearBit(id);
4518        uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
4519        const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
4520        const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
4521        LOGD("  lastGesture[%d]: index=%d, toolType=%d, "
4522                "x=%0.3f, y=%0.3f, pressure=%0.3f",
4523                id, index, properties.toolType,
4524                coords.getAxisValue(AMOTION_EVENT_AXIS_X),
4525                coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
4526                coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
4527    }
4528#endif
4529    return true;
4530}
4531
4532void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
4533        int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
4534        const PointerProperties* properties, const PointerCoords* coords,
4535        const uint32_t* idToIndex, BitSet32 idBits,
4536        int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {
4537    PointerCoords pointerCoords[MAX_POINTERS];
4538    PointerProperties pointerProperties[MAX_POINTERS];
4539    uint32_t pointerCount = 0;
4540    while (!idBits.isEmpty()) {
4541        uint32_t id = idBits.firstMarkedBit();
4542        idBits.clearBit(id);
4543        uint32_t index = idToIndex[id];
4544        pointerProperties[pointerCount].copyFrom(properties[index]);
4545        pointerCoords[pointerCount].copyFrom(coords[index]);
4546
4547        if (changedId >= 0 && id == uint32_t(changedId)) {
4548            action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
4549        }
4550
4551        pointerCount += 1;
4552    }
4553
4554    LOG_ASSERT(pointerCount != 0);
4555
4556    if (changedId >= 0 && pointerCount == 1) {
4557        // Replace initial down and final up action.
4558        // We can compare the action without masking off the changed pointer index
4559        // because we know the index is 0.
4560        if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
4561            action = AMOTION_EVENT_ACTION_DOWN;
4562        } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
4563            action = AMOTION_EVENT_ACTION_UP;
4564        } else {
4565            // Can't happen.
4566            LOG_ASSERT(false);
4567        }
4568    }
4569
4570    getDispatcher()->notifyMotion(when, getDeviceId(), source, policyFlags,
4571            action, flags, metaState, buttonState, edgeFlags,
4572            pointerCount, pointerProperties, pointerCoords, xPrecision, yPrecision, downTime);
4573}
4574
4575bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties,
4576        const PointerCoords* inCoords, const uint32_t* inIdToIndex,
4577        PointerProperties* outProperties, PointerCoords* outCoords, const uint32_t* outIdToIndex,
4578        BitSet32 idBits) const {
4579    bool changed = false;
4580    while (!idBits.isEmpty()) {
4581        uint32_t id = idBits.firstMarkedBit();
4582        idBits.clearBit(id);
4583
4584        uint32_t inIndex = inIdToIndex[id];
4585        uint32_t outIndex = outIdToIndex[id];
4586
4587        const PointerProperties& curInProperties = inProperties[inIndex];
4588        const PointerCoords& curInCoords = inCoords[inIndex];
4589        PointerProperties& curOutProperties = outProperties[outIndex];
4590        PointerCoords& curOutCoords = outCoords[outIndex];
4591
4592        if (curInProperties != curOutProperties) {
4593            curOutProperties.copyFrom(curInProperties);
4594            changed = true;
4595        }
4596
4597        if (curInCoords != curOutCoords) {
4598            curOutCoords.copyFrom(curInCoords);
4599            changed = true;
4600        }
4601    }
4602    return changed;
4603}
4604
4605void TouchInputMapper::fadePointer() {
4606    { // acquire lock
4607        AutoMutex _l(mLock);
4608        if (mPointerController != NULL) {
4609            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
4610        }
4611    } // release lock
4612}
4613
4614int32_t TouchInputMapper::getTouchToolType(bool isStylus) const {
4615    if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
4616        return isStylus ? AMOTION_EVENT_TOOL_TYPE_STYLUS : AMOTION_EVENT_TOOL_TYPE_FINGER;
4617    } else {
4618        return isStylus ? AMOTION_EVENT_TOOL_TYPE_INDIRECT_STYLUS
4619                : AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
4620    }
4621}
4622
4623bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
4624    return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
4625            && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
4626}
4627
4628const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
4629        int32_t x, int32_t y) {
4630    size_t numVirtualKeys = mLocked.virtualKeys.size();
4631    for (size_t i = 0; i < numVirtualKeys; i++) {
4632        const VirtualKey& virtualKey = mLocked.virtualKeys[i];
4633
4634#if DEBUG_VIRTUAL_KEYS
4635        LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
4636                "left=%d, top=%d, right=%d, bottom=%d",
4637                x, y,
4638                virtualKey.keyCode, virtualKey.scanCode,
4639                virtualKey.hitLeft, virtualKey.hitTop,
4640                virtualKey.hitRight, virtualKey.hitBottom);
4641#endif
4642
4643        if (virtualKey.isHit(x, y)) {
4644            return & virtualKey;
4645        }
4646    }
4647
4648    return NULL;
4649}
4650
4651void TouchInputMapper::calculatePointerIds() {
4652    uint32_t currentPointerCount = mCurrentTouch.pointerCount;
4653    uint32_t lastPointerCount = mLastTouch.pointerCount;
4654
4655    if (currentPointerCount == 0) {
4656        // No pointers to assign.
4657        mCurrentTouch.idBits.clear();
4658    } else if (lastPointerCount == 0) {
4659        // All pointers are new.
4660        mCurrentTouch.idBits.clear();
4661        for (uint32_t i = 0; i < currentPointerCount; i++) {
4662            mCurrentTouch.pointers[i].id = i;
4663            mCurrentTouch.idToIndex[i] = i;
4664            mCurrentTouch.idBits.markBit(i);
4665        }
4666    } else if (currentPointerCount == 1 && lastPointerCount == 1) {
4667        // Only one pointer and no change in count so it must have the same id as before.
4668        uint32_t id = mLastTouch.pointers[0].id;
4669        mCurrentTouch.pointers[0].id = id;
4670        mCurrentTouch.idToIndex[id] = 0;
4671        mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
4672    } else {
4673        // General case.
4674        // We build a heap of squared euclidean distances between current and last pointers
4675        // associated with the current and last pointer indices.  Then, we find the best
4676        // match (by distance) for each current pointer.
4677        PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
4678
4679        uint32_t heapSize = 0;
4680        for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
4681                currentPointerIndex++) {
4682            for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
4683                    lastPointerIndex++) {
4684                int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
4685                        - mLastTouch.pointers[lastPointerIndex].x;
4686                int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
4687                        - mLastTouch.pointers[lastPointerIndex].y;
4688
4689                uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
4690
4691                // Insert new element into the heap (sift up).
4692                heap[heapSize].currentPointerIndex = currentPointerIndex;
4693                heap[heapSize].lastPointerIndex = lastPointerIndex;
4694                heap[heapSize].distance = distance;
4695                heapSize += 1;
4696            }
4697        }
4698
4699        // Heapify
4700        for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
4701            startIndex -= 1;
4702            for (uint32_t parentIndex = startIndex; ;) {
4703                uint32_t childIndex = parentIndex * 2 + 1;
4704                if (childIndex >= heapSize) {
4705                    break;
4706                }
4707
4708                if (childIndex + 1 < heapSize
4709                        && heap[childIndex + 1].distance < heap[childIndex].distance) {
4710                    childIndex += 1;
4711                }
4712
4713                if (heap[parentIndex].distance <= heap[childIndex].distance) {
4714                    break;
4715                }
4716
4717                swap(heap[parentIndex], heap[childIndex]);
4718                parentIndex = childIndex;
4719            }
4720        }
4721
4722#if DEBUG_POINTER_ASSIGNMENT
4723        LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
4724        for (size_t i = 0; i < heapSize; i++) {
4725            LOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
4726                    i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
4727                    heap[i].distance);
4728        }
4729#endif
4730
4731        // Pull matches out by increasing order of distance.
4732        // To avoid reassigning pointers that have already been matched, the loop keeps track
4733        // of which last and current pointers have been matched using the matchedXXXBits variables.
4734        // It also tracks the used pointer id bits.
4735        BitSet32 matchedLastBits(0);
4736        BitSet32 matchedCurrentBits(0);
4737        BitSet32 usedIdBits(0);
4738        bool first = true;
4739        for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
4740            for (;;) {
4741                if (first) {
4742                    // The first time through the loop, we just consume the root element of
4743                    // the heap (the one with smallest distance).
4744                    first = false;
4745                } else {
4746                    // Previous iterations consumed the root element of the heap.
4747                    // Pop root element off of the heap (sift down).
4748                    heapSize -= 1;
4749                    LOG_ASSERT(heapSize > 0);
4750
4751                    // Sift down.
4752                    heap[0] = heap[heapSize];
4753                    for (uint32_t parentIndex = 0; ;) {
4754                        uint32_t childIndex = parentIndex * 2 + 1;
4755                        if (childIndex >= heapSize) {
4756                            break;
4757                        }
4758
4759                        if (childIndex + 1 < heapSize
4760                                && heap[childIndex + 1].distance < heap[childIndex].distance) {
4761                            childIndex += 1;
4762                        }
4763
4764                        if (heap[parentIndex].distance <= heap[childIndex].distance) {
4765                            break;
4766                        }
4767
4768                        swap(heap[parentIndex], heap[childIndex]);
4769                        parentIndex = childIndex;
4770                    }
4771
4772#if DEBUG_POINTER_ASSIGNMENT
4773                    LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
4774                    for (size_t i = 0; i < heapSize; i++) {
4775                        LOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
4776                                i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
4777                                heap[i].distance);
4778                    }
4779#endif
4780                }
4781
4782                uint32_t currentPointerIndex = heap[0].currentPointerIndex;
4783                if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
4784
4785                uint32_t lastPointerIndex = heap[0].lastPointerIndex;
4786                if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
4787
4788                matchedCurrentBits.markBit(currentPointerIndex);
4789                matchedLastBits.markBit(lastPointerIndex);
4790
4791                uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
4792                mCurrentTouch.pointers[currentPointerIndex].id = id;
4793                mCurrentTouch.idToIndex[id] = currentPointerIndex;
4794                usedIdBits.markBit(id);
4795
4796#if DEBUG_POINTER_ASSIGNMENT
4797                LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
4798                        lastPointerIndex, currentPointerIndex, id, heap[0].distance);
4799#endif
4800                break;
4801            }
4802        }
4803
4804        // Assign fresh ids to new pointers.
4805        if (currentPointerCount > lastPointerCount) {
4806            for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
4807                uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
4808                uint32_t id = usedIdBits.firstUnmarkedBit();
4809
4810                mCurrentTouch.pointers[currentPointerIndex].id = id;
4811                mCurrentTouch.idToIndex[id] = currentPointerIndex;
4812                usedIdBits.markBit(id);
4813
4814#if DEBUG_POINTER_ASSIGNMENT
4815                LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
4816                        currentPointerIndex, id);
4817#endif
4818
4819                if (--i == 0) break; // done
4820                matchedCurrentBits.markBit(currentPointerIndex);
4821            }
4822        }
4823
4824        // Fix id bits.
4825        mCurrentTouch.idBits = usedIdBits;
4826    }
4827}
4828
4829/* Special hack for devices that have bad screen data: if one of the
4830 * points has moved more than a screen height from the last position,
4831 * then drop it. */
4832bool TouchInputMapper::applyBadTouchFilter() {
4833    uint32_t pointerCount = mCurrentTouch.pointerCount;
4834
4835    // Nothing to do if there are no points.
4836    if (pointerCount == 0) {
4837        return false;
4838    }
4839
4840    // Don't do anything if a finger is going down or up.  We run
4841    // here before assigning pointer IDs, so there isn't a good
4842    // way to do per-finger matching.
4843    if (pointerCount != mLastTouch.pointerCount) {
4844        return false;
4845    }
4846
4847    // We consider a single movement across more than a 7/16 of
4848    // the long size of the screen to be bad.  This was a magic value
4849    // determined by looking at the maximum distance it is feasible
4850    // to actually move in one sample.
4851    int32_t maxDeltaY = (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1) * 7 / 16;
4852
4853    // XXX The original code in InputDevice.java included commented out
4854    //     code for testing the X axis.  Note that when we drop a point
4855    //     we don't actually restore the old X either.  Strange.
4856    //     The old code also tries to track when bad points were previously
4857    //     detected but it turns out that due to the placement of a "break"
4858    //     at the end of the loop, we never set mDroppedBadPoint to true
4859    //     so it is effectively dead code.
4860    // Need to figure out if the old code is busted or just overcomplicated
4861    // but working as intended.
4862
4863    // Look through all new points and see if any are farther than
4864    // acceptable from all previous points.
4865    for (uint32_t i = pointerCount; i-- > 0; ) {
4866        int32_t y = mCurrentTouch.pointers[i].y;
4867        int32_t closestY = INT_MAX;
4868        int32_t closestDeltaY = 0;
4869
4870#if DEBUG_HACKS
4871        LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
4872#endif
4873
4874        for (uint32_t j = pointerCount; j-- > 0; ) {
4875            int32_t lastY = mLastTouch.pointers[j].y;
4876            int32_t deltaY = abs(y - lastY);
4877
4878#if DEBUG_HACKS
4879            LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
4880                    j, lastY, deltaY);
4881#endif
4882
4883            if (deltaY < maxDeltaY) {
4884                goto SkipSufficientlyClosePoint;
4885            }
4886            if (deltaY < closestDeltaY) {
4887                closestDeltaY = deltaY;
4888                closestY = lastY;
4889            }
4890        }
4891
4892        // Must not have found a close enough match.
4893#if DEBUG_HACKS
4894        LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
4895                i, y, closestY, closestDeltaY, maxDeltaY);
4896#endif
4897
4898        mCurrentTouch.pointers[i].y = closestY;
4899        return true; // XXX original code only corrects one point
4900
4901    SkipSufficientlyClosePoint: ;
4902    }
4903
4904    // No change.
4905    return false;
4906}
4907
4908/* Special hack for devices that have bad screen data: drop points where
4909 * the coordinate value for one axis has jumped to the other pointer's location.
4910 */
4911bool TouchInputMapper::applyJumpyTouchFilter() {
4912    uint32_t pointerCount = mCurrentTouch.pointerCount;
4913    if (mLastTouch.pointerCount != pointerCount) {
4914#if DEBUG_HACKS
4915        LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
4916                mLastTouch.pointerCount, pointerCount);
4917        for (uint32_t i = 0; i < pointerCount; i++) {
4918            LOGD("  Pointer %d (%d, %d)", i,
4919                    mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
4920        }
4921#endif
4922
4923        if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
4924            if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
4925                // Just drop the first few events going from 1 to 2 pointers.
4926                // They're bad often enough that they're not worth considering.
4927                mCurrentTouch.pointerCount = 1;
4928                mJumpyTouchFilter.jumpyPointsDropped += 1;
4929
4930#if DEBUG_HACKS
4931                LOGD("JumpyTouchFilter: Pointer 2 dropped");
4932#endif
4933                return true;
4934            } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
4935                // The event when we go from 2 -> 1 tends to be messed up too
4936                mCurrentTouch.pointerCount = 2;
4937                mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
4938                mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
4939                mJumpyTouchFilter.jumpyPointsDropped += 1;
4940
4941#if DEBUG_HACKS
4942                for (int32_t i = 0; i < 2; i++) {
4943                    LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
4944                            mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
4945                }
4946#endif
4947                return true;
4948            }
4949        }
4950        // Reset jumpy points dropped on other transitions or if limit exceeded.
4951        mJumpyTouchFilter.jumpyPointsDropped = 0;
4952
4953#if DEBUG_HACKS
4954        LOGD("JumpyTouchFilter: Transition - drop limit reset");
4955#endif
4956        return false;
4957    }
4958
4959    // We have the same number of pointers as last time.
4960    // A 'jumpy' point is one where the coordinate value for one axis
4961    // has jumped to the other pointer's location. No need to do anything
4962    // else if we only have one pointer.
4963    if (pointerCount < 2) {
4964        return false;
4965    }
4966
4967    if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
4968        int jumpyEpsilon = (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1) / JUMPY_EPSILON_DIVISOR;
4969
4970        // We only replace the single worst jumpy point as characterized by pointer distance
4971        // in a single axis.
4972        int32_t badPointerIndex = -1;
4973        int32_t badPointerReplacementIndex = -1;
4974        int32_t badPointerDistance = INT_MIN; // distance to be corrected
4975
4976        for (uint32_t i = pointerCount; i-- > 0; ) {
4977            int32_t x = mCurrentTouch.pointers[i].x;
4978            int32_t y = mCurrentTouch.pointers[i].y;
4979
4980#if DEBUG_HACKS
4981            LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
4982#endif
4983
4984            // Check if a touch point is too close to another's coordinates
4985            bool dropX = false, dropY = false;
4986            for (uint32_t j = 0; j < pointerCount; j++) {
4987                if (i == j) {
4988                    continue;
4989                }
4990
4991                if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
4992                    dropX = true;
4993                    break;
4994                }
4995
4996                if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
4997                    dropY = true;
4998                    break;
4999                }
5000            }
5001            if (! dropX && ! dropY) {
5002                continue; // not jumpy
5003            }
5004
5005            // Find a replacement candidate by comparing with older points on the
5006            // complementary (non-jumpy) axis.
5007            int32_t distance = INT_MIN; // distance to be corrected
5008            int32_t replacementIndex = -1;
5009
5010            if (dropX) {
5011                // X looks too close.  Find an older replacement point with a close Y.
5012                int32_t smallestDeltaY = INT_MAX;
5013                for (uint32_t j = 0; j < pointerCount; j++) {
5014                    int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
5015                    if (deltaY < smallestDeltaY) {
5016                        smallestDeltaY = deltaY;
5017                        replacementIndex = j;
5018                    }
5019                }
5020                distance = abs(x - mLastTouch.pointers[replacementIndex].x);
5021            } else {
5022                // Y looks too close.  Find an older replacement point with a close X.
5023                int32_t smallestDeltaX = INT_MAX;
5024                for (uint32_t j = 0; j < pointerCount; j++) {
5025                    int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
5026                    if (deltaX < smallestDeltaX) {
5027                        smallestDeltaX = deltaX;
5028                        replacementIndex = j;
5029                    }
5030                }
5031                distance = abs(y - mLastTouch.pointers[replacementIndex].y);
5032            }
5033
5034            // If replacing this pointer would correct a worse error than the previous ones
5035            // considered, then use this replacement instead.
5036            if (distance > badPointerDistance) {
5037                badPointerIndex = i;
5038                badPointerReplacementIndex = replacementIndex;
5039                badPointerDistance = distance;
5040            }
5041        }
5042
5043        // Correct the jumpy pointer if one was found.
5044        if (badPointerIndex >= 0) {
5045#if DEBUG_HACKS
5046            LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
5047                    badPointerIndex,
5048                    mLastTouch.pointers[badPointerReplacementIndex].x,
5049                    mLastTouch.pointers[badPointerReplacementIndex].y);
5050#endif
5051
5052            mCurrentTouch.pointers[badPointerIndex].x =
5053                    mLastTouch.pointers[badPointerReplacementIndex].x;
5054            mCurrentTouch.pointers[badPointerIndex].y =
5055                    mLastTouch.pointers[badPointerReplacementIndex].y;
5056            mJumpyTouchFilter.jumpyPointsDropped += 1;
5057            return true;
5058        }
5059    }
5060
5061    mJumpyTouchFilter.jumpyPointsDropped = 0;
5062    return false;
5063}
5064
5065/* Special hack for devices that have bad screen data: aggregate and
5066 * compute averages of the coordinate data, to reduce the amount of
5067 * jitter seen by applications. */
5068void TouchInputMapper::applyAveragingTouchFilter() {
5069    for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
5070        uint32_t id = mCurrentTouch.pointers[currentIndex].id;
5071        int32_t x = mCurrentTouch.pointers[currentIndex].x;
5072        int32_t y = mCurrentTouch.pointers[currentIndex].y;
5073        int32_t pressure;
5074        switch (mCalibration.pressureSource) {
5075        case Calibration::PRESSURE_SOURCE_PRESSURE:
5076            pressure = mCurrentTouch.pointers[currentIndex].pressure;
5077            break;
5078        case Calibration::PRESSURE_SOURCE_TOUCH:
5079            pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
5080            break;
5081        default:
5082            pressure = 1;
5083            break;
5084        }
5085
5086        if (mLastTouch.idBits.hasBit(id)) {
5087            // Pointer was down before and is still down now.
5088            // Compute average over history trace.
5089            uint32_t start = mAveragingTouchFilter.historyStart[id];
5090            uint32_t end = mAveragingTouchFilter.historyEnd[id];
5091
5092            int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
5093            int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
5094            uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
5095
5096#if DEBUG_HACKS
5097            LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
5098                    id, distance);
5099#endif
5100
5101            if (distance < AVERAGING_DISTANCE_LIMIT) {
5102                // Increment end index in preparation for recording new historical data.
5103                end += 1;
5104                if (end > AVERAGING_HISTORY_SIZE) {
5105                    end = 0;
5106                }
5107
5108                // If the end index has looped back to the start index then we have filled
5109                // the historical trace up to the desired size so we drop the historical
5110                // data at the start of the trace.
5111                if (end == start) {
5112                    start += 1;
5113                    if (start > AVERAGING_HISTORY_SIZE) {
5114                        start = 0;
5115                    }
5116                }
5117
5118                // Add the raw data to the historical trace.
5119                mAveragingTouchFilter.historyStart[id] = start;
5120                mAveragingTouchFilter.historyEnd[id] = end;
5121                mAveragingTouchFilter.historyData[end].pointers[id].x = x;
5122                mAveragingTouchFilter.historyData[end].pointers[id].y = y;
5123                mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
5124
5125                // Average over all historical positions in the trace by total pressure.
5126                int32_t averagedX = 0;
5127                int32_t averagedY = 0;
5128                int32_t totalPressure = 0;
5129                for (;;) {
5130                    int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
5131                    int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
5132                    int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
5133                            .pointers[id].pressure;
5134
5135                    averagedX += historicalX * historicalPressure;
5136                    averagedY += historicalY * historicalPressure;
5137                    totalPressure += historicalPressure;
5138
5139                    if (start == end) {
5140                        break;
5141                    }
5142
5143                    start += 1;
5144                    if (start > AVERAGING_HISTORY_SIZE) {
5145                        start = 0;
5146                    }
5147                }
5148
5149                if (totalPressure != 0) {
5150                    averagedX /= totalPressure;
5151                    averagedY /= totalPressure;
5152
5153#if DEBUG_HACKS
5154                    LOGD("AveragingTouchFilter: Pointer id %d - "
5155                            "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
5156                            averagedX, averagedY);
5157#endif
5158
5159                    mCurrentTouch.pointers[currentIndex].x = averagedX;
5160                    mCurrentTouch.pointers[currentIndex].y = averagedY;
5161                }
5162            } else {
5163#if DEBUG_HACKS
5164                LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
5165#endif
5166            }
5167        } else {
5168#if DEBUG_HACKS
5169            LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
5170#endif
5171        }
5172
5173        // Reset pointer history.
5174        mAveragingTouchFilter.historyStart[id] = 0;
5175        mAveragingTouchFilter.historyEnd[id] = 0;
5176        mAveragingTouchFilter.historyData[0].pointers[id].x = x;
5177        mAveragingTouchFilter.historyData[0].pointers[id].y = y;
5178        mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
5179    }
5180}
5181
5182int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
5183    { // acquire lock
5184        AutoMutex _l(mLock);
5185
5186        if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
5187            return AKEY_STATE_VIRTUAL;
5188        }
5189
5190        size_t numVirtualKeys = mLocked.virtualKeys.size();
5191        for (size_t i = 0; i < numVirtualKeys; i++) {
5192            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
5193            if (virtualKey.keyCode == keyCode) {
5194                return AKEY_STATE_UP;
5195            }
5196        }
5197    } // release lock
5198
5199    return AKEY_STATE_UNKNOWN;
5200}
5201
5202int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
5203    { // acquire lock
5204        AutoMutex _l(mLock);
5205
5206        if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
5207            return AKEY_STATE_VIRTUAL;
5208        }
5209
5210        size_t numVirtualKeys = mLocked.virtualKeys.size();
5211        for (size_t i = 0; i < numVirtualKeys; i++) {
5212            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
5213            if (virtualKey.scanCode == scanCode) {
5214                return AKEY_STATE_UP;
5215            }
5216        }
5217    } // release lock
5218
5219    return AKEY_STATE_UNKNOWN;
5220}
5221
5222bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
5223        const int32_t* keyCodes, uint8_t* outFlags) {
5224    { // acquire lock
5225        AutoMutex _l(mLock);
5226
5227        size_t numVirtualKeys = mLocked.virtualKeys.size();
5228        for (size_t i = 0; i < numVirtualKeys; i++) {
5229            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
5230
5231            for (size_t i = 0; i < numCodes; i++) {
5232                if (virtualKey.keyCode == keyCodes[i]) {
5233                    outFlags[i] = 1;
5234                }
5235            }
5236        }
5237    } // release lock
5238
5239    return true;
5240}
5241
5242
5243// --- SingleTouchInputMapper ---
5244
5245SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
5246        TouchInputMapper(device) {
5247    clearState();
5248}
5249
5250SingleTouchInputMapper::~SingleTouchInputMapper() {
5251}
5252
5253void SingleTouchInputMapper::clearState() {
5254    mAccumulator.clear();
5255
5256    mDown = false;
5257    mX = 0;
5258    mY = 0;
5259    mPressure = 0; // default to 0 for devices that don't report pressure
5260    mToolWidth = 0; // default to 0 for devices that don't report tool width
5261    mButtonState = 0;
5262}
5263
5264void SingleTouchInputMapper::reset() {
5265    TouchInputMapper::reset();
5266
5267    clearState();
5268 }
5269
5270void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
5271    switch (rawEvent->type) {
5272    case EV_KEY:
5273        switch (rawEvent->scanCode) {
5274        case BTN_TOUCH:
5275            mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
5276            mAccumulator.btnTouch = rawEvent->value != 0;
5277            // Don't sync immediately.  Wait until the next SYN_REPORT since we might
5278            // not have received valid position information yet.  This logic assumes that
5279            // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
5280            break;
5281        default:
5282            if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
5283                int32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
5284                if (buttonState) {
5285                    if (rawEvent->value) {
5286                        mAccumulator.buttonDown |= buttonState;
5287                    } else {
5288                        mAccumulator.buttonUp |= buttonState;
5289                    }
5290                    mAccumulator.fields |= Accumulator::FIELD_BUTTONS;
5291                }
5292            }
5293            break;
5294        }
5295        break;
5296
5297    case EV_ABS:
5298        switch (rawEvent->scanCode) {
5299        case ABS_X:
5300            mAccumulator.fields |= Accumulator::FIELD_ABS_X;
5301            mAccumulator.absX = rawEvent->value;
5302            break;
5303        case ABS_Y:
5304            mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
5305            mAccumulator.absY = rawEvent->value;
5306            break;
5307        case ABS_PRESSURE:
5308            mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
5309            mAccumulator.absPressure = rawEvent->value;
5310            break;
5311        case ABS_TOOL_WIDTH:
5312            mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
5313            mAccumulator.absToolWidth = rawEvent->value;
5314            break;
5315        }
5316        break;
5317
5318    case EV_SYN:
5319        switch (rawEvent->scanCode) {
5320        case SYN_REPORT:
5321            sync(rawEvent->when);
5322            break;
5323        }
5324        break;
5325    }
5326}
5327
5328void SingleTouchInputMapper::sync(nsecs_t when) {
5329    uint32_t fields = mAccumulator.fields;
5330    if (fields == 0) {
5331        return; // no new state changes, so nothing to do
5332    }
5333
5334    if (fields & Accumulator::FIELD_BTN_TOUCH) {
5335        mDown = mAccumulator.btnTouch;
5336    }
5337
5338    if (fields & Accumulator::FIELD_ABS_X) {
5339        mX = mAccumulator.absX;
5340    }
5341
5342    if (fields & Accumulator::FIELD_ABS_Y) {
5343        mY = mAccumulator.absY;
5344    }
5345
5346    if (fields & Accumulator::FIELD_ABS_PRESSURE) {
5347        mPressure = mAccumulator.absPressure;
5348    }
5349
5350    if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
5351        mToolWidth = mAccumulator.absToolWidth;
5352    }
5353
5354    if (fields & Accumulator::FIELD_BUTTONS) {
5355        mButtonState = (mButtonState | mAccumulator.buttonDown) & ~mAccumulator.buttonUp;
5356    }
5357
5358    mCurrentTouch.clear();
5359
5360    if (mDown) {
5361        mCurrentTouch.pointerCount = 1;
5362        mCurrentTouch.pointers[0].id = 0;
5363        mCurrentTouch.pointers[0].x = mX;
5364        mCurrentTouch.pointers[0].y = mY;
5365        mCurrentTouch.pointers[0].pressure = mPressure;
5366        mCurrentTouch.pointers[0].touchMajor = 0;
5367        mCurrentTouch.pointers[0].touchMinor = 0;
5368        mCurrentTouch.pointers[0].toolMajor = mToolWidth;
5369        mCurrentTouch.pointers[0].toolMinor = mToolWidth;
5370        mCurrentTouch.pointers[0].orientation = 0;
5371        mCurrentTouch.pointers[0].distance = 0;
5372        mCurrentTouch.pointers[0].isStylus = false; // TODO: Set stylus
5373        mCurrentTouch.idToIndex[0] = 0;
5374        mCurrentTouch.idBits.markBit(0);
5375        mCurrentTouch.buttonState = mButtonState;
5376    }
5377
5378    syncTouch(when, true);
5379
5380    mAccumulator.clear();
5381}
5382
5383void SingleTouchInputMapper::configureRawAxes() {
5384    TouchInputMapper::configureRawAxes();
5385
5386    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
5387    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
5388    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
5389    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
5390}
5391
5392
5393// --- MultiTouchInputMapper ---
5394
5395MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
5396        TouchInputMapper(device), mSlotCount(0), mUsingSlotsProtocol(false) {
5397    clearState();
5398}
5399
5400MultiTouchInputMapper::~MultiTouchInputMapper() {
5401}
5402
5403void MultiTouchInputMapper::clearState() {
5404    mAccumulator.clearSlots(mSlotCount);
5405    mAccumulator.clearButtons();
5406    mButtonState = 0;
5407}
5408
5409void MultiTouchInputMapper::reset() {
5410    TouchInputMapper::reset();
5411
5412    clearState();
5413}
5414
5415void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
5416    switch (rawEvent->type) {
5417    case EV_KEY: {
5418        if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
5419            int32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
5420            if (buttonState) {
5421                if (rawEvent->value) {
5422                    mAccumulator.buttonDown |= buttonState;
5423                } else {
5424                    mAccumulator.buttonUp |= buttonState;
5425                }
5426            }
5427        }
5428        break;
5429    }
5430
5431    case EV_ABS: {
5432        bool newSlot = false;
5433        if (mUsingSlotsProtocol && rawEvent->scanCode == ABS_MT_SLOT) {
5434            mAccumulator.currentSlot = rawEvent->value;
5435            newSlot = true;
5436        }
5437
5438        if (mAccumulator.currentSlot < 0 || size_t(mAccumulator.currentSlot) >= mSlotCount) {
5439#if DEBUG_POINTERS
5440            if (newSlot) {
5441                LOGW("MultiTouch device %s emitted invalid slot index %d but it "
5442                        "should be between 0 and %d; ignoring this slot.",
5443                        getDeviceName().string(), mAccumulator.currentSlot, mSlotCount);
5444            }
5445#endif
5446            break;
5447        }
5448
5449        Accumulator::Slot* slot = &mAccumulator.slots[mAccumulator.currentSlot];
5450
5451        switch (rawEvent->scanCode) {
5452        case ABS_MT_POSITION_X:
5453            slot->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
5454            slot->absMTPositionX = rawEvent->value;
5455            break;
5456        case ABS_MT_POSITION_Y:
5457            slot->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
5458            slot->absMTPositionY = rawEvent->value;
5459            break;
5460        case ABS_MT_TOUCH_MAJOR:
5461            slot->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
5462            slot->absMTTouchMajor = rawEvent->value;
5463            break;
5464        case ABS_MT_TOUCH_MINOR:
5465            slot->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
5466            slot->absMTTouchMinor = rawEvent->value;
5467            break;
5468        case ABS_MT_WIDTH_MAJOR:
5469            slot->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
5470            slot->absMTWidthMajor = rawEvent->value;
5471            break;
5472        case ABS_MT_WIDTH_MINOR:
5473            slot->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
5474            slot->absMTWidthMinor = rawEvent->value;
5475            break;
5476        case ABS_MT_ORIENTATION:
5477            slot->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
5478            slot->absMTOrientation = rawEvent->value;
5479            break;
5480        case ABS_MT_TRACKING_ID:
5481            if (mUsingSlotsProtocol && rawEvent->value < 0) {
5482                slot->clear();
5483            } else {
5484                slot->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
5485                slot->absMTTrackingId = rawEvent->value;
5486            }
5487            break;
5488        case ABS_MT_PRESSURE:
5489            slot->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
5490            slot->absMTPressure = rawEvent->value;
5491            break;
5492        case ABS_MT_TOOL_TYPE:
5493            slot->fields |= Accumulator::FIELD_ABS_MT_TOOL_TYPE;
5494            slot->absMTToolType = rawEvent->value;
5495            break;
5496        }
5497        break;
5498    }
5499
5500    case EV_SYN:
5501        switch (rawEvent->scanCode) {
5502        case SYN_MT_REPORT: {
5503            // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
5504            mAccumulator.currentSlot += 1;
5505            break;
5506        }
5507
5508        case SYN_REPORT:
5509            sync(rawEvent->when);
5510            break;
5511        }
5512        break;
5513    }
5514}
5515
5516void MultiTouchInputMapper::sync(nsecs_t when) {
5517    static const uint32_t REQUIRED_FIELDS =
5518            Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
5519
5520    size_t inCount = mSlotCount;
5521    size_t outCount = 0;
5522    bool havePointerIds = true;
5523
5524    mCurrentTouch.clear();
5525
5526    for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
5527        const Accumulator::Slot& inSlot = mAccumulator.slots[inIndex];
5528        uint32_t fields = inSlot.fields;
5529
5530        if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
5531            // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
5532            // This may also indicate an unused slot.
5533            // Drop this finger.
5534            continue;
5535        }
5536
5537        if (outCount >= MAX_POINTERS) {
5538#if DEBUG_POINTERS
5539            LOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
5540                    "ignoring the rest.",
5541                    getDeviceName().string(), MAX_POINTERS);
5542#endif
5543            break; // too many fingers!
5544        }
5545
5546        PointerData& outPointer = mCurrentTouch.pointers[outCount];
5547        outPointer.x = inSlot.absMTPositionX;
5548        outPointer.y = inSlot.absMTPositionY;
5549
5550        if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
5551            outPointer.pressure = inSlot.absMTPressure;
5552        } else {
5553            // Default pressure to 0 if absent.
5554            outPointer.pressure = 0;
5555        }
5556
5557        if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
5558            if (inSlot.absMTTouchMajor <= 0) {
5559                // Some devices send sync packets with X / Y but with a 0 touch major to indicate
5560                // a pointer going up.  Drop this finger.
5561                continue;
5562            }
5563            outPointer.touchMajor = inSlot.absMTTouchMajor;
5564        } else {
5565            // Default touch area to 0 if absent.
5566            outPointer.touchMajor = 0;
5567        }
5568
5569        if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
5570            outPointer.touchMinor = inSlot.absMTTouchMinor;
5571        } else {
5572            // Assume touch area is circular.
5573            outPointer.touchMinor = outPointer.touchMajor;
5574        }
5575
5576        if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
5577            outPointer.toolMajor = inSlot.absMTWidthMajor;
5578        } else {
5579            // Default tool area to 0 if absent.
5580            outPointer.toolMajor = 0;
5581        }
5582
5583        if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
5584            outPointer.toolMinor = inSlot.absMTWidthMinor;
5585        } else {
5586            // Assume tool area is circular.
5587            outPointer.toolMinor = outPointer.toolMajor;
5588        }
5589
5590        if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
5591            outPointer.orientation = inSlot.absMTOrientation;
5592        } else {
5593            // Default orientation to vertical if absent.
5594            outPointer.orientation = 0;
5595        }
5596
5597        if (fields & Accumulator::FIELD_ABS_MT_DISTANCE) {
5598            outPointer.distance = inSlot.absMTDistance;
5599        } else {
5600            // Default distance is 0 (direct contact).
5601            outPointer.distance = 0;
5602        }
5603
5604        if (fields & Accumulator::FIELD_ABS_MT_TOOL_TYPE) {
5605            outPointer.isStylus = (inSlot.absMTToolType == MT_TOOL_PEN);
5606        } else {
5607            // Assume this is not a stylus.
5608            outPointer.isStylus = false;
5609        }
5610
5611        // Assign pointer id using tracking id if available.
5612        if (havePointerIds) {
5613            int32_t id;
5614            if (mUsingSlotsProtocol) {
5615                id = inIndex;
5616            } else if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
5617                id = inSlot.absMTTrackingId;
5618            } else {
5619                id = -1;
5620            }
5621
5622            if (id >= 0 && id <= MAX_POINTER_ID) {
5623                outPointer.id = id;
5624                mCurrentTouch.idToIndex[id] = outCount;
5625                mCurrentTouch.idBits.markBit(id);
5626            } else {
5627                if (id >= 0) {
5628#if DEBUG_POINTERS
5629                    LOGD("Pointers: Ignoring driver provided slot index or tracking id %d because "
5630                            "it is larger than the maximum supported pointer id %d",
5631                            id, MAX_POINTER_ID);
5632#endif
5633                }
5634                havePointerIds = false;
5635            }
5636        }
5637
5638        outCount += 1;
5639    }
5640
5641    mCurrentTouch.pointerCount = outCount;
5642
5643    mButtonState = (mButtonState | mAccumulator.buttonDown) & ~mAccumulator.buttonUp;
5644    mCurrentTouch.buttonState = mButtonState;
5645
5646    syncTouch(when, havePointerIds);
5647
5648    if (!mUsingSlotsProtocol) {
5649        mAccumulator.clearSlots(mSlotCount);
5650    }
5651    mAccumulator.clearButtons();
5652}
5653
5654void MultiTouchInputMapper::configureRawAxes() {
5655    TouchInputMapper::configureRawAxes();
5656
5657    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, &mRawAxes.x);
5658    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, &mRawAxes.y);
5659    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, &mRawAxes.touchMajor);
5660    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, &mRawAxes.touchMinor);
5661    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, &mRawAxes.toolMajor);
5662    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, &mRawAxes.toolMinor);
5663    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, &mRawAxes.orientation);
5664    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, &mRawAxes.pressure);
5665    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_DISTANCE, &mRawAxes.distance);
5666    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TRACKING_ID, &mRawAxes.trackingId);
5667    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_SLOT, &mRawAxes.slot);
5668
5669    if (mRawAxes.trackingId.valid
5670            && mRawAxes.slot.valid && mRawAxes.slot.minValue == 0 && mRawAxes.slot.maxValue > 0) {
5671        mSlotCount = mRawAxes.slot.maxValue + 1;
5672        if (mSlotCount > MAX_SLOTS) {
5673            LOGW("MultiTouch Device %s reported %d slots but the framework "
5674                    "only supports a maximum of %d slots at this time.",
5675                    getDeviceName().string(), mSlotCount, MAX_SLOTS);
5676            mSlotCount = MAX_SLOTS;
5677        }
5678        mUsingSlotsProtocol = true;
5679    } else {
5680        mSlotCount = MAX_POINTERS;
5681        mUsingSlotsProtocol = false;
5682    }
5683
5684    mAccumulator.allocateSlots(mSlotCount);
5685}
5686
5687
5688// --- JoystickInputMapper ---
5689
5690JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
5691        InputMapper(device) {
5692}
5693
5694JoystickInputMapper::~JoystickInputMapper() {
5695}
5696
5697uint32_t JoystickInputMapper::getSources() {
5698    return AINPUT_SOURCE_JOYSTICK;
5699}
5700
5701void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
5702    InputMapper::populateDeviceInfo(info);
5703
5704    for (size_t i = 0; i < mAxes.size(); i++) {
5705        const Axis& axis = mAxes.valueAt(i);
5706        info->addMotionRange(axis.axisInfo.axis, AINPUT_SOURCE_JOYSTICK,
5707                axis.min, axis.max, axis.flat, axis.fuzz);
5708        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5709            info->addMotionRange(axis.axisInfo.highAxis, AINPUT_SOURCE_JOYSTICK,
5710                    axis.min, axis.max, axis.flat, axis.fuzz);
5711        }
5712    }
5713}
5714
5715void JoystickInputMapper::dump(String8& dump) {
5716    dump.append(INDENT2 "Joystick Input Mapper:\n");
5717
5718    dump.append(INDENT3 "Axes:\n");
5719    size_t numAxes = mAxes.size();
5720    for (size_t i = 0; i < numAxes; i++) {
5721        const Axis& axis = mAxes.valueAt(i);
5722        const char* label = getAxisLabel(axis.axisInfo.axis);
5723        if (label) {
5724            dump.appendFormat(INDENT4 "%s", label);
5725        } else {
5726            dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis);
5727        }
5728        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5729            label = getAxisLabel(axis.axisInfo.highAxis);
5730            if (label) {
5731                dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue);
5732            } else {
5733                dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis,
5734                        axis.axisInfo.splitValue);
5735            }
5736        } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
5737            dump.append(" (invert)");
5738        }
5739
5740        dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f\n",
5741                axis.min, axis.max, axis.flat, axis.fuzz);
5742        dump.appendFormat(INDENT4 "  scale=%0.5f, offset=%0.5f, "
5743                "highScale=%0.5f, highOffset=%0.5f\n",
5744                axis.scale, axis.offset, axis.highScale, axis.highOffset);
5745        dump.appendFormat(INDENT4 "  rawAxis=%d, rawMin=%d, rawMax=%d, "
5746                "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n",
5747                mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
5748                axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, axis.rawAxisInfo.resolution);
5749    }
5750}
5751
5752void JoystickInputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) {
5753    InputMapper::configure(config, changes);
5754
5755    if (!changes) { // first time only
5756        // Collect all axes.
5757        for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
5758            RawAbsoluteAxisInfo rawAxisInfo;
5759            getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo);
5760            if (rawAxisInfo.valid) {
5761                // Map axis.
5762                AxisInfo axisInfo;
5763                bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
5764                if (!explicitlyMapped) {
5765                    // Axis is not explicitly mapped, will choose a generic axis later.
5766                    axisInfo.mode = AxisInfo::MODE_NORMAL;
5767                    axisInfo.axis = -1;
5768                }
5769
5770                // Apply flat override.
5771                int32_t rawFlat = axisInfo.flatOverride < 0
5772                        ? rawAxisInfo.flat : axisInfo.flatOverride;
5773
5774                // Calculate scaling factors and limits.
5775                Axis axis;
5776                if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
5777                    float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
5778                    float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
5779                    axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5780                            scale, 0.0f, highScale, 0.0f,
5781                            0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
5782                } else if (isCenteredAxis(axisInfo.axis)) {
5783                    float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
5784                    float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
5785                    axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5786                            scale, offset, scale, offset,
5787                            -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
5788                } else {
5789                    float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
5790                    axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5791                            scale, 0.0f, scale, 0.0f,
5792                            0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
5793                }
5794
5795                // To eliminate noise while the joystick is at rest, filter out small variations
5796                // in axis values up front.
5797                axis.filter = axis.flat * 0.25f;
5798
5799                mAxes.add(abs, axis);
5800            }
5801        }
5802
5803        // If there are too many axes, start dropping them.
5804        // Prefer to keep explicitly mapped axes.
5805        if (mAxes.size() > PointerCoords::MAX_AXES) {
5806            LOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
5807                    getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
5808            pruneAxes(true);
5809            pruneAxes(false);
5810        }
5811
5812        // Assign generic axis ids to remaining axes.
5813        int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
5814        size_t numAxes = mAxes.size();
5815        for (size_t i = 0; i < numAxes; i++) {
5816            Axis& axis = mAxes.editValueAt(i);
5817            if (axis.axisInfo.axis < 0) {
5818                while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
5819                        && haveAxis(nextGenericAxisId)) {
5820                    nextGenericAxisId += 1;
5821                }
5822
5823                if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
5824                    axis.axisInfo.axis = nextGenericAxisId;
5825                    nextGenericAxisId += 1;
5826                } else {
5827                    LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
5828                            "have already been assigned to other axes.",
5829                            getDeviceName().string(), mAxes.keyAt(i));
5830                    mAxes.removeItemsAt(i--);
5831                    numAxes -= 1;
5832                }
5833            }
5834        }
5835    }
5836}
5837
5838bool JoystickInputMapper::haveAxis(int32_t axisId) {
5839    size_t numAxes = mAxes.size();
5840    for (size_t i = 0; i < numAxes; i++) {
5841        const Axis& axis = mAxes.valueAt(i);
5842        if (axis.axisInfo.axis == axisId
5843                || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
5844                        && axis.axisInfo.highAxis == axisId)) {
5845            return true;
5846        }
5847    }
5848    return false;
5849}
5850
5851void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
5852    size_t i = mAxes.size();
5853    while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
5854        if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
5855            continue;
5856        }
5857        LOGI("Discarding joystick '%s' axis %d because there are too many axes.",
5858                getDeviceName().string(), mAxes.keyAt(i));
5859        mAxes.removeItemsAt(i);
5860    }
5861}
5862
5863bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
5864    switch (axis) {
5865    case AMOTION_EVENT_AXIS_X:
5866    case AMOTION_EVENT_AXIS_Y:
5867    case AMOTION_EVENT_AXIS_Z:
5868    case AMOTION_EVENT_AXIS_RX:
5869    case AMOTION_EVENT_AXIS_RY:
5870    case AMOTION_EVENT_AXIS_RZ:
5871    case AMOTION_EVENT_AXIS_HAT_X:
5872    case AMOTION_EVENT_AXIS_HAT_Y:
5873    case AMOTION_EVENT_AXIS_ORIENTATION:
5874    case AMOTION_EVENT_AXIS_RUDDER:
5875    case AMOTION_EVENT_AXIS_WHEEL:
5876        return true;
5877    default:
5878        return false;
5879    }
5880}
5881
5882void JoystickInputMapper::reset() {
5883    // Recenter all axes.
5884    nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
5885
5886    size_t numAxes = mAxes.size();
5887    for (size_t i = 0; i < numAxes; i++) {
5888        Axis& axis = mAxes.editValueAt(i);
5889        axis.resetValue();
5890    }
5891
5892    sync(when, true /*force*/);
5893
5894    InputMapper::reset();
5895}
5896
5897void JoystickInputMapper::process(const RawEvent* rawEvent) {
5898    switch (rawEvent->type) {
5899    case EV_ABS: {
5900        ssize_t index = mAxes.indexOfKey(rawEvent->scanCode);
5901        if (index >= 0) {
5902            Axis& axis = mAxes.editValueAt(index);
5903            float newValue, highNewValue;
5904            switch (axis.axisInfo.mode) {
5905            case AxisInfo::MODE_INVERT:
5906                newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
5907                        * axis.scale + axis.offset;
5908                highNewValue = 0.0f;
5909                break;
5910            case AxisInfo::MODE_SPLIT:
5911                if (rawEvent->value < axis.axisInfo.splitValue) {
5912                    newValue = (axis.axisInfo.splitValue - rawEvent->value)
5913                            * axis.scale + axis.offset;
5914                    highNewValue = 0.0f;
5915                } else if (rawEvent->value > axis.axisInfo.splitValue) {
5916                    newValue = 0.0f;
5917                    highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
5918                            * axis.highScale + axis.highOffset;
5919                } else {
5920                    newValue = 0.0f;
5921                    highNewValue = 0.0f;
5922                }
5923                break;
5924            default:
5925                newValue = rawEvent->value * axis.scale + axis.offset;
5926                highNewValue = 0.0f;
5927                break;
5928            }
5929            axis.newValue = newValue;
5930            axis.highNewValue = highNewValue;
5931        }
5932        break;
5933    }
5934
5935    case EV_SYN:
5936        switch (rawEvent->scanCode) {
5937        case SYN_REPORT:
5938            sync(rawEvent->when, false /*force*/);
5939            break;
5940        }
5941        break;
5942    }
5943}
5944
5945void JoystickInputMapper::sync(nsecs_t when, bool force) {
5946    if (!filterAxes(force)) {
5947        return;
5948    }
5949
5950    int32_t metaState = mContext->getGlobalMetaState();
5951    int32_t buttonState = 0;
5952
5953    PointerProperties pointerProperties;
5954    pointerProperties.clear();
5955    pointerProperties.id = 0;
5956    pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
5957
5958    PointerCoords pointerCoords;
5959    pointerCoords.clear();
5960
5961    size_t numAxes = mAxes.size();
5962    for (size_t i = 0; i < numAxes; i++) {
5963        const Axis& axis = mAxes.valueAt(i);
5964        pointerCoords.setAxisValue(axis.axisInfo.axis, axis.currentValue);
5965        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5966            pointerCoords.setAxisValue(axis.axisInfo.highAxis, axis.highCurrentValue);
5967        }
5968    }
5969
5970    // Moving a joystick axis should not wake the devide because joysticks can
5971    // be fairly noisy even when not in use.  On the other hand, pushing a gamepad
5972    // button will likely wake the device.
5973    // TODO: Use the input device configuration to control this behavior more finely.
5974    uint32_t policyFlags = 0;
5975
5976    getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
5977            AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
5978            1, &pointerProperties, &pointerCoords, 0, 0, 0);
5979}
5980
5981bool JoystickInputMapper::filterAxes(bool force) {
5982    bool atLeastOneSignificantChange = force;
5983    size_t numAxes = mAxes.size();
5984    for (size_t i = 0; i < numAxes; i++) {
5985        Axis& axis = mAxes.editValueAt(i);
5986        if (force || hasValueChangedSignificantly(axis.filter,
5987                axis.newValue, axis.currentValue, axis.min, axis.max)) {
5988            axis.currentValue = axis.newValue;
5989            atLeastOneSignificantChange = true;
5990        }
5991        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5992            if (force || hasValueChangedSignificantly(axis.filter,
5993                    axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
5994                axis.highCurrentValue = axis.highNewValue;
5995                atLeastOneSignificantChange = true;
5996            }
5997        }
5998    }
5999    return atLeastOneSignificantChange;
6000}
6001
6002bool JoystickInputMapper::hasValueChangedSignificantly(
6003        float filter, float newValue, float currentValue, float min, float max) {
6004    if (newValue != currentValue) {
6005        // Filter out small changes in value unless the value is converging on the axis
6006        // bounds or center point.  This is intended to reduce the amount of information
6007        // sent to applications by particularly noisy joysticks (such as PS3).
6008        if (fabs(newValue - currentValue) > filter
6009                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
6010                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
6011                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
6012            return true;
6013        }
6014    }
6015    return false;
6016}
6017
6018bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
6019        float filter, float newValue, float currentValue, float thresholdValue) {
6020    float newDistance = fabs(newValue - thresholdValue);
6021    if (newDistance < filter) {
6022        float oldDistance = fabs(currentValue - thresholdValue);
6023        if (newDistance < oldDistance) {
6024            return true;
6025        }
6026    }
6027    return false;
6028}
6029
6030} // namespace android
6031