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