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