widget/gonk/libui/InputReader.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     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  */
    17 #define LOG_TAG "InputReader"
    19 //#define LOG_NDEBUG 0
    20 #include "cutils_log.h"
    22 // Log debug messages for each raw event received from the EventHub.
    23 #define DEBUG_RAW_EVENTS 0
    25 // Log debug messages about touch screen filtering hacks.
    26 #define DEBUG_HACKS 0
    28 // Log debug messages about virtual key processing.
    29 #define DEBUG_VIRTUAL_KEYS 0
    31 // Log debug messages about pointers.
    32 #define DEBUG_POINTERS 0
    34 // Log debug messages about pointer assignment calculations.
    35 #define DEBUG_POINTER_ASSIGNMENT 0
    37 // Log debug messages about gesture detection.
    38 #define DEBUG_GESTURES 0
    40 // Log debug messages about the vibrator.
    41 #define DEBUG_VIBRATOR 0
    43 #include "InputReader.h"
    45 #include "Keyboard.h"
    46 #include "VirtualKeyMap.h"
    48 #include <stddef.h>
    49 #include <stdlib.h>
    50 #include <unistd.h>
    51 #include <errno.h>
    52 #include <limits.h>
    53 #include <math.h>
    55 #define INDENT "  "
    56 #define INDENT2 "    "
    57 #define INDENT3 "      "
    58 #define INDENT4 "        "
    59 #define INDENT5 "          "
    61 namespace android {
    63 // --- Constants ---
    65 // Maximum number of slots supported when using the slot-based Multitouch Protocol B.
    66 static const size_t MAX_SLOTS = 32;
    68 // --- Static Functions ---
    70 template<typename T>
    71 inline static T abs(const T& value) {
    72     return value < 0 ? - value : value;
    73 }
    75 template<typename T>
    76 inline static T min(const T& a, const T& b) {
    77     return a < b ? a : b;
    78 }
    80 template<typename T>
    81 inline static void swap(T& a, T& b) {
    82     T temp = a;
    83     a = b;
    84     b = temp;
    85 }
    87 inline static float avg(float x, float y) {
    88     return (x + y) / 2;
    89 }
    91 inline static float distance(float x1, float y1, float x2, float y2) {
    92     return hypotf(x1 - x2, y1 - y2);
    93 }
    95 inline static int32_t signExtendNybble(int32_t value) {
    96     return value >= 8 ? value - 16 : value;
    97 }
    99 static inline const char* toString(bool value) {
   100     return value ? "true" : "false";
   101 }
   103 static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
   104         const int32_t map[][4], size_t mapSize) {
   105     if (orientation != DISPLAY_ORIENTATION_0) {
   106         for (size_t i = 0; i < mapSize; i++) {
   107             if (value == map[i][0]) {
   108                 return map[i][orientation];
   109             }
   110         }
   111     }
   112     return value;
   113 }
   115 static const int32_t keyCodeRotationMap[][4] = {
   116         // key codes enumerated counter-clockwise with the original (unrotated) key first
   117         // no rotation,        90 degree rotation,  180 degree rotation, 270 degree rotation
   118         { AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT },
   119         { AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN },
   120         { AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT },
   121         { AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP },
   122 };
   123 static const size_t keyCodeRotationMapSize =
   124         sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
   126 static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
   127     return rotateValueUsingRotationMap(keyCode, orientation,
   128             keyCodeRotationMap, keyCodeRotationMapSize);
   129 }
   131 static void rotateDelta(int32_t orientation, float* deltaX, float* deltaY) {
   132     float temp;
   133     switch (orientation) {
   134     case DISPLAY_ORIENTATION_90:
   135         temp = *deltaX;
   136         *deltaX = *deltaY;
   137         *deltaY = -temp;
   138         break;
   140     case DISPLAY_ORIENTATION_180:
   141         *deltaX = -*deltaX;
   142         *deltaY = -*deltaY;
   143         break;
   145     case DISPLAY_ORIENTATION_270:
   146         temp = *deltaX;
   147         *deltaX = -*deltaY;
   148         *deltaY = temp;
   149         break;
   150     }
   151 }
   153 static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
   154     return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
   155 }
   157 // Returns true if the pointer should be reported as being down given the specified
   158 // button states.  This determines whether the event is reported as a touch event.
   159 static bool isPointerDown(int32_t buttonState) {
   160     return buttonState &
   161             (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY
   162                     | AMOTION_EVENT_BUTTON_TERTIARY);
   163 }
   165 static float calculateCommonVector(float a, float b) {
   166     if (a > 0 && b > 0) {
   167         return a < b ? a : b;
   168     } else if (a < 0 && b < 0) {
   169         return a > b ? a : b;
   170     } else {
   171         return 0;
   172     }
   173 }
   175 static void synthesizeButtonKey(InputReaderContext* context, int32_t action,
   176         nsecs_t when, int32_t deviceId, uint32_t source,
   177         uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState,
   178         int32_t buttonState, int32_t keyCode) {
   179     if (
   180             (action == AKEY_EVENT_ACTION_DOWN
   181                     && !(lastButtonState & buttonState)
   182                     && (currentButtonState & buttonState))
   183             || (action == AKEY_EVENT_ACTION_UP
   184                     && (lastButtonState & buttonState)
   185                     && !(currentButtonState & buttonState))) {
   186         NotifyKeyArgs args(when, deviceId, source, policyFlags,
   187                 action, 0, keyCode, 0, context->getGlobalMetaState(), when);
   188         context->getListener()->notifyKey(&args);
   189     }
   190 }
   192 static void synthesizeButtonKeys(InputReaderContext* context, int32_t action,
   193         nsecs_t when, int32_t deviceId, uint32_t source,
   194         uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) {
   195     synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
   196             lastButtonState, currentButtonState,
   197             AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK);
   198     synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
   199             lastButtonState, currentButtonState,
   200             AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD);
   201 }
   204 // --- InputReaderConfiguration ---
   206 bool InputReaderConfiguration::getDisplayInfo(bool external, DisplayViewport* outViewport) const {
   207     const DisplayViewport& viewport = external ? mExternalDisplay : mInternalDisplay;
   208     if (viewport.displayId >= 0) {
   209         *outViewport = viewport;
   210         return true;
   211     }
   212     return false;
   213 }
   215 void InputReaderConfiguration::setDisplayInfo(bool external, const DisplayViewport& viewport) {
   216     DisplayViewport& v = external ? mExternalDisplay : mInternalDisplay;
   217     v = viewport;
   218 }
   221 // --- InputReader ---
   223 InputReader::InputReader(const sp<EventHubInterface>& eventHub,
   224         const sp<InputReaderPolicyInterface>& policy,
   225         const sp<InputListenerInterface>& listener) :
   226         mContext(this), mEventHub(eventHub), mPolicy(policy),
   227         mGlobalMetaState(0), mGeneration(1),
   228         mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
   229         mConfigurationChangesToRefresh(0) {
   230     mQueuedListener = new QueuedInputListener(listener);
   232     { // acquire lock
   233         AutoMutex _l(mLock);
   235         refreshConfigurationLocked(0);
   236         updateGlobalMetaStateLocked();
   237     } // release lock
   238 }
   240 InputReader::~InputReader() {
   241     for (size_t i = 0; i < mDevices.size(); i++) {
   242         delete mDevices.valueAt(i);
   243     }
   244 }
   246 void InputReader::loopOnce() {
   247     int32_t oldGeneration;
   248     int32_t timeoutMillis;
   249     bool inputDevicesChanged = false;
   250     Vector<InputDeviceInfo> inputDevices;
   251     { // acquire lock
   252         AutoMutex _l(mLock);
   254         oldGeneration = mGeneration;
   255         timeoutMillis = -1;
   257         uint32_t changes = mConfigurationChangesToRefresh;
   258         if (changes) {
   259             mConfigurationChangesToRefresh = 0;
   260             timeoutMillis = 0;
   261             refreshConfigurationLocked(changes);
   262         } else if (mNextTimeout != LLONG_MAX) {
   263             nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
   264             timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
   265         }
   266     } // release lock
   268     size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
   270     { // acquire lock
   271         AutoMutex _l(mLock);
   272         mReaderIsAliveCondition.broadcast();
   274         if (count) {
   275             processEventsLocked(mEventBuffer, count);
   276         }
   278         if (mNextTimeout != LLONG_MAX) {
   279             nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
   280             if (now >= mNextTimeout) {
   281 #if DEBUG_RAW_EVENTS
   282                 ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
   283 #endif
   284                 mNextTimeout = LLONG_MAX;
   285                 timeoutExpiredLocked(now);
   286             }
   287         }
   289         if (oldGeneration != mGeneration) {
   290             inputDevicesChanged = true;
   291             getInputDevicesLocked(inputDevices);
   292         }
   293     } // release lock
   295     // Send out a message that the describes the changed input devices.
   296     if (inputDevicesChanged) {
   297         mPolicy->notifyInputDevicesChanged(inputDevices);
   298     }
   300     // Flush queued events out to the listener.
   301     // This must happen outside of the lock because the listener could potentially call
   302     // back into the InputReader's methods, such as getScanCodeState, or become blocked
   303     // on another thread similarly waiting to acquire the InputReader lock thereby
   304     // resulting in a deadlock.  This situation is actually quite plausible because the
   305     // listener is actually the input dispatcher, which calls into the window manager,
   306     // which occasionally calls into the input reader.
   307     mQueuedListener->flush();
   308 }
   310 void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
   311     for (const RawEvent* rawEvent = rawEvents; count;) {
   312         int32_t type = rawEvent->type;
   313         size_t batchSize = 1;
   314         if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
   315             int32_t deviceId = rawEvent->deviceId;
   316             while (batchSize < count) {
   317                 if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
   318                         || rawEvent[batchSize].deviceId != deviceId) {
   319                     break;
   320                 }
   321                 batchSize += 1;
   322             }
   323 #if DEBUG_RAW_EVENTS
   324             ALOGD("BatchSize: %d Count: %d", batchSize, count);
   325 #endif
   326             processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
   327         } else {
   328             switch (rawEvent->type) {
   329             case EventHubInterface::DEVICE_ADDED:
   330                 addDeviceLocked(rawEvent->when, rawEvent->deviceId);
   331                 break;
   332             case EventHubInterface::DEVICE_REMOVED:
   333                 removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
   334                 break;
   335             case EventHubInterface::FINISHED_DEVICE_SCAN:
   336                 handleConfigurationChangedLocked(rawEvent->when);
   337                 break;
   338             default:
   339                 ALOG_ASSERT(false); // can't happen
   340                 break;
   341             }
   342         }
   343         count -= batchSize;
   344         rawEvent += batchSize;
   345     }
   346 }
   348 void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
   349     ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
   350     if (deviceIndex >= 0) {
   351         ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
   352         return;
   353     }
   355     InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
   356     uint32_t classes = mEventHub->getDeviceClasses(deviceId);
   358     InputDevice* device = createDeviceLocked(deviceId, identifier, classes);
   359     device->configure(when, &mConfig, 0);
   360     device->reset(when);
   362     if (device->isIgnored()) {
   363         ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
   364                 identifier.name.string());
   365     } else {
   366         ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
   367                 identifier.name.string(), device->getSources());
   368     }
   370     mDevices.add(deviceId, device);
   371     bumpGenerationLocked();
   372 }
   374 void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
   375     InputDevice* device = NULL;
   376     ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
   377     if (deviceIndex < 0) {
   378         ALOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
   379         return;
   380     }
   382     device = mDevices.valueAt(deviceIndex);
   383     mDevices.removeItemsAt(deviceIndex, 1);
   384     bumpGenerationLocked();
   386     if (device->isIgnored()) {
   387         ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
   388                 device->getId(), device->getName().string());
   389     } else {
   390         ALOGI("Device removed: id=%d, name='%s', sources=0x%08x",
   391                 device->getId(), device->getName().string(), device->getSources());
   392     }
   394     device->reset(when);
   395     delete device;
   396 }
   398 InputDevice* InputReader::createDeviceLocked(int32_t deviceId,
   399         const InputDeviceIdentifier& identifier, uint32_t classes) {
   400     InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
   401             identifier, classes);
   403     // External devices.
   404     if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
   405         device->setExternal(true);
   406     }
   408     // Switch-like devices.
   409     if (classes & INPUT_DEVICE_CLASS_SWITCH) {
   410         device->addMapper(new SwitchInputMapper(device));
   411     }
   413     // Vibrator-like devices.
   414     if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
   415         device->addMapper(new VibratorInputMapper(device));
   416     }
   418     // Keyboard-like devices.
   419     uint32_t keyboardSource = 0;
   420     int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
   421     if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
   422         keyboardSource |= AINPUT_SOURCE_KEYBOARD;
   423     }
   424     if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
   425         keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
   426     }
   427     if (classes & INPUT_DEVICE_CLASS_DPAD) {
   428         keyboardSource |= AINPUT_SOURCE_DPAD;
   429     }
   430     if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
   431         keyboardSource |= AINPUT_SOURCE_GAMEPAD;
   432     }
   434     if (keyboardSource != 0) {
   435         device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
   436     }
   438     // Cursor-like devices.
   439     if (classes & INPUT_DEVICE_CLASS_CURSOR) {
   440         device->addMapper(new CursorInputMapper(device));
   441     }
   443     // Touchscreens and touchpad devices.
   444     if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
   445         device->addMapper(new MultiTouchInputMapper(device));
   446     } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
   447         device->addMapper(new SingleTouchInputMapper(device));
   448     }
   450     // Joystick-like devices.
   451     if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
   452         device->addMapper(new JoystickInputMapper(device));
   453     }
   455     return device;
   456 }
   458 void InputReader::processEventsForDeviceLocked(int32_t deviceId,
   459         const RawEvent* rawEvents, size_t count) {
   460     ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
   461     if (deviceIndex < 0) {
   462         ALOGW("Discarding event for unknown deviceId %d.", deviceId);
   463         return;
   464     }
   466     InputDevice* device = mDevices.valueAt(deviceIndex);
   467     if (device->isIgnored()) {
   468         //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
   469         return;
   470     }
   472     device->process(rawEvents, count);
   473 }
   475 void InputReader::timeoutExpiredLocked(nsecs_t when) {
   476     for (size_t i = 0; i < mDevices.size(); i++) {
   477         InputDevice* device = mDevices.valueAt(i);
   478         if (!device->isIgnored()) {
   479             device->timeoutExpired(when);
   480         }
   481     }
   482 }
   484 void InputReader::handleConfigurationChangedLocked(nsecs_t when) {
   485     // Reset global meta state because it depends on the list of all configured devices.
   486     updateGlobalMetaStateLocked();
   488     // Enqueue configuration changed.
   489     NotifyConfigurationChangedArgs args(when);
   490     mQueuedListener->notifyConfigurationChanged(&args);
   491 }
   493 void InputReader::refreshConfigurationLocked(uint32_t changes) {
   494     mPolicy->getReaderConfiguration(&mConfig);
   495     mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
   497     if (changes) {
   498         ALOGI("Reconfiguring input devices.  changes=0x%08x", changes);
   499         nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
   501         if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
   502             mEventHub->requestReopenDevices();
   503         } else {
   504             for (size_t i = 0; i < mDevices.size(); i++) {
   505                 InputDevice* device = mDevices.valueAt(i);
   506                 device->configure(now, &mConfig, changes);
   507             }
   508         }
   509     }
   510 }
   512 void InputReader::updateGlobalMetaStateLocked() {
   513     mGlobalMetaState = 0;
   515     for (size_t i = 0; i < mDevices.size(); i++) {
   516         InputDevice* device = mDevices.valueAt(i);
   517         mGlobalMetaState |= device->getMetaState();
   518     }
   519 }
   521 int32_t InputReader::getGlobalMetaStateLocked() {
   522     return mGlobalMetaState;
   523 }
   525 void InputReader::disableVirtualKeysUntilLocked(nsecs_t time) {
   526     mDisableVirtualKeysTimeout = time;
   527 }
   529 bool InputReader::shouldDropVirtualKeyLocked(nsecs_t now,
   530         InputDevice* device, int32_t keyCode, int32_t scanCode) {
   531     if (now < mDisableVirtualKeysTimeout) {
   532         ALOGI("Dropping virtual key from device %s because virtual keys are "
   533                 "temporarily disabled for the next %0.3fms.  keyCode=%d, scanCode=%d",
   534                 device->getName().string(),
   535                 (mDisableVirtualKeysTimeout - now) * 0.000001,
   536                 keyCode, scanCode);
   537         return true;
   538     } else {
   539         return false;
   540     }
   541 }
   543 void InputReader::fadePointerLocked() {
   544     for (size_t i = 0; i < mDevices.size(); i++) {
   545         InputDevice* device = mDevices.valueAt(i);
   546         device->fadePointer();
   547     }
   548 }
   550 void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) {
   551     if (when < mNextTimeout) {
   552         mNextTimeout = when;
   553         mEventHub->wake();
   554     }
   555 }
   557 int32_t InputReader::bumpGenerationLocked() {
   558     return ++mGeneration;
   559 }
   561 void InputReader::getInputDevices(Vector<InputDeviceInfo>& outInputDevices) {
   562     AutoMutex _l(mLock);
   563     getInputDevicesLocked(outInputDevices);
   564 }
   566 void InputReader::getInputDevicesLocked(Vector<InputDeviceInfo>& outInputDevices) {
   567     outInputDevices.clear();
   569     size_t numDevices = mDevices.size();
   570     for (size_t i = 0; i < numDevices; i++) {
   571         InputDevice* device = mDevices.valueAt(i);
   572         if (!device->isIgnored()) {
   573             outInputDevices.push();
   574             device->getDeviceInfo(&outInputDevices.editTop());
   575         }
   576     }
   577 }
   579 int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
   580         int32_t keyCode) {
   581     AutoMutex _l(mLock);
   583     return getStateLocked(deviceId, sourceMask, keyCode, &InputDevice::getKeyCodeState);
   584 }
   586 int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
   587         int32_t scanCode) {
   588     AutoMutex _l(mLock);
   590     return getStateLocked(deviceId, sourceMask, scanCode, &InputDevice::getScanCodeState);
   591 }
   593 int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
   594     AutoMutex _l(mLock);
   596     return getStateLocked(deviceId, sourceMask, switchCode, &InputDevice::getSwitchState);
   597 }
   599 int32_t InputReader::getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
   600         GetStateFunc getStateFunc) {
   601     int32_t result = AKEY_STATE_UNKNOWN;
   602     if (deviceId >= 0) {
   603         ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
   604         if (deviceIndex >= 0) {
   605             InputDevice* device = mDevices.valueAt(deviceIndex);
   606             if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
   607                 result = (device->*getStateFunc)(sourceMask, code);
   608             }
   609         }
   610     } else {
   611         size_t numDevices = mDevices.size();
   612         for (size_t i = 0; i < numDevices; i++) {
   613             InputDevice* device = mDevices.valueAt(i);
   614             if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
   615                 // If any device reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
   616                 // value.  Otherwise, return AKEY_STATE_UP as long as one device reports it.
   617                 int32_t currentResult = (device->*getStateFunc)(sourceMask, code);
   618                 if (currentResult >= AKEY_STATE_DOWN) {
   619                     return currentResult;
   620                 } else if (currentResult == AKEY_STATE_UP) {
   621                     result = currentResult;
   622                 }
   623             }
   624         }
   625     }
   626     return result;
   627 }
   629 bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
   630         size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
   631     AutoMutex _l(mLock);
   633     memset(outFlags, 0, numCodes);
   634     return markSupportedKeyCodesLocked(deviceId, sourceMask, numCodes, keyCodes, outFlags);
   635 }
   637 bool InputReader::markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask,
   638         size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
   639     bool result = false;
   640     if (deviceId >= 0) {
   641         ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
   642         if (deviceIndex >= 0) {
   643             InputDevice* device = mDevices.valueAt(deviceIndex);
   644             if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
   645                 result = device->markSupportedKeyCodes(sourceMask,
   646                         numCodes, keyCodes, outFlags);
   647             }
   648         }
   649     } else {
   650         size_t numDevices = mDevices.size();
   651         for (size_t i = 0; i < numDevices; i++) {
   652             InputDevice* device = mDevices.valueAt(i);
   653             if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
   654                 result |= device->markSupportedKeyCodes(sourceMask,
   655                         numCodes, keyCodes, outFlags);
   656             }
   657         }
   658     }
   659     return result;
   660 }
   662 void InputReader::requestRefreshConfiguration(uint32_t changes) {
   663     AutoMutex _l(mLock);
   665     if (changes) {
   666         bool needWake = !mConfigurationChangesToRefresh;
   667         mConfigurationChangesToRefresh |= changes;
   669         if (needWake) {
   670             mEventHub->wake();
   671         }
   672     }
   673 }
   675 void InputReader::vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
   676         ssize_t repeat, int32_t token) {
   677     AutoMutex _l(mLock);
   679     ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
   680     if (deviceIndex >= 0) {
   681         InputDevice* device = mDevices.valueAt(deviceIndex);
   682         device->vibrate(pattern, patternSize, repeat, token);
   683     }
   684 }
   686 void InputReader::cancelVibrate(int32_t deviceId, int32_t token) {
   687     AutoMutex _l(mLock);
   689     ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
   690     if (deviceIndex >= 0) {
   691         InputDevice* device = mDevices.valueAt(deviceIndex);
   692         device->cancelVibrate(token);
   693     }
   694 }
   696 void InputReader::dump(String8& dump) {
   697     AutoMutex _l(mLock);
   699     mEventHub->dump(dump);
   700     dump.append("\n");
   702     dump.append("Input Reader State:\n");
   704     for (size_t i = 0; i < mDevices.size(); i++) {
   705         mDevices.valueAt(i)->dump(dump);
   706     }
   708     dump.append(INDENT "Configuration:\n");
   709     dump.append(INDENT2 "ExcludedDeviceNames: [");
   710     for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
   711         if (i != 0) {
   712             dump.append(", ");
   713         }
   714         dump.append(mConfig.excludedDeviceNames.itemAt(i).string());
   715     }
   716     dump.append("]\n");
   717     dump.appendFormat(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
   718             mConfig.virtualKeyQuietTime * 0.000001f);
   720     dump.appendFormat(INDENT2 "PointerVelocityControlParameters: "
   721             "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
   722             mConfig.pointerVelocityControlParameters.scale,
   723             mConfig.pointerVelocityControlParameters.lowThreshold,
   724             mConfig.pointerVelocityControlParameters.highThreshold,
   725             mConfig.pointerVelocityControlParameters.acceleration);
   727     dump.appendFormat(INDENT2 "WheelVelocityControlParameters: "
   728             "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
   729             mConfig.wheelVelocityControlParameters.scale,
   730             mConfig.wheelVelocityControlParameters.lowThreshold,
   731             mConfig.wheelVelocityControlParameters.highThreshold,
   732             mConfig.wheelVelocityControlParameters.acceleration);
   734     dump.appendFormat(INDENT2 "PointerGesture:\n");
   735     dump.appendFormat(INDENT3 "Enabled: %s\n",
   736             toString(mConfig.pointerGesturesEnabled));
   737     dump.appendFormat(INDENT3 "QuietInterval: %0.1fms\n",
   738             mConfig.pointerGestureQuietInterval * 0.000001f);
   739     dump.appendFormat(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
   740             mConfig.pointerGestureDragMinSwitchSpeed);
   741     dump.appendFormat(INDENT3 "TapInterval: %0.1fms\n",
   742             mConfig.pointerGestureTapInterval * 0.000001f);
   743     dump.appendFormat(INDENT3 "TapDragInterval: %0.1fms\n",
   744             mConfig.pointerGestureTapDragInterval * 0.000001f);
   745     dump.appendFormat(INDENT3 "TapSlop: %0.1fpx\n",
   746             mConfig.pointerGestureTapSlop);
   747     dump.appendFormat(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
   748             mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
   749     dump.appendFormat(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
   750             mConfig.pointerGestureMultitouchMinDistance);
   751     dump.appendFormat(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
   752             mConfig.pointerGestureSwipeTransitionAngleCosine);
   753     dump.appendFormat(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
   754             mConfig.pointerGestureSwipeMaxWidthRatio);
   755     dump.appendFormat(INDENT3 "MovementSpeedRatio: %0.1f\n",
   756             mConfig.pointerGestureMovementSpeedRatio);
   757     dump.appendFormat(INDENT3 "ZoomSpeedRatio: %0.1f\n",
   758             mConfig.pointerGestureZoomSpeedRatio);
   759 }
   761 void InputReader::monitor() {
   762     // Acquire and release the lock to ensure that the reader has not deadlocked.
   763     mLock.lock();
   764     mEventHub->wake();
   765     mReaderIsAliveCondition.wait(mLock);
   766     mLock.unlock();
   768     // Check the EventHub
   769     mEventHub->monitor();
   770 }
   773 // --- InputReader::ContextImpl ---
   775 InputReader::ContextImpl::ContextImpl(InputReader* reader) :
   776         mReader(reader) {
   777 }
   779 void InputReader::ContextImpl::updateGlobalMetaState() {
   780     // lock is already held by the input loop
   781     mReader->updateGlobalMetaStateLocked();
   782 }
   784 int32_t InputReader::ContextImpl::getGlobalMetaState() {
   785     // lock is already held by the input loop
   786     return mReader->getGlobalMetaStateLocked();
   787 }
   789 void InputReader::ContextImpl::disableVirtualKeysUntil(nsecs_t time) {
   790     // lock is already held by the input loop
   791     mReader->disableVirtualKeysUntilLocked(time);
   792 }
   794 bool InputReader::ContextImpl::shouldDropVirtualKey(nsecs_t now,
   795         InputDevice* device, int32_t keyCode, int32_t scanCode) {
   796     // lock is already held by the input loop
   797     return mReader->shouldDropVirtualKeyLocked(now, device, keyCode, scanCode);
   798 }
   800 void InputReader::ContextImpl::fadePointer() {
   801     // lock is already held by the input loop
   802     mReader->fadePointerLocked();
   803 }
   805 void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) {
   806     // lock is already held by the input loop
   807     mReader->requestTimeoutAtTimeLocked(when);
   808 }
   810 int32_t InputReader::ContextImpl::bumpGeneration() {
   811     // lock is already held by the input loop
   812     return mReader->bumpGenerationLocked();
   813 }
   815 InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() {
   816     return mReader->mPolicy.get();
   817 }
   819 InputListenerInterface* InputReader::ContextImpl::getListener() {
   820     return mReader->mQueuedListener.get();
   821 }
   823 EventHubInterface* InputReader::ContextImpl::getEventHub() {
   824     return mReader->mEventHub.get();
   825 }
   828 // --- InputReaderThread ---
   830 InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
   831         Thread(/*canCallJava*/ true), mReader(reader) {
   832 }
   834 InputReaderThread::~InputReaderThread() {
   835 }
   837 bool InputReaderThread::threadLoop() {
   838     mReader->loopOnce();
   839     return true;
   840 }
   843 // --- InputDevice ---
   845 InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
   846         const InputDeviceIdentifier& identifier, uint32_t classes) :
   847         mContext(context), mId(id), mGeneration(generation),
   848         mIdentifier(identifier), mClasses(classes),
   849         mSources(0), mIsExternal(false), mDropUntilNextSync(false) {
   850 }
   852 InputDevice::~InputDevice() {
   853     size_t numMappers = mMappers.size();
   854     for (size_t i = 0; i < numMappers; i++) {
   855         delete mMappers[i];
   856     }
   857     mMappers.clear();
   858 }
   860 void InputDevice::dump(String8& dump) {
   861     InputDeviceInfo deviceInfo;
   862     getDeviceInfo(& deviceInfo);
   864     dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
   865             deviceInfo.getDisplayName().string());
   866     dump.appendFormat(INDENT2 "Generation: %d\n", mGeneration);
   867     dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
   868     dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
   869     dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
   871     const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
   872     if (!ranges.isEmpty()) {
   873         dump.append(INDENT2 "Motion Ranges:\n");
   874         for (size_t i = 0; i < ranges.size(); i++) {
   875             const InputDeviceInfo::MotionRange& range = ranges.itemAt(i);
   876             const char* label = getAxisLabel(range.axis);
   877             char name[32];
   878             if (label) {
   879                 strncpy(name, label, sizeof(name));
   880                 name[sizeof(name) - 1] = '\0';
   881             } else {
   882                 snprintf(name, sizeof(name), "%d", range.axis);
   883             }
   884             dump.appendFormat(INDENT3 "%s: source=0x%08x, "
   885                     "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, resolution=%0.3f\n",
   886                     name, range.source, range.min, range.max, range.flat, range.fuzz,
   887                     range.resolution);
   888         }
   889     }
   891     size_t numMappers = mMappers.size();
   892     for (size_t i = 0; i < numMappers; i++) {
   893         InputMapper* mapper = mMappers[i];
   894         mapper->dump(dump);
   895     }
   896 }
   898 void InputDevice::addMapper(InputMapper* mapper) {
   899     mMappers.add(mapper);
   900 }
   902 void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) {
   903     mSources = 0;
   905     if (!isIgnored()) {
   906         if (!changes) { // first time only
   907             mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
   908         }
   910         if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {
   911             if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
   912                 sp<KeyCharacterMap> keyboardLayout =
   913                         mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier.descriptor);
   914                 if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) {
   915                     bumpGeneration();
   916                 }
   917             }
   918         }
   920         if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
   921             if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
   922                 String8 alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
   923                 if (mAlias != alias) {
   924                     mAlias = alias;
   925                     bumpGeneration();
   926                 }
   927             }
   928         }
   930         size_t numMappers = mMappers.size();
   931         for (size_t i = 0; i < numMappers; i++) {
   932             InputMapper* mapper = mMappers[i];
   933             mapper->configure(when, config, changes);
   934             mSources |= mapper->getSources();
   935         }
   936     }
   937 }
   939 void InputDevice::reset(nsecs_t when) {
   940     size_t numMappers = mMappers.size();
   941     for (size_t i = 0; i < numMappers; i++) {
   942         InputMapper* mapper = mMappers[i];
   943         mapper->reset(when);
   944     }
   946     mContext->updateGlobalMetaState();
   948     notifyReset(when);
   949 }
   951 void InputDevice::process(const RawEvent* rawEvents, size_t count) {
   952     // Process all of the events in order for each mapper.
   953     // We cannot simply ask each mapper to process them in bulk because mappers may
   954     // have side-effects that must be interleaved.  For example, joystick movement events and
   955     // gamepad button presses are handled by different mappers but they should be dispatched
   956     // in the order received.
   957     size_t numMappers = mMappers.size();
   958     for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
   959 #if DEBUG_RAW_EVENTS
   960         ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%lld",
   961                 rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,
   962                 rawEvent->when);
   963 #endif
   965         if (mDropUntilNextSync) {
   966             if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
   967                 mDropUntilNextSync = false;
   968 #if DEBUG_RAW_EVENTS
   969                 ALOGD("Recovered from input event buffer overrun.");
   970 #endif
   971             } else {
   972 #if DEBUG_RAW_EVENTS
   973                 ALOGD("Dropped input event while waiting for next input sync.");
   974 #endif
   975             }
   976         } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
   977             ALOGI("Detected input event buffer overrun for device %s.", getName().string());
   978             mDropUntilNextSync = true;
   979             reset(rawEvent->when);
   980         } else {
   981             for (size_t i = 0; i < numMappers; i++) {
   982                 InputMapper* mapper = mMappers[i];
   983                 mapper->process(rawEvent);
   984             }
   985         }
   986     }
   987 }
   989 void InputDevice::timeoutExpired(nsecs_t when) {
   990     size_t numMappers = mMappers.size();
   991     for (size_t i = 0; i < numMappers; i++) {
   992         InputMapper* mapper = mMappers[i];
   993         mapper->timeoutExpired(when);
   994     }
   995 }
   997 void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
   998     outDeviceInfo->initialize(mId, mGeneration, mIdentifier, mAlias, mIsExternal);
  1000     size_t numMappers = mMappers.size();
  1001     for (size_t i = 0; i < numMappers; i++) {
  1002         InputMapper* mapper = mMappers[i];
  1003         mapper->populateDeviceInfo(outDeviceInfo);
  1007 int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
  1008     return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
  1011 int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
  1012     return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
  1015 int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
  1016     return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
  1019 int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
  1020     int32_t result = AKEY_STATE_UNKNOWN;
  1021     size_t numMappers = mMappers.size();
  1022     for (size_t i = 0; i < numMappers; i++) {
  1023         InputMapper* mapper = mMappers[i];
  1024         if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
  1025             // If any mapper reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
  1026             // value.  Otherwise, return AKEY_STATE_UP as long as one mapper reports it.
  1027             int32_t currentResult = (mapper->*getStateFunc)(sourceMask, code);
  1028             if (currentResult >= AKEY_STATE_DOWN) {
  1029                 return currentResult;
  1030             } else if (currentResult == AKEY_STATE_UP) {
  1031                 result = currentResult;
  1035     return result;
  1038 bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
  1039         const int32_t* keyCodes, uint8_t* outFlags) {
  1040     bool result = false;
  1041     size_t numMappers = mMappers.size();
  1042     for (size_t i = 0; i < numMappers; i++) {
  1043         InputMapper* mapper = mMappers[i];
  1044         if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
  1045             result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
  1048     return result;
  1051 void InputDevice::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
  1052         int32_t token) {
  1053     size_t numMappers = mMappers.size();
  1054     for (size_t i = 0; i < numMappers; i++) {
  1055         InputMapper* mapper = mMappers[i];
  1056         mapper->vibrate(pattern, patternSize, repeat, token);
  1060 void InputDevice::cancelVibrate(int32_t token) {
  1061     size_t numMappers = mMappers.size();
  1062     for (size_t i = 0; i < numMappers; i++) {
  1063         InputMapper* mapper = mMappers[i];
  1064         mapper->cancelVibrate(token);
  1068 int32_t InputDevice::getMetaState() {
  1069     int32_t result = 0;
  1070     size_t numMappers = mMappers.size();
  1071     for (size_t i = 0; i < numMappers; i++) {
  1072         InputMapper* mapper = mMappers[i];
  1073         result |= mapper->getMetaState();
  1075     return result;
  1078 void InputDevice::fadePointer() {
  1079     size_t numMappers = mMappers.size();
  1080     for (size_t i = 0; i < numMappers; i++) {
  1081         InputMapper* mapper = mMappers[i];
  1082         mapper->fadePointer();
  1086 void InputDevice::bumpGeneration() {
  1087     mGeneration = mContext->bumpGeneration();
  1090 void InputDevice::notifyReset(nsecs_t when) {
  1091     NotifyDeviceResetArgs args(when, mId);
  1092     mContext->getListener()->notifyDeviceReset(&args);
  1096 // --- CursorButtonAccumulator ---
  1098 CursorButtonAccumulator::CursorButtonAccumulator() {
  1099     clearButtons();
  1102 void CursorButtonAccumulator::reset(InputDevice* device) {
  1103     mBtnLeft = device->isKeyPressed(BTN_LEFT);
  1104     mBtnRight = device->isKeyPressed(BTN_RIGHT);
  1105     mBtnMiddle = device->isKeyPressed(BTN_MIDDLE);
  1106     mBtnBack = device->isKeyPressed(BTN_BACK);
  1107     mBtnSide = device->isKeyPressed(BTN_SIDE);
  1108     mBtnForward = device->isKeyPressed(BTN_FORWARD);
  1109     mBtnExtra = device->isKeyPressed(BTN_EXTRA);
  1110     mBtnTask = device->isKeyPressed(BTN_TASK);
  1113 void CursorButtonAccumulator::clearButtons() {
  1114     mBtnLeft = 0;
  1115     mBtnRight = 0;
  1116     mBtnMiddle = 0;
  1117     mBtnBack = 0;
  1118     mBtnSide = 0;
  1119     mBtnForward = 0;
  1120     mBtnExtra = 0;
  1121     mBtnTask = 0;
  1124 void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
  1125     if (rawEvent->type == EV_KEY) {
  1126         switch (rawEvent->code) {
  1127         case BTN_LEFT:
  1128             mBtnLeft = rawEvent->value;
  1129             break;
  1130         case BTN_RIGHT:
  1131             mBtnRight = rawEvent->value;
  1132             break;
  1133         case BTN_MIDDLE:
  1134             mBtnMiddle = rawEvent->value;
  1135             break;
  1136         case BTN_BACK:
  1137             mBtnBack = rawEvent->value;
  1138             break;
  1139         case BTN_SIDE:
  1140             mBtnSide = rawEvent->value;
  1141             break;
  1142         case BTN_FORWARD:
  1143             mBtnForward = rawEvent->value;
  1144             break;
  1145         case BTN_EXTRA:
  1146             mBtnExtra = rawEvent->value;
  1147             break;
  1148         case BTN_TASK:
  1149             mBtnTask = rawEvent->value;
  1150             break;
  1155 uint32_t CursorButtonAccumulator::getButtonState() const {
  1156     uint32_t result = 0;
  1157     if (mBtnLeft) {
  1158         result |= AMOTION_EVENT_BUTTON_PRIMARY;
  1160     if (mBtnRight) {
  1161         result |= AMOTION_EVENT_BUTTON_SECONDARY;
  1163     if (mBtnMiddle) {
  1164         result |= AMOTION_EVENT_BUTTON_TERTIARY;
  1166     if (mBtnBack || mBtnSide) {
  1167         result |= AMOTION_EVENT_BUTTON_BACK;
  1169     if (mBtnForward || mBtnExtra) {
  1170         result |= AMOTION_EVENT_BUTTON_FORWARD;
  1172     return result;
  1176 // --- CursorMotionAccumulator ---
  1178 CursorMotionAccumulator::CursorMotionAccumulator() {
  1179     clearRelativeAxes();
  1182 void CursorMotionAccumulator::reset(InputDevice* device) {
  1183     clearRelativeAxes();
  1186 void CursorMotionAccumulator::clearRelativeAxes() {
  1187     mRelX = 0;
  1188     mRelY = 0;
  1191 void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
  1192     if (rawEvent->type == EV_REL) {
  1193         switch (rawEvent->code) {
  1194         case REL_X:
  1195             mRelX = rawEvent->value;
  1196             break;
  1197         case REL_Y:
  1198             mRelY = rawEvent->value;
  1199             break;
  1204 void CursorMotionAccumulator::finishSync() {
  1205     clearRelativeAxes();
  1209 // --- CursorScrollAccumulator ---
  1211 CursorScrollAccumulator::CursorScrollAccumulator() :
  1212         mHaveRelWheel(false), mHaveRelHWheel(false) {
  1213     clearRelativeAxes();
  1216 void CursorScrollAccumulator::configure(InputDevice* device) {
  1217     mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
  1218     mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
  1221 void CursorScrollAccumulator::reset(InputDevice* device) {
  1222     clearRelativeAxes();
  1225 void CursorScrollAccumulator::clearRelativeAxes() {
  1226     mRelWheel = 0;
  1227     mRelHWheel = 0;
  1230 void CursorScrollAccumulator::process(const RawEvent* rawEvent) {
  1231     if (rawEvent->type == EV_REL) {
  1232         switch (rawEvent->code) {
  1233         case REL_WHEEL:
  1234             mRelWheel = rawEvent->value;
  1235             break;
  1236         case REL_HWHEEL:
  1237             mRelHWheel = rawEvent->value;
  1238             break;
  1243 void CursorScrollAccumulator::finishSync() {
  1244     clearRelativeAxes();
  1248 // --- TouchButtonAccumulator ---
  1250 TouchButtonAccumulator::TouchButtonAccumulator() :
  1251         mHaveBtnTouch(false), mHaveStylus(false) {
  1252     clearButtons();
  1255 void TouchButtonAccumulator::configure(InputDevice* device) {
  1256     mHaveBtnTouch = device->hasKey(BTN_TOUCH);
  1257     mHaveStylus = device->hasKey(BTN_TOOL_PEN)
  1258             || device->hasKey(BTN_TOOL_RUBBER)
  1259             || device->hasKey(BTN_TOOL_BRUSH)
  1260             || device->hasKey(BTN_TOOL_PENCIL)
  1261             || device->hasKey(BTN_TOOL_AIRBRUSH);
  1264 void TouchButtonAccumulator::reset(InputDevice* device) {
  1265     mBtnTouch = device->isKeyPressed(BTN_TOUCH);
  1266     mBtnStylus = device->isKeyPressed(BTN_STYLUS);
  1267     mBtnStylus2 = device->isKeyPressed(BTN_STYLUS);
  1268     mBtnToolFinger = device->isKeyPressed(BTN_TOOL_FINGER);
  1269     mBtnToolPen = device->isKeyPressed(BTN_TOOL_PEN);
  1270     mBtnToolRubber = device->isKeyPressed(BTN_TOOL_RUBBER);
  1271     mBtnToolBrush = device->isKeyPressed(BTN_TOOL_BRUSH);
  1272     mBtnToolPencil = device->isKeyPressed(BTN_TOOL_PENCIL);
  1273     mBtnToolAirbrush = device->isKeyPressed(BTN_TOOL_AIRBRUSH);
  1274     mBtnToolMouse = device->isKeyPressed(BTN_TOOL_MOUSE);
  1275     mBtnToolLens = device->isKeyPressed(BTN_TOOL_LENS);
  1276     mBtnToolDoubleTap = device->isKeyPressed(BTN_TOOL_DOUBLETAP);
  1277     mBtnToolTripleTap = device->isKeyPressed(BTN_TOOL_TRIPLETAP);
  1278     mBtnToolQuadTap = device->isKeyPressed(BTN_TOOL_QUADTAP);
  1281 void TouchButtonAccumulator::clearButtons() {
  1282     mBtnTouch = 0;
  1283     mBtnStylus = 0;
  1284     mBtnStylus2 = 0;
  1285     mBtnToolFinger = 0;
  1286     mBtnToolPen = 0;
  1287     mBtnToolRubber = 0;
  1288     mBtnToolBrush = 0;
  1289     mBtnToolPencil = 0;
  1290     mBtnToolAirbrush = 0;
  1291     mBtnToolMouse = 0;
  1292     mBtnToolLens = 0;
  1293     mBtnToolDoubleTap = 0;
  1294     mBtnToolTripleTap = 0;
  1295     mBtnToolQuadTap = 0;
  1298 void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
  1299     if (rawEvent->type == EV_KEY) {
  1300         switch (rawEvent->code) {
  1301         case BTN_TOUCH:
  1302             mBtnTouch = rawEvent->value;
  1303             break;
  1304         case BTN_STYLUS:
  1305             mBtnStylus = rawEvent->value;
  1306             break;
  1307         case BTN_STYLUS2:
  1308             mBtnStylus2 = rawEvent->value;
  1309             break;
  1310         case BTN_TOOL_FINGER:
  1311             mBtnToolFinger = rawEvent->value;
  1312             break;
  1313         case BTN_TOOL_PEN:
  1314             mBtnToolPen = rawEvent->value;
  1315             break;
  1316         case BTN_TOOL_RUBBER:
  1317             mBtnToolRubber = rawEvent->value;
  1318             break;
  1319         case BTN_TOOL_BRUSH:
  1320             mBtnToolBrush = rawEvent->value;
  1321             break;
  1322         case BTN_TOOL_PENCIL:
  1323             mBtnToolPencil = rawEvent->value;
  1324             break;
  1325         case BTN_TOOL_AIRBRUSH:
  1326             mBtnToolAirbrush = rawEvent->value;
  1327             break;
  1328         case BTN_TOOL_MOUSE:
  1329             mBtnToolMouse = rawEvent->value;
  1330             break;
  1331         case BTN_TOOL_LENS:
  1332             mBtnToolLens = rawEvent->value;
  1333             break;
  1334         case BTN_TOOL_DOUBLETAP:
  1335             mBtnToolDoubleTap = rawEvent->value;
  1336             break;
  1337         case BTN_TOOL_TRIPLETAP:
  1338             mBtnToolTripleTap = rawEvent->value;
  1339             break;
  1340         case BTN_TOOL_QUADTAP:
  1341             mBtnToolQuadTap = rawEvent->value;
  1342             break;
  1347 uint32_t TouchButtonAccumulator::getButtonState() const {
  1348     uint32_t result = 0;
  1349     if (mBtnStylus) {
  1350         result |= AMOTION_EVENT_BUTTON_SECONDARY;
  1352     if (mBtnStylus2) {
  1353         result |= AMOTION_EVENT_BUTTON_TERTIARY;
  1355     return result;
  1358 int32_t TouchButtonAccumulator::getToolType() const {
  1359     if (mBtnToolMouse || mBtnToolLens) {
  1360         return AMOTION_EVENT_TOOL_TYPE_MOUSE;
  1362     if (mBtnToolRubber) {
  1363         return AMOTION_EVENT_TOOL_TYPE_ERASER;
  1365     if (mBtnToolPen || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush) {
  1366         return AMOTION_EVENT_TOOL_TYPE_STYLUS;
  1368     if (mBtnToolFinger || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap) {
  1369         return AMOTION_EVENT_TOOL_TYPE_FINGER;
  1371     return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
  1374 bool TouchButtonAccumulator::isToolActive() const {
  1375     return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber
  1376             || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush
  1377             || mBtnToolMouse || mBtnToolLens
  1378             || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap;
  1381 bool TouchButtonAccumulator::isHovering() const {
  1382     return mHaveBtnTouch && !mBtnTouch;
  1385 bool TouchButtonAccumulator::hasStylus() const {
  1386     return mHaveStylus;
  1390 // --- RawPointerAxes ---
  1392 RawPointerAxes::RawPointerAxes() {
  1393     clear();
  1396 void RawPointerAxes::clear() {
  1397     x.clear();
  1398     y.clear();
  1399     pressure.clear();
  1400     touchMajor.clear();
  1401     touchMinor.clear();
  1402     toolMajor.clear();
  1403     toolMinor.clear();
  1404     orientation.clear();
  1405     distance.clear();
  1406     tiltX.clear();
  1407     tiltY.clear();
  1408     trackingId.clear();
  1409     slot.clear();
  1413 // --- RawPointerData ---
  1415 RawPointerData::RawPointerData() {
  1416     clear();
  1419 void RawPointerData::clear() {
  1420     pointerCount = 0;
  1421     clearIdBits();
  1424 void RawPointerData::copyFrom(const RawPointerData& other) {
  1425     pointerCount = other.pointerCount;
  1426     hoveringIdBits = other.hoveringIdBits;
  1427     touchingIdBits = other.touchingIdBits;
  1429     for (uint32_t i = 0; i < pointerCount; i++) {
  1430         pointers[i] = other.pointers[i];
  1432         int id = pointers[i].id;
  1433         idToIndex[id] = other.idToIndex[id];
  1437 void RawPointerData::getCentroidOfTouchingPointers(float* outX, float* outY) const {
  1438     float x = 0, y = 0;
  1439     uint32_t count = touchingIdBits.count();
  1440     if (count) {
  1441         for (BitSet32 idBits(touchingIdBits); !idBits.isEmpty(); ) {
  1442             uint32_t id = idBits.clearFirstMarkedBit();
  1443             const Pointer& pointer = pointerForId(id);
  1444             x += pointer.x;
  1445             y += pointer.y;
  1447         x /= count;
  1448         y /= count;
  1450     *outX = x;
  1451     *outY = y;
  1455 // --- CookedPointerData ---
  1457 CookedPointerData::CookedPointerData() {
  1458     clear();
  1461 void CookedPointerData::clear() {
  1462     pointerCount = 0;
  1463     hoveringIdBits.clear();
  1464     touchingIdBits.clear();
  1467 void CookedPointerData::copyFrom(const CookedPointerData& other) {
  1468     pointerCount = other.pointerCount;
  1469     hoveringIdBits = other.hoveringIdBits;
  1470     touchingIdBits = other.touchingIdBits;
  1472     for (uint32_t i = 0; i < pointerCount; i++) {
  1473         pointerProperties[i].copyFrom(other.pointerProperties[i]);
  1474         pointerCoords[i].copyFrom(other.pointerCoords[i]);
  1476         int id = pointerProperties[i].id;
  1477         idToIndex[id] = other.idToIndex[id];
  1482 // --- SingleTouchMotionAccumulator ---
  1484 SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() {
  1485     clearAbsoluteAxes();
  1488 void SingleTouchMotionAccumulator::reset(InputDevice* device) {
  1489     mAbsX = device->getAbsoluteAxisValue(ABS_X);
  1490     mAbsY = device->getAbsoluteAxisValue(ABS_Y);
  1491     mAbsPressure = device->getAbsoluteAxisValue(ABS_PRESSURE);
  1492     mAbsToolWidth = device->getAbsoluteAxisValue(ABS_TOOL_WIDTH);
  1493     mAbsDistance = device->getAbsoluteAxisValue(ABS_DISTANCE);
  1494     mAbsTiltX = device->getAbsoluteAxisValue(ABS_TILT_X);
  1495     mAbsTiltY = device->getAbsoluteAxisValue(ABS_TILT_Y);
  1498 void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
  1499     mAbsX = 0;
  1500     mAbsY = 0;
  1501     mAbsPressure = 0;
  1502     mAbsToolWidth = 0;
  1503     mAbsDistance = 0;
  1504     mAbsTiltX = 0;
  1505     mAbsTiltY = 0;
  1508 void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
  1509     if (rawEvent->type == EV_ABS) {
  1510         switch (rawEvent->code) {
  1511         case ABS_X:
  1512             mAbsX = rawEvent->value;
  1513             break;
  1514         case ABS_Y:
  1515             mAbsY = rawEvent->value;
  1516             break;
  1517         case ABS_PRESSURE:
  1518             mAbsPressure = rawEvent->value;
  1519             break;
  1520         case ABS_TOOL_WIDTH:
  1521             mAbsToolWidth = rawEvent->value;
  1522             break;
  1523         case ABS_DISTANCE:
  1524             mAbsDistance = rawEvent->value;
  1525             break;
  1526         case ABS_TILT_X:
  1527             mAbsTiltX = rawEvent->value;
  1528             break;
  1529         case ABS_TILT_Y:
  1530             mAbsTiltY = rawEvent->value;
  1531             break;
  1537 // --- MultiTouchMotionAccumulator ---
  1539 MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() :
  1540         mCurrentSlot(-1), mSlots(NULL), mSlotCount(0), mUsingSlotsProtocol(false),
  1541         mHaveStylus(false) {
  1544 MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
  1545     delete[] mSlots;
  1548 void MultiTouchMotionAccumulator::configure(InputDevice* device,
  1549         size_t slotCount, bool usingSlotsProtocol) {
  1550     mSlotCount = slotCount;
  1551     mUsingSlotsProtocol = usingSlotsProtocol;
  1552     mHaveStylus = device->hasAbsoluteAxis(ABS_MT_TOOL_TYPE);
  1554     delete[] mSlots;
  1555     mSlots = new Slot[slotCount];
  1558 void MultiTouchMotionAccumulator::reset(InputDevice* device) {
  1559     // Unfortunately there is no way to read the initial contents of the slots.
  1560     // So when we reset the accumulator, we must assume they are all zeroes.
  1561     if (mUsingSlotsProtocol) {
  1562         // Query the driver for the current slot index and use it as the initial slot
  1563         // before we start reading events from the device.  It is possible that the
  1564         // current slot index will not be the same as it was when the first event was
  1565         // written into the evdev buffer, which means the input mapper could start
  1566         // out of sync with the initial state of the events in the evdev buffer.
  1567         // In the extremely unlikely case that this happens, the data from
  1568         // two slots will be confused until the next ABS_MT_SLOT event is received.
  1569         // This can cause the touch point to "jump", but at least there will be
  1570         // no stuck touches.
  1571         int32_t initialSlot;
  1572         status_t status = device->getEventHub()->getAbsoluteAxisValue(device->getId(),
  1573                 ABS_MT_SLOT, &initialSlot);
  1574         if (status) {
  1575             ALOGD("Could not retrieve current multitouch slot index.  status=%d", status);
  1576             initialSlot = -1;
  1578         clearSlots(initialSlot);
  1579     } else {
  1580         clearSlots(-1);
  1584 void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
  1585     if (mSlots) {
  1586         for (size_t i = 0; i < mSlotCount; i++) {
  1587             mSlots[i].clear();
  1590     mCurrentSlot = initialSlot;
  1593 void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
  1594     if (rawEvent->type == EV_ABS) {
  1595         bool newSlot = false;
  1596         if (mUsingSlotsProtocol) {
  1597             if (rawEvent->code == ABS_MT_SLOT) {
  1598                 mCurrentSlot = rawEvent->value;
  1599                 newSlot = true;
  1601         } else if (mCurrentSlot < 0) {
  1602             mCurrentSlot = 0;
  1605         if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
  1606 #if DEBUG_POINTERS
  1607             if (newSlot) {
  1608                 ALOGW("MultiTouch device emitted invalid slot index %d but it "
  1609                         "should be between 0 and %d; ignoring this slot.",
  1610                         mCurrentSlot, mSlotCount - 1);
  1612 #endif
  1613         } else {
  1614             Slot* slot = &mSlots[mCurrentSlot];
  1616             switch (rawEvent->code) {
  1617             case ABS_MT_POSITION_X:
  1618                 slot->mInUse = true;
  1619                 slot->mAbsMTPositionX = rawEvent->value;
  1620                 break;
  1621             case ABS_MT_POSITION_Y:
  1622                 slot->mInUse = true;
  1623                 slot->mAbsMTPositionY = rawEvent->value;
  1624                 break;
  1625             case ABS_MT_TOUCH_MAJOR:
  1626                 slot->mInUse = true;
  1627                 slot->mAbsMTTouchMajor = rawEvent->value;
  1628                 break;
  1629             case ABS_MT_TOUCH_MINOR:
  1630                 slot->mInUse = true;
  1631                 slot->mAbsMTTouchMinor = rawEvent->value;
  1632                 slot->mHaveAbsMTTouchMinor = true;
  1633                 break;
  1634             case ABS_MT_WIDTH_MAJOR:
  1635                 slot->mInUse = true;
  1636                 slot->mAbsMTWidthMajor = rawEvent->value;
  1637                 break;
  1638             case ABS_MT_WIDTH_MINOR:
  1639                 slot->mInUse = true;
  1640                 slot->mAbsMTWidthMinor = rawEvent->value;
  1641                 slot->mHaveAbsMTWidthMinor = true;
  1642                 break;
  1643             case ABS_MT_ORIENTATION:
  1644                 slot->mInUse = true;
  1645                 slot->mAbsMTOrientation = rawEvent->value;
  1646                 break;
  1647             case ABS_MT_TRACKING_ID:
  1648                 if (mUsingSlotsProtocol && rawEvent->value < 0) {
  1649                     // The slot is no longer in use but it retains its previous contents,
  1650                     // which may be reused for subsequent touches.
  1651                     slot->mInUse = false;
  1652                 } else {
  1653                     slot->mInUse = true;
  1654                     slot->mAbsMTTrackingId = rawEvent->value;
  1656                 break;
  1657             case ABS_MT_PRESSURE:
  1658                 slot->mInUse = true;
  1659                 slot->mAbsMTPressure = rawEvent->value;
  1660                 break;
  1661             case ABS_MT_DISTANCE:
  1662                 slot->mInUse = true;
  1663                 slot->mAbsMTDistance = rawEvent->value;
  1664                 break;
  1665             case ABS_MT_TOOL_TYPE:
  1666                 slot->mInUse = true;
  1667                 slot->mAbsMTToolType = rawEvent->value;
  1668                 slot->mHaveAbsMTToolType = true;
  1669                 break;
  1672     } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {
  1673         // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
  1674         mCurrentSlot += 1;
  1678 void MultiTouchMotionAccumulator::finishSync() {
  1679     if (!mUsingSlotsProtocol) {
  1680         clearSlots(-1);
  1684 bool MultiTouchMotionAccumulator::hasStylus() const {
  1685     return mHaveStylus;
  1689 // --- MultiTouchMotionAccumulator::Slot ---
  1691 MultiTouchMotionAccumulator::Slot::Slot() {
  1692     clear();
  1695 void MultiTouchMotionAccumulator::Slot::clear() {
  1696     mInUse = false;
  1697     mHaveAbsMTTouchMinor = false;
  1698     mHaveAbsMTWidthMinor = false;
  1699     mHaveAbsMTToolType = false;
  1700     mAbsMTPositionX = 0;
  1701     mAbsMTPositionY = 0;
  1702     mAbsMTTouchMajor = 0;
  1703     mAbsMTTouchMinor = 0;
  1704     mAbsMTWidthMajor = 0;
  1705     mAbsMTWidthMinor = 0;
  1706     mAbsMTOrientation = 0;
  1707     mAbsMTTrackingId = -1;
  1708     mAbsMTPressure = 0;
  1709     mAbsMTDistance = 0;
  1710     mAbsMTToolType = 0;
  1713 int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
  1714     if (mHaveAbsMTToolType) {
  1715         switch (mAbsMTToolType) {
  1716         case MT_TOOL_FINGER:
  1717             return AMOTION_EVENT_TOOL_TYPE_FINGER;
  1718         case MT_TOOL_PEN:
  1719             return AMOTION_EVENT_TOOL_TYPE_STYLUS;
  1722     return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
  1726 // --- InputMapper ---
  1728 InputMapper::InputMapper(InputDevice* device) :
  1729         mDevice(device), mContext(device->getContext()) {
  1732 InputMapper::~InputMapper() {
  1735 void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
  1736     info->addSource(getSources());
  1739 void InputMapper::dump(String8& dump) {
  1742 void InputMapper::configure(nsecs_t when,
  1743         const InputReaderConfiguration* config, uint32_t changes) {
  1746 void InputMapper::reset(nsecs_t when) {
  1749 void InputMapper::timeoutExpired(nsecs_t when) {
  1752 int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
  1753     return AKEY_STATE_UNKNOWN;
  1756 int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
  1757     return AKEY_STATE_UNKNOWN;
  1760 int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
  1761     return AKEY_STATE_UNKNOWN;
  1764 bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
  1765         const int32_t* keyCodes, uint8_t* outFlags) {
  1766     return false;
  1769 void InputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
  1770         int32_t token) {
  1773 void InputMapper::cancelVibrate(int32_t token) {
  1776 int32_t InputMapper::getMetaState() {
  1777     return 0;
  1780 void InputMapper::fadePointer() {
  1783 status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) {
  1784     return getEventHub()->getAbsoluteAxisInfo(getDeviceId(), axis, axisInfo);
  1787 void InputMapper::bumpGeneration() {
  1788     mDevice->bumpGeneration();
  1791 void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
  1792         const RawAbsoluteAxisInfo& axis, const char* name) {
  1793     if (axis.valid) {
  1794         dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d, resolution=%d\n",
  1795                 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz, axis.resolution);
  1796     } else {
  1797         dump.appendFormat(INDENT4 "%s: unknown range\n", name);
  1802 // --- SwitchInputMapper ---
  1804 SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
  1805         InputMapper(device), mUpdatedSwitchValues(0), mUpdatedSwitchMask(0) {
  1808 SwitchInputMapper::~SwitchInputMapper() {
  1811 uint32_t SwitchInputMapper::getSources() {
  1812     return AINPUT_SOURCE_SWITCH;
  1815 void SwitchInputMapper::process(const RawEvent* rawEvent) {
  1816     switch (rawEvent->type) {
  1817     case EV_SW:
  1818         processSwitch(rawEvent->code, rawEvent->value);
  1819         break;
  1821     case EV_SYN:
  1822         if (rawEvent->code == SYN_REPORT) {
  1823             sync(rawEvent->when);
  1828 void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
  1829     if (switchCode >= 0 && switchCode < 32) {
  1830         if (switchValue) {
  1831             mUpdatedSwitchValues |= 1 << switchCode;
  1833         mUpdatedSwitchMask |= 1 << switchCode;
  1837 void SwitchInputMapper::sync(nsecs_t when) {
  1838     if (mUpdatedSwitchMask) {
  1839         NotifySwitchArgs args(when, 0, mUpdatedSwitchValues, mUpdatedSwitchMask);
  1840         getListener()->notifySwitch(&args);
  1842         mUpdatedSwitchValues = 0;
  1843         mUpdatedSwitchMask = 0;
  1847 int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
  1848     return getEventHub()->getSwitchState(getDeviceId(), switchCode);
  1852 // --- VibratorInputMapper ---
  1854 VibratorInputMapper::VibratorInputMapper(InputDevice* device) :
  1855         InputMapper(device), mVibrating(false) {
  1858 VibratorInputMapper::~VibratorInputMapper() {
  1861 uint32_t VibratorInputMapper::getSources() {
  1862     return 0;
  1865 void VibratorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
  1866     InputMapper::populateDeviceInfo(info);
  1868     info->setVibrator(true);
  1871 void VibratorInputMapper::process(const RawEvent* rawEvent) {
  1872     // TODO: Handle FF_STATUS, although it does not seem to be widely supported.
  1875 void VibratorInputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
  1876         int32_t token) {
  1877 #if DEBUG_VIBRATOR
  1878     String8 patternStr;
  1879     for (size_t i = 0; i < patternSize; i++) {
  1880         if (i != 0) {
  1881             patternStr.append(", ");
  1883         patternStr.appendFormat("%lld", pattern[i]);
  1885     ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%ld, token=%d",
  1886             getDeviceId(), patternStr.string(), repeat, token);
  1887 #endif
  1889     mVibrating = true;
  1890     memcpy(mPattern, pattern, patternSize * sizeof(nsecs_t));
  1891     mPatternSize = patternSize;
  1892     mRepeat = repeat;
  1893     mToken = token;
  1894     mIndex = -1;
  1896     nextStep();
  1899 void VibratorInputMapper::cancelVibrate(int32_t token) {
  1900 #if DEBUG_VIBRATOR
  1901     ALOGD("cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token);
  1902 #endif
  1904     if (mVibrating && mToken == token) {
  1905         stopVibrating();
  1909 void VibratorInputMapper::timeoutExpired(nsecs_t when) {
  1910     if (mVibrating) {
  1911         if (when >= mNextStepTime) {
  1912             nextStep();
  1913         } else {
  1914             getContext()->requestTimeoutAtTime(mNextStepTime);
  1919 void VibratorInputMapper::nextStep() {
  1920     mIndex += 1;
  1921     if (size_t(mIndex) >= mPatternSize) {
  1922         if (mRepeat < 0) {
  1923             // We are done.
  1924             stopVibrating();
  1925             return;
  1927         mIndex = mRepeat;
  1930     bool vibratorOn = mIndex & 1;
  1931     nsecs_t duration = mPattern[mIndex];
  1932     if (vibratorOn) {
  1933 #if DEBUG_VIBRATOR
  1934         ALOGD("nextStep: sending vibrate deviceId=%d, duration=%lld",
  1935                 getDeviceId(), duration);
  1936 #endif
  1937         getEventHub()->vibrate(getDeviceId(), duration);
  1938     } else {
  1939 #if DEBUG_VIBRATOR
  1940         ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId());
  1941 #endif
  1942         getEventHub()->cancelVibrate(getDeviceId());
  1944     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
  1945     mNextStepTime = now + duration;
  1946     getContext()->requestTimeoutAtTime(mNextStepTime);
  1947 #if DEBUG_VIBRATOR
  1948     ALOGD("nextStep: scheduled timeout in %0.3fms", duration * 0.000001f);
  1949 #endif
  1952 void VibratorInputMapper::stopVibrating() {
  1953     mVibrating = false;
  1954 #if DEBUG_VIBRATOR
  1955     ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId());
  1956 #endif
  1957     getEventHub()->cancelVibrate(getDeviceId());
  1960 void VibratorInputMapper::dump(String8& dump) {
  1961     dump.append(INDENT2 "Vibrator Input Mapper:\n");
  1962     dump.appendFormat(INDENT3 "Vibrating: %s\n", toString(mVibrating));
  1966 // --- KeyboardInputMapper ---
  1968 KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
  1969         uint32_t source, int32_t keyboardType) :
  1970         InputMapper(device), mSource(source),
  1971         mKeyboardType(keyboardType) {
  1974 KeyboardInputMapper::~KeyboardInputMapper() {
  1977 uint32_t KeyboardInputMapper::getSources() {
  1978     return mSource;
  1981 void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
  1982     InputMapper::populateDeviceInfo(info);
  1984     info->setKeyboardType(mKeyboardType);
  1985     info->setKeyCharacterMap(getEventHub()->getKeyCharacterMap(getDeviceId()));
  1988 void KeyboardInputMapper::dump(String8& dump) {
  1989     dump.append(INDENT2 "Keyboard Input Mapper:\n");
  1990     dumpParameters(dump);
  1991     dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
  1992     dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
  1993     dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mKeyDowns.size());
  1994     dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mMetaState);
  1995     dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime);
  1999 void KeyboardInputMapper::configure(nsecs_t when,
  2000         const InputReaderConfiguration* config, uint32_t changes) {
  2001     InputMapper::configure(when, config, changes);
  2003     if (!changes) { // first time only
  2004         // Configure basic parameters.
  2005         configureParameters();
  2008     if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
  2009         if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
  2010             DisplayViewport v;
  2011             if (config->getDisplayInfo(false /*external*/, &v)) {
  2012                 mOrientation = v.orientation;
  2013             } else {
  2014                 mOrientation = DISPLAY_ORIENTATION_0;
  2016         } else {
  2017             mOrientation = DISPLAY_ORIENTATION_0;
  2022 void KeyboardInputMapper::configureParameters() {
  2023     mParameters.orientationAware = false;
  2024     getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
  2025             mParameters.orientationAware);
  2027     mParameters.hasAssociatedDisplay = false;
  2028     if (mParameters.orientationAware) {
  2029         mParameters.hasAssociatedDisplay = true;
  2033 void KeyboardInputMapper::dumpParameters(String8& dump) {
  2034     dump.append(INDENT3 "Parameters:\n");
  2035     dump.appendFormat(INDENT4 "HasAssociatedDisplay: %s\n",
  2036             toString(mParameters.hasAssociatedDisplay));
  2037     dump.appendFormat(INDENT4 "OrientationAware: %s\n",
  2038             toString(mParameters.orientationAware));
  2041 void KeyboardInputMapper::reset(nsecs_t when) {
  2042     mMetaState = AMETA_NONE;
  2043     mDownTime = 0;
  2044     mKeyDowns.clear();
  2045     mCurrentHidUsage = 0;
  2047     resetLedState();
  2049     InputMapper::reset(when);
  2052 void KeyboardInputMapper::process(const RawEvent* rawEvent) {
  2053     switch (rawEvent->type) {
  2054     case EV_KEY: {
  2055         int32_t scanCode = rawEvent->code;
  2056         int32_t usageCode = mCurrentHidUsage;
  2057         mCurrentHidUsage = 0;
  2059         if (isKeyboardOrGamepadKey(scanCode)) {
  2060             int32_t keyCode;
  2061             uint32_t flags;
  2062             if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) {
  2063                 keyCode = AKEYCODE_UNKNOWN;
  2064                 flags = 0;
  2066             processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
  2068         break;
  2070     case EV_MSC: {
  2071         if (rawEvent->code == MSC_SCAN) {
  2072             mCurrentHidUsage = rawEvent->value;
  2074         break;
  2076     case EV_SYN: {
  2077         if (rawEvent->code == SYN_REPORT) {
  2078             mCurrentHidUsage = 0;
  2084 bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
  2085     return scanCode < BTN_MOUSE
  2086         || scanCode >= KEY_OK
  2087         || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE)
  2088         || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
  2091 void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
  2092         int32_t scanCode, uint32_t policyFlags) {
  2094     if (down) {
  2095         // Rotate key codes according to orientation if needed.
  2096         if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
  2097             keyCode = rotateKeyCode(keyCode, mOrientation);
  2100         // Add key down.
  2101         ssize_t keyDownIndex = findKeyDown(scanCode);
  2102         if (keyDownIndex >= 0) {
  2103             // key repeat, be sure to use same keycode as before in case of rotation
  2104             keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
  2105         } else {
  2106             // key down
  2107             if ((policyFlags & POLICY_FLAG_VIRTUAL)
  2108                     && mContext->shouldDropVirtualKey(when,
  2109                             getDevice(), keyCode, scanCode)) {
  2110                 return;
  2113             mKeyDowns.push();
  2114             KeyDown& keyDown = mKeyDowns.editTop();
  2115             keyDown.keyCode = keyCode;
  2116             keyDown.scanCode = scanCode;
  2119         mDownTime = when;
  2120     } else {
  2121         // Remove key down.
  2122         ssize_t keyDownIndex = findKeyDown(scanCode);
  2123         if (keyDownIndex >= 0) {
  2124             // key up, be sure to use same keycode as before in case of rotation
  2125             keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
  2126             mKeyDowns.removeAt(size_t(keyDownIndex));
  2127         } else {
  2128             // key was not actually down
  2129             ALOGI("Dropping key up from device %s because the key was not down.  "
  2130                     "keyCode=%d, scanCode=%d",
  2131                     getDeviceName().string(), keyCode, scanCode);
  2132             return;
  2136     bool metaStateChanged = false;
  2137     int32_t oldMetaState = mMetaState;
  2138     int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
  2139     if (oldMetaState != newMetaState) {
  2140         mMetaState = newMetaState;
  2141         metaStateChanged = true;
  2142         updateLedState(false);
  2145     nsecs_t downTime = mDownTime;
  2147     // Key down on external an keyboard should wake the device.
  2148     // We don't do this for internal keyboards to prevent them from waking up in your pocket.
  2149     // For internal keyboards, the key layout file should specify the policy flags for
  2150     // each wake key individually.
  2151     // TODO: Use the input device configuration to control this behavior more finely.
  2152     if (down && getDevice()->isExternal()
  2153             && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {
  2154         policyFlags |= POLICY_FLAG_WAKE_DROPPED;
  2157     if (metaStateChanged) {
  2158         getContext()->updateGlobalMetaState();
  2161     if (down && !isMetaKey(keyCode)) {
  2162         getContext()->fadePointer();
  2165     NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
  2166             down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
  2167             AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
  2168     getListener()->notifyKey(&args);
  2171 ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) {
  2172     size_t n = mKeyDowns.size();
  2173     for (size_t i = 0; i < n; i++) {
  2174         if (mKeyDowns[i].scanCode == scanCode) {
  2175             return i;
  2178     return -1;
  2181 int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
  2182     return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
  2185 int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
  2186     return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
  2189 bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
  2190         const int32_t* keyCodes, uint8_t* outFlags) {
  2191     return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
  2194 int32_t KeyboardInputMapper::getMetaState() {
  2195     return mMetaState;
  2198 void KeyboardInputMapper::resetLedState() {
  2199     initializeLedState(mCapsLockLedState, LED_CAPSL);
  2200     initializeLedState(mNumLockLedState, LED_NUML);
  2201     initializeLedState(mScrollLockLedState, LED_SCROLLL);
  2203     updateLedState(true);
  2206 void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
  2207     ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
  2208     ledState.on = false;
  2211 void KeyboardInputMapper::updateLedState(bool reset) {
  2212     updateLedStateForModifier(mCapsLockLedState, LED_CAPSL,
  2213             AMETA_CAPS_LOCK_ON, reset);
  2214     updateLedStateForModifier(mNumLockLedState, LED_NUML,
  2215             AMETA_NUM_LOCK_ON, reset);
  2216     updateLedStateForModifier(mScrollLockLedState, LED_SCROLLL,
  2217             AMETA_SCROLL_LOCK_ON, reset);
  2220 void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState,
  2221         int32_t led, int32_t modifier, bool reset) {
  2222     if (ledState.avail) {
  2223         bool desiredState = (mMetaState & modifier) != 0;
  2224         if (reset || ledState.on != desiredState) {
  2225             getEventHub()->setLedState(getDeviceId(), led, desiredState);
  2226             ledState.on = desiredState;
  2232 // --- CursorInputMapper ---
  2234 CursorInputMapper::CursorInputMapper(InputDevice* device) :
  2235         InputMapper(device) {
  2238 CursorInputMapper::~CursorInputMapper() {
  2241 uint32_t CursorInputMapper::getSources() {
  2242     return mSource;
  2245 void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
  2246     InputMapper::populateDeviceInfo(info);
  2248     if (mParameters.mode == Parameters::MODE_POINTER) {
  2249         float minX, minY, maxX, maxY;
  2250         if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
  2251             info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f, 0.0f);
  2252             info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f, 0.0f);
  2254     } else {
  2255         info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f);
  2256         info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f);
  2258     info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
  2260     if (mCursorScrollAccumulator.haveRelativeVWheel()) {
  2261         info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
  2263     if (mCursorScrollAccumulator.haveRelativeHWheel()) {
  2264         info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
  2268 void CursorInputMapper::dump(String8& dump) {
  2269     dump.append(INDENT2 "Cursor Input Mapper:\n");
  2270     dumpParameters(dump);
  2271     dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
  2272     dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
  2273     dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
  2274     dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
  2275     dump.appendFormat(INDENT3 "HaveVWheel: %s\n",
  2276             toString(mCursorScrollAccumulator.haveRelativeVWheel()));
  2277     dump.appendFormat(INDENT3 "HaveHWheel: %s\n",
  2278             toString(mCursorScrollAccumulator.haveRelativeHWheel()));
  2279     dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
  2280     dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
  2281     dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
  2282     dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
  2283     dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
  2284     dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime);
  2287 void CursorInputMapper::configure(nsecs_t when,
  2288         const InputReaderConfiguration* config, uint32_t changes) {
  2289     InputMapper::configure(when, config, changes);
  2291     if (!changes) { // first time only
  2292         mCursorScrollAccumulator.configure(getDevice());
  2294         // Configure basic parameters.
  2295         configureParameters();
  2297         // Configure device mode.
  2298         switch (mParameters.mode) {
  2299         case Parameters::MODE_POINTER:
  2300             mSource = AINPUT_SOURCE_MOUSE;
  2301             mXPrecision = 1.0f;
  2302             mYPrecision = 1.0f;
  2303             mXScale = 1.0f;
  2304             mYScale = 1.0f;
  2305             mPointerController = getPolicy()->obtainPointerController(getDeviceId());
  2306             break;
  2307         case Parameters::MODE_NAVIGATION:
  2308             mSource = AINPUT_SOURCE_TRACKBALL;
  2309             mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
  2310             mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
  2311             mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
  2312             mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
  2313             break;
  2316         mVWheelScale = 1.0f;
  2317         mHWheelScale = 1.0f;
  2320     if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
  2321         mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
  2322         mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
  2323         mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
  2326     if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
  2327         if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
  2328             DisplayViewport v;
  2329             if (config->getDisplayInfo(false /*external*/, &v)) {
  2330                 mOrientation = v.orientation;
  2331             } else {
  2332                 mOrientation = DISPLAY_ORIENTATION_0;
  2334         } else {
  2335             mOrientation = DISPLAY_ORIENTATION_0;
  2337         bumpGeneration();
  2341 void CursorInputMapper::configureParameters() {
  2342     mParameters.mode = Parameters::MODE_POINTER;
  2343     String8 cursorModeString;
  2344     if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
  2345         if (cursorModeString == "navigation") {
  2346             mParameters.mode = Parameters::MODE_NAVIGATION;
  2347         } else if (cursorModeString != "pointer" && cursorModeString != "default") {
  2348             ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
  2352     mParameters.orientationAware = false;
  2353     getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
  2354             mParameters.orientationAware);
  2356     mParameters.hasAssociatedDisplay = false;
  2357     if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) {
  2358         mParameters.hasAssociatedDisplay = true;
  2362 void CursorInputMapper::dumpParameters(String8& dump) {
  2363     dump.append(INDENT3 "Parameters:\n");
  2364     dump.appendFormat(INDENT4 "HasAssociatedDisplay: %s\n",
  2365             toString(mParameters.hasAssociatedDisplay));
  2367     switch (mParameters.mode) {
  2368     case Parameters::MODE_POINTER:
  2369         dump.append(INDENT4 "Mode: pointer\n");
  2370         break;
  2371     case Parameters::MODE_NAVIGATION:
  2372         dump.append(INDENT4 "Mode: navigation\n");
  2373         break;
  2374     default:
  2375         ALOG_ASSERT(false);
  2378     dump.appendFormat(INDENT4 "OrientationAware: %s\n",
  2379             toString(mParameters.orientationAware));
  2382 void CursorInputMapper::reset(nsecs_t when) {
  2383     mButtonState = 0;
  2384     mDownTime = 0;
  2386     mPointerVelocityControl.reset();
  2387     mWheelXVelocityControl.reset();
  2388     mWheelYVelocityControl.reset();
  2390     mCursorButtonAccumulator.reset(getDevice());
  2391     mCursorMotionAccumulator.reset(getDevice());
  2392     mCursorScrollAccumulator.reset(getDevice());
  2394     InputMapper::reset(when);
  2397 void CursorInputMapper::process(const RawEvent* rawEvent) {
  2398     mCursorButtonAccumulator.process(rawEvent);
  2399     mCursorMotionAccumulator.process(rawEvent);
  2400     mCursorScrollAccumulator.process(rawEvent);
  2402     if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
  2403         sync(rawEvent->when);
  2407 void CursorInputMapper::sync(nsecs_t when) {
  2408     int32_t lastButtonState = mButtonState;
  2409     int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
  2410     mButtonState = currentButtonState;
  2412     bool wasDown = isPointerDown(lastButtonState);
  2413     bool down = isPointerDown(currentButtonState);
  2414     bool downChanged;
  2415     if (!wasDown && down) {
  2416         mDownTime = when;
  2417         downChanged = true;
  2418     } else if (wasDown && !down) {
  2419         downChanged = true;
  2420     } else {
  2421         downChanged = false;
  2423     nsecs_t downTime = mDownTime;
  2424     bool buttonsChanged = currentButtonState != lastButtonState;
  2425     bool buttonsPressed = currentButtonState & ~lastButtonState;
  2427     float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
  2428     float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
  2429     bool moved = deltaX != 0 || deltaY != 0;
  2431     // Rotate delta according to orientation if needed.
  2432     if (mParameters.orientationAware && mParameters.hasAssociatedDisplay
  2433             && (deltaX != 0.0f || deltaY != 0.0f)) {
  2434         rotateDelta(mOrientation, &deltaX, &deltaY);
  2437     // Move the pointer.
  2438     PointerProperties pointerProperties;
  2439     pointerProperties.clear();
  2440     pointerProperties.id = 0;
  2441     pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
  2443     PointerCoords pointerCoords;
  2444     pointerCoords.clear();
  2446     float vscroll = mCursorScrollAccumulator.getRelativeVWheel();
  2447     float hscroll = mCursorScrollAccumulator.getRelativeHWheel();
  2448     bool scrolled = vscroll != 0 || hscroll != 0;
  2450     mWheelYVelocityControl.move(when, NULL, &vscroll);
  2451     mWheelXVelocityControl.move(when, &hscroll, NULL);
  2453     mPointerVelocityControl.move(when, &deltaX, &deltaY);
  2455     int32_t displayId;
  2456     if (mPointerController != NULL) {
  2457         if (moved || scrolled || buttonsChanged) {
  2458             mPointerController->setPresentation(
  2459                     PointerControllerInterface::PRESENTATION_POINTER);
  2461             if (moved) {
  2462                 mPointerController->move(deltaX, deltaY);
  2465             if (buttonsChanged) {
  2466                 mPointerController->setButtonState(currentButtonState);
  2469             mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
  2472         float x, y;
  2473         mPointerController->getPosition(&x, &y);
  2474         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
  2475         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
  2476         displayId = ADISPLAY_ID_DEFAULT;
  2477     } else {
  2478         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
  2479         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
  2480         displayId = ADISPLAY_ID_NONE;
  2483     pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
  2485     // Moving an external trackball or mouse should wake the device.
  2486     // We don't do this for internal cursor devices to prevent them from waking up
  2487     // the device in your pocket.
  2488     // TODO: Use the input device configuration to control this behavior more finely.
  2489     uint32_t policyFlags = 0;
  2490     if ((buttonsPressed || moved || scrolled) && getDevice()->isExternal()) {
  2491         policyFlags |= POLICY_FLAG_WAKE_DROPPED;
  2494     // Synthesize key down from buttons if needed.
  2495     synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
  2496             policyFlags, lastButtonState, currentButtonState);
  2498     // Send motion event.
  2499     if (downChanged || moved || scrolled || buttonsChanged) {
  2500         int32_t metaState = mContext->getGlobalMetaState();
  2501         int32_t motionEventAction;
  2502         if (downChanged) {
  2503             motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
  2504         } else if (down || mPointerController == NULL) {
  2505             motionEventAction = AMOTION_EVENT_ACTION_MOVE;
  2506         } else {
  2507             motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
  2510         NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
  2511                 motionEventAction, 0, metaState, currentButtonState, 0,
  2512                 displayId, 1, &pointerProperties, &pointerCoords,
  2513                 mXPrecision, mYPrecision, downTime);
  2514         getListener()->notifyMotion(&args);
  2516         // Send hover move after UP to tell the application that the mouse is hovering now.
  2517         if (motionEventAction == AMOTION_EVENT_ACTION_UP
  2518                 && mPointerController != NULL) {
  2519             NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, policyFlags,
  2520                     AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
  2521                     metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE,
  2522                     displayId, 1, &pointerProperties, &pointerCoords,
  2523                     mXPrecision, mYPrecision, downTime);
  2524             getListener()->notifyMotion(&hoverArgs);
  2527         // Send scroll events.
  2528         if (scrolled) {
  2529             pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
  2530             pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
  2532             NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags,
  2533                     AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState,
  2534                     AMOTION_EVENT_EDGE_FLAG_NONE,
  2535                     displayId, 1, &pointerProperties, &pointerCoords,
  2536                     mXPrecision, mYPrecision, downTime);
  2537             getListener()->notifyMotion(&scrollArgs);
  2541     // Synthesize key up from buttons if needed.
  2542     synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
  2543             policyFlags, lastButtonState, currentButtonState);
  2545     mCursorMotionAccumulator.finishSync();
  2546     mCursorScrollAccumulator.finishSync();
  2549 int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
  2550     if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
  2551         return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
  2552     } else {
  2553         return AKEY_STATE_UNKNOWN;
  2557 void CursorInputMapper::fadePointer() {
  2558     if (mPointerController != NULL) {
  2559         mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
  2564 // --- TouchInputMapper ---
  2566 TouchInputMapper::TouchInputMapper(InputDevice* device) :
  2567         InputMapper(device),
  2568         mSource(0), mDeviceMode(DEVICE_MODE_DISABLED),
  2569         mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0),
  2570         mSurfaceOrientation(DISPLAY_ORIENTATION_0) {
  2573 TouchInputMapper::~TouchInputMapper() {
  2576 uint32_t TouchInputMapper::getSources() {
  2577     return mSource;
  2580 void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
  2581     InputMapper::populateDeviceInfo(info);
  2583     if (mDeviceMode != DEVICE_MODE_DISABLED) {
  2584         info->addMotionRange(mOrientedRanges.x);
  2585         info->addMotionRange(mOrientedRanges.y);
  2586         info->addMotionRange(mOrientedRanges.pressure);
  2588         if (mOrientedRanges.haveSize) {
  2589             info->addMotionRange(mOrientedRanges.size);
  2592         if (mOrientedRanges.haveTouchSize) {
  2593             info->addMotionRange(mOrientedRanges.touchMajor);
  2594             info->addMotionRange(mOrientedRanges.touchMinor);
  2597         if (mOrientedRanges.haveToolSize) {
  2598             info->addMotionRange(mOrientedRanges.toolMajor);
  2599             info->addMotionRange(mOrientedRanges.toolMinor);
  2602         if (mOrientedRanges.haveOrientation) {
  2603             info->addMotionRange(mOrientedRanges.orientation);
  2606         if (mOrientedRanges.haveDistance) {
  2607             info->addMotionRange(mOrientedRanges.distance);
  2610         if (mOrientedRanges.haveTilt) {
  2611             info->addMotionRange(mOrientedRanges.tilt);
  2614         if (mCursorScrollAccumulator.haveRelativeVWheel()) {
  2615             info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
  2616                     0.0f);
  2618         if (mCursorScrollAccumulator.haveRelativeHWheel()) {
  2619             info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
  2620                     0.0f);
  2622         if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
  2623             const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
  2624             const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
  2625             info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_1, mSource, x.min, x.max, x.flat,
  2626                     x.fuzz, x.resolution);
  2627             info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_2, mSource, y.min, y.max, y.flat,
  2628                     y.fuzz, y.resolution);
  2629             info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_3, mSource, x.min, x.max, x.flat,
  2630                     x.fuzz, x.resolution);
  2631             info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_4, mSource, y.min, y.max, y.flat,
  2632                     y.fuzz, y.resolution);
  2637 void TouchInputMapper::dump(String8& dump) {
  2638     dump.append(INDENT2 "Touch Input Mapper:\n");
  2639     dumpParameters(dump);
  2640     dumpVirtualKeys(dump);
  2641     dumpRawPointerAxes(dump);
  2642     dumpCalibration(dump);
  2643     dumpSurface(dump);
  2645     dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
  2646     dump.appendFormat(INDENT4 "XTranslate: %0.3f\n", mXTranslate);
  2647     dump.appendFormat(INDENT4 "YTranslate: %0.3f\n", mYTranslate);
  2648     dump.appendFormat(INDENT4 "XScale: %0.3f\n", mXScale);
  2649     dump.appendFormat(INDENT4 "YScale: %0.3f\n", mYScale);
  2650     dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mXPrecision);
  2651     dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mYPrecision);
  2652     dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale);
  2653     dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mPressureScale);
  2654     dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mSizeScale);
  2655     dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale);
  2656     dump.appendFormat(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale);
  2657     dump.appendFormat(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt));
  2658     dump.appendFormat(INDENT4 "TiltXCenter: %0.3f\n", mTiltXCenter);
  2659     dump.appendFormat(INDENT4 "TiltXScale: %0.3f\n", mTiltXScale);
  2660     dump.appendFormat(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter);
  2661     dump.appendFormat(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale);
  2663     dump.appendFormat(INDENT3 "Last Button State: 0x%08x\n", mLastButtonState);
  2665     dump.appendFormat(INDENT3 "Last Raw Touch: pointerCount=%d\n",
  2666             mLastRawPointerData.pointerCount);
  2667     for (uint32_t i = 0; i < mLastRawPointerData.pointerCount; i++) {
  2668         const RawPointerData::Pointer& pointer = mLastRawPointerData.pointers[i];
  2669         dump.appendFormat(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
  2670                 "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
  2671                 "orientation=%d, tiltX=%d, tiltY=%d, distance=%d, "
  2672                 "toolType=%d, isHovering=%s\n", i,
  2673                 pointer.id, pointer.x, pointer.y, pointer.pressure,
  2674                 pointer.touchMajor, pointer.touchMinor,
  2675                 pointer.toolMajor, pointer.toolMinor,
  2676                 pointer.orientation, pointer.tiltX, pointer.tiltY, pointer.distance,
  2677                 pointer.toolType, toString(pointer.isHovering));
  2680     dump.appendFormat(INDENT3 "Last Cooked Touch: pointerCount=%d\n",
  2681             mLastCookedPointerData.pointerCount);
  2682     for (uint32_t i = 0; i < mLastCookedPointerData.pointerCount; i++) {
  2683         const PointerProperties& pointerProperties = mLastCookedPointerData.pointerProperties[i];
  2684         const PointerCoords& pointerCoords = mLastCookedPointerData.pointerCoords[i];
  2685         dump.appendFormat(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, "
  2686                 "touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, toolMinor=%0.3f, "
  2687                 "orientation=%0.3f, tilt=%0.3f, distance=%0.3f, "
  2688                 "toolType=%d, isHovering=%s\n", i,
  2689                 pointerProperties.id,
  2690                 pointerCoords.getX(),
  2691                 pointerCoords.getY(),
  2692                 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
  2693                 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
  2694                 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
  2695                 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
  2696                 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
  2697                 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION),
  2698                 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TILT),
  2699                 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE),
  2700                 pointerProperties.toolType,
  2701                 toString(mLastCookedPointerData.isHovering(i)));
  2704     if (mDeviceMode == DEVICE_MODE_POINTER) {
  2705         dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n");
  2706         dump.appendFormat(INDENT4 "XMovementScale: %0.3f\n",
  2707                 mPointerXMovementScale);
  2708         dump.appendFormat(INDENT4 "YMovementScale: %0.3f\n",
  2709                 mPointerYMovementScale);
  2710         dump.appendFormat(INDENT4 "XZoomScale: %0.3f\n",
  2711                 mPointerXZoomScale);
  2712         dump.appendFormat(INDENT4 "YZoomScale: %0.3f\n",
  2713                 mPointerYZoomScale);
  2714         dump.appendFormat(INDENT4 "MaxSwipeWidth: %f\n",
  2715                 mPointerGestureMaxSwipeWidth);
  2719 void TouchInputMapper::configure(nsecs_t when,
  2720         const InputReaderConfiguration* config, uint32_t changes) {
  2721     InputMapper::configure(when, config, changes);
  2723     mConfig = *config;
  2725     if (!changes) { // first time only
  2726         // Configure basic parameters.
  2727         configureParameters();
  2729         // Configure common accumulators.
  2730         mCursorScrollAccumulator.configure(getDevice());
  2731         mTouchButtonAccumulator.configure(getDevice());
  2733         // Configure absolute axis information.
  2734         configureRawPointerAxes();
  2736         // Prepare input device calibration.
  2737         parseCalibration();
  2738         resolveCalibration();
  2741     if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
  2742         // Update pointer speed.
  2743         mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters);
  2744         mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
  2745         mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
  2748     bool resetNeeded = false;
  2749     if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO
  2750             | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT
  2751             | InputReaderConfiguration::CHANGE_SHOW_TOUCHES))) {
  2752         // Configure device sources, surface dimensions, orientation and
  2753         // scaling factors.
  2754         configureSurface(when, &resetNeeded);
  2757     if (changes && resetNeeded) {
  2758         // Send reset, unless this is the first time the device has been configured,
  2759         // in which case the reader will call reset itself after all mappers are ready.
  2760         getDevice()->notifyReset(when);
  2764 void TouchInputMapper::configureParameters() {
  2765     // Use the pointer presentation mode for devices that do not support distinct
  2766     // multitouch.  The spot-based presentation relies on being able to accurately
  2767     // locate two or more fingers on the touch pad.
  2768     mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT)
  2769             ? Parameters::GESTURE_MODE_POINTER : Parameters::GESTURE_MODE_SPOTS;
  2771     String8 gestureModeString;
  2772     if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
  2773             gestureModeString)) {
  2774         if (gestureModeString == "pointer") {
  2775             mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER;
  2776         } else if (gestureModeString == "spots") {
  2777             mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
  2778         } else if (gestureModeString != "default") {
  2779             ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
  2783     if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
  2784         // The device is a touch screen.
  2785         mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
  2786     } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) {
  2787         // The device is a pointing device like a track pad.
  2788         mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
  2789     } else if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
  2790             || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
  2791         // The device is a cursor device with a touch pad attached.
  2792         // By default don't use the touch pad to move the pointer.
  2793         mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
  2794     } else {
  2795         // The device is a touch pad of unknown purpose.
  2796         mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
  2799     String8 deviceTypeString;
  2800     if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
  2801             deviceTypeString)) {
  2802         if (deviceTypeString == "touchScreen") {
  2803             mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
  2804         } else if (deviceTypeString == "touchPad") {
  2805             mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
  2806         } else if (deviceTypeString == "touchNavigation") {
  2807             mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION;
  2808         } else if (deviceTypeString == "pointer") {
  2809             mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
  2810         } else if (deviceTypeString != "default") {
  2811             ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
  2815     mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
  2816     getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
  2817             mParameters.orientationAware);
  2819     mParameters.hasAssociatedDisplay = false;
  2820     mParameters.associatedDisplayIsExternal = false;
  2821     if (mParameters.orientationAware
  2822             || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
  2823             || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
  2824         mParameters.hasAssociatedDisplay = true;
  2825         mParameters.associatedDisplayIsExternal =
  2826                 mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
  2827                         && getDevice()->isExternal();
  2831 void TouchInputMapper::dumpParameters(String8& dump) {
  2832     dump.append(INDENT3 "Parameters:\n");
  2834     switch (mParameters.gestureMode) {
  2835     case Parameters::GESTURE_MODE_POINTER:
  2836         dump.append(INDENT4 "GestureMode: pointer\n");
  2837         break;
  2838     case Parameters::GESTURE_MODE_SPOTS:
  2839         dump.append(INDENT4 "GestureMode: spots\n");
  2840         break;
  2841     default:
  2842         assert(false);
  2845     switch (mParameters.deviceType) {
  2846     case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
  2847         dump.append(INDENT4 "DeviceType: touchScreen\n");
  2848         break;
  2849     case Parameters::DEVICE_TYPE_TOUCH_PAD:
  2850         dump.append(INDENT4 "DeviceType: touchPad\n");
  2851         break;
  2852     case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION:
  2853         dump.append(INDENT4 "DeviceType: touchNavigation\n");
  2854         break;
  2855     case Parameters::DEVICE_TYPE_POINTER:
  2856         dump.append(INDENT4 "DeviceType: pointer\n");
  2857         break;
  2858     default:
  2859         ALOG_ASSERT(false);
  2862     dump.appendFormat(INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s\n",
  2863             toString(mParameters.hasAssociatedDisplay),
  2864             toString(mParameters.associatedDisplayIsExternal));
  2865     dump.appendFormat(INDENT4 "OrientationAware: %s\n",
  2866             toString(mParameters.orientationAware));
  2869 void TouchInputMapper::configureRawPointerAxes() {
  2870     mRawPointerAxes.clear();
  2873 void TouchInputMapper::dumpRawPointerAxes(String8& dump) {
  2874     dump.append(INDENT3 "Raw Touch Axes:\n");
  2875     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.x, "X");
  2876     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.y, "Y");
  2877     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.pressure, "Pressure");
  2878     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMajor, "TouchMajor");
  2879     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMinor, "TouchMinor");
  2880     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMajor, "ToolMajor");
  2881     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMinor, "ToolMinor");
  2882     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.orientation, "Orientation");
  2883     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.distance, "Distance");
  2884     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltX, "TiltX");
  2885     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltY, "TiltY");
  2886     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.trackingId, "TrackingId");
  2887     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot");
  2890 void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
  2891     int32_t oldDeviceMode = mDeviceMode;
  2893     // Determine device mode.
  2894     if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
  2895             && mConfig.pointerGesturesEnabled) {
  2896         mSource = AINPUT_SOURCE_MOUSE;
  2897         mDeviceMode = DEVICE_MODE_POINTER;
  2898         if (hasStylus()) {
  2899             mSource |= AINPUT_SOURCE_STYLUS;
  2901     } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
  2902             && mParameters.hasAssociatedDisplay) {
  2903         mSource = AINPUT_SOURCE_TOUCHSCREEN;
  2904         mDeviceMode = DEVICE_MODE_DIRECT;
  2905         if (hasStylus()) {
  2906             mSource |= AINPUT_SOURCE_STYLUS;
  2908     } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) {
  2909         mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
  2910         mDeviceMode = DEVICE_MODE_NAVIGATION;
  2911     } else {
  2912         mSource = AINPUT_SOURCE_TOUCHPAD;
  2913         mDeviceMode = DEVICE_MODE_UNSCALED;
  2916     // Ensure we have valid X and Y axes.
  2917     if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
  2918         ALOGW(INDENT "Touch device '%s' did not report support for X or Y axis!  "
  2919                 "The device will be inoperable.", getDeviceName().string());
  2920         mDeviceMode = DEVICE_MODE_DISABLED;
  2921         return;
  2924     // Raw width and height in the natural orientation.
  2925     int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
  2926     int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
  2928     // Get associated display dimensions.
  2929     bool viewportChanged = false;
  2930     DisplayViewport newViewport;
  2931     if (mParameters.hasAssociatedDisplay) {
  2932         if (!mConfig.getDisplayInfo(mParameters.associatedDisplayIsExternal, &newViewport)) {
  2933             ALOGI(INDENT "Touch device '%s' could not query the properties of its associated "
  2934                     "display.  The device will be inoperable until the display size "
  2935                     "becomes available.",
  2936                     getDeviceName().string());
  2937             mDeviceMode = DEVICE_MODE_DISABLED;
  2938             return;
  2940     } else {
  2941         newViewport.setNonDisplayViewport(rawWidth, rawHeight);
  2943     if (mViewport != newViewport) {
  2944         mViewport = newViewport;
  2945         viewportChanged = true;
  2947         if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
  2948             // Convert rotated viewport to natural surface coordinates.
  2949             int32_t naturalLogicalWidth, naturalLogicalHeight;
  2950             int32_t naturalPhysicalWidth, naturalPhysicalHeight;
  2951             int32_t naturalPhysicalLeft, naturalPhysicalTop;
  2952             int32_t naturalDeviceWidth, naturalDeviceHeight;
  2953             switch (mViewport.orientation) {
  2954             case DISPLAY_ORIENTATION_90:
  2955                 naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
  2956                 naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
  2957                 naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
  2958                 naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
  2959                 naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom;
  2960                 naturalPhysicalTop = mViewport.physicalLeft;
  2961                 naturalDeviceWidth = mViewport.deviceHeight;
  2962                 naturalDeviceHeight = mViewport.deviceWidth;
  2963                 break;
  2964             case DISPLAY_ORIENTATION_180:
  2965                 naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
  2966                 naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
  2967                 naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
  2968                 naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
  2969                 naturalPhysicalLeft = mViewport.deviceWidth - mViewport.physicalRight;
  2970                 naturalPhysicalTop = mViewport.deviceHeight - mViewport.physicalBottom;
  2971                 naturalDeviceWidth = mViewport.deviceWidth;
  2972                 naturalDeviceHeight = mViewport.deviceHeight;
  2973                 break;
  2974             case DISPLAY_ORIENTATION_270:
  2975                 naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
  2976                 naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
  2977                 naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
  2978                 naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
  2979                 naturalPhysicalLeft = mViewport.physicalTop;
  2980                 naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight;
  2981                 naturalDeviceWidth = mViewport.deviceHeight;
  2982                 naturalDeviceHeight = mViewport.deviceWidth;
  2983                 break;
  2984             case DISPLAY_ORIENTATION_0:
  2985             default:
  2986                 naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
  2987                 naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
  2988                 naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
  2989                 naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
  2990                 naturalPhysicalLeft = mViewport.physicalLeft;
  2991                 naturalPhysicalTop = mViewport.physicalTop;
  2992                 naturalDeviceWidth = mViewport.deviceWidth;
  2993                 naturalDeviceHeight = mViewport.deviceHeight;
  2994                 break;
  2997             mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
  2998             mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
  2999             mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth;
  3000             mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight;
  3002             mSurfaceOrientation = mParameters.orientationAware ?
  3003                     mViewport.orientation : DISPLAY_ORIENTATION_0;
  3004         } else {
  3005             mSurfaceWidth = rawWidth;
  3006             mSurfaceHeight = rawHeight;
  3007             mSurfaceLeft = 0;
  3008             mSurfaceTop = 0;
  3009             mSurfaceOrientation = DISPLAY_ORIENTATION_0;
  3013     // If moving between pointer modes, need to reset some state.
  3014     bool deviceModeChanged;
  3015     if (mDeviceMode != oldDeviceMode) {
  3016         deviceModeChanged = true;
  3017         mOrientedRanges.clear();
  3020     // Create pointer controller if needed.
  3021     if (mDeviceMode == DEVICE_MODE_POINTER ||
  3022             (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
  3023         if (mPointerController == NULL) {
  3024             mPointerController = getPolicy()->obtainPointerController(getDeviceId());
  3026     } else {
  3027         mPointerController.clear();
  3030     if (viewportChanged || deviceModeChanged) {
  3031         ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
  3032                 "display id %d",
  3033                 getDeviceId(), getDeviceName().string(), mSurfaceWidth, mSurfaceHeight,
  3034                 mSurfaceOrientation, mDeviceMode, mViewport.displayId);
  3036         // Configure X and Y factors.
  3037         mXScale = float(mSurfaceWidth) / rawWidth;
  3038         mYScale = float(mSurfaceHeight) / rawHeight;
  3039         mXTranslate = -mSurfaceLeft;
  3040         mYTranslate = -mSurfaceTop;
  3041         mXPrecision = 1.0f / mXScale;
  3042         mYPrecision = 1.0f / mYScale;
  3044         mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
  3045         mOrientedRanges.x.source = mSource;
  3046         mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
  3047         mOrientedRanges.y.source = mSource;
  3049         configureVirtualKeys();
  3051         // Scale factor for terms that are not oriented in a particular axis.
  3052         // If the pixels are square then xScale == yScale otherwise we fake it
  3053         // by choosing an average.
  3054         mGeometricScale = avg(mXScale, mYScale);
  3056         // Size of diagonal axis.
  3057         float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight);
  3059         // Size factors.
  3060         if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
  3061             if (mRawPointerAxes.touchMajor.valid
  3062                     && mRawPointerAxes.touchMajor.maxValue != 0) {
  3063                 mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue;
  3064             } else if (mRawPointerAxes.toolMajor.valid
  3065                     && mRawPointerAxes.toolMajor.maxValue != 0) {
  3066                 mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue;
  3067             } else {
  3068                 mSizeScale = 0.0f;
  3071             mOrientedRanges.haveTouchSize = true;
  3072             mOrientedRanges.haveToolSize = true;
  3073             mOrientedRanges.haveSize = true;
  3075             mOrientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
  3076             mOrientedRanges.touchMajor.source = mSource;
  3077             mOrientedRanges.touchMajor.min = 0;
  3078             mOrientedRanges.touchMajor.max = diagonalSize;
  3079             mOrientedRanges.touchMajor.flat = 0;
  3080             mOrientedRanges.touchMajor.fuzz = 0;
  3081             mOrientedRanges.touchMajor.resolution = 0;
  3083             mOrientedRanges.touchMinor = mOrientedRanges.touchMajor;
  3084             mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
  3086             mOrientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
  3087             mOrientedRanges.toolMajor.source = mSource;
  3088             mOrientedRanges.toolMajor.min = 0;
  3089             mOrientedRanges.toolMajor.max = diagonalSize;
  3090             mOrientedRanges.toolMajor.flat = 0;
  3091             mOrientedRanges.toolMajor.fuzz = 0;
  3092             mOrientedRanges.toolMajor.resolution = 0;
  3094             mOrientedRanges.toolMinor = mOrientedRanges.toolMajor;
  3095             mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
  3097             mOrientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
  3098             mOrientedRanges.size.source = mSource;
  3099             mOrientedRanges.size.min = 0;
  3100             mOrientedRanges.size.max = 1.0;
  3101             mOrientedRanges.size.flat = 0;
  3102             mOrientedRanges.size.fuzz = 0;
  3103             mOrientedRanges.size.resolution = 0;
  3104         } else {
  3105             mSizeScale = 0.0f;
  3108         // Pressure factors.
  3109         mPressureScale = 0;
  3110         if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
  3111                 || mCalibration.pressureCalibration
  3112                         == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
  3113             if (mCalibration.havePressureScale) {
  3114                 mPressureScale = mCalibration.pressureScale;
  3115             } else if (mRawPointerAxes.pressure.valid
  3116                     && mRawPointerAxes.pressure.maxValue != 0) {
  3117                 mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue;
  3121         mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
  3122         mOrientedRanges.pressure.source = mSource;
  3123         mOrientedRanges.pressure.min = 0;
  3124         mOrientedRanges.pressure.max = 1.0;
  3125         mOrientedRanges.pressure.flat = 0;
  3126         mOrientedRanges.pressure.fuzz = 0;
  3127         mOrientedRanges.pressure.resolution = 0;
  3129         // Tilt
  3130         mTiltXCenter = 0;
  3131         mTiltXScale = 0;
  3132         mTiltYCenter = 0;
  3133         mTiltYScale = 0;
  3134         mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid;
  3135         if (mHaveTilt) {
  3136             mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue,
  3137                     mRawPointerAxes.tiltX.maxValue);
  3138             mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue,
  3139                     mRawPointerAxes.tiltY.maxValue);
  3140             mTiltXScale = M_PI / 180;
  3141             mTiltYScale = M_PI / 180;
  3143             mOrientedRanges.haveTilt = true;
  3145             mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT;
  3146             mOrientedRanges.tilt.source = mSource;
  3147             mOrientedRanges.tilt.min = 0;
  3148             mOrientedRanges.tilt.max = M_PI_2;
  3149             mOrientedRanges.tilt.flat = 0;
  3150             mOrientedRanges.tilt.fuzz = 0;
  3151             mOrientedRanges.tilt.resolution = 0;
  3154         // Orientation
  3155         mOrientationScale = 0;
  3156         if (mHaveTilt) {
  3157             mOrientedRanges.haveOrientation = true;
  3159             mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
  3160             mOrientedRanges.orientation.source = mSource;
  3161             mOrientedRanges.orientation.min = -M_PI;
  3162             mOrientedRanges.orientation.max = M_PI;
  3163             mOrientedRanges.orientation.flat = 0;
  3164             mOrientedRanges.orientation.fuzz = 0;
  3165             mOrientedRanges.orientation.resolution = 0;
  3166         } else if (mCalibration.orientationCalibration !=
  3167                 Calibration::ORIENTATION_CALIBRATION_NONE) {
  3168             if (mCalibration.orientationCalibration
  3169                     == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
  3170                 if (mRawPointerAxes.orientation.valid) {
  3171                     if (mRawPointerAxes.orientation.maxValue > 0) {
  3172                         mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue;
  3173                     } else if (mRawPointerAxes.orientation.minValue < 0) {
  3174                         mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue;
  3175                     } else {
  3176                         mOrientationScale = 0;
  3181             mOrientedRanges.haveOrientation = true;
  3183             mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
  3184             mOrientedRanges.orientation.source = mSource;
  3185             mOrientedRanges.orientation.min = -M_PI_2;
  3186             mOrientedRanges.orientation.max = M_PI_2;
  3187             mOrientedRanges.orientation.flat = 0;
  3188             mOrientedRanges.orientation.fuzz = 0;
  3189             mOrientedRanges.orientation.resolution = 0;
  3192         // Distance
  3193         mDistanceScale = 0;
  3194         if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) {
  3195             if (mCalibration.distanceCalibration
  3196                     == Calibration::DISTANCE_CALIBRATION_SCALED) {
  3197                 if (mCalibration.haveDistanceScale) {
  3198                     mDistanceScale = mCalibration.distanceScale;
  3199                 } else {
  3200                     mDistanceScale = 1.0f;
  3204             mOrientedRanges.haveDistance = true;
  3206             mOrientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE;
  3207             mOrientedRanges.distance.source = mSource;
  3208             mOrientedRanges.distance.min =
  3209                     mRawPointerAxes.distance.minValue * mDistanceScale;
  3210             mOrientedRanges.distance.max =
  3211                     mRawPointerAxes.distance.maxValue * mDistanceScale;
  3212             mOrientedRanges.distance.flat = 0;
  3213             mOrientedRanges.distance.fuzz =
  3214                     mRawPointerAxes.distance.fuzz * mDistanceScale;
  3215             mOrientedRanges.distance.resolution = 0;
  3218         // Compute oriented precision, scales and ranges.
  3219         // Note that the maximum value reported is an inclusive maximum value so it is one
  3220         // unit less than the total width or height of surface.
  3221         switch (mSurfaceOrientation) {
  3222         case DISPLAY_ORIENTATION_90:
  3223         case DISPLAY_ORIENTATION_270:
  3224             mOrientedXPrecision = mYPrecision;
  3225             mOrientedYPrecision = mXPrecision;
  3227             mOrientedRanges.x.min = mYTranslate;
  3228             mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1;
  3229             mOrientedRanges.x.flat = 0;
  3230             mOrientedRanges.x.fuzz = 0;
  3231             mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mYScale;
  3233             mOrientedRanges.y.min = mXTranslate;
  3234             mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1;
  3235             mOrientedRanges.y.flat = 0;
  3236             mOrientedRanges.y.fuzz = 0;
  3237             mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mXScale;
  3238             break;
  3240         default:
  3241             mOrientedXPrecision = mXPrecision;
  3242             mOrientedYPrecision = mYPrecision;
  3244             mOrientedRanges.x.min = mXTranslate;
  3245             mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1;
  3246             mOrientedRanges.x.flat = 0;
  3247             mOrientedRanges.x.fuzz = 0;
  3248             mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mXScale;
  3250             mOrientedRanges.y.min = mYTranslate;
  3251             mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1;
  3252             mOrientedRanges.y.flat = 0;
  3253             mOrientedRanges.y.fuzz = 0;
  3254             mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale;
  3255             break;
  3258         if (mDeviceMode == DEVICE_MODE_POINTER) {
  3259             // Compute pointer gesture detection parameters.
  3260             float rawDiagonal = hypotf(rawWidth, rawHeight);
  3261             float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight);
  3263             // Scale movements such that one whole swipe of the touch pad covers a
  3264             // given area relative to the diagonal size of the display when no acceleration
  3265             // is applied.
  3266             // Assume that the touch pad has a square aspect ratio such that movements in
  3267             // X and Y of the same number of raw units cover the same physical distance.
  3268             mPointerXMovementScale = mConfig.pointerGestureMovementSpeedRatio
  3269                     * displayDiagonal / rawDiagonal;
  3270             mPointerYMovementScale = mPointerXMovementScale;
  3272             // Scale zooms to cover a smaller range of the display than movements do.
  3273             // This value determines the area around the pointer that is affected by freeform
  3274             // pointer gestures.
  3275             mPointerXZoomScale = mConfig.pointerGestureZoomSpeedRatio
  3276                     * displayDiagonal / rawDiagonal;
  3277             mPointerYZoomScale = mPointerXZoomScale;
  3279             // Max width between pointers to detect a swipe gesture is more than some fraction
  3280             // of the diagonal axis of the touch pad.  Touches that are wider than this are
  3281             // translated into freeform gestures.
  3282             mPointerGestureMaxSwipeWidth =
  3283                     mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
  3285             // Abort current pointer usages because the state has changed.
  3286             abortPointerUsage(when, 0 /*policyFlags*/);
  3289         // Inform the dispatcher about the changes.
  3290         *outResetNeeded = true;
  3291         bumpGeneration();
  3295 void TouchInputMapper::dumpSurface(String8& dump) {
  3296     dump.appendFormat(INDENT3 "Viewport: displayId=%d, orientation=%d, "
  3297             "logicalFrame=[%d, %d, %d, %d], "
  3298             "physicalFrame=[%d, %d, %d, %d], "
  3299             "deviceSize=[%d, %d]\n",
  3300             mViewport.displayId, mViewport.orientation,
  3301             mViewport.logicalLeft, mViewport.logicalTop,
  3302             mViewport.logicalRight, mViewport.logicalBottom,
  3303             mViewport.physicalLeft, mViewport.physicalTop,
  3304             mViewport.physicalRight, mViewport.physicalBottom,
  3305             mViewport.deviceWidth, mViewport.deviceHeight);
  3307     dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
  3308     dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
  3309     dump.appendFormat(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
  3310     dump.appendFormat(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
  3311     dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
  3314 void TouchInputMapper::configureVirtualKeys() {
  3315     Vector<VirtualKeyDefinition> virtualKeyDefinitions;
  3316     getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
  3318     mVirtualKeys.clear();
  3320     if (virtualKeyDefinitions.size() == 0) {
  3321         return;
  3324     mVirtualKeys.setCapacity(virtualKeyDefinitions.size());
  3326     int32_t touchScreenLeft = mRawPointerAxes.x.minValue;
  3327     int32_t touchScreenTop = mRawPointerAxes.y.minValue;
  3328     int32_t touchScreenWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
  3329     int32_t touchScreenHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
  3331     for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
  3332         const VirtualKeyDefinition& virtualKeyDefinition =
  3333                 virtualKeyDefinitions[i];
  3335         mVirtualKeys.add();
  3336         VirtualKey& virtualKey = mVirtualKeys.editTop();
  3338         virtualKey.scanCode = virtualKeyDefinition.scanCode;
  3339         int32_t keyCode;
  3340         uint32_t flags;
  3341         if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, 0, &keyCode, &flags)) {
  3342             ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
  3343                     virtualKey.scanCode);
  3344             mVirtualKeys.pop(); // drop the key
  3345             continue;
  3348         virtualKey.keyCode = keyCode;
  3349         virtualKey.flags = flags;
  3351         // convert the key definition's display coordinates into touch coordinates for a hit box
  3352         int32_t halfWidth = virtualKeyDefinition.width / 2;
  3353         int32_t halfHeight = virtualKeyDefinition.height / 2;
  3355         virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
  3356                 * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
  3357         virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
  3358                 * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
  3359         virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
  3360                 * touchScreenHeight / mSurfaceHeight + touchScreenTop;
  3361         virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
  3362                 * touchScreenHeight / mSurfaceHeight + touchScreenTop;
  3366 void TouchInputMapper::dumpVirtualKeys(String8& dump) {
  3367     if (!mVirtualKeys.isEmpty()) {
  3368         dump.append(INDENT3 "Virtual Keys:\n");
  3370         for (size_t i = 0; i < mVirtualKeys.size(); i++) {
  3371             const VirtualKey& virtualKey = mVirtualKeys.itemAt(i);
  3372             dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
  3373                     "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
  3374                     i, virtualKey.scanCode, virtualKey.keyCode,
  3375                     virtualKey.hitLeft, virtualKey.hitRight,
  3376                     virtualKey.hitTop, virtualKey.hitBottom);
  3381 void TouchInputMapper::parseCalibration() {
  3382     const PropertyMap& in = getDevice()->getConfiguration();
  3383     Calibration& out = mCalibration;
  3385     // Size
  3386     out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
  3387     String8 sizeCalibrationString;
  3388     if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
  3389         if (sizeCalibrationString == "none") {
  3390             out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
  3391         } else if (sizeCalibrationString == "geometric") {
  3392             out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
  3393         } else if (sizeCalibrationString == "diameter") {
  3394             out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER;
  3395         } else if (sizeCalibrationString == "box") {
  3396             out.sizeCalibration = Calibration::SIZE_CALIBRATION_BOX;
  3397         } else if (sizeCalibrationString == "area") {
  3398             out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA;
  3399         } else if (sizeCalibrationString != "default") {
  3400             ALOGW("Invalid value for touch.size.calibration: '%s'",
  3401                     sizeCalibrationString.string());
  3405     out.haveSizeScale = in.tryGetProperty(String8("touch.size.scale"),
  3406             out.sizeScale);
  3407     out.haveSizeBias = in.tryGetProperty(String8("touch.size.bias"),
  3408             out.sizeBias);
  3409     out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"),
  3410             out.sizeIsSummed);
  3412     // Pressure
  3413     out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
  3414     String8 pressureCalibrationString;
  3415     if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
  3416         if (pressureCalibrationString == "none") {
  3417             out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
  3418         } else if (pressureCalibrationString == "physical") {
  3419             out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
  3420         } else if (pressureCalibrationString == "amplitude") {
  3421             out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
  3422         } else if (pressureCalibrationString != "default") {
  3423             ALOGW("Invalid value for touch.pressure.calibration: '%s'",
  3424                     pressureCalibrationString.string());
  3428     out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
  3429             out.pressureScale);
  3431     // Orientation
  3432     out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
  3433     String8 orientationCalibrationString;
  3434     if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
  3435         if (orientationCalibrationString == "none") {
  3436             out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
  3437         } else if (orientationCalibrationString == "interpolated") {
  3438             out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
  3439         } else if (orientationCalibrationString == "vector") {
  3440             out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
  3441         } else if (orientationCalibrationString != "default") {
  3442             ALOGW("Invalid value for touch.orientation.calibration: '%s'",
  3443                     orientationCalibrationString.string());
  3447     // Distance
  3448     out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT;
  3449     String8 distanceCalibrationString;
  3450     if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
  3451         if (distanceCalibrationString == "none") {
  3452             out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
  3453         } else if (distanceCalibrationString == "scaled") {
  3454             out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
  3455         } else if (distanceCalibrationString != "default") {
  3456             ALOGW("Invalid value for touch.distance.calibration: '%s'",
  3457                     distanceCalibrationString.string());
  3461     out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"),
  3462             out.distanceScale);
  3464     out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_DEFAULT;
  3465     String8 coverageCalibrationString;
  3466     if (in.tryGetProperty(String8("touch.coverage.calibration"), coverageCalibrationString)) {
  3467         if (coverageCalibrationString == "none") {
  3468             out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
  3469         } else if (coverageCalibrationString == "box") {
  3470             out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_BOX;
  3471         } else if (coverageCalibrationString != "default") {
  3472             ALOGW("Invalid value for touch.coverage.calibration: '%s'",
  3473                     coverageCalibrationString.string());
  3478 void TouchInputMapper::resolveCalibration() {
  3479     // Size
  3480     if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) {
  3481         if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DEFAULT) {
  3482             mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
  3484     } else {
  3485         mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
  3488     // Pressure
  3489     if (mRawPointerAxes.pressure.valid) {
  3490         if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DEFAULT) {
  3491             mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
  3493     } else {
  3494         mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
  3497     // Orientation
  3498     if (mRawPointerAxes.orientation.valid) {
  3499         if (mCalibration.orientationCalibration == Calibration::ORIENTATION_CALIBRATION_DEFAULT) {
  3500             mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
  3502     } else {
  3503         mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
  3506     // Distance
  3507     if (mRawPointerAxes.distance.valid) {
  3508         if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_DEFAULT) {
  3509             mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
  3511     } else {
  3512         mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
  3515     // Coverage
  3516     if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_DEFAULT) {
  3517         mCalibration.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
  3521 void TouchInputMapper::dumpCalibration(String8& dump) {
  3522     dump.append(INDENT3 "Calibration:\n");
  3524     // Size
  3525     switch (mCalibration.sizeCalibration) {
  3526     case Calibration::SIZE_CALIBRATION_NONE:
  3527         dump.append(INDENT4 "touch.size.calibration: none\n");
  3528         break;
  3529     case Calibration::SIZE_CALIBRATION_GEOMETRIC:
  3530         dump.append(INDENT4 "touch.size.calibration: geometric\n");
  3531         break;
  3532     case Calibration::SIZE_CALIBRATION_DIAMETER:
  3533         dump.append(INDENT4 "touch.size.calibration: diameter\n");
  3534         break;
  3535     case Calibration::SIZE_CALIBRATION_BOX:
  3536         dump.append(INDENT4 "touch.size.calibration: box\n");
  3537         break;
  3538     case Calibration::SIZE_CALIBRATION_AREA:
  3539         dump.append(INDENT4 "touch.size.calibration: area\n");
  3540         break;
  3541     default:
  3542         ALOG_ASSERT(false);
  3545     if (mCalibration.haveSizeScale) {
  3546         dump.appendFormat(INDENT4 "touch.size.scale: %0.3f\n",
  3547                 mCalibration.sizeScale);
  3550     if (mCalibration.haveSizeBias) {
  3551         dump.appendFormat(INDENT4 "touch.size.bias: %0.3f\n",
  3552                 mCalibration.sizeBias);
  3555     if (mCalibration.haveSizeIsSummed) {
  3556         dump.appendFormat(INDENT4 "touch.size.isSummed: %s\n",
  3557                 toString(mCalibration.sizeIsSummed));
  3560     // Pressure
  3561     switch (mCalibration.pressureCalibration) {
  3562     case Calibration::PRESSURE_CALIBRATION_NONE:
  3563         dump.append(INDENT4 "touch.pressure.calibration: none\n");
  3564         break;
  3565     case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
  3566         dump.append(INDENT4 "touch.pressure.calibration: physical\n");
  3567         break;
  3568     case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
  3569         dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
  3570         break;
  3571     default:
  3572         ALOG_ASSERT(false);
  3575     if (mCalibration.havePressureScale) {
  3576         dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
  3577                 mCalibration.pressureScale);
  3580     // Orientation
  3581     switch (mCalibration.orientationCalibration) {
  3582     case Calibration::ORIENTATION_CALIBRATION_NONE:
  3583         dump.append(INDENT4 "touch.orientation.calibration: none\n");
  3584         break;
  3585     case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
  3586         dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
  3587         break;
  3588     case Calibration::ORIENTATION_CALIBRATION_VECTOR:
  3589         dump.append(INDENT4 "touch.orientation.calibration: vector\n");
  3590         break;
  3591     default:
  3592         ALOG_ASSERT(false);
  3595     // Distance
  3596     switch (mCalibration.distanceCalibration) {
  3597     case Calibration::DISTANCE_CALIBRATION_NONE:
  3598         dump.append(INDENT4 "touch.distance.calibration: none\n");
  3599         break;
  3600     case Calibration::DISTANCE_CALIBRATION_SCALED:
  3601         dump.append(INDENT4 "touch.distance.calibration: scaled\n");
  3602         break;
  3603     default:
  3604         ALOG_ASSERT(false);
  3607     if (mCalibration.haveDistanceScale) {
  3608         dump.appendFormat(INDENT4 "touch.distance.scale: %0.3f\n",
  3609                 mCalibration.distanceScale);
  3612     switch (mCalibration.coverageCalibration) {
  3613     case Calibration::COVERAGE_CALIBRATION_NONE:
  3614         dump.append(INDENT4 "touch.coverage.calibration: none\n");
  3615         break;
  3616     case Calibration::COVERAGE_CALIBRATION_BOX:
  3617         dump.append(INDENT4 "touch.coverage.calibration: box\n");
  3618         break;
  3619     default:
  3620         ALOG_ASSERT(false);
  3624 void TouchInputMapper::reset(nsecs_t when) {
  3625     mCursorButtonAccumulator.reset(getDevice());
  3626     mCursorScrollAccumulator.reset(getDevice());
  3627     mTouchButtonAccumulator.reset(getDevice());
  3629     mPointerVelocityControl.reset();
  3630     mWheelXVelocityControl.reset();
  3631     mWheelYVelocityControl.reset();
  3633     mCurrentRawPointerData.clear();
  3634     mLastRawPointerData.clear();
  3635     mCurrentCookedPointerData.clear();
  3636     mLastCookedPointerData.clear();
  3637     mCurrentButtonState = 0;
  3638     mLastButtonState = 0;
  3639     mCurrentRawVScroll = 0;
  3640     mCurrentRawHScroll = 0;
  3641     mCurrentFingerIdBits.clear();
  3642     mLastFingerIdBits.clear();
  3643     mCurrentStylusIdBits.clear();
  3644     mLastStylusIdBits.clear();
  3645     mCurrentMouseIdBits.clear();
  3646     mLastMouseIdBits.clear();
  3647     mPointerUsage = POINTER_USAGE_NONE;
  3648     mSentHoverEnter = false;
  3649     mDownTime = 0;
  3651     mCurrentVirtualKey.down = false;
  3653     mPointerGesture.reset();
  3654     mPointerSimple.reset();
  3656     if (mPointerController != NULL) {
  3657         mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
  3658         mPointerController->clearSpots();
  3661     InputMapper::reset(when);
  3664 void TouchInputMapper::process(const RawEvent* rawEvent) {
  3665     mCursorButtonAccumulator.process(rawEvent);
  3666     mCursorScrollAccumulator.process(rawEvent);
  3667     mTouchButtonAccumulator.process(rawEvent);
  3669     if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
  3670         sync(rawEvent->when);
  3674 void TouchInputMapper::sync(nsecs_t when) {
  3675     // Sync button state.
  3676     mCurrentButtonState = mTouchButtonAccumulator.getButtonState()
  3677             | mCursorButtonAccumulator.getButtonState();
  3679     // Sync scroll state.
  3680     mCurrentRawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
  3681     mCurrentRawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
  3682     mCursorScrollAccumulator.finishSync();
  3684     // Sync touch state.
  3685     bool havePointerIds = true;
  3686     mCurrentRawPointerData.clear();
  3687     syncTouch(when, &havePointerIds);
  3689 #if DEBUG_RAW_EVENTS
  3690     if (!havePointerIds) {
  3691         ALOGD("syncTouch: pointerCount %d -> %d, no pointer ids",
  3692                 mLastRawPointerData.pointerCount,
  3693                 mCurrentRawPointerData.pointerCount);
  3694     } else {
  3695         ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
  3696                 "hovering ids 0x%08x -> 0x%08x",
  3697                 mLastRawPointerData.pointerCount,
  3698                 mCurrentRawPointerData.pointerCount,
  3699                 mLastRawPointerData.touchingIdBits.value,
  3700                 mCurrentRawPointerData.touchingIdBits.value,
  3701                 mLastRawPointerData.hoveringIdBits.value,
  3702                 mCurrentRawPointerData.hoveringIdBits.value);
  3704 #endif
  3706     // Reset state that we will compute below.
  3707     mCurrentFingerIdBits.clear();
  3708     mCurrentStylusIdBits.clear();
  3709     mCurrentMouseIdBits.clear();
  3710     mCurrentCookedPointerData.clear();
  3712     if (mDeviceMode == DEVICE_MODE_DISABLED) {
  3713         // Drop all input if the device is disabled.
  3714         mCurrentRawPointerData.clear();
  3715         mCurrentButtonState = 0;
  3716     } else {
  3717         // Preprocess pointer data.
  3718         if (!havePointerIds) {
  3719             assignPointerIds();
  3722         // Handle policy on initial down or hover events.
  3723         uint32_t policyFlags = 0;
  3724         bool initialDown = mLastRawPointerData.pointerCount == 0
  3725                 && mCurrentRawPointerData.pointerCount != 0;
  3726         bool buttonsPressed = mCurrentButtonState & ~mLastButtonState;
  3727         if (initialDown || buttonsPressed) {
  3728             // If this is a touch screen, hide the pointer on an initial down.
  3729             if (mDeviceMode == DEVICE_MODE_DIRECT) {
  3730                 getContext()->fadePointer();
  3733             // Initial downs on external touch devices should wake the device.
  3734             // We don't do this for internal touch screens to prevent them from waking
  3735             // up in your pocket.
  3736             // TODO: Use the input device configuration to control this behavior more finely.
  3737             if (getDevice()->isExternal()) {
  3738                 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
  3742         // Synthesize key down from raw buttons if needed.
  3743         synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
  3744                 policyFlags, mLastButtonState, mCurrentButtonState);
  3746         // Consume raw off-screen touches before cooking pointer data.
  3747         // If touches are consumed, subsequent code will not receive any pointer data.
  3748         if (consumeRawTouches(when, policyFlags)) {
  3749             mCurrentRawPointerData.clear();
  3752         // Cook pointer data.  This call populates the mCurrentCookedPointerData structure
  3753         // with cooked pointer data that has the same ids and indices as the raw data.
  3754         // The following code can use either the raw or cooked data, as needed.
  3755         cookPointerData();
  3757         // Dispatch the touches either directly or by translation through a pointer on screen.
  3758         if (mDeviceMode == DEVICE_MODE_POINTER) {
  3759             for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); !idBits.isEmpty(); ) {
  3760                 uint32_t id = idBits.clearFirstMarkedBit();
  3761                 const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
  3762                 if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
  3763                         || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
  3764                     mCurrentStylusIdBits.markBit(id);
  3765                 } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
  3766                         || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
  3767                     mCurrentFingerIdBits.markBit(id);
  3768                 } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
  3769                     mCurrentMouseIdBits.markBit(id);
  3772             for (BitSet32 idBits(mCurrentRawPointerData.hoveringIdBits); !idBits.isEmpty(); ) {
  3773                 uint32_t id = idBits.clearFirstMarkedBit();
  3774                 const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
  3775                 if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
  3776                         || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
  3777                     mCurrentStylusIdBits.markBit(id);
  3781             // Stylus takes precedence over all tools, then mouse, then finger.
  3782             PointerUsage pointerUsage = mPointerUsage;
  3783             if (!mCurrentStylusIdBits.isEmpty()) {
  3784                 mCurrentMouseIdBits.clear();
  3785                 mCurrentFingerIdBits.clear();
  3786                 pointerUsage = POINTER_USAGE_STYLUS;
  3787             } else if (!mCurrentMouseIdBits.isEmpty()) {
  3788                 mCurrentFingerIdBits.clear();
  3789                 pointerUsage = POINTER_USAGE_MOUSE;
  3790             } else if (!mCurrentFingerIdBits.isEmpty() || isPointerDown(mCurrentButtonState)) {
  3791                 pointerUsage = POINTER_USAGE_GESTURES;
  3794             dispatchPointerUsage(when, policyFlags, pointerUsage);
  3795         } else {
  3796             if (mDeviceMode == DEVICE_MODE_DIRECT
  3797                     && mConfig.showTouches && mPointerController != NULL) {
  3798                 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
  3799                 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
  3801                 mPointerController->setButtonState(mCurrentButtonState);
  3802                 mPointerController->setSpots(mCurrentCookedPointerData.pointerCoords,
  3803                         mCurrentCookedPointerData.idToIndex,
  3804                         mCurrentCookedPointerData.touchingIdBits);
  3807             dispatchHoverExit(when, policyFlags);
  3808             dispatchTouches(when, policyFlags);
  3809             dispatchHoverEnterAndMove(when, policyFlags);
  3812         // Synthesize key up from raw buttons if needed.
  3813         synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
  3814                 policyFlags, mLastButtonState, mCurrentButtonState);
  3817     // Copy current touch to last touch in preparation for the next cycle.
  3818     mLastRawPointerData.copyFrom(mCurrentRawPointerData);
  3819     mLastCookedPointerData.copyFrom(mCurrentCookedPointerData);
  3820     mLastButtonState = mCurrentButtonState;
  3821     mLastFingerIdBits = mCurrentFingerIdBits;
  3822     mLastStylusIdBits = mCurrentStylusIdBits;
  3823     mLastMouseIdBits = mCurrentMouseIdBits;
  3825     // Clear some transient state.
  3826     mCurrentRawVScroll = 0;
  3827     mCurrentRawHScroll = 0;
  3830 void TouchInputMapper::timeoutExpired(nsecs_t when) {
  3831     if (mDeviceMode == DEVICE_MODE_POINTER) {
  3832         if (mPointerUsage == POINTER_USAGE_GESTURES) {
  3833             dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
  3838 bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) {
  3839     // Check for release of a virtual key.
  3840     if (mCurrentVirtualKey.down) {
  3841         if (mCurrentRawPointerData.touchingIdBits.isEmpty()) {
  3842             // Pointer went up while virtual key was down.
  3843             mCurrentVirtualKey.down = false;
  3844             if (!mCurrentVirtualKey.ignored) {
  3845 #if DEBUG_VIRTUAL_KEYS
  3846                 ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
  3847                         mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
  3848 #endif
  3849                 dispatchVirtualKey(when, policyFlags,
  3850                         AKEY_EVENT_ACTION_UP,
  3851                         AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
  3853             return true;
  3856         if (mCurrentRawPointerData.touchingIdBits.count() == 1) {
  3857             uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit();
  3858             const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
  3859             const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
  3860             if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) {
  3861                 // Pointer is still within the space of the virtual key.
  3862                 return true;
  3866         // Pointer left virtual key area or another pointer also went down.
  3867         // Send key cancellation but do not consume the touch yet.
  3868         // This is useful when the user swipes through from the virtual key area
  3869         // into the main display surface.
  3870         mCurrentVirtualKey.down = false;
  3871         if (!mCurrentVirtualKey.ignored) {
  3872 #if DEBUG_VIRTUAL_KEYS
  3873             ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
  3874                     mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
  3875 #endif
  3876             dispatchVirtualKey(when, policyFlags,
  3877                     AKEY_EVENT_ACTION_UP,
  3878                     AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
  3879                             | AKEY_EVENT_FLAG_CANCELED);
  3883     if (mLastRawPointerData.touchingIdBits.isEmpty()
  3884             && !mCurrentRawPointerData.touchingIdBits.isEmpty()) {
  3885         // Pointer just went down.  Check for virtual key press or off-screen touches.
  3886         uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit();
  3887         const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
  3888         if (!isPointInsideSurface(pointer.x, pointer.y)) {
  3889             // If exactly one pointer went down, check for virtual key hit.
  3890             // Otherwise we will drop the entire stroke.
  3891             if (mCurrentRawPointerData.touchingIdBits.count() == 1) {
  3892                 const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
  3893                 if (virtualKey) {
  3894                     mCurrentVirtualKey.down = true;
  3895                     mCurrentVirtualKey.downTime = when;
  3896                     mCurrentVirtualKey.keyCode = virtualKey->keyCode;
  3897                     mCurrentVirtualKey.scanCode = virtualKey->scanCode;
  3898                     mCurrentVirtualKey.ignored = mContext->shouldDropVirtualKey(
  3899                             when, getDevice(), virtualKey->keyCode, virtualKey->scanCode);
  3901                     if (!mCurrentVirtualKey.ignored) {
  3902 #if DEBUG_VIRTUAL_KEYS
  3903                         ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
  3904                                 mCurrentVirtualKey.keyCode,
  3905                                 mCurrentVirtualKey.scanCode);
  3906 #endif
  3907                         dispatchVirtualKey(when, policyFlags,
  3908                                 AKEY_EVENT_ACTION_DOWN,
  3909                                 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
  3913             return true;
  3917     // Disable all virtual key touches that happen within a short time interval of the
  3918     // most recent touch within the screen area.  The idea is to filter out stray
  3919     // virtual key presses when interacting with the touch screen.
  3920     //
  3921     // Problems we're trying to solve:
  3922     //
  3923     // 1. While scrolling a list or dragging the window shade, the user swipes down into a
  3924     //    virtual key area that is implemented by a separate touch panel and accidentally
  3925     //    triggers a virtual key.
  3926     //
  3927     // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
  3928     //    area and accidentally triggers a virtual key.  This often happens when virtual keys
  3929     //    are layed out below the screen near to where the on screen keyboard's space bar
  3930     //    is displayed.
  3931     if (mConfig.virtualKeyQuietTime > 0 && !mCurrentRawPointerData.touchingIdBits.isEmpty()) {
  3932         mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime);
  3934     return false;
  3937 void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
  3938         int32_t keyEventAction, int32_t keyEventFlags) {
  3939     int32_t keyCode = mCurrentVirtualKey.keyCode;
  3940     int32_t scanCode = mCurrentVirtualKey.scanCode;
  3941     nsecs_t downTime = mCurrentVirtualKey.downTime;
  3942     int32_t metaState = mContext->getGlobalMetaState();
  3943     policyFlags |= POLICY_FLAG_VIRTUAL;
  3945     NotifyKeyArgs args(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
  3946             keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
  3947     getListener()->notifyKey(&args);
  3950 void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
  3951     BitSet32 currentIdBits = mCurrentCookedPointerData.touchingIdBits;
  3952     BitSet32 lastIdBits = mLastCookedPointerData.touchingIdBits;
  3953     int32_t metaState = getContext()->getGlobalMetaState();
  3954     int32_t buttonState = mCurrentButtonState;
  3956     if (currentIdBits == lastIdBits) {
  3957         if (!currentIdBits.isEmpty()) {
  3958             // No pointer id changes so this is a move event.
  3959             // The listener takes care of batching moves so we don't have to deal with that here.
  3960             dispatchMotion(when, policyFlags, mSource,
  3961                     AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState,
  3962                     AMOTION_EVENT_EDGE_FLAG_NONE,
  3963                     mCurrentCookedPointerData.pointerProperties,
  3964                     mCurrentCookedPointerData.pointerCoords,
  3965                     mCurrentCookedPointerData.idToIndex,
  3966                     currentIdBits, -1,
  3967                     mOrientedXPrecision, mOrientedYPrecision, mDownTime);
  3969     } else {
  3970         // There may be pointers going up and pointers going down and pointers moving
  3971         // all at the same time.
  3972         BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
  3973         BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
  3974         BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
  3975         BitSet32 dispatchedIdBits(lastIdBits.value);
  3977         // Update last coordinates of pointers that have moved so that we observe the new
  3978         // pointer positions at the same time as other pointers that have just gone up.
  3979         bool moveNeeded = updateMovedPointers(
  3980                 mCurrentCookedPointerData.pointerProperties,
  3981                 mCurrentCookedPointerData.pointerCoords,
  3982                 mCurrentCookedPointerData.idToIndex,
  3983                 mLastCookedPointerData.pointerProperties,
  3984                 mLastCookedPointerData.pointerCoords,
  3985                 mLastCookedPointerData.idToIndex,
  3986                 moveIdBits);
  3987         if (buttonState != mLastButtonState) {
  3988             moveNeeded = true;
  3991         // Dispatch pointer up events.
  3992         while (!upIdBits.isEmpty()) {
  3993             uint32_t upId = upIdBits.clearFirstMarkedBit();
  3995             dispatchMotion(when, policyFlags, mSource,
  3996                     AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0,
  3997                     mLastCookedPointerData.pointerProperties,
  3998                     mLastCookedPointerData.pointerCoords,
  3999                     mLastCookedPointerData.idToIndex,
  4000                     dispatchedIdBits, upId,
  4001                     mOrientedXPrecision, mOrientedYPrecision, mDownTime);
  4002             dispatchedIdBits.clearBit(upId);
  4005         // Dispatch move events if any of the remaining pointers moved from their old locations.
  4006         // Although applications receive new locations as part of individual pointer up
  4007         // events, they do not generally handle them except when presented in a move event.
  4008         if (moveNeeded) {
  4009             ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
  4010             dispatchMotion(when, policyFlags, mSource,
  4011                     AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0,
  4012                     mCurrentCookedPointerData.pointerProperties,
  4013                     mCurrentCookedPointerData.pointerCoords,
  4014                     mCurrentCookedPointerData.idToIndex,
  4015                     dispatchedIdBits, -1,
  4016                     mOrientedXPrecision, mOrientedYPrecision, mDownTime);
  4019         // Dispatch pointer down events using the new pointer locations.
  4020         while (!downIdBits.isEmpty()) {
  4021             uint32_t downId = downIdBits.clearFirstMarkedBit();
  4022             dispatchedIdBits.markBit(downId);
  4024             if (dispatchedIdBits.count() == 1) {
  4025                 // First pointer is going down.  Set down time.
  4026                 mDownTime = when;
  4029             dispatchMotion(when, policyFlags, mSource,
  4030                     AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
  4031                     mCurrentCookedPointerData.pointerProperties,
  4032                     mCurrentCookedPointerData.pointerCoords,
  4033                     mCurrentCookedPointerData.idToIndex,
  4034                     dispatchedIdBits, downId,
  4035                     mOrientedXPrecision, mOrientedYPrecision, mDownTime);
  4040 void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) {
  4041     if (mSentHoverEnter &&
  4042             (mCurrentCookedPointerData.hoveringIdBits.isEmpty()
  4043                     || !mCurrentCookedPointerData.touchingIdBits.isEmpty())) {
  4044         int32_t metaState = getContext()->getGlobalMetaState();
  4045         dispatchMotion(when, policyFlags, mSource,
  4046                 AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
  4047                 mLastCookedPointerData.pointerProperties,
  4048                 mLastCookedPointerData.pointerCoords,
  4049                 mLastCookedPointerData.idToIndex,
  4050                 mLastCookedPointerData.hoveringIdBits, -1,
  4051                 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
  4052         mSentHoverEnter = false;
  4056 void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) {
  4057     if (mCurrentCookedPointerData.touchingIdBits.isEmpty()
  4058             && !mCurrentCookedPointerData.hoveringIdBits.isEmpty()) {
  4059         int32_t metaState = getContext()->getGlobalMetaState();
  4060         if (!mSentHoverEnter) {
  4061             dispatchMotion(when, policyFlags, mSource,
  4062                     AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
  4063                     mCurrentCookedPointerData.pointerProperties,
  4064                     mCurrentCookedPointerData.pointerCoords,
  4065                     mCurrentCookedPointerData.idToIndex,
  4066                     mCurrentCookedPointerData.hoveringIdBits, -1,
  4067                     mOrientedXPrecision, mOrientedYPrecision, mDownTime);
  4068             mSentHoverEnter = true;
  4071         dispatchMotion(when, policyFlags, mSource,
  4072                 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
  4073                 mCurrentCookedPointerData.pointerProperties,
  4074                 mCurrentCookedPointerData.pointerCoords,
  4075                 mCurrentCookedPointerData.idToIndex,
  4076                 mCurrentCookedPointerData.hoveringIdBits, -1,
  4077                 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
  4081 void TouchInputMapper::cookPointerData() {
  4082     uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount;
  4084     mCurrentCookedPointerData.clear();
  4085     mCurrentCookedPointerData.pointerCount = currentPointerCount;
  4086     mCurrentCookedPointerData.hoveringIdBits = mCurrentRawPointerData.hoveringIdBits;
  4087     mCurrentCookedPointerData.touchingIdBits = mCurrentRawPointerData.touchingIdBits;
  4089     // Walk through the the active pointers and map device coordinates onto
  4090     // surface coordinates and adjust for display orientation.
  4091     for (uint32_t i = 0; i < currentPointerCount; i++) {
  4092         const RawPointerData::Pointer& in = mCurrentRawPointerData.pointers[i];
  4094         // Size
  4095         float touchMajor, touchMinor, toolMajor, toolMinor, size;
  4096         switch (mCalibration.sizeCalibration) {
  4097         case Calibration::SIZE_CALIBRATION_GEOMETRIC:
  4098         case Calibration::SIZE_CALIBRATION_DIAMETER:
  4099         case Calibration::SIZE_CALIBRATION_BOX:
  4100         case Calibration::SIZE_CALIBRATION_AREA:
  4101             if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
  4102                 touchMajor = in.touchMajor;
  4103                 touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
  4104                 toolMajor = in.toolMajor;
  4105                 toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
  4106                 size = mRawPointerAxes.touchMinor.valid
  4107                         ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
  4108             } else if (mRawPointerAxes.touchMajor.valid) {
  4109                 toolMajor = touchMajor = in.touchMajor;
  4110                 toolMinor = touchMinor = mRawPointerAxes.touchMinor.valid
  4111                         ? in.touchMinor : in.touchMajor;
  4112                 size = mRawPointerAxes.touchMinor.valid
  4113                         ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
  4114             } else if (mRawPointerAxes.toolMajor.valid) {
  4115                 touchMajor = toolMajor = in.toolMajor;
  4116                 touchMinor = toolMinor = mRawPointerAxes.toolMinor.valid
  4117                         ? in.toolMinor : in.toolMajor;
  4118                 size = mRawPointerAxes.toolMinor.valid
  4119                         ? avg(in.toolMajor, in.toolMinor) : in.toolMajor;
  4120             } else {
  4121                 ALOG_ASSERT(false, "No touch or tool axes.  "
  4122                         "Size calibration should have been resolved to NONE.");
  4123                 touchMajor = 0;
  4124                 touchMinor = 0;
  4125                 toolMajor = 0;
  4126                 toolMinor = 0;
  4127                 size = 0;
  4130             if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) {
  4131                 uint32_t touchingCount = mCurrentRawPointerData.touchingIdBits.count();
  4132                 if (touchingCount > 1) {
  4133                     touchMajor /= touchingCount;
  4134                     touchMinor /= touchingCount;
  4135                     toolMajor /= touchingCount;
  4136                     toolMinor /= touchingCount;
  4137                     size /= touchingCount;
  4141             if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) {
  4142                 touchMajor *= mGeometricScale;
  4143                 touchMinor *= mGeometricScale;
  4144                 toolMajor *= mGeometricScale;
  4145                 toolMinor *= mGeometricScale;
  4146             } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) {
  4147                 touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
  4148                 touchMinor = touchMajor;
  4149                 toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
  4150                 toolMinor = toolMajor;
  4151             } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) {
  4152                 touchMinor = touchMajor;
  4153                 toolMinor = toolMajor;
  4156             mCalibration.applySizeScaleAndBias(&touchMajor);
  4157             mCalibration.applySizeScaleAndBias(&touchMinor);
  4158             mCalibration.applySizeScaleAndBias(&toolMajor);
  4159             mCalibration.applySizeScaleAndBias(&toolMinor);
  4160             size *= mSizeScale;
  4161             break;
  4162         default:
  4163             touchMajor = 0;
  4164             touchMinor = 0;
  4165             toolMajor = 0;
  4166             toolMinor = 0;
  4167             size = 0;
  4168             break;
  4171         // Pressure
  4172         float pressure;
  4173         switch (mCalibration.pressureCalibration) {
  4174         case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
  4175         case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
  4176             pressure = in.pressure * mPressureScale;
  4177             break;
  4178         default:
  4179             pressure = in.isHovering ? 0 : 1;
  4180             break;
  4183         // Tilt and Orientation
  4184         float tilt;
  4185         float orientation;
  4186         if (mHaveTilt) {
  4187             float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;
  4188             float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;
  4189             orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
  4190             tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
  4191         } else {
  4192             tilt = 0;
  4194             switch (mCalibration.orientationCalibration) {
  4195             case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
  4196                 orientation = in.orientation * mOrientationScale;
  4197                 break;
  4198             case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
  4199                 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
  4200                 int32_t c2 = signExtendNybble(in.orientation & 0x0f);
  4201                 if (c1 != 0 || c2 != 0) {
  4202                     orientation = atan2f(c1, c2) * 0.5f;
  4203                     float confidence = hypotf(c1, c2);
  4204                     float scale = 1.0f + confidence / 16.0f;
  4205                     touchMajor *= scale;
  4206                     touchMinor /= scale;
  4207                     toolMajor *= scale;
  4208                     toolMinor /= scale;
  4209                 } else {
  4210                     orientation = 0;
  4212                 break;
  4214             default:
  4215                 orientation = 0;
  4219         // Distance
  4220         float distance;
  4221         switch (mCalibration.distanceCalibration) {
  4222         case Calibration::DISTANCE_CALIBRATION_SCALED:
  4223             distance = in.distance * mDistanceScale;
  4224             break;
  4225         default:
  4226             distance = 0;
  4229         // Coverage
  4230         int32_t rawLeft, rawTop, rawRight, rawBottom;
  4231         switch (mCalibration.coverageCalibration) {
  4232         case Calibration::COVERAGE_CALIBRATION_BOX:
  4233             rawLeft = (in.toolMinor & 0xffff0000) >> 16;
  4234             rawRight = in.toolMinor & 0x0000ffff;
  4235             rawBottom = in.toolMajor & 0x0000ffff;
  4236             rawTop = (in.toolMajor & 0xffff0000) >> 16;
  4237             break;
  4238         default:
  4239             rawLeft = rawTop = rawRight = rawBottom = 0;
  4240             break;
  4243         // X, Y, and the bounding box for coverage information
  4244         // Adjust coords for surface orientation.
  4245         float x, y, left, top, right, bottom;
  4246         switch (mSurfaceOrientation) {
  4247         case DISPLAY_ORIENTATION_90:
  4248             x = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
  4249             y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate;
  4250             left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
  4251             right = float(rawBottom- mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
  4252             bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
  4253             top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
  4254             orientation -= M_PI_2;
  4255             if (orientation < - M_PI_2) {
  4256                 orientation += M_PI;
  4258             break;
  4259         case DISPLAY_ORIENTATION_180:
  4260             x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate;
  4261             y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate;
  4262             left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
  4263             right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
  4264             bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
  4265             top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
  4266             break;
  4267         case DISPLAY_ORIENTATION_270:
  4268             x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate;
  4269             y = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
  4270             left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
  4271             right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
  4272             bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
  4273             top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
  4274             orientation += M_PI_2;
  4275             if (orientation > M_PI_2) {
  4276                 orientation -= M_PI;
  4278             break;
  4279         default:
  4280             x = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
  4281             y = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
  4282             left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
  4283             right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
  4284             bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
  4285             top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
  4286             break;
  4289         // Write output coords.
  4290         PointerCoords& out = mCurrentCookedPointerData.pointerCoords[i];
  4291         out.clear();
  4292         out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
  4293         out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
  4294         out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
  4295         out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
  4296         out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
  4297         out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
  4298         out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
  4299         out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
  4300         out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
  4301         if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
  4302             out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left);
  4303             out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top);
  4304             out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right);
  4305             out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_4, bottom);
  4306         } else {
  4307             out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
  4308             out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
  4311         // Write output properties.
  4312         PointerProperties& properties = mCurrentCookedPointerData.pointerProperties[i];
  4313         uint32_t id = in.id;
  4314         properties.clear();
  4315         properties.id = id;
  4316         properties.toolType = in.toolType;
  4318         // Write id index.
  4319         mCurrentCookedPointerData.idToIndex[id] = i;
  4323 void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags,
  4324         PointerUsage pointerUsage) {
  4325     if (pointerUsage != mPointerUsage) {
  4326         abortPointerUsage(when, policyFlags);
  4327         mPointerUsage = pointerUsage;
  4330     switch (mPointerUsage) {
  4331     case POINTER_USAGE_GESTURES:
  4332         dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
  4333         break;
  4334     case POINTER_USAGE_STYLUS:
  4335         dispatchPointerStylus(when, policyFlags);
  4336         break;
  4337     case POINTER_USAGE_MOUSE:
  4338         dispatchPointerMouse(when, policyFlags);
  4339         break;
  4340     default:
  4341         break;
  4345 void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) {
  4346     switch (mPointerUsage) {
  4347     case POINTER_USAGE_GESTURES:
  4348         abortPointerGestures(when, policyFlags);
  4349         break;
  4350     case POINTER_USAGE_STYLUS:
  4351         abortPointerStylus(when, policyFlags);
  4352         break;
  4353     case POINTER_USAGE_MOUSE:
  4354         abortPointerMouse(when, policyFlags);
  4355         break;
  4356     default:
  4357         break;
  4360     mPointerUsage = POINTER_USAGE_NONE;
  4363 void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
  4364         bool isTimeout) {
  4365     // Update current gesture coordinates.
  4366     bool cancelPreviousGesture, finishPreviousGesture;
  4367     bool sendEvents = preparePointerGestures(when,
  4368             &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
  4369     if (!sendEvents) {
  4370         return;
  4372     if (finishPreviousGesture) {
  4373         cancelPreviousGesture = false;
  4376     // Update the pointer presentation and spots.
  4377     if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
  4378         mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
  4379         if (finishPreviousGesture || cancelPreviousGesture) {
  4380             mPointerController->clearSpots();
  4382         mPointerController->setSpots(mPointerGesture.currentGestureCoords,
  4383                 mPointerGesture.currentGestureIdToIndex,
  4384                 mPointerGesture.currentGestureIdBits);
  4385     } else {
  4386         mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
  4389     // Show or hide the pointer if needed.
  4390     switch (mPointerGesture.currentGestureMode) {
  4391     case PointerGesture::NEUTRAL:
  4392     case PointerGesture::QUIET:
  4393         if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
  4394                 && (mPointerGesture.lastGestureMode == PointerGesture::SWIPE
  4395                         || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)) {
  4396             // Remind the user of where the pointer is after finishing a gesture with spots.
  4397             mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
  4399         break;
  4400     case PointerGesture::TAP:
  4401     case PointerGesture::TAP_DRAG:
  4402     case PointerGesture::BUTTON_CLICK_OR_DRAG:
  4403     case PointerGesture::HOVER:
  4404     case PointerGesture::PRESS:
  4405         // Unfade the pointer when the current gesture manipulates the
  4406         // area directly under the pointer.
  4407         mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
  4408         break;
  4409     case PointerGesture::SWIPE:
  4410     case PointerGesture::FREEFORM:
  4411         // Fade the pointer when the current gesture manipulates a different
  4412         // area and there are spots to guide the user experience.
  4413         if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
  4414             mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
  4415         } else {
  4416             mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
  4418         break;
  4421     // Send events!
  4422     int32_t metaState = getContext()->getGlobalMetaState();
  4423     int32_t buttonState = mCurrentButtonState;
  4425     // Update last coordinates of pointers that have moved so that we observe the new
  4426     // pointer positions at the same time as other pointers that have just gone up.
  4427     bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP
  4428             || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG
  4429             || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
  4430             || mPointerGesture.currentGestureMode == PointerGesture::PRESS
  4431             || mPointerGesture.currentGestureMode == PointerGesture::SWIPE
  4432             || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
  4433     bool moveNeeded = false;
  4434     if (down && !cancelPreviousGesture && !finishPreviousGesture
  4435             && !mPointerGesture.lastGestureIdBits.isEmpty()
  4436             && !mPointerGesture.currentGestureIdBits.isEmpty()) {
  4437         BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value
  4438                 & mPointerGesture.lastGestureIdBits.value);
  4439         moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties,
  4440                 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
  4441                 mPointerGesture.lastGestureProperties,
  4442                 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
  4443                 movedGestureIdBits);
  4444         if (buttonState != mLastButtonState) {
  4445             moveNeeded = true;
  4449     // Send motion events for all pointers that went up or were canceled.
  4450     BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
  4451     if (!dispatchedGestureIdBits.isEmpty()) {
  4452         if (cancelPreviousGesture) {
  4453             dispatchMotion(when, policyFlags, mSource,
  4454                     AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
  4455                     AMOTION_EVENT_EDGE_FLAG_NONE,
  4456                     mPointerGesture.lastGestureProperties,
  4457                     mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
  4458                     dispatchedGestureIdBits, -1,
  4459                     0, 0, mPointerGesture.downTime);
  4461             dispatchedGestureIdBits.clear();
  4462         } else {
  4463             BitSet32 upGestureIdBits;
  4464             if (finishPreviousGesture) {
  4465                 upGestureIdBits = dispatchedGestureIdBits;
  4466             } else {
  4467                 upGestureIdBits.value = dispatchedGestureIdBits.value
  4468                         & ~mPointerGesture.currentGestureIdBits.value;
  4470             while (!upGestureIdBits.isEmpty()) {
  4471                 uint32_t id = upGestureIdBits.clearFirstMarkedBit();
  4473                 dispatchMotion(when, policyFlags, mSource,
  4474                         AMOTION_EVENT_ACTION_POINTER_UP, 0,
  4475                         metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
  4476                         mPointerGesture.lastGestureProperties,
  4477                         mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
  4478                         dispatchedGestureIdBits, id,
  4479                         0, 0, mPointerGesture.downTime);
  4481                 dispatchedGestureIdBits.clearBit(id);
  4486     // Send motion events for all pointers that moved.
  4487     if (moveNeeded) {
  4488         dispatchMotion(when, policyFlags, mSource,
  4489                 AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
  4490                 mPointerGesture.currentGestureProperties,
  4491                 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
  4492                 dispatchedGestureIdBits, -1,
  4493                 0, 0, mPointerGesture.downTime);
  4496     // Send motion events for all pointers that went down.
  4497     if (down) {
  4498         BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value
  4499                 & ~dispatchedGestureIdBits.value);
  4500         while (!downGestureIdBits.isEmpty()) {
  4501             uint32_t id = downGestureIdBits.clearFirstMarkedBit();
  4502             dispatchedGestureIdBits.markBit(id);
  4504             if (dispatchedGestureIdBits.count() == 1) {
  4505                 mPointerGesture.downTime = when;
  4508             dispatchMotion(when, policyFlags, mSource,
  4509                     AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
  4510                     mPointerGesture.currentGestureProperties,
  4511                     mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
  4512                     dispatchedGestureIdBits, id,
  4513                     0, 0, mPointerGesture.downTime);
  4517     // Send motion events for hover.
  4518     if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
  4519         dispatchMotion(when, policyFlags, mSource,
  4520                 AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
  4521                 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
  4522                 mPointerGesture.currentGestureProperties,
  4523                 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
  4524                 mPointerGesture.currentGestureIdBits, -1,
  4525                 0, 0, mPointerGesture.downTime);
  4526     } else if (dispatchedGestureIdBits.isEmpty()
  4527             && !mPointerGesture.lastGestureIdBits.isEmpty()) {
  4528         // Synthesize a hover move event after all pointers go up to indicate that
  4529         // the pointer is hovering again even if the user is not currently touching
  4530         // the touch pad.  This ensures that a view will receive a fresh hover enter
  4531         // event after a tap.
  4532         float x, y;
  4533         mPointerController->getPosition(&x, &y);
  4535         PointerProperties pointerProperties;
  4536         pointerProperties.clear();
  4537         pointerProperties.id = 0;
  4538         pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
  4540         PointerCoords pointerCoords;
  4541         pointerCoords.clear();
  4542         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
  4543         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
  4545         NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
  4546                 AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
  4547                 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
  4548                 mViewport.displayId, 1, &pointerProperties, &pointerCoords,
  4549                 0, 0, mPointerGesture.downTime);
  4550         getListener()->notifyMotion(&args);
  4553     // Update state.
  4554     mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
  4555     if (!down) {
  4556         mPointerGesture.lastGestureIdBits.clear();
  4557     } else {
  4558         mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
  4559         for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) {
  4560             uint32_t id = idBits.clearFirstMarkedBit();
  4561             uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
  4562             mPointerGesture.lastGestureProperties[index].copyFrom(
  4563                     mPointerGesture.currentGestureProperties[index]);
  4564             mPointerGesture.lastGestureCoords[index].copyFrom(
  4565                     mPointerGesture.currentGestureCoords[index]);
  4566             mPointerGesture.lastGestureIdToIndex[id] = index;
  4571 void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) {
  4572     // Cancel previously dispatches pointers.
  4573     if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
  4574         int32_t metaState = getContext()->getGlobalMetaState();
  4575         int32_t buttonState = mCurrentButtonState;
  4576         dispatchMotion(when, policyFlags, mSource,
  4577                 AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
  4578                 AMOTION_EVENT_EDGE_FLAG_NONE,
  4579                 mPointerGesture.lastGestureProperties,
  4580                 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
  4581                 mPointerGesture.lastGestureIdBits, -1,
  4582                 0, 0, mPointerGesture.downTime);
  4585     // Reset the current pointer gesture.
  4586     mPointerGesture.reset();
  4587     mPointerVelocityControl.reset();
  4589     // Remove any current spots.
  4590     if (mPointerController != NULL) {
  4591         mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
  4592         mPointerController->clearSpots();
  4596 bool TouchInputMapper::preparePointerGestures(nsecs_t when,
  4597         bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
  4598     *outCancelPreviousGesture = false;
  4599     *outFinishPreviousGesture = false;
  4601     // Handle TAP timeout.
  4602     if (isTimeout) {
  4603 #if DEBUG_GESTURES
  4604         ALOGD("Gestures: Processing timeout");
  4605 #endif
  4607         if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
  4608             if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
  4609                 // The tap/drag timeout has not yet expired.
  4610                 getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime
  4611                         + mConfig.pointerGestureTapDragInterval);
  4612             } else {
  4613                 // The tap is finished.
  4614 #if DEBUG_GESTURES
  4615                 ALOGD("Gestures: TAP finished");
  4616 #endif
  4617                 *outFinishPreviousGesture = true;
  4619                 mPointerGesture.activeGestureId = -1;
  4620                 mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
  4621                 mPointerGesture.currentGestureIdBits.clear();
  4623                 mPointerVelocityControl.reset();
  4624                 return true;
  4628         // We did not handle this timeout.
  4629         return false;
  4632     const uint32_t currentFingerCount = mCurrentFingerIdBits.count();
  4633     const uint32_t lastFingerCount = mLastFingerIdBits.count();
  4635     // Update the velocity tracker.
  4637         VelocityTracker::Position positions[MAX_POINTERS];
  4638         uint32_t count = 0;
  4639         for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); count++) {
  4640             uint32_t id = idBits.clearFirstMarkedBit();
  4641             const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
  4642             positions[count].x = pointer.x * mPointerXMovementScale;
  4643             positions[count].y = pointer.y * mPointerYMovementScale;
  4645         mPointerGesture.velocityTracker.addMovement(when,
  4646                 mCurrentFingerIdBits, positions);
  4649     // Pick a new active touch id if needed.
  4650     // Choose an arbitrary pointer that just went down, if there is one.
  4651     // Otherwise choose an arbitrary remaining pointer.
  4652     // This guarantees we always have an active touch id when there is at least one pointer.
  4653     // We keep the same active touch id for as long as possible.
  4654     bool activeTouchChanged = false;
  4655     int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
  4656     int32_t activeTouchId = lastActiveTouchId;
  4657     if (activeTouchId < 0) {
  4658         if (!mCurrentFingerIdBits.isEmpty()) {
  4659             activeTouchChanged = true;
  4660             activeTouchId = mPointerGesture.activeTouchId =
  4661                     mCurrentFingerIdBits.firstMarkedBit();
  4662             mPointerGesture.firstTouchTime = when;
  4664     } else if (!mCurrentFingerIdBits.hasBit(activeTouchId)) {
  4665         activeTouchChanged = true;
  4666         if (!mCurrentFingerIdBits.isEmpty()) {
  4667             activeTouchId = mPointerGesture.activeTouchId =
  4668                     mCurrentFingerIdBits.firstMarkedBit();
  4669         } else {
  4670             activeTouchId = mPointerGesture.activeTouchId = -1;
  4674     // Determine whether we are in quiet time.
  4675     bool isQuietTime = false;
  4676     if (activeTouchId < 0) {
  4677         mPointerGesture.resetQuietTime();
  4678     } else {
  4679         isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval;
  4680         if (!isQuietTime) {
  4681             if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
  4682                     || mPointerGesture.lastGestureMode == PointerGesture::SWIPE
  4683                     || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)
  4684                     && currentFingerCount < 2) {
  4685                 // Enter quiet time when exiting swipe or freeform state.
  4686                 // This is to prevent accidentally entering the hover state and flinging the
  4687                 // pointer when finishing a swipe and there is still one pointer left onscreen.
  4688                 isQuietTime = true;
  4689             } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
  4690                     && currentFingerCount >= 2
  4691                     && !isPointerDown(mCurrentButtonState)) {
  4692                 // Enter quiet time when releasing the button and there are still two or more
  4693                 // fingers down.  This may indicate that one finger was used to press the button
  4694                 // but it has not gone up yet.
  4695                 isQuietTime = true;
  4697             if (isQuietTime) {
  4698                 mPointerGesture.quietTime = when;
  4703     // Switch states based on button and pointer state.
  4704     if (isQuietTime) {
  4705         // Case 1: Quiet time. (QUIET)
  4706 #if DEBUG_GESTURES
  4707         ALOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime
  4708                 + mConfig.pointerGestureQuietInterval - when) * 0.000001f);
  4709 #endif
  4710         if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
  4711             *outFinishPreviousGesture = true;
  4714         mPointerGesture.activeGestureId = -1;
  4715         mPointerGesture.currentGestureMode = PointerGesture::QUIET;
  4716         mPointerGesture.currentGestureIdBits.clear();
  4718         mPointerVelocityControl.reset();
  4719     } else if (isPointerDown(mCurrentButtonState)) {
  4720         // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
  4721         // The pointer follows the active touch point.
  4722         // Emit DOWN, MOVE, UP events at the pointer location.
  4723         //
  4724         // Only the active touch matters; other fingers are ignored.  This policy helps
  4725         // to handle the case where the user places a second finger on the touch pad
  4726         // to apply the necessary force to depress an integrated button below the surface.
  4727         // We don't want the second finger to be delivered to applications.
  4728         //
  4729         // For this to work well, we need to make sure to track the pointer that is really
  4730         // active.  If the user first puts one finger down to click then adds another
  4731         // finger to drag then the active pointer should switch to the finger that is
  4732         // being dragged.
  4733 #if DEBUG_GESTURES
  4734         ALOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
  4735                 "currentFingerCount=%d", activeTouchId, currentFingerCount);
  4736 #endif
  4737         // Reset state when just starting.
  4738         if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
  4739             *outFinishPreviousGesture = true;
  4740             mPointerGesture.activeGestureId = 0;
  4743         // Switch pointers if needed.
  4744         // Find the fastest pointer and follow it.
  4745         if (activeTouchId >= 0 && currentFingerCount > 1) {
  4746             int32_t bestId = -1;
  4747             float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
  4748             for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); ) {
  4749                 uint32_t id = idBits.clearFirstMarkedBit();
  4750                 float vx, vy;
  4751                 if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
  4752                     float speed = hypotf(vx, vy);
  4753                     if (speed > bestSpeed) {
  4754                         bestId = id;
  4755                         bestSpeed = speed;
  4759             if (bestId >= 0 && bestId != activeTouchId) {
  4760                 mPointerGesture.activeTouchId = activeTouchId = bestId;
  4761                 activeTouchChanged = true;
  4762 #if DEBUG_GESTURES
  4763                 ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
  4764                         "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
  4765 #endif
  4769         if (activeTouchId >= 0 && mLastFingerIdBits.hasBit(activeTouchId)) {
  4770             const RawPointerData::Pointer& currentPointer =
  4771                     mCurrentRawPointerData.pointerForId(activeTouchId);
  4772             const RawPointerData::Pointer& lastPointer =
  4773                     mLastRawPointerData.pointerForId(activeTouchId);
  4774             float deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
  4775             float deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
  4777             rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
  4778             mPointerVelocityControl.move(when, &deltaX, &deltaY);
  4780             // Move the pointer using a relative motion.
  4781             // When using spots, the click will occur at the position of the anchor
  4782             // spot and all other spots will move there.
  4783             mPointerController->move(deltaX, deltaY);
  4784         } else {
  4785             mPointerVelocityControl.reset();
  4788         float x, y;
  4789         mPointerController->getPosition(&x, &y);
  4791         mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
  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 = AMOTION_EVENT_TOOL_TYPE_FINGER;
  4798         mPointerGesture.currentGestureCoords[0].clear();
  4799         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
  4800         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
  4801         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
  4802     } else if (currentFingerCount == 0) {
  4803         // Case 3. No fingers down and button is not pressed. (NEUTRAL)
  4804         if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
  4805             *outFinishPreviousGesture = true;
  4808         // Watch for taps coming out of HOVER or TAP_DRAG mode.
  4809         // Checking for taps after TAP_DRAG allows us to detect double-taps.
  4810         bool tapped = false;
  4811         if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
  4812                 || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
  4813                 && lastFingerCount == 1) {
  4814             if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
  4815                 float x, y;
  4816                 mPointerController->getPosition(&x, &y);
  4817                 if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
  4818                         && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
  4819 #if DEBUG_GESTURES
  4820                     ALOGD("Gestures: TAP");
  4821 #endif
  4823                     mPointerGesture.tapUpTime = when;
  4824                     getContext()->requestTimeoutAtTime(when
  4825                             + mConfig.pointerGestureTapDragInterval);
  4827                     mPointerGesture.activeGestureId = 0;
  4828                     mPointerGesture.currentGestureMode = PointerGesture::TAP;
  4829                     mPointerGesture.currentGestureIdBits.clear();
  4830                     mPointerGesture.currentGestureIdBits.markBit(
  4831                             mPointerGesture.activeGestureId);
  4832                     mPointerGesture.currentGestureIdToIndex[
  4833                             mPointerGesture.activeGestureId] = 0;
  4834                     mPointerGesture.currentGestureProperties[0].clear();
  4835                     mPointerGesture.currentGestureProperties[0].id =
  4836                             mPointerGesture.activeGestureId;
  4837                     mPointerGesture.currentGestureProperties[0].toolType =
  4838                             AMOTION_EVENT_TOOL_TYPE_FINGER;
  4839                     mPointerGesture.currentGestureCoords[0].clear();
  4840                     mPointerGesture.currentGestureCoords[0].setAxisValue(
  4841                             AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
  4842                     mPointerGesture.currentGestureCoords[0].setAxisValue(
  4843                             AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY);
  4844                     mPointerGesture.currentGestureCoords[0].setAxisValue(
  4845                             AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
  4847                     tapped = true;
  4848                 } else {
  4849 #if DEBUG_GESTURES
  4850                     ALOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f",
  4851                             x - mPointerGesture.tapX,
  4852                             y - mPointerGesture.tapY);
  4853 #endif
  4855             } else {
  4856 #if DEBUG_GESTURES
  4857                 ALOGD("Gestures: Not a TAP, %0.3fms since down",
  4858                         (when - mPointerGesture.tapDownTime) * 0.000001f);
  4859 #endif
  4863         mPointerVelocityControl.reset();
  4865         if (!tapped) {
  4866 #if DEBUG_GESTURES
  4867             ALOGD("Gestures: NEUTRAL");
  4868 #endif
  4869             mPointerGesture.activeGestureId = -1;
  4870             mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
  4871             mPointerGesture.currentGestureIdBits.clear();
  4873     } else if (currentFingerCount == 1) {
  4874         // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
  4875         // The pointer follows the active touch point.
  4876         // When in HOVER, emit HOVER_MOVE events at the pointer location.
  4877         // When in TAP_DRAG, emit MOVE events at the pointer location.
  4878         ALOG_ASSERT(activeTouchId >= 0);
  4880         mPointerGesture.currentGestureMode = PointerGesture::HOVER;
  4881         if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
  4882             if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
  4883                 float x, y;
  4884                 mPointerController->getPosition(&x, &y);
  4885                 if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
  4886                         && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
  4887                     mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
  4888                 } else {
  4889 #if DEBUG_GESTURES
  4890                     ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
  4891                             x - mPointerGesture.tapX,
  4892                             y - mPointerGesture.tapY);
  4893 #endif
  4895             } else {
  4896 #if DEBUG_GESTURES
  4897                 ALOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
  4898                         (when - mPointerGesture.tapUpTime) * 0.000001f);
  4899 #endif
  4901         } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
  4902             mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
  4905         if (mLastFingerIdBits.hasBit(activeTouchId)) {
  4906             const RawPointerData::Pointer& currentPointer =
  4907                     mCurrentRawPointerData.pointerForId(activeTouchId);
  4908             const RawPointerData::Pointer& lastPointer =
  4909                     mLastRawPointerData.pointerForId(activeTouchId);
  4910             float deltaX = (currentPointer.x - lastPointer.x)
  4911                     * mPointerXMovementScale;
  4912             float deltaY = (currentPointer.y - lastPointer.y)
  4913                     * mPointerYMovementScale;
  4915             rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
  4916             mPointerVelocityControl.move(when, &deltaX, &deltaY);
  4918             // Move the pointer using a relative motion.
  4919             // When using spots, the hover or drag will occur at the position of the anchor spot.
  4920             mPointerController->move(deltaX, deltaY);
  4921         } else {
  4922             mPointerVelocityControl.reset();
  4925         bool down;
  4926         if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
  4927 #if DEBUG_GESTURES
  4928             ALOGD("Gestures: TAP_DRAG");
  4929 #endif
  4930             down = true;
  4931         } else {
  4932 #if DEBUG_GESTURES
  4933             ALOGD("Gestures: HOVER");
  4934 #endif
  4935             if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
  4936                 *outFinishPreviousGesture = true;
  4938             mPointerGesture.activeGestureId = 0;
  4939             down = false;
  4942         float x, y;
  4943         mPointerController->getPosition(&x, &y);
  4945         mPointerGesture.currentGestureIdBits.clear();
  4946         mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
  4947         mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
  4948         mPointerGesture.currentGestureProperties[0].clear();
  4949         mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
  4950         mPointerGesture.currentGestureProperties[0].toolType =
  4951                 AMOTION_EVENT_TOOL_TYPE_FINGER;
  4952         mPointerGesture.currentGestureCoords[0].clear();
  4953         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
  4954         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
  4955         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
  4956                 down ? 1.0f : 0.0f);
  4958         if (lastFingerCount == 0 && currentFingerCount != 0) {
  4959             mPointerGesture.resetTap();
  4960             mPointerGesture.tapDownTime = when;
  4961             mPointerGesture.tapX = x;
  4962             mPointerGesture.tapY = y;
  4964     } else {
  4965         // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
  4966         // We need to provide feedback for each finger that goes down so we cannot wait
  4967         // for the fingers to move before deciding what to do.
  4968         //
  4969         // The ambiguous case is deciding what to do when there are two fingers down but they
  4970         // have not moved enough to determine whether they are part of a drag or part of a
  4971         // freeform gesture, or just a press or long-press at the pointer location.
  4972         //
  4973         // When there are two fingers we start with the PRESS hypothesis and we generate a
  4974         // down at the pointer location.
  4975         //
  4976         // When the two fingers move enough or when additional fingers are added, we make
  4977         // a decision to transition into SWIPE or FREEFORM mode accordingly.
  4978         ALOG_ASSERT(activeTouchId >= 0);
  4980         bool settled = when >= mPointerGesture.firstTouchTime
  4981                 + mConfig.pointerGestureMultitouchSettleInterval;
  4982         if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
  4983                 && mPointerGesture.lastGestureMode != PointerGesture::SWIPE
  4984                 && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
  4985             *outFinishPreviousGesture = true;
  4986         } else if (!settled && currentFingerCount > lastFingerCount) {
  4987             // Additional pointers have gone down but not yet settled.
  4988             // Reset the gesture.
  4989 #if DEBUG_GESTURES
  4990             ALOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
  4991                     "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
  4992                             + mConfig.pointerGestureMultitouchSettleInterval - when)
  4993                             * 0.000001f);
  4994 #endif
  4995             *outCancelPreviousGesture = true;
  4996         } else {
  4997             // Continue previous gesture.
  4998             mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
  5001         if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
  5002             mPointerGesture.currentGestureMode = PointerGesture::PRESS;
  5003             mPointerGesture.activeGestureId = 0;
  5004             mPointerGesture.referenceIdBits.clear();
  5005             mPointerVelocityControl.reset();
  5007             // Use the centroid and pointer location as the reference points for the gesture.
  5008 #if DEBUG_GESTURES
  5009             ALOGD("Gestures: Using centroid as reference for MULTITOUCH, "
  5010                     "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
  5011                             + mConfig.pointerGestureMultitouchSettleInterval - when)
  5012                             * 0.000001f);
  5013 #endif
  5014             mCurrentRawPointerData.getCentroidOfTouchingPointers(
  5015                     &mPointerGesture.referenceTouchX,
  5016                     &mPointerGesture.referenceTouchY);
  5017             mPointerController->getPosition(&mPointerGesture.referenceGestureX,
  5018                     &mPointerGesture.referenceGestureY);
  5021         // Clear the reference deltas for fingers not yet included in the reference calculation.
  5022         for (BitSet32 idBits(mCurrentFingerIdBits.value
  5023                 & ~mPointerGesture.referenceIdBits.value); !idBits.isEmpty(); ) {
  5024             uint32_t id = idBits.clearFirstMarkedBit();
  5025             mPointerGesture.referenceDeltas[id].dx = 0;
  5026             mPointerGesture.referenceDeltas[id].dy = 0;
  5028         mPointerGesture.referenceIdBits = mCurrentFingerIdBits;
  5030         // Add delta for all fingers and calculate a common movement delta.
  5031         float commonDeltaX = 0, commonDeltaY = 0;
  5032         BitSet32 commonIdBits(mLastFingerIdBits.value
  5033                 & mCurrentFingerIdBits.value);
  5034         for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
  5035             bool first = (idBits == commonIdBits);
  5036             uint32_t id = idBits.clearFirstMarkedBit();
  5037             const RawPointerData::Pointer& cpd = mCurrentRawPointerData.pointerForId(id);
  5038             const RawPointerData::Pointer& lpd = mLastRawPointerData.pointerForId(id);
  5039             PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
  5040             delta.dx += cpd.x - lpd.x;
  5041             delta.dy += cpd.y - lpd.y;
  5043             if (first) {
  5044                 commonDeltaX = delta.dx;
  5045                 commonDeltaY = delta.dy;
  5046             } else {
  5047                 commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
  5048                 commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
  5052         // Consider transitions from PRESS to SWIPE or MULTITOUCH.
  5053         if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
  5054             float dist[MAX_POINTER_ID + 1];
  5055             int32_t distOverThreshold = 0;
  5056             for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
  5057                 uint32_t id = idBits.clearFirstMarkedBit();
  5058                 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
  5059                 dist[id] = hypotf(delta.dx * mPointerXZoomScale,
  5060                         delta.dy * mPointerYZoomScale);
  5061                 if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) {
  5062                     distOverThreshold += 1;
  5066             // Only transition when at least two pointers have moved further than
  5067             // the minimum distance threshold.
  5068             if (distOverThreshold >= 2) {
  5069                 if (currentFingerCount > 2) {
  5070                     // There are more than two pointers, switch to FREEFORM.
  5071 #if DEBUG_GESTURES
  5072                     ALOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
  5073                             currentFingerCount);
  5074 #endif
  5075                     *outCancelPreviousGesture = true;
  5076                     mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
  5077                 } else {
  5078                     // There are exactly two pointers.
  5079                     BitSet32 idBits(mCurrentFingerIdBits);
  5080                     uint32_t id1 = idBits.clearFirstMarkedBit();
  5081                     uint32_t id2 = idBits.firstMarkedBit();
  5082                     const RawPointerData::Pointer& p1 = mCurrentRawPointerData.pointerForId(id1);
  5083                     const RawPointerData::Pointer& p2 = mCurrentRawPointerData.pointerForId(id2);
  5084                     float mutualDistance = distance(p1.x, p1.y, p2.x, p2.y);
  5085                     if (mutualDistance > mPointerGestureMaxSwipeWidth) {
  5086                         // There are two pointers but they are too far apart for a SWIPE,
  5087                         // switch to FREEFORM.
  5088 #if DEBUG_GESTURES
  5089                         ALOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
  5090                                 mutualDistance, mPointerGestureMaxSwipeWidth);
  5091 #endif
  5092                         *outCancelPreviousGesture = true;
  5093                         mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
  5094                     } else {
  5095                         // There are two pointers.  Wait for both pointers to start moving
  5096                         // before deciding whether this is a SWIPE or FREEFORM gesture.
  5097                         float dist1 = dist[id1];
  5098                         float dist2 = dist[id2];
  5099                         if (dist1 >= mConfig.pointerGestureMultitouchMinDistance
  5100                                 && dist2 >= mConfig.pointerGestureMultitouchMinDistance) {
  5101                             // Calculate the dot product of the displacement vectors.
  5102                             // When the vectors are oriented in approximately the same direction,
  5103                             // the angle betweeen them is near zero and the cosine of the angle
  5104                             // approches 1.0.  Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
  5105                             PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
  5106                             PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
  5107                             float dx1 = delta1.dx * mPointerXZoomScale;
  5108                             float dy1 = delta1.dy * mPointerYZoomScale;
  5109                             float dx2 = delta2.dx * mPointerXZoomScale;
  5110                             float dy2 = delta2.dy * mPointerYZoomScale;
  5111                             float dot = dx1 * dx2 + dy1 * dy2;
  5112                             float cosine = dot / (dist1 * dist2); // denominator always > 0
  5113                             if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
  5114                                 // Pointers are moving in the same direction.  Switch to SWIPE.
  5115 #if DEBUG_GESTURES
  5116                                 ALOGD("Gestures: PRESS transitioned to SWIPE, "
  5117                                         "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
  5118                                         "cosine %0.3f >= %0.3f",
  5119                                         dist1, mConfig.pointerGestureMultitouchMinDistance,
  5120                                         dist2, mConfig.pointerGestureMultitouchMinDistance,
  5121                                         cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
  5122 #endif
  5123                                 mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
  5124                             } else {
  5125                                 // Pointers are moving in different directions.  Switch to FREEFORM.
  5126 #if DEBUG_GESTURES
  5127                                 ALOGD("Gestures: PRESS transitioned to FREEFORM, "
  5128                                         "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
  5129                                         "cosine %0.3f < %0.3f",
  5130                                         dist1, mConfig.pointerGestureMultitouchMinDistance,
  5131                                         dist2, mConfig.pointerGestureMultitouchMinDistance,
  5132                                         cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
  5133 #endif
  5134                                 *outCancelPreviousGesture = true;
  5135                                 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
  5141         } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
  5142             // Switch from SWIPE to FREEFORM if additional pointers go down.
  5143             // Cancel previous gesture.
  5144             if (currentFingerCount > 2) {
  5145 #if DEBUG_GESTURES
  5146                 ALOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
  5147                         currentFingerCount);
  5148 #endif
  5149                 *outCancelPreviousGesture = true;
  5150                 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
  5154         // Move the reference points based on the overall group motion of the fingers
  5155         // except in PRESS mode while waiting for a transition to occur.
  5156         if (mPointerGesture.currentGestureMode != PointerGesture::PRESS
  5157                 && (commonDeltaX || commonDeltaY)) {
  5158             for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
  5159                 uint32_t id = idBits.clearFirstMarkedBit();
  5160                 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
  5161                 delta.dx = 0;
  5162                 delta.dy = 0;
  5165             mPointerGesture.referenceTouchX += commonDeltaX;
  5166             mPointerGesture.referenceTouchY += commonDeltaY;
  5168             commonDeltaX *= mPointerXMovementScale;
  5169             commonDeltaY *= mPointerYMovementScale;
  5171             rotateDelta(mSurfaceOrientation, &commonDeltaX, &commonDeltaY);
  5172             mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
  5174             mPointerGesture.referenceGestureX += commonDeltaX;
  5175             mPointerGesture.referenceGestureY += commonDeltaY;
  5178         // Report gestures.
  5179         if (mPointerGesture.currentGestureMode == PointerGesture::PRESS
  5180                 || mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
  5181             // PRESS or SWIPE mode.
  5182 #if DEBUG_GESTURES
  5183             ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
  5184                     "activeGestureId=%d, currentTouchPointerCount=%d",
  5185                     activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
  5186 #endif
  5187             ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
  5189             mPointerGesture.currentGestureIdBits.clear();
  5190             mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
  5191             mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
  5192             mPointerGesture.currentGestureProperties[0].clear();
  5193             mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
  5194             mPointerGesture.currentGestureProperties[0].toolType =
  5195                     AMOTION_EVENT_TOOL_TYPE_FINGER;
  5196             mPointerGesture.currentGestureCoords[0].clear();
  5197             mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
  5198                     mPointerGesture.referenceGestureX);
  5199             mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
  5200                     mPointerGesture.referenceGestureY);
  5201             mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
  5202         } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
  5203             // FREEFORM mode.
  5204 #if DEBUG_GESTURES
  5205             ALOGD("Gestures: FREEFORM activeTouchId=%d,"
  5206                     "activeGestureId=%d, currentTouchPointerCount=%d",
  5207                     activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
  5208 #endif
  5209             ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
  5211             mPointerGesture.currentGestureIdBits.clear();
  5213             BitSet32 mappedTouchIdBits;
  5214             BitSet32 usedGestureIdBits;
  5215             if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
  5216                 // Initially, assign the active gesture id to the active touch point
  5217                 // if there is one.  No other touch id bits are mapped yet.
  5218                 if (!*outCancelPreviousGesture) {
  5219                     mappedTouchIdBits.markBit(activeTouchId);
  5220                     usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
  5221                     mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
  5222                             mPointerGesture.activeGestureId;
  5223                 } else {
  5224                     mPointerGesture.activeGestureId = -1;
  5226             } else {
  5227                 // Otherwise, assume we mapped all touches from the previous frame.
  5228                 // Reuse all mappings that are still applicable.
  5229                 mappedTouchIdBits.value = mLastFingerIdBits.value
  5230                         & mCurrentFingerIdBits.value;
  5231                 usedGestureIdBits = mPointerGesture.lastGestureIdBits;
  5233                 // Check whether we need to choose a new active gesture id because the
  5234                 // current went went up.
  5235                 for (BitSet32 upTouchIdBits(mLastFingerIdBits.value
  5236                         & ~mCurrentFingerIdBits.value);
  5237                         !upTouchIdBits.isEmpty(); ) {
  5238                     uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit();
  5239                     uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
  5240                     if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
  5241                         mPointerGesture.activeGestureId = -1;
  5242                         break;
  5247 #if DEBUG_GESTURES
  5248             ALOGD("Gestures: FREEFORM follow up "
  5249                     "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
  5250                     "activeGestureId=%d",
  5251                     mappedTouchIdBits.value, usedGestureIdBits.value,
  5252                     mPointerGesture.activeGestureId);
  5253 #endif
  5255             BitSet32 idBits(mCurrentFingerIdBits);
  5256             for (uint32_t i = 0; i < currentFingerCount; i++) {
  5257                 uint32_t touchId = idBits.clearFirstMarkedBit();
  5258                 uint32_t gestureId;
  5259                 if (!mappedTouchIdBits.hasBit(touchId)) {
  5260                     gestureId = usedGestureIdBits.markFirstUnmarkedBit();
  5261                     mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
  5262 #if DEBUG_GESTURES
  5263                     ALOGD("Gestures: FREEFORM "
  5264                             "new mapping for touch id %d -> gesture id %d",
  5265                             touchId, gestureId);
  5266 #endif
  5267                 } else {
  5268                     gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
  5269 #if DEBUG_GESTURES
  5270                     ALOGD("Gestures: FREEFORM "
  5271                             "existing mapping for touch id %d -> gesture id %d",
  5272                             touchId, gestureId);
  5273 #endif
  5275                 mPointerGesture.currentGestureIdBits.markBit(gestureId);
  5276                 mPointerGesture.currentGestureIdToIndex[gestureId] = i;
  5278                 const RawPointerData::Pointer& pointer =
  5279                         mCurrentRawPointerData.pointerForId(touchId);
  5280                 float deltaX = (pointer.x - mPointerGesture.referenceTouchX)
  5281                         * mPointerXZoomScale;
  5282                 float deltaY = (pointer.y - mPointerGesture.referenceTouchY)
  5283                         * mPointerYZoomScale;
  5284                 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
  5286                 mPointerGesture.currentGestureProperties[i].clear();
  5287                 mPointerGesture.currentGestureProperties[i].id = gestureId;
  5288                 mPointerGesture.currentGestureProperties[i].toolType =
  5289                         AMOTION_EVENT_TOOL_TYPE_FINGER;
  5290                 mPointerGesture.currentGestureCoords[i].clear();
  5291                 mPointerGesture.currentGestureCoords[i].setAxisValue(
  5292                         AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX);
  5293                 mPointerGesture.currentGestureCoords[i].setAxisValue(
  5294                         AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY + deltaY);
  5295                 mPointerGesture.currentGestureCoords[i].setAxisValue(
  5296                         AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
  5299             if (mPointerGesture.activeGestureId < 0) {
  5300                 mPointerGesture.activeGestureId =
  5301                         mPointerGesture.currentGestureIdBits.firstMarkedBit();
  5302 #if DEBUG_GESTURES
  5303                 ALOGD("Gestures: FREEFORM new "
  5304                         "activeGestureId=%d", mPointerGesture.activeGestureId);
  5305 #endif
  5310     mPointerController->setButtonState(mCurrentButtonState);
  5312 #if DEBUG_GESTURES
  5313     ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
  5314             "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
  5315             "lastGestureMode=%d, lastGestureIdBits=0x%08x",
  5316             toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
  5317             mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
  5318             mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
  5319     for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) {
  5320         uint32_t id = idBits.clearFirstMarkedBit();
  5321         uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
  5322         const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
  5323         const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
  5324         ALOGD("  currentGesture[%d]: index=%d, toolType=%d, "
  5325                 "x=%0.3f, y=%0.3f, pressure=%0.3f",
  5326                 id, index, properties.toolType,
  5327                 coords.getAxisValue(AMOTION_EVENT_AXIS_X),
  5328                 coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
  5329                 coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
  5331     for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) {
  5332         uint32_t id = idBits.clearFirstMarkedBit();
  5333         uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
  5334         const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
  5335         const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
  5336         ALOGD("  lastGesture[%d]: index=%d, toolType=%d, "
  5337                 "x=%0.3f, y=%0.3f, pressure=%0.3f",
  5338                 id, index, properties.toolType,
  5339                 coords.getAxisValue(AMOTION_EVENT_AXIS_X),
  5340                 coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
  5341                 coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
  5343 #endif
  5344     return true;
  5347 void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) {
  5348     mPointerSimple.currentCoords.clear();
  5349     mPointerSimple.currentProperties.clear();
  5351     bool down, hovering;
  5352     if (!mCurrentStylusIdBits.isEmpty()) {
  5353         uint32_t id = mCurrentStylusIdBits.firstMarkedBit();
  5354         uint32_t index = mCurrentCookedPointerData.idToIndex[id];
  5355         float x = mCurrentCookedPointerData.pointerCoords[index].getX();
  5356         float y = mCurrentCookedPointerData.pointerCoords[index].getY();
  5357         mPointerController->setPosition(x, y);
  5359         hovering = mCurrentCookedPointerData.hoveringIdBits.hasBit(id);
  5360         down = !hovering;
  5362         mPointerController->getPosition(&x, &y);
  5363         mPointerSimple.currentCoords.copyFrom(mCurrentCookedPointerData.pointerCoords[index]);
  5364         mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
  5365         mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
  5366         mPointerSimple.currentProperties.id = 0;
  5367         mPointerSimple.currentProperties.toolType =
  5368                 mCurrentCookedPointerData.pointerProperties[index].toolType;
  5369     } else {
  5370         down = false;
  5371         hovering = false;
  5374     dispatchPointerSimple(when, policyFlags, down, hovering);
  5377 void TouchInputMapper::abortPointerStylus(nsecs_t when, uint32_t policyFlags) {
  5378     abortPointerSimple(when, policyFlags);
  5381 void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) {
  5382     mPointerSimple.currentCoords.clear();
  5383     mPointerSimple.currentProperties.clear();
  5385     bool down, hovering;
  5386     if (!mCurrentMouseIdBits.isEmpty()) {
  5387         uint32_t id = mCurrentMouseIdBits.firstMarkedBit();
  5388         uint32_t currentIndex = mCurrentRawPointerData.idToIndex[id];
  5389         if (mLastMouseIdBits.hasBit(id)) {
  5390             uint32_t lastIndex = mCurrentRawPointerData.idToIndex[id];
  5391             float deltaX = (mCurrentRawPointerData.pointers[currentIndex].x
  5392                     - mLastRawPointerData.pointers[lastIndex].x)
  5393                     * mPointerXMovementScale;
  5394             float deltaY = (mCurrentRawPointerData.pointers[currentIndex].y
  5395                     - mLastRawPointerData.pointers[lastIndex].y)
  5396                     * mPointerYMovementScale;
  5398             rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
  5399             mPointerVelocityControl.move(when, &deltaX, &deltaY);
  5401             mPointerController->move(deltaX, deltaY);
  5402         } else {
  5403             mPointerVelocityControl.reset();
  5406         down = isPointerDown(mCurrentButtonState);
  5407         hovering = !down;
  5409         float x, y;
  5410         mPointerController->getPosition(&x, &y);
  5411         mPointerSimple.currentCoords.copyFrom(
  5412                 mCurrentCookedPointerData.pointerCoords[currentIndex]);
  5413         mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
  5414         mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
  5415         mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
  5416                 hovering ? 0.0f : 1.0f);
  5417         mPointerSimple.currentProperties.id = 0;
  5418         mPointerSimple.currentProperties.toolType =
  5419                 mCurrentCookedPointerData.pointerProperties[currentIndex].toolType;
  5420     } else {
  5421         mPointerVelocityControl.reset();
  5423         down = false;
  5424         hovering = false;
  5427     dispatchPointerSimple(when, policyFlags, down, hovering);
  5430 void TouchInputMapper::abortPointerMouse(nsecs_t when, uint32_t policyFlags) {
  5431     abortPointerSimple(when, policyFlags);
  5433     mPointerVelocityControl.reset();
  5436 void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
  5437         bool down, bool hovering) {
  5438     int32_t metaState = getContext()->getGlobalMetaState();
  5440     if (mPointerController != NULL) {
  5441         if (down || hovering) {
  5442             mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
  5443             mPointerController->clearSpots();
  5444             mPointerController->setButtonState(mCurrentButtonState);
  5445             mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
  5446         } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
  5447             mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
  5451     if (mPointerSimple.down && !down) {
  5452         mPointerSimple.down = false;
  5454         // Send up.
  5455         NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
  5456                  AMOTION_EVENT_ACTION_UP, 0, metaState, mLastButtonState, 0,
  5457                  mViewport.displayId,
  5458                  1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
  5459                  mOrientedXPrecision, mOrientedYPrecision,
  5460                  mPointerSimple.downTime);
  5461         getListener()->notifyMotion(&args);
  5464     if (mPointerSimple.hovering && !hovering) {
  5465         mPointerSimple.hovering = false;
  5467         // Send hover exit.
  5468         NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
  5469                 AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
  5470                 mViewport.displayId,
  5471                 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
  5472                 mOrientedXPrecision, mOrientedYPrecision,
  5473                 mPointerSimple.downTime);
  5474         getListener()->notifyMotion(&args);
  5477     if (down) {
  5478         if (!mPointerSimple.down) {
  5479             mPointerSimple.down = true;
  5480             mPointerSimple.downTime = when;
  5482             // Send down.
  5483             NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
  5484                     AMOTION_EVENT_ACTION_DOWN, 0, metaState, mCurrentButtonState, 0,
  5485                     mViewport.displayId,
  5486                     1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
  5487                     mOrientedXPrecision, mOrientedYPrecision,
  5488                     mPointerSimple.downTime);
  5489             getListener()->notifyMotion(&args);
  5492         // Send move.
  5493         NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
  5494                 AMOTION_EVENT_ACTION_MOVE, 0, metaState, mCurrentButtonState, 0,
  5495                 mViewport.displayId,
  5496                 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
  5497                 mOrientedXPrecision, mOrientedYPrecision,
  5498                 mPointerSimple.downTime);
  5499         getListener()->notifyMotion(&args);
  5502     if (hovering) {
  5503         if (!mPointerSimple.hovering) {
  5504             mPointerSimple.hovering = true;
  5506             // Send hover enter.
  5507             NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
  5508                     AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
  5509                     mViewport.displayId,
  5510                     1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
  5511                     mOrientedXPrecision, mOrientedYPrecision,
  5512                     mPointerSimple.downTime);
  5513             getListener()->notifyMotion(&args);
  5516         // Send hover move.
  5517         NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
  5518                 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
  5519                 mViewport.displayId,
  5520                 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
  5521                 mOrientedXPrecision, mOrientedYPrecision,
  5522                 mPointerSimple.downTime);
  5523         getListener()->notifyMotion(&args);
  5526     if (mCurrentRawVScroll || mCurrentRawHScroll) {
  5527         float vscroll = mCurrentRawVScroll;
  5528         float hscroll = mCurrentRawHScroll;
  5529         mWheelYVelocityControl.move(when, NULL, &vscroll);
  5530         mWheelXVelocityControl.move(when, &hscroll, NULL);
  5532         // Send scroll.
  5533         PointerCoords pointerCoords;
  5534         pointerCoords.copyFrom(mPointerSimple.currentCoords);
  5535         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
  5536         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
  5538         NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
  5539                 AMOTION_EVENT_ACTION_SCROLL, 0, metaState, mCurrentButtonState, 0,
  5540                 mViewport.displayId,
  5541                 1, &mPointerSimple.currentProperties, &pointerCoords,
  5542                 mOrientedXPrecision, mOrientedYPrecision,
  5543                 mPointerSimple.downTime);
  5544         getListener()->notifyMotion(&args);
  5547     // Save state.
  5548     if (down || hovering) {
  5549         mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords);
  5550         mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
  5551     } else {
  5552         mPointerSimple.reset();
  5556 void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) {
  5557     mPointerSimple.currentCoords.clear();
  5558     mPointerSimple.currentProperties.clear();
  5560     dispatchPointerSimple(when, policyFlags, false, false);
  5563 void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
  5564         int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
  5565         const PointerProperties* properties, const PointerCoords* coords,
  5566         const uint32_t* idToIndex, BitSet32 idBits,
  5567         int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {
  5568     PointerCoords pointerCoords[MAX_POINTERS];
  5569     PointerProperties pointerProperties[MAX_POINTERS];
  5570     uint32_t pointerCount = 0;
  5571     while (!idBits.isEmpty()) {
  5572         uint32_t id = idBits.clearFirstMarkedBit();
  5573         uint32_t index = idToIndex[id];
  5574         pointerProperties[pointerCount].copyFrom(properties[index]);
  5575         pointerCoords[pointerCount].copyFrom(coords[index]);
  5577         if (changedId >= 0 && id == uint32_t(changedId)) {
  5578             action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
  5581         pointerCount += 1;
  5584     ALOG_ASSERT(pointerCount != 0);
  5586     if (changedId >= 0 && pointerCount == 1) {
  5587         // Replace initial down and final up action.
  5588         // We can compare the action without masking off the changed pointer index
  5589         // because we know the index is 0.
  5590         if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
  5591             action = AMOTION_EVENT_ACTION_DOWN;
  5592         } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
  5593             action = AMOTION_EVENT_ACTION_UP;
  5594         } else {
  5595             // Can't happen.
  5596             ALOG_ASSERT(false);
  5600     NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
  5601             action, flags, metaState, buttonState, edgeFlags,
  5602             mViewport.displayId, pointerCount, pointerProperties, pointerCoords,
  5603             xPrecision, yPrecision, downTime);
  5604     getListener()->notifyMotion(&args);
  5607 bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties,
  5608         const PointerCoords* inCoords, const uint32_t* inIdToIndex,
  5609         PointerProperties* outProperties, PointerCoords* outCoords, const uint32_t* outIdToIndex,
  5610         BitSet32 idBits) const {
  5611     bool changed = false;
  5612     while (!idBits.isEmpty()) {
  5613         uint32_t id = idBits.clearFirstMarkedBit();
  5614         uint32_t inIndex = inIdToIndex[id];
  5615         uint32_t outIndex = outIdToIndex[id];
  5617         const PointerProperties& curInProperties = inProperties[inIndex];
  5618         const PointerCoords& curInCoords = inCoords[inIndex];
  5619         PointerProperties& curOutProperties = outProperties[outIndex];
  5620         PointerCoords& curOutCoords = outCoords[outIndex];
  5622         if (curInProperties != curOutProperties) {
  5623             curOutProperties.copyFrom(curInProperties);
  5624             changed = true;
  5627         if (curInCoords != curOutCoords) {
  5628             curOutCoords.copyFrom(curInCoords);
  5629             changed = true;
  5632     return changed;
  5635 void TouchInputMapper::fadePointer() {
  5636     if (mPointerController != NULL) {
  5637         mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
  5641 bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
  5642     return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue
  5643             && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue;
  5646 const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(
  5647         int32_t x, int32_t y) {
  5648     size_t numVirtualKeys = mVirtualKeys.size();
  5649     for (size_t i = 0; i < numVirtualKeys; i++) {
  5650         const VirtualKey& virtualKey = mVirtualKeys[i];
  5652 #if DEBUG_VIRTUAL_KEYS
  5653         ALOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
  5654                 "left=%d, top=%d, right=%d, bottom=%d",
  5655                 x, y,
  5656                 virtualKey.keyCode, virtualKey.scanCode,
  5657                 virtualKey.hitLeft, virtualKey.hitTop,
  5658                 virtualKey.hitRight, virtualKey.hitBottom);
  5659 #endif
  5661         if (virtualKey.isHit(x, y)) {
  5662             return & virtualKey;
  5666     return NULL;
  5669 void TouchInputMapper::assignPointerIds() {
  5670     uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount;
  5671     uint32_t lastPointerCount = mLastRawPointerData.pointerCount;
  5673     mCurrentRawPointerData.clearIdBits();
  5675     if (currentPointerCount == 0) {
  5676         // No pointers to assign.
  5677         return;
  5680     if (lastPointerCount == 0) {
  5681         // All pointers are new.
  5682         for (uint32_t i = 0; i < currentPointerCount; i++) {
  5683             uint32_t id = i;
  5684             mCurrentRawPointerData.pointers[i].id = id;
  5685             mCurrentRawPointerData.idToIndex[id] = i;
  5686             mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(i));
  5688         return;
  5691     if (currentPointerCount == 1 && lastPointerCount == 1
  5692             && mCurrentRawPointerData.pointers[0].toolType
  5693                     == mLastRawPointerData.pointers[0].toolType) {
  5694         // Only one pointer and no change in count so it must have the same id as before.
  5695         uint32_t id = mLastRawPointerData.pointers[0].id;
  5696         mCurrentRawPointerData.pointers[0].id = id;
  5697         mCurrentRawPointerData.idToIndex[id] = 0;
  5698         mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(0));
  5699         return;
  5702     // General case.
  5703     // We build a heap of squared euclidean distances between current and last pointers
  5704     // associated with the current and last pointer indices.  Then, we find the best
  5705     // match (by distance) for each current pointer.
  5706     // The pointers must have the same tool type but it is possible for them to
  5707     // transition from hovering to touching or vice-versa while retaining the same id.
  5708     PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
  5710     uint32_t heapSize = 0;
  5711     for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
  5712             currentPointerIndex++) {
  5713         for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
  5714                 lastPointerIndex++) {
  5715             const RawPointerData::Pointer& currentPointer =
  5716                     mCurrentRawPointerData.pointers[currentPointerIndex];
  5717             const RawPointerData::Pointer& lastPointer =
  5718                     mLastRawPointerData.pointers[lastPointerIndex];
  5719             if (currentPointer.toolType == lastPointer.toolType) {
  5720                 int64_t deltaX = currentPointer.x - lastPointer.x;
  5721                 int64_t deltaY = currentPointer.y - lastPointer.y;
  5723                 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
  5725                 // Insert new element into the heap (sift up).
  5726                 heap[heapSize].currentPointerIndex = currentPointerIndex;
  5727                 heap[heapSize].lastPointerIndex = lastPointerIndex;
  5728                 heap[heapSize].distance = distance;
  5729                 heapSize += 1;
  5734     // Heapify
  5735     for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
  5736         startIndex -= 1;
  5737         for (uint32_t parentIndex = startIndex; ;) {
  5738             uint32_t childIndex = parentIndex * 2 + 1;
  5739             if (childIndex >= heapSize) {
  5740                 break;
  5743             if (childIndex + 1 < heapSize
  5744                     && heap[childIndex + 1].distance < heap[childIndex].distance) {
  5745                 childIndex += 1;
  5748             if (heap[parentIndex].distance <= heap[childIndex].distance) {
  5749                 break;
  5752             swap(heap[parentIndex], heap[childIndex]);
  5753             parentIndex = childIndex;
  5757 #if DEBUG_POINTER_ASSIGNMENT
  5758     ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
  5759     for (size_t i = 0; i < heapSize; i++) {
  5760         ALOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
  5761                 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
  5762                 heap[i].distance);
  5764 #endif
  5766     // Pull matches out by increasing order of distance.
  5767     // To avoid reassigning pointers that have already been matched, the loop keeps track
  5768     // of which last and current pointers have been matched using the matchedXXXBits variables.
  5769     // It also tracks the used pointer id bits.
  5770     BitSet32 matchedLastBits(0);
  5771     BitSet32 matchedCurrentBits(0);
  5772     BitSet32 usedIdBits(0);
  5773     bool first = true;
  5774     for (uint32_t i = min(currentPointerCount, lastPointerCount); heapSize > 0 && i > 0; i--) {
  5775         while (heapSize > 0) {
  5776             if (first) {
  5777                 // The first time through the loop, we just consume the root element of
  5778                 // the heap (the one with smallest distance).
  5779                 first = false;
  5780             } else {
  5781                 // Previous iterations consumed the root element of the heap.
  5782                 // Pop root element off of the heap (sift down).
  5783                 heap[0] = heap[heapSize];
  5784                 for (uint32_t parentIndex = 0; ;) {
  5785                     uint32_t childIndex = parentIndex * 2 + 1;
  5786                     if (childIndex >= heapSize) {
  5787                         break;
  5790                     if (childIndex + 1 < heapSize
  5791                             && heap[childIndex + 1].distance < heap[childIndex].distance) {
  5792                         childIndex += 1;
  5795                     if (heap[parentIndex].distance <= heap[childIndex].distance) {
  5796                         break;
  5799                     swap(heap[parentIndex], heap[childIndex]);
  5800                     parentIndex = childIndex;
  5803 #if DEBUG_POINTER_ASSIGNMENT
  5804                 ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
  5805                 for (size_t i = 0; i < heapSize; i++) {
  5806                     ALOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
  5807                             i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
  5808                             heap[i].distance);
  5810 #endif
  5813             heapSize -= 1;
  5815             uint32_t currentPointerIndex = heap[0].currentPointerIndex;
  5816             if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
  5818             uint32_t lastPointerIndex = heap[0].lastPointerIndex;
  5819             if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
  5821             matchedCurrentBits.markBit(currentPointerIndex);
  5822             matchedLastBits.markBit(lastPointerIndex);
  5824             uint32_t id = mLastRawPointerData.pointers[lastPointerIndex].id;
  5825             mCurrentRawPointerData.pointers[currentPointerIndex].id = id;
  5826             mCurrentRawPointerData.idToIndex[id] = currentPointerIndex;
  5827             mCurrentRawPointerData.markIdBit(id,
  5828                     mCurrentRawPointerData.isHovering(currentPointerIndex));
  5829             usedIdBits.markBit(id);
  5831 #if DEBUG_POINTER_ASSIGNMENT
  5832             ALOGD("assignPointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
  5833                     lastPointerIndex, currentPointerIndex, id, heap[0].distance);
  5834 #endif
  5835             break;
  5839     // Assign fresh ids to pointers that were not matched in the process.
  5840     for (uint32_t i = currentPointerCount - matchedCurrentBits.count(); i != 0; i--) {
  5841         uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit();
  5842         uint32_t id = usedIdBits.markFirstUnmarkedBit();
  5844         mCurrentRawPointerData.pointers[currentPointerIndex].id = id;
  5845         mCurrentRawPointerData.idToIndex[id] = currentPointerIndex;
  5846         mCurrentRawPointerData.markIdBit(id,
  5847                 mCurrentRawPointerData.isHovering(currentPointerIndex));
  5849 #if DEBUG_POINTER_ASSIGNMENT
  5850         ALOGD("assignPointerIds - assigned: cur=%d, id=%d",
  5851                 currentPointerIndex, id);
  5852 #endif
  5856 int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
  5857     if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) {
  5858         return AKEY_STATE_VIRTUAL;
  5861     size_t numVirtualKeys = mVirtualKeys.size();
  5862     for (size_t i = 0; i < numVirtualKeys; i++) {
  5863         const VirtualKey& virtualKey = mVirtualKeys[i];
  5864         if (virtualKey.keyCode == keyCode) {
  5865             return AKEY_STATE_UP;
  5869     return AKEY_STATE_UNKNOWN;
  5872 int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
  5873     if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) {
  5874         return AKEY_STATE_VIRTUAL;
  5877     size_t numVirtualKeys = mVirtualKeys.size();
  5878     for (size_t i = 0; i < numVirtualKeys; i++) {
  5879         const VirtualKey& virtualKey = mVirtualKeys[i];
  5880         if (virtualKey.scanCode == scanCode) {
  5881             return AKEY_STATE_UP;
  5885     return AKEY_STATE_UNKNOWN;
  5888 bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
  5889         const int32_t* keyCodes, uint8_t* outFlags) {
  5890     size_t numVirtualKeys = mVirtualKeys.size();
  5891     for (size_t i = 0; i < numVirtualKeys; i++) {
  5892         const VirtualKey& virtualKey = mVirtualKeys[i];
  5894         for (size_t i = 0; i < numCodes; i++) {
  5895             if (virtualKey.keyCode == keyCodes[i]) {
  5896                 outFlags[i] = 1;
  5901     return true;
  5905 // --- SingleTouchInputMapper ---
  5907 SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
  5908         TouchInputMapper(device) {
  5911 SingleTouchInputMapper::~SingleTouchInputMapper() {
  5914 void SingleTouchInputMapper::reset(nsecs_t when) {
  5915     mSingleTouchMotionAccumulator.reset(getDevice());
  5917     TouchInputMapper::reset(when);
  5920 void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
  5921     TouchInputMapper::process(rawEvent);
  5923     mSingleTouchMotionAccumulator.process(rawEvent);
  5926 void SingleTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) {
  5927     if (mTouchButtonAccumulator.isToolActive()) {
  5928         mCurrentRawPointerData.pointerCount = 1;
  5929         mCurrentRawPointerData.idToIndex[0] = 0;
  5931         bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
  5932                 && (mTouchButtonAccumulator.isHovering()
  5933                         || (mRawPointerAxes.pressure.valid
  5934                                 && mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0));
  5935         mCurrentRawPointerData.markIdBit(0, isHovering);
  5937         RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[0];
  5938         outPointer.id = 0;
  5939         outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
  5940         outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
  5941         outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
  5942         outPointer.touchMajor = 0;
  5943         outPointer.touchMinor = 0;
  5944         outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
  5945         outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
  5946         outPointer.orientation = 0;
  5947         outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
  5948         outPointer.tiltX = mSingleTouchMotionAccumulator.getAbsoluteTiltX();
  5949         outPointer.tiltY = mSingleTouchMotionAccumulator.getAbsoluteTiltY();
  5950         outPointer.toolType = mTouchButtonAccumulator.getToolType();
  5951         if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
  5952             outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
  5954         outPointer.isHovering = isHovering;
  5958 void SingleTouchInputMapper::configureRawPointerAxes() {
  5959     TouchInputMapper::configureRawPointerAxes();
  5961     getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x);
  5962     getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y);
  5963     getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure);
  5964     getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor);
  5965     getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance);
  5966     getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX);
  5967     getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY);
  5970 bool SingleTouchInputMapper::hasStylus() const {
  5971     return mTouchButtonAccumulator.hasStylus();
  5975 // --- MultiTouchInputMapper ---
  5977 MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
  5978         TouchInputMapper(device) {
  5981 MultiTouchInputMapper::~MultiTouchInputMapper() {
  5984 void MultiTouchInputMapper::reset(nsecs_t when) {
  5985     mMultiTouchMotionAccumulator.reset(getDevice());
  5987     mPointerIdBits.clear();
  5989     TouchInputMapper::reset(when);
  5992 void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
  5993     TouchInputMapper::process(rawEvent);
  5995     mMultiTouchMotionAccumulator.process(rawEvent);
  5998 void MultiTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) {
  5999     size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
  6000     size_t outCount = 0;
  6001     BitSet32 newPointerIdBits;
  6003     for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
  6004         const MultiTouchMotionAccumulator::Slot* inSlot =
  6005                 mMultiTouchMotionAccumulator.getSlot(inIndex);
  6006         if (!inSlot->isInUse()) {
  6007             continue;
  6010         if (outCount >= MAX_POINTERS) {
  6011 #if DEBUG_POINTERS
  6012             ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
  6013                     "ignoring the rest.",
  6014                     getDeviceName().string(), MAX_POINTERS);
  6015 #endif
  6016             break; // too many fingers!
  6019         RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[outCount];
  6020         outPointer.x = inSlot->getX();
  6021         outPointer.y = inSlot->getY();
  6022         outPointer.pressure = inSlot->getPressure();
  6023         outPointer.touchMajor = inSlot->getTouchMajor();
  6024         outPointer.touchMinor = inSlot->getTouchMinor();
  6025         outPointer.toolMajor = inSlot->getToolMajor();
  6026         outPointer.toolMinor = inSlot->getToolMinor();
  6027         outPointer.orientation = inSlot->getOrientation();
  6028         outPointer.distance = inSlot->getDistance();
  6029         outPointer.tiltX = 0;
  6030         outPointer.tiltY = 0;
  6032         outPointer.toolType = inSlot->getToolType();
  6033         if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
  6034             outPointer.toolType = mTouchButtonAccumulator.getToolType();
  6035             if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
  6036                 outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
  6040         bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
  6041                 && (mTouchButtonAccumulator.isHovering()
  6042                         || (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
  6043         outPointer.isHovering = isHovering;
  6045         // Assign pointer id using tracking id if available.
  6046         if (*outHavePointerIds) {
  6047             int32_t trackingId = inSlot->getTrackingId();
  6048             int32_t id = -1;
  6049             if (trackingId >= 0) {
  6050                 for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
  6051                     uint32_t n = idBits.clearFirstMarkedBit();
  6052                     if (mPointerTrackingIdMap[n] == trackingId) {
  6053                         id = n;
  6057                 if (id < 0 && !mPointerIdBits.isFull()) {
  6058                     id = mPointerIdBits.markFirstUnmarkedBit();
  6059                     mPointerTrackingIdMap[id] = trackingId;
  6062             if (id < 0) {
  6063                 *outHavePointerIds = false;
  6064                 mCurrentRawPointerData.clearIdBits();
  6065                 newPointerIdBits.clear();
  6066             } else {
  6067                 outPointer.id = id;
  6068                 mCurrentRawPointerData.idToIndex[id] = outCount;
  6069                 mCurrentRawPointerData.markIdBit(id, isHovering);
  6070                 newPointerIdBits.markBit(id);
  6074         outCount += 1;
  6077     mCurrentRawPointerData.pointerCount = outCount;
  6078     mPointerIdBits = newPointerIdBits;
  6080     mMultiTouchMotionAccumulator.finishSync();
  6083 void MultiTouchInputMapper::configureRawPointerAxes() {
  6084     TouchInputMapper::configureRawPointerAxes();
  6086     getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x);
  6087     getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y);
  6088     getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor);
  6089     getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor);
  6090     getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor);
  6091     getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor);
  6092     getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation);
  6093     getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure);
  6094     getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance);
  6095     getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId);
  6096     getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot);
  6098     if (mRawPointerAxes.trackingId.valid
  6099             && mRawPointerAxes.slot.valid
  6100             && mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
  6101         size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
  6102         if (slotCount > MAX_SLOTS) {
  6103             ALOGW("MultiTouch Device %s reported %d slots but the framework "
  6104                     "only supports a maximum of %d slots at this time.",
  6105                     getDeviceName().string(), slotCount, MAX_SLOTS);
  6106             slotCount = MAX_SLOTS;
  6108         mMultiTouchMotionAccumulator.configure(getDevice(),
  6109                 slotCount, true /*usingSlotsProtocol*/);
  6110     } else {
  6111         mMultiTouchMotionAccumulator.configure(getDevice(),
  6112                 MAX_POINTERS, false /*usingSlotsProtocol*/);
  6116 bool MultiTouchInputMapper::hasStylus() const {
  6117     return mMultiTouchMotionAccumulator.hasStylus()
  6118             || mTouchButtonAccumulator.hasStylus();
  6122 // --- JoystickInputMapper ---
  6124 JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
  6125         InputMapper(device) {
  6128 JoystickInputMapper::~JoystickInputMapper() {
  6131 uint32_t JoystickInputMapper::getSources() {
  6132     return AINPUT_SOURCE_JOYSTICK;
  6135 void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
  6136     InputMapper::populateDeviceInfo(info);
  6138     for (size_t i = 0; i < mAxes.size(); i++) {
  6139         const Axis& axis = mAxes.valueAt(i);
  6140         addMotionRange(axis.axisInfo.axis, axis, info);
  6142         if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
  6143             addMotionRange(axis.axisInfo.highAxis, axis, info);
  6149 void JoystickInputMapper::addMotionRange(int32_t axisId, const Axis& axis,
  6150         InputDeviceInfo* info) {
  6151     info->addMotionRange(axisId, AINPUT_SOURCE_JOYSTICK,
  6152             axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
  6153     /* In order to ease the transition for developers from using the old axes
  6154      * to the newer, more semantically correct axes, we'll continue to register
  6155      * the old axes as duplicates of their corresponding new ones.  */
  6156     int32_t compatAxis = getCompatAxis(axisId);
  6157     if (compatAxis >= 0) {
  6158         info->addMotionRange(compatAxis, AINPUT_SOURCE_JOYSTICK,
  6159                 axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
  6163 /* A mapping from axes the joystick actually has to the axes that should be
  6164  * artificially created for compatibility purposes.
  6165  * Returns -1 if no compatibility axis is needed. */
  6166 int32_t JoystickInputMapper::getCompatAxis(int32_t axis) {
  6167     switch(axis) {
  6168     case AMOTION_EVENT_AXIS_LTRIGGER:
  6169         return AMOTION_EVENT_AXIS_BRAKE;
  6170     case AMOTION_EVENT_AXIS_RTRIGGER:
  6171         return AMOTION_EVENT_AXIS_GAS;
  6173     return -1;
  6176 void JoystickInputMapper::dump(String8& dump) {
  6177     dump.append(INDENT2 "Joystick Input Mapper:\n");
  6179     dump.append(INDENT3 "Axes:\n");
  6180     size_t numAxes = mAxes.size();
  6181     for (size_t i = 0; i < numAxes; i++) {
  6182         const Axis& axis = mAxes.valueAt(i);
  6183         const char* label = getAxisLabel(axis.axisInfo.axis);
  6184         if (label) {
  6185             dump.appendFormat(INDENT4 "%s", label);
  6186         } else {
  6187             dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis);
  6189         if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
  6190             label = getAxisLabel(axis.axisInfo.highAxis);
  6191             if (label) {
  6192                 dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue);
  6193             } else {
  6194                 dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis,
  6195                         axis.axisInfo.splitValue);
  6197         } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
  6198             dump.append(" (invert)");
  6201         dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f, resolution=%0.5f\n",
  6202                 axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
  6203         dump.appendFormat(INDENT4 "  scale=%0.5f, offset=%0.5f, "
  6204                 "highScale=%0.5f, highOffset=%0.5f\n",
  6205                 axis.scale, axis.offset, axis.highScale, axis.highOffset);
  6206         dump.appendFormat(INDENT4 "  rawAxis=%d, rawMin=%d, rawMax=%d, "
  6207                 "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n",
  6208                 mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
  6209                 axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, axis.rawAxisInfo.resolution);
  6213 void JoystickInputMapper::configure(nsecs_t when,
  6214         const InputReaderConfiguration* config, uint32_t changes) {
  6215     InputMapper::configure(when, config, changes);
  6217     if (!changes) { // first time only
  6218         // Collect all axes.
  6219         for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
  6220             if (!(getAbsAxisUsage(abs, getDevice()->getClasses())
  6221                     & INPUT_DEVICE_CLASS_JOYSTICK)) {
  6222                 continue; // axis must be claimed by a different device
  6225             RawAbsoluteAxisInfo rawAxisInfo;
  6226             getAbsoluteAxisInfo(abs, &rawAxisInfo);
  6227             if (rawAxisInfo.valid) {
  6228                 // Map axis.
  6229                 AxisInfo axisInfo;
  6230                 bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
  6231                 if (!explicitlyMapped) {
  6232                     // Axis is not explicitly mapped, will choose a generic axis later.
  6233                     axisInfo.mode = AxisInfo::MODE_NORMAL;
  6234                     axisInfo.axis = -1;
  6237                 // Apply flat override.
  6238                 int32_t rawFlat = axisInfo.flatOverride < 0
  6239                         ? rawAxisInfo.flat : axisInfo.flatOverride;
  6241                 // Calculate scaling factors and limits.
  6242                 Axis axis;
  6243                 if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
  6244                     float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
  6245                     float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
  6246                     axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
  6247                             scale, 0.0f, highScale, 0.0f,
  6248                             0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
  6249                             rawAxisInfo.resolution * scale);
  6250                 } else if (isCenteredAxis(axisInfo.axis)) {
  6251                     float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
  6252                     float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
  6253                     axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
  6254                             scale, offset, scale, offset,
  6255                             -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
  6256                             rawAxisInfo.resolution * scale);
  6257                 } else {
  6258                     float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
  6259                     axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
  6260                             scale, 0.0f, scale, 0.0f,
  6261                             0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
  6262                             rawAxisInfo.resolution * scale);
  6265                 // To eliminate noise while the joystick is at rest, filter out small variations
  6266                 // in axis values up front.
  6267                 axis.filter = axis.flat * 0.25f;
  6269                 mAxes.add(abs, axis);
  6273         // If there are too many axes, start dropping them.
  6274         // Prefer to keep explicitly mapped axes.
  6275         if (mAxes.size() > PointerCoords::MAX_AXES) {
  6276             ALOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
  6277                     getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
  6278             pruneAxes(true);
  6279             pruneAxes(false);
  6282         // Assign generic axis ids to remaining axes.
  6283         int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
  6284         size_t numAxes = mAxes.size();
  6285         for (size_t i = 0; i < numAxes; i++) {
  6286             Axis& axis = mAxes.editValueAt(i);
  6287             if (axis.axisInfo.axis < 0) {
  6288                 while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
  6289                         && haveAxis(nextGenericAxisId)) {
  6290                     nextGenericAxisId += 1;
  6293                 if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
  6294                     axis.axisInfo.axis = nextGenericAxisId;
  6295                     nextGenericAxisId += 1;
  6296                 } else {
  6297                     ALOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
  6298                             "have already been assigned to other axes.",
  6299                             getDeviceName().string(), mAxes.keyAt(i));
  6300                     mAxes.removeItemsAt(i--);
  6301                     numAxes -= 1;
  6308 bool JoystickInputMapper::haveAxis(int32_t axisId) {
  6309     size_t numAxes = mAxes.size();
  6310     for (size_t i = 0; i < numAxes; i++) {
  6311         const Axis& axis = mAxes.valueAt(i);
  6312         if (axis.axisInfo.axis == axisId
  6313                 || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
  6314                         && axis.axisInfo.highAxis == axisId)) {
  6315             return true;
  6318     return false;
  6321 void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
  6322     size_t i = mAxes.size();
  6323     while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
  6324         if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
  6325             continue;
  6327         ALOGI("Discarding joystick '%s' axis %d because there are too many axes.",
  6328                 getDeviceName().string(), mAxes.keyAt(i));
  6329         mAxes.removeItemsAt(i);
  6333 bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
  6334     switch (axis) {
  6335     case AMOTION_EVENT_AXIS_X:
  6336     case AMOTION_EVENT_AXIS_Y:
  6337     case AMOTION_EVENT_AXIS_Z:
  6338     case AMOTION_EVENT_AXIS_RX:
  6339     case AMOTION_EVENT_AXIS_RY:
  6340     case AMOTION_EVENT_AXIS_RZ:
  6341     case AMOTION_EVENT_AXIS_HAT_X:
  6342     case AMOTION_EVENT_AXIS_HAT_Y:
  6343     case AMOTION_EVENT_AXIS_ORIENTATION:
  6344     case AMOTION_EVENT_AXIS_RUDDER:
  6345     case AMOTION_EVENT_AXIS_WHEEL:
  6346         return true;
  6347     default:
  6348         return false;
  6352 void JoystickInputMapper::reset(nsecs_t when) {
  6353     // Recenter all axes.
  6354     size_t numAxes = mAxes.size();
  6355     for (size_t i = 0; i < numAxes; i++) {
  6356         Axis& axis = mAxes.editValueAt(i);
  6357         axis.resetValue();
  6360     InputMapper::reset(when);
  6363 void JoystickInputMapper::process(const RawEvent* rawEvent) {
  6364     switch (rawEvent->type) {
  6365     case EV_ABS: {
  6366         ssize_t index = mAxes.indexOfKey(rawEvent->code);
  6367         if (index >= 0) {
  6368             Axis& axis = mAxes.editValueAt(index);
  6369             float newValue, highNewValue;
  6370             switch (axis.axisInfo.mode) {
  6371             case AxisInfo::MODE_INVERT:
  6372                 newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
  6373                         * axis.scale + axis.offset;
  6374                 highNewValue = 0.0f;
  6375                 break;
  6376             case AxisInfo::MODE_SPLIT:
  6377                 if (rawEvent->value < axis.axisInfo.splitValue) {
  6378                     newValue = (axis.axisInfo.splitValue - rawEvent->value)
  6379                             * axis.scale + axis.offset;
  6380                     highNewValue = 0.0f;
  6381                 } else if (rawEvent->value > axis.axisInfo.splitValue) {
  6382                     newValue = 0.0f;
  6383                     highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
  6384                             * axis.highScale + axis.highOffset;
  6385                 } else {
  6386                     newValue = 0.0f;
  6387                     highNewValue = 0.0f;
  6389                 break;
  6390             default:
  6391                 newValue = rawEvent->value * axis.scale + axis.offset;
  6392                 highNewValue = 0.0f;
  6393                 break;
  6395             axis.newValue = newValue;
  6396             axis.highNewValue = highNewValue;
  6398         break;
  6401     case EV_SYN:
  6402         switch (rawEvent->code) {
  6403         case SYN_REPORT:
  6404             sync(rawEvent->when, false /*force*/);
  6405             break;
  6407         break;
  6411 void JoystickInputMapper::sync(nsecs_t when, bool force) {
  6412     if (!filterAxes(force)) {
  6413         return;
  6416     int32_t metaState = mContext->getGlobalMetaState();
  6417     int32_t buttonState = 0;
  6419     PointerProperties pointerProperties;
  6420     pointerProperties.clear();
  6421     pointerProperties.id = 0;
  6422     pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
  6424     PointerCoords pointerCoords;
  6425     pointerCoords.clear();
  6427     size_t numAxes = mAxes.size();
  6428     for (size_t i = 0; i < numAxes; i++) {
  6429         const Axis& axis = mAxes.valueAt(i);
  6430         setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.axis, axis.currentValue);
  6431         if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
  6432             setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.highAxis,
  6433                     axis.highCurrentValue);
  6437     // Moving a joystick axis should not wake the device because joysticks can
  6438     // be fairly noisy even when not in use.  On the other hand, pushing a gamepad
  6439     // button will likely wake the device.
  6440     // TODO: Use the input device configuration to control this behavior more finely.
  6441     uint32_t policyFlags = 0;
  6443     NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
  6444             AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
  6445             ADISPLAY_ID_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, 0);
  6446     getListener()->notifyMotion(&args);
  6449 void JoystickInputMapper::setPointerCoordsAxisValue(PointerCoords* pointerCoords,
  6450         int32_t axis, float value) {
  6451     pointerCoords->setAxisValue(axis, value);
  6452     /* In order to ease the transition for developers from using the old axes
  6453      * to the newer, more semantically correct axes, we'll continue to produce
  6454      * values for the old axes as mirrors of the value of their corresponding
  6455      * new axes. */
  6456     int32_t compatAxis = getCompatAxis(axis);
  6457     if (compatAxis >= 0) {
  6458         pointerCoords->setAxisValue(compatAxis, value);
  6462 bool JoystickInputMapper::filterAxes(bool force) {
  6463     bool atLeastOneSignificantChange = force;
  6464     size_t numAxes = mAxes.size();
  6465     for (size_t i = 0; i < numAxes; i++) {
  6466         Axis& axis = mAxes.editValueAt(i);
  6467         if (force || hasValueChangedSignificantly(axis.filter,
  6468                 axis.newValue, axis.currentValue, axis.min, axis.max)) {
  6469             axis.currentValue = axis.newValue;
  6470             atLeastOneSignificantChange = true;
  6472         if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
  6473             if (force || hasValueChangedSignificantly(axis.filter,
  6474                     axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
  6475                 axis.highCurrentValue = axis.highNewValue;
  6476                 atLeastOneSignificantChange = true;
  6480     return atLeastOneSignificantChange;
  6483 bool JoystickInputMapper::hasValueChangedSignificantly(
  6484         float filter, float newValue, float currentValue, float min, float max) {
  6485     if (newValue != currentValue) {
  6486         // Filter out small changes in value unless the value is converging on the axis
  6487         // bounds or center point.  This is intended to reduce the amount of information
  6488         // sent to applications by particularly noisy joysticks (such as PS3).
  6489         if (fabs(newValue - currentValue) > filter
  6490                 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
  6491                 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
  6492                 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
  6493             return true;
  6496     return false;
  6499 bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
  6500         float filter, float newValue, float currentValue, float thresholdValue) {
  6501     float newDistance = fabs(newValue - thresholdValue);
  6502     if (newDistance < filter) {
  6503         float oldDistance = fabs(currentValue - thresholdValue);
  6504         if (newDistance < oldDistance) {
  6505             return true;
  6508     return false;
  6511 } // namespace android

mercurial