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