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