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