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