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