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