InputReader.cpp revision 4e3f7206eb0af14d3da4c03bdf9918161774e726
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(PointerControllerInterface::TRANSITION_IMMEDIATE);
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(PointerControllerInterface::TRANSITION_GRADUAL);
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: select the default gesture mode based on whether the device supports
1877    // distinct multitouch
1878    mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
1879
1880    String8 gestureModeString;
1881    if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
1882            gestureModeString)) {
1883        if (gestureModeString == "pointer") {
1884            mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER;
1885        } else if (gestureModeString == "spots") {
1886            mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
1887        } else if (gestureModeString != "default") {
1888            LOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
1889        }
1890    }
1891
1892    if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
1893            || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
1894        // The device is a cursor device with a touch pad attached.
1895        // By default don't use the touch pad to move the pointer.
1896        mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
1897    } else {
1898        // The device is just a touch pad.
1899        // By default use the touch pad to move the pointer and to perform related gestures.
1900        mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
1901    }
1902
1903    String8 deviceTypeString;
1904    if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
1905            deviceTypeString)) {
1906        if (deviceTypeString == "touchScreen") {
1907            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1908        } else if (deviceTypeString == "touchPad") {
1909            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
1910        } else if (deviceTypeString == "pointer") {
1911            mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
1912        } else if (deviceTypeString != "default") {
1913            LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
1914        }
1915    }
1916
1917    mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1918    getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
1919            mParameters.orientationAware);
1920
1921    mParameters.associatedDisplayId = mParameters.orientationAware
1922            || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
1923            || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
1924            ? 0 : -1;
1925}
1926
1927void TouchInputMapper::dumpParameters(String8& dump) {
1928    dump.append(INDENT3 "Parameters:\n");
1929
1930    switch (mParameters.gestureMode) {
1931    case Parameters::GESTURE_MODE_POINTER:
1932        dump.append(INDENT4 "GestureMode: pointer\n");
1933        break;
1934    case Parameters::GESTURE_MODE_SPOTS:
1935        dump.append(INDENT4 "GestureMode: spots\n");
1936        break;
1937    default:
1938        assert(false);
1939    }
1940
1941    switch (mParameters.deviceType) {
1942    case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1943        dump.append(INDENT4 "DeviceType: touchScreen\n");
1944        break;
1945    case Parameters::DEVICE_TYPE_TOUCH_PAD:
1946        dump.append(INDENT4 "DeviceType: touchPad\n");
1947        break;
1948    case Parameters::DEVICE_TYPE_POINTER:
1949        dump.append(INDENT4 "DeviceType: pointer\n");
1950        break;
1951    default:
1952        assert(false);
1953    }
1954
1955    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1956            mParameters.associatedDisplayId);
1957    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1958            toString(mParameters.orientationAware));
1959
1960    dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
1961            toString(mParameters.useBadTouchFilter));
1962    dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
1963            toString(mParameters.useAveragingTouchFilter));
1964    dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
1965            toString(mParameters.useJumpyTouchFilter));
1966}
1967
1968void TouchInputMapper::configureRawAxes() {
1969    mRawAxes.x.clear();
1970    mRawAxes.y.clear();
1971    mRawAxes.pressure.clear();
1972    mRawAxes.touchMajor.clear();
1973    mRawAxes.touchMinor.clear();
1974    mRawAxes.toolMajor.clear();
1975    mRawAxes.toolMinor.clear();
1976    mRawAxes.orientation.clear();
1977}
1978
1979void TouchInputMapper::dumpRawAxes(String8& dump) {
1980    dump.append(INDENT3 "Raw Axes:\n");
1981    dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X");
1982    dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y");
1983    dumpRawAbsoluteAxisInfo(dump, mRawAxes.pressure, "Pressure");
1984    dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1985    dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1986    dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1987    dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1988    dumpRawAbsoluteAxisInfo(dump, mRawAxes.orientation, "Orientation");
1989}
1990
1991bool TouchInputMapper::configureSurfaceLocked() {
1992    // Ensure we have valid X and Y axes.
1993    if (!mRawAxes.x.valid || !mRawAxes.y.valid) {
1994        LOGW(INDENT "Touch device '%s' did not report support for X or Y axis!  "
1995                "The device will be inoperable.", getDeviceName().string());
1996        return false;
1997    }
1998
1999    // Update orientation and dimensions if needed.
2000    int32_t orientation = DISPLAY_ORIENTATION_0;
2001    int32_t width = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
2002    int32_t height = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
2003
2004    if (mParameters.associatedDisplayId >= 0) {
2005        // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
2006        if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
2007                &mLocked.associatedDisplayWidth, &mLocked.associatedDisplayHeight,
2008                &mLocked.associatedDisplayOrientation)) {
2009            return false;
2010        }
2011
2012        // A touch screen inherits the dimensions of the display.
2013        if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
2014            width = mLocked.associatedDisplayWidth;
2015            height = mLocked.associatedDisplayHeight;
2016        }
2017
2018        // The device inherits the orientation of the display if it is orientation aware.
2019        if (mParameters.orientationAware) {
2020            orientation = mLocked.associatedDisplayOrientation;
2021        }
2022    }
2023
2024    if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
2025            && mPointerController == NULL) {
2026        mPointerController = getPolicy()->obtainPointerController(getDeviceId());
2027    }
2028
2029    bool orientationChanged = mLocked.surfaceOrientation != orientation;
2030    if (orientationChanged) {
2031        mLocked.surfaceOrientation = orientation;
2032    }
2033
2034    bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
2035    if (sizeChanged) {
2036        LOGI("Device reconfigured: id=%d, name='%s', surface size is now %dx%d",
2037                getDeviceId(), getDeviceName().string(), width, height);
2038
2039        mLocked.surfaceWidth = width;
2040        mLocked.surfaceHeight = height;
2041
2042        // Configure X and Y factors.
2043        mLocked.xScale = float(width) / (mRawAxes.x.maxValue - mRawAxes.x.minValue + 1);
2044        mLocked.yScale = float(height) / (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1);
2045        mLocked.xPrecision = 1.0f / mLocked.xScale;
2046        mLocked.yPrecision = 1.0f / mLocked.yScale;
2047
2048        mLocked.orientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
2049        mLocked.orientedRanges.x.source = mTouchSource;
2050        mLocked.orientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
2051        mLocked.orientedRanges.y.source = mTouchSource;
2052
2053        configureVirtualKeysLocked();
2054
2055        // Scale factor for terms that are not oriented in a particular axis.
2056        // If the pixels are square then xScale == yScale otherwise we fake it
2057        // by choosing an average.
2058        mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
2059
2060        // Size of diagonal axis.
2061        float diagonalSize = hypotf(width, height);
2062
2063        // TouchMajor and TouchMinor factors.
2064        if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
2065            mLocked.orientedRanges.haveTouchSize = true;
2066
2067            mLocked.orientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
2068            mLocked.orientedRanges.touchMajor.source = mTouchSource;
2069            mLocked.orientedRanges.touchMajor.min = 0;
2070            mLocked.orientedRanges.touchMajor.max = diagonalSize;
2071            mLocked.orientedRanges.touchMajor.flat = 0;
2072            mLocked.orientedRanges.touchMajor.fuzz = 0;
2073
2074            mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
2075            mLocked.orientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
2076        }
2077
2078        // ToolMajor and ToolMinor factors.
2079        mLocked.toolSizeLinearScale = 0;
2080        mLocked.toolSizeLinearBias = 0;
2081        mLocked.toolSizeAreaScale = 0;
2082        mLocked.toolSizeAreaBias = 0;
2083        if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2084            if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
2085                if (mCalibration.haveToolSizeLinearScale) {
2086                    mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
2087                } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
2088                    mLocked.toolSizeLinearScale = float(min(width, height))
2089                            / mRawAxes.toolMajor.maxValue;
2090                }
2091
2092                if (mCalibration.haveToolSizeLinearBias) {
2093                    mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
2094                }
2095            } else if (mCalibration.toolSizeCalibration ==
2096                    Calibration::TOOL_SIZE_CALIBRATION_AREA) {
2097                if (mCalibration.haveToolSizeLinearScale) {
2098                    mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
2099                } else {
2100                    mLocked.toolSizeLinearScale = min(width, height);
2101                }
2102
2103                if (mCalibration.haveToolSizeLinearBias) {
2104                    mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
2105                }
2106
2107                if (mCalibration.haveToolSizeAreaScale) {
2108                    mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
2109                } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
2110                    mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
2111                }
2112
2113                if (mCalibration.haveToolSizeAreaBias) {
2114                    mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
2115                }
2116            }
2117
2118            mLocked.orientedRanges.haveToolSize = true;
2119
2120            mLocked.orientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
2121            mLocked.orientedRanges.toolMajor.source = mTouchSource;
2122            mLocked.orientedRanges.toolMajor.min = 0;
2123            mLocked.orientedRanges.toolMajor.max = diagonalSize;
2124            mLocked.orientedRanges.toolMajor.flat = 0;
2125            mLocked.orientedRanges.toolMajor.fuzz = 0;
2126
2127            mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
2128            mLocked.orientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
2129        }
2130
2131        // Pressure factors.
2132        mLocked.pressureScale = 0;
2133        if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
2134            RawAbsoluteAxisInfo rawPressureAxis;
2135            switch (mCalibration.pressureSource) {
2136            case Calibration::PRESSURE_SOURCE_PRESSURE:
2137                rawPressureAxis = mRawAxes.pressure;
2138                break;
2139            case Calibration::PRESSURE_SOURCE_TOUCH:
2140                rawPressureAxis = mRawAxes.touchMajor;
2141                break;
2142            default:
2143                rawPressureAxis.clear();
2144            }
2145
2146            if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
2147                    || mCalibration.pressureCalibration
2148                            == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
2149                if (mCalibration.havePressureScale) {
2150                    mLocked.pressureScale = mCalibration.pressureScale;
2151                } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
2152                    mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
2153                }
2154            }
2155
2156            mLocked.orientedRanges.havePressure = true;
2157
2158            mLocked.orientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
2159            mLocked.orientedRanges.pressure.source = mTouchSource;
2160            mLocked.orientedRanges.pressure.min = 0;
2161            mLocked.orientedRanges.pressure.max = 1.0;
2162            mLocked.orientedRanges.pressure.flat = 0;
2163            mLocked.orientedRanges.pressure.fuzz = 0;
2164        }
2165
2166        // Size factors.
2167        mLocked.sizeScale = 0;
2168        if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
2169            if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
2170                if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
2171                    mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
2172                }
2173            }
2174
2175            mLocked.orientedRanges.haveSize = true;
2176
2177            mLocked.orientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
2178            mLocked.orientedRanges.size.source = mTouchSource;
2179            mLocked.orientedRanges.size.min = 0;
2180            mLocked.orientedRanges.size.max = 1.0;
2181            mLocked.orientedRanges.size.flat = 0;
2182            mLocked.orientedRanges.size.fuzz = 0;
2183        }
2184
2185        // Orientation
2186        mLocked.orientationScale = 0;
2187        if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
2188            if (mCalibration.orientationCalibration
2189                    == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
2190                if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
2191                    mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
2192                }
2193            }
2194
2195            mLocked.orientedRanges.haveOrientation = true;
2196
2197            mLocked.orientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
2198            mLocked.orientedRanges.orientation.source = mTouchSource;
2199            mLocked.orientedRanges.orientation.min = - M_PI_2;
2200            mLocked.orientedRanges.orientation.max = M_PI_2;
2201            mLocked.orientedRanges.orientation.flat = 0;
2202            mLocked.orientedRanges.orientation.fuzz = 0;
2203        }
2204    }
2205
2206    if (orientationChanged || sizeChanged) {
2207        // Compute oriented surface dimensions, precision, scales and ranges.
2208        // Note that the maximum value reported is an inclusive maximum value so it is one
2209        // unit less than the total width or height of surface.
2210        switch (mLocked.surfaceOrientation) {
2211        case DISPLAY_ORIENTATION_90:
2212        case DISPLAY_ORIENTATION_270:
2213            mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
2214            mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
2215
2216            mLocked.orientedXPrecision = mLocked.yPrecision;
2217            mLocked.orientedYPrecision = mLocked.xPrecision;
2218
2219            mLocked.orientedRanges.x.min = 0;
2220            mLocked.orientedRanges.x.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue)
2221                    * mLocked.yScale;
2222            mLocked.orientedRanges.x.flat = 0;
2223            mLocked.orientedRanges.x.fuzz = mLocked.yScale;
2224
2225            mLocked.orientedRanges.y.min = 0;
2226            mLocked.orientedRanges.y.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue)
2227                    * mLocked.xScale;
2228            mLocked.orientedRanges.y.flat = 0;
2229            mLocked.orientedRanges.y.fuzz = mLocked.xScale;
2230            break;
2231
2232        default:
2233            mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
2234            mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
2235
2236            mLocked.orientedXPrecision = mLocked.xPrecision;
2237            mLocked.orientedYPrecision = mLocked.yPrecision;
2238
2239            mLocked.orientedRanges.x.min = 0;
2240            mLocked.orientedRanges.x.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue)
2241                    * mLocked.xScale;
2242            mLocked.orientedRanges.x.flat = 0;
2243            mLocked.orientedRanges.x.fuzz = mLocked.xScale;
2244
2245            mLocked.orientedRanges.y.min = 0;
2246            mLocked.orientedRanges.y.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue)
2247                    * mLocked.yScale;
2248            mLocked.orientedRanges.y.flat = 0;
2249            mLocked.orientedRanges.y.fuzz = mLocked.yScale;
2250            break;
2251        }
2252
2253        // Compute pointer gesture detection parameters.
2254        // TODO: These factors should not be hardcoded.
2255        if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
2256            int32_t rawWidth = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
2257            int32_t rawHeight = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
2258            float rawDiagonal = hypotf(rawWidth, rawHeight);
2259            float displayDiagonal = hypotf(mLocked.associatedDisplayWidth,
2260                    mLocked.associatedDisplayHeight);
2261
2262            // Scale movements such that one whole swipe of the touch pad covers a
2263            // given area relative to the diagonal size of the display.
2264            // Assume that the touch pad has a square aspect ratio such that movements in
2265            // X and Y of the same number of raw units cover the same physical distance.
2266            const float scaleFactor = 0.8f;
2267
2268            mLocked.pointerGestureXMovementScale = GESTURE_MOVEMENT_SPEED_RATIO
2269                    * displayDiagonal / rawDiagonal;
2270            mLocked.pointerGestureYMovementScale = mLocked.pointerGestureXMovementScale;
2271
2272            // Scale zooms to cover a smaller range of the display than movements do.
2273            // This value determines the area around the pointer that is affected by freeform
2274            // pointer gestures.
2275            mLocked.pointerGestureXZoomScale = GESTURE_ZOOM_SPEED_RATIO
2276                    * displayDiagonal / rawDiagonal;
2277            mLocked.pointerGestureYZoomScale = mLocked.pointerGestureXZoomScale;
2278
2279            // Max width between pointers to detect a swipe gesture is more than some fraction
2280            // of the diagonal axis of the touch pad.  Touches that are wider than this are
2281            // translated into freeform gestures.
2282            mLocked.pointerGestureMaxSwipeWidth = SWIPE_MAX_WIDTH_RATIO * rawDiagonal;
2283
2284            // Reset the current pointer gesture.
2285            mPointerGesture.reset();
2286
2287            // Remove any current spots.
2288            if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
2289                mPointerController->clearSpots();
2290            }
2291        }
2292    }
2293
2294    return true;
2295}
2296
2297void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
2298    dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
2299    dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
2300    dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
2301}
2302
2303void TouchInputMapper::configureVirtualKeysLocked() {
2304    Vector<VirtualKeyDefinition> virtualKeyDefinitions;
2305    getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
2306
2307    mLocked.virtualKeys.clear();
2308
2309    if (virtualKeyDefinitions.size() == 0) {
2310        return;
2311    }
2312
2313    mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
2314
2315    int32_t touchScreenLeft = mRawAxes.x.minValue;
2316    int32_t touchScreenTop = mRawAxes.y.minValue;
2317    int32_t touchScreenWidth = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
2318    int32_t touchScreenHeight = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
2319
2320    for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
2321        const VirtualKeyDefinition& virtualKeyDefinition =
2322                virtualKeyDefinitions[i];
2323
2324        mLocked.virtualKeys.add();
2325        VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
2326
2327        virtualKey.scanCode = virtualKeyDefinition.scanCode;
2328        int32_t keyCode;
2329        uint32_t flags;
2330        if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode,
2331                & keyCode, & flags)) {
2332            LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
2333                    virtualKey.scanCode);
2334            mLocked.virtualKeys.pop(); // drop the key
2335            continue;
2336        }
2337
2338        virtualKey.keyCode = keyCode;
2339        virtualKey.flags = flags;
2340
2341        // convert the key definition's display coordinates into touch coordinates for a hit box
2342        int32_t halfWidth = virtualKeyDefinition.width / 2;
2343        int32_t halfHeight = virtualKeyDefinition.height / 2;
2344
2345        virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
2346                * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
2347        virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
2348                * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
2349        virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
2350                * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
2351        virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
2352                * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
2353    }
2354}
2355
2356void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
2357    if (!mLocked.virtualKeys.isEmpty()) {
2358        dump.append(INDENT3 "Virtual Keys:\n");
2359
2360        for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
2361            const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
2362            dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
2363                    "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
2364                    i, virtualKey.scanCode, virtualKey.keyCode,
2365                    virtualKey.hitLeft, virtualKey.hitRight,
2366                    virtualKey.hitTop, virtualKey.hitBottom);
2367        }
2368    }
2369}
2370
2371void TouchInputMapper::parseCalibration() {
2372    const PropertyMap& in = getDevice()->getConfiguration();
2373    Calibration& out = mCalibration;
2374
2375    // Touch Size
2376    out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
2377    String8 touchSizeCalibrationString;
2378    if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
2379        if (touchSizeCalibrationString == "none") {
2380            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
2381        } else if (touchSizeCalibrationString == "geometric") {
2382            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
2383        } else if (touchSizeCalibrationString == "pressure") {
2384            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
2385        } else if (touchSizeCalibrationString != "default") {
2386            LOGW("Invalid value for touch.touchSize.calibration: '%s'",
2387                    touchSizeCalibrationString.string());
2388        }
2389    }
2390
2391    // Tool Size
2392    out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
2393    String8 toolSizeCalibrationString;
2394    if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
2395        if (toolSizeCalibrationString == "none") {
2396            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
2397        } else if (toolSizeCalibrationString == "geometric") {
2398            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
2399        } else if (toolSizeCalibrationString == "linear") {
2400            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
2401        } else if (toolSizeCalibrationString == "area") {
2402            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
2403        } else if (toolSizeCalibrationString != "default") {
2404            LOGW("Invalid value for touch.toolSize.calibration: '%s'",
2405                    toolSizeCalibrationString.string());
2406        }
2407    }
2408
2409    out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
2410            out.toolSizeLinearScale);
2411    out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
2412            out.toolSizeLinearBias);
2413    out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
2414            out.toolSizeAreaScale);
2415    out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
2416            out.toolSizeAreaBias);
2417    out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
2418            out.toolSizeIsSummed);
2419
2420    // Pressure
2421    out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
2422    String8 pressureCalibrationString;
2423    if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
2424        if (pressureCalibrationString == "none") {
2425            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2426        } else if (pressureCalibrationString == "physical") {
2427            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
2428        } else if (pressureCalibrationString == "amplitude") {
2429            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2430        } else if (pressureCalibrationString != "default") {
2431            LOGW("Invalid value for touch.pressure.calibration: '%s'",
2432                    pressureCalibrationString.string());
2433        }
2434    }
2435
2436    out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
2437    String8 pressureSourceString;
2438    if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
2439        if (pressureSourceString == "pressure") {
2440            out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2441        } else if (pressureSourceString == "touch") {
2442            out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2443        } else if (pressureSourceString != "default") {
2444            LOGW("Invalid value for touch.pressure.source: '%s'",
2445                    pressureSourceString.string());
2446        }
2447    }
2448
2449    out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
2450            out.pressureScale);
2451
2452    // Size
2453    out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
2454    String8 sizeCalibrationString;
2455    if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
2456        if (sizeCalibrationString == "none") {
2457            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2458        } else if (sizeCalibrationString == "normalized") {
2459            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2460        } else if (sizeCalibrationString != "default") {
2461            LOGW("Invalid value for touch.size.calibration: '%s'",
2462                    sizeCalibrationString.string());
2463        }
2464    }
2465
2466    // Orientation
2467    out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
2468    String8 orientationCalibrationString;
2469    if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
2470        if (orientationCalibrationString == "none") {
2471            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2472        } else if (orientationCalibrationString == "interpolated") {
2473            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2474        } else if (orientationCalibrationString == "vector") {
2475            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
2476        } else if (orientationCalibrationString != "default") {
2477            LOGW("Invalid value for touch.orientation.calibration: '%s'",
2478                    orientationCalibrationString.string());
2479        }
2480    }
2481}
2482
2483void TouchInputMapper::resolveCalibration() {
2484    // Pressure
2485    switch (mCalibration.pressureSource) {
2486    case Calibration::PRESSURE_SOURCE_DEFAULT:
2487        if (mRawAxes.pressure.valid) {
2488            mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2489        } else if (mRawAxes.touchMajor.valid) {
2490            mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2491        }
2492        break;
2493
2494    case Calibration::PRESSURE_SOURCE_PRESSURE:
2495        if (! mRawAxes.pressure.valid) {
2496            LOGW("Calibration property touch.pressure.source is 'pressure' but "
2497                    "the pressure axis is not available.");
2498        }
2499        break;
2500
2501    case Calibration::PRESSURE_SOURCE_TOUCH:
2502        if (! mRawAxes.touchMajor.valid) {
2503            LOGW("Calibration property touch.pressure.source is 'touch' but "
2504                    "the touchMajor axis is not available.");
2505        }
2506        break;
2507
2508    default:
2509        break;
2510    }
2511
2512    switch (mCalibration.pressureCalibration) {
2513    case Calibration::PRESSURE_CALIBRATION_DEFAULT:
2514        if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
2515            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2516        } else {
2517            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2518        }
2519        break;
2520
2521    default:
2522        break;
2523    }
2524
2525    // Tool Size
2526    switch (mCalibration.toolSizeCalibration) {
2527    case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
2528        if (mRawAxes.toolMajor.valid) {
2529            mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
2530        } else {
2531            mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
2532        }
2533        break;
2534
2535    default:
2536        break;
2537    }
2538
2539    // Touch Size
2540    switch (mCalibration.touchSizeCalibration) {
2541    case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
2542        if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
2543                && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2544            mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
2545        } else {
2546            mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
2547        }
2548        break;
2549
2550    default:
2551        break;
2552    }
2553
2554    // Size
2555    switch (mCalibration.sizeCalibration) {
2556    case Calibration::SIZE_CALIBRATION_DEFAULT:
2557        if (mRawAxes.toolMajor.valid) {
2558            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2559        } else {
2560            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2561        }
2562        break;
2563
2564    default:
2565        break;
2566    }
2567
2568    // Orientation
2569    switch (mCalibration.orientationCalibration) {
2570    case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
2571        if (mRawAxes.orientation.valid) {
2572            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2573        } else {
2574            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2575        }
2576        break;
2577
2578    default:
2579        break;
2580    }
2581}
2582
2583void TouchInputMapper::dumpCalibration(String8& dump) {
2584    dump.append(INDENT3 "Calibration:\n");
2585
2586    // Touch Size
2587    switch (mCalibration.touchSizeCalibration) {
2588    case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
2589        dump.append(INDENT4 "touch.touchSize.calibration: none\n");
2590        break;
2591    case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
2592        dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
2593        break;
2594    case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
2595        dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
2596        break;
2597    default:
2598        assert(false);
2599    }
2600
2601    // Tool Size
2602    switch (mCalibration.toolSizeCalibration) {
2603    case Calibration::TOOL_SIZE_CALIBRATION_NONE:
2604        dump.append(INDENT4 "touch.toolSize.calibration: none\n");
2605        break;
2606    case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
2607        dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
2608        break;
2609    case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
2610        dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
2611        break;
2612    case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2613        dump.append(INDENT4 "touch.toolSize.calibration: area\n");
2614        break;
2615    default:
2616        assert(false);
2617    }
2618
2619    if (mCalibration.haveToolSizeLinearScale) {
2620        dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
2621                mCalibration.toolSizeLinearScale);
2622    }
2623
2624    if (mCalibration.haveToolSizeLinearBias) {
2625        dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
2626                mCalibration.toolSizeLinearBias);
2627    }
2628
2629    if (mCalibration.haveToolSizeAreaScale) {
2630        dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
2631                mCalibration.toolSizeAreaScale);
2632    }
2633
2634    if (mCalibration.haveToolSizeAreaBias) {
2635        dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
2636                mCalibration.toolSizeAreaBias);
2637    }
2638
2639    if (mCalibration.haveToolSizeIsSummed) {
2640        dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
2641                toString(mCalibration.toolSizeIsSummed));
2642    }
2643
2644    // Pressure
2645    switch (mCalibration.pressureCalibration) {
2646    case Calibration::PRESSURE_CALIBRATION_NONE:
2647        dump.append(INDENT4 "touch.pressure.calibration: none\n");
2648        break;
2649    case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2650        dump.append(INDENT4 "touch.pressure.calibration: physical\n");
2651        break;
2652    case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2653        dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
2654        break;
2655    default:
2656        assert(false);
2657    }
2658
2659    switch (mCalibration.pressureSource) {
2660    case Calibration::PRESSURE_SOURCE_PRESSURE:
2661        dump.append(INDENT4 "touch.pressure.source: pressure\n");
2662        break;
2663    case Calibration::PRESSURE_SOURCE_TOUCH:
2664        dump.append(INDENT4 "touch.pressure.source: touch\n");
2665        break;
2666    case Calibration::PRESSURE_SOURCE_DEFAULT:
2667        break;
2668    default:
2669        assert(false);
2670    }
2671
2672    if (mCalibration.havePressureScale) {
2673        dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
2674                mCalibration.pressureScale);
2675    }
2676
2677    // Size
2678    switch (mCalibration.sizeCalibration) {
2679    case Calibration::SIZE_CALIBRATION_NONE:
2680        dump.append(INDENT4 "touch.size.calibration: none\n");
2681        break;
2682    case Calibration::SIZE_CALIBRATION_NORMALIZED:
2683        dump.append(INDENT4 "touch.size.calibration: normalized\n");
2684        break;
2685    default:
2686        assert(false);
2687    }
2688
2689    // Orientation
2690    switch (mCalibration.orientationCalibration) {
2691    case Calibration::ORIENTATION_CALIBRATION_NONE:
2692        dump.append(INDENT4 "touch.orientation.calibration: none\n");
2693        break;
2694    case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2695        dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
2696        break;
2697    case Calibration::ORIENTATION_CALIBRATION_VECTOR:
2698        dump.append(INDENT4 "touch.orientation.calibration: vector\n");
2699        break;
2700    default:
2701        assert(false);
2702    }
2703}
2704
2705void TouchInputMapper::reset() {
2706    // Synthesize touch up event if touch is currently down.
2707    // This will also take care of finishing virtual key processing if needed.
2708    if (mLastTouch.pointerCount != 0) {
2709        nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2710        mCurrentTouch.clear();
2711        syncTouch(when, true);
2712    }
2713
2714    { // acquire lock
2715        AutoMutex _l(mLock);
2716        initializeLocked();
2717
2718        if (mPointerController != NULL
2719                && mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
2720            mPointerController->clearSpots();
2721        }
2722    } // release lock
2723
2724    InputMapper::reset();
2725}
2726
2727void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
2728#if DEBUG_RAW_EVENTS
2729    if (!havePointerIds) {
2730        LOGD("syncTouch: pointerCount=%d, no pointer ids", mCurrentTouch.pointerCount);
2731    } else {
2732        LOGD("syncTouch: pointerCount=%d, up=0x%08x, down=0x%08x, move=0x%08x, "
2733                "last=0x%08x, current=0x%08x", mCurrentTouch.pointerCount,
2734                mLastTouch.idBits.value & ~mCurrentTouch.idBits.value,
2735                mCurrentTouch.idBits.value & ~mLastTouch.idBits.value,
2736                mLastTouch.idBits.value & mCurrentTouch.idBits.value,
2737                mLastTouch.idBits.value, mCurrentTouch.idBits.value);
2738    }
2739#endif
2740
2741    // Preprocess pointer data.
2742    if (mParameters.useBadTouchFilter) {
2743        if (applyBadTouchFilter()) {
2744            havePointerIds = false;
2745        }
2746    }
2747
2748    if (mParameters.useJumpyTouchFilter) {
2749        if (applyJumpyTouchFilter()) {
2750            havePointerIds = false;
2751        }
2752    }
2753
2754    if (!havePointerIds) {
2755        calculatePointerIds();
2756    }
2757
2758    TouchData temp;
2759    TouchData* savedTouch;
2760    if (mParameters.useAveragingTouchFilter) {
2761        temp.copyFrom(mCurrentTouch);
2762        savedTouch = & temp;
2763
2764        applyAveragingTouchFilter();
2765    } else {
2766        savedTouch = & mCurrentTouch;
2767    }
2768
2769    uint32_t policyFlags = 0;
2770    if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
2771        if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
2772            // If this is a touch screen, hide the pointer on an initial down.
2773            getContext()->fadePointer();
2774        }
2775
2776        // Initial downs on external touch devices should wake the device.
2777        // We don't do this for internal touch screens to prevent them from waking
2778        // up in your pocket.
2779        // TODO: Use the input device configuration to control this behavior more finely.
2780        if (getDevice()->isExternal()) {
2781            policyFlags |= POLICY_FLAG_WAKE_DROPPED;
2782        }
2783    }
2784
2785    TouchResult touchResult;
2786    if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount == 0
2787            && mLastTouch.buttonState == mCurrentTouch.buttonState) {
2788        // Drop spurious syncs.
2789        touchResult = DROP_STROKE;
2790    } else {
2791        // Process touches and virtual keys.
2792        touchResult = consumeOffScreenTouches(when, policyFlags);
2793        if (touchResult == DISPATCH_TOUCH) {
2794            suppressSwipeOntoVirtualKeys(when);
2795            if (mPointerController != NULL) {
2796                dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
2797            }
2798            dispatchTouches(when, policyFlags);
2799        }
2800    }
2801
2802    // Copy current touch to last touch in preparation for the next cycle.
2803    // Keep the button state so we can track edge-triggered button state changes.
2804    if (touchResult == DROP_STROKE) {
2805        mLastTouch.clear();
2806        mLastTouch.buttonState = savedTouch->buttonState;
2807    } else {
2808        mLastTouch.copyFrom(*savedTouch);
2809    }
2810}
2811
2812void TouchInputMapper::timeoutExpired(nsecs_t when) {
2813    if (mPointerController != NULL) {
2814        dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
2815    }
2816}
2817
2818TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2819        nsecs_t when, uint32_t policyFlags) {
2820    int32_t keyEventAction, keyEventFlags;
2821    int32_t keyCode, scanCode, downTime;
2822    TouchResult touchResult;
2823
2824    { // acquire lock
2825        AutoMutex _l(mLock);
2826
2827        // Update surface size and orientation, including virtual key positions.
2828        if (! configureSurfaceLocked()) {
2829            return DROP_STROKE;
2830        }
2831
2832        // Check for virtual key press.
2833        if (mLocked.currentVirtualKey.down) {
2834            if (mCurrentTouch.pointerCount == 0) {
2835                // Pointer went up while virtual key was down.
2836                mLocked.currentVirtualKey.down = false;
2837#if DEBUG_VIRTUAL_KEYS
2838                LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
2839                        mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
2840#endif
2841                keyEventAction = AKEY_EVENT_ACTION_UP;
2842                keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2843                touchResult = SKIP_TOUCH;
2844                goto DispatchVirtualKey;
2845            }
2846
2847            if (mCurrentTouch.pointerCount == 1) {
2848                int32_t x = mCurrentTouch.pointers[0].x;
2849                int32_t y = mCurrentTouch.pointers[0].y;
2850                const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2851                if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
2852                    // Pointer is still within the space of the virtual key.
2853                    return SKIP_TOUCH;
2854                }
2855            }
2856
2857            // Pointer left virtual key area or another pointer also went down.
2858            // Send key cancellation and drop the stroke so subsequent motions will be
2859            // considered fresh downs.  This is useful when the user swipes away from the
2860            // virtual key area into the main display surface.
2861            mLocked.currentVirtualKey.down = false;
2862#if DEBUG_VIRTUAL_KEYS
2863            LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
2864                    mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
2865#endif
2866            keyEventAction = AKEY_EVENT_ACTION_UP;
2867            keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2868                    | AKEY_EVENT_FLAG_CANCELED;
2869
2870            // Check whether the pointer moved inside the display area where we should
2871            // start a new stroke.
2872            int32_t x = mCurrentTouch.pointers[0].x;
2873            int32_t y = mCurrentTouch.pointers[0].y;
2874            if (isPointInsideSurfaceLocked(x, y)) {
2875                mLastTouch.clear();
2876                touchResult = DISPATCH_TOUCH;
2877            } else {
2878                touchResult = DROP_STROKE;
2879            }
2880        } else {
2881            if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2882                // Pointer just went down.  Handle off-screen touches, if needed.
2883                int32_t x = mCurrentTouch.pointers[0].x;
2884                int32_t y = mCurrentTouch.pointers[0].y;
2885                if (! isPointInsideSurfaceLocked(x, y)) {
2886                    // If exactly one pointer went down, check for virtual key hit.
2887                    // Otherwise we will drop the entire stroke.
2888                    if (mCurrentTouch.pointerCount == 1) {
2889                        const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2890                        if (virtualKey) {
2891                            if (mContext->shouldDropVirtualKey(when, getDevice(),
2892                                    virtualKey->keyCode, virtualKey->scanCode)) {
2893                                return DROP_STROKE;
2894                            }
2895
2896                            mLocked.currentVirtualKey.down = true;
2897                            mLocked.currentVirtualKey.downTime = when;
2898                            mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2899                            mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
2900#if DEBUG_VIRTUAL_KEYS
2901                            LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
2902                                    mLocked.currentVirtualKey.keyCode,
2903                                    mLocked.currentVirtualKey.scanCode);
2904#endif
2905                            keyEventAction = AKEY_EVENT_ACTION_DOWN;
2906                            keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2907                                    | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2908                            touchResult = SKIP_TOUCH;
2909                            goto DispatchVirtualKey;
2910                        }
2911                    }
2912                    return DROP_STROKE;
2913                }
2914            }
2915            return DISPATCH_TOUCH;
2916        }
2917
2918    DispatchVirtualKey:
2919        // Collect remaining state needed to dispatch virtual key.
2920        keyCode = mLocked.currentVirtualKey.keyCode;
2921        scanCode = mLocked.currentVirtualKey.scanCode;
2922        downTime = mLocked.currentVirtualKey.downTime;
2923    } // release lock
2924
2925    // Dispatch virtual key.
2926    int32_t metaState = mContext->getGlobalMetaState();
2927    policyFlags |= POLICY_FLAG_VIRTUAL;
2928    getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
2929            keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2930    return touchResult;
2931}
2932
2933void TouchInputMapper::suppressSwipeOntoVirtualKeys(nsecs_t when) {
2934    // Disable all virtual key touches that happen within a short time interval of the
2935    // most recent touch.  The idea is to filter out stray virtual key presses when
2936    // interacting with the touch screen.
2937    //
2938    // Problems we're trying to solve:
2939    //
2940    // 1. While scrolling a list or dragging the window shade, the user swipes down into a
2941    //    virtual key area that is implemented by a separate touch panel and accidentally
2942    //    triggers a virtual key.
2943    //
2944    // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
2945    //    area and accidentally triggers a virtual key.  This often happens when virtual keys
2946    //    are layed out below the screen near to where the on screen keyboard's space bar
2947    //    is displayed.
2948    if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
2949        mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime);
2950    }
2951}
2952
2953void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2954    uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2955    uint32_t lastPointerCount = mLastTouch.pointerCount;
2956    if (currentPointerCount == 0 && lastPointerCount == 0) {
2957        return; // nothing to do!
2958    }
2959
2960    // Update current touch coordinates.
2961    int32_t edgeFlags;
2962    float xPrecision, yPrecision;
2963    prepareTouches(&edgeFlags, &xPrecision, &yPrecision);
2964
2965    // Dispatch motions.
2966    BitSet32 currentIdBits = mCurrentTouch.idBits;
2967    BitSet32 lastIdBits = mLastTouch.idBits;
2968    uint32_t metaState = getContext()->getGlobalMetaState();
2969
2970    if (currentIdBits == lastIdBits) {
2971        // No pointer id changes so this is a move event.
2972        // The dispatcher takes care of batching moves so we don't have to deal with that here.
2973        dispatchMotion(when, policyFlags, mTouchSource,
2974                AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
2975                mCurrentTouchCoords, mCurrentTouch.idToIndex, currentIdBits, -1,
2976                xPrecision, yPrecision, mDownTime);
2977    } else {
2978        // There may be pointers going up and pointers going down and pointers moving
2979        // all at the same time.
2980        BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
2981        BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
2982        BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
2983        BitSet32 dispatchedIdBits(lastIdBits.value);
2984
2985        // Update last coordinates of pointers that have moved so that we observe the new
2986        // pointer positions at the same time as other pointers that have just gone up.
2987        bool moveNeeded = updateMovedPointerCoords(
2988                mCurrentTouchCoords, mCurrentTouch.idToIndex,
2989                mLastTouchCoords, mLastTouch.idToIndex,
2990                moveIdBits);
2991
2992        // Dispatch pointer up events.
2993        while (!upIdBits.isEmpty()) {
2994            uint32_t upId = upIdBits.firstMarkedBit();
2995            upIdBits.clearBit(upId);
2996
2997            dispatchMotion(when, policyFlags, mTouchSource,
2998                    AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, 0,
2999                    mLastTouchCoords, mLastTouch.idToIndex, dispatchedIdBits, upId,
3000                    xPrecision, yPrecision, mDownTime);
3001            dispatchedIdBits.clearBit(upId);
3002        }
3003
3004        // Dispatch move events if any of the remaining pointers moved from their old locations.
3005        // Although applications receive new locations as part of individual pointer up
3006        // events, they do not generally handle them except when presented in a move event.
3007        if (moveNeeded) {
3008            assert(moveIdBits.value == dispatchedIdBits.value);
3009            dispatchMotion(when, policyFlags, mTouchSource,
3010                    AMOTION_EVENT_ACTION_MOVE, 0, metaState, 0,
3011                    mCurrentTouchCoords, mCurrentTouch.idToIndex, dispatchedIdBits, -1,
3012                    xPrecision, yPrecision, mDownTime);
3013        }
3014
3015        // Dispatch pointer down events using the new pointer locations.
3016        while (!downIdBits.isEmpty()) {
3017            uint32_t downId = downIdBits.firstMarkedBit();
3018            downIdBits.clearBit(downId);
3019            dispatchedIdBits.markBit(downId);
3020
3021            if (dispatchedIdBits.count() == 1) {
3022                // First pointer is going down.  Set down time.
3023                mDownTime = when;
3024            } else {
3025                // Only send edge flags with first pointer down.
3026                edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
3027            }
3028
3029            dispatchMotion(when, policyFlags, mTouchSource,
3030                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, edgeFlags,
3031                    mCurrentTouchCoords, mCurrentTouch.idToIndex, dispatchedIdBits, downId,
3032                    xPrecision, yPrecision, mDownTime);
3033        }
3034    }
3035
3036    // Update state for next time.
3037    for (uint32_t i = 0; i < currentPointerCount; i++) {
3038        mLastTouchCoords[i].copyFrom(mCurrentTouchCoords[i]);
3039    }
3040}
3041
3042void TouchInputMapper::prepareTouches(int32_t* outEdgeFlags,
3043        float* outXPrecision, float* outYPrecision) {
3044    uint32_t currentPointerCount = mCurrentTouch.pointerCount;
3045    uint32_t lastPointerCount = mLastTouch.pointerCount;
3046
3047    AutoMutex _l(mLock);
3048
3049    // Walk through the the active pointers and map touch screen coordinates (TouchData) into
3050    // display or surface coordinates (PointerCoords) and adjust for display orientation.
3051    for (uint32_t i = 0; i < currentPointerCount; i++) {
3052        const PointerData& in = mCurrentTouch.pointers[i];
3053
3054        // ToolMajor and ToolMinor
3055        float toolMajor, toolMinor;
3056        switch (mCalibration.toolSizeCalibration) {
3057        case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
3058            toolMajor = in.toolMajor * mLocked.geometricScale;
3059            if (mRawAxes.toolMinor.valid) {
3060                toolMinor = in.toolMinor * mLocked.geometricScale;
3061            } else {
3062                toolMinor = toolMajor;
3063            }
3064            break;
3065        case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
3066            toolMajor = in.toolMajor != 0
3067                    ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
3068                    : 0;
3069            if (mRawAxes.toolMinor.valid) {
3070                toolMinor = in.toolMinor != 0
3071                        ? in.toolMinor * mLocked.toolSizeLinearScale
3072                                + mLocked.toolSizeLinearBias
3073                        : 0;
3074            } else {
3075                toolMinor = toolMajor;
3076            }
3077            break;
3078        case Calibration::TOOL_SIZE_CALIBRATION_AREA:
3079            if (in.toolMajor != 0) {
3080                float diameter = sqrtf(in.toolMajor
3081                        * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
3082                toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
3083            } else {
3084                toolMajor = 0;
3085            }
3086            toolMinor = toolMajor;
3087            break;
3088        default:
3089            toolMajor = 0;
3090            toolMinor = 0;
3091            break;
3092        }
3093
3094        if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
3095            toolMajor /= currentPointerCount;
3096            toolMinor /= currentPointerCount;
3097        }
3098
3099        // Pressure
3100        float rawPressure;
3101        switch (mCalibration.pressureSource) {
3102        case Calibration::PRESSURE_SOURCE_PRESSURE:
3103            rawPressure = in.pressure;
3104            break;
3105        case Calibration::PRESSURE_SOURCE_TOUCH:
3106            rawPressure = in.touchMajor;
3107            break;
3108        default:
3109            rawPressure = 0;
3110        }
3111
3112        float pressure;
3113        switch (mCalibration.pressureCalibration) {
3114        case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
3115        case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
3116            pressure = rawPressure * mLocked.pressureScale;
3117            break;
3118        default:
3119            pressure = 1;
3120            break;
3121        }
3122
3123        // TouchMajor and TouchMinor
3124        float touchMajor, touchMinor;
3125        switch (mCalibration.touchSizeCalibration) {
3126        case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
3127            touchMajor = in.touchMajor * mLocked.geometricScale;
3128            if (mRawAxes.touchMinor.valid) {
3129                touchMinor = in.touchMinor * mLocked.geometricScale;
3130            } else {
3131                touchMinor = touchMajor;
3132            }
3133            break;
3134        case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
3135            touchMajor = toolMajor * pressure;
3136            touchMinor = toolMinor * pressure;
3137            break;
3138        default:
3139            touchMajor = 0;
3140            touchMinor = 0;
3141            break;
3142        }
3143
3144        if (touchMajor > toolMajor) {
3145            touchMajor = toolMajor;
3146        }
3147        if (touchMinor > toolMinor) {
3148            touchMinor = toolMinor;
3149        }
3150
3151        // Size
3152        float size;
3153        switch (mCalibration.sizeCalibration) {
3154        case Calibration::SIZE_CALIBRATION_NORMALIZED: {
3155            float rawSize = mRawAxes.toolMinor.valid
3156                    ? avg(in.toolMajor, in.toolMinor)
3157                    : in.toolMajor;
3158            size = rawSize * mLocked.sizeScale;
3159            break;
3160        }
3161        default:
3162            size = 0;
3163            break;
3164        }
3165
3166        // Orientation
3167        float orientation;
3168        switch (mCalibration.orientationCalibration) {
3169        case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
3170            orientation = in.orientation * mLocked.orientationScale;
3171            break;
3172        case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
3173            int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
3174            int32_t c2 = signExtendNybble(in.orientation & 0x0f);
3175            if (c1 != 0 || c2 != 0) {
3176                orientation = atan2f(c1, c2) * 0.5f;
3177                float scale = 1.0f + hypotf(c1, c2) / 16.0f;
3178                touchMajor *= scale;
3179                touchMinor /= scale;
3180                toolMajor *= scale;
3181                toolMinor /= scale;
3182            } else {
3183                orientation = 0;
3184            }
3185            break;
3186        }
3187        default:
3188            orientation = 0;
3189        }
3190
3191        // X and Y
3192        // Adjust coords for surface orientation.
3193        float x, y;
3194        switch (mLocked.surfaceOrientation) {
3195        case DISPLAY_ORIENTATION_90:
3196            x = float(in.y - mRawAxes.y.minValue) * mLocked.yScale;
3197            y = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale;
3198            orientation -= M_PI_2;
3199            if (orientation < - M_PI_2) {
3200                orientation += M_PI;
3201            }
3202            break;
3203        case DISPLAY_ORIENTATION_180:
3204            x = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale;
3205            y = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale;
3206            break;
3207        case DISPLAY_ORIENTATION_270:
3208            x = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale;
3209            y = float(in.x - mRawAxes.x.minValue) * mLocked.xScale;
3210            orientation += M_PI_2;
3211            if (orientation > M_PI_2) {
3212                orientation -= M_PI;
3213            }
3214            break;
3215        default:
3216            x = float(in.x - mRawAxes.x.minValue) * mLocked.xScale;
3217            y = float(in.y - mRawAxes.y.minValue) * mLocked.yScale;
3218            break;
3219        }
3220
3221        // Write output coords.
3222        PointerCoords& out = mCurrentTouchCoords[i];
3223        out.clear();
3224        out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
3225        out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
3226        out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
3227        out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
3228        out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
3229        out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
3230        out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
3231        out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
3232        out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
3233    }
3234
3235    // Check edge flags by looking only at the first pointer since the flags are
3236    // global to the event.
3237    *outEdgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
3238    if (lastPointerCount == 0 && currentPointerCount > 0) {
3239        const PointerData& in = mCurrentTouch.pointers[0];
3240
3241        if (in.x <= mRawAxes.x.minValue) {
3242            *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_LEFT,
3243                    mLocked.surfaceOrientation);
3244        } else if (in.x >= mRawAxes.x.maxValue) {
3245            *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_RIGHT,
3246                    mLocked.surfaceOrientation);
3247        }
3248        if (in.y <= mRawAxes.y.minValue) {
3249            *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_TOP,
3250                    mLocked.surfaceOrientation);
3251        } else if (in.y >= mRawAxes.y.maxValue) {
3252            *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_BOTTOM,
3253                    mLocked.surfaceOrientation);
3254        }
3255    }
3256
3257    *outXPrecision = mLocked.orientedXPrecision;
3258    *outYPrecision = mLocked.orientedYPrecision;
3259}
3260
3261void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
3262        bool isTimeout) {
3263    // Switch pointer presentation.
3264    mPointerController->setPresentation(
3265            mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
3266                    ? PointerControllerInterface::PRESENTATION_SPOT
3267                    : PointerControllerInterface::PRESENTATION_POINTER);
3268
3269    // Update current gesture coordinates.
3270    bool cancelPreviousGesture, finishPreviousGesture;
3271    bool sendEvents = preparePointerGestures(when,
3272            &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
3273    if (!sendEvents) {
3274        return;
3275    }
3276
3277    // Show or hide the pointer if needed.
3278    switch (mPointerGesture.currentGestureMode) {
3279    case PointerGesture::NEUTRAL:
3280    case PointerGesture::QUIET:
3281        if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
3282                && (mPointerGesture.lastGestureMode == PointerGesture::SWIPE
3283                        || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)) {
3284            // Remind the user of where the pointer is after finishing a gesture with spots.
3285            mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
3286        }
3287        break;
3288    case PointerGesture::TAP:
3289    case PointerGesture::TAP_DRAG:
3290    case PointerGesture::BUTTON_CLICK_OR_DRAG:
3291    case PointerGesture::HOVER:
3292    case PointerGesture::PRESS:
3293        // Unfade the pointer when the current gesture manipulates the
3294        // area directly under the pointer.
3295        mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
3296        break;
3297    case PointerGesture::SWIPE:
3298    case PointerGesture::FREEFORM:
3299        // Fade the pointer when the current gesture manipulates a different
3300        // area and there are spots to guide the user experience.
3301        if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3302            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
3303        } else {
3304            mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
3305        }
3306        break;
3307    }
3308
3309    // Send events!
3310    uint32_t metaState = getContext()->getGlobalMetaState();
3311
3312    // Update last coordinates of pointers that have moved so that we observe the new
3313    // pointer positions at the same time as other pointers that have just gone up.
3314    bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP
3315            || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG
3316            || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
3317            || mPointerGesture.currentGestureMode == PointerGesture::PRESS
3318            || mPointerGesture.currentGestureMode == PointerGesture::SWIPE
3319            || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
3320    bool moveNeeded = false;
3321    if (down && !cancelPreviousGesture && !finishPreviousGesture
3322            && !mPointerGesture.lastGestureIdBits.isEmpty()
3323            && !mPointerGesture.currentGestureIdBits.isEmpty()) {
3324        BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value
3325                & mPointerGesture.lastGestureIdBits.value);
3326        moveNeeded = updateMovedPointerCoords(
3327                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3328                mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
3329                movedGestureIdBits);
3330    }
3331
3332    // Send motion events for all pointers that went up or were canceled.
3333    BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
3334    if (!dispatchedGestureIdBits.isEmpty()) {
3335        if (cancelPreviousGesture) {
3336            dispatchMotion(when, policyFlags, mPointerSource,
3337                    AMOTION_EVENT_ACTION_CANCEL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
3338                    mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
3339                    dispatchedGestureIdBits, -1,
3340                    0, 0, mPointerGesture.downTime);
3341
3342            dispatchedGestureIdBits.clear();
3343        } else {
3344            BitSet32 upGestureIdBits;
3345            if (finishPreviousGesture) {
3346                upGestureIdBits = dispatchedGestureIdBits;
3347            } else {
3348                upGestureIdBits.value = dispatchedGestureIdBits.value
3349                        & ~mPointerGesture.currentGestureIdBits.value;
3350            }
3351            while (!upGestureIdBits.isEmpty()) {
3352                uint32_t id = upGestureIdBits.firstMarkedBit();
3353                upGestureIdBits.clearBit(id);
3354
3355                dispatchMotion(when, policyFlags, mPointerSource,
3356                        AMOTION_EVENT_ACTION_POINTER_UP, 0,
3357                        metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
3358                        mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
3359                        dispatchedGestureIdBits, id,
3360                        0, 0, mPointerGesture.downTime);
3361
3362                dispatchedGestureIdBits.clearBit(id);
3363            }
3364        }
3365    }
3366
3367    // Send motion events for all pointers that moved.
3368    if (moveNeeded) {
3369        dispatchMotion(when, policyFlags, mPointerSource,
3370                AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
3371                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3372                dispatchedGestureIdBits, -1,
3373                0, 0, mPointerGesture.downTime);
3374    }
3375
3376    // Send motion events for all pointers that went down.
3377    if (down) {
3378        BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value
3379                & ~dispatchedGestureIdBits.value);
3380        while (!downGestureIdBits.isEmpty()) {
3381            uint32_t id = downGestureIdBits.firstMarkedBit();
3382            downGestureIdBits.clearBit(id);
3383            dispatchedGestureIdBits.markBit(id);
3384
3385            int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
3386            if (dispatchedGestureIdBits.count() == 1) {
3387                // First pointer is going down.  Calculate edge flags and set down time.
3388                uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
3389                const PointerCoords& downCoords = mPointerGesture.currentGestureCoords[index];
3390                edgeFlags = calculateEdgeFlagsUsingPointerBounds(mPointerController,
3391                        downCoords.getAxisValue(AMOTION_EVENT_AXIS_X),
3392                        downCoords.getAxisValue(AMOTION_EVENT_AXIS_Y));
3393                mPointerGesture.downTime = when;
3394            }
3395
3396            dispatchMotion(when, policyFlags, mPointerSource,
3397                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, edgeFlags,
3398                    mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3399                    dispatchedGestureIdBits, id,
3400                    0, 0, mPointerGesture.downTime);
3401        }
3402    }
3403
3404    // Send motion events for hover.
3405    if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
3406        dispatchMotion(when, policyFlags, mPointerSource,
3407                AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
3408                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3409                mPointerGesture.currentGestureIdBits, -1,
3410                0, 0, mPointerGesture.downTime);
3411    }
3412
3413    // Update state.
3414    mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
3415    if (!down) {
3416        mPointerGesture.lastGestureIdBits.clear();
3417    } else {
3418        mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
3419        for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) {
3420            uint32_t id = idBits.firstMarkedBit();
3421            idBits.clearBit(id);
3422            uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
3423            mPointerGesture.lastGestureCoords[index].copyFrom(
3424                    mPointerGesture.currentGestureCoords[index]);
3425            mPointerGesture.lastGestureIdToIndex[id] = index;
3426        }
3427    }
3428}
3429
3430bool TouchInputMapper::preparePointerGestures(nsecs_t when,
3431        bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
3432    *outCancelPreviousGesture = false;
3433    *outFinishPreviousGesture = false;
3434
3435    AutoMutex _l(mLock);
3436
3437    // Handle TAP timeout.
3438    if (isTimeout) {
3439#if DEBUG_GESTURES
3440        LOGD("Gestures: Processing timeout");
3441#endif
3442
3443        if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
3444            if (when <= mPointerGesture.tapUpTime + TAP_DRAG_INTERVAL) {
3445                // The tap/drag timeout has not yet expired.
3446                getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime + TAP_DRAG_INTERVAL);
3447            } else {
3448                // The tap is finished.
3449#if DEBUG_GESTURES
3450                LOGD("Gestures: TAP finished");
3451#endif
3452                *outFinishPreviousGesture = true;
3453
3454                mPointerGesture.activeGestureId = -1;
3455                mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
3456                mPointerGesture.currentGestureIdBits.clear();
3457
3458                if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3459                    mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
3460                    mPointerGesture.spotIdBits.clear();
3461                    moveSpotsLocked();
3462                }
3463                return true;
3464            }
3465        }
3466
3467        // We did not handle this timeout.
3468        return false;
3469    }
3470
3471    // Update the velocity tracker.
3472    {
3473        VelocityTracker::Position positions[MAX_POINTERS];
3474        uint32_t count = 0;
3475        for (BitSet32 idBits(mCurrentTouch.idBits); !idBits.isEmpty(); count++) {
3476            uint32_t id = idBits.firstMarkedBit();
3477            idBits.clearBit(id);
3478            uint32_t index = mCurrentTouch.idToIndex[id];
3479            positions[count].x = mCurrentTouch.pointers[index].x
3480                    * mLocked.pointerGestureXMovementScale;
3481            positions[count].y = mCurrentTouch.pointers[index].y
3482                    * mLocked.pointerGestureYMovementScale;
3483        }
3484        mPointerGesture.velocityTracker.addMovement(when, mCurrentTouch.idBits, positions);
3485    }
3486
3487    // Pick a new active touch id if needed.
3488    // Choose an arbitrary pointer that just went down, if there is one.
3489    // Otherwise choose an arbitrary remaining pointer.
3490    // This guarantees we always have an active touch id when there is at least one pointer.
3491    // We keep the same active touch id for as long as possible.
3492    bool activeTouchChanged = false;
3493    int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
3494    int32_t activeTouchId = lastActiveTouchId;
3495    if (activeTouchId < 0) {
3496        if (!mCurrentTouch.idBits.isEmpty()) {
3497            activeTouchChanged = true;
3498            activeTouchId = mPointerGesture.activeTouchId = mCurrentTouch.idBits.firstMarkedBit();
3499            mPointerGesture.firstTouchTime = when;
3500        }
3501    } else if (!mCurrentTouch.idBits.hasBit(activeTouchId)) {
3502        activeTouchChanged = true;
3503        if (!mCurrentTouch.idBits.isEmpty()) {
3504            activeTouchId = mPointerGesture.activeTouchId = mCurrentTouch.idBits.firstMarkedBit();
3505        } else {
3506            activeTouchId = mPointerGesture.activeTouchId = -1;
3507        }
3508    }
3509
3510    // Determine whether we are in quiet time.
3511    bool isQuietTime = false;
3512    if (activeTouchId < 0) {
3513        mPointerGesture.resetQuietTime();
3514    } else {
3515        isQuietTime = when < mPointerGesture.quietTime + QUIET_INTERVAL;
3516        if (!isQuietTime) {
3517            if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
3518                    || mPointerGesture.lastGestureMode == PointerGesture::SWIPE
3519                    || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)
3520                    && mCurrentTouch.pointerCount < 2) {
3521                // Enter quiet time when exiting swipe or freeform state.
3522                // This is to prevent accidentally entering the hover state and flinging the
3523                // pointer when finishing a swipe and there is still one pointer left onscreen.
3524                isQuietTime = true;
3525            } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
3526                    && mCurrentTouch.pointerCount >= 2
3527                    && !isPointerDown(mCurrentTouch.buttonState)) {
3528                // Enter quiet time when releasing the button and there are still two or more
3529                // fingers down.  This may indicate that one finger was used to press the button
3530                // but it has not gone up yet.
3531                isQuietTime = true;
3532            }
3533            if (isQuietTime) {
3534                mPointerGesture.quietTime = when;
3535            }
3536        }
3537    }
3538
3539    // Switch states based on button and pointer state.
3540    if (isQuietTime) {
3541        // Case 1: Quiet time. (QUIET)
3542#if DEBUG_GESTURES
3543        LOGD("Gestures: QUIET for next %0.3fms",
3544                (mPointerGesture.quietTime + QUIET_INTERVAL - when) * 0.000001f);
3545#endif
3546        *outFinishPreviousGesture = true;
3547
3548        mPointerGesture.activeGestureId = -1;
3549        mPointerGesture.currentGestureMode = PointerGesture::QUIET;
3550        mPointerGesture.currentGestureIdBits.clear();
3551
3552        if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3553            mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
3554            mPointerGesture.spotIdBits.clear();
3555            moveSpotsLocked();
3556        }
3557    } else if (isPointerDown(mCurrentTouch.buttonState)) {
3558        // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
3559        // The pointer follows the active touch point.
3560        // Emit DOWN, MOVE, UP events at the pointer location.
3561        //
3562        // Only the active touch matters; other fingers are ignored.  This policy helps
3563        // to handle the case where the user places a second finger on the touch pad
3564        // to apply the necessary force to depress an integrated button below the surface.
3565        // We don't want the second finger to be delivered to applications.
3566        //
3567        // For this to work well, we need to make sure to track the pointer that is really
3568        // active.  If the user first puts one finger down to click then adds another
3569        // finger to drag then the active pointer should switch to the finger that is
3570        // being dragged.
3571#if DEBUG_GESTURES
3572        LOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
3573                "currentTouchPointerCount=%d", activeTouchId, mCurrentTouch.pointerCount);
3574#endif
3575        // Reset state when just starting.
3576        if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
3577            *outFinishPreviousGesture = true;
3578            mPointerGesture.activeGestureId = 0;
3579        }
3580
3581        // Switch pointers if needed.
3582        // Find the fastest pointer and follow it.
3583        if (activeTouchId >= 0) {
3584            if (mCurrentTouch.pointerCount > 1) {
3585                int32_t bestId = -1;
3586                float bestSpeed = DRAG_MIN_SWITCH_SPEED;
3587                for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
3588                    uint32_t id = mCurrentTouch.pointers[i].id;
3589                    float vx, vy;
3590                    if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
3591                        float speed = hypotf(vx, vy);
3592                        if (speed > bestSpeed) {
3593                            bestId = id;
3594                            bestSpeed = speed;
3595                        }
3596                    }
3597                }
3598                if (bestId >= 0 && bestId != activeTouchId) {
3599                    mPointerGesture.activeTouchId = activeTouchId = bestId;
3600                    activeTouchChanged = true;
3601#if DEBUG_GESTURES
3602                    LOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
3603                            "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
3604#endif
3605                }
3606            }
3607
3608            if (mLastTouch.idBits.hasBit(activeTouchId)) {
3609                const PointerData& currentPointer =
3610                        mCurrentTouch.pointers[mCurrentTouch.idToIndex[activeTouchId]];
3611                const PointerData& lastPointer =
3612                        mLastTouch.pointers[mLastTouch.idToIndex[activeTouchId]];
3613                float deltaX = (currentPointer.x - lastPointer.x)
3614                        * mLocked.pointerGestureXMovementScale;
3615                float deltaY = (currentPointer.y - lastPointer.y)
3616                        * mLocked.pointerGestureYMovementScale;
3617
3618                // Move the pointer using a relative motion.
3619                // When using spots, the click will occur at the position of the anchor
3620                // spot and all other spots will move there.
3621                mPointerController->move(deltaX, deltaY);
3622            }
3623        }
3624
3625        float x, y;
3626        mPointerController->getPosition(&x, &y);
3627
3628        mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
3629        mPointerGesture.currentGestureIdBits.clear();
3630        mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
3631        mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
3632        mPointerGesture.currentGestureCoords[0].clear();
3633        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
3634        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
3635        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
3636
3637        if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3638            if (activeTouchId >= 0) {
3639                // Collapse all spots into one point at the pointer location.
3640                mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_BUTTON_DRAG;
3641                mPointerGesture.spotIdBits.clear();
3642                for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
3643                    uint32_t id = mCurrentTouch.pointers[i].id;
3644                    mPointerGesture.spotIdBits.markBit(id);
3645                    mPointerGesture.spotIdToIndex[id] = i;
3646                    mPointerGesture.spotCoords[i] = mPointerGesture.currentGestureCoords[0];
3647                }
3648            } else {
3649                // No fingers.  Generate a spot at the pointer location so the
3650                // anchor appears to be pressed.
3651                mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_BUTTON_CLICK;
3652                mPointerGesture.spotIdBits.clear();
3653                mPointerGesture.spotIdBits.markBit(0);
3654                mPointerGesture.spotIdToIndex[0] = 0;
3655                mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0];
3656            }
3657            moveSpotsLocked();
3658        }
3659    } else if (mCurrentTouch.pointerCount == 0) {
3660        // Case 3. No fingers down and button is not pressed. (NEUTRAL)
3661        *outFinishPreviousGesture = true;
3662
3663        // Watch for taps coming out of HOVER or TAP_DRAG mode.
3664        bool tapped = false;
3665        if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
3666                || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
3667                && mLastTouch.pointerCount == 1) {
3668            if (when <= mPointerGesture.tapDownTime + TAP_INTERVAL) {
3669                float x, y;
3670                mPointerController->getPosition(&x, &y);
3671                if (fabs(x - mPointerGesture.tapX) <= TAP_SLOP
3672                        && fabs(y - mPointerGesture.tapY) <= TAP_SLOP) {
3673#if DEBUG_GESTURES
3674                    LOGD("Gestures: TAP");
3675#endif
3676
3677                    mPointerGesture.tapUpTime = when;
3678                    getContext()->requestTimeoutAtTime(when + TAP_DRAG_INTERVAL);
3679
3680                    mPointerGesture.activeGestureId = 0;
3681                    mPointerGesture.currentGestureMode = PointerGesture::TAP;
3682                    mPointerGesture.currentGestureIdBits.clear();
3683                    mPointerGesture.currentGestureIdBits.markBit(
3684                            mPointerGesture.activeGestureId);
3685                    mPointerGesture.currentGestureIdToIndex[
3686                            mPointerGesture.activeGestureId] = 0;
3687                    mPointerGesture.currentGestureCoords[0].clear();
3688                    mPointerGesture.currentGestureCoords[0].setAxisValue(
3689                            AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
3690                    mPointerGesture.currentGestureCoords[0].setAxisValue(
3691                            AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY);
3692                    mPointerGesture.currentGestureCoords[0].setAxisValue(
3693                            AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
3694
3695                    if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3696                        mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_TAP;
3697                        mPointerGesture.spotIdBits.clear();
3698                        mPointerGesture.spotIdBits.markBit(lastActiveTouchId);
3699                        mPointerGesture.spotIdToIndex[lastActiveTouchId] = 0;
3700                        mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0];
3701                        moveSpotsLocked();
3702                    }
3703
3704                    tapped = true;
3705                } else {
3706#if DEBUG_GESTURES
3707                    LOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f",
3708                            x - mPointerGesture.tapX,
3709                            y - mPointerGesture.tapY);
3710#endif
3711                }
3712            } else {
3713#if DEBUG_GESTURES
3714                LOGD("Gestures: Not a TAP, %0.3fms since down",
3715                        (when - mPointerGesture.tapDownTime) * 0.000001f);
3716#endif
3717            }
3718        }
3719
3720        if (!tapped) {
3721#if DEBUG_GESTURES
3722            LOGD("Gestures: NEUTRAL");
3723#endif
3724            mPointerGesture.activeGestureId = -1;
3725            mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
3726            mPointerGesture.currentGestureIdBits.clear();
3727
3728            if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3729                mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
3730                mPointerGesture.spotIdBits.clear();
3731                moveSpotsLocked();
3732            }
3733        }
3734    } else if (mCurrentTouch.pointerCount == 1) {
3735        // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
3736        // The pointer follows the active touch point.
3737        // When in HOVER, emit HOVER_MOVE events at the pointer location.
3738        // When in TAP_DRAG, emit MOVE events at the pointer location.
3739        LOG_ASSERT(activeTouchId >= 0);
3740
3741        mPointerGesture.currentGestureMode = PointerGesture::HOVER;
3742        if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
3743            if (when <= mPointerGesture.tapUpTime + TAP_DRAG_INTERVAL) {
3744                float x, y;
3745                mPointerController->getPosition(&x, &y);
3746                if (fabs(x - mPointerGesture.tapX) <= TAP_SLOP
3747                        && fabs(y - mPointerGesture.tapY) <= TAP_SLOP) {
3748                    mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
3749                } else {
3750#if DEBUG_GESTURES
3751                    LOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
3752                            x - mPointerGesture.tapX,
3753                            y - mPointerGesture.tapY);
3754#endif
3755                }
3756            } else {
3757#if DEBUG_GESTURES
3758                LOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
3759                        (when - mPointerGesture.tapUpTime) * 0.000001f);
3760#endif
3761            }
3762        } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
3763            mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
3764        }
3765
3766        if (mLastTouch.idBits.hasBit(activeTouchId)) {
3767            const PointerData& currentPointer =
3768                    mCurrentTouch.pointers[mCurrentTouch.idToIndex[activeTouchId]];
3769            const PointerData& lastPointer =
3770                    mLastTouch.pointers[mLastTouch.idToIndex[activeTouchId]];
3771            float deltaX = (currentPointer.x - lastPointer.x)
3772                    * mLocked.pointerGestureXMovementScale;
3773            float deltaY = (currentPointer.y - lastPointer.y)
3774                    * mLocked.pointerGestureYMovementScale;
3775
3776            // Move the pointer using a relative motion.
3777            // When using spots, the hover or drag will occur at the position of the anchor spot.
3778            mPointerController->move(deltaX, deltaY);
3779        }
3780
3781        bool down;
3782        if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
3783#if DEBUG_GESTURES
3784            LOGD("Gestures: TAP_DRAG");
3785#endif
3786            down = true;
3787        } else {
3788#if DEBUG_GESTURES
3789            LOGD("Gestures: HOVER");
3790#endif
3791            *outFinishPreviousGesture = true;
3792            mPointerGesture.activeGestureId = 0;
3793            down = false;
3794        }
3795
3796        float x, y;
3797        mPointerController->getPosition(&x, &y);
3798
3799        mPointerGesture.currentGestureIdBits.clear();
3800        mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
3801        mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
3802        mPointerGesture.currentGestureCoords[0].clear();
3803        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
3804        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
3805        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
3806                down ? 1.0f : 0.0f);
3807
3808        if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
3809            mPointerGesture.resetTap();
3810            mPointerGesture.tapDownTime = when;
3811            mPointerGesture.tapX = x;
3812            mPointerGesture.tapY = y;
3813        }
3814
3815        if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3816            mPointerGesture.spotGesture = down ? PointerControllerInterface::SPOT_GESTURE_DRAG
3817                    : PointerControllerInterface::SPOT_GESTURE_HOVER;
3818            mPointerGesture.spotIdBits.clear();
3819            mPointerGesture.spotIdBits.markBit(activeTouchId);
3820            mPointerGesture.spotIdToIndex[activeTouchId] = 0;
3821            mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0];
3822            moveSpotsLocked();
3823        }
3824    } else {
3825        // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
3826        // We need to provide feedback for each finger that goes down so we cannot wait
3827        // for the fingers to move before deciding what to do.
3828        //
3829        // The ambiguous case is deciding what to do when there are two fingers down but they
3830        // have not moved enough to determine whether they are part of a drag or part of a
3831        // freeform gesture, or just a press or long-press at the pointer location.
3832        //
3833        // When there are two fingers we start with the PRESS hypothesis and we generate a
3834        // down at the pointer location.
3835        //
3836        // When the two fingers move enough or when additional fingers are added, we make
3837        // a decision to transition into SWIPE or FREEFORM mode accordingly.
3838        LOG_ASSERT(activeTouchId >= 0);
3839
3840        bool needReference = false;
3841        bool settled = when >= mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL;
3842        if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
3843                && mPointerGesture.lastGestureMode != PointerGesture::SWIPE
3844                && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
3845            *outFinishPreviousGesture = true;
3846            mPointerGesture.currentGestureMode = PointerGesture::PRESS;
3847            mPointerGesture.activeGestureId = 0;
3848            mPointerGesture.referenceIdBits.clear();
3849
3850            if (settled && mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
3851                    && mLastTouch.idBits.hasBit(mPointerGesture.activeTouchId)) {
3852                // The spot is already visible and has settled, use it as the reference point
3853                // for the gesture.  Other spots will be positioned relative to this one.
3854#if DEBUG_GESTURES
3855                LOGD("Gestures: Using active spot as reference for MULTITOUCH, "
3856                        "settle time expired %0.3fms ago",
3857                        (when - mPointerGesture.firstTouchTime - MULTITOUCH_SETTLE_INTERVAL)
3858                                * 0.000001f);
3859#endif
3860                const PointerData& d = mLastTouch.pointers[mLastTouch.idToIndex[
3861                        mPointerGesture.activeTouchId]];
3862                mPointerGesture.referenceTouchX = d.x;
3863                mPointerGesture.referenceTouchY = d.y;
3864                const PointerCoords& c = mPointerGesture.spotCoords[mPointerGesture.spotIdToIndex[
3865                        mPointerGesture.activeTouchId]];
3866                mPointerGesture.referenceGestureX = c.getAxisValue(AMOTION_EVENT_AXIS_X);
3867                mPointerGesture.referenceGestureY = c.getAxisValue(AMOTION_EVENT_AXIS_Y);
3868            } else {
3869#if DEBUG_GESTURES
3870                LOGD("Gestures: Using centroid as reference for MULTITOUCH, "
3871                        "settle time remaining %0.3fms",
3872                        (mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL - when)
3873                                * 0.000001f);
3874#endif
3875                needReference = true;
3876            }
3877        } else if (!settled && mCurrentTouch.pointerCount > mLastTouch.pointerCount) {
3878            // Additional pointers have gone down but not yet settled.
3879            // Reset the gesture.
3880#if DEBUG_GESTURES
3881            LOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
3882                    "settle time remaining %0.3fms",
3883                    (mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL - when)
3884                            * 0.000001f);
3885#endif
3886            *outCancelPreviousGesture = true;
3887            mPointerGesture.currentGestureMode = PointerGesture::PRESS;
3888            mPointerGesture.activeGestureId = 0;
3889        } else {
3890            // Continue previous gesture.
3891            mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
3892        }
3893
3894        if (needReference) {
3895            // Use the centroid and pointer location as the reference points for the gesture.
3896            mCurrentTouch.getCentroid(&mPointerGesture.referenceTouchX,
3897                    &mPointerGesture.referenceTouchY);
3898            mPointerController->getPosition(&mPointerGesture.referenceGestureX,
3899                    &mPointerGesture.referenceGestureY);
3900        }
3901
3902        if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
3903            float d;
3904            if (mCurrentTouch.pointerCount > 2) {
3905                // There are more than two pointers, switch to FREEFORM.
3906#if DEBUG_GESTURES
3907                LOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
3908                        mCurrentTouch.pointerCount);
3909#endif
3910                *outCancelPreviousGesture = true;
3911                mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
3912            } else if (((d = distance(
3913                    mCurrentTouch.pointers[0].x, mCurrentTouch.pointers[0].y,
3914                    mCurrentTouch.pointers[1].x, mCurrentTouch.pointers[1].y))
3915                            > mLocked.pointerGestureMaxSwipeWidth)) {
3916                // There are two pointers but they are too far apart, switch to FREEFORM.
3917#if DEBUG_GESTURES
3918                LOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
3919                        d, mLocked.pointerGestureMaxSwipeWidth);
3920#endif
3921                *outCancelPreviousGesture = true;
3922                mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
3923            } else {
3924                // There are two pointers.  Wait for both pointers to start moving
3925                // before deciding whether this is a SWIPE or FREEFORM gesture.
3926                uint32_t id1 = mCurrentTouch.pointers[0].id;
3927                uint32_t id2 = mCurrentTouch.pointers[1].id;
3928
3929                float vx1, vy1, vx2, vy2;
3930                mPointerGesture.velocityTracker.getVelocity(id1, &vx1, &vy1);
3931                mPointerGesture.velocityTracker.getVelocity(id2, &vx2, &vy2);
3932
3933                float speed1 = hypotf(vx1, vy1);
3934                float speed2 = hypotf(vx2, vy2);
3935                if (speed1 >= MULTITOUCH_MIN_SPEED && speed2 >= MULTITOUCH_MIN_SPEED) {
3936                    // Calculate the dot product of the velocity vectors.
3937                    // When the vectors are oriented in approximately the same direction,
3938                    // the angle betweeen them is near zero and the cosine of the angle
3939                    // approches 1.0.  Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
3940                    float dot = vx1 * vx2 + vy1 * vy2;
3941                    float cosine = dot / (speed1 * speed2); // denominator always > 0
3942                    if (cosine >= SWIPE_TRANSITION_ANGLE_COSINE) {
3943                        // Pointers are moving in the same direction.  Switch to SWIPE.
3944#if DEBUG_GESTURES
3945                        LOGD("Gestures: PRESS transitioned to SWIPE, "
3946                                "speed1 %0.3f >= %0.3f, speed2 %0.3f >= %0.3f, "
3947                                "cosine %0.3f >= %0.3f",
3948                                speed1, MULTITOUCH_MIN_SPEED, speed2, MULTITOUCH_MIN_SPEED,
3949                                cosine, SWIPE_TRANSITION_ANGLE_COSINE);
3950#endif
3951                        mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
3952                    } else {
3953                        // Pointers are moving in different directions.  Switch to FREEFORM.
3954#if DEBUG_GESTURES
3955                        LOGD("Gestures: PRESS transitioned to FREEFORM, "
3956                                "speed1 %0.3f >= %0.3f, speed2 %0.3f >= %0.3f, "
3957                                "cosine %0.3f < %0.3f",
3958                                speed1, MULTITOUCH_MIN_SPEED, speed2, MULTITOUCH_MIN_SPEED,
3959                                cosine, SWIPE_TRANSITION_ANGLE_COSINE);
3960#endif
3961                        *outCancelPreviousGesture = true;
3962                        mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
3963                    }
3964                }
3965            }
3966        } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
3967            // Switch from SWIPE to FREEFORM if additional pointers go down.
3968            // Cancel previous gesture.
3969            if (mCurrentTouch.pointerCount > 2) {
3970#if DEBUG_GESTURES
3971                LOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
3972                        mCurrentTouch.pointerCount);
3973#endif
3974                *outCancelPreviousGesture = true;
3975                mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
3976            }
3977        }
3978
3979        // Clear the reference deltas for fingers not yet included in the reference calculation.
3980        for (BitSet32 idBits(mCurrentTouch.idBits.value & ~mPointerGesture.referenceIdBits.value);
3981                !idBits.isEmpty(); ) {
3982            uint32_t id = idBits.firstMarkedBit();
3983            idBits.clearBit(id);
3984
3985            mPointerGesture.referenceDeltas[id].dx = 0;
3986            mPointerGesture.referenceDeltas[id].dy = 0;
3987        }
3988        mPointerGesture.referenceIdBits = mCurrentTouch.idBits;
3989
3990        // Move the reference points based on the overall group motion of the fingers.
3991        // The objective is to calculate a vector delta that is common to the movement
3992        // of all fingers.
3993        BitSet32 commonIdBits(mLastTouch.idBits.value & mCurrentTouch.idBits.value);
3994        if (!commonIdBits.isEmpty()) {
3995            float commonDeltaX = 0, commonDeltaY = 0;
3996            for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
3997                bool first = (idBits == commonIdBits);
3998                uint32_t id = idBits.firstMarkedBit();
3999                idBits.clearBit(id);
4000
4001                const PointerData& cpd = mCurrentTouch.pointers[mCurrentTouch.idToIndex[id]];
4002                const PointerData& lpd = mLastTouch.pointers[mLastTouch.idToIndex[id]];
4003                PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
4004                delta.dx += cpd.x - lpd.x;
4005                delta.dy += cpd.y - lpd.y;
4006
4007                if (first) {
4008                    commonDeltaX = delta.dx;
4009                    commonDeltaY = delta.dy;
4010                } else {
4011                    commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
4012                    commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
4013                }
4014            }
4015
4016            if (commonDeltaX || commonDeltaY) {
4017                for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
4018                    uint32_t id = idBits.firstMarkedBit();
4019                    idBits.clearBit(id);
4020
4021                    PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
4022                    delta.dx = 0;
4023                    delta.dy = 0;
4024                }
4025
4026                mPointerGesture.referenceTouchX += commonDeltaX;
4027                mPointerGesture.referenceTouchY += commonDeltaY;
4028                mPointerGesture.referenceGestureX +=
4029                        commonDeltaX * mLocked.pointerGestureXMovementScale;
4030                mPointerGesture.referenceGestureY +=
4031                        commonDeltaY * mLocked.pointerGestureYMovementScale;
4032                clampPositionUsingPointerBounds(mPointerController,
4033                        &mPointerGesture.referenceGestureX,
4034                        &mPointerGesture.referenceGestureY);
4035            }
4036        }
4037
4038        // Report gestures.
4039        if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
4040            // PRESS mode.
4041#if DEBUG_GESTURES
4042            LOGD("Gestures: PRESS activeTouchId=%d,"
4043                    "activeGestureId=%d, currentTouchPointerCount=%d",
4044                    activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount);
4045#endif
4046            LOG_ASSERT(mPointerGesture.activeGestureId >= 0);
4047
4048            mPointerGesture.currentGestureIdBits.clear();
4049            mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4050            mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
4051            mPointerGesture.currentGestureCoords[0].clear();
4052            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
4053                    mPointerGesture.referenceGestureX);
4054            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
4055                    mPointerGesture.referenceGestureY);
4056            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4057
4058            if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
4059                mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_PRESS;
4060            }
4061        } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
4062            // SWIPE mode.
4063#if DEBUG_GESTURES
4064            LOGD("Gestures: SWIPE activeTouchId=%d,"
4065                    "activeGestureId=%d, currentTouchPointerCount=%d",
4066                    activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount);
4067#endif
4068            assert(mPointerGesture.activeGestureId >= 0);
4069
4070            mPointerGesture.currentGestureIdBits.clear();
4071            mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4072            mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
4073            mPointerGesture.currentGestureCoords[0].clear();
4074            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
4075                    mPointerGesture.referenceGestureX);
4076            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
4077                    mPointerGesture.referenceGestureY);
4078            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4079
4080            if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
4081                mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_SWIPE;
4082            }
4083        } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
4084            // FREEFORM mode.
4085#if DEBUG_GESTURES
4086            LOGD("Gestures: FREEFORM activeTouchId=%d,"
4087                    "activeGestureId=%d, currentTouchPointerCount=%d",
4088                    activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount);
4089#endif
4090            assert(mPointerGesture.activeGestureId >= 0);
4091
4092            mPointerGesture.currentGestureIdBits.clear();
4093
4094            BitSet32 mappedTouchIdBits;
4095            BitSet32 usedGestureIdBits;
4096            if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
4097                // Initially, assign the active gesture id to the active touch point
4098                // if there is one.  No other touch id bits are mapped yet.
4099                if (!*outCancelPreviousGesture) {
4100                    mappedTouchIdBits.markBit(activeTouchId);
4101                    usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
4102                    mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
4103                            mPointerGesture.activeGestureId;
4104                } else {
4105                    mPointerGesture.activeGestureId = -1;
4106                }
4107            } else {
4108                // Otherwise, assume we mapped all touches from the previous frame.
4109                // Reuse all mappings that are still applicable.
4110                mappedTouchIdBits.value = mLastTouch.idBits.value & mCurrentTouch.idBits.value;
4111                usedGestureIdBits = mPointerGesture.lastGestureIdBits;
4112
4113                // Check whether we need to choose a new active gesture id because the
4114                // current went went up.
4115                for (BitSet32 upTouchIdBits(mLastTouch.idBits.value & ~mCurrentTouch.idBits.value);
4116                        !upTouchIdBits.isEmpty(); ) {
4117                    uint32_t upTouchId = upTouchIdBits.firstMarkedBit();
4118                    upTouchIdBits.clearBit(upTouchId);
4119                    uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
4120                    if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
4121                        mPointerGesture.activeGestureId = -1;
4122                        break;
4123                    }
4124                }
4125            }
4126
4127#if DEBUG_GESTURES
4128            LOGD("Gestures: FREEFORM follow up "
4129                    "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
4130                    "activeGestureId=%d",
4131                    mappedTouchIdBits.value, usedGestureIdBits.value,
4132                    mPointerGesture.activeGestureId);
4133#endif
4134
4135            for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
4136                uint32_t touchId = mCurrentTouch.pointers[i].id;
4137                uint32_t gestureId;
4138                if (!mappedTouchIdBits.hasBit(touchId)) {
4139                    gestureId = usedGestureIdBits.firstUnmarkedBit();
4140                    usedGestureIdBits.markBit(gestureId);
4141                    mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
4142#if DEBUG_GESTURES
4143                    LOGD("Gestures: FREEFORM "
4144                            "new mapping for touch id %d -> gesture id %d",
4145                            touchId, gestureId);
4146#endif
4147                } else {
4148                    gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
4149#if DEBUG_GESTURES
4150                    LOGD("Gestures: FREEFORM "
4151                            "existing mapping for touch id %d -> gesture id %d",
4152                            touchId, gestureId);
4153#endif
4154                }
4155                mPointerGesture.currentGestureIdBits.markBit(gestureId);
4156                mPointerGesture.currentGestureIdToIndex[gestureId] = i;
4157
4158                float x = (mCurrentTouch.pointers[i].x - mPointerGesture.referenceTouchX)
4159                        * mLocked.pointerGestureXZoomScale + mPointerGesture.referenceGestureX;
4160                float y = (mCurrentTouch.pointers[i].y - mPointerGesture.referenceTouchY)
4161                        * mLocked.pointerGestureYZoomScale + mPointerGesture.referenceGestureY;
4162
4163                mPointerGesture.currentGestureCoords[i].clear();
4164                mPointerGesture.currentGestureCoords[i].setAxisValue(
4165                        AMOTION_EVENT_AXIS_X, x);
4166                mPointerGesture.currentGestureCoords[i].setAxisValue(
4167                        AMOTION_EVENT_AXIS_Y, y);
4168                mPointerGesture.currentGestureCoords[i].setAxisValue(
4169                        AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4170            }
4171
4172            if (mPointerGesture.activeGestureId < 0) {
4173                mPointerGesture.activeGestureId =
4174                        mPointerGesture.currentGestureIdBits.firstMarkedBit();
4175#if DEBUG_GESTURES
4176                LOGD("Gestures: FREEFORM new "
4177                        "activeGestureId=%d", mPointerGesture.activeGestureId);
4178#endif
4179            }
4180
4181            if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
4182                mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_FREEFORM;
4183            }
4184        }
4185
4186        // Update spot locations for PRESS, SWIPE and FREEFORM.
4187        // We use the same calculation as we do to calculate the gesture pointers
4188        // for FREEFORM so that the spots smoothly track gestures.
4189        if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
4190            mPointerGesture.spotIdBits.clear();
4191            for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
4192                uint32_t id = mCurrentTouch.pointers[i].id;
4193                mPointerGesture.spotIdBits.markBit(id);
4194                mPointerGesture.spotIdToIndex[id] = i;
4195
4196                float x = (mCurrentTouch.pointers[i].x - mPointerGesture.referenceTouchX)
4197                        * mLocked.pointerGestureXZoomScale + mPointerGesture.referenceGestureX;
4198                float y = (mCurrentTouch.pointers[i].y - mPointerGesture.referenceTouchY)
4199                        * mLocked.pointerGestureYZoomScale + mPointerGesture.referenceGestureY;
4200
4201                mPointerGesture.spotCoords[i].clear();
4202                mPointerGesture.spotCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, x);
4203                mPointerGesture.spotCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
4204                mPointerGesture.spotCoords[i].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4205            }
4206            moveSpotsLocked();
4207        }
4208    }
4209
4210    mPointerController->setButtonState(mCurrentTouch.buttonState);
4211
4212#if DEBUG_GESTURES
4213    LOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
4214            "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
4215            "lastGestureMode=%d, lastGestureIdBits=0x%08x",
4216            toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
4217            mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
4218            mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
4219    for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) {
4220        uint32_t id = idBits.firstMarkedBit();
4221        idBits.clearBit(id);
4222        uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
4223        const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
4224        LOGD("  currentGesture[%d]: index=%d, x=%0.3f, y=%0.3f, pressure=%0.3f",
4225                id, index, coords.getAxisValue(AMOTION_EVENT_AXIS_X),
4226                coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
4227                coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
4228    }
4229    for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) {
4230        uint32_t id = idBits.firstMarkedBit();
4231        idBits.clearBit(id);
4232        uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
4233        const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
4234        LOGD("  lastGesture[%d]: index=%d, x=%0.3f, y=%0.3f, pressure=%0.3f",
4235                id, index, coords.getAxisValue(AMOTION_EVENT_AXIS_X),
4236                coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
4237                coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
4238    }
4239#endif
4240    return true;
4241}
4242
4243void TouchInputMapper::moveSpotsLocked() {
4244    mPointerController->setSpots(mPointerGesture.spotGesture,
4245            mPointerGesture.spotCoords, mPointerGesture.spotIdToIndex, mPointerGesture.spotIdBits);
4246}
4247
4248void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
4249        int32_t action, int32_t flags, uint32_t metaState, int32_t edgeFlags,
4250        const PointerCoords* coords, const uint32_t* idToIndex, BitSet32 idBits,
4251        int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {
4252    PointerCoords pointerCoords[MAX_POINTERS];
4253    int32_t pointerIds[MAX_POINTERS];
4254    uint32_t pointerCount = 0;
4255    while (!idBits.isEmpty()) {
4256        uint32_t id = idBits.firstMarkedBit();
4257        idBits.clearBit(id);
4258        uint32_t index = idToIndex[id];
4259        pointerIds[pointerCount] = id;
4260        pointerCoords[pointerCount].copyFrom(coords[index]);
4261
4262        if (changedId >= 0 && id == uint32_t(changedId)) {
4263            action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
4264        }
4265
4266        pointerCount += 1;
4267    }
4268
4269    assert(pointerCount != 0);
4270
4271    if (changedId >= 0 && pointerCount == 1) {
4272        // Replace initial down and final up action.
4273        // We can compare the action without masking off the changed pointer index
4274        // because we know the index is 0.
4275        if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
4276            action = AMOTION_EVENT_ACTION_DOWN;
4277        } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
4278            action = AMOTION_EVENT_ACTION_UP;
4279        } else {
4280            // Can't happen.
4281            assert(false);
4282        }
4283    }
4284
4285    getDispatcher()->notifyMotion(when, getDeviceId(), source, policyFlags,
4286            action, flags, metaState, edgeFlags,
4287            pointerCount, pointerIds, pointerCoords, xPrecision, yPrecision, downTime);
4288}
4289
4290bool TouchInputMapper::updateMovedPointerCoords(
4291        const PointerCoords* inCoords, const uint32_t* inIdToIndex,
4292        PointerCoords* outCoords, const uint32_t* outIdToIndex, BitSet32 idBits) const {
4293    bool changed = false;
4294    while (!idBits.isEmpty()) {
4295        uint32_t id = idBits.firstMarkedBit();
4296        idBits.clearBit(id);
4297
4298        uint32_t inIndex = inIdToIndex[id];
4299        uint32_t outIndex = outIdToIndex[id];
4300        const PointerCoords& curInCoords = inCoords[inIndex];
4301        PointerCoords& curOutCoords = outCoords[outIndex];
4302
4303        if (curInCoords != curOutCoords) {
4304            curOutCoords.copyFrom(curInCoords);
4305            changed = true;
4306        }
4307    }
4308    return changed;
4309}
4310
4311void TouchInputMapper::fadePointer() {
4312    { // acquire lock
4313        AutoMutex _l(mLock);
4314        if (mPointerController != NULL) {
4315            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
4316        }
4317    } // release lock
4318}
4319
4320bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
4321    return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
4322            && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
4323}
4324
4325const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
4326        int32_t x, int32_t y) {
4327    size_t numVirtualKeys = mLocked.virtualKeys.size();
4328    for (size_t i = 0; i < numVirtualKeys; i++) {
4329        const VirtualKey& virtualKey = mLocked.virtualKeys[i];
4330
4331#if DEBUG_VIRTUAL_KEYS
4332        LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
4333                "left=%d, top=%d, right=%d, bottom=%d",
4334                x, y,
4335                virtualKey.keyCode, virtualKey.scanCode,
4336                virtualKey.hitLeft, virtualKey.hitTop,
4337                virtualKey.hitRight, virtualKey.hitBottom);
4338#endif
4339
4340        if (virtualKey.isHit(x, y)) {
4341            return & virtualKey;
4342        }
4343    }
4344
4345    return NULL;
4346}
4347
4348void TouchInputMapper::calculatePointerIds() {
4349    uint32_t currentPointerCount = mCurrentTouch.pointerCount;
4350    uint32_t lastPointerCount = mLastTouch.pointerCount;
4351
4352    if (currentPointerCount == 0) {
4353        // No pointers to assign.
4354        mCurrentTouch.idBits.clear();
4355    } else if (lastPointerCount == 0) {
4356        // All pointers are new.
4357        mCurrentTouch.idBits.clear();
4358        for (uint32_t i = 0; i < currentPointerCount; i++) {
4359            mCurrentTouch.pointers[i].id = i;
4360            mCurrentTouch.idToIndex[i] = i;
4361            mCurrentTouch.idBits.markBit(i);
4362        }
4363    } else if (currentPointerCount == 1 && lastPointerCount == 1) {
4364        // Only one pointer and no change in count so it must have the same id as before.
4365        uint32_t id = mLastTouch.pointers[0].id;
4366        mCurrentTouch.pointers[0].id = id;
4367        mCurrentTouch.idToIndex[id] = 0;
4368        mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
4369    } else {
4370        // General case.
4371        // We build a heap of squared euclidean distances between current and last pointers
4372        // associated with the current and last pointer indices.  Then, we find the best
4373        // match (by distance) for each current pointer.
4374        PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
4375
4376        uint32_t heapSize = 0;
4377        for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
4378                currentPointerIndex++) {
4379            for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
4380                    lastPointerIndex++) {
4381                int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
4382                        - mLastTouch.pointers[lastPointerIndex].x;
4383                int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
4384                        - mLastTouch.pointers[lastPointerIndex].y;
4385
4386                uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
4387
4388                // Insert new element into the heap (sift up).
4389                heap[heapSize].currentPointerIndex = currentPointerIndex;
4390                heap[heapSize].lastPointerIndex = lastPointerIndex;
4391                heap[heapSize].distance = distance;
4392                heapSize += 1;
4393            }
4394        }
4395
4396        // Heapify
4397        for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
4398            startIndex -= 1;
4399            for (uint32_t parentIndex = startIndex; ;) {
4400                uint32_t childIndex = parentIndex * 2 + 1;
4401                if (childIndex >= heapSize) {
4402                    break;
4403                }
4404
4405                if (childIndex + 1 < heapSize
4406                        && heap[childIndex + 1].distance < heap[childIndex].distance) {
4407                    childIndex += 1;
4408                }
4409
4410                if (heap[parentIndex].distance <= heap[childIndex].distance) {
4411                    break;
4412                }
4413
4414                swap(heap[parentIndex], heap[childIndex]);
4415                parentIndex = childIndex;
4416            }
4417        }
4418
4419#if DEBUG_POINTER_ASSIGNMENT
4420        LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
4421        for (size_t i = 0; i < heapSize; i++) {
4422            LOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
4423                    i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
4424                    heap[i].distance);
4425        }
4426#endif
4427
4428        // Pull matches out by increasing order of distance.
4429        // To avoid reassigning pointers that have already been matched, the loop keeps track
4430        // of which last and current pointers have been matched using the matchedXXXBits variables.
4431        // It also tracks the used pointer id bits.
4432        BitSet32 matchedLastBits(0);
4433        BitSet32 matchedCurrentBits(0);
4434        BitSet32 usedIdBits(0);
4435        bool first = true;
4436        for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
4437            for (;;) {
4438                if (first) {
4439                    // The first time through the loop, we just consume the root element of
4440                    // the heap (the one with smallest distance).
4441                    first = false;
4442                } else {
4443                    // Previous iterations consumed the root element of the heap.
4444                    // Pop root element off of the heap (sift down).
4445                    heapSize -= 1;
4446                    assert(heapSize > 0);
4447
4448                    // Sift down.
4449                    heap[0] = heap[heapSize];
4450                    for (uint32_t parentIndex = 0; ;) {
4451                        uint32_t childIndex = parentIndex * 2 + 1;
4452                        if (childIndex >= heapSize) {
4453                            break;
4454                        }
4455
4456                        if (childIndex + 1 < heapSize
4457                                && heap[childIndex + 1].distance < heap[childIndex].distance) {
4458                            childIndex += 1;
4459                        }
4460
4461                        if (heap[parentIndex].distance <= heap[childIndex].distance) {
4462                            break;
4463                        }
4464
4465                        swap(heap[parentIndex], heap[childIndex]);
4466                        parentIndex = childIndex;
4467                    }
4468
4469#if DEBUG_POINTER_ASSIGNMENT
4470                    LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
4471                    for (size_t i = 0; i < heapSize; i++) {
4472                        LOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
4473                                i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
4474                                heap[i].distance);
4475                    }
4476#endif
4477                }
4478
4479                uint32_t currentPointerIndex = heap[0].currentPointerIndex;
4480                if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
4481
4482                uint32_t lastPointerIndex = heap[0].lastPointerIndex;
4483                if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
4484
4485                matchedCurrentBits.markBit(currentPointerIndex);
4486                matchedLastBits.markBit(lastPointerIndex);
4487
4488                uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
4489                mCurrentTouch.pointers[currentPointerIndex].id = id;
4490                mCurrentTouch.idToIndex[id] = currentPointerIndex;
4491                usedIdBits.markBit(id);
4492
4493#if DEBUG_POINTER_ASSIGNMENT
4494                LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
4495                        lastPointerIndex, currentPointerIndex, id, heap[0].distance);
4496#endif
4497                break;
4498            }
4499        }
4500
4501        // Assign fresh ids to new pointers.
4502        if (currentPointerCount > lastPointerCount) {
4503            for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
4504                uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
4505                uint32_t id = usedIdBits.firstUnmarkedBit();
4506
4507                mCurrentTouch.pointers[currentPointerIndex].id = id;
4508                mCurrentTouch.idToIndex[id] = currentPointerIndex;
4509                usedIdBits.markBit(id);
4510
4511#if DEBUG_POINTER_ASSIGNMENT
4512                LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
4513                        currentPointerIndex, id);
4514#endif
4515
4516                if (--i == 0) break; // done
4517                matchedCurrentBits.markBit(currentPointerIndex);
4518            }
4519        }
4520
4521        // Fix id bits.
4522        mCurrentTouch.idBits = usedIdBits;
4523    }
4524}
4525
4526/* Special hack for devices that have bad screen data: if one of the
4527 * points has moved more than a screen height from the last position,
4528 * then drop it. */
4529bool TouchInputMapper::applyBadTouchFilter() {
4530    uint32_t pointerCount = mCurrentTouch.pointerCount;
4531
4532    // Nothing to do if there are no points.
4533    if (pointerCount == 0) {
4534        return false;
4535    }
4536
4537    // Don't do anything if a finger is going down or up.  We run
4538    // here before assigning pointer IDs, so there isn't a good
4539    // way to do per-finger matching.
4540    if (pointerCount != mLastTouch.pointerCount) {
4541        return false;
4542    }
4543
4544    // We consider a single movement across more than a 7/16 of
4545    // the long size of the screen to be bad.  This was a magic value
4546    // determined by looking at the maximum distance it is feasible
4547    // to actually move in one sample.
4548    int32_t maxDeltaY = (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1) * 7 / 16;
4549
4550    // XXX The original code in InputDevice.java included commented out
4551    //     code for testing the X axis.  Note that when we drop a point
4552    //     we don't actually restore the old X either.  Strange.
4553    //     The old code also tries to track when bad points were previously
4554    //     detected but it turns out that due to the placement of a "break"
4555    //     at the end of the loop, we never set mDroppedBadPoint to true
4556    //     so it is effectively dead code.
4557    // Need to figure out if the old code is busted or just overcomplicated
4558    // but working as intended.
4559
4560    // Look through all new points and see if any are farther than
4561    // acceptable from all previous points.
4562    for (uint32_t i = pointerCount; i-- > 0; ) {
4563        int32_t y = mCurrentTouch.pointers[i].y;
4564        int32_t closestY = INT_MAX;
4565        int32_t closestDeltaY = 0;
4566
4567#if DEBUG_HACKS
4568        LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
4569#endif
4570
4571        for (uint32_t j = pointerCount; j-- > 0; ) {
4572            int32_t lastY = mLastTouch.pointers[j].y;
4573            int32_t deltaY = abs(y - lastY);
4574
4575#if DEBUG_HACKS
4576            LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
4577                    j, lastY, deltaY);
4578#endif
4579
4580            if (deltaY < maxDeltaY) {
4581                goto SkipSufficientlyClosePoint;
4582            }
4583            if (deltaY < closestDeltaY) {
4584                closestDeltaY = deltaY;
4585                closestY = lastY;
4586            }
4587        }
4588
4589        // Must not have found a close enough match.
4590#if DEBUG_HACKS
4591        LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
4592                i, y, closestY, closestDeltaY, maxDeltaY);
4593#endif
4594
4595        mCurrentTouch.pointers[i].y = closestY;
4596        return true; // XXX original code only corrects one point
4597
4598    SkipSufficientlyClosePoint: ;
4599    }
4600
4601    // No change.
4602    return false;
4603}
4604
4605/* Special hack for devices that have bad screen data: drop points where
4606 * the coordinate value for one axis has jumped to the other pointer's location.
4607 */
4608bool TouchInputMapper::applyJumpyTouchFilter() {
4609    uint32_t pointerCount = mCurrentTouch.pointerCount;
4610    if (mLastTouch.pointerCount != pointerCount) {
4611#if DEBUG_HACKS
4612        LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
4613                mLastTouch.pointerCount, pointerCount);
4614        for (uint32_t i = 0; i < pointerCount; i++) {
4615            LOGD("  Pointer %d (%d, %d)", i,
4616                    mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
4617        }
4618#endif
4619
4620        if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
4621            if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
4622                // Just drop the first few events going from 1 to 2 pointers.
4623                // They're bad often enough that they're not worth considering.
4624                mCurrentTouch.pointerCount = 1;
4625                mJumpyTouchFilter.jumpyPointsDropped += 1;
4626
4627#if DEBUG_HACKS
4628                LOGD("JumpyTouchFilter: Pointer 2 dropped");
4629#endif
4630                return true;
4631            } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
4632                // The event when we go from 2 -> 1 tends to be messed up too
4633                mCurrentTouch.pointerCount = 2;
4634                mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
4635                mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
4636                mJumpyTouchFilter.jumpyPointsDropped += 1;
4637
4638#if DEBUG_HACKS
4639                for (int32_t i = 0; i < 2; i++) {
4640                    LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
4641                            mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
4642                }
4643#endif
4644                return true;
4645            }
4646        }
4647        // Reset jumpy points dropped on other transitions or if limit exceeded.
4648        mJumpyTouchFilter.jumpyPointsDropped = 0;
4649
4650#if DEBUG_HACKS
4651        LOGD("JumpyTouchFilter: Transition - drop limit reset");
4652#endif
4653        return false;
4654    }
4655
4656    // We have the same number of pointers as last time.
4657    // A 'jumpy' point is one where the coordinate value for one axis
4658    // has jumped to the other pointer's location. No need to do anything
4659    // else if we only have one pointer.
4660    if (pointerCount < 2) {
4661        return false;
4662    }
4663
4664    if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
4665        int jumpyEpsilon = (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1) / JUMPY_EPSILON_DIVISOR;
4666
4667        // We only replace the single worst jumpy point as characterized by pointer distance
4668        // in a single axis.
4669        int32_t badPointerIndex = -1;
4670        int32_t badPointerReplacementIndex = -1;
4671        int32_t badPointerDistance = INT_MIN; // distance to be corrected
4672
4673        for (uint32_t i = pointerCount; i-- > 0; ) {
4674            int32_t x = mCurrentTouch.pointers[i].x;
4675            int32_t y = mCurrentTouch.pointers[i].y;
4676
4677#if DEBUG_HACKS
4678            LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
4679#endif
4680
4681            // Check if a touch point is too close to another's coordinates
4682            bool dropX = false, dropY = false;
4683            for (uint32_t j = 0; j < pointerCount; j++) {
4684                if (i == j) {
4685                    continue;
4686                }
4687
4688                if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
4689                    dropX = true;
4690                    break;
4691                }
4692
4693                if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
4694                    dropY = true;
4695                    break;
4696                }
4697            }
4698            if (! dropX && ! dropY) {
4699                continue; // not jumpy
4700            }
4701
4702            // Find a replacement candidate by comparing with older points on the
4703            // complementary (non-jumpy) axis.
4704            int32_t distance = INT_MIN; // distance to be corrected
4705            int32_t replacementIndex = -1;
4706
4707            if (dropX) {
4708                // X looks too close.  Find an older replacement point with a close Y.
4709                int32_t smallestDeltaY = INT_MAX;
4710                for (uint32_t j = 0; j < pointerCount; j++) {
4711                    int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
4712                    if (deltaY < smallestDeltaY) {
4713                        smallestDeltaY = deltaY;
4714                        replacementIndex = j;
4715                    }
4716                }
4717                distance = abs(x - mLastTouch.pointers[replacementIndex].x);
4718            } else {
4719                // Y looks too close.  Find an older replacement point with a close X.
4720                int32_t smallestDeltaX = INT_MAX;
4721                for (uint32_t j = 0; j < pointerCount; j++) {
4722                    int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
4723                    if (deltaX < smallestDeltaX) {
4724                        smallestDeltaX = deltaX;
4725                        replacementIndex = j;
4726                    }
4727                }
4728                distance = abs(y - mLastTouch.pointers[replacementIndex].y);
4729            }
4730
4731            // If replacing this pointer would correct a worse error than the previous ones
4732            // considered, then use this replacement instead.
4733            if (distance > badPointerDistance) {
4734                badPointerIndex = i;
4735                badPointerReplacementIndex = replacementIndex;
4736                badPointerDistance = distance;
4737            }
4738        }
4739
4740        // Correct the jumpy pointer if one was found.
4741        if (badPointerIndex >= 0) {
4742#if DEBUG_HACKS
4743            LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
4744                    badPointerIndex,
4745                    mLastTouch.pointers[badPointerReplacementIndex].x,
4746                    mLastTouch.pointers[badPointerReplacementIndex].y);
4747#endif
4748
4749            mCurrentTouch.pointers[badPointerIndex].x =
4750                    mLastTouch.pointers[badPointerReplacementIndex].x;
4751            mCurrentTouch.pointers[badPointerIndex].y =
4752                    mLastTouch.pointers[badPointerReplacementIndex].y;
4753            mJumpyTouchFilter.jumpyPointsDropped += 1;
4754            return true;
4755        }
4756    }
4757
4758    mJumpyTouchFilter.jumpyPointsDropped = 0;
4759    return false;
4760}
4761
4762/* Special hack for devices that have bad screen data: aggregate and
4763 * compute averages of the coordinate data, to reduce the amount of
4764 * jitter seen by applications. */
4765void TouchInputMapper::applyAveragingTouchFilter() {
4766    for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
4767        uint32_t id = mCurrentTouch.pointers[currentIndex].id;
4768        int32_t x = mCurrentTouch.pointers[currentIndex].x;
4769        int32_t y = mCurrentTouch.pointers[currentIndex].y;
4770        int32_t pressure;
4771        switch (mCalibration.pressureSource) {
4772        case Calibration::PRESSURE_SOURCE_PRESSURE:
4773            pressure = mCurrentTouch.pointers[currentIndex].pressure;
4774            break;
4775        case Calibration::PRESSURE_SOURCE_TOUCH:
4776            pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
4777            break;
4778        default:
4779            pressure = 1;
4780            break;
4781        }
4782
4783        if (mLastTouch.idBits.hasBit(id)) {
4784            // Pointer was down before and is still down now.
4785            // Compute average over history trace.
4786            uint32_t start = mAveragingTouchFilter.historyStart[id];
4787            uint32_t end = mAveragingTouchFilter.historyEnd[id];
4788
4789            int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
4790            int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
4791            uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
4792
4793#if DEBUG_HACKS
4794            LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
4795                    id, distance);
4796#endif
4797
4798            if (distance < AVERAGING_DISTANCE_LIMIT) {
4799                // Increment end index in preparation for recording new historical data.
4800                end += 1;
4801                if (end > AVERAGING_HISTORY_SIZE) {
4802                    end = 0;
4803                }
4804
4805                // If the end index has looped back to the start index then we have filled
4806                // the historical trace up to the desired size so we drop the historical
4807                // data at the start of the trace.
4808                if (end == start) {
4809                    start += 1;
4810                    if (start > AVERAGING_HISTORY_SIZE) {
4811                        start = 0;
4812                    }
4813                }
4814
4815                // Add the raw data to the historical trace.
4816                mAveragingTouchFilter.historyStart[id] = start;
4817                mAveragingTouchFilter.historyEnd[id] = end;
4818                mAveragingTouchFilter.historyData[end].pointers[id].x = x;
4819                mAveragingTouchFilter.historyData[end].pointers[id].y = y;
4820                mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
4821
4822                // Average over all historical positions in the trace by total pressure.
4823                int32_t averagedX = 0;
4824                int32_t averagedY = 0;
4825                int32_t totalPressure = 0;
4826                for (;;) {
4827                    int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
4828                    int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
4829                    int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
4830                            .pointers[id].pressure;
4831
4832                    averagedX += historicalX * historicalPressure;
4833                    averagedY += historicalY * historicalPressure;
4834                    totalPressure += historicalPressure;
4835
4836                    if (start == end) {
4837                        break;
4838                    }
4839
4840                    start += 1;
4841                    if (start > AVERAGING_HISTORY_SIZE) {
4842                        start = 0;
4843                    }
4844                }
4845
4846                if (totalPressure != 0) {
4847                    averagedX /= totalPressure;
4848                    averagedY /= totalPressure;
4849
4850#if DEBUG_HACKS
4851                    LOGD("AveragingTouchFilter: Pointer id %d - "
4852                            "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
4853                            averagedX, averagedY);
4854#endif
4855
4856                    mCurrentTouch.pointers[currentIndex].x = averagedX;
4857                    mCurrentTouch.pointers[currentIndex].y = averagedY;
4858                }
4859            } else {
4860#if DEBUG_HACKS
4861                LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
4862#endif
4863            }
4864        } else {
4865#if DEBUG_HACKS
4866            LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
4867#endif
4868        }
4869
4870        // Reset pointer history.
4871        mAveragingTouchFilter.historyStart[id] = 0;
4872        mAveragingTouchFilter.historyEnd[id] = 0;
4873        mAveragingTouchFilter.historyData[0].pointers[id].x = x;
4874        mAveragingTouchFilter.historyData[0].pointers[id].y = y;
4875        mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
4876    }
4877}
4878
4879int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
4880    { // acquire lock
4881        AutoMutex _l(mLock);
4882
4883        if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
4884            return AKEY_STATE_VIRTUAL;
4885        }
4886
4887        size_t numVirtualKeys = mLocked.virtualKeys.size();
4888        for (size_t i = 0; i < numVirtualKeys; i++) {
4889            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
4890            if (virtualKey.keyCode == keyCode) {
4891                return AKEY_STATE_UP;
4892            }
4893        }
4894    } // release lock
4895
4896    return AKEY_STATE_UNKNOWN;
4897}
4898
4899int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
4900    { // acquire lock
4901        AutoMutex _l(mLock);
4902
4903        if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
4904            return AKEY_STATE_VIRTUAL;
4905        }
4906
4907        size_t numVirtualKeys = mLocked.virtualKeys.size();
4908        for (size_t i = 0; i < numVirtualKeys; i++) {
4909            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
4910            if (virtualKey.scanCode == scanCode) {
4911                return AKEY_STATE_UP;
4912            }
4913        }
4914    } // release lock
4915
4916    return AKEY_STATE_UNKNOWN;
4917}
4918
4919bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
4920        const int32_t* keyCodes, uint8_t* outFlags) {
4921    { // acquire lock
4922        AutoMutex _l(mLock);
4923
4924        size_t numVirtualKeys = mLocked.virtualKeys.size();
4925        for (size_t i = 0; i < numVirtualKeys; i++) {
4926            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
4927
4928            for (size_t i = 0; i < numCodes; i++) {
4929                if (virtualKey.keyCode == keyCodes[i]) {
4930                    outFlags[i] = 1;
4931                }
4932            }
4933        }
4934    } // release lock
4935
4936    return true;
4937}
4938
4939
4940// --- SingleTouchInputMapper ---
4941
4942SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
4943        TouchInputMapper(device) {
4944    initialize();
4945}
4946
4947SingleTouchInputMapper::~SingleTouchInputMapper() {
4948}
4949
4950void SingleTouchInputMapper::initialize() {
4951    mAccumulator.clear();
4952
4953    mDown = false;
4954    mX = 0;
4955    mY = 0;
4956    mPressure = 0; // default to 0 for devices that don't report pressure
4957    mToolWidth = 0; // default to 0 for devices that don't report tool width
4958    mButtonState = 0;
4959}
4960
4961void SingleTouchInputMapper::reset() {
4962    TouchInputMapper::reset();
4963
4964    initialize();
4965 }
4966
4967void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
4968    switch (rawEvent->type) {
4969    case EV_KEY:
4970        switch (rawEvent->scanCode) {
4971        case BTN_TOUCH:
4972            mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
4973            mAccumulator.btnTouch = rawEvent->value != 0;
4974            // Don't sync immediately.  Wait until the next SYN_REPORT since we might
4975            // not have received valid position information yet.  This logic assumes that
4976            // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
4977            break;
4978        default:
4979            if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
4980                uint32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
4981                if (buttonState) {
4982                    if (rawEvent->value) {
4983                        mAccumulator.buttonDown |= buttonState;
4984                    } else {
4985                        mAccumulator.buttonUp |= buttonState;
4986                    }
4987                    mAccumulator.fields |= Accumulator::FIELD_BUTTONS;
4988                }
4989            }
4990            break;
4991        }
4992        break;
4993
4994    case EV_ABS:
4995        switch (rawEvent->scanCode) {
4996        case ABS_X:
4997            mAccumulator.fields |= Accumulator::FIELD_ABS_X;
4998            mAccumulator.absX = rawEvent->value;
4999            break;
5000        case ABS_Y:
5001            mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
5002            mAccumulator.absY = rawEvent->value;
5003            break;
5004        case ABS_PRESSURE:
5005            mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
5006            mAccumulator.absPressure = rawEvent->value;
5007            break;
5008        case ABS_TOOL_WIDTH:
5009            mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
5010            mAccumulator.absToolWidth = rawEvent->value;
5011            break;
5012        }
5013        break;
5014
5015    case EV_SYN:
5016        switch (rawEvent->scanCode) {
5017        case SYN_REPORT:
5018            sync(rawEvent->when);
5019            break;
5020        }
5021        break;
5022    }
5023}
5024
5025void SingleTouchInputMapper::sync(nsecs_t when) {
5026    uint32_t fields = mAccumulator.fields;
5027    if (fields == 0) {
5028        return; // no new state changes, so nothing to do
5029    }
5030
5031    if (fields & Accumulator::FIELD_BTN_TOUCH) {
5032        mDown = mAccumulator.btnTouch;
5033    }
5034
5035    if (fields & Accumulator::FIELD_ABS_X) {
5036        mX = mAccumulator.absX;
5037    }
5038
5039    if (fields & Accumulator::FIELD_ABS_Y) {
5040        mY = mAccumulator.absY;
5041    }
5042
5043    if (fields & Accumulator::FIELD_ABS_PRESSURE) {
5044        mPressure = mAccumulator.absPressure;
5045    }
5046
5047    if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
5048        mToolWidth = mAccumulator.absToolWidth;
5049    }
5050
5051    if (fields & Accumulator::FIELD_BUTTONS) {
5052        mButtonState = (mButtonState | mAccumulator.buttonDown) & ~mAccumulator.buttonUp;
5053    }
5054
5055    mCurrentTouch.clear();
5056
5057    if (mDown) {
5058        mCurrentTouch.pointerCount = 1;
5059        mCurrentTouch.pointers[0].id = 0;
5060        mCurrentTouch.pointers[0].x = mX;
5061        mCurrentTouch.pointers[0].y = mY;
5062        mCurrentTouch.pointers[0].pressure = mPressure;
5063        mCurrentTouch.pointers[0].touchMajor = 0;
5064        mCurrentTouch.pointers[0].touchMinor = 0;
5065        mCurrentTouch.pointers[0].toolMajor = mToolWidth;
5066        mCurrentTouch.pointers[0].toolMinor = mToolWidth;
5067        mCurrentTouch.pointers[0].orientation = 0;
5068        mCurrentTouch.idToIndex[0] = 0;
5069        mCurrentTouch.idBits.markBit(0);
5070        mCurrentTouch.buttonState = mButtonState;
5071    }
5072
5073    syncTouch(when, true);
5074
5075    mAccumulator.clear();
5076}
5077
5078void SingleTouchInputMapper::configureRawAxes() {
5079    TouchInputMapper::configureRawAxes();
5080
5081    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
5082    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
5083    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
5084    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
5085}
5086
5087
5088// --- MultiTouchInputMapper ---
5089
5090MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
5091        TouchInputMapper(device) {
5092    initialize();
5093}
5094
5095MultiTouchInputMapper::~MultiTouchInputMapper() {
5096}
5097
5098void MultiTouchInputMapper::initialize() {
5099    mAccumulator.clear();
5100    mButtonState = 0;
5101}
5102
5103void MultiTouchInputMapper::reset() {
5104    TouchInputMapper::reset();
5105
5106    initialize();
5107}
5108
5109void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
5110    switch (rawEvent->type) {
5111    case EV_KEY: {
5112        if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
5113            uint32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
5114            if (buttonState) {
5115                if (rawEvent->value) {
5116                    mAccumulator.buttonDown |= buttonState;
5117                } else {
5118                    mAccumulator.buttonUp |= buttonState;
5119                }
5120            }
5121        }
5122        break;
5123    }
5124
5125    case EV_ABS: {
5126        uint32_t pointerIndex = mAccumulator.pointerCount;
5127        Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
5128
5129        switch (rawEvent->scanCode) {
5130        case ABS_MT_POSITION_X:
5131            pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
5132            pointer->absMTPositionX = rawEvent->value;
5133            break;
5134        case ABS_MT_POSITION_Y:
5135            pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
5136            pointer->absMTPositionY = rawEvent->value;
5137            break;
5138        case ABS_MT_TOUCH_MAJOR:
5139            pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
5140            pointer->absMTTouchMajor = rawEvent->value;
5141            break;
5142        case ABS_MT_TOUCH_MINOR:
5143            pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
5144            pointer->absMTTouchMinor = rawEvent->value;
5145            break;
5146        case ABS_MT_WIDTH_MAJOR:
5147            pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
5148            pointer->absMTWidthMajor = rawEvent->value;
5149            break;
5150        case ABS_MT_WIDTH_MINOR:
5151            pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
5152            pointer->absMTWidthMinor = rawEvent->value;
5153            break;
5154        case ABS_MT_ORIENTATION:
5155            pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
5156            pointer->absMTOrientation = rawEvent->value;
5157            break;
5158        case ABS_MT_TRACKING_ID:
5159            pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
5160            pointer->absMTTrackingId = rawEvent->value;
5161            break;
5162        case ABS_MT_PRESSURE:
5163            pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
5164            pointer->absMTPressure = rawEvent->value;
5165            break;
5166        }
5167        break;
5168    }
5169
5170    case EV_SYN:
5171        switch (rawEvent->scanCode) {
5172        case SYN_MT_REPORT: {
5173            // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
5174            uint32_t pointerIndex = mAccumulator.pointerCount;
5175
5176            if (mAccumulator.pointers[pointerIndex].fields) {
5177                if (pointerIndex == MAX_POINTERS) {
5178                    LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
5179                            MAX_POINTERS);
5180                } else {
5181                    pointerIndex += 1;
5182                    mAccumulator.pointerCount = pointerIndex;
5183                }
5184            }
5185
5186            mAccumulator.pointers[pointerIndex].clear();
5187            break;
5188        }
5189
5190        case SYN_REPORT:
5191            sync(rawEvent->when);
5192            break;
5193        }
5194        break;
5195    }
5196}
5197
5198void MultiTouchInputMapper::sync(nsecs_t when) {
5199    static const uint32_t REQUIRED_FIELDS =
5200            Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
5201
5202    uint32_t inCount = mAccumulator.pointerCount;
5203    uint32_t outCount = 0;
5204    bool havePointerIds = true;
5205
5206    mCurrentTouch.clear();
5207
5208    for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
5209        const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
5210        uint32_t fields = inPointer.fields;
5211
5212        if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
5213            // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
5214            // Drop this finger.
5215            continue;
5216        }
5217
5218        PointerData& outPointer = mCurrentTouch.pointers[outCount];
5219        outPointer.x = inPointer.absMTPositionX;
5220        outPointer.y = inPointer.absMTPositionY;
5221
5222        if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
5223            if (inPointer.absMTPressure <= 0) {
5224                // Some devices send sync packets with X / Y but with a 0 pressure to indicate
5225                // a pointer going up.  Drop this finger.
5226                continue;
5227            }
5228            outPointer.pressure = inPointer.absMTPressure;
5229        } else {
5230            // Default pressure to 0 if absent.
5231            outPointer.pressure = 0;
5232        }
5233
5234        if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
5235            if (inPointer.absMTTouchMajor <= 0) {
5236                // Some devices send sync packets with X / Y but with a 0 touch major to indicate
5237                // a pointer going up.  Drop this finger.
5238                continue;
5239            }
5240            outPointer.touchMajor = inPointer.absMTTouchMajor;
5241        } else {
5242            // Default touch area to 0 if absent.
5243            outPointer.touchMajor = 0;
5244        }
5245
5246        if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
5247            outPointer.touchMinor = inPointer.absMTTouchMinor;
5248        } else {
5249            // Assume touch area is circular.
5250            outPointer.touchMinor = outPointer.touchMajor;
5251        }
5252
5253        if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
5254            outPointer.toolMajor = inPointer.absMTWidthMajor;
5255        } else {
5256            // Default tool area to 0 if absent.
5257            outPointer.toolMajor = 0;
5258        }
5259
5260        if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
5261            outPointer.toolMinor = inPointer.absMTWidthMinor;
5262        } else {
5263            // Assume tool area is circular.
5264            outPointer.toolMinor = outPointer.toolMajor;
5265        }
5266
5267        if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
5268            outPointer.orientation = inPointer.absMTOrientation;
5269        } else {
5270            // Default orientation to vertical if absent.
5271            outPointer.orientation = 0;
5272        }
5273
5274        // Assign pointer id using tracking id if available.
5275        if (havePointerIds) {
5276            if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
5277                uint32_t id = uint32_t(inPointer.absMTTrackingId);
5278
5279                if (id > MAX_POINTER_ID) {
5280#if DEBUG_POINTERS
5281                    LOGD("Pointers: Ignoring driver provided pointer id %d because "
5282                            "it is larger than max supported id %d",
5283                            id, MAX_POINTER_ID);
5284#endif
5285                    havePointerIds = false;
5286                }
5287                else {
5288                    outPointer.id = id;
5289                    mCurrentTouch.idToIndex[id] = outCount;
5290                    mCurrentTouch.idBits.markBit(id);
5291                }
5292            } else {
5293                havePointerIds = false;
5294            }
5295        }
5296
5297        outCount += 1;
5298    }
5299
5300    mCurrentTouch.pointerCount = outCount;
5301
5302    mButtonState = (mButtonState | mAccumulator.buttonDown) & ~mAccumulator.buttonUp;
5303    mCurrentTouch.buttonState = mButtonState;
5304
5305    syncTouch(when, havePointerIds);
5306
5307    mAccumulator.clear();
5308}
5309
5310void MultiTouchInputMapper::configureRawAxes() {
5311    TouchInputMapper::configureRawAxes();
5312
5313    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
5314    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
5315    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
5316    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
5317    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
5318    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
5319    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
5320    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
5321}
5322
5323
5324// --- JoystickInputMapper ---
5325
5326JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
5327        InputMapper(device) {
5328}
5329
5330JoystickInputMapper::~JoystickInputMapper() {
5331}
5332
5333uint32_t JoystickInputMapper::getSources() {
5334    return AINPUT_SOURCE_JOYSTICK;
5335}
5336
5337void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
5338    InputMapper::populateDeviceInfo(info);
5339
5340    for (size_t i = 0; i < mAxes.size(); i++) {
5341        const Axis& axis = mAxes.valueAt(i);
5342        info->addMotionRange(axis.axisInfo.axis, AINPUT_SOURCE_JOYSTICK,
5343                axis.min, axis.max, axis.flat, axis.fuzz);
5344        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5345            info->addMotionRange(axis.axisInfo.highAxis, AINPUT_SOURCE_JOYSTICK,
5346                    axis.min, axis.max, axis.flat, axis.fuzz);
5347        }
5348    }
5349}
5350
5351void JoystickInputMapper::dump(String8& dump) {
5352    dump.append(INDENT2 "Joystick Input Mapper:\n");
5353
5354    dump.append(INDENT3 "Axes:\n");
5355    size_t numAxes = mAxes.size();
5356    for (size_t i = 0; i < numAxes; i++) {
5357        const Axis& axis = mAxes.valueAt(i);
5358        const char* label = getAxisLabel(axis.axisInfo.axis);
5359        if (label) {
5360            dump.appendFormat(INDENT4 "%s", label);
5361        } else {
5362            dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis);
5363        }
5364        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5365            label = getAxisLabel(axis.axisInfo.highAxis);
5366            if (label) {
5367                dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue);
5368            } else {
5369                dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis,
5370                        axis.axisInfo.splitValue);
5371            }
5372        } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
5373            dump.append(" (invert)");
5374        }
5375
5376        dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f\n",
5377                axis.min, axis.max, axis.flat, axis.fuzz);
5378        dump.appendFormat(INDENT4 "  scale=%0.5f, offset=%0.5f, "
5379                "highScale=%0.5f, highOffset=%0.5f\n",
5380                axis.scale, axis.offset, axis.highScale, axis.highOffset);
5381        dump.appendFormat(INDENT4 "  rawAxis=%d, rawMin=%d, rawMax=%d, rawFlat=%d, rawFuzz=%d\n",
5382                mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
5383                axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz);
5384    }
5385}
5386
5387void JoystickInputMapper::configure() {
5388    InputMapper::configure();
5389
5390    // Collect all axes.
5391    for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
5392        RawAbsoluteAxisInfo rawAxisInfo;
5393        getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo);
5394        if (rawAxisInfo.valid) {
5395            // Map axis.
5396            AxisInfo axisInfo;
5397            bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
5398            if (!explicitlyMapped) {
5399                // Axis is not explicitly mapped, will choose a generic axis later.
5400                axisInfo.mode = AxisInfo::MODE_NORMAL;
5401                axisInfo.axis = -1;
5402            }
5403
5404            // Apply flat override.
5405            int32_t rawFlat = axisInfo.flatOverride < 0
5406                    ? rawAxisInfo.flat : axisInfo.flatOverride;
5407
5408            // Calculate scaling factors and limits.
5409            Axis axis;
5410            if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
5411                float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
5412                float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
5413                axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5414                        scale, 0.0f, highScale, 0.0f,
5415                        0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
5416            } else if (isCenteredAxis(axisInfo.axis)) {
5417                float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
5418                float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
5419                axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5420                        scale, offset, scale, offset,
5421                        -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
5422            } else {
5423                float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
5424                axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5425                        scale, 0.0f, scale, 0.0f,
5426                        0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
5427            }
5428
5429            // To eliminate noise while the joystick is at rest, filter out small variations
5430            // in axis values up front.
5431            axis.filter = axis.flat * 0.25f;
5432
5433            mAxes.add(abs, axis);
5434        }
5435    }
5436
5437    // If there are too many axes, start dropping them.
5438    // Prefer to keep explicitly mapped axes.
5439    if (mAxes.size() > PointerCoords::MAX_AXES) {
5440        LOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
5441                getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
5442        pruneAxes(true);
5443        pruneAxes(false);
5444    }
5445
5446    // Assign generic axis ids to remaining axes.
5447    int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
5448    size_t numAxes = mAxes.size();
5449    for (size_t i = 0; i < numAxes; i++) {
5450        Axis& axis = mAxes.editValueAt(i);
5451        if (axis.axisInfo.axis < 0) {
5452            while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
5453                    && haveAxis(nextGenericAxisId)) {
5454                nextGenericAxisId += 1;
5455            }
5456
5457            if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
5458                axis.axisInfo.axis = nextGenericAxisId;
5459                nextGenericAxisId += 1;
5460            } else {
5461                LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
5462                        "have already been assigned to other axes.",
5463                        getDeviceName().string(), mAxes.keyAt(i));
5464                mAxes.removeItemsAt(i--);
5465                numAxes -= 1;
5466            }
5467        }
5468    }
5469}
5470
5471bool JoystickInputMapper::haveAxis(int32_t axisId) {
5472    size_t numAxes = mAxes.size();
5473    for (size_t i = 0; i < numAxes; i++) {
5474        const Axis& axis = mAxes.valueAt(i);
5475        if (axis.axisInfo.axis == axisId
5476                || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
5477                        && axis.axisInfo.highAxis == axisId)) {
5478            return true;
5479        }
5480    }
5481    return false;
5482}
5483
5484void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
5485    size_t i = mAxes.size();
5486    while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
5487        if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
5488            continue;
5489        }
5490        LOGI("Discarding joystick '%s' axis %d because there are too many axes.",
5491                getDeviceName().string(), mAxes.keyAt(i));
5492        mAxes.removeItemsAt(i);
5493    }
5494}
5495
5496bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
5497    switch (axis) {
5498    case AMOTION_EVENT_AXIS_X:
5499    case AMOTION_EVENT_AXIS_Y:
5500    case AMOTION_EVENT_AXIS_Z:
5501    case AMOTION_EVENT_AXIS_RX:
5502    case AMOTION_EVENT_AXIS_RY:
5503    case AMOTION_EVENT_AXIS_RZ:
5504    case AMOTION_EVENT_AXIS_HAT_X:
5505    case AMOTION_EVENT_AXIS_HAT_Y:
5506    case AMOTION_EVENT_AXIS_ORIENTATION:
5507    case AMOTION_EVENT_AXIS_RUDDER:
5508    case AMOTION_EVENT_AXIS_WHEEL:
5509        return true;
5510    default:
5511        return false;
5512    }
5513}
5514
5515void JoystickInputMapper::reset() {
5516    // Recenter all axes.
5517    nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
5518
5519    size_t numAxes = mAxes.size();
5520    for (size_t i = 0; i < numAxes; i++) {
5521        Axis& axis = mAxes.editValueAt(i);
5522        axis.resetValue();
5523    }
5524
5525    sync(when, true /*force*/);
5526
5527    InputMapper::reset();
5528}
5529
5530void JoystickInputMapper::process(const RawEvent* rawEvent) {
5531    switch (rawEvent->type) {
5532    case EV_ABS: {
5533        ssize_t index = mAxes.indexOfKey(rawEvent->scanCode);
5534        if (index >= 0) {
5535            Axis& axis = mAxes.editValueAt(index);
5536            float newValue, highNewValue;
5537            switch (axis.axisInfo.mode) {
5538            case AxisInfo::MODE_INVERT:
5539                newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
5540                        * axis.scale + axis.offset;
5541                highNewValue = 0.0f;
5542                break;
5543            case AxisInfo::MODE_SPLIT:
5544                if (rawEvent->value < axis.axisInfo.splitValue) {
5545                    newValue = (axis.axisInfo.splitValue - rawEvent->value)
5546                            * axis.scale + axis.offset;
5547                    highNewValue = 0.0f;
5548                } else if (rawEvent->value > axis.axisInfo.splitValue) {
5549                    newValue = 0.0f;
5550                    highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
5551                            * axis.highScale + axis.highOffset;
5552                } else {
5553                    newValue = 0.0f;
5554                    highNewValue = 0.0f;
5555                }
5556                break;
5557            default:
5558                newValue = rawEvent->value * axis.scale + axis.offset;
5559                highNewValue = 0.0f;
5560                break;
5561            }
5562            axis.newValue = newValue;
5563            axis.highNewValue = highNewValue;
5564        }
5565        break;
5566    }
5567
5568    case EV_SYN:
5569        switch (rawEvent->scanCode) {
5570        case SYN_REPORT:
5571            sync(rawEvent->when, false /*force*/);
5572            break;
5573        }
5574        break;
5575    }
5576}
5577
5578void JoystickInputMapper::sync(nsecs_t when, bool force) {
5579    if (!filterAxes(force)) {
5580        return;
5581    }
5582
5583    int32_t metaState = mContext->getGlobalMetaState();
5584
5585    PointerCoords pointerCoords;
5586    pointerCoords.clear();
5587
5588    size_t numAxes = mAxes.size();
5589    for (size_t i = 0; i < numAxes; i++) {
5590        const Axis& axis = mAxes.valueAt(i);
5591        pointerCoords.setAxisValue(axis.axisInfo.axis, axis.currentValue);
5592        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5593            pointerCoords.setAxisValue(axis.axisInfo.highAxis, axis.highCurrentValue);
5594        }
5595    }
5596
5597    // Moving a joystick axis should not wake the devide because joysticks can
5598    // be fairly noisy even when not in use.  On the other hand, pushing a gamepad
5599    // button will likely wake the device.
5600    // TODO: Use the input device configuration to control this behavior more finely.
5601    uint32_t policyFlags = 0;
5602
5603    int32_t pointerId = 0;
5604    getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
5605            AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
5606            1, &pointerId, &pointerCoords, 0, 0, 0);
5607}
5608
5609bool JoystickInputMapper::filterAxes(bool force) {
5610    bool atLeastOneSignificantChange = force;
5611    size_t numAxes = mAxes.size();
5612    for (size_t i = 0; i < numAxes; i++) {
5613        Axis& axis = mAxes.editValueAt(i);
5614        if (force || hasValueChangedSignificantly(axis.filter,
5615                axis.newValue, axis.currentValue, axis.min, axis.max)) {
5616            axis.currentValue = axis.newValue;
5617            atLeastOneSignificantChange = true;
5618        }
5619        if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5620            if (force || hasValueChangedSignificantly(axis.filter,
5621                    axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
5622                axis.highCurrentValue = axis.highNewValue;
5623                atLeastOneSignificantChange = true;
5624            }
5625        }
5626    }
5627    return atLeastOneSignificantChange;
5628}
5629
5630bool JoystickInputMapper::hasValueChangedSignificantly(
5631        float filter, float newValue, float currentValue, float min, float max) {
5632    if (newValue != currentValue) {
5633        // Filter out small changes in value unless the value is converging on the axis
5634        // bounds or center point.  This is intended to reduce the amount of information
5635        // sent to applications by particularly noisy joysticks (such as PS3).
5636        if (fabs(newValue - currentValue) > filter
5637                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
5638                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
5639                || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
5640            return true;
5641        }
5642    }
5643    return false;
5644}
5645
5646bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
5647        float filter, float newValue, float currentValue, float thresholdValue) {
5648    float newDistance = fabs(newValue - thresholdValue);
5649    if (newDistance < filter) {
5650        float oldDistance = fabs(currentValue - thresholdValue);
5651        if (newDistance < oldDistance) {
5652            return true;
5653        }
5654    }
5655    return false;
5656}
5657
5658} // namespace android
5659