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