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