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