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