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