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