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