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