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