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