InputReader.cpp revision 2dceb67f1f32bd2ec589c4ac3d83da0b8dbe4a5c
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
2836void TouchInputMapper::dumpParameters(String8& dump) {
2837    dump.append(INDENT3 "Parameters:\n");
2838
2839    switch (mParameters.gestureMode) {
2840    case Parameters::GESTURE_MODE_POINTER:
2841        dump.append(INDENT4 "GestureMode: pointer\n");
2842        break;
2843    case Parameters::GESTURE_MODE_SPOTS:
2844        dump.append(INDENT4 "GestureMode: spots\n");
2845        break;
2846    default:
2847        assert(false);
2848    }
2849
2850    switch (mParameters.deviceType) {
2851    case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
2852        dump.append(INDENT4 "DeviceType: touchScreen\n");
2853        break;
2854    case Parameters::DEVICE_TYPE_TOUCH_PAD:
2855        dump.append(INDENT4 "DeviceType: touchPad\n");
2856        break;
2857    case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION:
2858        dump.append(INDENT4 "DeviceType: touchNavigation\n");
2859        break;
2860    case Parameters::DEVICE_TYPE_POINTER:
2861        dump.append(INDENT4 "DeviceType: pointer\n");
2862        break;
2863    default:
2864        ALOG_ASSERT(false);
2865    }
2866
2867    dump.appendFormat(INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s\n",
2868            toString(mParameters.hasAssociatedDisplay),
2869            toString(mParameters.associatedDisplayIsExternal));
2870    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
2871            toString(mParameters.orientationAware));
2872}
2873
2874void TouchInputMapper::configureRawPointerAxes() {
2875    mRawPointerAxes.clear();
2876}
2877
2878void TouchInputMapper::dumpRawPointerAxes(String8& dump) {
2879    dump.append(INDENT3 "Raw Touch Axes:\n");
2880    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.x, "X");
2881    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.y, "Y");
2882    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.pressure, "Pressure");
2883    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMajor, "TouchMajor");
2884    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMinor, "TouchMinor");
2885    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMajor, "ToolMajor");
2886    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMinor, "ToolMinor");
2887    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.orientation, "Orientation");
2888    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.distance, "Distance");
2889    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltX, "TiltX");
2890    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltY, "TiltY");
2891    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.trackingId, "TrackingId");
2892    dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot");
2893}
2894
2895void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
2896    int32_t oldDeviceMode = mDeviceMode;
2897
2898    // Determine device mode.
2899    if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
2900            && mConfig.pointerGesturesEnabled) {
2901        mSource = AINPUT_SOURCE_MOUSE;
2902        mDeviceMode = DEVICE_MODE_POINTER;
2903        if (hasStylus()) {
2904            mSource |= AINPUT_SOURCE_STYLUS;
2905        }
2906    } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
2907            && mParameters.hasAssociatedDisplay) {
2908        mSource = AINPUT_SOURCE_TOUCHSCREEN;
2909        mDeviceMode = DEVICE_MODE_DIRECT;
2910        if (hasStylus()) {
2911            mSource |= AINPUT_SOURCE_STYLUS;
2912        }
2913    } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) {
2914        mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
2915        mDeviceMode = DEVICE_MODE_NAVIGATION;
2916    } else {
2917        mSource = AINPUT_SOURCE_TOUCHPAD;
2918        mDeviceMode = DEVICE_MODE_UNSCALED;
2919    }
2920
2921    // Ensure we have valid X and Y axes.
2922    if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
2923        ALOGW(INDENT "Touch device '%s' did not report support for X or Y axis!  "
2924                "The device will be inoperable.", getDeviceName().string());
2925        mDeviceMode = DEVICE_MODE_DISABLED;
2926        return;
2927    }
2928
2929    // Raw width and height in the natural orientation.
2930    int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
2931    int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
2932
2933    // Get associated display dimensions.
2934    DisplayViewport newViewport;
2935    if (mParameters.hasAssociatedDisplay) {
2936        if (!mConfig.getDisplayInfo(mParameters.associatedDisplayIsExternal, &newViewport)) {
2937            ALOGI(INDENT "Touch device '%s' could not query the properties of its associated "
2938                    "display.  The device will be inoperable until the display size "
2939                    "becomes available.",
2940                    getDeviceName().string());
2941            mDeviceMode = DEVICE_MODE_DISABLED;
2942            return;
2943        }
2944    } else {
2945        newViewport.setNonDisplayViewport(rawWidth, rawHeight);
2946    }
2947    bool viewportChanged = mViewport != newViewport;
2948    if (viewportChanged) {
2949        mViewport = newViewport;
2950
2951        if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
2952            // Convert rotated viewport to natural surface coordinates.
2953            int32_t naturalLogicalWidth, naturalLogicalHeight;
2954            int32_t naturalPhysicalWidth, naturalPhysicalHeight;
2955            int32_t naturalPhysicalLeft, naturalPhysicalTop;
2956            int32_t naturalDeviceWidth, naturalDeviceHeight;
2957            switch (mViewport.orientation) {
2958            case DISPLAY_ORIENTATION_90:
2959                naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
2960                naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
2961                naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
2962                naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
2963                naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom;
2964                naturalPhysicalTop = mViewport.physicalLeft;
2965                naturalDeviceWidth = mViewport.deviceHeight;
2966                naturalDeviceHeight = mViewport.deviceWidth;
2967                break;
2968            case DISPLAY_ORIENTATION_180:
2969                naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
2970                naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
2971                naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
2972                naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
2973                naturalPhysicalLeft = mViewport.deviceWidth - mViewport.physicalRight;
2974                naturalPhysicalTop = mViewport.deviceHeight - mViewport.physicalBottom;
2975                naturalDeviceWidth = mViewport.deviceWidth;
2976                naturalDeviceHeight = mViewport.deviceHeight;
2977                break;
2978            case DISPLAY_ORIENTATION_270:
2979                naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
2980                naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
2981                naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
2982                naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
2983                naturalPhysicalLeft = mViewport.physicalTop;
2984                naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight;
2985                naturalDeviceWidth = mViewport.deviceHeight;
2986                naturalDeviceHeight = mViewport.deviceWidth;
2987                break;
2988            case DISPLAY_ORIENTATION_0:
2989            default:
2990                naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
2991                naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
2992                naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
2993                naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
2994                naturalPhysicalLeft = mViewport.physicalLeft;
2995                naturalPhysicalTop = mViewport.physicalTop;
2996                naturalDeviceWidth = mViewport.deviceWidth;
2997                naturalDeviceHeight = mViewport.deviceHeight;
2998                break;
2999            }
3000
3001            mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
3002            mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
3003            mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth;
3004            mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight;
3005
3006            mSurfaceOrientation = mParameters.orientationAware ?
3007                    mViewport.orientation : DISPLAY_ORIENTATION_0;
3008        } else {
3009            mSurfaceWidth = rawWidth;
3010            mSurfaceHeight = rawHeight;
3011            mSurfaceLeft = 0;
3012            mSurfaceTop = 0;
3013            mSurfaceOrientation = DISPLAY_ORIENTATION_0;
3014        }
3015    }
3016
3017    // If moving between pointer modes, need to reset some state.
3018    bool deviceModeChanged = mDeviceMode != oldDeviceMode;
3019    if (deviceModeChanged) {
3020        mOrientedRanges.clear();
3021    }
3022
3023    // Create pointer controller if needed.
3024    if (mDeviceMode == DEVICE_MODE_POINTER ||
3025            (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
3026        if (mPointerController == NULL) {
3027            mPointerController = getPolicy()->obtainPointerController(getDeviceId());
3028        }
3029    } else {
3030        mPointerController.clear();
3031    }
3032
3033    if (viewportChanged || deviceModeChanged) {
3034        ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
3035                "display id %d",
3036                getDeviceId(), getDeviceName().string(), mSurfaceWidth, mSurfaceHeight,
3037                mSurfaceOrientation, mDeviceMode, mViewport.displayId);
3038
3039        // Configure X and Y factors.
3040        mXScale = float(mSurfaceWidth) / rawWidth;
3041        mYScale = float(mSurfaceHeight) / rawHeight;
3042        mXTranslate = -mSurfaceLeft;
3043        mYTranslate = -mSurfaceTop;
3044        mXPrecision = 1.0f / mXScale;
3045        mYPrecision = 1.0f / mYScale;
3046
3047        mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
3048        mOrientedRanges.x.source = mSource;
3049        mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
3050        mOrientedRanges.y.source = mSource;
3051
3052        configureVirtualKeys();
3053
3054        // Scale factor for terms that are not oriented in a particular axis.
3055        // If the pixels are square then xScale == yScale otherwise we fake it
3056        // by choosing an average.
3057        mGeometricScale = avg(mXScale, mYScale);
3058
3059        // Size of diagonal axis.
3060        float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight);
3061
3062        // Size factors.
3063        if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
3064            if (mRawPointerAxes.touchMajor.valid
3065                    && mRawPointerAxes.touchMajor.maxValue != 0) {
3066                mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue;
3067            } else if (mRawPointerAxes.toolMajor.valid
3068                    && mRawPointerAxes.toolMajor.maxValue != 0) {
3069                mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue;
3070            } else {
3071                mSizeScale = 0.0f;
3072            }
3073
3074            mOrientedRanges.haveTouchSize = true;
3075            mOrientedRanges.haveToolSize = true;
3076            mOrientedRanges.haveSize = true;
3077
3078            mOrientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
3079            mOrientedRanges.touchMajor.source = mSource;
3080            mOrientedRanges.touchMajor.min = 0;
3081            mOrientedRanges.touchMajor.max = diagonalSize;
3082            mOrientedRanges.touchMajor.flat = 0;
3083            mOrientedRanges.touchMajor.fuzz = 0;
3084            mOrientedRanges.touchMajor.resolution = 0;
3085
3086            mOrientedRanges.touchMinor = mOrientedRanges.touchMajor;
3087            mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
3088
3089            mOrientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
3090            mOrientedRanges.toolMajor.source = mSource;
3091            mOrientedRanges.toolMajor.min = 0;
3092            mOrientedRanges.toolMajor.max = diagonalSize;
3093            mOrientedRanges.toolMajor.flat = 0;
3094            mOrientedRanges.toolMajor.fuzz = 0;
3095            mOrientedRanges.toolMajor.resolution = 0;
3096
3097            mOrientedRanges.toolMinor = mOrientedRanges.toolMajor;
3098            mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
3099
3100            mOrientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
3101            mOrientedRanges.size.source = mSource;
3102            mOrientedRanges.size.min = 0;
3103            mOrientedRanges.size.max = 1.0;
3104            mOrientedRanges.size.flat = 0;
3105            mOrientedRanges.size.fuzz = 0;
3106            mOrientedRanges.size.resolution = 0;
3107        } else {
3108            mSizeScale = 0.0f;
3109        }
3110
3111        // Pressure factors.
3112        mPressureScale = 0;
3113        if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
3114                || mCalibration.pressureCalibration
3115                        == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
3116            if (mCalibration.havePressureScale) {
3117                mPressureScale = mCalibration.pressureScale;
3118            } else if (mRawPointerAxes.pressure.valid
3119                    && mRawPointerAxes.pressure.maxValue != 0) {
3120                mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue;
3121            }
3122        }
3123
3124        mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
3125        mOrientedRanges.pressure.source = mSource;
3126        mOrientedRanges.pressure.min = 0;
3127        mOrientedRanges.pressure.max = 1.0;
3128        mOrientedRanges.pressure.flat = 0;
3129        mOrientedRanges.pressure.fuzz = 0;
3130        mOrientedRanges.pressure.resolution = 0;
3131
3132        // Tilt
3133        mTiltXCenter = 0;
3134        mTiltXScale = 0;
3135        mTiltYCenter = 0;
3136        mTiltYScale = 0;
3137        mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid;
3138        if (mHaveTilt) {
3139            mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue,
3140                    mRawPointerAxes.tiltX.maxValue);
3141            mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue,
3142                    mRawPointerAxes.tiltY.maxValue);
3143            mTiltXScale = M_PI / 180;
3144            mTiltYScale = M_PI / 180;
3145
3146            mOrientedRanges.haveTilt = true;
3147
3148            mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT;
3149            mOrientedRanges.tilt.source = mSource;
3150            mOrientedRanges.tilt.min = 0;
3151            mOrientedRanges.tilt.max = M_PI_2;
3152            mOrientedRanges.tilt.flat = 0;
3153            mOrientedRanges.tilt.fuzz = 0;
3154            mOrientedRanges.tilt.resolution = 0;
3155        }
3156
3157        // Orientation
3158        mOrientationScale = 0;
3159        if (mHaveTilt) {
3160            mOrientedRanges.haveOrientation = true;
3161
3162            mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
3163            mOrientedRanges.orientation.source = mSource;
3164            mOrientedRanges.orientation.min = -M_PI;
3165            mOrientedRanges.orientation.max = M_PI;
3166            mOrientedRanges.orientation.flat = 0;
3167            mOrientedRanges.orientation.fuzz = 0;
3168            mOrientedRanges.orientation.resolution = 0;
3169        } else if (mCalibration.orientationCalibration !=
3170                Calibration::ORIENTATION_CALIBRATION_NONE) {
3171            if (mCalibration.orientationCalibration
3172                    == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
3173                if (mRawPointerAxes.orientation.valid) {
3174                    if (mRawPointerAxes.orientation.maxValue > 0) {
3175                        mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue;
3176                    } else if (mRawPointerAxes.orientation.minValue < 0) {
3177                        mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue;
3178                    } else {
3179                        mOrientationScale = 0;
3180                    }
3181                }
3182            }
3183
3184            mOrientedRanges.haveOrientation = true;
3185
3186            mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
3187            mOrientedRanges.orientation.source = mSource;
3188            mOrientedRanges.orientation.min = -M_PI_2;
3189            mOrientedRanges.orientation.max = M_PI_2;
3190            mOrientedRanges.orientation.flat = 0;
3191            mOrientedRanges.orientation.fuzz = 0;
3192            mOrientedRanges.orientation.resolution = 0;
3193        }
3194
3195        // Distance
3196        mDistanceScale = 0;
3197        if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) {
3198            if (mCalibration.distanceCalibration
3199                    == Calibration::DISTANCE_CALIBRATION_SCALED) {
3200                if (mCalibration.haveDistanceScale) {
3201                    mDistanceScale = mCalibration.distanceScale;
3202                } else {
3203                    mDistanceScale = 1.0f;
3204                }
3205            }
3206
3207            mOrientedRanges.haveDistance = true;
3208
3209            mOrientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE;
3210            mOrientedRanges.distance.source = mSource;
3211            mOrientedRanges.distance.min =
3212                    mRawPointerAxes.distance.minValue * mDistanceScale;
3213            mOrientedRanges.distance.max =
3214                    mRawPointerAxes.distance.maxValue * mDistanceScale;
3215            mOrientedRanges.distance.flat = 0;
3216            mOrientedRanges.distance.fuzz =
3217                    mRawPointerAxes.distance.fuzz * mDistanceScale;
3218            mOrientedRanges.distance.resolution = 0;
3219        }
3220
3221        // Compute oriented precision, scales and ranges.
3222        // Note that the maximum value reported is an inclusive maximum value so it is one
3223        // unit less than the total width or height of surface.
3224        switch (mSurfaceOrientation) {
3225        case DISPLAY_ORIENTATION_90:
3226        case DISPLAY_ORIENTATION_270:
3227            mOrientedXPrecision = mYPrecision;
3228            mOrientedYPrecision = mXPrecision;
3229
3230            mOrientedRanges.x.min = mYTranslate;
3231            mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1;
3232            mOrientedRanges.x.flat = 0;
3233            mOrientedRanges.x.fuzz = 0;
3234            mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mYScale;
3235
3236            mOrientedRanges.y.min = mXTranslate;
3237            mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1;
3238            mOrientedRanges.y.flat = 0;
3239            mOrientedRanges.y.fuzz = 0;
3240            mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mXScale;
3241            break;
3242
3243        default:
3244            mOrientedXPrecision = mXPrecision;
3245            mOrientedYPrecision = mYPrecision;
3246
3247            mOrientedRanges.x.min = mXTranslate;
3248            mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1;
3249            mOrientedRanges.x.flat = 0;
3250            mOrientedRanges.x.fuzz = 0;
3251            mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mXScale;
3252
3253            mOrientedRanges.y.min = mYTranslate;
3254            mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1;
3255            mOrientedRanges.y.flat = 0;
3256            mOrientedRanges.y.fuzz = 0;
3257            mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale;
3258            break;
3259        }
3260
3261        if (mDeviceMode == DEVICE_MODE_POINTER) {
3262            // Compute pointer gesture detection parameters.
3263            float rawDiagonal = hypotf(rawWidth, rawHeight);
3264            float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight);
3265
3266            // Scale movements such that one whole swipe of the touch pad covers a
3267            // given area relative to the diagonal size of the display when no acceleration
3268            // is applied.
3269            // Assume that the touch pad has a square aspect ratio such that movements in
3270            // X and Y of the same number of raw units cover the same physical distance.
3271            mPointerXMovementScale = mConfig.pointerGestureMovementSpeedRatio
3272                    * displayDiagonal / rawDiagonal;
3273            mPointerYMovementScale = mPointerXMovementScale;
3274
3275            // Scale zooms to cover a smaller range of the display than movements do.
3276            // This value determines the area around the pointer that is affected by freeform
3277            // pointer gestures.
3278            mPointerXZoomScale = mConfig.pointerGestureZoomSpeedRatio
3279                    * displayDiagonal / rawDiagonal;
3280            mPointerYZoomScale = mPointerXZoomScale;
3281
3282            // Max width between pointers to detect a swipe gesture is more than some fraction
3283            // of the diagonal axis of the touch pad.  Touches that are wider than this are
3284            // translated into freeform gestures.
3285            mPointerGestureMaxSwipeWidth =
3286                    mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
3287
3288            // Abort current pointer usages because the state has changed.
3289            abortPointerUsage(when, 0 /*policyFlags*/);
3290        }
3291
3292        // Inform the dispatcher about the changes.
3293        *outResetNeeded = true;
3294        bumpGeneration();
3295    }
3296}
3297
3298void TouchInputMapper::dumpSurface(String8& dump) {
3299    dump.appendFormat(INDENT3 "Viewport: displayId=%d, orientation=%d, "
3300            "logicalFrame=[%d, %d, %d, %d], "
3301            "physicalFrame=[%d, %d, %d, %d], "
3302            "deviceSize=[%d, %d]\n",
3303            mViewport.displayId, mViewport.orientation,
3304            mViewport.logicalLeft, mViewport.logicalTop,
3305            mViewport.logicalRight, mViewport.logicalBottom,
3306            mViewport.physicalLeft, mViewport.physicalTop,
3307            mViewport.physicalRight, mViewport.physicalBottom,
3308            mViewport.deviceWidth, mViewport.deviceHeight);
3309
3310    dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
3311    dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
3312    dump.appendFormat(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
3313    dump.appendFormat(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
3314    dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
3315}
3316
3317void TouchInputMapper::configureVirtualKeys() {
3318    Vector<VirtualKeyDefinition> virtualKeyDefinitions;
3319    getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
3320
3321    mVirtualKeys.clear();
3322
3323    if (virtualKeyDefinitions.size() == 0) {
3324        return;
3325    }
3326
3327    mVirtualKeys.setCapacity(virtualKeyDefinitions.size());
3328
3329    int32_t touchScreenLeft = mRawPointerAxes.x.minValue;
3330    int32_t touchScreenTop = mRawPointerAxes.y.minValue;
3331    int32_t touchScreenWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
3332    int32_t touchScreenHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
3333
3334    for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
3335        const VirtualKeyDefinition& virtualKeyDefinition =
3336                virtualKeyDefinitions[i];
3337
3338        mVirtualKeys.add();
3339        VirtualKey& virtualKey = mVirtualKeys.editTop();
3340
3341        virtualKey.scanCode = virtualKeyDefinition.scanCode;
3342        int32_t keyCode;
3343        uint32_t flags;
3344        if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, 0, &keyCode, &flags)) {
3345            ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
3346                    virtualKey.scanCode);
3347            mVirtualKeys.pop(); // drop the key
3348            continue;
3349        }
3350
3351        virtualKey.keyCode = keyCode;
3352        virtualKey.flags = flags;
3353
3354        // convert the key definition's display coordinates into touch coordinates for a hit box
3355        int32_t halfWidth = virtualKeyDefinition.width / 2;
3356        int32_t halfHeight = virtualKeyDefinition.height / 2;
3357
3358        virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
3359                * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
3360        virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
3361                * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
3362        virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
3363                * touchScreenHeight / mSurfaceHeight + touchScreenTop;
3364        virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
3365                * touchScreenHeight / mSurfaceHeight + touchScreenTop;
3366    }
3367}
3368
3369void TouchInputMapper::dumpVirtualKeys(String8& dump) {
3370    if (!mVirtualKeys.isEmpty()) {
3371        dump.append(INDENT3 "Virtual Keys:\n");
3372
3373        for (size_t i = 0; i < mVirtualKeys.size(); i++) {
3374            const VirtualKey& virtualKey = mVirtualKeys.itemAt(i);
3375            dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
3376                    "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
3377                    i, virtualKey.scanCode, virtualKey.keyCode,
3378                    virtualKey.hitLeft, virtualKey.hitRight,
3379                    virtualKey.hitTop, virtualKey.hitBottom);
3380        }
3381    }
3382}
3383
3384void TouchInputMapper::parseCalibration() {
3385    const PropertyMap& in = getDevice()->getConfiguration();
3386    Calibration& out = mCalibration;
3387
3388    // Size
3389    out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
3390    String8 sizeCalibrationString;
3391    if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
3392        if (sizeCalibrationString == "none") {
3393            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
3394        } else if (sizeCalibrationString == "geometric") {
3395            out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
3396        } else if (sizeCalibrationString == "diameter") {
3397            out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER;
3398        } else if (sizeCalibrationString == "box") {
3399            out.sizeCalibration = Calibration::SIZE_CALIBRATION_BOX;
3400        } else if (sizeCalibrationString == "area") {
3401            out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA;
3402        } else if (sizeCalibrationString != "default") {
3403            ALOGW("Invalid value for touch.size.calibration: '%s'",
3404                    sizeCalibrationString.string());
3405        }
3406    }
3407
3408    out.haveSizeScale = in.tryGetProperty(String8("touch.size.scale"),
3409            out.sizeScale);
3410    out.haveSizeBias = in.tryGetProperty(String8("touch.size.bias"),
3411            out.sizeBias);
3412    out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"),
3413            out.sizeIsSummed);
3414
3415    // Pressure
3416    out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
3417    String8 pressureCalibrationString;
3418    if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
3419        if (pressureCalibrationString == "none") {
3420            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
3421        } else if (pressureCalibrationString == "physical") {
3422            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
3423        } else if (pressureCalibrationString == "amplitude") {
3424            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
3425        } else if (pressureCalibrationString != "default") {
3426            ALOGW("Invalid value for touch.pressure.calibration: '%s'",
3427                    pressureCalibrationString.string());
3428        }
3429    }
3430
3431    out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
3432            out.pressureScale);
3433
3434    // Orientation
3435    out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
3436    String8 orientationCalibrationString;
3437    if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
3438        if (orientationCalibrationString == "none") {
3439            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
3440        } else if (orientationCalibrationString == "interpolated") {
3441            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
3442        } else if (orientationCalibrationString == "vector") {
3443            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
3444        } else if (orientationCalibrationString != "default") {
3445            ALOGW("Invalid value for touch.orientation.calibration: '%s'",
3446                    orientationCalibrationString.string());
3447        }
3448    }
3449
3450    // Distance
3451    out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT;
3452    String8 distanceCalibrationString;
3453    if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
3454        if (distanceCalibrationString == "none") {
3455            out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
3456        } else if (distanceCalibrationString == "scaled") {
3457            out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
3458        } else if (distanceCalibrationString != "default") {
3459            ALOGW("Invalid value for touch.distance.calibration: '%s'",
3460                    distanceCalibrationString.string());
3461        }
3462    }
3463
3464    out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"),
3465            out.distanceScale);
3466
3467    out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_DEFAULT;
3468    String8 coverageCalibrationString;
3469    if (in.tryGetProperty(String8("touch.coverage.calibration"), coverageCalibrationString)) {
3470        if (coverageCalibrationString == "none") {
3471            out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
3472        } else if (coverageCalibrationString == "box") {
3473            out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_BOX;
3474        } else if (coverageCalibrationString != "default") {
3475            ALOGW("Invalid value for touch.coverage.calibration: '%s'",
3476                    coverageCalibrationString.string());
3477        }
3478    }
3479}
3480
3481void TouchInputMapper::resolveCalibration() {
3482    // Size
3483    if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) {
3484        if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DEFAULT) {
3485            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
3486        }
3487    } else {
3488        mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
3489    }
3490
3491    // Pressure
3492    if (mRawPointerAxes.pressure.valid) {
3493        if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DEFAULT) {
3494            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
3495        }
3496    } else {
3497        mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
3498    }
3499
3500    // Orientation
3501    if (mRawPointerAxes.orientation.valid) {
3502        if (mCalibration.orientationCalibration == Calibration::ORIENTATION_CALIBRATION_DEFAULT) {
3503            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
3504        }
3505    } else {
3506        mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
3507    }
3508
3509    // Distance
3510    if (mRawPointerAxes.distance.valid) {
3511        if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_DEFAULT) {
3512            mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
3513        }
3514    } else {
3515        mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
3516    }
3517
3518    // Coverage
3519    if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_DEFAULT) {
3520        mCalibration.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
3521    }
3522}
3523
3524void TouchInputMapper::dumpCalibration(String8& dump) {
3525    dump.append(INDENT3 "Calibration:\n");
3526
3527    // Size
3528    switch (mCalibration.sizeCalibration) {
3529    case Calibration::SIZE_CALIBRATION_NONE:
3530        dump.append(INDENT4 "touch.size.calibration: none\n");
3531        break;
3532    case Calibration::SIZE_CALIBRATION_GEOMETRIC:
3533        dump.append(INDENT4 "touch.size.calibration: geometric\n");
3534        break;
3535    case Calibration::SIZE_CALIBRATION_DIAMETER:
3536        dump.append(INDENT4 "touch.size.calibration: diameter\n");
3537        break;
3538    case Calibration::SIZE_CALIBRATION_BOX:
3539        dump.append(INDENT4 "touch.size.calibration: box\n");
3540        break;
3541    case Calibration::SIZE_CALIBRATION_AREA:
3542        dump.append(INDENT4 "touch.size.calibration: area\n");
3543        break;
3544    default:
3545        ALOG_ASSERT(false);
3546    }
3547
3548    if (mCalibration.haveSizeScale) {
3549        dump.appendFormat(INDENT4 "touch.size.scale: %0.3f\n",
3550                mCalibration.sizeScale);
3551    }
3552
3553    if (mCalibration.haveSizeBias) {
3554        dump.appendFormat(INDENT4 "touch.size.bias: %0.3f\n",
3555                mCalibration.sizeBias);
3556    }
3557
3558    if (mCalibration.haveSizeIsSummed) {
3559        dump.appendFormat(INDENT4 "touch.size.isSummed: %s\n",
3560                toString(mCalibration.sizeIsSummed));
3561    }
3562
3563    // Pressure
3564    switch (mCalibration.pressureCalibration) {
3565    case Calibration::PRESSURE_CALIBRATION_NONE:
3566        dump.append(INDENT4 "touch.pressure.calibration: none\n");
3567        break;
3568    case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
3569        dump.append(INDENT4 "touch.pressure.calibration: physical\n");
3570        break;
3571    case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
3572        dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
3573        break;
3574    default:
3575        ALOG_ASSERT(false);
3576    }
3577
3578    if (mCalibration.havePressureScale) {
3579        dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
3580                mCalibration.pressureScale);
3581    }
3582
3583    // Orientation
3584    switch (mCalibration.orientationCalibration) {
3585    case Calibration::ORIENTATION_CALIBRATION_NONE:
3586        dump.append(INDENT4 "touch.orientation.calibration: none\n");
3587        break;
3588    case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
3589        dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
3590        break;
3591    case Calibration::ORIENTATION_CALIBRATION_VECTOR:
3592        dump.append(INDENT4 "touch.orientation.calibration: vector\n");
3593        break;
3594    default:
3595        ALOG_ASSERT(false);
3596    }
3597
3598    // Distance
3599    switch (mCalibration.distanceCalibration) {
3600    case Calibration::DISTANCE_CALIBRATION_NONE:
3601        dump.append(INDENT4 "touch.distance.calibration: none\n");
3602        break;
3603    case Calibration::DISTANCE_CALIBRATION_SCALED:
3604        dump.append(INDENT4 "touch.distance.calibration: scaled\n");
3605        break;
3606    default:
3607        ALOG_ASSERT(false);
3608    }
3609
3610    if (mCalibration.haveDistanceScale) {
3611        dump.appendFormat(INDENT4 "touch.distance.scale: %0.3f\n",
3612                mCalibration.distanceScale);
3613    }
3614
3615    switch (mCalibration.coverageCalibration) {
3616    case Calibration::COVERAGE_CALIBRATION_NONE:
3617        dump.append(INDENT4 "touch.coverage.calibration: none\n");
3618        break;
3619    case Calibration::COVERAGE_CALIBRATION_BOX:
3620        dump.append(INDENT4 "touch.coverage.calibration: box\n");
3621        break;
3622    default:
3623        ALOG_ASSERT(false);
3624    }
3625}
3626
3627void TouchInputMapper::reset(nsecs_t when) {
3628    mCursorButtonAccumulator.reset(getDevice());
3629    mCursorScrollAccumulator.reset(getDevice());
3630    mTouchButtonAccumulator.reset(getDevice());
3631
3632    mPointerVelocityControl.reset();
3633    mWheelXVelocityControl.reset();
3634    mWheelYVelocityControl.reset();
3635
3636    mCurrentRawPointerData.clear();
3637    mLastRawPointerData.clear();
3638    mCurrentCookedPointerData.clear();
3639    mLastCookedPointerData.clear();
3640    mCurrentButtonState = 0;
3641    mLastButtonState = 0;
3642    mCurrentRawVScroll = 0;
3643    mCurrentRawHScroll = 0;
3644    mCurrentFingerIdBits.clear();
3645    mLastFingerIdBits.clear();
3646    mCurrentStylusIdBits.clear();
3647    mLastStylusIdBits.clear();
3648    mCurrentMouseIdBits.clear();
3649    mLastMouseIdBits.clear();
3650    mPointerUsage = POINTER_USAGE_NONE;
3651    mSentHoverEnter = false;
3652    mDownTime = 0;
3653
3654    mCurrentVirtualKey.down = false;
3655
3656    mPointerGesture.reset();
3657    mPointerSimple.reset();
3658
3659    if (mPointerController != NULL) {
3660        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
3661        mPointerController->clearSpots();
3662    }
3663
3664    InputMapper::reset(when);
3665}
3666
3667void TouchInputMapper::process(const RawEvent* rawEvent) {
3668    mCursorButtonAccumulator.process(rawEvent);
3669    mCursorScrollAccumulator.process(rawEvent);
3670    mTouchButtonAccumulator.process(rawEvent);
3671
3672    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
3673        sync(rawEvent->when);
3674    }
3675}
3676
3677void TouchInputMapper::sync(nsecs_t when) {
3678    // Sync button state.
3679    mCurrentButtonState = mTouchButtonAccumulator.getButtonState()
3680            | mCursorButtonAccumulator.getButtonState();
3681
3682    // Sync scroll state.
3683    mCurrentRawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
3684    mCurrentRawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
3685    mCursorScrollAccumulator.finishSync();
3686
3687    // Sync touch state.
3688    bool havePointerIds = true;
3689    mCurrentRawPointerData.clear();
3690    syncTouch(when, &havePointerIds);
3691
3692#if DEBUG_RAW_EVENTS
3693    if (!havePointerIds) {
3694        ALOGD("syncTouch: pointerCount %d -> %d, no pointer ids",
3695                mLastRawPointerData.pointerCount,
3696                mCurrentRawPointerData.pointerCount);
3697    } else {
3698        ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
3699                "hovering ids 0x%08x -> 0x%08x",
3700                mLastRawPointerData.pointerCount,
3701                mCurrentRawPointerData.pointerCount,
3702                mLastRawPointerData.touchingIdBits.value,
3703                mCurrentRawPointerData.touchingIdBits.value,
3704                mLastRawPointerData.hoveringIdBits.value,
3705                mCurrentRawPointerData.hoveringIdBits.value);
3706    }
3707#endif
3708
3709    // Reset state that we will compute below.
3710    mCurrentFingerIdBits.clear();
3711    mCurrentStylusIdBits.clear();
3712    mCurrentMouseIdBits.clear();
3713    mCurrentCookedPointerData.clear();
3714
3715    if (mDeviceMode == DEVICE_MODE_DISABLED) {
3716        // Drop all input if the device is disabled.
3717        mCurrentRawPointerData.clear();
3718        mCurrentButtonState = 0;
3719    } else {
3720        // Preprocess pointer data.
3721        if (!havePointerIds) {
3722            assignPointerIds();
3723        }
3724
3725        // Handle policy on initial down or hover events.
3726        uint32_t policyFlags = 0;
3727        bool initialDown = mLastRawPointerData.pointerCount == 0
3728                && mCurrentRawPointerData.pointerCount != 0;
3729        bool buttonsPressed = mCurrentButtonState & ~mLastButtonState;
3730        if (initialDown || buttonsPressed) {
3731            // If this is a touch screen, hide the pointer on an initial down.
3732            if (mDeviceMode == DEVICE_MODE_DIRECT) {
3733                getContext()->fadePointer();
3734            }
3735
3736            // Initial downs on external touch devices should wake the device.
3737            // We don't do this for internal touch screens to prevent them from waking
3738            // up in your pocket.
3739            // TODO: Use the input device configuration to control this behavior more finely.
3740            if (getDevice()->isExternal()) {
3741                policyFlags |= POLICY_FLAG_WAKE_DROPPED;
3742            }
3743        }
3744
3745        // Synthesize key down from raw buttons if needed.
3746        synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
3747                policyFlags, mLastButtonState, mCurrentButtonState);
3748
3749        // Consume raw off-screen touches before cooking pointer data.
3750        // If touches are consumed, subsequent code will not receive any pointer data.
3751        if (consumeRawTouches(when, policyFlags)) {
3752            mCurrentRawPointerData.clear();
3753        }
3754
3755        // Cook pointer data.  This call populates the mCurrentCookedPointerData structure
3756        // with cooked pointer data that has the same ids and indices as the raw data.
3757        // The following code can use either the raw or cooked data, as needed.
3758        cookPointerData();
3759
3760        // Dispatch the touches either directly or by translation through a pointer on screen.
3761        if (mDeviceMode == DEVICE_MODE_POINTER) {
3762            for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); !idBits.isEmpty(); ) {
3763                uint32_t id = idBits.clearFirstMarkedBit();
3764                const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
3765                if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
3766                        || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
3767                    mCurrentStylusIdBits.markBit(id);
3768                } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
3769                        || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
3770                    mCurrentFingerIdBits.markBit(id);
3771                } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
3772                    mCurrentMouseIdBits.markBit(id);
3773                }
3774            }
3775            for (BitSet32 idBits(mCurrentRawPointerData.hoveringIdBits); !idBits.isEmpty(); ) {
3776                uint32_t id = idBits.clearFirstMarkedBit();
3777                const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
3778                if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
3779                        || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
3780                    mCurrentStylusIdBits.markBit(id);
3781                }
3782            }
3783
3784            // Stylus takes precedence over all tools, then mouse, then finger.
3785            PointerUsage pointerUsage = mPointerUsage;
3786            if (!mCurrentStylusIdBits.isEmpty()) {
3787                mCurrentMouseIdBits.clear();
3788                mCurrentFingerIdBits.clear();
3789                pointerUsage = POINTER_USAGE_STYLUS;
3790            } else if (!mCurrentMouseIdBits.isEmpty()) {
3791                mCurrentFingerIdBits.clear();
3792                pointerUsage = POINTER_USAGE_MOUSE;
3793            } else if (!mCurrentFingerIdBits.isEmpty() || isPointerDown(mCurrentButtonState)) {
3794                pointerUsage = POINTER_USAGE_GESTURES;
3795            }
3796
3797            dispatchPointerUsage(when, policyFlags, pointerUsage);
3798        } else {
3799            if (mDeviceMode == DEVICE_MODE_DIRECT
3800                    && mConfig.showTouches && mPointerController != NULL) {
3801                mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
3802                mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
3803
3804                mPointerController->setButtonState(mCurrentButtonState);
3805                mPointerController->setSpots(mCurrentCookedPointerData.pointerCoords,
3806                        mCurrentCookedPointerData.idToIndex,
3807                        mCurrentCookedPointerData.touchingIdBits);
3808            }
3809
3810            dispatchHoverExit(when, policyFlags);
3811            dispatchTouches(when, policyFlags);
3812            dispatchHoverEnterAndMove(when, policyFlags);
3813        }
3814
3815        // Synthesize key up from raw buttons if needed.
3816        synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
3817                policyFlags, mLastButtonState, mCurrentButtonState);
3818    }
3819
3820    // Copy current touch to last touch in preparation for the next cycle.
3821    mLastRawPointerData.copyFrom(mCurrentRawPointerData);
3822    mLastCookedPointerData.copyFrom(mCurrentCookedPointerData);
3823    mLastButtonState = mCurrentButtonState;
3824    mLastFingerIdBits = mCurrentFingerIdBits;
3825    mLastStylusIdBits = mCurrentStylusIdBits;
3826    mLastMouseIdBits = mCurrentMouseIdBits;
3827
3828    // Clear some transient state.
3829    mCurrentRawVScroll = 0;
3830    mCurrentRawHScroll = 0;
3831}
3832
3833void TouchInputMapper::timeoutExpired(nsecs_t when) {
3834    if (mDeviceMode == DEVICE_MODE_POINTER) {
3835        if (mPointerUsage == POINTER_USAGE_GESTURES) {
3836            dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
3837        }
3838    }
3839}
3840
3841bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) {
3842    // Check for release of a virtual key.
3843    if (mCurrentVirtualKey.down) {
3844        if (mCurrentRawPointerData.touchingIdBits.isEmpty()) {
3845            // Pointer went up while virtual key was down.
3846            mCurrentVirtualKey.down = false;
3847            if (!mCurrentVirtualKey.ignored) {
3848#if DEBUG_VIRTUAL_KEYS
3849                ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
3850                        mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
3851#endif
3852                dispatchVirtualKey(when, policyFlags,
3853                        AKEY_EVENT_ACTION_UP,
3854                        AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
3855            }
3856            return true;
3857        }
3858
3859        if (mCurrentRawPointerData.touchingIdBits.count() == 1) {
3860            uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit();
3861            const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
3862            const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
3863            if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) {
3864                // Pointer is still within the space of the virtual key.
3865                return true;
3866            }
3867        }
3868
3869        // Pointer left virtual key area or another pointer also went down.
3870        // Send key cancellation but do not consume the touch yet.
3871        // This is useful when the user swipes through from the virtual key area
3872        // into the main display surface.
3873        mCurrentVirtualKey.down = false;
3874        if (!mCurrentVirtualKey.ignored) {
3875#if DEBUG_VIRTUAL_KEYS
3876            ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
3877                    mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
3878#endif
3879            dispatchVirtualKey(when, policyFlags,
3880                    AKEY_EVENT_ACTION_UP,
3881                    AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
3882                            | AKEY_EVENT_FLAG_CANCELED);
3883        }
3884    }
3885
3886    if (mLastRawPointerData.touchingIdBits.isEmpty()
3887            && !mCurrentRawPointerData.touchingIdBits.isEmpty()) {
3888        // Pointer just went down.  Check for virtual key press or off-screen touches.
3889        uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit();
3890        const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
3891        if (!isPointInsideSurface(pointer.x, pointer.y)) {
3892            // If exactly one pointer went down, check for virtual key hit.
3893            // Otherwise we will drop the entire stroke.
3894            if (mCurrentRawPointerData.touchingIdBits.count() == 1) {
3895                const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
3896                if (virtualKey) {
3897                    mCurrentVirtualKey.down = true;
3898                    mCurrentVirtualKey.downTime = when;
3899                    mCurrentVirtualKey.keyCode = virtualKey->keyCode;
3900                    mCurrentVirtualKey.scanCode = virtualKey->scanCode;
3901                    mCurrentVirtualKey.ignored = mContext->shouldDropVirtualKey(
3902                            when, getDevice(), virtualKey->keyCode, virtualKey->scanCode);
3903
3904                    if (!mCurrentVirtualKey.ignored) {
3905#if DEBUG_VIRTUAL_KEYS
3906                        ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
3907                                mCurrentVirtualKey.keyCode,
3908                                mCurrentVirtualKey.scanCode);
3909#endif
3910                        dispatchVirtualKey(when, policyFlags,
3911                                AKEY_EVENT_ACTION_DOWN,
3912                                AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
3913                    }
3914                }
3915            }
3916            return true;
3917        }
3918    }
3919
3920    // Disable all virtual key touches that happen within a short time interval of the
3921    // most recent touch within the screen area.  The idea is to filter out stray
3922    // virtual key presses when interacting with the touch screen.
3923    //
3924    // Problems we're trying to solve:
3925    //
3926    // 1. While scrolling a list or dragging the window shade, the user swipes down into a
3927    //    virtual key area that is implemented by a separate touch panel and accidentally
3928    //    triggers a virtual key.
3929    //
3930    // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
3931    //    area and accidentally triggers a virtual key.  This often happens when virtual keys
3932    //    are layed out below the screen near to where the on screen keyboard's space bar
3933    //    is displayed.
3934    if (mConfig.virtualKeyQuietTime > 0 && !mCurrentRawPointerData.touchingIdBits.isEmpty()) {
3935        mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime);
3936    }
3937    return false;
3938}
3939
3940void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
3941        int32_t keyEventAction, int32_t keyEventFlags) {
3942    int32_t keyCode = mCurrentVirtualKey.keyCode;
3943    int32_t scanCode = mCurrentVirtualKey.scanCode;
3944    nsecs_t downTime = mCurrentVirtualKey.downTime;
3945    int32_t metaState = mContext->getGlobalMetaState();
3946    policyFlags |= POLICY_FLAG_VIRTUAL;
3947
3948    NotifyKeyArgs args(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
3949            keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
3950    getListener()->notifyKey(&args);
3951}
3952
3953void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
3954    BitSet32 currentIdBits = mCurrentCookedPointerData.touchingIdBits;
3955    BitSet32 lastIdBits = mLastCookedPointerData.touchingIdBits;
3956    int32_t metaState = getContext()->getGlobalMetaState();
3957    int32_t buttonState = mCurrentButtonState;
3958
3959    if (currentIdBits == lastIdBits) {
3960        if (!currentIdBits.isEmpty()) {
3961            // No pointer id changes so this is a move event.
3962            // The listener takes care of batching moves so we don't have to deal with that here.
3963            dispatchMotion(when, policyFlags, mSource,
3964                    AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState,
3965                    AMOTION_EVENT_EDGE_FLAG_NONE,
3966                    mCurrentCookedPointerData.pointerProperties,
3967                    mCurrentCookedPointerData.pointerCoords,
3968                    mCurrentCookedPointerData.idToIndex,
3969                    currentIdBits, -1,
3970                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
3971        }
3972    } else {
3973        // There may be pointers going up and pointers going down and pointers moving
3974        // all at the same time.
3975        BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
3976        BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
3977        BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
3978        BitSet32 dispatchedIdBits(lastIdBits.value);
3979
3980        // Update last coordinates of pointers that have moved so that we observe the new
3981        // pointer positions at the same time as other pointers that have just gone up.
3982        bool moveNeeded = updateMovedPointers(
3983                mCurrentCookedPointerData.pointerProperties,
3984                mCurrentCookedPointerData.pointerCoords,
3985                mCurrentCookedPointerData.idToIndex,
3986                mLastCookedPointerData.pointerProperties,
3987                mLastCookedPointerData.pointerCoords,
3988                mLastCookedPointerData.idToIndex,
3989                moveIdBits);
3990        if (buttonState != mLastButtonState) {
3991            moveNeeded = true;
3992        }
3993
3994        // Dispatch pointer up events.
3995        while (!upIdBits.isEmpty()) {
3996            uint32_t upId = upIdBits.clearFirstMarkedBit();
3997
3998            dispatchMotion(when, policyFlags, mSource,
3999                    AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0,
4000                    mLastCookedPointerData.pointerProperties,
4001                    mLastCookedPointerData.pointerCoords,
4002                    mLastCookedPointerData.idToIndex,
4003                    dispatchedIdBits, upId,
4004                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4005            dispatchedIdBits.clearBit(upId);
4006        }
4007
4008        // Dispatch move events if any of the remaining pointers moved from their old locations.
4009        // Although applications receive new locations as part of individual pointer up
4010        // events, they do not generally handle them except when presented in a move event.
4011        if (moveNeeded) {
4012            ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
4013            dispatchMotion(when, policyFlags, mSource,
4014                    AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0,
4015                    mCurrentCookedPointerData.pointerProperties,
4016                    mCurrentCookedPointerData.pointerCoords,
4017                    mCurrentCookedPointerData.idToIndex,
4018                    dispatchedIdBits, -1,
4019                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4020        }
4021
4022        // Dispatch pointer down events using the new pointer locations.
4023        while (!downIdBits.isEmpty()) {
4024            uint32_t downId = downIdBits.clearFirstMarkedBit();
4025            dispatchedIdBits.markBit(downId);
4026
4027            if (dispatchedIdBits.count() == 1) {
4028                // First pointer is going down.  Set down time.
4029                mDownTime = when;
4030            }
4031
4032            dispatchMotion(when, policyFlags, mSource,
4033                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
4034                    mCurrentCookedPointerData.pointerProperties,
4035                    mCurrentCookedPointerData.pointerCoords,
4036                    mCurrentCookedPointerData.idToIndex,
4037                    dispatchedIdBits, downId,
4038                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4039        }
4040    }
4041}
4042
4043void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) {
4044    if (mSentHoverEnter &&
4045            (mCurrentCookedPointerData.hoveringIdBits.isEmpty()
4046                    || !mCurrentCookedPointerData.touchingIdBits.isEmpty())) {
4047        int32_t metaState = getContext()->getGlobalMetaState();
4048        dispatchMotion(when, policyFlags, mSource,
4049                AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
4050                mLastCookedPointerData.pointerProperties,
4051                mLastCookedPointerData.pointerCoords,
4052                mLastCookedPointerData.idToIndex,
4053                mLastCookedPointerData.hoveringIdBits, -1,
4054                mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4055        mSentHoverEnter = false;
4056    }
4057}
4058
4059void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) {
4060    if (mCurrentCookedPointerData.touchingIdBits.isEmpty()
4061            && !mCurrentCookedPointerData.hoveringIdBits.isEmpty()) {
4062        int32_t metaState = getContext()->getGlobalMetaState();
4063        if (!mSentHoverEnter) {
4064            dispatchMotion(when, policyFlags, mSource,
4065                    AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
4066                    mCurrentCookedPointerData.pointerProperties,
4067                    mCurrentCookedPointerData.pointerCoords,
4068                    mCurrentCookedPointerData.idToIndex,
4069                    mCurrentCookedPointerData.hoveringIdBits, -1,
4070                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4071            mSentHoverEnter = true;
4072        }
4073
4074        dispatchMotion(when, policyFlags, mSource,
4075                AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
4076                mCurrentCookedPointerData.pointerProperties,
4077                mCurrentCookedPointerData.pointerCoords,
4078                mCurrentCookedPointerData.idToIndex,
4079                mCurrentCookedPointerData.hoveringIdBits, -1,
4080                mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4081    }
4082}
4083
4084void TouchInputMapper::cookPointerData() {
4085    uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount;
4086
4087    mCurrentCookedPointerData.clear();
4088    mCurrentCookedPointerData.pointerCount = currentPointerCount;
4089    mCurrentCookedPointerData.hoveringIdBits = mCurrentRawPointerData.hoveringIdBits;
4090    mCurrentCookedPointerData.touchingIdBits = mCurrentRawPointerData.touchingIdBits;
4091
4092    // Walk through the the active pointers and map device coordinates onto
4093    // surface coordinates and adjust for display orientation.
4094    for (uint32_t i = 0; i < currentPointerCount; i++) {
4095        const RawPointerData::Pointer& in = mCurrentRawPointerData.pointers[i];
4096
4097        // Size
4098        float touchMajor, touchMinor, toolMajor, toolMinor, size;
4099        switch (mCalibration.sizeCalibration) {
4100        case Calibration::SIZE_CALIBRATION_GEOMETRIC:
4101        case Calibration::SIZE_CALIBRATION_DIAMETER:
4102        case Calibration::SIZE_CALIBRATION_BOX:
4103        case Calibration::SIZE_CALIBRATION_AREA:
4104            if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
4105                touchMajor = in.touchMajor;
4106                touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
4107                toolMajor = in.toolMajor;
4108                toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
4109                size = mRawPointerAxes.touchMinor.valid
4110                        ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
4111            } else if (mRawPointerAxes.touchMajor.valid) {
4112                toolMajor = touchMajor = in.touchMajor;
4113                toolMinor = touchMinor = mRawPointerAxes.touchMinor.valid
4114                        ? in.touchMinor : in.touchMajor;
4115                size = mRawPointerAxes.touchMinor.valid
4116                        ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
4117            } else if (mRawPointerAxes.toolMajor.valid) {
4118                touchMajor = toolMajor = in.toolMajor;
4119                touchMinor = toolMinor = mRawPointerAxes.toolMinor.valid
4120                        ? in.toolMinor : in.toolMajor;
4121                size = mRawPointerAxes.toolMinor.valid
4122                        ? avg(in.toolMajor, in.toolMinor) : in.toolMajor;
4123            } else {
4124                ALOG_ASSERT(false, "No touch or tool axes.  "
4125                        "Size calibration should have been resolved to NONE.");
4126                touchMajor = 0;
4127                touchMinor = 0;
4128                toolMajor = 0;
4129                toolMinor = 0;
4130                size = 0;
4131            }
4132
4133            if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) {
4134                uint32_t touchingCount = mCurrentRawPointerData.touchingIdBits.count();
4135                if (touchingCount > 1) {
4136                    touchMajor /= touchingCount;
4137                    touchMinor /= touchingCount;
4138                    toolMajor /= touchingCount;
4139                    toolMinor /= touchingCount;
4140                    size /= touchingCount;
4141                }
4142            }
4143
4144            if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) {
4145                touchMajor *= mGeometricScale;
4146                touchMinor *= mGeometricScale;
4147                toolMajor *= mGeometricScale;
4148                toolMinor *= mGeometricScale;
4149            } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) {
4150                touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
4151                touchMinor = touchMajor;
4152                toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
4153                toolMinor = toolMajor;
4154            } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) {
4155                touchMinor = touchMajor;
4156                toolMinor = toolMajor;
4157            }
4158
4159            mCalibration.applySizeScaleAndBias(&touchMajor);
4160            mCalibration.applySizeScaleAndBias(&touchMinor);
4161            mCalibration.applySizeScaleAndBias(&toolMajor);
4162            mCalibration.applySizeScaleAndBias(&toolMinor);
4163            size *= mSizeScale;
4164            break;
4165        default:
4166            touchMajor = 0;
4167            touchMinor = 0;
4168            toolMajor = 0;
4169            toolMinor = 0;
4170            size = 0;
4171            break;
4172        }
4173
4174        // Pressure
4175        float pressure;
4176        switch (mCalibration.pressureCalibration) {
4177        case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
4178        case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
4179            pressure = in.pressure * mPressureScale;
4180            break;
4181        default:
4182            pressure = in.isHovering ? 0 : 1;
4183            break;
4184        }
4185
4186        // Tilt and Orientation
4187        float tilt;
4188        float orientation;
4189        if (mHaveTilt) {
4190            float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;
4191            float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;
4192            orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
4193            tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
4194        } else {
4195            tilt = 0;
4196
4197            switch (mCalibration.orientationCalibration) {
4198            case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
4199                orientation = in.orientation * mOrientationScale;
4200                break;
4201            case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
4202                int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
4203                int32_t c2 = signExtendNybble(in.orientation & 0x0f);
4204                if (c1 != 0 || c2 != 0) {
4205                    orientation = atan2f(c1, c2) * 0.5f;
4206                    float confidence = hypotf(c1, c2);
4207                    float scale = 1.0f + confidence / 16.0f;
4208                    touchMajor *= scale;
4209                    touchMinor /= scale;
4210                    toolMajor *= scale;
4211                    toolMinor /= scale;
4212                } else {
4213                    orientation = 0;
4214                }
4215                break;
4216            }
4217            default:
4218                orientation = 0;
4219            }
4220        }
4221
4222        // Distance
4223        float distance;
4224        switch (mCalibration.distanceCalibration) {
4225        case Calibration::DISTANCE_CALIBRATION_SCALED:
4226            distance = in.distance * mDistanceScale;
4227            break;
4228        default:
4229            distance = 0;
4230        }
4231
4232        // Coverage
4233        int32_t rawLeft, rawTop, rawRight, rawBottom;
4234        switch (mCalibration.coverageCalibration) {
4235        case Calibration::COVERAGE_CALIBRATION_BOX:
4236            rawLeft = (in.toolMinor & 0xffff0000) >> 16;
4237            rawRight = in.toolMinor & 0x0000ffff;
4238            rawBottom = in.toolMajor & 0x0000ffff;
4239            rawTop = (in.toolMajor & 0xffff0000) >> 16;
4240            break;
4241        default:
4242            rawLeft = rawTop = rawRight = rawBottom = 0;
4243            break;
4244        }
4245
4246        // X, Y, and the bounding box for coverage information
4247        // Adjust coords for surface orientation.
4248        float x, y, left, top, right, bottom;
4249        switch (mSurfaceOrientation) {
4250        case DISPLAY_ORIENTATION_90:
4251            x = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
4252            y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate;
4253            left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
4254            right = float(rawBottom- mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
4255            bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
4256            top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
4257            orientation -= M_PI_2;
4258            if (orientation < mOrientedRanges.orientation.min) {
4259                orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
4260            }
4261            break;
4262        case DISPLAY_ORIENTATION_180:
4263            x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate;
4264            y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate;
4265            left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
4266            right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
4267            bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
4268            top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
4269            orientation -= M_PI;
4270            if (orientation < mOrientedRanges.orientation.min) {
4271                orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
4272            }
4273            break;
4274        case DISPLAY_ORIENTATION_270:
4275            x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate;
4276            y = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
4277            left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
4278            right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
4279            bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
4280            top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
4281            orientation += M_PI_2;
4282            if (orientation > mOrientedRanges.orientation.max) {
4283                orientation -= (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
4284            }
4285            break;
4286        default:
4287            x = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
4288            y = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
4289            left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
4290            right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
4291            bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
4292            top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
4293            break;
4294        }
4295
4296        // Write output coords.
4297        PointerCoords& out = mCurrentCookedPointerData.pointerCoords[i];
4298        out.clear();
4299        out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
4300        out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
4301        out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
4302        out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
4303        out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
4304        out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
4305        out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
4306        out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
4307        out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
4308        if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
4309            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left);
4310            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top);
4311            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right);
4312            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_4, bottom);
4313        } else {
4314            out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
4315            out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
4316        }
4317
4318        // Write output properties.
4319        PointerProperties& properties = mCurrentCookedPointerData.pointerProperties[i];
4320        uint32_t id = in.id;
4321        properties.clear();
4322        properties.id = id;
4323        properties.toolType = in.toolType;
4324
4325        // Write id index.
4326        mCurrentCookedPointerData.idToIndex[id] = i;
4327    }
4328}
4329
4330void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags,
4331        PointerUsage pointerUsage) {
4332    if (pointerUsage != mPointerUsage) {
4333        abortPointerUsage(when, policyFlags);
4334        mPointerUsage = pointerUsage;
4335    }
4336
4337    switch (mPointerUsage) {
4338    case POINTER_USAGE_GESTURES:
4339        dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
4340        break;
4341    case POINTER_USAGE_STYLUS:
4342        dispatchPointerStylus(when, policyFlags);
4343        break;
4344    case POINTER_USAGE_MOUSE:
4345        dispatchPointerMouse(when, policyFlags);
4346        break;
4347    default:
4348        break;
4349    }
4350}
4351
4352void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) {
4353    switch (mPointerUsage) {
4354    case POINTER_USAGE_GESTURES:
4355        abortPointerGestures(when, policyFlags);
4356        break;
4357    case POINTER_USAGE_STYLUS:
4358        abortPointerStylus(when, policyFlags);
4359        break;
4360    case POINTER_USAGE_MOUSE:
4361        abortPointerMouse(when, policyFlags);
4362        break;
4363    default:
4364        break;
4365    }
4366
4367    mPointerUsage = POINTER_USAGE_NONE;
4368}
4369
4370void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
4371        bool isTimeout) {
4372    // Update current gesture coordinates.
4373    bool cancelPreviousGesture, finishPreviousGesture;
4374    bool sendEvents = preparePointerGestures(when,
4375            &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
4376    if (!sendEvents) {
4377        return;
4378    }
4379    if (finishPreviousGesture) {
4380        cancelPreviousGesture = false;
4381    }
4382
4383    // Update the pointer presentation and spots.
4384    if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
4385        mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
4386        if (finishPreviousGesture || cancelPreviousGesture) {
4387            mPointerController->clearSpots();
4388        }
4389        mPointerController->setSpots(mPointerGesture.currentGestureCoords,
4390                mPointerGesture.currentGestureIdToIndex,
4391                mPointerGesture.currentGestureIdBits);
4392    } else {
4393        mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
4394    }
4395
4396    // Show or hide the pointer if needed.
4397    switch (mPointerGesture.currentGestureMode) {
4398    case PointerGesture::NEUTRAL:
4399    case PointerGesture::QUIET:
4400        if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
4401                && (mPointerGesture.lastGestureMode == PointerGesture::SWIPE
4402                        || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)) {
4403            // Remind the user of where the pointer is after finishing a gesture with spots.
4404            mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
4405        }
4406        break;
4407    case PointerGesture::TAP:
4408    case PointerGesture::TAP_DRAG:
4409    case PointerGesture::BUTTON_CLICK_OR_DRAG:
4410    case PointerGesture::HOVER:
4411    case PointerGesture::PRESS:
4412        // Unfade the pointer when the current gesture manipulates the
4413        // area directly under the pointer.
4414        mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
4415        break;
4416    case PointerGesture::SWIPE:
4417    case PointerGesture::FREEFORM:
4418        // Fade the pointer when the current gesture manipulates a different
4419        // area and there are spots to guide the user experience.
4420        if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
4421            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
4422        } else {
4423            mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
4424        }
4425        break;
4426    }
4427
4428    // Send events!
4429    int32_t metaState = getContext()->getGlobalMetaState();
4430    int32_t buttonState = mCurrentButtonState;
4431
4432    // Update last coordinates of pointers that have moved so that we observe the new
4433    // pointer positions at the same time as other pointers that have just gone up.
4434    bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP
4435            || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG
4436            || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
4437            || mPointerGesture.currentGestureMode == PointerGesture::PRESS
4438            || mPointerGesture.currentGestureMode == PointerGesture::SWIPE
4439            || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
4440    bool moveNeeded = false;
4441    if (down && !cancelPreviousGesture && !finishPreviousGesture
4442            && !mPointerGesture.lastGestureIdBits.isEmpty()
4443            && !mPointerGesture.currentGestureIdBits.isEmpty()) {
4444        BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value
4445                & mPointerGesture.lastGestureIdBits.value);
4446        moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties,
4447                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
4448                mPointerGesture.lastGestureProperties,
4449                mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
4450                movedGestureIdBits);
4451        if (buttonState != mLastButtonState) {
4452            moveNeeded = true;
4453        }
4454    }
4455
4456    // Send motion events for all pointers that went up or were canceled.
4457    BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
4458    if (!dispatchedGestureIdBits.isEmpty()) {
4459        if (cancelPreviousGesture) {
4460            dispatchMotion(when, policyFlags, mSource,
4461                    AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
4462                    AMOTION_EVENT_EDGE_FLAG_NONE,
4463                    mPointerGesture.lastGestureProperties,
4464                    mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
4465                    dispatchedGestureIdBits, -1,
4466                    0, 0, mPointerGesture.downTime);
4467
4468            dispatchedGestureIdBits.clear();
4469        } else {
4470            BitSet32 upGestureIdBits;
4471            if (finishPreviousGesture) {
4472                upGestureIdBits = dispatchedGestureIdBits;
4473            } else {
4474                upGestureIdBits.value = dispatchedGestureIdBits.value
4475                        & ~mPointerGesture.currentGestureIdBits.value;
4476            }
4477            while (!upGestureIdBits.isEmpty()) {
4478                uint32_t id = upGestureIdBits.clearFirstMarkedBit();
4479
4480                dispatchMotion(when, policyFlags, mSource,
4481                        AMOTION_EVENT_ACTION_POINTER_UP, 0,
4482                        metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
4483                        mPointerGesture.lastGestureProperties,
4484                        mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
4485                        dispatchedGestureIdBits, id,
4486                        0, 0, mPointerGesture.downTime);
4487
4488                dispatchedGestureIdBits.clearBit(id);
4489            }
4490        }
4491    }
4492
4493    // Send motion events for all pointers that moved.
4494    if (moveNeeded) {
4495        dispatchMotion(when, policyFlags, mSource,
4496                AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
4497                mPointerGesture.currentGestureProperties,
4498                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
4499                dispatchedGestureIdBits, -1,
4500                0, 0, mPointerGesture.downTime);
4501    }
4502
4503    // Send motion events for all pointers that went down.
4504    if (down) {
4505        BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value
4506                & ~dispatchedGestureIdBits.value);
4507        while (!downGestureIdBits.isEmpty()) {
4508            uint32_t id = downGestureIdBits.clearFirstMarkedBit();
4509            dispatchedGestureIdBits.markBit(id);
4510
4511            if (dispatchedGestureIdBits.count() == 1) {
4512                mPointerGesture.downTime = when;
4513            }
4514
4515            dispatchMotion(when, policyFlags, mSource,
4516                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
4517                    mPointerGesture.currentGestureProperties,
4518                    mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
4519                    dispatchedGestureIdBits, id,
4520                    0, 0, mPointerGesture.downTime);
4521        }
4522    }
4523
4524    // Send motion events for hover.
4525    if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
4526        dispatchMotion(when, policyFlags, mSource,
4527                AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
4528                metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
4529                mPointerGesture.currentGestureProperties,
4530                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
4531                mPointerGesture.currentGestureIdBits, -1,
4532                0, 0, mPointerGesture.downTime);
4533    } else if (dispatchedGestureIdBits.isEmpty()
4534            && !mPointerGesture.lastGestureIdBits.isEmpty()) {
4535        // Synthesize a hover move event after all pointers go up to indicate that
4536        // the pointer is hovering again even if the user is not currently touching
4537        // the touch pad.  This ensures that a view will receive a fresh hover enter
4538        // event after a tap.
4539        float x, y;
4540        mPointerController->getPosition(&x, &y);
4541
4542        PointerProperties pointerProperties;
4543        pointerProperties.clear();
4544        pointerProperties.id = 0;
4545        pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
4546
4547        PointerCoords pointerCoords;
4548        pointerCoords.clear();
4549        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
4550        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
4551
4552        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
4553                AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
4554                metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
4555                mViewport.displayId, 1, &pointerProperties, &pointerCoords,
4556                0, 0, mPointerGesture.downTime);
4557        getListener()->notifyMotion(&args);
4558    }
4559
4560    // Update state.
4561    mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
4562    if (!down) {
4563        mPointerGesture.lastGestureIdBits.clear();
4564    } else {
4565        mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
4566        for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) {
4567            uint32_t id = idBits.clearFirstMarkedBit();
4568            uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
4569            mPointerGesture.lastGestureProperties[index].copyFrom(
4570                    mPointerGesture.currentGestureProperties[index]);
4571            mPointerGesture.lastGestureCoords[index].copyFrom(
4572                    mPointerGesture.currentGestureCoords[index]);
4573            mPointerGesture.lastGestureIdToIndex[id] = index;
4574        }
4575    }
4576}
4577
4578void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) {
4579    // Cancel previously dispatches pointers.
4580    if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
4581        int32_t metaState = getContext()->getGlobalMetaState();
4582        int32_t buttonState = mCurrentButtonState;
4583        dispatchMotion(when, policyFlags, mSource,
4584                AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
4585                AMOTION_EVENT_EDGE_FLAG_NONE,
4586                mPointerGesture.lastGestureProperties,
4587                mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
4588                mPointerGesture.lastGestureIdBits, -1,
4589                0, 0, mPointerGesture.downTime);
4590    }
4591
4592    // Reset the current pointer gesture.
4593    mPointerGesture.reset();
4594    mPointerVelocityControl.reset();
4595
4596    // Remove any current spots.
4597    if (mPointerController != NULL) {
4598        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
4599        mPointerController->clearSpots();
4600    }
4601}
4602
4603bool TouchInputMapper::preparePointerGestures(nsecs_t when,
4604        bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
4605    *outCancelPreviousGesture = false;
4606    *outFinishPreviousGesture = false;
4607
4608    // Handle TAP timeout.
4609    if (isTimeout) {
4610#if DEBUG_GESTURES
4611        ALOGD("Gestures: Processing timeout");
4612#endif
4613
4614        if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
4615            if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
4616                // The tap/drag timeout has not yet expired.
4617                getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime
4618                        + mConfig.pointerGestureTapDragInterval);
4619            } else {
4620                // The tap is finished.
4621#if DEBUG_GESTURES
4622                ALOGD("Gestures: TAP finished");
4623#endif
4624                *outFinishPreviousGesture = true;
4625
4626                mPointerGesture.activeGestureId = -1;
4627                mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
4628                mPointerGesture.currentGestureIdBits.clear();
4629
4630                mPointerVelocityControl.reset();
4631                return true;
4632            }
4633        }
4634
4635        // We did not handle this timeout.
4636        return false;
4637    }
4638
4639    const uint32_t currentFingerCount = mCurrentFingerIdBits.count();
4640    const uint32_t lastFingerCount = mLastFingerIdBits.count();
4641
4642    // Update the velocity tracker.
4643    {
4644        VelocityTracker::Position positions[MAX_POINTERS];
4645        uint32_t count = 0;
4646        for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); count++) {
4647            uint32_t id = idBits.clearFirstMarkedBit();
4648            const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
4649            positions[count].x = pointer.x * mPointerXMovementScale;
4650            positions[count].y = pointer.y * mPointerYMovementScale;
4651        }
4652        mPointerGesture.velocityTracker.addMovement(when,
4653                mCurrentFingerIdBits, positions);
4654    }
4655
4656    // If the gesture ever enters a mode other than TAP, HOVER or TAP_DRAG, without first returning
4657    // to NEUTRAL, then we should not generate tap event.
4658    if (mPointerGesture.lastGestureMode != PointerGesture::HOVER
4659            && mPointerGesture.lastGestureMode != PointerGesture::TAP
4660            && mPointerGesture.lastGestureMode != PointerGesture::TAP_DRAG) {
4661        mPointerGesture.resetTap();
4662    }
4663
4664    // Pick a new active touch id if needed.
4665    // Choose an arbitrary pointer that just went down, if there is one.
4666    // Otherwise choose an arbitrary remaining pointer.
4667    // This guarantees we always have an active touch id when there is at least one pointer.
4668    // We keep the same active touch id for as long as possible.
4669    bool activeTouchChanged = false;
4670    int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
4671    int32_t activeTouchId = lastActiveTouchId;
4672    if (activeTouchId < 0) {
4673        if (!mCurrentFingerIdBits.isEmpty()) {
4674            activeTouchChanged = true;
4675            activeTouchId = mPointerGesture.activeTouchId =
4676                    mCurrentFingerIdBits.firstMarkedBit();
4677            mPointerGesture.firstTouchTime = when;
4678        }
4679    } else if (!mCurrentFingerIdBits.hasBit(activeTouchId)) {
4680        activeTouchChanged = true;
4681        if (!mCurrentFingerIdBits.isEmpty()) {
4682            activeTouchId = mPointerGesture.activeTouchId =
4683                    mCurrentFingerIdBits.firstMarkedBit();
4684        } else {
4685            activeTouchId = mPointerGesture.activeTouchId = -1;
4686        }
4687    }
4688
4689    // Determine whether we are in quiet time.
4690    bool isQuietTime = false;
4691    if (activeTouchId < 0) {
4692        mPointerGesture.resetQuietTime();
4693    } else {
4694        isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval;
4695        if (!isQuietTime) {
4696            if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
4697                    || mPointerGesture.lastGestureMode == PointerGesture::SWIPE
4698                    || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)
4699                    && currentFingerCount < 2) {
4700                // Enter quiet time when exiting swipe or freeform state.
4701                // This is to prevent accidentally entering the hover state and flinging the
4702                // pointer when finishing a swipe and there is still one pointer left onscreen.
4703                isQuietTime = true;
4704            } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
4705                    && currentFingerCount >= 2
4706                    && !isPointerDown(mCurrentButtonState)) {
4707                // Enter quiet time when releasing the button and there are still two or more
4708                // fingers down.  This may indicate that one finger was used to press the button
4709                // but it has not gone up yet.
4710                isQuietTime = true;
4711            }
4712            if (isQuietTime) {
4713                mPointerGesture.quietTime = when;
4714            }
4715        }
4716    }
4717
4718    // Switch states based on button and pointer state.
4719    if (isQuietTime) {
4720        // Case 1: Quiet time. (QUIET)
4721#if DEBUG_GESTURES
4722        ALOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime
4723                + mConfig.pointerGestureQuietInterval - when) * 0.000001f);
4724#endif
4725        if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
4726            *outFinishPreviousGesture = true;
4727        }
4728
4729        mPointerGesture.activeGestureId = -1;
4730        mPointerGesture.currentGestureMode = PointerGesture::QUIET;
4731        mPointerGesture.currentGestureIdBits.clear();
4732
4733        mPointerVelocityControl.reset();
4734    } else if (isPointerDown(mCurrentButtonState)) {
4735        // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
4736        // The pointer follows the active touch point.
4737        // Emit DOWN, MOVE, UP events at the pointer location.
4738        //
4739        // Only the active touch matters; other fingers are ignored.  This policy helps
4740        // to handle the case where the user places a second finger on the touch pad
4741        // to apply the necessary force to depress an integrated button below the surface.
4742        // We don't want the second finger to be delivered to applications.
4743        //
4744        // For this to work well, we need to make sure to track the pointer that is really
4745        // active.  If the user first puts one finger down to click then adds another
4746        // finger to drag then the active pointer should switch to the finger that is
4747        // being dragged.
4748#if DEBUG_GESTURES
4749        ALOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
4750                "currentFingerCount=%d", activeTouchId, currentFingerCount);
4751#endif
4752        // Reset state when just starting.
4753        if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
4754            *outFinishPreviousGesture = true;
4755            mPointerGesture.activeGestureId = 0;
4756        }
4757
4758        // Switch pointers if needed.
4759        // Find the fastest pointer and follow it.
4760        if (activeTouchId >= 0 && currentFingerCount > 1) {
4761            int32_t bestId = -1;
4762            float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
4763            for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); ) {
4764                uint32_t id = idBits.clearFirstMarkedBit();
4765                float vx, vy;
4766                if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
4767                    float speed = hypotf(vx, vy);
4768                    if (speed > bestSpeed) {
4769                        bestId = id;
4770                        bestSpeed = speed;
4771                    }
4772                }
4773            }
4774            if (bestId >= 0 && bestId != activeTouchId) {
4775                mPointerGesture.activeTouchId = activeTouchId = bestId;
4776                activeTouchChanged = true;
4777#if DEBUG_GESTURES
4778                ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
4779                        "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
4780#endif
4781            }
4782        }
4783
4784        if (activeTouchId >= 0 && mLastFingerIdBits.hasBit(activeTouchId)) {
4785            const RawPointerData::Pointer& currentPointer =
4786                    mCurrentRawPointerData.pointerForId(activeTouchId);
4787            const RawPointerData::Pointer& lastPointer =
4788                    mLastRawPointerData.pointerForId(activeTouchId);
4789            float deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
4790            float deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
4791
4792            rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
4793            mPointerVelocityControl.move(when, &deltaX, &deltaY);
4794
4795            // Move the pointer using a relative motion.
4796            // When using spots, the click will occur at the position of the anchor
4797            // spot and all other spots will move there.
4798            mPointerController->move(deltaX, deltaY);
4799        } else {
4800            mPointerVelocityControl.reset();
4801        }
4802
4803        float x, y;
4804        mPointerController->getPosition(&x, &y);
4805
4806        mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
4807        mPointerGesture.currentGestureIdBits.clear();
4808        mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4809        mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
4810        mPointerGesture.currentGestureProperties[0].clear();
4811        mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
4812        mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
4813        mPointerGesture.currentGestureCoords[0].clear();
4814        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
4815        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
4816        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4817    } else if (currentFingerCount == 0) {
4818        // Case 3. No fingers down and button is not pressed. (NEUTRAL)
4819        if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
4820            *outFinishPreviousGesture = true;
4821        }
4822
4823        // Watch for taps coming out of HOVER or TAP_DRAG mode.
4824        // Checking for taps after TAP_DRAG allows us to detect double-taps.
4825        bool tapped = false;
4826        if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
4827                || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
4828                && lastFingerCount == 1) {
4829            if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
4830                float x, y;
4831                mPointerController->getPosition(&x, &y);
4832                if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
4833                        && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
4834#if DEBUG_GESTURES
4835                    ALOGD("Gestures: TAP");
4836#endif
4837
4838                    mPointerGesture.tapUpTime = when;
4839                    getContext()->requestTimeoutAtTime(when
4840                            + mConfig.pointerGestureTapDragInterval);
4841
4842                    mPointerGesture.activeGestureId = 0;
4843                    mPointerGesture.currentGestureMode = PointerGesture::TAP;
4844                    mPointerGesture.currentGestureIdBits.clear();
4845                    mPointerGesture.currentGestureIdBits.markBit(
4846                            mPointerGesture.activeGestureId);
4847                    mPointerGesture.currentGestureIdToIndex[
4848                            mPointerGesture.activeGestureId] = 0;
4849                    mPointerGesture.currentGestureProperties[0].clear();
4850                    mPointerGesture.currentGestureProperties[0].id =
4851                            mPointerGesture.activeGestureId;
4852                    mPointerGesture.currentGestureProperties[0].toolType =
4853                            AMOTION_EVENT_TOOL_TYPE_FINGER;
4854                    mPointerGesture.currentGestureCoords[0].clear();
4855                    mPointerGesture.currentGestureCoords[0].setAxisValue(
4856                            AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
4857                    mPointerGesture.currentGestureCoords[0].setAxisValue(
4858                            AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY);
4859                    mPointerGesture.currentGestureCoords[0].setAxisValue(
4860                            AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4861
4862                    tapped = true;
4863                } else {
4864#if DEBUG_GESTURES
4865                    ALOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f",
4866                            x - mPointerGesture.tapX,
4867                            y - mPointerGesture.tapY);
4868#endif
4869                }
4870            } else {
4871#if DEBUG_GESTURES
4872                if (mPointerGesture.tapDownTime != LLONG_MIN) {
4873                    ALOGD("Gestures: Not a TAP, %0.3fms since down",
4874                            (when - mPointerGesture.tapDownTime) * 0.000001f);
4875                } else {
4876                    ALOGD("Gestures: Not a TAP, incompatible mode transitions");
4877                }
4878#endif
4879            }
4880        }
4881
4882        mPointerVelocityControl.reset();
4883
4884        if (!tapped) {
4885#if DEBUG_GESTURES
4886            ALOGD("Gestures: NEUTRAL");
4887#endif
4888            mPointerGesture.activeGestureId = -1;
4889            mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
4890            mPointerGesture.currentGestureIdBits.clear();
4891        }
4892    } else if (currentFingerCount == 1) {
4893        // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
4894        // The pointer follows the active touch point.
4895        // When in HOVER, emit HOVER_MOVE events at the pointer location.
4896        // When in TAP_DRAG, emit MOVE events at the pointer location.
4897        ALOG_ASSERT(activeTouchId >= 0);
4898
4899        mPointerGesture.currentGestureMode = PointerGesture::HOVER;
4900        if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
4901            if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
4902                float x, y;
4903                mPointerController->getPosition(&x, &y);
4904                if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
4905                        && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
4906                    mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
4907                } else {
4908#if DEBUG_GESTURES
4909                    ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
4910                            x - mPointerGesture.tapX,
4911                            y - mPointerGesture.tapY);
4912#endif
4913                }
4914            } else {
4915#if DEBUG_GESTURES
4916                ALOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
4917                        (when - mPointerGesture.tapUpTime) * 0.000001f);
4918#endif
4919            }
4920        } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
4921            mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
4922        }
4923
4924        if (mLastFingerIdBits.hasBit(activeTouchId)) {
4925            const RawPointerData::Pointer& currentPointer =
4926                    mCurrentRawPointerData.pointerForId(activeTouchId);
4927            const RawPointerData::Pointer& lastPointer =
4928                    mLastRawPointerData.pointerForId(activeTouchId);
4929            float deltaX = (currentPointer.x - lastPointer.x)
4930                    * mPointerXMovementScale;
4931            float deltaY = (currentPointer.y - lastPointer.y)
4932                    * mPointerYMovementScale;
4933
4934            rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
4935            mPointerVelocityControl.move(when, &deltaX, &deltaY);
4936
4937            // Move the pointer using a relative motion.
4938            // When using spots, the hover or drag will occur at the position of the anchor spot.
4939            mPointerController->move(deltaX, deltaY);
4940        } else {
4941            mPointerVelocityControl.reset();
4942        }
4943
4944        bool down;
4945        if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
4946#if DEBUG_GESTURES
4947            ALOGD("Gestures: TAP_DRAG");
4948#endif
4949            down = true;
4950        } else {
4951#if DEBUG_GESTURES
4952            ALOGD("Gestures: HOVER");
4953#endif
4954            if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
4955                *outFinishPreviousGesture = true;
4956            }
4957            mPointerGesture.activeGestureId = 0;
4958            down = false;
4959        }
4960
4961        float x, y;
4962        mPointerController->getPosition(&x, &y);
4963
4964        mPointerGesture.currentGestureIdBits.clear();
4965        mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4966        mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
4967        mPointerGesture.currentGestureProperties[0].clear();
4968        mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
4969        mPointerGesture.currentGestureProperties[0].toolType =
4970                AMOTION_EVENT_TOOL_TYPE_FINGER;
4971        mPointerGesture.currentGestureCoords[0].clear();
4972        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
4973        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
4974        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
4975                down ? 1.0f : 0.0f);
4976
4977        if (lastFingerCount == 0 && currentFingerCount != 0) {
4978            mPointerGesture.resetTap();
4979            mPointerGesture.tapDownTime = when;
4980            mPointerGesture.tapX = x;
4981            mPointerGesture.tapY = y;
4982        }
4983    } else {
4984        // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
4985        // We need to provide feedback for each finger that goes down so we cannot wait
4986        // for the fingers to move before deciding what to do.
4987        //
4988        // The ambiguous case is deciding what to do when there are two fingers down but they
4989        // have not moved enough to determine whether they are part of a drag or part of a
4990        // freeform gesture, or just a press or long-press at the pointer location.
4991        //
4992        // When there are two fingers we start with the PRESS hypothesis and we generate a
4993        // down at the pointer location.
4994        //
4995        // When the two fingers move enough or when additional fingers are added, we make
4996        // a decision to transition into SWIPE or FREEFORM mode accordingly.
4997        ALOG_ASSERT(activeTouchId >= 0);
4998
4999        bool settled = when >= mPointerGesture.firstTouchTime
5000                + mConfig.pointerGestureMultitouchSettleInterval;
5001        if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
5002                && mPointerGesture.lastGestureMode != PointerGesture::SWIPE
5003                && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
5004            *outFinishPreviousGesture = true;
5005        } else if (!settled && currentFingerCount > lastFingerCount) {
5006            // Additional pointers have gone down but not yet settled.
5007            // Reset the gesture.
5008#if DEBUG_GESTURES
5009            ALOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
5010                    "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
5011                            + mConfig.pointerGestureMultitouchSettleInterval - when)
5012                            * 0.000001f);
5013#endif
5014            *outCancelPreviousGesture = true;
5015        } else {
5016            // Continue previous gesture.
5017            mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
5018        }
5019
5020        if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
5021            mPointerGesture.currentGestureMode = PointerGesture::PRESS;
5022            mPointerGesture.activeGestureId = 0;
5023            mPointerGesture.referenceIdBits.clear();
5024            mPointerVelocityControl.reset();
5025
5026            // Use the centroid and pointer location as the reference points for the gesture.
5027#if DEBUG_GESTURES
5028            ALOGD("Gestures: Using centroid as reference for MULTITOUCH, "
5029                    "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
5030                            + mConfig.pointerGestureMultitouchSettleInterval - when)
5031                            * 0.000001f);
5032#endif
5033            mCurrentRawPointerData.getCentroidOfTouchingPointers(
5034                    &mPointerGesture.referenceTouchX,
5035                    &mPointerGesture.referenceTouchY);
5036            mPointerController->getPosition(&mPointerGesture.referenceGestureX,
5037                    &mPointerGesture.referenceGestureY);
5038        }
5039
5040        // Clear the reference deltas for fingers not yet included in the reference calculation.
5041        for (BitSet32 idBits(mCurrentFingerIdBits.value
5042                & ~mPointerGesture.referenceIdBits.value); !idBits.isEmpty(); ) {
5043            uint32_t id = idBits.clearFirstMarkedBit();
5044            mPointerGesture.referenceDeltas[id].dx = 0;
5045            mPointerGesture.referenceDeltas[id].dy = 0;
5046        }
5047        mPointerGesture.referenceIdBits = mCurrentFingerIdBits;
5048
5049        // Add delta for all fingers and calculate a common movement delta.
5050        float commonDeltaX = 0, commonDeltaY = 0;
5051        BitSet32 commonIdBits(mLastFingerIdBits.value
5052                & mCurrentFingerIdBits.value);
5053        for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
5054            bool first = (idBits == commonIdBits);
5055            uint32_t id = idBits.clearFirstMarkedBit();
5056            const RawPointerData::Pointer& cpd = mCurrentRawPointerData.pointerForId(id);
5057            const RawPointerData::Pointer& lpd = mLastRawPointerData.pointerForId(id);
5058            PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
5059            delta.dx += cpd.x - lpd.x;
5060            delta.dy += cpd.y - lpd.y;
5061
5062            if (first) {
5063                commonDeltaX = delta.dx;
5064                commonDeltaY = delta.dy;
5065            } else {
5066                commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
5067                commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
5068            }
5069        }
5070
5071        // Consider transitions from PRESS to SWIPE or MULTITOUCH.
5072        if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
5073            float dist[MAX_POINTER_ID + 1];
5074            int32_t distOverThreshold = 0;
5075            for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
5076                uint32_t id = idBits.clearFirstMarkedBit();
5077                PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
5078                dist[id] = hypotf(delta.dx * mPointerXZoomScale,
5079                        delta.dy * mPointerYZoomScale);
5080                if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) {
5081                    distOverThreshold += 1;
5082                }
5083            }
5084
5085            // Only transition when at least two pointers have moved further than
5086            // the minimum distance threshold.
5087            if (distOverThreshold >= 2) {
5088                if (currentFingerCount > 2) {
5089                    // There are more than two pointers, switch to FREEFORM.
5090#if DEBUG_GESTURES
5091                    ALOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
5092                            currentFingerCount);
5093#endif
5094                    *outCancelPreviousGesture = true;
5095                    mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
5096                } else {
5097                    // There are exactly two pointers.
5098                    BitSet32 idBits(mCurrentFingerIdBits);
5099                    uint32_t id1 = idBits.clearFirstMarkedBit();
5100                    uint32_t id2 = idBits.firstMarkedBit();
5101                    const RawPointerData::Pointer& p1 = mCurrentRawPointerData.pointerForId(id1);
5102                    const RawPointerData::Pointer& p2 = mCurrentRawPointerData.pointerForId(id2);
5103                    float mutualDistance = distance(p1.x, p1.y, p2.x, p2.y);
5104                    if (mutualDistance > mPointerGestureMaxSwipeWidth) {
5105                        // There are two pointers but they are too far apart for a SWIPE,
5106                        // switch to FREEFORM.
5107#if DEBUG_GESTURES
5108                        ALOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
5109                                mutualDistance, mPointerGestureMaxSwipeWidth);
5110#endif
5111                        *outCancelPreviousGesture = true;
5112                        mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
5113                    } else {
5114                        // There are two pointers.  Wait for both pointers to start moving
5115                        // before deciding whether this is a SWIPE or FREEFORM gesture.
5116                        float dist1 = dist[id1];
5117                        float dist2 = dist[id2];
5118                        if (dist1 >= mConfig.pointerGestureMultitouchMinDistance
5119                                && dist2 >= mConfig.pointerGestureMultitouchMinDistance) {
5120                            // Calculate the dot product of the displacement vectors.
5121                            // When the vectors are oriented in approximately the same direction,
5122                            // the angle betweeen them is near zero and the cosine of the angle
5123                            // approches 1.0.  Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
5124                            PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
5125                            PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
5126                            float dx1 = delta1.dx * mPointerXZoomScale;
5127                            float dy1 = delta1.dy * mPointerYZoomScale;
5128                            float dx2 = delta2.dx * mPointerXZoomScale;
5129                            float dy2 = delta2.dy * mPointerYZoomScale;
5130                            float dot = dx1 * dx2 + dy1 * dy2;
5131                            float cosine = dot / (dist1 * dist2); // denominator always > 0
5132                            if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
5133                                // Pointers are moving in the same direction.  Switch to SWIPE.
5134#if DEBUG_GESTURES
5135                                ALOGD("Gestures: PRESS transitioned to SWIPE, "
5136                                        "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
5137                                        "cosine %0.3f >= %0.3f",
5138                                        dist1, mConfig.pointerGestureMultitouchMinDistance,
5139                                        dist2, mConfig.pointerGestureMultitouchMinDistance,
5140                                        cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
5141#endif
5142                                mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
5143                            } else {
5144                                // Pointers are moving in different directions.  Switch to FREEFORM.
5145#if DEBUG_GESTURES
5146                                ALOGD("Gestures: PRESS transitioned to FREEFORM, "
5147                                        "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
5148                                        "cosine %0.3f < %0.3f",
5149                                        dist1, mConfig.pointerGestureMultitouchMinDistance,
5150                                        dist2, mConfig.pointerGestureMultitouchMinDistance,
5151                                        cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
5152#endif
5153                                *outCancelPreviousGesture = true;
5154                                mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
5155                            }
5156                        }
5157                    }
5158                }
5159            }
5160        } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
5161            // Switch from SWIPE to FREEFORM if additional pointers go down.
5162            // Cancel previous gesture.
5163            if (currentFingerCount > 2) {
5164#if DEBUG_GESTURES
5165                ALOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
5166                        currentFingerCount);
5167#endif
5168                *outCancelPreviousGesture = true;
5169                mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
5170            }
5171        }
5172
5173        // Move the reference points based on the overall group motion of the fingers
5174        // except in PRESS mode while waiting for a transition to occur.
5175        if (mPointerGesture.currentGestureMode != PointerGesture::PRESS
5176                && (commonDeltaX || commonDeltaY)) {
5177            for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
5178                uint32_t id = idBits.clearFirstMarkedBit();
5179                PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
5180                delta.dx = 0;
5181                delta.dy = 0;
5182            }
5183
5184            mPointerGesture.referenceTouchX += commonDeltaX;
5185            mPointerGesture.referenceTouchY += commonDeltaY;
5186
5187            commonDeltaX *= mPointerXMovementScale;
5188            commonDeltaY *= mPointerYMovementScale;
5189
5190            rotateDelta(mSurfaceOrientation, &commonDeltaX, &commonDeltaY);
5191            mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
5192
5193            mPointerGesture.referenceGestureX += commonDeltaX;
5194            mPointerGesture.referenceGestureY += commonDeltaY;
5195        }
5196
5197        // Report gestures.
5198        if (mPointerGesture.currentGestureMode == PointerGesture::PRESS
5199                || mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
5200            // PRESS or SWIPE mode.
5201#if DEBUG_GESTURES
5202            ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
5203                    "activeGestureId=%d, currentTouchPointerCount=%d",
5204                    activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
5205#endif
5206            ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
5207
5208            mPointerGesture.currentGestureIdBits.clear();
5209            mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
5210            mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
5211            mPointerGesture.currentGestureProperties[0].clear();
5212            mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
5213            mPointerGesture.currentGestureProperties[0].toolType =
5214                    AMOTION_EVENT_TOOL_TYPE_FINGER;
5215            mPointerGesture.currentGestureCoords[0].clear();
5216            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5217                    mPointerGesture.referenceGestureX);
5218            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
5219                    mPointerGesture.referenceGestureY);
5220            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
5221        } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
5222            // FREEFORM mode.
5223#if DEBUG_GESTURES
5224            ALOGD("Gestures: FREEFORM activeTouchId=%d,"
5225                    "activeGestureId=%d, currentTouchPointerCount=%d",
5226                    activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
5227#endif
5228            ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
5229
5230            mPointerGesture.currentGestureIdBits.clear();
5231
5232            BitSet32 mappedTouchIdBits;
5233            BitSet32 usedGestureIdBits;
5234            if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
5235                // Initially, assign the active gesture id to the active touch point
5236                // if there is one.  No other touch id bits are mapped yet.
5237                if (!*outCancelPreviousGesture) {
5238                    mappedTouchIdBits.markBit(activeTouchId);
5239                    usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
5240                    mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
5241                            mPointerGesture.activeGestureId;
5242                } else {
5243                    mPointerGesture.activeGestureId = -1;
5244                }
5245            } else {
5246                // Otherwise, assume we mapped all touches from the previous frame.
5247                // Reuse all mappings that are still applicable.
5248                mappedTouchIdBits.value = mLastFingerIdBits.value
5249                        & mCurrentFingerIdBits.value;
5250                usedGestureIdBits = mPointerGesture.lastGestureIdBits;
5251
5252                // Check whether we need to choose a new active gesture id because the
5253                // current went went up.
5254                for (BitSet32 upTouchIdBits(mLastFingerIdBits.value
5255                        & ~mCurrentFingerIdBits.value);
5256                        !upTouchIdBits.isEmpty(); ) {
5257                    uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit();
5258                    uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
5259                    if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
5260                        mPointerGesture.activeGestureId = -1;
5261                        break;
5262                    }
5263                }
5264            }
5265
5266#if DEBUG_GESTURES
5267            ALOGD("Gestures: FREEFORM follow up "
5268                    "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
5269                    "activeGestureId=%d",
5270                    mappedTouchIdBits.value, usedGestureIdBits.value,
5271                    mPointerGesture.activeGestureId);
5272#endif
5273
5274            BitSet32 idBits(mCurrentFingerIdBits);
5275            for (uint32_t i = 0; i < currentFingerCount; i++) {
5276                uint32_t touchId = idBits.clearFirstMarkedBit();
5277                uint32_t gestureId;
5278                if (!mappedTouchIdBits.hasBit(touchId)) {
5279                    gestureId = usedGestureIdBits.markFirstUnmarkedBit();
5280                    mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
5281#if DEBUG_GESTURES
5282                    ALOGD("Gestures: FREEFORM "
5283                            "new mapping for touch id %d -> gesture id %d",
5284                            touchId, gestureId);
5285#endif
5286                } else {
5287                    gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
5288#if DEBUG_GESTURES
5289                    ALOGD("Gestures: FREEFORM "
5290                            "existing mapping for touch id %d -> gesture id %d",
5291                            touchId, gestureId);
5292#endif
5293                }
5294                mPointerGesture.currentGestureIdBits.markBit(gestureId);
5295                mPointerGesture.currentGestureIdToIndex[gestureId] = i;
5296
5297                const RawPointerData::Pointer& pointer =
5298                        mCurrentRawPointerData.pointerForId(touchId);
5299                float deltaX = (pointer.x - mPointerGesture.referenceTouchX)
5300                        * mPointerXZoomScale;
5301                float deltaY = (pointer.y - mPointerGesture.referenceTouchY)
5302                        * mPointerYZoomScale;
5303                rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
5304
5305                mPointerGesture.currentGestureProperties[i].clear();
5306                mPointerGesture.currentGestureProperties[i].id = gestureId;
5307                mPointerGesture.currentGestureProperties[i].toolType =
5308                        AMOTION_EVENT_TOOL_TYPE_FINGER;
5309                mPointerGesture.currentGestureCoords[i].clear();
5310                mPointerGesture.currentGestureCoords[i].setAxisValue(
5311                        AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX);
5312                mPointerGesture.currentGestureCoords[i].setAxisValue(
5313                        AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY + deltaY);
5314                mPointerGesture.currentGestureCoords[i].setAxisValue(
5315                        AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
5316            }
5317
5318            if (mPointerGesture.activeGestureId < 0) {
5319                mPointerGesture.activeGestureId =
5320                        mPointerGesture.currentGestureIdBits.firstMarkedBit();
5321#if DEBUG_GESTURES
5322                ALOGD("Gestures: FREEFORM new "
5323                        "activeGestureId=%d", mPointerGesture.activeGestureId);
5324#endif
5325            }
5326        }
5327    }
5328
5329    mPointerController->setButtonState(mCurrentButtonState);
5330
5331#if DEBUG_GESTURES
5332    ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
5333            "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
5334            "lastGestureMode=%d, lastGestureIdBits=0x%08x",
5335            toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
5336            mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
5337            mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
5338    for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) {
5339        uint32_t id = idBits.clearFirstMarkedBit();
5340        uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
5341        const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
5342        const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
5343        ALOGD("  currentGesture[%d]: index=%d, toolType=%d, "
5344                "x=%0.3f, y=%0.3f, pressure=%0.3f",
5345                id, index, properties.toolType,
5346                coords.getAxisValue(AMOTION_EVENT_AXIS_X),
5347                coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
5348                coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
5349    }
5350    for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) {
5351        uint32_t id = idBits.clearFirstMarkedBit();
5352        uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
5353        const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
5354        const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
5355        ALOGD("  lastGesture[%d]: index=%d, toolType=%d, "
5356                "x=%0.3f, y=%0.3f, pressure=%0.3f",
5357                id, index, properties.toolType,
5358                coords.getAxisValue(AMOTION_EVENT_AXIS_X),
5359                coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
5360                coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
5361    }
5362#endif
5363    return true;
5364}
5365
5366void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) {
5367    mPointerSimple.currentCoords.clear();
5368    mPointerSimple.currentProperties.clear();
5369
5370    bool down, hovering;
5371    if (!mCurrentStylusIdBits.isEmpty()) {
5372        uint32_t id = mCurrentStylusIdBits.firstMarkedBit();
5373        uint32_t index = mCurrentCookedPointerData.idToIndex[id];
5374        float x = mCurrentCookedPointerData.pointerCoords[index].getX();
5375        float y = mCurrentCookedPointerData.pointerCoords[index].getY();
5376        mPointerController->setPosition(x, y);
5377
5378        hovering = mCurrentCookedPointerData.hoveringIdBits.hasBit(id);
5379        down = !hovering;
5380
5381        mPointerController->getPosition(&x, &y);
5382        mPointerSimple.currentCoords.copyFrom(mCurrentCookedPointerData.pointerCoords[index]);
5383        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
5384        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5385        mPointerSimple.currentProperties.id = 0;
5386        mPointerSimple.currentProperties.toolType =
5387                mCurrentCookedPointerData.pointerProperties[index].toolType;
5388    } else {
5389        down = false;
5390        hovering = false;
5391    }
5392
5393    dispatchPointerSimple(when, policyFlags, down, hovering);
5394}
5395
5396void TouchInputMapper::abortPointerStylus(nsecs_t when, uint32_t policyFlags) {
5397    abortPointerSimple(when, policyFlags);
5398}
5399
5400void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) {
5401    mPointerSimple.currentCoords.clear();
5402    mPointerSimple.currentProperties.clear();
5403
5404    bool down, hovering;
5405    if (!mCurrentMouseIdBits.isEmpty()) {
5406        uint32_t id = mCurrentMouseIdBits.firstMarkedBit();
5407        uint32_t currentIndex = mCurrentRawPointerData.idToIndex[id];
5408        if (mLastMouseIdBits.hasBit(id)) {
5409            uint32_t lastIndex = mCurrentRawPointerData.idToIndex[id];
5410            float deltaX = (mCurrentRawPointerData.pointers[currentIndex].x
5411                    - mLastRawPointerData.pointers[lastIndex].x)
5412                    * mPointerXMovementScale;
5413            float deltaY = (mCurrentRawPointerData.pointers[currentIndex].y
5414                    - mLastRawPointerData.pointers[lastIndex].y)
5415                    * mPointerYMovementScale;
5416
5417            rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
5418            mPointerVelocityControl.move(when, &deltaX, &deltaY);
5419
5420            mPointerController->move(deltaX, deltaY);
5421        } else {
5422            mPointerVelocityControl.reset();
5423        }
5424
5425        down = isPointerDown(mCurrentButtonState);
5426        hovering = !down;
5427
5428        float x, y;
5429        mPointerController->getPosition(&x, &y);
5430        mPointerSimple.currentCoords.copyFrom(
5431                mCurrentCookedPointerData.pointerCoords[currentIndex]);
5432        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
5433        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5434        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
5435                hovering ? 0.0f : 1.0f);
5436        mPointerSimple.currentProperties.id = 0;
5437        mPointerSimple.currentProperties.toolType =
5438                mCurrentCookedPointerData.pointerProperties[currentIndex].toolType;
5439    } else {
5440        mPointerVelocityControl.reset();
5441
5442        down = false;
5443        hovering = false;
5444    }
5445
5446    dispatchPointerSimple(when, policyFlags, down, hovering);
5447}
5448
5449void TouchInputMapper::abortPointerMouse(nsecs_t when, uint32_t policyFlags) {
5450    abortPointerSimple(when, policyFlags);
5451
5452    mPointerVelocityControl.reset();
5453}
5454
5455void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
5456        bool down, bool hovering) {
5457    int32_t metaState = getContext()->getGlobalMetaState();
5458
5459    if (mPointerController != NULL) {
5460        if (down || hovering) {
5461            mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
5462            mPointerController->clearSpots();
5463            mPointerController->setButtonState(mCurrentButtonState);
5464            mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
5465        } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
5466            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
5467        }
5468    }
5469
5470    if (mPointerSimple.down && !down) {
5471        mPointerSimple.down = false;
5472
5473        // Send up.
5474        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5475                 AMOTION_EVENT_ACTION_UP, 0, metaState, mLastButtonState, 0,
5476                 mViewport.displayId,
5477                 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
5478                 mOrientedXPrecision, mOrientedYPrecision,
5479                 mPointerSimple.downTime);
5480        getListener()->notifyMotion(&args);
5481    }
5482
5483    if (mPointerSimple.hovering && !hovering) {
5484        mPointerSimple.hovering = false;
5485
5486        // Send hover exit.
5487        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5488                AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
5489                mViewport.displayId,
5490                1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
5491                mOrientedXPrecision, mOrientedYPrecision,
5492                mPointerSimple.downTime);
5493        getListener()->notifyMotion(&args);
5494    }
5495
5496    if (down) {
5497        if (!mPointerSimple.down) {
5498            mPointerSimple.down = true;
5499            mPointerSimple.downTime = when;
5500
5501            // Send down.
5502            NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5503                    AMOTION_EVENT_ACTION_DOWN, 0, metaState, mCurrentButtonState, 0,
5504                    mViewport.displayId,
5505                    1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
5506                    mOrientedXPrecision, mOrientedYPrecision,
5507                    mPointerSimple.downTime);
5508            getListener()->notifyMotion(&args);
5509        }
5510
5511        // Send move.
5512        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5513                AMOTION_EVENT_ACTION_MOVE, 0, metaState, mCurrentButtonState, 0,
5514                mViewport.displayId,
5515                1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
5516                mOrientedXPrecision, mOrientedYPrecision,
5517                mPointerSimple.downTime);
5518        getListener()->notifyMotion(&args);
5519    }
5520
5521    if (hovering) {
5522        if (!mPointerSimple.hovering) {
5523            mPointerSimple.hovering = true;
5524
5525            // Send hover enter.
5526            NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5527                    AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
5528                    mViewport.displayId,
5529                    1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
5530                    mOrientedXPrecision, mOrientedYPrecision,
5531                    mPointerSimple.downTime);
5532            getListener()->notifyMotion(&args);
5533        }
5534
5535        // Send hover move.
5536        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5537                AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
5538                mViewport.displayId,
5539                1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
5540                mOrientedXPrecision, mOrientedYPrecision,
5541                mPointerSimple.downTime);
5542        getListener()->notifyMotion(&args);
5543    }
5544
5545    if (mCurrentRawVScroll || mCurrentRawHScroll) {
5546        float vscroll = mCurrentRawVScroll;
5547        float hscroll = mCurrentRawHScroll;
5548        mWheelYVelocityControl.move(when, NULL, &vscroll);
5549        mWheelXVelocityControl.move(when, &hscroll, NULL);
5550
5551        // Send scroll.
5552        PointerCoords pointerCoords;
5553        pointerCoords.copyFrom(mPointerSimple.currentCoords);
5554        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
5555        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
5556
5557        NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5558                AMOTION_EVENT_ACTION_SCROLL, 0, metaState, mCurrentButtonState, 0,
5559                mViewport.displayId,
5560                1, &mPointerSimple.currentProperties, &pointerCoords,
5561                mOrientedXPrecision, mOrientedYPrecision,
5562                mPointerSimple.downTime);
5563        getListener()->notifyMotion(&args);
5564    }
5565
5566    // Save state.
5567    if (down || hovering) {
5568        mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords);
5569        mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
5570    } else {
5571        mPointerSimple.reset();
5572    }
5573}
5574
5575void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) {
5576    mPointerSimple.currentCoords.clear();
5577    mPointerSimple.currentProperties.clear();
5578
5579    dispatchPointerSimple(when, policyFlags, false, false);
5580}
5581
5582void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
5583        int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
5584        const PointerProperties* properties, const PointerCoords* coords,
5585        const uint32_t* idToIndex, BitSet32 idBits,
5586        int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {
5587    PointerCoords pointerCoords[MAX_POINTERS];
5588    PointerProperties pointerProperties[MAX_POINTERS];
5589    uint32_t pointerCount = 0;
5590    while (!idBits.isEmpty()) {
5591        uint32_t id = idBits.clearFirstMarkedBit();
5592        uint32_t index = idToIndex[id];
5593        pointerProperties[pointerCount].copyFrom(properties[index]);
5594        pointerCoords[pointerCount].copyFrom(coords[index]);
5595
5596        if (changedId >= 0 && id == uint32_t(changedId)) {
5597            action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
5598        }
5599
5600        pointerCount += 1;
5601    }
5602
5603    ALOG_ASSERT(pointerCount != 0);
5604
5605    if (changedId >= 0 && pointerCount == 1) {
5606        // Replace initial down and final up action.
5607        // We can compare the action without masking off the changed pointer index
5608        // because we know the index is 0.
5609        if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
5610            action = AMOTION_EVENT_ACTION_DOWN;
5611        } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
5612            action = AMOTION_EVENT_ACTION_UP;
5613        } else {
5614            // Can't happen.
5615            ALOG_ASSERT(false);
5616        }
5617    }
5618
5619    NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
5620            action, flags, metaState, buttonState, edgeFlags,
5621            mViewport.displayId, pointerCount, pointerProperties, pointerCoords,
5622            xPrecision, yPrecision, downTime);
5623    getListener()->notifyMotion(&args);
5624}
5625
5626bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties,
5627        const PointerCoords* inCoords, const uint32_t* inIdToIndex,
5628        PointerProperties* outProperties, PointerCoords* outCoords, const uint32_t* outIdToIndex,
5629        BitSet32 idBits) const {
5630    bool changed = false;
5631    while (!idBits.isEmpty()) {
5632        uint32_t id = idBits.clearFirstMarkedBit();
5633        uint32_t inIndex = inIdToIndex[id];
5634        uint32_t outIndex = outIdToIndex[id];
5635
5636        const PointerProperties& curInProperties = inProperties[inIndex];
5637        const PointerCoords& curInCoords = inCoords[inIndex];
5638        PointerProperties& curOutProperties = outProperties[outIndex];
5639        PointerCoords& curOutCoords = outCoords[outIndex];
5640
5641        if (curInProperties != curOutProperties) {
5642            curOutProperties.copyFrom(curInProperties);
5643            changed = true;
5644        }
5645
5646        if (curInCoords != curOutCoords) {
5647            curOutCoords.copyFrom(curInCoords);
5648            changed = true;
5649        }
5650    }
5651    return changed;
5652}
5653
5654void TouchInputMapper::fadePointer() {
5655    if (mPointerController != NULL) {
5656        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
5657    }
5658}
5659
5660bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
5661    return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue
5662            && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue;
5663}
5664
5665const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(
5666        int32_t x, int32_t y) {
5667    size_t numVirtualKeys = mVirtualKeys.size();
5668    for (size_t i = 0; i < numVirtualKeys; i++) {
5669        const VirtualKey& virtualKey = mVirtualKeys[i];
5670
5671#if DEBUG_VIRTUAL_KEYS
5672        ALOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
5673                "left=%d, top=%d, right=%d, bottom=%d",
5674                x, y,
5675                virtualKey.keyCode, virtualKey.scanCode,
5676                virtualKey.hitLeft, virtualKey.hitTop,
5677                virtualKey.hitRight, virtualKey.hitBottom);
5678#endif
5679
5680        if (virtualKey.isHit(x, y)) {
5681            return & virtualKey;
5682        }
5683    }
5684
5685    return NULL;
5686}
5687
5688void TouchInputMapper::assignPointerIds() {
5689    uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount;
5690    uint32_t lastPointerCount = mLastRawPointerData.pointerCount;
5691
5692    mCurrentRawPointerData.clearIdBits();
5693
5694    if (currentPointerCount == 0) {
5695        // No pointers to assign.
5696        return;
5697    }
5698
5699    if (lastPointerCount == 0) {
5700        // All pointers are new.
5701        for (uint32_t i = 0; i < currentPointerCount; i++) {
5702            uint32_t id = i;
5703            mCurrentRawPointerData.pointers[i].id = id;
5704            mCurrentRawPointerData.idToIndex[id] = i;
5705            mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(i));
5706        }
5707        return;
5708    }
5709
5710    if (currentPointerCount == 1 && lastPointerCount == 1
5711            && mCurrentRawPointerData.pointers[0].toolType
5712                    == mLastRawPointerData.pointers[0].toolType) {
5713        // Only one pointer and no change in count so it must have the same id as before.
5714        uint32_t id = mLastRawPointerData.pointers[0].id;
5715        mCurrentRawPointerData.pointers[0].id = id;
5716        mCurrentRawPointerData.idToIndex[id] = 0;
5717        mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(0));
5718        return;
5719    }
5720
5721    // General case.
5722    // We build a heap of squared euclidean distances between current and last pointers
5723    // associated with the current and last pointer indices.  Then, we find the best
5724    // match (by distance) for each current pointer.
5725    // The pointers must have the same tool type but it is possible for them to
5726    // transition from hovering to touching or vice-versa while retaining the same id.
5727    PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
5728
5729    uint32_t heapSize = 0;
5730    for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
5731            currentPointerIndex++) {
5732        for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
5733                lastPointerIndex++) {
5734            const RawPointerData::Pointer& currentPointer =
5735                    mCurrentRawPointerData.pointers[currentPointerIndex];
5736            const RawPointerData::Pointer& lastPointer =
5737                    mLastRawPointerData.pointers[lastPointerIndex];
5738            if (currentPointer.toolType == lastPointer.toolType) {
5739                int64_t deltaX = currentPointer.x - lastPointer.x;
5740                int64_t deltaY = currentPointer.y - lastPointer.y;
5741
5742                uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
5743
5744                // Insert new element into the heap (sift up).
5745                heap[heapSize].currentPointerIndex = currentPointerIndex;
5746                heap[heapSize].lastPointerIndex = lastPointerIndex;
5747                heap[heapSize].distance = distance;
5748                heapSize += 1;
5749            }
5750        }
5751    }
5752
5753    // Heapify
5754    for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
5755        startIndex -= 1;
5756        for (uint32_t parentIndex = startIndex; ;) {
5757            uint32_t childIndex = parentIndex * 2 + 1;
5758            if (childIndex >= heapSize) {
5759                break;
5760            }
5761
5762            if (childIndex + 1 < heapSize
5763                    && heap[childIndex + 1].distance < heap[childIndex].distance) {
5764                childIndex += 1;
5765            }
5766
5767            if (heap[parentIndex].distance <= heap[childIndex].distance) {
5768                break;
5769            }
5770
5771            swap(heap[parentIndex], heap[childIndex]);
5772            parentIndex = childIndex;
5773        }
5774    }
5775
5776#if DEBUG_POINTER_ASSIGNMENT
5777    ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
5778    for (size_t i = 0; i < heapSize; i++) {
5779        ALOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
5780                i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
5781                heap[i].distance);
5782    }
5783#endif
5784
5785    // Pull matches out by increasing order of distance.
5786    // To avoid reassigning pointers that have already been matched, the loop keeps track
5787    // of which last and current pointers have been matched using the matchedXXXBits variables.
5788    // It also tracks the used pointer id bits.
5789    BitSet32 matchedLastBits(0);
5790    BitSet32 matchedCurrentBits(0);
5791    BitSet32 usedIdBits(0);
5792    bool first = true;
5793    for (uint32_t i = min(currentPointerCount, lastPointerCount); heapSize > 0 && i > 0; i--) {
5794        while (heapSize > 0) {
5795            if (first) {
5796                // The first time through the loop, we just consume the root element of
5797                // the heap (the one with smallest distance).
5798                first = false;
5799            } else {
5800                // Previous iterations consumed the root element of the heap.
5801                // Pop root element off of the heap (sift down).
5802                heap[0] = heap[heapSize];
5803                for (uint32_t parentIndex = 0; ;) {
5804                    uint32_t childIndex = parentIndex * 2 + 1;
5805                    if (childIndex >= heapSize) {
5806                        break;
5807                    }
5808
5809                    if (childIndex + 1 < heapSize
5810                            && heap[childIndex + 1].distance < heap[childIndex].distance) {
5811                        childIndex += 1;
5812                    }
5813
5814                    if (heap[parentIndex].distance <= heap[childIndex].distance) {
5815                        break;
5816                    }
5817
5818                    swap(heap[parentIndex], heap[childIndex]);
5819                    parentIndex = childIndex;
5820                }
5821
5822#if DEBUG_POINTER_ASSIGNMENT
5823                ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
5824                for (size_t i = 0; i < heapSize; i++) {
5825                    ALOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
5826                            i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
5827                            heap[i].distance);
5828                }
5829#endif
5830            }
5831
5832            heapSize -= 1;
5833
5834            uint32_t currentPointerIndex = heap[0].currentPointerIndex;
5835            if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
5836
5837            uint32_t lastPointerIndex = heap[0].lastPointerIndex;
5838            if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
5839
5840            matchedCurrentBits.markBit(currentPointerIndex);
5841            matchedLastBits.markBit(lastPointerIndex);
5842
5843            uint32_t id = mLastRawPointerData.pointers[lastPointerIndex].id;
5844            mCurrentRawPointerData.pointers[currentPointerIndex].id = id;
5845            mCurrentRawPointerData.idToIndex[id] = currentPointerIndex;
5846            mCurrentRawPointerData.markIdBit(id,
5847                    mCurrentRawPointerData.isHovering(currentPointerIndex));
5848            usedIdBits.markBit(id);
5849
5850#if DEBUG_POINTER_ASSIGNMENT
5851            ALOGD("assignPointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
5852                    lastPointerIndex, currentPointerIndex, id, heap[0].distance);
5853#endif
5854            break;
5855        }
5856    }
5857
5858    // Assign fresh ids to pointers that were not matched in the process.
5859    for (uint32_t i = currentPointerCount - matchedCurrentBits.count(); i != 0; i--) {
5860        uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit();
5861        uint32_t id = usedIdBits.markFirstUnmarkedBit();
5862
5863        mCurrentRawPointerData.pointers[currentPointerIndex].id = id;
5864        mCurrentRawPointerData.idToIndex[id] = currentPointerIndex;
5865        mCurrentRawPointerData.markIdBit(id,
5866                mCurrentRawPointerData.isHovering(currentPointerIndex));
5867
5868#if DEBUG_POINTER_ASSIGNMENT
5869        ALOGD("assignPointerIds - assigned: cur=%d, id=%d",
5870                currentPointerIndex, id);
5871#endif
5872    }
5873}
5874
5875int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
5876    if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) {
5877        return AKEY_STATE_VIRTUAL;
5878    }
5879
5880    size_t numVirtualKeys = mVirtualKeys.size();
5881    for (size_t i = 0; i < numVirtualKeys; i++) {
5882        const VirtualKey& virtualKey = mVirtualKeys[i];
5883        if (virtualKey.keyCode == keyCode) {
5884            return AKEY_STATE_UP;
5885        }
5886    }
5887
5888    return AKEY_STATE_UNKNOWN;
5889}
5890
5891int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
5892    if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) {
5893        return AKEY_STATE_VIRTUAL;
5894    }
5895
5896    size_t numVirtualKeys = mVirtualKeys.size();
5897    for (size_t i = 0; i < numVirtualKeys; i++) {
5898        const VirtualKey& virtualKey = mVirtualKeys[i];
5899        if (virtualKey.scanCode == scanCode) {
5900            return AKEY_STATE_UP;
5901        }
5902    }
5903
5904    return AKEY_STATE_UNKNOWN;
5905}
5906
5907bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
5908        const int32_t* keyCodes, uint8_t* outFlags) {
5909    size_t numVirtualKeys = mVirtualKeys.size();
5910    for (size_t i = 0; i < numVirtualKeys; i++) {
5911        const VirtualKey& virtualKey = mVirtualKeys[i];
5912
5913        for (size_t i = 0; i < numCodes; i++) {
5914            if (virtualKey.keyCode == keyCodes[i]) {
5915                outFlags[i] = 1;
5916            }
5917        }
5918    }
5919
5920    return true;
5921}
5922
5923
5924// --- SingleTouchInputMapper ---
5925
5926SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
5927        TouchInputMapper(device) {
5928}
5929
5930SingleTouchInputMapper::~SingleTouchInputMapper() {
5931}
5932
5933void SingleTouchInputMapper::reset(nsecs_t when) {
5934    mSingleTouchMotionAccumulator.reset(getDevice());
5935
5936    TouchInputMapper::reset(when);
5937}
5938
5939void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
5940    TouchInputMapper::process(rawEvent);
5941
5942    mSingleTouchMotionAccumulator.process(rawEvent);
5943}
5944
5945void SingleTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) {
5946    if (mTouchButtonAccumulator.isToolActive()) {
5947        mCurrentRawPointerData.pointerCount = 1;
5948        mCurrentRawPointerData.idToIndex[0] = 0;
5949
5950        bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
5951                && (mTouchButtonAccumulator.isHovering()
5952                        || (mRawPointerAxes.pressure.valid
5953                                && mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0));
5954        mCurrentRawPointerData.markIdBit(0, isHovering);
5955
5956        RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[0];
5957        outPointer.id = 0;
5958        outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
5959        outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
5960        outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
5961        outPointer.touchMajor = 0;
5962        outPointer.touchMinor = 0;
5963        outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
5964        outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
5965        outPointer.orientation = 0;
5966        outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
5967        outPointer.tiltX = mSingleTouchMotionAccumulator.getAbsoluteTiltX();
5968        outPointer.tiltY = mSingleTouchMotionAccumulator.getAbsoluteTiltY();
5969        outPointer.toolType = mTouchButtonAccumulator.getToolType();
5970        if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
5971            outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
5972        }
5973        outPointer.isHovering = isHovering;
5974    }
5975}
5976
5977void SingleTouchInputMapper::configureRawPointerAxes() {
5978    TouchInputMapper::configureRawPointerAxes();
5979
5980    getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x);
5981    getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y);
5982    getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure);
5983    getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor);
5984    getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance);
5985    getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX);
5986    getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY);
5987}
5988
5989bool SingleTouchInputMapper::hasStylus() const {
5990    return mTouchButtonAccumulator.hasStylus();
5991}
5992
5993
5994// --- MultiTouchInputMapper ---
5995
5996MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
5997        TouchInputMapper(device) {
5998}
5999
6000MultiTouchInputMapper::~MultiTouchInputMapper() {
6001}
6002
6003void MultiTouchInputMapper::reset(nsecs_t when) {
6004    mMultiTouchMotionAccumulator.reset(getDevice());
6005
6006    mPointerIdBits.clear();
6007
6008    TouchInputMapper::reset(when);
6009}
6010
6011void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
6012    TouchInputMapper::process(rawEvent);
6013
6014    mMultiTouchMotionAccumulator.process(rawEvent);
6015}
6016
6017void MultiTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) {
6018    size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
6019    size_t outCount = 0;
6020    BitSet32 newPointerIdBits;
6021
6022    for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
6023        const MultiTouchMotionAccumulator::Slot* inSlot =
6024                mMultiTouchMotionAccumulator.getSlot(inIndex);
6025        if (!inSlot->isInUse()) {
6026            continue;
6027        }
6028
6029        if (outCount >= MAX_POINTERS) {
6030#if DEBUG_POINTERS
6031            ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
6032                    "ignoring the rest.",
6033                    getDeviceName().string(), MAX_POINTERS);
6034#endif
6035            break; // too many fingers!
6036        }
6037
6038        RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[outCount];
6039        outPointer.x = inSlot->getX();
6040        outPointer.y = inSlot->getY();
6041        outPointer.pressure = inSlot->getPressure();
6042        outPointer.touchMajor = inSlot->getTouchMajor();
6043        outPointer.touchMinor = inSlot->getTouchMinor();
6044        outPointer.toolMajor = inSlot->getToolMajor();
6045        outPointer.toolMinor = inSlot->getToolMinor();
6046        outPointer.orientation = inSlot->getOrientation();
6047        outPointer.distance = inSlot->getDistance();
6048        outPointer.tiltX = 0;
6049        outPointer.tiltY = 0;
6050
6051        outPointer.toolType = inSlot->getToolType();
6052        if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
6053            outPointer.toolType = mTouchButtonAccumulator.getToolType();
6054            if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
6055                outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
6056            }
6057        }
6058
6059        bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
6060                && (mTouchButtonAccumulator.isHovering()
6061                        || (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
6062        outPointer.isHovering = isHovering;
6063
6064        // Assign pointer id using tracking id if available.
6065        if (*outHavePointerIds) {
6066            int32_t trackingId = inSlot->getTrackingId();
6067            int32_t id = -1;
6068            if (trackingId >= 0) {
6069                for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
6070                    uint32_t n = idBits.clearFirstMarkedBit();
6071                    if (mPointerTrackingIdMap[n] == trackingId) {
6072                        id = n;
6073                    }
6074                }
6075
6076                if (id < 0 && !mPointerIdBits.isFull()) {
6077                    id = mPointerIdBits.markFirstUnmarkedBit();
6078                    mPointerTrackingIdMap[id] = trackingId;
6079                }
6080            }
6081            if (id < 0) {
6082                *outHavePointerIds = false;
6083                mCurrentRawPointerData.clearIdBits();
6084                newPointerIdBits.clear();
6085            } else {
6086                outPointer.id = id;
6087                mCurrentRawPointerData.idToIndex[id] = outCount;
6088                mCurrentRawPointerData.markIdBit(id, isHovering);
6089                newPointerIdBits.markBit(id);
6090            }
6091        }
6092
6093        outCount += 1;
6094    }
6095
6096    mCurrentRawPointerData.pointerCount = outCount;
6097    mPointerIdBits = newPointerIdBits;
6098
6099    mMultiTouchMotionAccumulator.finishSync();
6100}
6101
6102void MultiTouchInputMapper::configureRawPointerAxes() {
6103    TouchInputMapper::configureRawPointerAxes();
6104
6105    getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x);
6106    getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y);
6107    getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor);
6108    getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor);
6109    getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor);
6110    getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor);
6111    getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation);
6112    getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure);
6113    getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance);
6114    getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId);
6115    getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot);
6116
6117    if (mRawPointerAxes.trackingId.valid
6118            && mRawPointerAxes.slot.valid
6119            && mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
6120        size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
6121        if (slotCount > MAX_SLOTS) {
6122            ALOGW("MultiTouch Device %s reported %d slots but the framework "
6123                    "only supports a maximum of %d slots at this time.",
6124                    getDeviceName().string(), slotCount, MAX_SLOTS);
6125            slotCount = MAX_SLOTS;
6126        }
6127        mMultiTouchMotionAccumulator.configure(getDevice(),
6128                slotCount, true /*usingSlotsProtocol*/);
6129    } else {
6130        mMultiTouchMotionAccumulator.configure(getDevice(),
6131                MAX_POINTERS, false /*usingSlotsProtocol*/);
6132    }
6133}
6134
6135bool MultiTouchInputMapper::hasStylus() const {
6136    return mMultiTouchMotionAccumulator.hasStylus()
6137            || mTouchButtonAccumulator.hasStylus();
6138}
6139
6140
6141// --- JoystickInputMapper ---
6142
6143JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
6144        InputMapper(device) {
6145}
6146
6147JoystickInputMapper::~JoystickInputMapper() {
6148}
6149
6150uint32_t JoystickInputMapper::getSources() {
6151    return AINPUT_SOURCE_JOYSTICK;
6152}
6153
6154void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
6155    InputMapper::populateDeviceInfo(info);
6156
6157    for (size_t i = 0; i < mAxes.size(); i++) {
6158        const Axis& axis = mAxes.valueAt(i);
6159        addMotionRange(axis.axisInfo.axis, axis, info);
6160
6161        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
6162            addMotionRange(axis.axisInfo.highAxis, axis, info);
6163
6164        }
6165    }
6166}
6167
6168void JoystickInputMapper::addMotionRange(int32_t axisId, const Axis& axis,
6169        InputDeviceInfo* info) {
6170    info->addMotionRange(axisId, AINPUT_SOURCE_JOYSTICK,
6171            axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
6172    /* In order to ease the transition for developers from using the old axes
6173     * to the newer, more semantically correct axes, we'll continue to register
6174     * the old axes as duplicates of their corresponding new ones.  */
6175    int32_t compatAxis = getCompatAxis(axisId);
6176    if (compatAxis >= 0) {
6177        info->addMotionRange(compatAxis, AINPUT_SOURCE_JOYSTICK,
6178                axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
6179    }
6180}
6181
6182/* A mapping from axes the joystick actually has to the axes that should be
6183 * artificially created for compatibility purposes.
6184 * Returns -1 if no compatibility axis is needed. */
6185int32_t JoystickInputMapper::getCompatAxis(int32_t axis) {
6186    switch(axis) {
6187    case AMOTION_EVENT_AXIS_LTRIGGER:
6188        return AMOTION_EVENT_AXIS_BRAKE;
6189    case AMOTION_EVENT_AXIS_RTRIGGER:
6190        return AMOTION_EVENT_AXIS_GAS;
6191    }
6192    return -1;
6193}
6194
6195void JoystickInputMapper::dump(String8& dump) {
6196    dump.append(INDENT2 "Joystick Input Mapper:\n");
6197
6198    dump.append(INDENT3 "Axes:\n");
6199    size_t numAxes = mAxes.size();
6200    for (size_t i = 0; i < numAxes; i++) {
6201        const Axis& axis = mAxes.valueAt(i);
6202        const char* label = getAxisLabel(axis.axisInfo.axis);
6203        if (label) {
6204            dump.appendFormat(INDENT4 "%s", label);
6205        } else {
6206            dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis);
6207        }
6208        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
6209            label = getAxisLabel(axis.axisInfo.highAxis);
6210            if (label) {
6211                dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue);
6212            } else {
6213                dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis,
6214                        axis.axisInfo.splitValue);
6215            }
6216        } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
6217            dump.append(" (invert)");
6218        }
6219
6220        dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f, resolution=%0.5f\n",
6221                axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
6222        dump.appendFormat(INDENT4 "  scale=%0.5f, offset=%0.5f, "
6223                "highScale=%0.5f, highOffset=%0.5f\n",
6224                axis.scale, axis.offset, axis.highScale, axis.highOffset);
6225        dump.appendFormat(INDENT4 "  rawAxis=%d, rawMin=%d, rawMax=%d, "
6226                "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n",
6227                mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
6228                axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, axis.rawAxisInfo.resolution);
6229    }
6230}
6231
6232void JoystickInputMapper::configure(nsecs_t when,
6233        const InputReaderConfiguration* config, uint32_t changes) {
6234    InputMapper::configure(when, config, changes);
6235
6236    if (!changes) { // first time only
6237        // Collect all axes.
6238        for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
6239            if (!(getAbsAxisUsage(abs, getDevice()->getClasses())
6240                    & INPUT_DEVICE_CLASS_JOYSTICK)) {
6241                continue; // axis must be claimed by a different device
6242            }
6243
6244            RawAbsoluteAxisInfo rawAxisInfo;
6245            getAbsoluteAxisInfo(abs, &rawAxisInfo);
6246            if (rawAxisInfo.valid) {
6247                // Map axis.
6248                AxisInfo axisInfo;
6249                bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
6250                if (!explicitlyMapped) {
6251                    // Axis is not explicitly mapped, will choose a generic axis later.
6252                    axisInfo.mode = AxisInfo::MODE_NORMAL;
6253                    axisInfo.axis = -1;
6254                }
6255
6256                // Apply flat override.
6257                int32_t rawFlat = axisInfo.flatOverride < 0
6258                        ? rawAxisInfo.flat : axisInfo.flatOverride;
6259
6260                // Calculate scaling factors and limits.
6261                Axis axis;
6262                if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
6263                    float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
6264                    float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
6265                    axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
6266                            scale, 0.0f, highScale, 0.0f,
6267                            0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
6268                            rawAxisInfo.resolution * scale);
6269                } else if (isCenteredAxis(axisInfo.axis)) {
6270                    float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
6271                    float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
6272                    axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
6273                            scale, offset, scale, offset,
6274                            -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
6275                            rawAxisInfo.resolution * scale);
6276                } else {
6277                    float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
6278                    axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
6279                            scale, 0.0f, scale, 0.0f,
6280                            0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
6281                            rawAxisInfo.resolution * scale);
6282                }
6283
6284                // To eliminate noise while the joystick is at rest, filter out small variations
6285                // in axis values up front.
6286                axis.filter = axis.fuzz ? axis.fuzz : axis.flat * 0.25f;
6287
6288                mAxes.add(abs, axis);
6289            }
6290        }
6291
6292        // If there are too many axes, start dropping them.
6293        // Prefer to keep explicitly mapped axes.
6294        if (mAxes.size() > PointerCoords::MAX_AXES) {
6295            ALOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
6296                    getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
6297            pruneAxes(true);
6298            pruneAxes(false);
6299        }
6300
6301        // Assign generic axis ids to remaining axes.
6302        int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
6303        size_t numAxes = mAxes.size();
6304        for (size_t i = 0; i < numAxes; i++) {
6305            Axis& axis = mAxes.editValueAt(i);
6306            if (axis.axisInfo.axis < 0) {
6307                while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
6308                        && haveAxis(nextGenericAxisId)) {
6309                    nextGenericAxisId += 1;
6310                }
6311
6312                if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
6313                    axis.axisInfo.axis = nextGenericAxisId;
6314                    nextGenericAxisId += 1;
6315                } else {
6316                    ALOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
6317                            "have already been assigned to other axes.",
6318                            getDeviceName().string(), mAxes.keyAt(i));
6319                    mAxes.removeItemsAt(i--);
6320                    numAxes -= 1;
6321                }
6322            }
6323        }
6324    }
6325}
6326
6327bool JoystickInputMapper::haveAxis(int32_t axisId) {
6328    size_t numAxes = mAxes.size();
6329    for (size_t i = 0; i < numAxes; i++) {
6330        const Axis& axis = mAxes.valueAt(i);
6331        if (axis.axisInfo.axis == axisId
6332                || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
6333                        && axis.axisInfo.highAxis == axisId)) {
6334            return true;
6335        }
6336    }
6337    return false;
6338}
6339
6340void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
6341    size_t i = mAxes.size();
6342    while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
6343        if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
6344            continue;
6345        }
6346        ALOGI("Discarding joystick '%s' axis %d because there are too many axes.",
6347                getDeviceName().string(), mAxes.keyAt(i));
6348        mAxes.removeItemsAt(i);
6349    }
6350}
6351
6352bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
6353    switch (axis) {
6354    case AMOTION_EVENT_AXIS_X:
6355    case AMOTION_EVENT_AXIS_Y:
6356    case AMOTION_EVENT_AXIS_Z:
6357    case AMOTION_EVENT_AXIS_RX:
6358    case AMOTION_EVENT_AXIS_RY:
6359    case AMOTION_EVENT_AXIS_RZ:
6360    case AMOTION_EVENT_AXIS_HAT_X:
6361    case AMOTION_EVENT_AXIS_HAT_Y:
6362    case AMOTION_EVENT_AXIS_ORIENTATION:
6363    case AMOTION_EVENT_AXIS_RUDDER:
6364    case AMOTION_EVENT_AXIS_WHEEL:
6365        return true;
6366    default:
6367        return false;
6368    }
6369}
6370
6371void JoystickInputMapper::reset(nsecs_t when) {
6372    // Recenter all axes.
6373    size_t numAxes = mAxes.size();
6374    for (size_t i = 0; i < numAxes; i++) {
6375        Axis& axis = mAxes.editValueAt(i);
6376        axis.resetValue();
6377    }
6378
6379    InputMapper::reset(when);
6380}
6381
6382void JoystickInputMapper::process(const RawEvent* rawEvent) {
6383    switch (rawEvent->type) {
6384    case EV_ABS: {
6385        ssize_t index = mAxes.indexOfKey(rawEvent->code);
6386        if (index >= 0) {
6387            Axis& axis = mAxes.editValueAt(index);
6388            float newValue, highNewValue;
6389            switch (axis.axisInfo.mode) {
6390            case AxisInfo::MODE_INVERT:
6391                newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
6392                        * axis.scale + axis.offset;
6393                highNewValue = 0.0f;
6394                break;
6395            case AxisInfo::MODE_SPLIT:
6396                if (rawEvent->value < axis.axisInfo.splitValue) {
6397                    newValue = (axis.axisInfo.splitValue - rawEvent->value)
6398                            * axis.scale + axis.offset;
6399                    highNewValue = 0.0f;
6400                } else if (rawEvent->value > axis.axisInfo.splitValue) {
6401                    newValue = 0.0f;
6402                    highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
6403                            * axis.highScale + axis.highOffset;
6404                } else {
6405                    newValue = 0.0f;
6406                    highNewValue = 0.0f;
6407                }
6408                break;
6409            default:
6410                newValue = rawEvent->value * axis.scale + axis.offset;
6411                highNewValue = 0.0f;
6412                break;
6413            }
6414            axis.newValue = newValue;
6415            axis.highNewValue = highNewValue;
6416        }
6417        break;
6418    }
6419
6420    case EV_SYN:
6421        switch (rawEvent->code) {
6422        case SYN_REPORT:
6423            sync(rawEvent->when, false /*force*/);
6424            break;
6425        }
6426        break;
6427    }
6428}
6429
6430void JoystickInputMapper::sync(nsecs_t when, bool force) {
6431    if (!filterAxes(force)) {
6432        return;
6433    }
6434
6435    int32_t metaState = mContext->getGlobalMetaState();
6436    int32_t buttonState = 0;
6437
6438    PointerProperties pointerProperties;
6439    pointerProperties.clear();
6440    pointerProperties.id = 0;
6441    pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
6442
6443    PointerCoords pointerCoords;
6444    pointerCoords.clear();
6445
6446    size_t numAxes = mAxes.size();
6447    for (size_t i = 0; i < numAxes; i++) {
6448        const Axis& axis = mAxes.valueAt(i);
6449        setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.axis, axis.currentValue);
6450        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
6451            setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.highAxis,
6452                    axis.highCurrentValue);
6453        }
6454    }
6455
6456    // Moving a joystick axis should not wake the device because joysticks can
6457    // be fairly noisy even when not in use.  On the other hand, pushing a gamepad
6458    // button will likely wake the device.
6459    // TODO: Use the input device configuration to control this behavior more finely.
6460    uint32_t policyFlags = 0;
6461
6462    NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
6463            AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
6464            ADISPLAY_ID_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, 0);
6465    getListener()->notifyMotion(&args);
6466}
6467
6468void JoystickInputMapper::setPointerCoordsAxisValue(PointerCoords* pointerCoords,
6469        int32_t axis, float value) {
6470    pointerCoords->setAxisValue(axis, value);
6471    /* In order to ease the transition for developers from using the old axes
6472     * to the newer, more semantically correct axes, we'll continue to produce
6473     * values for the old axes as mirrors of the value of their corresponding
6474     * new axes. */
6475    int32_t compatAxis = getCompatAxis(axis);
6476    if (compatAxis >= 0) {
6477        pointerCoords->setAxisValue(compatAxis, value);
6478    }
6479}
6480
6481bool JoystickInputMapper::filterAxes(bool force) {
6482    bool atLeastOneSignificantChange = force;
6483    size_t numAxes = mAxes.size();
6484    for (size_t i = 0; i < numAxes; i++) {
6485        Axis& axis = mAxes.editValueAt(i);
6486        if (force || hasValueChangedSignificantly(axis.filter,
6487                axis.newValue, axis.currentValue, axis.min, axis.max)) {
6488            axis.currentValue = axis.newValue;
6489            atLeastOneSignificantChange = true;
6490        }
6491        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
6492            if (force || hasValueChangedSignificantly(axis.filter,
6493                    axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
6494                axis.highCurrentValue = axis.highNewValue;
6495                atLeastOneSignificantChange = true;
6496            }
6497        }
6498    }
6499    return atLeastOneSignificantChange;
6500}
6501
6502bool JoystickInputMapper::hasValueChangedSignificantly(
6503        float filter, float newValue, float currentValue, float min, float max) {
6504    if (newValue != currentValue) {
6505        // Filter out small changes in value unless the value is converging on the axis
6506        // bounds or center point.  This is intended to reduce the amount of information
6507        // sent to applications by particularly noisy joysticks (such as PS3).
6508        if (fabs(newValue - currentValue) > filter
6509                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
6510                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
6511                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
6512            return true;
6513        }
6514    }
6515    return false;
6516}
6517
6518bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
6519        float filter, float newValue, float currentValue, float thresholdValue) {
6520    float newDistance = fabs(newValue - thresholdValue);
6521    if (newDistance < filter) {
6522        float oldDistance = fabs(currentValue - thresholdValue);
6523        if (newDistance < oldDistance) {
6524            return true;
6525        }
6526    }
6527    return false;
6528}
6529
6530} // namespace android
6531