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