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