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