1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/gonk/libui/InputReader.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,6511 @@ 1.4 +/* 1.5 + * Copyright (C) 2010 The Android Open Source Project 1.6 + * 1.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.8 + * you may not use this file except in compliance with the License. 1.9 + * You may obtain a copy of the License at 1.10 + * 1.11 + * http://www.apache.org/licenses/LICENSE-2.0 1.12 + * 1.13 + * Unless required by applicable law or agreed to in writing, software 1.14 + * distributed under the License is distributed on an "AS IS" BASIS, 1.15 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.16 + * See the License for the specific language governing permissions and 1.17 + * limitations under the License. 1.18 + */ 1.19 + 1.20 +#define LOG_TAG "InputReader" 1.21 + 1.22 +//#define LOG_NDEBUG 0 1.23 +#include "cutils_log.h" 1.24 + 1.25 +// Log debug messages for each raw event received from the EventHub. 1.26 +#define DEBUG_RAW_EVENTS 0 1.27 + 1.28 +// Log debug messages about touch screen filtering hacks. 1.29 +#define DEBUG_HACKS 0 1.30 + 1.31 +// Log debug messages about virtual key processing. 1.32 +#define DEBUG_VIRTUAL_KEYS 0 1.33 + 1.34 +// Log debug messages about pointers. 1.35 +#define DEBUG_POINTERS 0 1.36 + 1.37 +// Log debug messages about pointer assignment calculations. 1.38 +#define DEBUG_POINTER_ASSIGNMENT 0 1.39 + 1.40 +// Log debug messages about gesture detection. 1.41 +#define DEBUG_GESTURES 0 1.42 + 1.43 +// Log debug messages about the vibrator. 1.44 +#define DEBUG_VIBRATOR 0 1.45 + 1.46 +#include "InputReader.h" 1.47 + 1.48 +#include "Keyboard.h" 1.49 +#include "VirtualKeyMap.h" 1.50 + 1.51 +#include <stddef.h> 1.52 +#include <stdlib.h> 1.53 +#include <unistd.h> 1.54 +#include <errno.h> 1.55 +#include <limits.h> 1.56 +#include <math.h> 1.57 + 1.58 +#define INDENT " " 1.59 +#define INDENT2 " " 1.60 +#define INDENT3 " " 1.61 +#define INDENT4 " " 1.62 +#define INDENT5 " " 1.63 + 1.64 +namespace android { 1.65 + 1.66 +// --- Constants --- 1.67 + 1.68 +// Maximum number of slots supported when using the slot-based Multitouch Protocol B. 1.69 +static const size_t MAX_SLOTS = 32; 1.70 + 1.71 +// --- Static Functions --- 1.72 + 1.73 +template<typename T> 1.74 +inline static T abs(const T& value) { 1.75 + return value < 0 ? - value : value; 1.76 +} 1.77 + 1.78 +template<typename T> 1.79 +inline static T min(const T& a, const T& b) { 1.80 + return a < b ? a : b; 1.81 +} 1.82 + 1.83 +template<typename T> 1.84 +inline static void swap(T& a, T& b) { 1.85 + T temp = a; 1.86 + a = b; 1.87 + b = temp; 1.88 +} 1.89 + 1.90 +inline static float avg(float x, float y) { 1.91 + return (x + y) / 2; 1.92 +} 1.93 + 1.94 +inline static float distance(float x1, float y1, float x2, float y2) { 1.95 + return hypotf(x1 - x2, y1 - y2); 1.96 +} 1.97 + 1.98 +inline static int32_t signExtendNybble(int32_t value) { 1.99 + return value >= 8 ? value - 16 : value; 1.100 +} 1.101 + 1.102 +static inline const char* toString(bool value) { 1.103 + return value ? "true" : "false"; 1.104 +} 1.105 + 1.106 +static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation, 1.107 + const int32_t map[][4], size_t mapSize) { 1.108 + if (orientation != DISPLAY_ORIENTATION_0) { 1.109 + for (size_t i = 0; i < mapSize; i++) { 1.110 + if (value == map[i][0]) { 1.111 + return map[i][orientation]; 1.112 + } 1.113 + } 1.114 + } 1.115 + return value; 1.116 +} 1.117 + 1.118 +static const int32_t keyCodeRotationMap[][4] = { 1.119 + // key codes enumerated counter-clockwise with the original (unrotated) key first 1.120 + // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation 1.121 + { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT }, 1.122 + { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN }, 1.123 + { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT }, 1.124 + { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP }, 1.125 +}; 1.126 +static const size_t keyCodeRotationMapSize = 1.127 + sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]); 1.128 + 1.129 +static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) { 1.130 + return rotateValueUsingRotationMap(keyCode, orientation, 1.131 + keyCodeRotationMap, keyCodeRotationMapSize); 1.132 +} 1.133 + 1.134 +static void rotateDelta(int32_t orientation, float* deltaX, float* deltaY) { 1.135 + float temp; 1.136 + switch (orientation) { 1.137 + case DISPLAY_ORIENTATION_90: 1.138 + temp = *deltaX; 1.139 + *deltaX = *deltaY; 1.140 + *deltaY = -temp; 1.141 + break; 1.142 + 1.143 + case DISPLAY_ORIENTATION_180: 1.144 + *deltaX = -*deltaX; 1.145 + *deltaY = -*deltaY; 1.146 + break; 1.147 + 1.148 + case DISPLAY_ORIENTATION_270: 1.149 + temp = *deltaX; 1.150 + *deltaX = -*deltaY; 1.151 + *deltaY = temp; 1.152 + break; 1.153 + } 1.154 +} 1.155 + 1.156 +static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) { 1.157 + return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0; 1.158 +} 1.159 + 1.160 +// Returns true if the pointer should be reported as being down given the specified 1.161 +// button states. This determines whether the event is reported as a touch event. 1.162 +static bool isPointerDown(int32_t buttonState) { 1.163 + return buttonState & 1.164 + (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY 1.165 + | AMOTION_EVENT_BUTTON_TERTIARY); 1.166 +} 1.167 + 1.168 +static float calculateCommonVector(float a, float b) { 1.169 + if (a > 0 && b > 0) { 1.170 + return a < b ? a : b; 1.171 + } else if (a < 0 && b < 0) { 1.172 + return a > b ? a : b; 1.173 + } else { 1.174 + return 0; 1.175 + } 1.176 +} 1.177 + 1.178 +static void synthesizeButtonKey(InputReaderContext* context, int32_t action, 1.179 + nsecs_t when, int32_t deviceId, uint32_t source, 1.180 + uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState, 1.181 + int32_t buttonState, int32_t keyCode) { 1.182 + if ( 1.183 + (action == AKEY_EVENT_ACTION_DOWN 1.184 + && !(lastButtonState & buttonState) 1.185 + && (currentButtonState & buttonState)) 1.186 + || (action == AKEY_EVENT_ACTION_UP 1.187 + && (lastButtonState & buttonState) 1.188 + && !(currentButtonState & buttonState))) { 1.189 + NotifyKeyArgs args(when, deviceId, source, policyFlags, 1.190 + action, 0, keyCode, 0, context->getGlobalMetaState(), when); 1.191 + context->getListener()->notifyKey(&args); 1.192 + } 1.193 +} 1.194 + 1.195 +static void synthesizeButtonKeys(InputReaderContext* context, int32_t action, 1.196 + nsecs_t when, int32_t deviceId, uint32_t source, 1.197 + uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) { 1.198 + synthesizeButtonKey(context, action, when, deviceId, source, policyFlags, 1.199 + lastButtonState, currentButtonState, 1.200 + AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK); 1.201 + synthesizeButtonKey(context, action, when, deviceId, source, policyFlags, 1.202 + lastButtonState, currentButtonState, 1.203 + AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD); 1.204 +} 1.205 + 1.206 + 1.207 +// --- InputReaderConfiguration --- 1.208 + 1.209 +bool InputReaderConfiguration::getDisplayInfo(bool external, DisplayViewport* outViewport) const { 1.210 + const DisplayViewport& viewport = external ? mExternalDisplay : mInternalDisplay; 1.211 + if (viewport.displayId >= 0) { 1.212 + *outViewport = viewport; 1.213 + return true; 1.214 + } 1.215 + return false; 1.216 +} 1.217 + 1.218 +void InputReaderConfiguration::setDisplayInfo(bool external, const DisplayViewport& viewport) { 1.219 + DisplayViewport& v = external ? mExternalDisplay : mInternalDisplay; 1.220 + v = viewport; 1.221 +} 1.222 + 1.223 + 1.224 +// --- InputReader --- 1.225 + 1.226 +InputReader::InputReader(const sp<EventHubInterface>& eventHub, 1.227 + const sp<InputReaderPolicyInterface>& policy, 1.228 + const sp<InputListenerInterface>& listener) : 1.229 + mContext(this), mEventHub(eventHub), mPolicy(policy), 1.230 + mGlobalMetaState(0), mGeneration(1), 1.231 + mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX), 1.232 + mConfigurationChangesToRefresh(0) { 1.233 + mQueuedListener = new QueuedInputListener(listener); 1.234 + 1.235 + { // acquire lock 1.236 + AutoMutex _l(mLock); 1.237 + 1.238 + refreshConfigurationLocked(0); 1.239 + updateGlobalMetaStateLocked(); 1.240 + } // release lock 1.241 +} 1.242 + 1.243 +InputReader::~InputReader() { 1.244 + for (size_t i = 0; i < mDevices.size(); i++) { 1.245 + delete mDevices.valueAt(i); 1.246 + } 1.247 +} 1.248 + 1.249 +void InputReader::loopOnce() { 1.250 + int32_t oldGeneration; 1.251 + int32_t timeoutMillis; 1.252 + bool inputDevicesChanged = false; 1.253 + Vector<InputDeviceInfo> inputDevices; 1.254 + { // acquire lock 1.255 + AutoMutex _l(mLock); 1.256 + 1.257 + oldGeneration = mGeneration; 1.258 + timeoutMillis = -1; 1.259 + 1.260 + uint32_t changes = mConfigurationChangesToRefresh; 1.261 + if (changes) { 1.262 + mConfigurationChangesToRefresh = 0; 1.263 + timeoutMillis = 0; 1.264 + refreshConfigurationLocked(changes); 1.265 + } else if (mNextTimeout != LLONG_MAX) { 1.266 + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); 1.267 + timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout); 1.268 + } 1.269 + } // release lock 1.270 + 1.271 + size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); 1.272 + 1.273 + { // acquire lock 1.274 + AutoMutex _l(mLock); 1.275 + mReaderIsAliveCondition.broadcast(); 1.276 + 1.277 + if (count) { 1.278 + processEventsLocked(mEventBuffer, count); 1.279 + } 1.280 + 1.281 + if (mNextTimeout != LLONG_MAX) { 1.282 + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); 1.283 + if (now >= mNextTimeout) { 1.284 +#if DEBUG_RAW_EVENTS 1.285 + ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f); 1.286 +#endif 1.287 + mNextTimeout = LLONG_MAX; 1.288 + timeoutExpiredLocked(now); 1.289 + } 1.290 + } 1.291 + 1.292 + if (oldGeneration != mGeneration) { 1.293 + inputDevicesChanged = true; 1.294 + getInputDevicesLocked(inputDevices); 1.295 + } 1.296 + } // release lock 1.297 + 1.298 + // Send out a message that the describes the changed input devices. 1.299 + if (inputDevicesChanged) { 1.300 + mPolicy->notifyInputDevicesChanged(inputDevices); 1.301 + } 1.302 + 1.303 + // Flush queued events out to the listener. 1.304 + // This must happen outside of the lock because the listener could potentially call 1.305 + // back into the InputReader's methods, such as getScanCodeState, or become blocked 1.306 + // on another thread similarly waiting to acquire the InputReader lock thereby 1.307 + // resulting in a deadlock. This situation is actually quite plausible because the 1.308 + // listener is actually the input dispatcher, which calls into the window manager, 1.309 + // which occasionally calls into the input reader. 1.310 + mQueuedListener->flush(); 1.311 +} 1.312 + 1.313 +void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) { 1.314 + for (const RawEvent* rawEvent = rawEvents; count;) { 1.315 + int32_t type = rawEvent->type; 1.316 + size_t batchSize = 1; 1.317 + if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) { 1.318 + int32_t deviceId = rawEvent->deviceId; 1.319 + while (batchSize < count) { 1.320 + if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT 1.321 + || rawEvent[batchSize].deviceId != deviceId) { 1.322 + break; 1.323 + } 1.324 + batchSize += 1; 1.325 + } 1.326 +#if DEBUG_RAW_EVENTS 1.327 + ALOGD("BatchSize: %d Count: %d", batchSize, count); 1.328 +#endif 1.329 + processEventsForDeviceLocked(deviceId, rawEvent, batchSize); 1.330 + } else { 1.331 + switch (rawEvent->type) { 1.332 + case EventHubInterface::DEVICE_ADDED: 1.333 + addDeviceLocked(rawEvent->when, rawEvent->deviceId); 1.334 + break; 1.335 + case EventHubInterface::DEVICE_REMOVED: 1.336 + removeDeviceLocked(rawEvent->when, rawEvent->deviceId); 1.337 + break; 1.338 + case EventHubInterface::FINISHED_DEVICE_SCAN: 1.339 + handleConfigurationChangedLocked(rawEvent->when); 1.340 + break; 1.341 + default: 1.342 + ALOG_ASSERT(false); // can't happen 1.343 + break; 1.344 + } 1.345 + } 1.346 + count -= batchSize; 1.347 + rawEvent += batchSize; 1.348 + } 1.349 +} 1.350 + 1.351 +void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) { 1.352 + ssize_t deviceIndex = mDevices.indexOfKey(deviceId); 1.353 + if (deviceIndex >= 0) { 1.354 + ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId); 1.355 + return; 1.356 + } 1.357 + 1.358 + InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId); 1.359 + uint32_t classes = mEventHub->getDeviceClasses(deviceId); 1.360 + 1.361 + InputDevice* device = createDeviceLocked(deviceId, identifier, classes); 1.362 + device->configure(when, &mConfig, 0); 1.363 + device->reset(when); 1.364 + 1.365 + if (device->isIgnored()) { 1.366 + ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, 1.367 + identifier.name.string()); 1.368 + } else { 1.369 + ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, 1.370 + identifier.name.string(), device->getSources()); 1.371 + } 1.372 + 1.373 + mDevices.add(deviceId, device); 1.374 + bumpGenerationLocked(); 1.375 +} 1.376 + 1.377 +void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) { 1.378 + InputDevice* device = NULL; 1.379 + ssize_t deviceIndex = mDevices.indexOfKey(deviceId); 1.380 + if (deviceIndex < 0) { 1.381 + ALOGW("Ignoring spurious device removed event for deviceId %d.", deviceId); 1.382 + return; 1.383 + } 1.384 + 1.385 + device = mDevices.valueAt(deviceIndex); 1.386 + mDevices.removeItemsAt(deviceIndex, 1); 1.387 + bumpGenerationLocked(); 1.388 + 1.389 + if (device->isIgnored()) { 1.390 + ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)", 1.391 + device->getId(), device->getName().string()); 1.392 + } else { 1.393 + ALOGI("Device removed: id=%d, name='%s', sources=0x%08x", 1.394 + device->getId(), device->getName().string(), device->getSources()); 1.395 + } 1.396 + 1.397 + device->reset(when); 1.398 + delete device; 1.399 +} 1.400 + 1.401 +InputDevice* InputReader::createDeviceLocked(int32_t deviceId, 1.402 + const InputDeviceIdentifier& identifier, uint32_t classes) { 1.403 + InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(), 1.404 + identifier, classes); 1.405 + 1.406 + // External devices. 1.407 + if (classes & INPUT_DEVICE_CLASS_EXTERNAL) { 1.408 + device->setExternal(true); 1.409 + } 1.410 + 1.411 + // Switch-like devices. 1.412 + if (classes & INPUT_DEVICE_CLASS_SWITCH) { 1.413 + device->addMapper(new SwitchInputMapper(device)); 1.414 + } 1.415 + 1.416 + // Vibrator-like devices. 1.417 + if (classes & INPUT_DEVICE_CLASS_VIBRATOR) { 1.418 + device->addMapper(new VibratorInputMapper(device)); 1.419 + } 1.420 + 1.421 + // Keyboard-like devices. 1.422 + uint32_t keyboardSource = 0; 1.423 + int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC; 1.424 + if (classes & INPUT_DEVICE_CLASS_KEYBOARD) { 1.425 + keyboardSource |= AINPUT_SOURCE_KEYBOARD; 1.426 + } 1.427 + if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) { 1.428 + keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC; 1.429 + } 1.430 + if (classes & INPUT_DEVICE_CLASS_DPAD) { 1.431 + keyboardSource |= AINPUT_SOURCE_DPAD; 1.432 + } 1.433 + if (classes & INPUT_DEVICE_CLASS_GAMEPAD) { 1.434 + keyboardSource |= AINPUT_SOURCE_GAMEPAD; 1.435 + } 1.436 + 1.437 + if (keyboardSource != 0) { 1.438 + device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType)); 1.439 + } 1.440 + 1.441 + // Cursor-like devices. 1.442 + if (classes & INPUT_DEVICE_CLASS_CURSOR) { 1.443 + device->addMapper(new CursorInputMapper(device)); 1.444 + } 1.445 + 1.446 + // Touchscreens and touchpad devices. 1.447 + if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) { 1.448 + device->addMapper(new MultiTouchInputMapper(device)); 1.449 + } else if (classes & INPUT_DEVICE_CLASS_TOUCH) { 1.450 + device->addMapper(new SingleTouchInputMapper(device)); 1.451 + } 1.452 + 1.453 + // Joystick-like devices. 1.454 + if (classes & INPUT_DEVICE_CLASS_JOYSTICK) { 1.455 + device->addMapper(new JoystickInputMapper(device)); 1.456 + } 1.457 + 1.458 + return device; 1.459 +} 1.460 + 1.461 +void InputReader::processEventsForDeviceLocked(int32_t deviceId, 1.462 + const RawEvent* rawEvents, size_t count) { 1.463 + ssize_t deviceIndex = mDevices.indexOfKey(deviceId); 1.464 + if (deviceIndex < 0) { 1.465 + ALOGW("Discarding event for unknown deviceId %d.", deviceId); 1.466 + return; 1.467 + } 1.468 + 1.469 + InputDevice* device = mDevices.valueAt(deviceIndex); 1.470 + if (device->isIgnored()) { 1.471 + //ALOGD("Discarding event for ignored deviceId %d.", deviceId); 1.472 + return; 1.473 + } 1.474 + 1.475 + device->process(rawEvents, count); 1.476 +} 1.477 + 1.478 +void InputReader::timeoutExpiredLocked(nsecs_t when) { 1.479 + for (size_t i = 0; i < mDevices.size(); i++) { 1.480 + InputDevice* device = mDevices.valueAt(i); 1.481 + if (!device->isIgnored()) { 1.482 + device->timeoutExpired(when); 1.483 + } 1.484 + } 1.485 +} 1.486 + 1.487 +void InputReader::handleConfigurationChangedLocked(nsecs_t when) { 1.488 + // Reset global meta state because it depends on the list of all configured devices. 1.489 + updateGlobalMetaStateLocked(); 1.490 + 1.491 + // Enqueue configuration changed. 1.492 + NotifyConfigurationChangedArgs args(when); 1.493 + mQueuedListener->notifyConfigurationChanged(&args); 1.494 +} 1.495 + 1.496 +void InputReader::refreshConfigurationLocked(uint32_t changes) { 1.497 + mPolicy->getReaderConfiguration(&mConfig); 1.498 + mEventHub->setExcludedDevices(mConfig.excludedDeviceNames); 1.499 + 1.500 + if (changes) { 1.501 + ALOGI("Reconfiguring input devices. changes=0x%08x", changes); 1.502 + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); 1.503 + 1.504 + if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) { 1.505 + mEventHub->requestReopenDevices(); 1.506 + } else { 1.507 + for (size_t i = 0; i < mDevices.size(); i++) { 1.508 + InputDevice* device = mDevices.valueAt(i); 1.509 + device->configure(now, &mConfig, changes); 1.510 + } 1.511 + } 1.512 + } 1.513 +} 1.514 + 1.515 +void InputReader::updateGlobalMetaStateLocked() { 1.516 + mGlobalMetaState = 0; 1.517 + 1.518 + for (size_t i = 0; i < mDevices.size(); i++) { 1.519 + InputDevice* device = mDevices.valueAt(i); 1.520 + mGlobalMetaState |= device->getMetaState(); 1.521 + } 1.522 +} 1.523 + 1.524 +int32_t InputReader::getGlobalMetaStateLocked() { 1.525 + return mGlobalMetaState; 1.526 +} 1.527 + 1.528 +void InputReader::disableVirtualKeysUntilLocked(nsecs_t time) { 1.529 + mDisableVirtualKeysTimeout = time; 1.530 +} 1.531 + 1.532 +bool InputReader::shouldDropVirtualKeyLocked(nsecs_t now, 1.533 + InputDevice* device, int32_t keyCode, int32_t scanCode) { 1.534 + if (now < mDisableVirtualKeysTimeout) { 1.535 + ALOGI("Dropping virtual key from device %s because virtual keys are " 1.536 + "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d", 1.537 + device->getName().string(), 1.538 + (mDisableVirtualKeysTimeout - now) * 0.000001, 1.539 + keyCode, scanCode); 1.540 + return true; 1.541 + } else { 1.542 + return false; 1.543 + } 1.544 +} 1.545 + 1.546 +void InputReader::fadePointerLocked() { 1.547 + for (size_t i = 0; i < mDevices.size(); i++) { 1.548 + InputDevice* device = mDevices.valueAt(i); 1.549 + device->fadePointer(); 1.550 + } 1.551 +} 1.552 + 1.553 +void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) { 1.554 + if (when < mNextTimeout) { 1.555 + mNextTimeout = when; 1.556 + mEventHub->wake(); 1.557 + } 1.558 +} 1.559 + 1.560 +int32_t InputReader::bumpGenerationLocked() { 1.561 + return ++mGeneration; 1.562 +} 1.563 + 1.564 +void InputReader::getInputDevices(Vector<InputDeviceInfo>& outInputDevices) { 1.565 + AutoMutex _l(mLock); 1.566 + getInputDevicesLocked(outInputDevices); 1.567 +} 1.568 + 1.569 +void InputReader::getInputDevicesLocked(Vector<InputDeviceInfo>& outInputDevices) { 1.570 + outInputDevices.clear(); 1.571 + 1.572 + size_t numDevices = mDevices.size(); 1.573 + for (size_t i = 0; i < numDevices; i++) { 1.574 + InputDevice* device = mDevices.valueAt(i); 1.575 + if (!device->isIgnored()) { 1.576 + outInputDevices.push(); 1.577 + device->getDeviceInfo(&outInputDevices.editTop()); 1.578 + } 1.579 + } 1.580 +} 1.581 + 1.582 +int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask, 1.583 + int32_t keyCode) { 1.584 + AutoMutex _l(mLock); 1.585 + 1.586 + return getStateLocked(deviceId, sourceMask, keyCode, &InputDevice::getKeyCodeState); 1.587 +} 1.588 + 1.589 +int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask, 1.590 + int32_t scanCode) { 1.591 + AutoMutex _l(mLock); 1.592 + 1.593 + return getStateLocked(deviceId, sourceMask, scanCode, &InputDevice::getScanCodeState); 1.594 +} 1.595 + 1.596 +int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) { 1.597 + AutoMutex _l(mLock); 1.598 + 1.599 + return getStateLocked(deviceId, sourceMask, switchCode, &InputDevice::getSwitchState); 1.600 +} 1.601 + 1.602 +int32_t InputReader::getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code, 1.603 + GetStateFunc getStateFunc) { 1.604 + int32_t result = AKEY_STATE_UNKNOWN; 1.605 + if (deviceId >= 0) { 1.606 + ssize_t deviceIndex = mDevices.indexOfKey(deviceId); 1.607 + if (deviceIndex >= 0) { 1.608 + InputDevice* device = mDevices.valueAt(deviceIndex); 1.609 + if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) { 1.610 + result = (device->*getStateFunc)(sourceMask, code); 1.611 + } 1.612 + } 1.613 + } else { 1.614 + size_t numDevices = mDevices.size(); 1.615 + for (size_t i = 0; i < numDevices; i++) { 1.616 + InputDevice* device = mDevices.valueAt(i); 1.617 + if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) { 1.618 + // If any device reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that 1.619 + // value. Otherwise, return AKEY_STATE_UP as long as one device reports it. 1.620 + int32_t currentResult = (device->*getStateFunc)(sourceMask, code); 1.621 + if (currentResult >= AKEY_STATE_DOWN) { 1.622 + return currentResult; 1.623 + } else if (currentResult == AKEY_STATE_UP) { 1.624 + result = currentResult; 1.625 + } 1.626 + } 1.627 + } 1.628 + } 1.629 + return result; 1.630 +} 1.631 + 1.632 +bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask, 1.633 + size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) { 1.634 + AutoMutex _l(mLock); 1.635 + 1.636 + memset(outFlags, 0, numCodes); 1.637 + return markSupportedKeyCodesLocked(deviceId, sourceMask, numCodes, keyCodes, outFlags); 1.638 +} 1.639 + 1.640 +bool InputReader::markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask, 1.641 + size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) { 1.642 + bool result = false; 1.643 + if (deviceId >= 0) { 1.644 + ssize_t deviceIndex = mDevices.indexOfKey(deviceId); 1.645 + if (deviceIndex >= 0) { 1.646 + InputDevice* device = mDevices.valueAt(deviceIndex); 1.647 + if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) { 1.648 + result = device->markSupportedKeyCodes(sourceMask, 1.649 + numCodes, keyCodes, outFlags); 1.650 + } 1.651 + } 1.652 + } else { 1.653 + size_t numDevices = mDevices.size(); 1.654 + for (size_t i = 0; i < numDevices; i++) { 1.655 + InputDevice* device = mDevices.valueAt(i); 1.656 + if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) { 1.657 + result |= device->markSupportedKeyCodes(sourceMask, 1.658 + numCodes, keyCodes, outFlags); 1.659 + } 1.660 + } 1.661 + } 1.662 + return result; 1.663 +} 1.664 + 1.665 +void InputReader::requestRefreshConfiguration(uint32_t changes) { 1.666 + AutoMutex _l(mLock); 1.667 + 1.668 + if (changes) { 1.669 + bool needWake = !mConfigurationChangesToRefresh; 1.670 + mConfigurationChangesToRefresh |= changes; 1.671 + 1.672 + if (needWake) { 1.673 + mEventHub->wake(); 1.674 + } 1.675 + } 1.676 +} 1.677 + 1.678 +void InputReader::vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize, 1.679 + ssize_t repeat, int32_t token) { 1.680 + AutoMutex _l(mLock); 1.681 + 1.682 + ssize_t deviceIndex = mDevices.indexOfKey(deviceId); 1.683 + if (deviceIndex >= 0) { 1.684 + InputDevice* device = mDevices.valueAt(deviceIndex); 1.685 + device->vibrate(pattern, patternSize, repeat, token); 1.686 + } 1.687 +} 1.688 + 1.689 +void InputReader::cancelVibrate(int32_t deviceId, int32_t token) { 1.690 + AutoMutex _l(mLock); 1.691 + 1.692 + ssize_t deviceIndex = mDevices.indexOfKey(deviceId); 1.693 + if (deviceIndex >= 0) { 1.694 + InputDevice* device = mDevices.valueAt(deviceIndex); 1.695 + device->cancelVibrate(token); 1.696 + } 1.697 +} 1.698 + 1.699 +void InputReader::dump(String8& dump) { 1.700 + AutoMutex _l(mLock); 1.701 + 1.702 + mEventHub->dump(dump); 1.703 + dump.append("\n"); 1.704 + 1.705 + dump.append("Input Reader State:\n"); 1.706 + 1.707 + for (size_t i = 0; i < mDevices.size(); i++) { 1.708 + mDevices.valueAt(i)->dump(dump); 1.709 + } 1.710 + 1.711 + dump.append(INDENT "Configuration:\n"); 1.712 + dump.append(INDENT2 "ExcludedDeviceNames: ["); 1.713 + for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) { 1.714 + if (i != 0) { 1.715 + dump.append(", "); 1.716 + } 1.717 + dump.append(mConfig.excludedDeviceNames.itemAt(i).string()); 1.718 + } 1.719 + dump.append("]\n"); 1.720 + dump.appendFormat(INDENT2 "VirtualKeyQuietTime: %0.1fms\n", 1.721 + mConfig.virtualKeyQuietTime * 0.000001f); 1.722 + 1.723 + dump.appendFormat(INDENT2 "PointerVelocityControlParameters: " 1.724 + "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n", 1.725 + mConfig.pointerVelocityControlParameters.scale, 1.726 + mConfig.pointerVelocityControlParameters.lowThreshold, 1.727 + mConfig.pointerVelocityControlParameters.highThreshold, 1.728 + mConfig.pointerVelocityControlParameters.acceleration); 1.729 + 1.730 + dump.appendFormat(INDENT2 "WheelVelocityControlParameters: " 1.731 + "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n", 1.732 + mConfig.wheelVelocityControlParameters.scale, 1.733 + mConfig.wheelVelocityControlParameters.lowThreshold, 1.734 + mConfig.wheelVelocityControlParameters.highThreshold, 1.735 + mConfig.wheelVelocityControlParameters.acceleration); 1.736 + 1.737 + dump.appendFormat(INDENT2 "PointerGesture:\n"); 1.738 + dump.appendFormat(INDENT3 "Enabled: %s\n", 1.739 + toString(mConfig.pointerGesturesEnabled)); 1.740 + dump.appendFormat(INDENT3 "QuietInterval: %0.1fms\n", 1.741 + mConfig.pointerGestureQuietInterval * 0.000001f); 1.742 + dump.appendFormat(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n", 1.743 + mConfig.pointerGestureDragMinSwitchSpeed); 1.744 + dump.appendFormat(INDENT3 "TapInterval: %0.1fms\n", 1.745 + mConfig.pointerGestureTapInterval * 0.000001f); 1.746 + dump.appendFormat(INDENT3 "TapDragInterval: %0.1fms\n", 1.747 + mConfig.pointerGestureTapDragInterval * 0.000001f); 1.748 + dump.appendFormat(INDENT3 "TapSlop: %0.1fpx\n", 1.749 + mConfig.pointerGestureTapSlop); 1.750 + dump.appendFormat(INDENT3 "MultitouchSettleInterval: %0.1fms\n", 1.751 + mConfig.pointerGestureMultitouchSettleInterval * 0.000001f); 1.752 + dump.appendFormat(INDENT3 "MultitouchMinDistance: %0.1fpx\n", 1.753 + mConfig.pointerGestureMultitouchMinDistance); 1.754 + dump.appendFormat(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n", 1.755 + mConfig.pointerGestureSwipeTransitionAngleCosine); 1.756 + dump.appendFormat(INDENT3 "SwipeMaxWidthRatio: %0.1f\n", 1.757 + mConfig.pointerGestureSwipeMaxWidthRatio); 1.758 + dump.appendFormat(INDENT3 "MovementSpeedRatio: %0.1f\n", 1.759 + mConfig.pointerGestureMovementSpeedRatio); 1.760 + dump.appendFormat(INDENT3 "ZoomSpeedRatio: %0.1f\n", 1.761 + mConfig.pointerGestureZoomSpeedRatio); 1.762 +} 1.763 + 1.764 +void InputReader::monitor() { 1.765 + // Acquire and release the lock to ensure that the reader has not deadlocked. 1.766 + mLock.lock(); 1.767 + mEventHub->wake(); 1.768 + mReaderIsAliveCondition.wait(mLock); 1.769 + mLock.unlock(); 1.770 + 1.771 + // Check the EventHub 1.772 + mEventHub->monitor(); 1.773 +} 1.774 + 1.775 + 1.776 +// --- InputReader::ContextImpl --- 1.777 + 1.778 +InputReader::ContextImpl::ContextImpl(InputReader* reader) : 1.779 + mReader(reader) { 1.780 +} 1.781 + 1.782 +void InputReader::ContextImpl::updateGlobalMetaState() { 1.783 + // lock is already held by the input loop 1.784 + mReader->updateGlobalMetaStateLocked(); 1.785 +} 1.786 + 1.787 +int32_t InputReader::ContextImpl::getGlobalMetaState() { 1.788 + // lock is already held by the input loop 1.789 + return mReader->getGlobalMetaStateLocked(); 1.790 +} 1.791 + 1.792 +void InputReader::ContextImpl::disableVirtualKeysUntil(nsecs_t time) { 1.793 + // lock is already held by the input loop 1.794 + mReader->disableVirtualKeysUntilLocked(time); 1.795 +} 1.796 + 1.797 +bool InputReader::ContextImpl::shouldDropVirtualKey(nsecs_t now, 1.798 + InputDevice* device, int32_t keyCode, int32_t scanCode) { 1.799 + // lock is already held by the input loop 1.800 + return mReader->shouldDropVirtualKeyLocked(now, device, keyCode, scanCode); 1.801 +} 1.802 + 1.803 +void InputReader::ContextImpl::fadePointer() { 1.804 + // lock is already held by the input loop 1.805 + mReader->fadePointerLocked(); 1.806 +} 1.807 + 1.808 +void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) { 1.809 + // lock is already held by the input loop 1.810 + mReader->requestTimeoutAtTimeLocked(when); 1.811 +} 1.812 + 1.813 +int32_t InputReader::ContextImpl::bumpGeneration() { 1.814 + // lock is already held by the input loop 1.815 + return mReader->bumpGenerationLocked(); 1.816 +} 1.817 + 1.818 +InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() { 1.819 + return mReader->mPolicy.get(); 1.820 +} 1.821 + 1.822 +InputListenerInterface* InputReader::ContextImpl::getListener() { 1.823 + return mReader->mQueuedListener.get(); 1.824 +} 1.825 + 1.826 +EventHubInterface* InputReader::ContextImpl::getEventHub() { 1.827 + return mReader->mEventHub.get(); 1.828 +} 1.829 + 1.830 + 1.831 +// --- InputReaderThread --- 1.832 + 1.833 +InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) : 1.834 + Thread(/*canCallJava*/ true), mReader(reader) { 1.835 +} 1.836 + 1.837 +InputReaderThread::~InputReaderThread() { 1.838 +} 1.839 + 1.840 +bool InputReaderThread::threadLoop() { 1.841 + mReader->loopOnce(); 1.842 + return true; 1.843 +} 1.844 + 1.845 + 1.846 +// --- InputDevice --- 1.847 + 1.848 +InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation, 1.849 + const InputDeviceIdentifier& identifier, uint32_t classes) : 1.850 + mContext(context), mId(id), mGeneration(generation), 1.851 + mIdentifier(identifier), mClasses(classes), 1.852 + mSources(0), mIsExternal(false), mDropUntilNextSync(false) { 1.853 +} 1.854 + 1.855 +InputDevice::~InputDevice() { 1.856 + size_t numMappers = mMappers.size(); 1.857 + for (size_t i = 0; i < numMappers; i++) { 1.858 + delete mMappers[i]; 1.859 + } 1.860 + mMappers.clear(); 1.861 +} 1.862 + 1.863 +void InputDevice::dump(String8& dump) { 1.864 + InputDeviceInfo deviceInfo; 1.865 + getDeviceInfo(& deviceInfo); 1.866 + 1.867 + dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(), 1.868 + deviceInfo.getDisplayName().string()); 1.869 + dump.appendFormat(INDENT2 "Generation: %d\n", mGeneration); 1.870 + dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal)); 1.871 + dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources()); 1.872 + dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType()); 1.873 + 1.874 + const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges(); 1.875 + if (!ranges.isEmpty()) { 1.876 + dump.append(INDENT2 "Motion Ranges:\n"); 1.877 + for (size_t i = 0; i < ranges.size(); i++) { 1.878 + const InputDeviceInfo::MotionRange& range = ranges.itemAt(i); 1.879 + const char* label = getAxisLabel(range.axis); 1.880 + char name[32]; 1.881 + if (label) { 1.882 + strncpy(name, label, sizeof(name)); 1.883 + name[sizeof(name) - 1] = '\0'; 1.884 + } else { 1.885 + snprintf(name, sizeof(name), "%d", range.axis); 1.886 + } 1.887 + dump.appendFormat(INDENT3 "%s: source=0x%08x, " 1.888 + "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, resolution=%0.3f\n", 1.889 + name, range.source, range.min, range.max, range.flat, range.fuzz, 1.890 + range.resolution); 1.891 + } 1.892 + } 1.893 + 1.894 + size_t numMappers = mMappers.size(); 1.895 + for (size_t i = 0; i < numMappers; i++) { 1.896 + InputMapper* mapper = mMappers[i]; 1.897 + mapper->dump(dump); 1.898 + } 1.899 +} 1.900 + 1.901 +void InputDevice::addMapper(InputMapper* mapper) { 1.902 + mMappers.add(mapper); 1.903 +} 1.904 + 1.905 +void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) { 1.906 + mSources = 0; 1.907 + 1.908 + if (!isIgnored()) { 1.909 + if (!changes) { // first time only 1.910 + mContext->getEventHub()->getConfiguration(mId, &mConfiguration); 1.911 + } 1.912 + 1.913 + if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) { 1.914 + if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) { 1.915 + sp<KeyCharacterMap> keyboardLayout = 1.916 + mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier.descriptor); 1.917 + if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) { 1.918 + bumpGeneration(); 1.919 + } 1.920 + } 1.921 + } 1.922 + 1.923 + if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) { 1.924 + if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) { 1.925 + String8 alias = mContext->getPolicy()->getDeviceAlias(mIdentifier); 1.926 + if (mAlias != alias) { 1.927 + mAlias = alias; 1.928 + bumpGeneration(); 1.929 + } 1.930 + } 1.931 + } 1.932 + 1.933 + size_t numMappers = mMappers.size(); 1.934 + for (size_t i = 0; i < numMappers; i++) { 1.935 + InputMapper* mapper = mMappers[i]; 1.936 + mapper->configure(when, config, changes); 1.937 + mSources |= mapper->getSources(); 1.938 + } 1.939 + } 1.940 +} 1.941 + 1.942 +void InputDevice::reset(nsecs_t when) { 1.943 + size_t numMappers = mMappers.size(); 1.944 + for (size_t i = 0; i < numMappers; i++) { 1.945 + InputMapper* mapper = mMappers[i]; 1.946 + mapper->reset(when); 1.947 + } 1.948 + 1.949 + mContext->updateGlobalMetaState(); 1.950 + 1.951 + notifyReset(when); 1.952 +} 1.953 + 1.954 +void InputDevice::process(const RawEvent* rawEvents, size_t count) { 1.955 + // Process all of the events in order for each mapper. 1.956 + // We cannot simply ask each mapper to process them in bulk because mappers may 1.957 + // have side-effects that must be interleaved. For example, joystick movement events and 1.958 + // gamepad button presses are handled by different mappers but they should be dispatched 1.959 + // in the order received. 1.960 + size_t numMappers = mMappers.size(); 1.961 + for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) { 1.962 +#if DEBUG_RAW_EVENTS 1.963 + ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%lld", 1.964 + rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value, 1.965 + rawEvent->when); 1.966 +#endif 1.967 + 1.968 + if (mDropUntilNextSync) { 1.969 + if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { 1.970 + mDropUntilNextSync = false; 1.971 +#if DEBUG_RAW_EVENTS 1.972 + ALOGD("Recovered from input event buffer overrun."); 1.973 +#endif 1.974 + } else { 1.975 +#if DEBUG_RAW_EVENTS 1.976 + ALOGD("Dropped input event while waiting for next input sync."); 1.977 +#endif 1.978 + } 1.979 + } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) { 1.980 + ALOGI("Detected input event buffer overrun for device %s.", getName().string()); 1.981 + mDropUntilNextSync = true; 1.982 + reset(rawEvent->when); 1.983 + } else { 1.984 + for (size_t i = 0; i < numMappers; i++) { 1.985 + InputMapper* mapper = mMappers[i]; 1.986 + mapper->process(rawEvent); 1.987 + } 1.988 + } 1.989 + } 1.990 +} 1.991 + 1.992 +void InputDevice::timeoutExpired(nsecs_t when) { 1.993 + size_t numMappers = mMappers.size(); 1.994 + for (size_t i = 0; i < numMappers; i++) { 1.995 + InputMapper* mapper = mMappers[i]; 1.996 + mapper->timeoutExpired(when); 1.997 + } 1.998 +} 1.999 + 1.1000 +void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) { 1.1001 + outDeviceInfo->initialize(mId, mGeneration, mIdentifier, mAlias, mIsExternal); 1.1002 + 1.1003 + size_t numMappers = mMappers.size(); 1.1004 + for (size_t i = 0; i < numMappers; i++) { 1.1005 + InputMapper* mapper = mMappers[i]; 1.1006 + mapper->populateDeviceInfo(outDeviceInfo); 1.1007 + } 1.1008 +} 1.1009 + 1.1010 +int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) { 1.1011 + return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState); 1.1012 +} 1.1013 + 1.1014 +int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) { 1.1015 + return getState(sourceMask, scanCode, & InputMapper::getScanCodeState); 1.1016 +} 1.1017 + 1.1018 +int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) { 1.1019 + return getState(sourceMask, switchCode, & InputMapper::getSwitchState); 1.1020 +} 1.1021 + 1.1022 +int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) { 1.1023 + int32_t result = AKEY_STATE_UNKNOWN; 1.1024 + size_t numMappers = mMappers.size(); 1.1025 + for (size_t i = 0; i < numMappers; i++) { 1.1026 + InputMapper* mapper = mMappers[i]; 1.1027 + if (sourcesMatchMask(mapper->getSources(), sourceMask)) { 1.1028 + // If any mapper reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that 1.1029 + // value. Otherwise, return AKEY_STATE_UP as long as one mapper reports it. 1.1030 + int32_t currentResult = (mapper->*getStateFunc)(sourceMask, code); 1.1031 + if (currentResult >= AKEY_STATE_DOWN) { 1.1032 + return currentResult; 1.1033 + } else if (currentResult == AKEY_STATE_UP) { 1.1034 + result = currentResult; 1.1035 + } 1.1036 + } 1.1037 + } 1.1038 + return result; 1.1039 +} 1.1040 + 1.1041 +bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, 1.1042 + const int32_t* keyCodes, uint8_t* outFlags) { 1.1043 + bool result = false; 1.1044 + size_t numMappers = mMappers.size(); 1.1045 + for (size_t i = 0; i < numMappers; i++) { 1.1046 + InputMapper* mapper = mMappers[i]; 1.1047 + if (sourcesMatchMask(mapper->getSources(), sourceMask)) { 1.1048 + result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags); 1.1049 + } 1.1050 + } 1.1051 + return result; 1.1052 +} 1.1053 + 1.1054 +void InputDevice::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, 1.1055 + int32_t token) { 1.1056 + size_t numMappers = mMappers.size(); 1.1057 + for (size_t i = 0; i < numMappers; i++) { 1.1058 + InputMapper* mapper = mMappers[i]; 1.1059 + mapper->vibrate(pattern, patternSize, repeat, token); 1.1060 + } 1.1061 +} 1.1062 + 1.1063 +void InputDevice::cancelVibrate(int32_t token) { 1.1064 + size_t numMappers = mMappers.size(); 1.1065 + for (size_t i = 0; i < numMappers; i++) { 1.1066 + InputMapper* mapper = mMappers[i]; 1.1067 + mapper->cancelVibrate(token); 1.1068 + } 1.1069 +} 1.1070 + 1.1071 +int32_t InputDevice::getMetaState() { 1.1072 + int32_t result = 0; 1.1073 + size_t numMappers = mMappers.size(); 1.1074 + for (size_t i = 0; i < numMappers; i++) { 1.1075 + InputMapper* mapper = mMappers[i]; 1.1076 + result |= mapper->getMetaState(); 1.1077 + } 1.1078 + return result; 1.1079 +} 1.1080 + 1.1081 +void InputDevice::fadePointer() { 1.1082 + size_t numMappers = mMappers.size(); 1.1083 + for (size_t i = 0; i < numMappers; i++) { 1.1084 + InputMapper* mapper = mMappers[i]; 1.1085 + mapper->fadePointer(); 1.1086 + } 1.1087 +} 1.1088 + 1.1089 +void InputDevice::bumpGeneration() { 1.1090 + mGeneration = mContext->bumpGeneration(); 1.1091 +} 1.1092 + 1.1093 +void InputDevice::notifyReset(nsecs_t when) { 1.1094 + NotifyDeviceResetArgs args(when, mId); 1.1095 + mContext->getListener()->notifyDeviceReset(&args); 1.1096 +} 1.1097 + 1.1098 + 1.1099 +// --- CursorButtonAccumulator --- 1.1100 + 1.1101 +CursorButtonAccumulator::CursorButtonAccumulator() { 1.1102 + clearButtons(); 1.1103 +} 1.1104 + 1.1105 +void CursorButtonAccumulator::reset(InputDevice* device) { 1.1106 + mBtnLeft = device->isKeyPressed(BTN_LEFT); 1.1107 + mBtnRight = device->isKeyPressed(BTN_RIGHT); 1.1108 + mBtnMiddle = device->isKeyPressed(BTN_MIDDLE); 1.1109 + mBtnBack = device->isKeyPressed(BTN_BACK); 1.1110 + mBtnSide = device->isKeyPressed(BTN_SIDE); 1.1111 + mBtnForward = device->isKeyPressed(BTN_FORWARD); 1.1112 + mBtnExtra = device->isKeyPressed(BTN_EXTRA); 1.1113 + mBtnTask = device->isKeyPressed(BTN_TASK); 1.1114 +} 1.1115 + 1.1116 +void CursorButtonAccumulator::clearButtons() { 1.1117 + mBtnLeft = 0; 1.1118 + mBtnRight = 0; 1.1119 + mBtnMiddle = 0; 1.1120 + mBtnBack = 0; 1.1121 + mBtnSide = 0; 1.1122 + mBtnForward = 0; 1.1123 + mBtnExtra = 0; 1.1124 + mBtnTask = 0; 1.1125 +} 1.1126 + 1.1127 +void CursorButtonAccumulator::process(const RawEvent* rawEvent) { 1.1128 + if (rawEvent->type == EV_KEY) { 1.1129 + switch (rawEvent->code) { 1.1130 + case BTN_LEFT: 1.1131 + mBtnLeft = rawEvent->value; 1.1132 + break; 1.1133 + case BTN_RIGHT: 1.1134 + mBtnRight = rawEvent->value; 1.1135 + break; 1.1136 + case BTN_MIDDLE: 1.1137 + mBtnMiddle = rawEvent->value; 1.1138 + break; 1.1139 + case BTN_BACK: 1.1140 + mBtnBack = rawEvent->value; 1.1141 + break; 1.1142 + case BTN_SIDE: 1.1143 + mBtnSide = rawEvent->value; 1.1144 + break; 1.1145 + case BTN_FORWARD: 1.1146 + mBtnForward = rawEvent->value; 1.1147 + break; 1.1148 + case BTN_EXTRA: 1.1149 + mBtnExtra = rawEvent->value; 1.1150 + break; 1.1151 + case BTN_TASK: 1.1152 + mBtnTask = rawEvent->value; 1.1153 + break; 1.1154 + } 1.1155 + } 1.1156 +} 1.1157 + 1.1158 +uint32_t CursorButtonAccumulator::getButtonState() const { 1.1159 + uint32_t result = 0; 1.1160 + if (mBtnLeft) { 1.1161 + result |= AMOTION_EVENT_BUTTON_PRIMARY; 1.1162 + } 1.1163 + if (mBtnRight) { 1.1164 + result |= AMOTION_EVENT_BUTTON_SECONDARY; 1.1165 + } 1.1166 + if (mBtnMiddle) { 1.1167 + result |= AMOTION_EVENT_BUTTON_TERTIARY; 1.1168 + } 1.1169 + if (mBtnBack || mBtnSide) { 1.1170 + result |= AMOTION_EVENT_BUTTON_BACK; 1.1171 + } 1.1172 + if (mBtnForward || mBtnExtra) { 1.1173 + result |= AMOTION_EVENT_BUTTON_FORWARD; 1.1174 + } 1.1175 + return result; 1.1176 +} 1.1177 + 1.1178 + 1.1179 +// --- CursorMotionAccumulator --- 1.1180 + 1.1181 +CursorMotionAccumulator::CursorMotionAccumulator() { 1.1182 + clearRelativeAxes(); 1.1183 +} 1.1184 + 1.1185 +void CursorMotionAccumulator::reset(InputDevice* device) { 1.1186 + clearRelativeAxes(); 1.1187 +} 1.1188 + 1.1189 +void CursorMotionAccumulator::clearRelativeAxes() { 1.1190 + mRelX = 0; 1.1191 + mRelY = 0; 1.1192 +} 1.1193 + 1.1194 +void CursorMotionAccumulator::process(const RawEvent* rawEvent) { 1.1195 + if (rawEvent->type == EV_REL) { 1.1196 + switch (rawEvent->code) { 1.1197 + case REL_X: 1.1198 + mRelX = rawEvent->value; 1.1199 + break; 1.1200 + case REL_Y: 1.1201 + mRelY = rawEvent->value; 1.1202 + break; 1.1203 + } 1.1204 + } 1.1205 +} 1.1206 + 1.1207 +void CursorMotionAccumulator::finishSync() { 1.1208 + clearRelativeAxes(); 1.1209 +} 1.1210 + 1.1211 + 1.1212 +// --- CursorScrollAccumulator --- 1.1213 + 1.1214 +CursorScrollAccumulator::CursorScrollAccumulator() : 1.1215 + mHaveRelWheel(false), mHaveRelHWheel(false) { 1.1216 + clearRelativeAxes(); 1.1217 +} 1.1218 + 1.1219 +void CursorScrollAccumulator::configure(InputDevice* device) { 1.1220 + mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL); 1.1221 + mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL); 1.1222 +} 1.1223 + 1.1224 +void CursorScrollAccumulator::reset(InputDevice* device) { 1.1225 + clearRelativeAxes(); 1.1226 +} 1.1227 + 1.1228 +void CursorScrollAccumulator::clearRelativeAxes() { 1.1229 + mRelWheel = 0; 1.1230 + mRelHWheel = 0; 1.1231 +} 1.1232 + 1.1233 +void CursorScrollAccumulator::process(const RawEvent* rawEvent) { 1.1234 + if (rawEvent->type == EV_REL) { 1.1235 + switch (rawEvent->code) { 1.1236 + case REL_WHEEL: 1.1237 + mRelWheel = rawEvent->value; 1.1238 + break; 1.1239 + case REL_HWHEEL: 1.1240 + mRelHWheel = rawEvent->value; 1.1241 + break; 1.1242 + } 1.1243 + } 1.1244 +} 1.1245 + 1.1246 +void CursorScrollAccumulator::finishSync() { 1.1247 + clearRelativeAxes(); 1.1248 +} 1.1249 + 1.1250 + 1.1251 +// --- TouchButtonAccumulator --- 1.1252 + 1.1253 +TouchButtonAccumulator::TouchButtonAccumulator() : 1.1254 + mHaveBtnTouch(false), mHaveStylus(false) { 1.1255 + clearButtons(); 1.1256 +} 1.1257 + 1.1258 +void TouchButtonAccumulator::configure(InputDevice* device) { 1.1259 + mHaveBtnTouch = device->hasKey(BTN_TOUCH); 1.1260 + mHaveStylus = device->hasKey(BTN_TOOL_PEN) 1.1261 + || device->hasKey(BTN_TOOL_RUBBER) 1.1262 + || device->hasKey(BTN_TOOL_BRUSH) 1.1263 + || device->hasKey(BTN_TOOL_PENCIL) 1.1264 + || device->hasKey(BTN_TOOL_AIRBRUSH); 1.1265 +} 1.1266 + 1.1267 +void TouchButtonAccumulator::reset(InputDevice* device) { 1.1268 + mBtnTouch = device->isKeyPressed(BTN_TOUCH); 1.1269 + mBtnStylus = device->isKeyPressed(BTN_STYLUS); 1.1270 + mBtnStylus2 = device->isKeyPressed(BTN_STYLUS); 1.1271 + mBtnToolFinger = device->isKeyPressed(BTN_TOOL_FINGER); 1.1272 + mBtnToolPen = device->isKeyPressed(BTN_TOOL_PEN); 1.1273 + mBtnToolRubber = device->isKeyPressed(BTN_TOOL_RUBBER); 1.1274 + mBtnToolBrush = device->isKeyPressed(BTN_TOOL_BRUSH); 1.1275 + mBtnToolPencil = device->isKeyPressed(BTN_TOOL_PENCIL); 1.1276 + mBtnToolAirbrush = device->isKeyPressed(BTN_TOOL_AIRBRUSH); 1.1277 + mBtnToolMouse = device->isKeyPressed(BTN_TOOL_MOUSE); 1.1278 + mBtnToolLens = device->isKeyPressed(BTN_TOOL_LENS); 1.1279 + mBtnToolDoubleTap = device->isKeyPressed(BTN_TOOL_DOUBLETAP); 1.1280 + mBtnToolTripleTap = device->isKeyPressed(BTN_TOOL_TRIPLETAP); 1.1281 + mBtnToolQuadTap = device->isKeyPressed(BTN_TOOL_QUADTAP); 1.1282 +} 1.1283 + 1.1284 +void TouchButtonAccumulator::clearButtons() { 1.1285 + mBtnTouch = 0; 1.1286 + mBtnStylus = 0; 1.1287 + mBtnStylus2 = 0; 1.1288 + mBtnToolFinger = 0; 1.1289 + mBtnToolPen = 0; 1.1290 + mBtnToolRubber = 0; 1.1291 + mBtnToolBrush = 0; 1.1292 + mBtnToolPencil = 0; 1.1293 + mBtnToolAirbrush = 0; 1.1294 + mBtnToolMouse = 0; 1.1295 + mBtnToolLens = 0; 1.1296 + mBtnToolDoubleTap = 0; 1.1297 + mBtnToolTripleTap = 0; 1.1298 + mBtnToolQuadTap = 0; 1.1299 +} 1.1300 + 1.1301 +void TouchButtonAccumulator::process(const RawEvent* rawEvent) { 1.1302 + if (rawEvent->type == EV_KEY) { 1.1303 + switch (rawEvent->code) { 1.1304 + case BTN_TOUCH: 1.1305 + mBtnTouch = rawEvent->value; 1.1306 + break; 1.1307 + case BTN_STYLUS: 1.1308 + mBtnStylus = rawEvent->value; 1.1309 + break; 1.1310 + case BTN_STYLUS2: 1.1311 + mBtnStylus2 = rawEvent->value; 1.1312 + break; 1.1313 + case BTN_TOOL_FINGER: 1.1314 + mBtnToolFinger = rawEvent->value; 1.1315 + break; 1.1316 + case BTN_TOOL_PEN: 1.1317 + mBtnToolPen = rawEvent->value; 1.1318 + break; 1.1319 + case BTN_TOOL_RUBBER: 1.1320 + mBtnToolRubber = rawEvent->value; 1.1321 + break; 1.1322 + case BTN_TOOL_BRUSH: 1.1323 + mBtnToolBrush = rawEvent->value; 1.1324 + break; 1.1325 + case BTN_TOOL_PENCIL: 1.1326 + mBtnToolPencil = rawEvent->value; 1.1327 + break; 1.1328 + case BTN_TOOL_AIRBRUSH: 1.1329 + mBtnToolAirbrush = rawEvent->value; 1.1330 + break; 1.1331 + case BTN_TOOL_MOUSE: 1.1332 + mBtnToolMouse = rawEvent->value; 1.1333 + break; 1.1334 + case BTN_TOOL_LENS: 1.1335 + mBtnToolLens = rawEvent->value; 1.1336 + break; 1.1337 + case BTN_TOOL_DOUBLETAP: 1.1338 + mBtnToolDoubleTap = rawEvent->value; 1.1339 + break; 1.1340 + case BTN_TOOL_TRIPLETAP: 1.1341 + mBtnToolTripleTap = rawEvent->value; 1.1342 + break; 1.1343 + case BTN_TOOL_QUADTAP: 1.1344 + mBtnToolQuadTap = rawEvent->value; 1.1345 + break; 1.1346 + } 1.1347 + } 1.1348 +} 1.1349 + 1.1350 +uint32_t TouchButtonAccumulator::getButtonState() const { 1.1351 + uint32_t result = 0; 1.1352 + if (mBtnStylus) { 1.1353 + result |= AMOTION_EVENT_BUTTON_SECONDARY; 1.1354 + } 1.1355 + if (mBtnStylus2) { 1.1356 + result |= AMOTION_EVENT_BUTTON_TERTIARY; 1.1357 + } 1.1358 + return result; 1.1359 +} 1.1360 + 1.1361 +int32_t TouchButtonAccumulator::getToolType() const { 1.1362 + if (mBtnToolMouse || mBtnToolLens) { 1.1363 + return AMOTION_EVENT_TOOL_TYPE_MOUSE; 1.1364 + } 1.1365 + if (mBtnToolRubber) { 1.1366 + return AMOTION_EVENT_TOOL_TYPE_ERASER; 1.1367 + } 1.1368 + if (mBtnToolPen || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush) { 1.1369 + return AMOTION_EVENT_TOOL_TYPE_STYLUS; 1.1370 + } 1.1371 + if (mBtnToolFinger || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap) { 1.1372 + return AMOTION_EVENT_TOOL_TYPE_FINGER; 1.1373 + } 1.1374 + return AMOTION_EVENT_TOOL_TYPE_UNKNOWN; 1.1375 +} 1.1376 + 1.1377 +bool TouchButtonAccumulator::isToolActive() const { 1.1378 + return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber 1.1379 + || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush 1.1380 + || mBtnToolMouse || mBtnToolLens 1.1381 + || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap; 1.1382 +} 1.1383 + 1.1384 +bool TouchButtonAccumulator::isHovering() const { 1.1385 + return mHaveBtnTouch && !mBtnTouch; 1.1386 +} 1.1387 + 1.1388 +bool TouchButtonAccumulator::hasStylus() const { 1.1389 + return mHaveStylus; 1.1390 +} 1.1391 + 1.1392 + 1.1393 +// --- RawPointerAxes --- 1.1394 + 1.1395 +RawPointerAxes::RawPointerAxes() { 1.1396 + clear(); 1.1397 +} 1.1398 + 1.1399 +void RawPointerAxes::clear() { 1.1400 + x.clear(); 1.1401 + y.clear(); 1.1402 + pressure.clear(); 1.1403 + touchMajor.clear(); 1.1404 + touchMinor.clear(); 1.1405 + toolMajor.clear(); 1.1406 + toolMinor.clear(); 1.1407 + orientation.clear(); 1.1408 + distance.clear(); 1.1409 + tiltX.clear(); 1.1410 + tiltY.clear(); 1.1411 + trackingId.clear(); 1.1412 + slot.clear(); 1.1413 +} 1.1414 + 1.1415 + 1.1416 +// --- RawPointerData --- 1.1417 + 1.1418 +RawPointerData::RawPointerData() { 1.1419 + clear(); 1.1420 +} 1.1421 + 1.1422 +void RawPointerData::clear() { 1.1423 + pointerCount = 0; 1.1424 + clearIdBits(); 1.1425 +} 1.1426 + 1.1427 +void RawPointerData::copyFrom(const RawPointerData& other) { 1.1428 + pointerCount = other.pointerCount; 1.1429 + hoveringIdBits = other.hoveringIdBits; 1.1430 + touchingIdBits = other.touchingIdBits; 1.1431 + 1.1432 + for (uint32_t i = 0; i < pointerCount; i++) { 1.1433 + pointers[i] = other.pointers[i]; 1.1434 + 1.1435 + int id = pointers[i].id; 1.1436 + idToIndex[id] = other.idToIndex[id]; 1.1437 + } 1.1438 +} 1.1439 + 1.1440 +void RawPointerData::getCentroidOfTouchingPointers(float* outX, float* outY) const { 1.1441 + float x = 0, y = 0; 1.1442 + uint32_t count = touchingIdBits.count(); 1.1443 + if (count) { 1.1444 + for (BitSet32 idBits(touchingIdBits); !idBits.isEmpty(); ) { 1.1445 + uint32_t id = idBits.clearFirstMarkedBit(); 1.1446 + const Pointer& pointer = pointerForId(id); 1.1447 + x += pointer.x; 1.1448 + y += pointer.y; 1.1449 + } 1.1450 + x /= count; 1.1451 + y /= count; 1.1452 + } 1.1453 + *outX = x; 1.1454 + *outY = y; 1.1455 +} 1.1456 + 1.1457 + 1.1458 +// --- CookedPointerData --- 1.1459 + 1.1460 +CookedPointerData::CookedPointerData() { 1.1461 + clear(); 1.1462 +} 1.1463 + 1.1464 +void CookedPointerData::clear() { 1.1465 + pointerCount = 0; 1.1466 + hoveringIdBits.clear(); 1.1467 + touchingIdBits.clear(); 1.1468 +} 1.1469 + 1.1470 +void CookedPointerData::copyFrom(const CookedPointerData& other) { 1.1471 + pointerCount = other.pointerCount; 1.1472 + hoveringIdBits = other.hoveringIdBits; 1.1473 + touchingIdBits = other.touchingIdBits; 1.1474 + 1.1475 + for (uint32_t i = 0; i < pointerCount; i++) { 1.1476 + pointerProperties[i].copyFrom(other.pointerProperties[i]); 1.1477 + pointerCoords[i].copyFrom(other.pointerCoords[i]); 1.1478 + 1.1479 + int id = pointerProperties[i].id; 1.1480 + idToIndex[id] = other.idToIndex[id]; 1.1481 + } 1.1482 +} 1.1483 + 1.1484 + 1.1485 +// --- SingleTouchMotionAccumulator --- 1.1486 + 1.1487 +SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() { 1.1488 + clearAbsoluteAxes(); 1.1489 +} 1.1490 + 1.1491 +void SingleTouchMotionAccumulator::reset(InputDevice* device) { 1.1492 + mAbsX = device->getAbsoluteAxisValue(ABS_X); 1.1493 + mAbsY = device->getAbsoluteAxisValue(ABS_Y); 1.1494 + mAbsPressure = device->getAbsoluteAxisValue(ABS_PRESSURE); 1.1495 + mAbsToolWidth = device->getAbsoluteAxisValue(ABS_TOOL_WIDTH); 1.1496 + mAbsDistance = device->getAbsoluteAxisValue(ABS_DISTANCE); 1.1497 + mAbsTiltX = device->getAbsoluteAxisValue(ABS_TILT_X); 1.1498 + mAbsTiltY = device->getAbsoluteAxisValue(ABS_TILT_Y); 1.1499 +} 1.1500 + 1.1501 +void SingleTouchMotionAccumulator::clearAbsoluteAxes() { 1.1502 + mAbsX = 0; 1.1503 + mAbsY = 0; 1.1504 + mAbsPressure = 0; 1.1505 + mAbsToolWidth = 0; 1.1506 + mAbsDistance = 0; 1.1507 + mAbsTiltX = 0; 1.1508 + mAbsTiltY = 0; 1.1509 +} 1.1510 + 1.1511 +void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) { 1.1512 + if (rawEvent->type == EV_ABS) { 1.1513 + switch (rawEvent->code) { 1.1514 + case ABS_X: 1.1515 + mAbsX = rawEvent->value; 1.1516 + break; 1.1517 + case ABS_Y: 1.1518 + mAbsY = rawEvent->value; 1.1519 + break; 1.1520 + case ABS_PRESSURE: 1.1521 + mAbsPressure = rawEvent->value; 1.1522 + break; 1.1523 + case ABS_TOOL_WIDTH: 1.1524 + mAbsToolWidth = rawEvent->value; 1.1525 + break; 1.1526 + case ABS_DISTANCE: 1.1527 + mAbsDistance = rawEvent->value; 1.1528 + break; 1.1529 + case ABS_TILT_X: 1.1530 + mAbsTiltX = rawEvent->value; 1.1531 + break; 1.1532 + case ABS_TILT_Y: 1.1533 + mAbsTiltY = rawEvent->value; 1.1534 + break; 1.1535 + } 1.1536 + } 1.1537 +} 1.1538 + 1.1539 + 1.1540 +// --- MultiTouchMotionAccumulator --- 1.1541 + 1.1542 +MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() : 1.1543 + mCurrentSlot(-1), mSlots(NULL), mSlotCount(0), mUsingSlotsProtocol(false), 1.1544 + mHaveStylus(false) { 1.1545 +} 1.1546 + 1.1547 +MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() { 1.1548 + delete[] mSlots; 1.1549 +} 1.1550 + 1.1551 +void MultiTouchMotionAccumulator::configure(InputDevice* device, 1.1552 + size_t slotCount, bool usingSlotsProtocol) { 1.1553 + mSlotCount = slotCount; 1.1554 + mUsingSlotsProtocol = usingSlotsProtocol; 1.1555 + mHaveStylus = device->hasAbsoluteAxis(ABS_MT_TOOL_TYPE); 1.1556 + 1.1557 + delete[] mSlots; 1.1558 + mSlots = new Slot[slotCount]; 1.1559 +} 1.1560 + 1.1561 +void MultiTouchMotionAccumulator::reset(InputDevice* device) { 1.1562 + // Unfortunately there is no way to read the initial contents of the slots. 1.1563 + // So when we reset the accumulator, we must assume they are all zeroes. 1.1564 + if (mUsingSlotsProtocol) { 1.1565 + // Query the driver for the current slot index and use it as the initial slot 1.1566 + // before we start reading events from the device. It is possible that the 1.1567 + // current slot index will not be the same as it was when the first event was 1.1568 + // written into the evdev buffer, which means the input mapper could start 1.1569 + // out of sync with the initial state of the events in the evdev buffer. 1.1570 + // In the extremely unlikely case that this happens, the data from 1.1571 + // two slots will be confused until the next ABS_MT_SLOT event is received. 1.1572 + // This can cause the touch point to "jump", but at least there will be 1.1573 + // no stuck touches. 1.1574 + int32_t initialSlot; 1.1575 + status_t status = device->getEventHub()->getAbsoluteAxisValue(device->getId(), 1.1576 + ABS_MT_SLOT, &initialSlot); 1.1577 + if (status) { 1.1578 + ALOGD("Could not retrieve current multitouch slot index. status=%d", status); 1.1579 + initialSlot = -1; 1.1580 + } 1.1581 + clearSlots(initialSlot); 1.1582 + } else { 1.1583 + clearSlots(-1); 1.1584 + } 1.1585 +} 1.1586 + 1.1587 +void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) { 1.1588 + if (mSlots) { 1.1589 + for (size_t i = 0; i < mSlotCount; i++) { 1.1590 + mSlots[i].clear(); 1.1591 + } 1.1592 + } 1.1593 + mCurrentSlot = initialSlot; 1.1594 +} 1.1595 + 1.1596 +void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) { 1.1597 + if (rawEvent->type == EV_ABS) { 1.1598 + bool newSlot = false; 1.1599 + if (mUsingSlotsProtocol) { 1.1600 + if (rawEvent->code == ABS_MT_SLOT) { 1.1601 + mCurrentSlot = rawEvent->value; 1.1602 + newSlot = true; 1.1603 + } 1.1604 + } else if (mCurrentSlot < 0) { 1.1605 + mCurrentSlot = 0; 1.1606 + } 1.1607 + 1.1608 + if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) { 1.1609 +#if DEBUG_POINTERS 1.1610 + if (newSlot) { 1.1611 + ALOGW("MultiTouch device emitted invalid slot index %d but it " 1.1612 + "should be between 0 and %d; ignoring this slot.", 1.1613 + mCurrentSlot, mSlotCount - 1); 1.1614 + } 1.1615 +#endif 1.1616 + } else { 1.1617 + Slot* slot = &mSlots[mCurrentSlot]; 1.1618 + 1.1619 + switch (rawEvent->code) { 1.1620 + case ABS_MT_POSITION_X: 1.1621 + slot->mInUse = true; 1.1622 + slot->mAbsMTPositionX = rawEvent->value; 1.1623 + break; 1.1624 + case ABS_MT_POSITION_Y: 1.1625 + slot->mInUse = true; 1.1626 + slot->mAbsMTPositionY = rawEvent->value; 1.1627 + break; 1.1628 + case ABS_MT_TOUCH_MAJOR: 1.1629 + slot->mInUse = true; 1.1630 + slot->mAbsMTTouchMajor = rawEvent->value; 1.1631 + break; 1.1632 + case ABS_MT_TOUCH_MINOR: 1.1633 + slot->mInUse = true; 1.1634 + slot->mAbsMTTouchMinor = rawEvent->value; 1.1635 + slot->mHaveAbsMTTouchMinor = true; 1.1636 + break; 1.1637 + case ABS_MT_WIDTH_MAJOR: 1.1638 + slot->mInUse = true; 1.1639 + slot->mAbsMTWidthMajor = rawEvent->value; 1.1640 + break; 1.1641 + case ABS_MT_WIDTH_MINOR: 1.1642 + slot->mInUse = true; 1.1643 + slot->mAbsMTWidthMinor = rawEvent->value; 1.1644 + slot->mHaveAbsMTWidthMinor = true; 1.1645 + break; 1.1646 + case ABS_MT_ORIENTATION: 1.1647 + slot->mInUse = true; 1.1648 + slot->mAbsMTOrientation = rawEvent->value; 1.1649 + break; 1.1650 + case ABS_MT_TRACKING_ID: 1.1651 + if (mUsingSlotsProtocol && rawEvent->value < 0) { 1.1652 + // The slot is no longer in use but it retains its previous contents, 1.1653 + // which may be reused for subsequent touches. 1.1654 + slot->mInUse = false; 1.1655 + } else { 1.1656 + slot->mInUse = true; 1.1657 + slot->mAbsMTTrackingId = rawEvent->value; 1.1658 + } 1.1659 + break; 1.1660 + case ABS_MT_PRESSURE: 1.1661 + slot->mInUse = true; 1.1662 + slot->mAbsMTPressure = rawEvent->value; 1.1663 + break; 1.1664 + case ABS_MT_DISTANCE: 1.1665 + slot->mInUse = true; 1.1666 + slot->mAbsMTDistance = rawEvent->value; 1.1667 + break; 1.1668 + case ABS_MT_TOOL_TYPE: 1.1669 + slot->mInUse = true; 1.1670 + slot->mAbsMTToolType = rawEvent->value; 1.1671 + slot->mHaveAbsMTToolType = true; 1.1672 + break; 1.1673 + } 1.1674 + } 1.1675 + } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) { 1.1676 + // MultiTouch Sync: The driver has returned all data for *one* of the pointers. 1.1677 + mCurrentSlot += 1; 1.1678 + } 1.1679 +} 1.1680 + 1.1681 +void MultiTouchMotionAccumulator::finishSync() { 1.1682 + if (!mUsingSlotsProtocol) { 1.1683 + clearSlots(-1); 1.1684 + } 1.1685 +} 1.1686 + 1.1687 +bool MultiTouchMotionAccumulator::hasStylus() const { 1.1688 + return mHaveStylus; 1.1689 +} 1.1690 + 1.1691 + 1.1692 +// --- MultiTouchMotionAccumulator::Slot --- 1.1693 + 1.1694 +MultiTouchMotionAccumulator::Slot::Slot() { 1.1695 + clear(); 1.1696 +} 1.1697 + 1.1698 +void MultiTouchMotionAccumulator::Slot::clear() { 1.1699 + mInUse = false; 1.1700 + mHaveAbsMTTouchMinor = false; 1.1701 + mHaveAbsMTWidthMinor = false; 1.1702 + mHaveAbsMTToolType = false; 1.1703 + mAbsMTPositionX = 0; 1.1704 + mAbsMTPositionY = 0; 1.1705 + mAbsMTTouchMajor = 0; 1.1706 + mAbsMTTouchMinor = 0; 1.1707 + mAbsMTWidthMajor = 0; 1.1708 + mAbsMTWidthMinor = 0; 1.1709 + mAbsMTOrientation = 0; 1.1710 + mAbsMTTrackingId = -1; 1.1711 + mAbsMTPressure = 0; 1.1712 + mAbsMTDistance = 0; 1.1713 + mAbsMTToolType = 0; 1.1714 +} 1.1715 + 1.1716 +int32_t MultiTouchMotionAccumulator::Slot::getToolType() const { 1.1717 + if (mHaveAbsMTToolType) { 1.1718 + switch (mAbsMTToolType) { 1.1719 + case MT_TOOL_FINGER: 1.1720 + return AMOTION_EVENT_TOOL_TYPE_FINGER; 1.1721 + case MT_TOOL_PEN: 1.1722 + return AMOTION_EVENT_TOOL_TYPE_STYLUS; 1.1723 + } 1.1724 + } 1.1725 + return AMOTION_EVENT_TOOL_TYPE_UNKNOWN; 1.1726 +} 1.1727 + 1.1728 + 1.1729 +// --- InputMapper --- 1.1730 + 1.1731 +InputMapper::InputMapper(InputDevice* device) : 1.1732 + mDevice(device), mContext(device->getContext()) { 1.1733 +} 1.1734 + 1.1735 +InputMapper::~InputMapper() { 1.1736 +} 1.1737 + 1.1738 +void InputMapper::populateDeviceInfo(InputDeviceInfo* info) { 1.1739 + info->addSource(getSources()); 1.1740 +} 1.1741 + 1.1742 +void InputMapper::dump(String8& dump) { 1.1743 +} 1.1744 + 1.1745 +void InputMapper::configure(nsecs_t when, 1.1746 + const InputReaderConfiguration* config, uint32_t changes) { 1.1747 +} 1.1748 + 1.1749 +void InputMapper::reset(nsecs_t when) { 1.1750 +} 1.1751 + 1.1752 +void InputMapper::timeoutExpired(nsecs_t when) { 1.1753 +} 1.1754 + 1.1755 +int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) { 1.1756 + return AKEY_STATE_UNKNOWN; 1.1757 +} 1.1758 + 1.1759 +int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) { 1.1760 + return AKEY_STATE_UNKNOWN; 1.1761 +} 1.1762 + 1.1763 +int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) { 1.1764 + return AKEY_STATE_UNKNOWN; 1.1765 +} 1.1766 + 1.1767 +bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, 1.1768 + const int32_t* keyCodes, uint8_t* outFlags) { 1.1769 + return false; 1.1770 +} 1.1771 + 1.1772 +void InputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, 1.1773 + int32_t token) { 1.1774 +} 1.1775 + 1.1776 +void InputMapper::cancelVibrate(int32_t token) { 1.1777 +} 1.1778 + 1.1779 +int32_t InputMapper::getMetaState() { 1.1780 + return 0; 1.1781 +} 1.1782 + 1.1783 +void InputMapper::fadePointer() { 1.1784 +} 1.1785 + 1.1786 +status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) { 1.1787 + return getEventHub()->getAbsoluteAxisInfo(getDeviceId(), axis, axisInfo); 1.1788 +} 1.1789 + 1.1790 +void InputMapper::bumpGeneration() { 1.1791 + mDevice->bumpGeneration(); 1.1792 +} 1.1793 + 1.1794 +void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump, 1.1795 + const RawAbsoluteAxisInfo& axis, const char* name) { 1.1796 + if (axis.valid) { 1.1797 + dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d, resolution=%d\n", 1.1798 + name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz, axis.resolution); 1.1799 + } else { 1.1800 + dump.appendFormat(INDENT4 "%s: unknown range\n", name); 1.1801 + } 1.1802 +} 1.1803 + 1.1804 + 1.1805 +// --- SwitchInputMapper --- 1.1806 + 1.1807 +SwitchInputMapper::SwitchInputMapper(InputDevice* device) : 1.1808 + InputMapper(device), mUpdatedSwitchValues(0), mUpdatedSwitchMask(0) { 1.1809 +} 1.1810 + 1.1811 +SwitchInputMapper::~SwitchInputMapper() { 1.1812 +} 1.1813 + 1.1814 +uint32_t SwitchInputMapper::getSources() { 1.1815 + return AINPUT_SOURCE_SWITCH; 1.1816 +} 1.1817 + 1.1818 +void SwitchInputMapper::process(const RawEvent* rawEvent) { 1.1819 + switch (rawEvent->type) { 1.1820 + case EV_SW: 1.1821 + processSwitch(rawEvent->code, rawEvent->value); 1.1822 + break; 1.1823 + 1.1824 + case EV_SYN: 1.1825 + if (rawEvent->code == SYN_REPORT) { 1.1826 + sync(rawEvent->when); 1.1827 + } 1.1828 + } 1.1829 +} 1.1830 + 1.1831 +void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) { 1.1832 + if (switchCode >= 0 && switchCode < 32) { 1.1833 + if (switchValue) { 1.1834 + mUpdatedSwitchValues |= 1 << switchCode; 1.1835 + } 1.1836 + mUpdatedSwitchMask |= 1 << switchCode; 1.1837 + } 1.1838 +} 1.1839 + 1.1840 +void SwitchInputMapper::sync(nsecs_t when) { 1.1841 + if (mUpdatedSwitchMask) { 1.1842 + NotifySwitchArgs args(when, 0, mUpdatedSwitchValues, mUpdatedSwitchMask); 1.1843 + getListener()->notifySwitch(&args); 1.1844 + 1.1845 + mUpdatedSwitchValues = 0; 1.1846 + mUpdatedSwitchMask = 0; 1.1847 + } 1.1848 +} 1.1849 + 1.1850 +int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) { 1.1851 + return getEventHub()->getSwitchState(getDeviceId(), switchCode); 1.1852 +} 1.1853 + 1.1854 + 1.1855 +// --- VibratorInputMapper --- 1.1856 + 1.1857 +VibratorInputMapper::VibratorInputMapper(InputDevice* device) : 1.1858 + InputMapper(device), mVibrating(false) { 1.1859 +} 1.1860 + 1.1861 +VibratorInputMapper::~VibratorInputMapper() { 1.1862 +} 1.1863 + 1.1864 +uint32_t VibratorInputMapper::getSources() { 1.1865 + return 0; 1.1866 +} 1.1867 + 1.1868 +void VibratorInputMapper::populateDeviceInfo(InputDeviceInfo* info) { 1.1869 + InputMapper::populateDeviceInfo(info); 1.1870 + 1.1871 + info->setVibrator(true); 1.1872 +} 1.1873 + 1.1874 +void VibratorInputMapper::process(const RawEvent* rawEvent) { 1.1875 + // TODO: Handle FF_STATUS, although it does not seem to be widely supported. 1.1876 +} 1.1877 + 1.1878 +void VibratorInputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, 1.1879 + int32_t token) { 1.1880 +#if DEBUG_VIBRATOR 1.1881 + String8 patternStr; 1.1882 + for (size_t i = 0; i < patternSize; i++) { 1.1883 + if (i != 0) { 1.1884 + patternStr.append(", "); 1.1885 + } 1.1886 + patternStr.appendFormat("%lld", pattern[i]); 1.1887 + } 1.1888 + ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%ld, token=%d", 1.1889 + getDeviceId(), patternStr.string(), repeat, token); 1.1890 +#endif 1.1891 + 1.1892 + mVibrating = true; 1.1893 + memcpy(mPattern, pattern, patternSize * sizeof(nsecs_t)); 1.1894 + mPatternSize = patternSize; 1.1895 + mRepeat = repeat; 1.1896 + mToken = token; 1.1897 + mIndex = -1; 1.1898 + 1.1899 + nextStep(); 1.1900 +} 1.1901 + 1.1902 +void VibratorInputMapper::cancelVibrate(int32_t token) { 1.1903 +#if DEBUG_VIBRATOR 1.1904 + ALOGD("cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token); 1.1905 +#endif 1.1906 + 1.1907 + if (mVibrating && mToken == token) { 1.1908 + stopVibrating(); 1.1909 + } 1.1910 +} 1.1911 + 1.1912 +void VibratorInputMapper::timeoutExpired(nsecs_t when) { 1.1913 + if (mVibrating) { 1.1914 + if (when >= mNextStepTime) { 1.1915 + nextStep(); 1.1916 + } else { 1.1917 + getContext()->requestTimeoutAtTime(mNextStepTime); 1.1918 + } 1.1919 + } 1.1920 +} 1.1921 + 1.1922 +void VibratorInputMapper::nextStep() { 1.1923 + mIndex += 1; 1.1924 + if (size_t(mIndex) >= mPatternSize) { 1.1925 + if (mRepeat < 0) { 1.1926 + // We are done. 1.1927 + stopVibrating(); 1.1928 + return; 1.1929 + } 1.1930 + mIndex = mRepeat; 1.1931 + } 1.1932 + 1.1933 + bool vibratorOn = mIndex & 1; 1.1934 + nsecs_t duration = mPattern[mIndex]; 1.1935 + if (vibratorOn) { 1.1936 +#if DEBUG_VIBRATOR 1.1937 + ALOGD("nextStep: sending vibrate deviceId=%d, duration=%lld", 1.1938 + getDeviceId(), duration); 1.1939 +#endif 1.1940 + getEventHub()->vibrate(getDeviceId(), duration); 1.1941 + } else { 1.1942 +#if DEBUG_VIBRATOR 1.1943 + ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId()); 1.1944 +#endif 1.1945 + getEventHub()->cancelVibrate(getDeviceId()); 1.1946 + } 1.1947 + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); 1.1948 + mNextStepTime = now + duration; 1.1949 + getContext()->requestTimeoutAtTime(mNextStepTime); 1.1950 +#if DEBUG_VIBRATOR 1.1951 + ALOGD("nextStep: scheduled timeout in %0.3fms", duration * 0.000001f); 1.1952 +#endif 1.1953 +} 1.1954 + 1.1955 +void VibratorInputMapper::stopVibrating() { 1.1956 + mVibrating = false; 1.1957 +#if DEBUG_VIBRATOR 1.1958 + ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId()); 1.1959 +#endif 1.1960 + getEventHub()->cancelVibrate(getDeviceId()); 1.1961 +} 1.1962 + 1.1963 +void VibratorInputMapper::dump(String8& dump) { 1.1964 + dump.append(INDENT2 "Vibrator Input Mapper:\n"); 1.1965 + dump.appendFormat(INDENT3 "Vibrating: %s\n", toString(mVibrating)); 1.1966 +} 1.1967 + 1.1968 + 1.1969 +// --- KeyboardInputMapper --- 1.1970 + 1.1971 +KeyboardInputMapper::KeyboardInputMapper(InputDevice* device, 1.1972 + uint32_t source, int32_t keyboardType) : 1.1973 + InputMapper(device), mSource(source), 1.1974 + mKeyboardType(keyboardType) { 1.1975 +} 1.1976 + 1.1977 +KeyboardInputMapper::~KeyboardInputMapper() { 1.1978 +} 1.1979 + 1.1980 +uint32_t KeyboardInputMapper::getSources() { 1.1981 + return mSource; 1.1982 +} 1.1983 + 1.1984 +void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) { 1.1985 + InputMapper::populateDeviceInfo(info); 1.1986 + 1.1987 + info->setKeyboardType(mKeyboardType); 1.1988 + info->setKeyCharacterMap(getEventHub()->getKeyCharacterMap(getDeviceId())); 1.1989 +} 1.1990 + 1.1991 +void KeyboardInputMapper::dump(String8& dump) { 1.1992 + dump.append(INDENT2 "Keyboard Input Mapper:\n"); 1.1993 + dumpParameters(dump); 1.1994 + dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType); 1.1995 + dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation); 1.1996 + dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mKeyDowns.size()); 1.1997 + dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mMetaState); 1.1998 + dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime); 1.1999 +} 1.2000 + 1.2001 + 1.2002 +void KeyboardInputMapper::configure(nsecs_t when, 1.2003 + const InputReaderConfiguration* config, uint32_t changes) { 1.2004 + InputMapper::configure(when, config, changes); 1.2005 + 1.2006 + if (!changes) { // first time only 1.2007 + // Configure basic parameters. 1.2008 + configureParameters(); 1.2009 + } 1.2010 + 1.2011 + if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { 1.2012 + if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) { 1.2013 + DisplayViewport v; 1.2014 + if (config->getDisplayInfo(false /*external*/, &v)) { 1.2015 + mOrientation = v.orientation; 1.2016 + } else { 1.2017 + mOrientation = DISPLAY_ORIENTATION_0; 1.2018 + } 1.2019 + } else { 1.2020 + mOrientation = DISPLAY_ORIENTATION_0; 1.2021 + } 1.2022 + } 1.2023 +} 1.2024 + 1.2025 +void KeyboardInputMapper::configureParameters() { 1.2026 + mParameters.orientationAware = false; 1.2027 + getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"), 1.2028 + mParameters.orientationAware); 1.2029 + 1.2030 + mParameters.hasAssociatedDisplay = false; 1.2031 + if (mParameters.orientationAware) { 1.2032 + mParameters.hasAssociatedDisplay = true; 1.2033 + } 1.2034 +} 1.2035 + 1.2036 +void KeyboardInputMapper::dumpParameters(String8& dump) { 1.2037 + dump.append(INDENT3 "Parameters:\n"); 1.2038 + dump.appendFormat(INDENT4 "HasAssociatedDisplay: %s\n", 1.2039 + toString(mParameters.hasAssociatedDisplay)); 1.2040 + dump.appendFormat(INDENT4 "OrientationAware: %s\n", 1.2041 + toString(mParameters.orientationAware)); 1.2042 +} 1.2043 + 1.2044 +void KeyboardInputMapper::reset(nsecs_t when) { 1.2045 + mMetaState = AMETA_NONE; 1.2046 + mDownTime = 0; 1.2047 + mKeyDowns.clear(); 1.2048 + mCurrentHidUsage = 0; 1.2049 + 1.2050 + resetLedState(); 1.2051 + 1.2052 + InputMapper::reset(when); 1.2053 +} 1.2054 + 1.2055 +void KeyboardInputMapper::process(const RawEvent* rawEvent) { 1.2056 + switch (rawEvent->type) { 1.2057 + case EV_KEY: { 1.2058 + int32_t scanCode = rawEvent->code; 1.2059 + int32_t usageCode = mCurrentHidUsage; 1.2060 + mCurrentHidUsage = 0; 1.2061 + 1.2062 + if (isKeyboardOrGamepadKey(scanCode)) { 1.2063 + int32_t keyCode; 1.2064 + uint32_t flags; 1.2065 + if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) { 1.2066 + keyCode = AKEYCODE_UNKNOWN; 1.2067 + flags = 0; 1.2068 + } 1.2069 + processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags); 1.2070 + } 1.2071 + break; 1.2072 + } 1.2073 + case EV_MSC: { 1.2074 + if (rawEvent->code == MSC_SCAN) { 1.2075 + mCurrentHidUsage = rawEvent->value; 1.2076 + } 1.2077 + break; 1.2078 + } 1.2079 + case EV_SYN: { 1.2080 + if (rawEvent->code == SYN_REPORT) { 1.2081 + mCurrentHidUsage = 0; 1.2082 + } 1.2083 + } 1.2084 + } 1.2085 +} 1.2086 + 1.2087 +bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) { 1.2088 + return scanCode < BTN_MOUSE 1.2089 + || scanCode >= KEY_OK 1.2090 + || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE) 1.2091 + || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI); 1.2092 +} 1.2093 + 1.2094 +void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode, 1.2095 + int32_t scanCode, uint32_t policyFlags) { 1.2096 + 1.2097 + if (down) { 1.2098 + // Rotate key codes according to orientation if needed. 1.2099 + if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) { 1.2100 + keyCode = rotateKeyCode(keyCode, mOrientation); 1.2101 + } 1.2102 + 1.2103 + // Add key down. 1.2104 + ssize_t keyDownIndex = findKeyDown(scanCode); 1.2105 + if (keyDownIndex >= 0) { 1.2106 + // key repeat, be sure to use same keycode as before in case of rotation 1.2107 + keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode; 1.2108 + } else { 1.2109 + // key down 1.2110 + if ((policyFlags & POLICY_FLAG_VIRTUAL) 1.2111 + && mContext->shouldDropVirtualKey(when, 1.2112 + getDevice(), keyCode, scanCode)) { 1.2113 + return; 1.2114 + } 1.2115 + 1.2116 + mKeyDowns.push(); 1.2117 + KeyDown& keyDown = mKeyDowns.editTop(); 1.2118 + keyDown.keyCode = keyCode; 1.2119 + keyDown.scanCode = scanCode; 1.2120 + } 1.2121 + 1.2122 + mDownTime = when; 1.2123 + } else { 1.2124 + // Remove key down. 1.2125 + ssize_t keyDownIndex = findKeyDown(scanCode); 1.2126 + if (keyDownIndex >= 0) { 1.2127 + // key up, be sure to use same keycode as before in case of rotation 1.2128 + keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode; 1.2129 + mKeyDowns.removeAt(size_t(keyDownIndex)); 1.2130 + } else { 1.2131 + // key was not actually down 1.2132 + ALOGI("Dropping key up from device %s because the key was not down. " 1.2133 + "keyCode=%d, scanCode=%d", 1.2134 + getDeviceName().string(), keyCode, scanCode); 1.2135 + return; 1.2136 + } 1.2137 + } 1.2138 + 1.2139 + bool metaStateChanged = false; 1.2140 + int32_t oldMetaState = mMetaState; 1.2141 + int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState); 1.2142 + if (oldMetaState != newMetaState) { 1.2143 + mMetaState = newMetaState; 1.2144 + metaStateChanged = true; 1.2145 + updateLedState(false); 1.2146 + } 1.2147 + 1.2148 + nsecs_t downTime = mDownTime; 1.2149 + 1.2150 + // Key down on external an keyboard should wake the device. 1.2151 + // We don't do this for internal keyboards to prevent them from waking up in your pocket. 1.2152 + // For internal keyboards, the key layout file should specify the policy flags for 1.2153 + // each wake key individually. 1.2154 + // TODO: Use the input device configuration to control this behavior more finely. 1.2155 + if (down && getDevice()->isExternal() 1.2156 + && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) { 1.2157 + policyFlags |= POLICY_FLAG_WAKE_DROPPED; 1.2158 + } 1.2159 + 1.2160 + if (metaStateChanged) { 1.2161 + getContext()->updateGlobalMetaState(); 1.2162 + } 1.2163 + 1.2164 + if (down && !isMetaKey(keyCode)) { 1.2165 + getContext()->fadePointer(); 1.2166 + } 1.2167 + 1.2168 + NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags, 1.2169 + down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, 1.2170 + AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime); 1.2171 + getListener()->notifyKey(&args); 1.2172 +} 1.2173 + 1.2174 +ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) { 1.2175 + size_t n = mKeyDowns.size(); 1.2176 + for (size_t i = 0; i < n; i++) { 1.2177 + if (mKeyDowns[i].scanCode == scanCode) { 1.2178 + return i; 1.2179 + } 1.2180 + } 1.2181 + return -1; 1.2182 +} 1.2183 + 1.2184 +int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) { 1.2185 + return getEventHub()->getKeyCodeState(getDeviceId(), keyCode); 1.2186 +} 1.2187 + 1.2188 +int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) { 1.2189 + return getEventHub()->getScanCodeState(getDeviceId(), scanCode); 1.2190 +} 1.2191 + 1.2192 +bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, 1.2193 + const int32_t* keyCodes, uint8_t* outFlags) { 1.2194 + return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags); 1.2195 +} 1.2196 + 1.2197 +int32_t KeyboardInputMapper::getMetaState() { 1.2198 + return mMetaState; 1.2199 +} 1.2200 + 1.2201 +void KeyboardInputMapper::resetLedState() { 1.2202 + initializeLedState(mCapsLockLedState, LED_CAPSL); 1.2203 + initializeLedState(mNumLockLedState, LED_NUML); 1.2204 + initializeLedState(mScrollLockLedState, LED_SCROLLL); 1.2205 + 1.2206 + updateLedState(true); 1.2207 +} 1.2208 + 1.2209 +void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) { 1.2210 + ledState.avail = getEventHub()->hasLed(getDeviceId(), led); 1.2211 + ledState.on = false; 1.2212 +} 1.2213 + 1.2214 +void KeyboardInputMapper::updateLedState(bool reset) { 1.2215 + updateLedStateForModifier(mCapsLockLedState, LED_CAPSL, 1.2216 + AMETA_CAPS_LOCK_ON, reset); 1.2217 + updateLedStateForModifier(mNumLockLedState, LED_NUML, 1.2218 + AMETA_NUM_LOCK_ON, reset); 1.2219 + updateLedStateForModifier(mScrollLockLedState, LED_SCROLLL, 1.2220 + AMETA_SCROLL_LOCK_ON, reset); 1.2221 +} 1.2222 + 1.2223 +void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState, 1.2224 + int32_t led, int32_t modifier, bool reset) { 1.2225 + if (ledState.avail) { 1.2226 + bool desiredState = (mMetaState & modifier) != 0; 1.2227 + if (reset || ledState.on != desiredState) { 1.2228 + getEventHub()->setLedState(getDeviceId(), led, desiredState); 1.2229 + ledState.on = desiredState; 1.2230 + } 1.2231 + } 1.2232 +} 1.2233 + 1.2234 + 1.2235 +// --- CursorInputMapper --- 1.2236 + 1.2237 +CursorInputMapper::CursorInputMapper(InputDevice* device) : 1.2238 + InputMapper(device) { 1.2239 +} 1.2240 + 1.2241 +CursorInputMapper::~CursorInputMapper() { 1.2242 +} 1.2243 + 1.2244 +uint32_t CursorInputMapper::getSources() { 1.2245 + return mSource; 1.2246 +} 1.2247 + 1.2248 +void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) { 1.2249 + InputMapper::populateDeviceInfo(info); 1.2250 + 1.2251 + if (mParameters.mode == Parameters::MODE_POINTER) { 1.2252 + float minX, minY, maxX, maxY; 1.2253 + if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) { 1.2254 + info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f, 0.0f); 1.2255 + info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f, 0.0f); 1.2256 + } 1.2257 + } else { 1.2258 + info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f); 1.2259 + info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f); 1.2260 + } 1.2261 + info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f); 1.2262 + 1.2263 + if (mCursorScrollAccumulator.haveRelativeVWheel()) { 1.2264 + info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f); 1.2265 + } 1.2266 + if (mCursorScrollAccumulator.haveRelativeHWheel()) { 1.2267 + info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f); 1.2268 + } 1.2269 +} 1.2270 + 1.2271 +void CursorInputMapper::dump(String8& dump) { 1.2272 + dump.append(INDENT2 "Cursor Input Mapper:\n"); 1.2273 + dumpParameters(dump); 1.2274 + dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale); 1.2275 + dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale); 1.2276 + dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision); 1.2277 + dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision); 1.2278 + dump.appendFormat(INDENT3 "HaveVWheel: %s\n", 1.2279 + toString(mCursorScrollAccumulator.haveRelativeVWheel())); 1.2280 + dump.appendFormat(INDENT3 "HaveHWheel: %s\n", 1.2281 + toString(mCursorScrollAccumulator.haveRelativeHWheel())); 1.2282 + dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale); 1.2283 + dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale); 1.2284 + dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation); 1.2285 + dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mButtonState); 1.2286 + dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState))); 1.2287 + dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime); 1.2288 +} 1.2289 + 1.2290 +void CursorInputMapper::configure(nsecs_t when, 1.2291 + const InputReaderConfiguration* config, uint32_t changes) { 1.2292 + InputMapper::configure(when, config, changes); 1.2293 + 1.2294 + if (!changes) { // first time only 1.2295 + mCursorScrollAccumulator.configure(getDevice()); 1.2296 + 1.2297 + // Configure basic parameters. 1.2298 + configureParameters(); 1.2299 + 1.2300 + // Configure device mode. 1.2301 + switch (mParameters.mode) { 1.2302 + case Parameters::MODE_POINTER: 1.2303 + mSource = AINPUT_SOURCE_MOUSE; 1.2304 + mXPrecision = 1.0f; 1.2305 + mYPrecision = 1.0f; 1.2306 + mXScale = 1.0f; 1.2307 + mYScale = 1.0f; 1.2308 + mPointerController = getPolicy()->obtainPointerController(getDeviceId()); 1.2309 + break; 1.2310 + case Parameters::MODE_NAVIGATION: 1.2311 + mSource = AINPUT_SOURCE_TRACKBALL; 1.2312 + mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD; 1.2313 + mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD; 1.2314 + mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD; 1.2315 + mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD; 1.2316 + break; 1.2317 + } 1.2318 + 1.2319 + mVWheelScale = 1.0f; 1.2320 + mHWheelScale = 1.0f; 1.2321 + } 1.2322 + 1.2323 + if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) { 1.2324 + mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters); 1.2325 + mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters); 1.2326 + mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters); 1.2327 + } 1.2328 + 1.2329 + if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { 1.2330 + if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) { 1.2331 + DisplayViewport v; 1.2332 + if (config->getDisplayInfo(false /*external*/, &v)) { 1.2333 + mOrientation = v.orientation; 1.2334 + } else { 1.2335 + mOrientation = DISPLAY_ORIENTATION_0; 1.2336 + } 1.2337 + } else { 1.2338 + mOrientation = DISPLAY_ORIENTATION_0; 1.2339 + } 1.2340 + bumpGeneration(); 1.2341 + } 1.2342 +} 1.2343 + 1.2344 +void CursorInputMapper::configureParameters() { 1.2345 + mParameters.mode = Parameters::MODE_POINTER; 1.2346 + String8 cursorModeString; 1.2347 + if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) { 1.2348 + if (cursorModeString == "navigation") { 1.2349 + mParameters.mode = Parameters::MODE_NAVIGATION; 1.2350 + } else if (cursorModeString != "pointer" && cursorModeString != "default") { 1.2351 + ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string()); 1.2352 + } 1.2353 + } 1.2354 + 1.2355 + mParameters.orientationAware = false; 1.2356 + getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"), 1.2357 + mParameters.orientationAware); 1.2358 + 1.2359 + mParameters.hasAssociatedDisplay = false; 1.2360 + if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) { 1.2361 + mParameters.hasAssociatedDisplay = true; 1.2362 + } 1.2363 +} 1.2364 + 1.2365 +void CursorInputMapper::dumpParameters(String8& dump) { 1.2366 + dump.append(INDENT3 "Parameters:\n"); 1.2367 + dump.appendFormat(INDENT4 "HasAssociatedDisplay: %s\n", 1.2368 + toString(mParameters.hasAssociatedDisplay)); 1.2369 + 1.2370 + switch (mParameters.mode) { 1.2371 + case Parameters::MODE_POINTER: 1.2372 + dump.append(INDENT4 "Mode: pointer\n"); 1.2373 + break; 1.2374 + case Parameters::MODE_NAVIGATION: 1.2375 + dump.append(INDENT4 "Mode: navigation\n"); 1.2376 + break; 1.2377 + default: 1.2378 + ALOG_ASSERT(false); 1.2379 + } 1.2380 + 1.2381 + dump.appendFormat(INDENT4 "OrientationAware: %s\n", 1.2382 + toString(mParameters.orientationAware)); 1.2383 +} 1.2384 + 1.2385 +void CursorInputMapper::reset(nsecs_t when) { 1.2386 + mButtonState = 0; 1.2387 + mDownTime = 0; 1.2388 + 1.2389 + mPointerVelocityControl.reset(); 1.2390 + mWheelXVelocityControl.reset(); 1.2391 + mWheelYVelocityControl.reset(); 1.2392 + 1.2393 + mCursorButtonAccumulator.reset(getDevice()); 1.2394 + mCursorMotionAccumulator.reset(getDevice()); 1.2395 + mCursorScrollAccumulator.reset(getDevice()); 1.2396 + 1.2397 + InputMapper::reset(when); 1.2398 +} 1.2399 + 1.2400 +void CursorInputMapper::process(const RawEvent* rawEvent) { 1.2401 + mCursorButtonAccumulator.process(rawEvent); 1.2402 + mCursorMotionAccumulator.process(rawEvent); 1.2403 + mCursorScrollAccumulator.process(rawEvent); 1.2404 + 1.2405 + if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { 1.2406 + sync(rawEvent->when); 1.2407 + } 1.2408 +} 1.2409 + 1.2410 +void CursorInputMapper::sync(nsecs_t when) { 1.2411 + int32_t lastButtonState = mButtonState; 1.2412 + int32_t currentButtonState = mCursorButtonAccumulator.getButtonState(); 1.2413 + mButtonState = currentButtonState; 1.2414 + 1.2415 + bool wasDown = isPointerDown(lastButtonState); 1.2416 + bool down = isPointerDown(currentButtonState); 1.2417 + bool downChanged; 1.2418 + if (!wasDown && down) { 1.2419 + mDownTime = when; 1.2420 + downChanged = true; 1.2421 + } else if (wasDown && !down) { 1.2422 + downChanged = true; 1.2423 + } else { 1.2424 + downChanged = false; 1.2425 + } 1.2426 + nsecs_t downTime = mDownTime; 1.2427 + bool buttonsChanged = currentButtonState != lastButtonState; 1.2428 + bool buttonsPressed = currentButtonState & ~lastButtonState; 1.2429 + 1.2430 + float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale; 1.2431 + float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale; 1.2432 + bool moved = deltaX != 0 || deltaY != 0; 1.2433 + 1.2434 + // Rotate delta according to orientation if needed. 1.2435 + if (mParameters.orientationAware && mParameters.hasAssociatedDisplay 1.2436 + && (deltaX != 0.0f || deltaY != 0.0f)) { 1.2437 + rotateDelta(mOrientation, &deltaX, &deltaY); 1.2438 + } 1.2439 + 1.2440 + // Move the pointer. 1.2441 + PointerProperties pointerProperties; 1.2442 + pointerProperties.clear(); 1.2443 + pointerProperties.id = 0; 1.2444 + pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE; 1.2445 + 1.2446 + PointerCoords pointerCoords; 1.2447 + pointerCoords.clear(); 1.2448 + 1.2449 + float vscroll = mCursorScrollAccumulator.getRelativeVWheel(); 1.2450 + float hscroll = mCursorScrollAccumulator.getRelativeHWheel(); 1.2451 + bool scrolled = vscroll != 0 || hscroll != 0; 1.2452 + 1.2453 + mWheelYVelocityControl.move(when, NULL, &vscroll); 1.2454 + mWheelXVelocityControl.move(when, &hscroll, NULL); 1.2455 + 1.2456 + mPointerVelocityControl.move(when, &deltaX, &deltaY); 1.2457 + 1.2458 + int32_t displayId; 1.2459 + if (mPointerController != NULL) { 1.2460 + if (moved || scrolled || buttonsChanged) { 1.2461 + mPointerController->setPresentation( 1.2462 + PointerControllerInterface::PRESENTATION_POINTER); 1.2463 + 1.2464 + if (moved) { 1.2465 + mPointerController->move(deltaX, deltaY); 1.2466 + } 1.2467 + 1.2468 + if (buttonsChanged) { 1.2469 + mPointerController->setButtonState(currentButtonState); 1.2470 + } 1.2471 + 1.2472 + mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE); 1.2473 + } 1.2474 + 1.2475 + float x, y; 1.2476 + mPointerController->getPosition(&x, &y); 1.2477 + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x); 1.2478 + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y); 1.2479 + displayId = ADISPLAY_ID_DEFAULT; 1.2480 + } else { 1.2481 + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX); 1.2482 + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY); 1.2483 + displayId = ADISPLAY_ID_NONE; 1.2484 + } 1.2485 + 1.2486 + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f); 1.2487 + 1.2488 + // Moving an external trackball or mouse should wake the device. 1.2489 + // We don't do this for internal cursor devices to prevent them from waking up 1.2490 + // the device in your pocket. 1.2491 + // TODO: Use the input device configuration to control this behavior more finely. 1.2492 + uint32_t policyFlags = 0; 1.2493 + if ((buttonsPressed || moved || scrolled) && getDevice()->isExternal()) { 1.2494 + policyFlags |= POLICY_FLAG_WAKE_DROPPED; 1.2495 + } 1.2496 + 1.2497 + // Synthesize key down from buttons if needed. 1.2498 + synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource, 1.2499 + policyFlags, lastButtonState, currentButtonState); 1.2500 + 1.2501 + // Send motion event. 1.2502 + if (downChanged || moved || scrolled || buttonsChanged) { 1.2503 + int32_t metaState = mContext->getGlobalMetaState(); 1.2504 + int32_t motionEventAction; 1.2505 + if (downChanged) { 1.2506 + motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP; 1.2507 + } else if (down || mPointerController == NULL) { 1.2508 + motionEventAction = AMOTION_EVENT_ACTION_MOVE; 1.2509 + } else { 1.2510 + motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE; 1.2511 + } 1.2512 + 1.2513 + NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, 1.2514 + motionEventAction, 0, metaState, currentButtonState, 0, 1.2515 + displayId, 1, &pointerProperties, &pointerCoords, 1.2516 + mXPrecision, mYPrecision, downTime); 1.2517 + getListener()->notifyMotion(&args); 1.2518 + 1.2519 + // Send hover move after UP to tell the application that the mouse is hovering now. 1.2520 + if (motionEventAction == AMOTION_EVENT_ACTION_UP 1.2521 + && mPointerController != NULL) { 1.2522 + NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, policyFlags, 1.2523 + AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 1.2524 + metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE, 1.2525 + displayId, 1, &pointerProperties, &pointerCoords, 1.2526 + mXPrecision, mYPrecision, downTime); 1.2527 + getListener()->notifyMotion(&hoverArgs); 1.2528 + } 1.2529 + 1.2530 + // Send scroll events. 1.2531 + if (scrolled) { 1.2532 + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll); 1.2533 + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll); 1.2534 + 1.2535 + NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags, 1.2536 + AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState, 1.2537 + AMOTION_EVENT_EDGE_FLAG_NONE, 1.2538 + displayId, 1, &pointerProperties, &pointerCoords, 1.2539 + mXPrecision, mYPrecision, downTime); 1.2540 + getListener()->notifyMotion(&scrollArgs); 1.2541 + } 1.2542 + } 1.2543 + 1.2544 + // Synthesize key up from buttons if needed. 1.2545 + synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource, 1.2546 + policyFlags, lastButtonState, currentButtonState); 1.2547 + 1.2548 + mCursorMotionAccumulator.finishSync(); 1.2549 + mCursorScrollAccumulator.finishSync(); 1.2550 +} 1.2551 + 1.2552 +int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) { 1.2553 + if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) { 1.2554 + return getEventHub()->getScanCodeState(getDeviceId(), scanCode); 1.2555 + } else { 1.2556 + return AKEY_STATE_UNKNOWN; 1.2557 + } 1.2558 +} 1.2559 + 1.2560 +void CursorInputMapper::fadePointer() { 1.2561 + if (mPointerController != NULL) { 1.2562 + mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); 1.2563 + } 1.2564 +} 1.2565 + 1.2566 + 1.2567 +// --- TouchInputMapper --- 1.2568 + 1.2569 +TouchInputMapper::TouchInputMapper(InputDevice* device) : 1.2570 + InputMapper(device), 1.2571 + mSource(0), mDeviceMode(DEVICE_MODE_DISABLED), 1.2572 + mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0), 1.2573 + mSurfaceOrientation(DISPLAY_ORIENTATION_0) { 1.2574 +} 1.2575 + 1.2576 +TouchInputMapper::~TouchInputMapper() { 1.2577 +} 1.2578 + 1.2579 +uint32_t TouchInputMapper::getSources() { 1.2580 + return mSource; 1.2581 +} 1.2582 + 1.2583 +void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) { 1.2584 + InputMapper::populateDeviceInfo(info); 1.2585 + 1.2586 + if (mDeviceMode != DEVICE_MODE_DISABLED) { 1.2587 + info->addMotionRange(mOrientedRanges.x); 1.2588 + info->addMotionRange(mOrientedRanges.y); 1.2589 + info->addMotionRange(mOrientedRanges.pressure); 1.2590 + 1.2591 + if (mOrientedRanges.haveSize) { 1.2592 + info->addMotionRange(mOrientedRanges.size); 1.2593 + } 1.2594 + 1.2595 + if (mOrientedRanges.haveTouchSize) { 1.2596 + info->addMotionRange(mOrientedRanges.touchMajor); 1.2597 + info->addMotionRange(mOrientedRanges.touchMinor); 1.2598 + } 1.2599 + 1.2600 + if (mOrientedRanges.haveToolSize) { 1.2601 + info->addMotionRange(mOrientedRanges.toolMajor); 1.2602 + info->addMotionRange(mOrientedRanges.toolMinor); 1.2603 + } 1.2604 + 1.2605 + if (mOrientedRanges.haveOrientation) { 1.2606 + info->addMotionRange(mOrientedRanges.orientation); 1.2607 + } 1.2608 + 1.2609 + if (mOrientedRanges.haveDistance) { 1.2610 + info->addMotionRange(mOrientedRanges.distance); 1.2611 + } 1.2612 + 1.2613 + if (mOrientedRanges.haveTilt) { 1.2614 + info->addMotionRange(mOrientedRanges.tilt); 1.2615 + } 1.2616 + 1.2617 + if (mCursorScrollAccumulator.haveRelativeVWheel()) { 1.2618 + info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 1.2619 + 0.0f); 1.2620 + } 1.2621 + if (mCursorScrollAccumulator.haveRelativeHWheel()) { 1.2622 + info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 1.2623 + 0.0f); 1.2624 + } 1.2625 + if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) { 1.2626 + const InputDeviceInfo::MotionRange& x = mOrientedRanges.x; 1.2627 + const InputDeviceInfo::MotionRange& y = mOrientedRanges.y; 1.2628 + info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_1, mSource, x.min, x.max, x.flat, 1.2629 + x.fuzz, x.resolution); 1.2630 + info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_2, mSource, y.min, y.max, y.flat, 1.2631 + y.fuzz, y.resolution); 1.2632 + info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_3, mSource, x.min, x.max, x.flat, 1.2633 + x.fuzz, x.resolution); 1.2634 + info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_4, mSource, y.min, y.max, y.flat, 1.2635 + y.fuzz, y.resolution); 1.2636 + } 1.2637 + } 1.2638 +} 1.2639 + 1.2640 +void TouchInputMapper::dump(String8& dump) { 1.2641 + dump.append(INDENT2 "Touch Input Mapper:\n"); 1.2642 + dumpParameters(dump); 1.2643 + dumpVirtualKeys(dump); 1.2644 + dumpRawPointerAxes(dump); 1.2645 + dumpCalibration(dump); 1.2646 + dumpSurface(dump); 1.2647 + 1.2648 + dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n"); 1.2649 + dump.appendFormat(INDENT4 "XTranslate: %0.3f\n", mXTranslate); 1.2650 + dump.appendFormat(INDENT4 "YTranslate: %0.3f\n", mYTranslate); 1.2651 + dump.appendFormat(INDENT4 "XScale: %0.3f\n", mXScale); 1.2652 + dump.appendFormat(INDENT4 "YScale: %0.3f\n", mYScale); 1.2653 + dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mXPrecision); 1.2654 + dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mYPrecision); 1.2655 + dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale); 1.2656 + dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mPressureScale); 1.2657 + dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mSizeScale); 1.2658 + dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale); 1.2659 + dump.appendFormat(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale); 1.2660 + dump.appendFormat(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt)); 1.2661 + dump.appendFormat(INDENT4 "TiltXCenter: %0.3f\n", mTiltXCenter); 1.2662 + dump.appendFormat(INDENT4 "TiltXScale: %0.3f\n", mTiltXScale); 1.2663 + dump.appendFormat(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter); 1.2664 + dump.appendFormat(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale); 1.2665 + 1.2666 + dump.appendFormat(INDENT3 "Last Button State: 0x%08x\n", mLastButtonState); 1.2667 + 1.2668 + dump.appendFormat(INDENT3 "Last Raw Touch: pointerCount=%d\n", 1.2669 + mLastRawPointerData.pointerCount); 1.2670 + for (uint32_t i = 0; i < mLastRawPointerData.pointerCount; i++) { 1.2671 + const RawPointerData::Pointer& pointer = mLastRawPointerData.pointers[i]; 1.2672 + dump.appendFormat(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, " 1.2673 + "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, " 1.2674 + "orientation=%d, tiltX=%d, tiltY=%d, distance=%d, " 1.2675 + "toolType=%d, isHovering=%s\n", i, 1.2676 + pointer.id, pointer.x, pointer.y, pointer.pressure, 1.2677 + pointer.touchMajor, pointer.touchMinor, 1.2678 + pointer.toolMajor, pointer.toolMinor, 1.2679 + pointer.orientation, pointer.tiltX, pointer.tiltY, pointer.distance, 1.2680 + pointer.toolType, toString(pointer.isHovering)); 1.2681 + } 1.2682 + 1.2683 + dump.appendFormat(INDENT3 "Last Cooked Touch: pointerCount=%d\n", 1.2684 + mLastCookedPointerData.pointerCount); 1.2685 + for (uint32_t i = 0; i < mLastCookedPointerData.pointerCount; i++) { 1.2686 + const PointerProperties& pointerProperties = mLastCookedPointerData.pointerProperties[i]; 1.2687 + const PointerCoords& pointerCoords = mLastCookedPointerData.pointerCoords[i]; 1.2688 + dump.appendFormat(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, " 1.2689 + "touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, toolMinor=%0.3f, " 1.2690 + "orientation=%0.3f, tilt=%0.3f, distance=%0.3f, " 1.2691 + "toolType=%d, isHovering=%s\n", i, 1.2692 + pointerProperties.id, 1.2693 + pointerCoords.getX(), 1.2694 + pointerCoords.getY(), 1.2695 + pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), 1.2696 + pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR), 1.2697 + pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR), 1.2698 + pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), 1.2699 + pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), 1.2700 + pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION), 1.2701 + pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TILT), 1.2702 + pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE), 1.2703 + pointerProperties.toolType, 1.2704 + toString(mLastCookedPointerData.isHovering(i))); 1.2705 + } 1.2706 + 1.2707 + if (mDeviceMode == DEVICE_MODE_POINTER) { 1.2708 + dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n"); 1.2709 + dump.appendFormat(INDENT4 "XMovementScale: %0.3f\n", 1.2710 + mPointerXMovementScale); 1.2711 + dump.appendFormat(INDENT4 "YMovementScale: %0.3f\n", 1.2712 + mPointerYMovementScale); 1.2713 + dump.appendFormat(INDENT4 "XZoomScale: %0.3f\n", 1.2714 + mPointerXZoomScale); 1.2715 + dump.appendFormat(INDENT4 "YZoomScale: %0.3f\n", 1.2716 + mPointerYZoomScale); 1.2717 + dump.appendFormat(INDENT4 "MaxSwipeWidth: %f\n", 1.2718 + mPointerGestureMaxSwipeWidth); 1.2719 + } 1.2720 +} 1.2721 + 1.2722 +void TouchInputMapper::configure(nsecs_t when, 1.2723 + const InputReaderConfiguration* config, uint32_t changes) { 1.2724 + InputMapper::configure(when, config, changes); 1.2725 + 1.2726 + mConfig = *config; 1.2727 + 1.2728 + if (!changes) { // first time only 1.2729 + // Configure basic parameters. 1.2730 + configureParameters(); 1.2731 + 1.2732 + // Configure common accumulators. 1.2733 + mCursorScrollAccumulator.configure(getDevice()); 1.2734 + mTouchButtonAccumulator.configure(getDevice()); 1.2735 + 1.2736 + // Configure absolute axis information. 1.2737 + configureRawPointerAxes(); 1.2738 + 1.2739 + // Prepare input device calibration. 1.2740 + parseCalibration(); 1.2741 + resolveCalibration(); 1.2742 + } 1.2743 + 1.2744 + if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) { 1.2745 + // Update pointer speed. 1.2746 + mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters); 1.2747 + mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters); 1.2748 + mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters); 1.2749 + } 1.2750 + 1.2751 + bool resetNeeded = false; 1.2752 + if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO 1.2753 + | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT 1.2754 + | InputReaderConfiguration::CHANGE_SHOW_TOUCHES))) { 1.2755 + // Configure device sources, surface dimensions, orientation and 1.2756 + // scaling factors. 1.2757 + configureSurface(when, &resetNeeded); 1.2758 + } 1.2759 + 1.2760 + if (changes && resetNeeded) { 1.2761 + // Send reset, unless this is the first time the device has been configured, 1.2762 + // in which case the reader will call reset itself after all mappers are ready. 1.2763 + getDevice()->notifyReset(when); 1.2764 + } 1.2765 +} 1.2766 + 1.2767 +void TouchInputMapper::configureParameters() { 1.2768 + // Use the pointer presentation mode for devices that do not support distinct 1.2769 + // multitouch. The spot-based presentation relies on being able to accurately 1.2770 + // locate two or more fingers on the touch pad. 1.2771 + mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT) 1.2772 + ? Parameters::GESTURE_MODE_POINTER : Parameters::GESTURE_MODE_SPOTS; 1.2773 + 1.2774 + String8 gestureModeString; 1.2775 + if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"), 1.2776 + gestureModeString)) { 1.2777 + if (gestureModeString == "pointer") { 1.2778 + mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER; 1.2779 + } else if (gestureModeString == "spots") { 1.2780 + mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS; 1.2781 + } else if (gestureModeString != "default") { 1.2782 + ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string()); 1.2783 + } 1.2784 + } 1.2785 + 1.2786 + if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) { 1.2787 + // The device is a touch screen. 1.2788 + mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN; 1.2789 + } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) { 1.2790 + // The device is a pointing device like a track pad. 1.2791 + mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER; 1.2792 + } else if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X) 1.2793 + || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) { 1.2794 + // The device is a cursor device with a touch pad attached. 1.2795 + // By default don't use the touch pad to move the pointer. 1.2796 + mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD; 1.2797 + } else { 1.2798 + // The device is a touch pad of unknown purpose. 1.2799 + mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER; 1.2800 + } 1.2801 + 1.2802 + String8 deviceTypeString; 1.2803 + if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"), 1.2804 + deviceTypeString)) { 1.2805 + if (deviceTypeString == "touchScreen") { 1.2806 + mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN; 1.2807 + } else if (deviceTypeString == "touchPad") { 1.2808 + mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD; 1.2809 + } else if (deviceTypeString == "touchNavigation") { 1.2810 + mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION; 1.2811 + } else if (deviceTypeString == "pointer") { 1.2812 + mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER; 1.2813 + } else if (deviceTypeString != "default") { 1.2814 + ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string()); 1.2815 + } 1.2816 + } 1.2817 + 1.2818 + mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN; 1.2819 + getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"), 1.2820 + mParameters.orientationAware); 1.2821 + 1.2822 + mParameters.hasAssociatedDisplay = false; 1.2823 + mParameters.associatedDisplayIsExternal = false; 1.2824 + if (mParameters.orientationAware 1.2825 + || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN 1.2826 + || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) { 1.2827 + mParameters.hasAssociatedDisplay = true; 1.2828 + mParameters.associatedDisplayIsExternal = 1.2829 + mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN 1.2830 + && getDevice()->isExternal(); 1.2831 + } 1.2832 +} 1.2833 + 1.2834 +void TouchInputMapper::dumpParameters(String8& dump) { 1.2835 + dump.append(INDENT3 "Parameters:\n"); 1.2836 + 1.2837 + switch (mParameters.gestureMode) { 1.2838 + case Parameters::GESTURE_MODE_POINTER: 1.2839 + dump.append(INDENT4 "GestureMode: pointer\n"); 1.2840 + break; 1.2841 + case Parameters::GESTURE_MODE_SPOTS: 1.2842 + dump.append(INDENT4 "GestureMode: spots\n"); 1.2843 + break; 1.2844 + default: 1.2845 + assert(false); 1.2846 + } 1.2847 + 1.2848 + switch (mParameters.deviceType) { 1.2849 + case Parameters::DEVICE_TYPE_TOUCH_SCREEN: 1.2850 + dump.append(INDENT4 "DeviceType: touchScreen\n"); 1.2851 + break; 1.2852 + case Parameters::DEVICE_TYPE_TOUCH_PAD: 1.2853 + dump.append(INDENT4 "DeviceType: touchPad\n"); 1.2854 + break; 1.2855 + case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION: 1.2856 + dump.append(INDENT4 "DeviceType: touchNavigation\n"); 1.2857 + break; 1.2858 + case Parameters::DEVICE_TYPE_POINTER: 1.2859 + dump.append(INDENT4 "DeviceType: pointer\n"); 1.2860 + break; 1.2861 + default: 1.2862 + ALOG_ASSERT(false); 1.2863 + } 1.2864 + 1.2865 + dump.appendFormat(INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s\n", 1.2866 + toString(mParameters.hasAssociatedDisplay), 1.2867 + toString(mParameters.associatedDisplayIsExternal)); 1.2868 + dump.appendFormat(INDENT4 "OrientationAware: %s\n", 1.2869 + toString(mParameters.orientationAware)); 1.2870 +} 1.2871 + 1.2872 +void TouchInputMapper::configureRawPointerAxes() { 1.2873 + mRawPointerAxes.clear(); 1.2874 +} 1.2875 + 1.2876 +void TouchInputMapper::dumpRawPointerAxes(String8& dump) { 1.2877 + dump.append(INDENT3 "Raw Touch Axes:\n"); 1.2878 + dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.x, "X"); 1.2879 + dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.y, "Y"); 1.2880 + dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.pressure, "Pressure"); 1.2881 + dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMajor, "TouchMajor"); 1.2882 + dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMinor, "TouchMinor"); 1.2883 + dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMajor, "ToolMajor"); 1.2884 + dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMinor, "ToolMinor"); 1.2885 + dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.orientation, "Orientation"); 1.2886 + dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.distance, "Distance"); 1.2887 + dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltX, "TiltX"); 1.2888 + dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltY, "TiltY"); 1.2889 + dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.trackingId, "TrackingId"); 1.2890 + dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot"); 1.2891 +} 1.2892 + 1.2893 +void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { 1.2894 + int32_t oldDeviceMode = mDeviceMode; 1.2895 + 1.2896 + // Determine device mode. 1.2897 + if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER 1.2898 + && mConfig.pointerGesturesEnabled) { 1.2899 + mSource = AINPUT_SOURCE_MOUSE; 1.2900 + mDeviceMode = DEVICE_MODE_POINTER; 1.2901 + if (hasStylus()) { 1.2902 + mSource |= AINPUT_SOURCE_STYLUS; 1.2903 + } 1.2904 + } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN 1.2905 + && mParameters.hasAssociatedDisplay) { 1.2906 + mSource = AINPUT_SOURCE_TOUCHSCREEN; 1.2907 + mDeviceMode = DEVICE_MODE_DIRECT; 1.2908 + if (hasStylus()) { 1.2909 + mSource |= AINPUT_SOURCE_STYLUS; 1.2910 + } 1.2911 + } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) { 1.2912 + mSource = AINPUT_SOURCE_TOUCH_NAVIGATION; 1.2913 + mDeviceMode = DEVICE_MODE_NAVIGATION; 1.2914 + } else { 1.2915 + mSource = AINPUT_SOURCE_TOUCHPAD; 1.2916 + mDeviceMode = DEVICE_MODE_UNSCALED; 1.2917 + } 1.2918 + 1.2919 + // Ensure we have valid X and Y axes. 1.2920 + if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) { 1.2921 + ALOGW(INDENT "Touch device '%s' did not report support for X or Y axis! " 1.2922 + "The device will be inoperable.", getDeviceName().string()); 1.2923 + mDeviceMode = DEVICE_MODE_DISABLED; 1.2924 + return; 1.2925 + } 1.2926 + 1.2927 + // Raw width and height in the natural orientation. 1.2928 + int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1; 1.2929 + int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1; 1.2930 + 1.2931 + // Get associated display dimensions. 1.2932 + bool viewportChanged = false; 1.2933 + DisplayViewport newViewport; 1.2934 + if (mParameters.hasAssociatedDisplay) { 1.2935 + if (!mConfig.getDisplayInfo(mParameters.associatedDisplayIsExternal, &newViewport)) { 1.2936 + ALOGI(INDENT "Touch device '%s' could not query the properties of its associated " 1.2937 + "display. The device will be inoperable until the display size " 1.2938 + "becomes available.", 1.2939 + getDeviceName().string()); 1.2940 + mDeviceMode = DEVICE_MODE_DISABLED; 1.2941 + return; 1.2942 + } 1.2943 + } else { 1.2944 + newViewport.setNonDisplayViewport(rawWidth, rawHeight); 1.2945 + } 1.2946 + if (mViewport != newViewport) { 1.2947 + mViewport = newViewport; 1.2948 + viewportChanged = true; 1.2949 + 1.2950 + if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) { 1.2951 + // Convert rotated viewport to natural surface coordinates. 1.2952 + int32_t naturalLogicalWidth, naturalLogicalHeight; 1.2953 + int32_t naturalPhysicalWidth, naturalPhysicalHeight; 1.2954 + int32_t naturalPhysicalLeft, naturalPhysicalTop; 1.2955 + int32_t naturalDeviceWidth, naturalDeviceHeight; 1.2956 + switch (mViewport.orientation) { 1.2957 + case DISPLAY_ORIENTATION_90: 1.2958 + naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop; 1.2959 + naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft; 1.2960 + naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop; 1.2961 + naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft; 1.2962 + naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom; 1.2963 + naturalPhysicalTop = mViewport.physicalLeft; 1.2964 + naturalDeviceWidth = mViewport.deviceHeight; 1.2965 + naturalDeviceHeight = mViewport.deviceWidth; 1.2966 + break; 1.2967 + case DISPLAY_ORIENTATION_180: 1.2968 + naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft; 1.2969 + naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop; 1.2970 + naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft; 1.2971 + naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop; 1.2972 + naturalPhysicalLeft = mViewport.deviceWidth - mViewport.physicalRight; 1.2973 + naturalPhysicalTop = mViewport.deviceHeight - mViewport.physicalBottom; 1.2974 + naturalDeviceWidth = mViewport.deviceWidth; 1.2975 + naturalDeviceHeight = mViewport.deviceHeight; 1.2976 + break; 1.2977 + case DISPLAY_ORIENTATION_270: 1.2978 + naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop; 1.2979 + naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft; 1.2980 + naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop; 1.2981 + naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft; 1.2982 + naturalPhysicalLeft = mViewport.physicalTop; 1.2983 + naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight; 1.2984 + naturalDeviceWidth = mViewport.deviceHeight; 1.2985 + naturalDeviceHeight = mViewport.deviceWidth; 1.2986 + break; 1.2987 + case DISPLAY_ORIENTATION_0: 1.2988 + default: 1.2989 + naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft; 1.2990 + naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop; 1.2991 + naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft; 1.2992 + naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop; 1.2993 + naturalPhysicalLeft = mViewport.physicalLeft; 1.2994 + naturalPhysicalTop = mViewport.physicalTop; 1.2995 + naturalDeviceWidth = mViewport.deviceWidth; 1.2996 + naturalDeviceHeight = mViewport.deviceHeight; 1.2997 + break; 1.2998 + } 1.2999 + 1.3000 + mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth; 1.3001 + mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight; 1.3002 + mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth; 1.3003 + mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight; 1.3004 + 1.3005 + mSurfaceOrientation = mParameters.orientationAware ? 1.3006 + mViewport.orientation : DISPLAY_ORIENTATION_0; 1.3007 + } else { 1.3008 + mSurfaceWidth = rawWidth; 1.3009 + mSurfaceHeight = rawHeight; 1.3010 + mSurfaceLeft = 0; 1.3011 + mSurfaceTop = 0; 1.3012 + mSurfaceOrientation = DISPLAY_ORIENTATION_0; 1.3013 + } 1.3014 + } 1.3015 + 1.3016 + // If moving between pointer modes, need to reset some state. 1.3017 + bool deviceModeChanged; 1.3018 + if (mDeviceMode != oldDeviceMode) { 1.3019 + deviceModeChanged = true; 1.3020 + mOrientedRanges.clear(); 1.3021 + } 1.3022 + 1.3023 + // Create pointer controller if needed. 1.3024 + if (mDeviceMode == DEVICE_MODE_POINTER || 1.3025 + (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) { 1.3026 + if (mPointerController == NULL) { 1.3027 + mPointerController = getPolicy()->obtainPointerController(getDeviceId()); 1.3028 + } 1.3029 + } else { 1.3030 + mPointerController.clear(); 1.3031 + } 1.3032 + 1.3033 + if (viewportChanged || deviceModeChanged) { 1.3034 + ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, " 1.3035 + "display id %d", 1.3036 + getDeviceId(), getDeviceName().string(), mSurfaceWidth, mSurfaceHeight, 1.3037 + mSurfaceOrientation, mDeviceMode, mViewport.displayId); 1.3038 + 1.3039 + // Configure X and Y factors. 1.3040 + mXScale = float(mSurfaceWidth) / rawWidth; 1.3041 + mYScale = float(mSurfaceHeight) / rawHeight; 1.3042 + mXTranslate = -mSurfaceLeft; 1.3043 + mYTranslate = -mSurfaceTop; 1.3044 + mXPrecision = 1.0f / mXScale; 1.3045 + mYPrecision = 1.0f / mYScale; 1.3046 + 1.3047 + mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X; 1.3048 + mOrientedRanges.x.source = mSource; 1.3049 + mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y; 1.3050 + mOrientedRanges.y.source = mSource; 1.3051 + 1.3052 + configureVirtualKeys(); 1.3053 + 1.3054 + // Scale factor for terms that are not oriented in a particular axis. 1.3055 + // If the pixels are square then xScale == yScale otherwise we fake it 1.3056 + // by choosing an average. 1.3057 + mGeometricScale = avg(mXScale, mYScale); 1.3058 + 1.3059 + // Size of diagonal axis. 1.3060 + float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight); 1.3061 + 1.3062 + // Size factors. 1.3063 + if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) { 1.3064 + if (mRawPointerAxes.touchMajor.valid 1.3065 + && mRawPointerAxes.touchMajor.maxValue != 0) { 1.3066 + mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue; 1.3067 + } else if (mRawPointerAxes.toolMajor.valid 1.3068 + && mRawPointerAxes.toolMajor.maxValue != 0) { 1.3069 + mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue; 1.3070 + } else { 1.3071 + mSizeScale = 0.0f; 1.3072 + } 1.3073 + 1.3074 + mOrientedRanges.haveTouchSize = true; 1.3075 + mOrientedRanges.haveToolSize = true; 1.3076 + mOrientedRanges.haveSize = true; 1.3077 + 1.3078 + mOrientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR; 1.3079 + mOrientedRanges.touchMajor.source = mSource; 1.3080 + mOrientedRanges.touchMajor.min = 0; 1.3081 + mOrientedRanges.touchMajor.max = diagonalSize; 1.3082 + mOrientedRanges.touchMajor.flat = 0; 1.3083 + mOrientedRanges.touchMajor.fuzz = 0; 1.3084 + mOrientedRanges.touchMajor.resolution = 0; 1.3085 + 1.3086 + mOrientedRanges.touchMinor = mOrientedRanges.touchMajor; 1.3087 + mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR; 1.3088 + 1.3089 + mOrientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR; 1.3090 + mOrientedRanges.toolMajor.source = mSource; 1.3091 + mOrientedRanges.toolMajor.min = 0; 1.3092 + mOrientedRanges.toolMajor.max = diagonalSize; 1.3093 + mOrientedRanges.toolMajor.flat = 0; 1.3094 + mOrientedRanges.toolMajor.fuzz = 0; 1.3095 + mOrientedRanges.toolMajor.resolution = 0; 1.3096 + 1.3097 + mOrientedRanges.toolMinor = mOrientedRanges.toolMajor; 1.3098 + mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR; 1.3099 + 1.3100 + mOrientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE; 1.3101 + mOrientedRanges.size.source = mSource; 1.3102 + mOrientedRanges.size.min = 0; 1.3103 + mOrientedRanges.size.max = 1.0; 1.3104 + mOrientedRanges.size.flat = 0; 1.3105 + mOrientedRanges.size.fuzz = 0; 1.3106 + mOrientedRanges.size.resolution = 0; 1.3107 + } else { 1.3108 + mSizeScale = 0.0f; 1.3109 + } 1.3110 + 1.3111 + // Pressure factors. 1.3112 + mPressureScale = 0; 1.3113 + if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL 1.3114 + || mCalibration.pressureCalibration 1.3115 + == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) { 1.3116 + if (mCalibration.havePressureScale) { 1.3117 + mPressureScale = mCalibration.pressureScale; 1.3118 + } else if (mRawPointerAxes.pressure.valid 1.3119 + && mRawPointerAxes.pressure.maxValue != 0) { 1.3120 + mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue; 1.3121 + } 1.3122 + } 1.3123 + 1.3124 + mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE; 1.3125 + mOrientedRanges.pressure.source = mSource; 1.3126 + mOrientedRanges.pressure.min = 0; 1.3127 + mOrientedRanges.pressure.max = 1.0; 1.3128 + mOrientedRanges.pressure.flat = 0; 1.3129 + mOrientedRanges.pressure.fuzz = 0; 1.3130 + mOrientedRanges.pressure.resolution = 0; 1.3131 + 1.3132 + // Tilt 1.3133 + mTiltXCenter = 0; 1.3134 + mTiltXScale = 0; 1.3135 + mTiltYCenter = 0; 1.3136 + mTiltYScale = 0; 1.3137 + mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid; 1.3138 + if (mHaveTilt) { 1.3139 + mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue, 1.3140 + mRawPointerAxes.tiltX.maxValue); 1.3141 + mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue, 1.3142 + mRawPointerAxes.tiltY.maxValue); 1.3143 + mTiltXScale = M_PI / 180; 1.3144 + mTiltYScale = M_PI / 180; 1.3145 + 1.3146 + mOrientedRanges.haveTilt = true; 1.3147 + 1.3148 + mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT; 1.3149 + mOrientedRanges.tilt.source = mSource; 1.3150 + mOrientedRanges.tilt.min = 0; 1.3151 + mOrientedRanges.tilt.max = M_PI_2; 1.3152 + mOrientedRanges.tilt.flat = 0; 1.3153 + mOrientedRanges.tilt.fuzz = 0; 1.3154 + mOrientedRanges.tilt.resolution = 0; 1.3155 + } 1.3156 + 1.3157 + // Orientation 1.3158 + mOrientationScale = 0; 1.3159 + if (mHaveTilt) { 1.3160 + mOrientedRanges.haveOrientation = true; 1.3161 + 1.3162 + mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION; 1.3163 + mOrientedRanges.orientation.source = mSource; 1.3164 + mOrientedRanges.orientation.min = -M_PI; 1.3165 + mOrientedRanges.orientation.max = M_PI; 1.3166 + mOrientedRanges.orientation.flat = 0; 1.3167 + mOrientedRanges.orientation.fuzz = 0; 1.3168 + mOrientedRanges.orientation.resolution = 0; 1.3169 + } else if (mCalibration.orientationCalibration != 1.3170 + Calibration::ORIENTATION_CALIBRATION_NONE) { 1.3171 + if (mCalibration.orientationCalibration 1.3172 + == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) { 1.3173 + if (mRawPointerAxes.orientation.valid) { 1.3174 + if (mRawPointerAxes.orientation.maxValue > 0) { 1.3175 + mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue; 1.3176 + } else if (mRawPointerAxes.orientation.minValue < 0) { 1.3177 + mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue; 1.3178 + } else { 1.3179 + mOrientationScale = 0; 1.3180 + } 1.3181 + } 1.3182 + } 1.3183 + 1.3184 + mOrientedRanges.haveOrientation = true; 1.3185 + 1.3186 + mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION; 1.3187 + mOrientedRanges.orientation.source = mSource; 1.3188 + mOrientedRanges.orientation.min = -M_PI_2; 1.3189 + mOrientedRanges.orientation.max = M_PI_2; 1.3190 + mOrientedRanges.orientation.flat = 0; 1.3191 + mOrientedRanges.orientation.fuzz = 0; 1.3192 + mOrientedRanges.orientation.resolution = 0; 1.3193 + } 1.3194 + 1.3195 + // Distance 1.3196 + mDistanceScale = 0; 1.3197 + if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) { 1.3198 + if (mCalibration.distanceCalibration 1.3199 + == Calibration::DISTANCE_CALIBRATION_SCALED) { 1.3200 + if (mCalibration.haveDistanceScale) { 1.3201 + mDistanceScale = mCalibration.distanceScale; 1.3202 + } else { 1.3203 + mDistanceScale = 1.0f; 1.3204 + } 1.3205 + } 1.3206 + 1.3207 + mOrientedRanges.haveDistance = true; 1.3208 + 1.3209 + mOrientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE; 1.3210 + mOrientedRanges.distance.source = mSource; 1.3211 + mOrientedRanges.distance.min = 1.3212 + mRawPointerAxes.distance.minValue * mDistanceScale; 1.3213 + mOrientedRanges.distance.max = 1.3214 + mRawPointerAxes.distance.maxValue * mDistanceScale; 1.3215 + mOrientedRanges.distance.flat = 0; 1.3216 + mOrientedRanges.distance.fuzz = 1.3217 + mRawPointerAxes.distance.fuzz * mDistanceScale; 1.3218 + mOrientedRanges.distance.resolution = 0; 1.3219 + } 1.3220 + 1.3221 + // Compute oriented precision, scales and ranges. 1.3222 + // Note that the maximum value reported is an inclusive maximum value so it is one 1.3223 + // unit less than the total width or height of surface. 1.3224 + switch (mSurfaceOrientation) { 1.3225 + case DISPLAY_ORIENTATION_90: 1.3226 + case DISPLAY_ORIENTATION_270: 1.3227 + mOrientedXPrecision = mYPrecision; 1.3228 + mOrientedYPrecision = mXPrecision; 1.3229 + 1.3230 + mOrientedRanges.x.min = mYTranslate; 1.3231 + mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1; 1.3232 + mOrientedRanges.x.flat = 0; 1.3233 + mOrientedRanges.x.fuzz = 0; 1.3234 + mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mYScale; 1.3235 + 1.3236 + mOrientedRanges.y.min = mXTranslate; 1.3237 + mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1; 1.3238 + mOrientedRanges.y.flat = 0; 1.3239 + mOrientedRanges.y.fuzz = 0; 1.3240 + mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mXScale; 1.3241 + break; 1.3242 + 1.3243 + default: 1.3244 + mOrientedXPrecision = mXPrecision; 1.3245 + mOrientedYPrecision = mYPrecision; 1.3246 + 1.3247 + mOrientedRanges.x.min = mXTranslate; 1.3248 + mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1; 1.3249 + mOrientedRanges.x.flat = 0; 1.3250 + mOrientedRanges.x.fuzz = 0; 1.3251 + mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mXScale; 1.3252 + 1.3253 + mOrientedRanges.y.min = mYTranslate; 1.3254 + mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1; 1.3255 + mOrientedRanges.y.flat = 0; 1.3256 + mOrientedRanges.y.fuzz = 0; 1.3257 + mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale; 1.3258 + break; 1.3259 + } 1.3260 + 1.3261 + if (mDeviceMode == DEVICE_MODE_POINTER) { 1.3262 + // Compute pointer gesture detection parameters. 1.3263 + float rawDiagonal = hypotf(rawWidth, rawHeight); 1.3264 + float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight); 1.3265 + 1.3266 + // Scale movements such that one whole swipe of the touch pad covers a 1.3267 + // given area relative to the diagonal size of the display when no acceleration 1.3268 + // is applied. 1.3269 + // Assume that the touch pad has a square aspect ratio such that movements in 1.3270 + // X and Y of the same number of raw units cover the same physical distance. 1.3271 + mPointerXMovementScale = mConfig.pointerGestureMovementSpeedRatio 1.3272 + * displayDiagonal / rawDiagonal; 1.3273 + mPointerYMovementScale = mPointerXMovementScale; 1.3274 + 1.3275 + // Scale zooms to cover a smaller range of the display than movements do. 1.3276 + // This value determines the area around the pointer that is affected by freeform 1.3277 + // pointer gestures. 1.3278 + mPointerXZoomScale = mConfig.pointerGestureZoomSpeedRatio 1.3279 + * displayDiagonal / rawDiagonal; 1.3280 + mPointerYZoomScale = mPointerXZoomScale; 1.3281 + 1.3282 + // Max width between pointers to detect a swipe gesture is more than some fraction 1.3283 + // of the diagonal axis of the touch pad. Touches that are wider than this are 1.3284 + // translated into freeform gestures. 1.3285 + mPointerGestureMaxSwipeWidth = 1.3286 + mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal; 1.3287 + 1.3288 + // Abort current pointer usages because the state has changed. 1.3289 + abortPointerUsage(when, 0 /*policyFlags*/); 1.3290 + } 1.3291 + 1.3292 + // Inform the dispatcher about the changes. 1.3293 + *outResetNeeded = true; 1.3294 + bumpGeneration(); 1.3295 + } 1.3296 +} 1.3297 + 1.3298 +void TouchInputMapper::dumpSurface(String8& dump) { 1.3299 + dump.appendFormat(INDENT3 "Viewport: displayId=%d, orientation=%d, " 1.3300 + "logicalFrame=[%d, %d, %d, %d], " 1.3301 + "physicalFrame=[%d, %d, %d, %d], " 1.3302 + "deviceSize=[%d, %d]\n", 1.3303 + mViewport.displayId, mViewport.orientation, 1.3304 + mViewport.logicalLeft, mViewport.logicalTop, 1.3305 + mViewport.logicalRight, mViewport.logicalBottom, 1.3306 + mViewport.physicalLeft, mViewport.physicalTop, 1.3307 + mViewport.physicalRight, mViewport.physicalBottom, 1.3308 + mViewport.deviceWidth, mViewport.deviceHeight); 1.3309 + 1.3310 + dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth); 1.3311 + dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight); 1.3312 + dump.appendFormat(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft); 1.3313 + dump.appendFormat(INDENT3 "SurfaceTop: %d\n", mSurfaceTop); 1.3314 + dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation); 1.3315 +} 1.3316 + 1.3317 +void TouchInputMapper::configureVirtualKeys() { 1.3318 + Vector<VirtualKeyDefinition> virtualKeyDefinitions; 1.3319 + getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions); 1.3320 + 1.3321 + mVirtualKeys.clear(); 1.3322 + 1.3323 + if (virtualKeyDefinitions.size() == 0) { 1.3324 + return; 1.3325 + } 1.3326 + 1.3327 + mVirtualKeys.setCapacity(virtualKeyDefinitions.size()); 1.3328 + 1.3329 + int32_t touchScreenLeft = mRawPointerAxes.x.minValue; 1.3330 + int32_t touchScreenTop = mRawPointerAxes.y.minValue; 1.3331 + int32_t touchScreenWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1; 1.3332 + int32_t touchScreenHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1; 1.3333 + 1.3334 + for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) { 1.3335 + const VirtualKeyDefinition& virtualKeyDefinition = 1.3336 + virtualKeyDefinitions[i]; 1.3337 + 1.3338 + mVirtualKeys.add(); 1.3339 + VirtualKey& virtualKey = mVirtualKeys.editTop(); 1.3340 + 1.3341 + virtualKey.scanCode = virtualKeyDefinition.scanCode; 1.3342 + int32_t keyCode; 1.3343 + uint32_t flags; 1.3344 + if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, 0, &keyCode, &flags)) { 1.3345 + ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring", 1.3346 + virtualKey.scanCode); 1.3347 + mVirtualKeys.pop(); // drop the key 1.3348 + continue; 1.3349 + } 1.3350 + 1.3351 + virtualKey.keyCode = keyCode; 1.3352 + virtualKey.flags = flags; 1.3353 + 1.3354 + // convert the key definition's display coordinates into touch coordinates for a hit box 1.3355 + int32_t halfWidth = virtualKeyDefinition.width / 2; 1.3356 + int32_t halfHeight = virtualKeyDefinition.height / 2; 1.3357 + 1.3358 + virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth) 1.3359 + * touchScreenWidth / mSurfaceWidth + touchScreenLeft; 1.3360 + virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth) 1.3361 + * touchScreenWidth / mSurfaceWidth + touchScreenLeft; 1.3362 + virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight) 1.3363 + * touchScreenHeight / mSurfaceHeight + touchScreenTop; 1.3364 + virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight) 1.3365 + * touchScreenHeight / mSurfaceHeight + touchScreenTop; 1.3366 + } 1.3367 +} 1.3368 + 1.3369 +void TouchInputMapper::dumpVirtualKeys(String8& dump) { 1.3370 + if (!mVirtualKeys.isEmpty()) { 1.3371 + dump.append(INDENT3 "Virtual Keys:\n"); 1.3372 + 1.3373 + for (size_t i = 0; i < mVirtualKeys.size(); i++) { 1.3374 + const VirtualKey& virtualKey = mVirtualKeys.itemAt(i); 1.3375 + dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, " 1.3376 + "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n", 1.3377 + i, virtualKey.scanCode, virtualKey.keyCode, 1.3378 + virtualKey.hitLeft, virtualKey.hitRight, 1.3379 + virtualKey.hitTop, virtualKey.hitBottom); 1.3380 + } 1.3381 + } 1.3382 +} 1.3383 + 1.3384 +void TouchInputMapper::parseCalibration() { 1.3385 + const PropertyMap& in = getDevice()->getConfiguration(); 1.3386 + Calibration& out = mCalibration; 1.3387 + 1.3388 + // Size 1.3389 + out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT; 1.3390 + String8 sizeCalibrationString; 1.3391 + if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) { 1.3392 + if (sizeCalibrationString == "none") { 1.3393 + out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE; 1.3394 + } else if (sizeCalibrationString == "geometric") { 1.3395 + out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC; 1.3396 + } else if (sizeCalibrationString == "diameter") { 1.3397 + out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER; 1.3398 + } else if (sizeCalibrationString == "box") { 1.3399 + out.sizeCalibration = Calibration::SIZE_CALIBRATION_BOX; 1.3400 + } else if (sizeCalibrationString == "area") { 1.3401 + out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA; 1.3402 + } else if (sizeCalibrationString != "default") { 1.3403 + ALOGW("Invalid value for touch.size.calibration: '%s'", 1.3404 + sizeCalibrationString.string()); 1.3405 + } 1.3406 + } 1.3407 + 1.3408 + out.haveSizeScale = in.tryGetProperty(String8("touch.size.scale"), 1.3409 + out.sizeScale); 1.3410 + out.haveSizeBias = in.tryGetProperty(String8("touch.size.bias"), 1.3411 + out.sizeBias); 1.3412 + out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"), 1.3413 + out.sizeIsSummed); 1.3414 + 1.3415 + // Pressure 1.3416 + out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT; 1.3417 + String8 pressureCalibrationString; 1.3418 + if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) { 1.3419 + if (pressureCalibrationString == "none") { 1.3420 + out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE; 1.3421 + } else if (pressureCalibrationString == "physical") { 1.3422 + out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL; 1.3423 + } else if (pressureCalibrationString == "amplitude") { 1.3424 + out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE; 1.3425 + } else if (pressureCalibrationString != "default") { 1.3426 + ALOGW("Invalid value for touch.pressure.calibration: '%s'", 1.3427 + pressureCalibrationString.string()); 1.3428 + } 1.3429 + } 1.3430 + 1.3431 + out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"), 1.3432 + out.pressureScale); 1.3433 + 1.3434 + // Orientation 1.3435 + out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT; 1.3436 + String8 orientationCalibrationString; 1.3437 + if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) { 1.3438 + if (orientationCalibrationString == "none") { 1.3439 + out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE; 1.3440 + } else if (orientationCalibrationString == "interpolated") { 1.3441 + out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED; 1.3442 + } else if (orientationCalibrationString == "vector") { 1.3443 + out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR; 1.3444 + } else if (orientationCalibrationString != "default") { 1.3445 + ALOGW("Invalid value for touch.orientation.calibration: '%s'", 1.3446 + orientationCalibrationString.string()); 1.3447 + } 1.3448 + } 1.3449 + 1.3450 + // Distance 1.3451 + out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT; 1.3452 + String8 distanceCalibrationString; 1.3453 + if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) { 1.3454 + if (distanceCalibrationString == "none") { 1.3455 + out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE; 1.3456 + } else if (distanceCalibrationString == "scaled") { 1.3457 + out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED; 1.3458 + } else if (distanceCalibrationString != "default") { 1.3459 + ALOGW("Invalid value for touch.distance.calibration: '%s'", 1.3460 + distanceCalibrationString.string()); 1.3461 + } 1.3462 + } 1.3463 + 1.3464 + out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"), 1.3465 + out.distanceScale); 1.3466 + 1.3467 + out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_DEFAULT; 1.3468 + String8 coverageCalibrationString; 1.3469 + if (in.tryGetProperty(String8("touch.coverage.calibration"), coverageCalibrationString)) { 1.3470 + if (coverageCalibrationString == "none") { 1.3471 + out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE; 1.3472 + } else if (coverageCalibrationString == "box") { 1.3473 + out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_BOX; 1.3474 + } else if (coverageCalibrationString != "default") { 1.3475 + ALOGW("Invalid value for touch.coverage.calibration: '%s'", 1.3476 + coverageCalibrationString.string()); 1.3477 + } 1.3478 + } 1.3479 +} 1.3480 + 1.3481 +void TouchInputMapper::resolveCalibration() { 1.3482 + // Size 1.3483 + if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) { 1.3484 + if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DEFAULT) { 1.3485 + mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC; 1.3486 + } 1.3487 + } else { 1.3488 + mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE; 1.3489 + } 1.3490 + 1.3491 + // Pressure 1.3492 + if (mRawPointerAxes.pressure.valid) { 1.3493 + if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DEFAULT) { 1.3494 + mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL; 1.3495 + } 1.3496 + } else { 1.3497 + mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE; 1.3498 + } 1.3499 + 1.3500 + // Orientation 1.3501 + if (mRawPointerAxes.orientation.valid) { 1.3502 + if (mCalibration.orientationCalibration == Calibration::ORIENTATION_CALIBRATION_DEFAULT) { 1.3503 + mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED; 1.3504 + } 1.3505 + } else { 1.3506 + mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE; 1.3507 + } 1.3508 + 1.3509 + // Distance 1.3510 + if (mRawPointerAxes.distance.valid) { 1.3511 + if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_DEFAULT) { 1.3512 + mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED; 1.3513 + } 1.3514 + } else { 1.3515 + mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE; 1.3516 + } 1.3517 + 1.3518 + // Coverage 1.3519 + if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_DEFAULT) { 1.3520 + mCalibration.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE; 1.3521 + } 1.3522 +} 1.3523 + 1.3524 +void TouchInputMapper::dumpCalibration(String8& dump) { 1.3525 + dump.append(INDENT3 "Calibration:\n"); 1.3526 + 1.3527 + // Size 1.3528 + switch (mCalibration.sizeCalibration) { 1.3529 + case Calibration::SIZE_CALIBRATION_NONE: 1.3530 + dump.append(INDENT4 "touch.size.calibration: none\n"); 1.3531 + break; 1.3532 + case Calibration::SIZE_CALIBRATION_GEOMETRIC: 1.3533 + dump.append(INDENT4 "touch.size.calibration: geometric\n"); 1.3534 + break; 1.3535 + case Calibration::SIZE_CALIBRATION_DIAMETER: 1.3536 + dump.append(INDENT4 "touch.size.calibration: diameter\n"); 1.3537 + break; 1.3538 + case Calibration::SIZE_CALIBRATION_BOX: 1.3539 + dump.append(INDENT4 "touch.size.calibration: box\n"); 1.3540 + break; 1.3541 + case Calibration::SIZE_CALIBRATION_AREA: 1.3542 + dump.append(INDENT4 "touch.size.calibration: area\n"); 1.3543 + break; 1.3544 + default: 1.3545 + ALOG_ASSERT(false); 1.3546 + } 1.3547 + 1.3548 + if (mCalibration.haveSizeScale) { 1.3549 + dump.appendFormat(INDENT4 "touch.size.scale: %0.3f\n", 1.3550 + mCalibration.sizeScale); 1.3551 + } 1.3552 + 1.3553 + if (mCalibration.haveSizeBias) { 1.3554 + dump.appendFormat(INDENT4 "touch.size.bias: %0.3f\n", 1.3555 + mCalibration.sizeBias); 1.3556 + } 1.3557 + 1.3558 + if (mCalibration.haveSizeIsSummed) { 1.3559 + dump.appendFormat(INDENT4 "touch.size.isSummed: %s\n", 1.3560 + toString(mCalibration.sizeIsSummed)); 1.3561 + } 1.3562 + 1.3563 + // Pressure 1.3564 + switch (mCalibration.pressureCalibration) { 1.3565 + case Calibration::PRESSURE_CALIBRATION_NONE: 1.3566 + dump.append(INDENT4 "touch.pressure.calibration: none\n"); 1.3567 + break; 1.3568 + case Calibration::PRESSURE_CALIBRATION_PHYSICAL: 1.3569 + dump.append(INDENT4 "touch.pressure.calibration: physical\n"); 1.3570 + break; 1.3571 + case Calibration::PRESSURE_CALIBRATION_AMPLITUDE: 1.3572 + dump.append(INDENT4 "touch.pressure.calibration: amplitude\n"); 1.3573 + break; 1.3574 + default: 1.3575 + ALOG_ASSERT(false); 1.3576 + } 1.3577 + 1.3578 + if (mCalibration.havePressureScale) { 1.3579 + dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n", 1.3580 + mCalibration.pressureScale); 1.3581 + } 1.3582 + 1.3583 + // Orientation 1.3584 + switch (mCalibration.orientationCalibration) { 1.3585 + case Calibration::ORIENTATION_CALIBRATION_NONE: 1.3586 + dump.append(INDENT4 "touch.orientation.calibration: none\n"); 1.3587 + break; 1.3588 + case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED: 1.3589 + dump.append(INDENT4 "touch.orientation.calibration: interpolated\n"); 1.3590 + break; 1.3591 + case Calibration::ORIENTATION_CALIBRATION_VECTOR: 1.3592 + dump.append(INDENT4 "touch.orientation.calibration: vector\n"); 1.3593 + break; 1.3594 + default: 1.3595 + ALOG_ASSERT(false); 1.3596 + } 1.3597 + 1.3598 + // Distance 1.3599 + switch (mCalibration.distanceCalibration) { 1.3600 + case Calibration::DISTANCE_CALIBRATION_NONE: 1.3601 + dump.append(INDENT4 "touch.distance.calibration: none\n"); 1.3602 + break; 1.3603 + case Calibration::DISTANCE_CALIBRATION_SCALED: 1.3604 + dump.append(INDENT4 "touch.distance.calibration: scaled\n"); 1.3605 + break; 1.3606 + default: 1.3607 + ALOG_ASSERT(false); 1.3608 + } 1.3609 + 1.3610 + if (mCalibration.haveDistanceScale) { 1.3611 + dump.appendFormat(INDENT4 "touch.distance.scale: %0.3f\n", 1.3612 + mCalibration.distanceScale); 1.3613 + } 1.3614 + 1.3615 + switch (mCalibration.coverageCalibration) { 1.3616 + case Calibration::COVERAGE_CALIBRATION_NONE: 1.3617 + dump.append(INDENT4 "touch.coverage.calibration: none\n"); 1.3618 + break; 1.3619 + case Calibration::COVERAGE_CALIBRATION_BOX: 1.3620 + dump.append(INDENT4 "touch.coverage.calibration: box\n"); 1.3621 + break; 1.3622 + default: 1.3623 + ALOG_ASSERT(false); 1.3624 + } 1.3625 +} 1.3626 + 1.3627 +void TouchInputMapper::reset(nsecs_t when) { 1.3628 + mCursorButtonAccumulator.reset(getDevice()); 1.3629 + mCursorScrollAccumulator.reset(getDevice()); 1.3630 + mTouchButtonAccumulator.reset(getDevice()); 1.3631 + 1.3632 + mPointerVelocityControl.reset(); 1.3633 + mWheelXVelocityControl.reset(); 1.3634 + mWheelYVelocityControl.reset(); 1.3635 + 1.3636 + mCurrentRawPointerData.clear(); 1.3637 + mLastRawPointerData.clear(); 1.3638 + mCurrentCookedPointerData.clear(); 1.3639 + mLastCookedPointerData.clear(); 1.3640 + mCurrentButtonState = 0; 1.3641 + mLastButtonState = 0; 1.3642 + mCurrentRawVScroll = 0; 1.3643 + mCurrentRawHScroll = 0; 1.3644 + mCurrentFingerIdBits.clear(); 1.3645 + mLastFingerIdBits.clear(); 1.3646 + mCurrentStylusIdBits.clear(); 1.3647 + mLastStylusIdBits.clear(); 1.3648 + mCurrentMouseIdBits.clear(); 1.3649 + mLastMouseIdBits.clear(); 1.3650 + mPointerUsage = POINTER_USAGE_NONE; 1.3651 + mSentHoverEnter = false; 1.3652 + mDownTime = 0; 1.3653 + 1.3654 + mCurrentVirtualKey.down = false; 1.3655 + 1.3656 + mPointerGesture.reset(); 1.3657 + mPointerSimple.reset(); 1.3658 + 1.3659 + if (mPointerController != NULL) { 1.3660 + mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); 1.3661 + mPointerController->clearSpots(); 1.3662 + } 1.3663 + 1.3664 + InputMapper::reset(when); 1.3665 +} 1.3666 + 1.3667 +void TouchInputMapper::process(const RawEvent* rawEvent) { 1.3668 + mCursorButtonAccumulator.process(rawEvent); 1.3669 + mCursorScrollAccumulator.process(rawEvent); 1.3670 + mTouchButtonAccumulator.process(rawEvent); 1.3671 + 1.3672 + if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { 1.3673 + sync(rawEvent->when); 1.3674 + } 1.3675 +} 1.3676 + 1.3677 +void TouchInputMapper::sync(nsecs_t when) { 1.3678 + // Sync button state. 1.3679 + mCurrentButtonState = mTouchButtonAccumulator.getButtonState() 1.3680 + | mCursorButtonAccumulator.getButtonState(); 1.3681 + 1.3682 + // Sync scroll state. 1.3683 + mCurrentRawVScroll = mCursorScrollAccumulator.getRelativeVWheel(); 1.3684 + mCurrentRawHScroll = mCursorScrollAccumulator.getRelativeHWheel(); 1.3685 + mCursorScrollAccumulator.finishSync(); 1.3686 + 1.3687 + // Sync touch state. 1.3688 + bool havePointerIds = true; 1.3689 + mCurrentRawPointerData.clear(); 1.3690 + syncTouch(when, &havePointerIds); 1.3691 + 1.3692 +#if DEBUG_RAW_EVENTS 1.3693 + if (!havePointerIds) { 1.3694 + ALOGD("syncTouch: pointerCount %d -> %d, no pointer ids", 1.3695 + mLastRawPointerData.pointerCount, 1.3696 + mCurrentRawPointerData.pointerCount); 1.3697 + } else { 1.3698 + ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, " 1.3699 + "hovering ids 0x%08x -> 0x%08x", 1.3700 + mLastRawPointerData.pointerCount, 1.3701 + mCurrentRawPointerData.pointerCount, 1.3702 + mLastRawPointerData.touchingIdBits.value, 1.3703 + mCurrentRawPointerData.touchingIdBits.value, 1.3704 + mLastRawPointerData.hoveringIdBits.value, 1.3705 + mCurrentRawPointerData.hoveringIdBits.value); 1.3706 + } 1.3707 +#endif 1.3708 + 1.3709 + // Reset state that we will compute below. 1.3710 + mCurrentFingerIdBits.clear(); 1.3711 + mCurrentStylusIdBits.clear(); 1.3712 + mCurrentMouseIdBits.clear(); 1.3713 + mCurrentCookedPointerData.clear(); 1.3714 + 1.3715 + if (mDeviceMode == DEVICE_MODE_DISABLED) { 1.3716 + // Drop all input if the device is disabled. 1.3717 + mCurrentRawPointerData.clear(); 1.3718 + mCurrentButtonState = 0; 1.3719 + } else { 1.3720 + // Preprocess pointer data. 1.3721 + if (!havePointerIds) { 1.3722 + assignPointerIds(); 1.3723 + } 1.3724 + 1.3725 + // Handle policy on initial down or hover events. 1.3726 + uint32_t policyFlags = 0; 1.3727 + bool initialDown = mLastRawPointerData.pointerCount == 0 1.3728 + && mCurrentRawPointerData.pointerCount != 0; 1.3729 + bool buttonsPressed = mCurrentButtonState & ~mLastButtonState; 1.3730 + if (initialDown || buttonsPressed) { 1.3731 + // If this is a touch screen, hide the pointer on an initial down. 1.3732 + if (mDeviceMode == DEVICE_MODE_DIRECT) { 1.3733 + getContext()->fadePointer(); 1.3734 + } 1.3735 + 1.3736 + // Initial downs on external touch devices should wake the device. 1.3737 + // We don't do this for internal touch screens to prevent them from waking 1.3738 + // up in your pocket. 1.3739 + // TODO: Use the input device configuration to control this behavior more finely. 1.3740 + if (getDevice()->isExternal()) { 1.3741 + policyFlags |= POLICY_FLAG_WAKE_DROPPED; 1.3742 + } 1.3743 + } 1.3744 + 1.3745 + // Synthesize key down from raw buttons if needed. 1.3746 + synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource, 1.3747 + policyFlags, mLastButtonState, mCurrentButtonState); 1.3748 + 1.3749 + // Consume raw off-screen touches before cooking pointer data. 1.3750 + // If touches are consumed, subsequent code will not receive any pointer data. 1.3751 + if (consumeRawTouches(when, policyFlags)) { 1.3752 + mCurrentRawPointerData.clear(); 1.3753 + } 1.3754 + 1.3755 + // Cook pointer data. This call populates the mCurrentCookedPointerData structure 1.3756 + // with cooked pointer data that has the same ids and indices as the raw data. 1.3757 + // The following code can use either the raw or cooked data, as needed. 1.3758 + cookPointerData(); 1.3759 + 1.3760 + // Dispatch the touches either directly or by translation through a pointer on screen. 1.3761 + if (mDeviceMode == DEVICE_MODE_POINTER) { 1.3762 + for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); !idBits.isEmpty(); ) { 1.3763 + uint32_t id = idBits.clearFirstMarkedBit(); 1.3764 + const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id); 1.3765 + if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS 1.3766 + || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) { 1.3767 + mCurrentStylusIdBits.markBit(id); 1.3768 + } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER 1.3769 + || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) { 1.3770 + mCurrentFingerIdBits.markBit(id); 1.3771 + } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) { 1.3772 + mCurrentMouseIdBits.markBit(id); 1.3773 + } 1.3774 + } 1.3775 + for (BitSet32 idBits(mCurrentRawPointerData.hoveringIdBits); !idBits.isEmpty(); ) { 1.3776 + uint32_t id = idBits.clearFirstMarkedBit(); 1.3777 + const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id); 1.3778 + if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS 1.3779 + || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) { 1.3780 + mCurrentStylusIdBits.markBit(id); 1.3781 + } 1.3782 + } 1.3783 + 1.3784 + // Stylus takes precedence over all tools, then mouse, then finger. 1.3785 + PointerUsage pointerUsage = mPointerUsage; 1.3786 + if (!mCurrentStylusIdBits.isEmpty()) { 1.3787 + mCurrentMouseIdBits.clear(); 1.3788 + mCurrentFingerIdBits.clear(); 1.3789 + pointerUsage = POINTER_USAGE_STYLUS; 1.3790 + } else if (!mCurrentMouseIdBits.isEmpty()) { 1.3791 + mCurrentFingerIdBits.clear(); 1.3792 + pointerUsage = POINTER_USAGE_MOUSE; 1.3793 + } else if (!mCurrentFingerIdBits.isEmpty() || isPointerDown(mCurrentButtonState)) { 1.3794 + pointerUsage = POINTER_USAGE_GESTURES; 1.3795 + } 1.3796 + 1.3797 + dispatchPointerUsage(when, policyFlags, pointerUsage); 1.3798 + } else { 1.3799 + if (mDeviceMode == DEVICE_MODE_DIRECT 1.3800 + && mConfig.showTouches && mPointerController != NULL) { 1.3801 + mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT); 1.3802 + mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); 1.3803 + 1.3804 + mPointerController->setButtonState(mCurrentButtonState); 1.3805 + mPointerController->setSpots(mCurrentCookedPointerData.pointerCoords, 1.3806 + mCurrentCookedPointerData.idToIndex, 1.3807 + mCurrentCookedPointerData.touchingIdBits); 1.3808 + } 1.3809 + 1.3810 + dispatchHoverExit(when, policyFlags); 1.3811 + dispatchTouches(when, policyFlags); 1.3812 + dispatchHoverEnterAndMove(when, policyFlags); 1.3813 + } 1.3814 + 1.3815 + // Synthesize key up from raw buttons if needed. 1.3816 + synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource, 1.3817 + policyFlags, mLastButtonState, mCurrentButtonState); 1.3818 + } 1.3819 + 1.3820 + // Copy current touch to last touch in preparation for the next cycle. 1.3821 + mLastRawPointerData.copyFrom(mCurrentRawPointerData); 1.3822 + mLastCookedPointerData.copyFrom(mCurrentCookedPointerData); 1.3823 + mLastButtonState = mCurrentButtonState; 1.3824 + mLastFingerIdBits = mCurrentFingerIdBits; 1.3825 + mLastStylusIdBits = mCurrentStylusIdBits; 1.3826 + mLastMouseIdBits = mCurrentMouseIdBits; 1.3827 + 1.3828 + // Clear some transient state. 1.3829 + mCurrentRawVScroll = 0; 1.3830 + mCurrentRawHScroll = 0; 1.3831 +} 1.3832 + 1.3833 +void TouchInputMapper::timeoutExpired(nsecs_t when) { 1.3834 + if (mDeviceMode == DEVICE_MODE_POINTER) { 1.3835 + if (mPointerUsage == POINTER_USAGE_GESTURES) { 1.3836 + dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/); 1.3837 + } 1.3838 + } 1.3839 +} 1.3840 + 1.3841 +bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) { 1.3842 + // Check for release of a virtual key. 1.3843 + if (mCurrentVirtualKey.down) { 1.3844 + if (mCurrentRawPointerData.touchingIdBits.isEmpty()) { 1.3845 + // Pointer went up while virtual key was down. 1.3846 + mCurrentVirtualKey.down = false; 1.3847 + if (!mCurrentVirtualKey.ignored) { 1.3848 +#if DEBUG_VIRTUAL_KEYS 1.3849 + ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d", 1.3850 + mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode); 1.3851 +#endif 1.3852 + dispatchVirtualKey(when, policyFlags, 1.3853 + AKEY_EVENT_ACTION_UP, 1.3854 + AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY); 1.3855 + } 1.3856 + return true; 1.3857 + } 1.3858 + 1.3859 + if (mCurrentRawPointerData.touchingIdBits.count() == 1) { 1.3860 + uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit(); 1.3861 + const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id); 1.3862 + const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y); 1.3863 + if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) { 1.3864 + // Pointer is still within the space of the virtual key. 1.3865 + return true; 1.3866 + } 1.3867 + } 1.3868 + 1.3869 + // Pointer left virtual key area or another pointer also went down. 1.3870 + // Send key cancellation but do not consume the touch yet. 1.3871 + // This is useful when the user swipes through from the virtual key area 1.3872 + // into the main display surface. 1.3873 + mCurrentVirtualKey.down = false; 1.3874 + if (!mCurrentVirtualKey.ignored) { 1.3875 +#if DEBUG_VIRTUAL_KEYS 1.3876 + ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d", 1.3877 + mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode); 1.3878 +#endif 1.3879 + dispatchVirtualKey(when, policyFlags, 1.3880 + AKEY_EVENT_ACTION_UP, 1.3881 + AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY 1.3882 + | AKEY_EVENT_FLAG_CANCELED); 1.3883 + } 1.3884 + } 1.3885 + 1.3886 + if (mLastRawPointerData.touchingIdBits.isEmpty() 1.3887 + && !mCurrentRawPointerData.touchingIdBits.isEmpty()) { 1.3888 + // Pointer just went down. Check for virtual key press or off-screen touches. 1.3889 + uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit(); 1.3890 + const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id); 1.3891 + if (!isPointInsideSurface(pointer.x, pointer.y)) { 1.3892 + // If exactly one pointer went down, check for virtual key hit. 1.3893 + // Otherwise we will drop the entire stroke. 1.3894 + if (mCurrentRawPointerData.touchingIdBits.count() == 1) { 1.3895 + const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y); 1.3896 + if (virtualKey) { 1.3897 + mCurrentVirtualKey.down = true; 1.3898 + mCurrentVirtualKey.downTime = when; 1.3899 + mCurrentVirtualKey.keyCode = virtualKey->keyCode; 1.3900 + mCurrentVirtualKey.scanCode = virtualKey->scanCode; 1.3901 + mCurrentVirtualKey.ignored = mContext->shouldDropVirtualKey( 1.3902 + when, getDevice(), virtualKey->keyCode, virtualKey->scanCode); 1.3903 + 1.3904 + if (!mCurrentVirtualKey.ignored) { 1.3905 +#if DEBUG_VIRTUAL_KEYS 1.3906 + ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d", 1.3907 + mCurrentVirtualKey.keyCode, 1.3908 + mCurrentVirtualKey.scanCode); 1.3909 +#endif 1.3910 + dispatchVirtualKey(when, policyFlags, 1.3911 + AKEY_EVENT_ACTION_DOWN, 1.3912 + AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY); 1.3913 + } 1.3914 + } 1.3915 + } 1.3916 + return true; 1.3917 + } 1.3918 + } 1.3919 + 1.3920 + // Disable all virtual key touches that happen within a short time interval of the 1.3921 + // most recent touch within the screen area. The idea is to filter out stray 1.3922 + // virtual key presses when interacting with the touch screen. 1.3923 + // 1.3924 + // Problems we're trying to solve: 1.3925 + // 1.3926 + // 1. While scrolling a list or dragging the window shade, the user swipes down into a 1.3927 + // virtual key area that is implemented by a separate touch panel and accidentally 1.3928 + // triggers a virtual key. 1.3929 + // 1.3930 + // 2. While typing in the on screen keyboard, the user taps slightly outside the screen 1.3931 + // area and accidentally triggers a virtual key. This often happens when virtual keys 1.3932 + // are layed out below the screen near to where the on screen keyboard's space bar 1.3933 + // is displayed. 1.3934 + if (mConfig.virtualKeyQuietTime > 0 && !mCurrentRawPointerData.touchingIdBits.isEmpty()) { 1.3935 + mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime); 1.3936 + } 1.3937 + return false; 1.3938 +} 1.3939 + 1.3940 +void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags, 1.3941 + int32_t keyEventAction, int32_t keyEventFlags) { 1.3942 + int32_t keyCode = mCurrentVirtualKey.keyCode; 1.3943 + int32_t scanCode = mCurrentVirtualKey.scanCode; 1.3944 + nsecs_t downTime = mCurrentVirtualKey.downTime; 1.3945 + int32_t metaState = mContext->getGlobalMetaState(); 1.3946 + policyFlags |= POLICY_FLAG_VIRTUAL; 1.3947 + 1.3948 + NotifyKeyArgs args(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags, 1.3949 + keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime); 1.3950 + getListener()->notifyKey(&args); 1.3951 +} 1.3952 + 1.3953 +void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { 1.3954 + BitSet32 currentIdBits = mCurrentCookedPointerData.touchingIdBits; 1.3955 + BitSet32 lastIdBits = mLastCookedPointerData.touchingIdBits; 1.3956 + int32_t metaState = getContext()->getGlobalMetaState(); 1.3957 + int32_t buttonState = mCurrentButtonState; 1.3958 + 1.3959 + if (currentIdBits == lastIdBits) { 1.3960 + if (!currentIdBits.isEmpty()) { 1.3961 + // No pointer id changes so this is a move event. 1.3962 + // The listener takes care of batching moves so we don't have to deal with that here. 1.3963 + dispatchMotion(when, policyFlags, mSource, 1.3964 + AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 1.3965 + AMOTION_EVENT_EDGE_FLAG_NONE, 1.3966 + mCurrentCookedPointerData.pointerProperties, 1.3967 + mCurrentCookedPointerData.pointerCoords, 1.3968 + mCurrentCookedPointerData.idToIndex, 1.3969 + currentIdBits, -1, 1.3970 + mOrientedXPrecision, mOrientedYPrecision, mDownTime); 1.3971 + } 1.3972 + } else { 1.3973 + // There may be pointers going up and pointers going down and pointers moving 1.3974 + // all at the same time. 1.3975 + BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value); 1.3976 + BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value); 1.3977 + BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value); 1.3978 + BitSet32 dispatchedIdBits(lastIdBits.value); 1.3979 + 1.3980 + // Update last coordinates of pointers that have moved so that we observe the new 1.3981 + // pointer positions at the same time as other pointers that have just gone up. 1.3982 + bool moveNeeded = updateMovedPointers( 1.3983 + mCurrentCookedPointerData.pointerProperties, 1.3984 + mCurrentCookedPointerData.pointerCoords, 1.3985 + mCurrentCookedPointerData.idToIndex, 1.3986 + mLastCookedPointerData.pointerProperties, 1.3987 + mLastCookedPointerData.pointerCoords, 1.3988 + mLastCookedPointerData.idToIndex, 1.3989 + moveIdBits); 1.3990 + if (buttonState != mLastButtonState) { 1.3991 + moveNeeded = true; 1.3992 + } 1.3993 + 1.3994 + // Dispatch pointer up events. 1.3995 + while (!upIdBits.isEmpty()) { 1.3996 + uint32_t upId = upIdBits.clearFirstMarkedBit(); 1.3997 + 1.3998 + dispatchMotion(when, policyFlags, mSource, 1.3999 + AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0, 1.4000 + mLastCookedPointerData.pointerProperties, 1.4001 + mLastCookedPointerData.pointerCoords, 1.4002 + mLastCookedPointerData.idToIndex, 1.4003 + dispatchedIdBits, upId, 1.4004 + mOrientedXPrecision, mOrientedYPrecision, mDownTime); 1.4005 + dispatchedIdBits.clearBit(upId); 1.4006 + } 1.4007 + 1.4008 + // Dispatch move events if any of the remaining pointers moved from their old locations. 1.4009 + // Although applications receive new locations as part of individual pointer up 1.4010 + // events, they do not generally handle them except when presented in a move event. 1.4011 + if (moveNeeded) { 1.4012 + ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value); 1.4013 + dispatchMotion(when, policyFlags, mSource, 1.4014 + AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0, 1.4015 + mCurrentCookedPointerData.pointerProperties, 1.4016 + mCurrentCookedPointerData.pointerCoords, 1.4017 + mCurrentCookedPointerData.idToIndex, 1.4018 + dispatchedIdBits, -1, 1.4019 + mOrientedXPrecision, mOrientedYPrecision, mDownTime); 1.4020 + } 1.4021 + 1.4022 + // Dispatch pointer down events using the new pointer locations. 1.4023 + while (!downIdBits.isEmpty()) { 1.4024 + uint32_t downId = downIdBits.clearFirstMarkedBit(); 1.4025 + dispatchedIdBits.markBit(downId); 1.4026 + 1.4027 + if (dispatchedIdBits.count() == 1) { 1.4028 + // First pointer is going down. Set down time. 1.4029 + mDownTime = when; 1.4030 + } 1.4031 + 1.4032 + dispatchMotion(when, policyFlags, mSource, 1.4033 + AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0, 1.4034 + mCurrentCookedPointerData.pointerProperties, 1.4035 + mCurrentCookedPointerData.pointerCoords, 1.4036 + mCurrentCookedPointerData.idToIndex, 1.4037 + dispatchedIdBits, downId, 1.4038 + mOrientedXPrecision, mOrientedYPrecision, mDownTime); 1.4039 + } 1.4040 + } 1.4041 +} 1.4042 + 1.4043 +void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) { 1.4044 + if (mSentHoverEnter && 1.4045 + (mCurrentCookedPointerData.hoveringIdBits.isEmpty() 1.4046 + || !mCurrentCookedPointerData.touchingIdBits.isEmpty())) { 1.4047 + int32_t metaState = getContext()->getGlobalMetaState(); 1.4048 + dispatchMotion(when, policyFlags, mSource, 1.4049 + AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0, 1.4050 + mLastCookedPointerData.pointerProperties, 1.4051 + mLastCookedPointerData.pointerCoords, 1.4052 + mLastCookedPointerData.idToIndex, 1.4053 + mLastCookedPointerData.hoveringIdBits, -1, 1.4054 + mOrientedXPrecision, mOrientedYPrecision, mDownTime); 1.4055 + mSentHoverEnter = false; 1.4056 + } 1.4057 +} 1.4058 + 1.4059 +void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) { 1.4060 + if (mCurrentCookedPointerData.touchingIdBits.isEmpty() 1.4061 + && !mCurrentCookedPointerData.hoveringIdBits.isEmpty()) { 1.4062 + int32_t metaState = getContext()->getGlobalMetaState(); 1.4063 + if (!mSentHoverEnter) { 1.4064 + dispatchMotion(when, policyFlags, mSource, 1.4065 + AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0, 1.4066 + mCurrentCookedPointerData.pointerProperties, 1.4067 + mCurrentCookedPointerData.pointerCoords, 1.4068 + mCurrentCookedPointerData.idToIndex, 1.4069 + mCurrentCookedPointerData.hoveringIdBits, -1, 1.4070 + mOrientedXPrecision, mOrientedYPrecision, mDownTime); 1.4071 + mSentHoverEnter = true; 1.4072 + } 1.4073 + 1.4074 + dispatchMotion(when, policyFlags, mSource, 1.4075 + AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0, 1.4076 + mCurrentCookedPointerData.pointerProperties, 1.4077 + mCurrentCookedPointerData.pointerCoords, 1.4078 + mCurrentCookedPointerData.idToIndex, 1.4079 + mCurrentCookedPointerData.hoveringIdBits, -1, 1.4080 + mOrientedXPrecision, mOrientedYPrecision, mDownTime); 1.4081 + } 1.4082 +} 1.4083 + 1.4084 +void TouchInputMapper::cookPointerData() { 1.4085 + uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount; 1.4086 + 1.4087 + mCurrentCookedPointerData.clear(); 1.4088 + mCurrentCookedPointerData.pointerCount = currentPointerCount; 1.4089 + mCurrentCookedPointerData.hoveringIdBits = mCurrentRawPointerData.hoveringIdBits; 1.4090 + mCurrentCookedPointerData.touchingIdBits = mCurrentRawPointerData.touchingIdBits; 1.4091 + 1.4092 + // Walk through the the active pointers and map device coordinates onto 1.4093 + // surface coordinates and adjust for display orientation. 1.4094 + for (uint32_t i = 0; i < currentPointerCount; i++) { 1.4095 + const RawPointerData::Pointer& in = mCurrentRawPointerData.pointers[i]; 1.4096 + 1.4097 + // Size 1.4098 + float touchMajor, touchMinor, toolMajor, toolMinor, size; 1.4099 + switch (mCalibration.sizeCalibration) { 1.4100 + case Calibration::SIZE_CALIBRATION_GEOMETRIC: 1.4101 + case Calibration::SIZE_CALIBRATION_DIAMETER: 1.4102 + case Calibration::SIZE_CALIBRATION_BOX: 1.4103 + case Calibration::SIZE_CALIBRATION_AREA: 1.4104 + if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) { 1.4105 + touchMajor = in.touchMajor; 1.4106 + touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor; 1.4107 + toolMajor = in.toolMajor; 1.4108 + toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor; 1.4109 + size = mRawPointerAxes.touchMinor.valid 1.4110 + ? avg(in.touchMajor, in.touchMinor) : in.touchMajor; 1.4111 + } else if (mRawPointerAxes.touchMajor.valid) { 1.4112 + toolMajor = touchMajor = in.touchMajor; 1.4113 + toolMinor = touchMinor = mRawPointerAxes.touchMinor.valid 1.4114 + ? in.touchMinor : in.touchMajor; 1.4115 + size = mRawPointerAxes.touchMinor.valid 1.4116 + ? avg(in.touchMajor, in.touchMinor) : in.touchMajor; 1.4117 + } else if (mRawPointerAxes.toolMajor.valid) { 1.4118 + touchMajor = toolMajor = in.toolMajor; 1.4119 + touchMinor = toolMinor = mRawPointerAxes.toolMinor.valid 1.4120 + ? in.toolMinor : in.toolMajor; 1.4121 + size = mRawPointerAxes.toolMinor.valid 1.4122 + ? avg(in.toolMajor, in.toolMinor) : in.toolMajor; 1.4123 + } else { 1.4124 + ALOG_ASSERT(false, "No touch or tool axes. " 1.4125 + "Size calibration should have been resolved to NONE."); 1.4126 + touchMajor = 0; 1.4127 + touchMinor = 0; 1.4128 + toolMajor = 0; 1.4129 + toolMinor = 0; 1.4130 + size = 0; 1.4131 + } 1.4132 + 1.4133 + if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) { 1.4134 + uint32_t touchingCount = mCurrentRawPointerData.touchingIdBits.count(); 1.4135 + if (touchingCount > 1) { 1.4136 + touchMajor /= touchingCount; 1.4137 + touchMinor /= touchingCount; 1.4138 + toolMajor /= touchingCount; 1.4139 + toolMinor /= touchingCount; 1.4140 + size /= touchingCount; 1.4141 + } 1.4142 + } 1.4143 + 1.4144 + if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) { 1.4145 + touchMajor *= mGeometricScale; 1.4146 + touchMinor *= mGeometricScale; 1.4147 + toolMajor *= mGeometricScale; 1.4148 + toolMinor *= mGeometricScale; 1.4149 + } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) { 1.4150 + touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0; 1.4151 + touchMinor = touchMajor; 1.4152 + toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0; 1.4153 + toolMinor = toolMajor; 1.4154 + } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) { 1.4155 + touchMinor = touchMajor; 1.4156 + toolMinor = toolMajor; 1.4157 + } 1.4158 + 1.4159 + mCalibration.applySizeScaleAndBias(&touchMajor); 1.4160 + mCalibration.applySizeScaleAndBias(&touchMinor); 1.4161 + mCalibration.applySizeScaleAndBias(&toolMajor); 1.4162 + mCalibration.applySizeScaleAndBias(&toolMinor); 1.4163 + size *= mSizeScale; 1.4164 + break; 1.4165 + default: 1.4166 + touchMajor = 0; 1.4167 + touchMinor = 0; 1.4168 + toolMajor = 0; 1.4169 + toolMinor = 0; 1.4170 + size = 0; 1.4171 + break; 1.4172 + } 1.4173 + 1.4174 + // Pressure 1.4175 + float pressure; 1.4176 + switch (mCalibration.pressureCalibration) { 1.4177 + case Calibration::PRESSURE_CALIBRATION_PHYSICAL: 1.4178 + case Calibration::PRESSURE_CALIBRATION_AMPLITUDE: 1.4179 + pressure = in.pressure * mPressureScale; 1.4180 + break; 1.4181 + default: 1.4182 + pressure = in.isHovering ? 0 : 1; 1.4183 + break; 1.4184 + } 1.4185 + 1.4186 + // Tilt and Orientation 1.4187 + float tilt; 1.4188 + float orientation; 1.4189 + if (mHaveTilt) { 1.4190 + float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale; 1.4191 + float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale; 1.4192 + orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle)); 1.4193 + tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle)); 1.4194 + } else { 1.4195 + tilt = 0; 1.4196 + 1.4197 + switch (mCalibration.orientationCalibration) { 1.4198 + case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED: 1.4199 + orientation = in.orientation * mOrientationScale; 1.4200 + break; 1.4201 + case Calibration::ORIENTATION_CALIBRATION_VECTOR: { 1.4202 + int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4); 1.4203 + int32_t c2 = signExtendNybble(in.orientation & 0x0f); 1.4204 + if (c1 != 0 || c2 != 0) { 1.4205 + orientation = atan2f(c1, c2) * 0.5f; 1.4206 + float confidence = hypotf(c1, c2); 1.4207 + float scale = 1.0f + confidence / 16.0f; 1.4208 + touchMajor *= scale; 1.4209 + touchMinor /= scale; 1.4210 + toolMajor *= scale; 1.4211 + toolMinor /= scale; 1.4212 + } else { 1.4213 + orientation = 0; 1.4214 + } 1.4215 + break; 1.4216 + } 1.4217 + default: 1.4218 + orientation = 0; 1.4219 + } 1.4220 + } 1.4221 + 1.4222 + // Distance 1.4223 + float distance; 1.4224 + switch (mCalibration.distanceCalibration) { 1.4225 + case Calibration::DISTANCE_CALIBRATION_SCALED: 1.4226 + distance = in.distance * mDistanceScale; 1.4227 + break; 1.4228 + default: 1.4229 + distance = 0; 1.4230 + } 1.4231 + 1.4232 + // Coverage 1.4233 + int32_t rawLeft, rawTop, rawRight, rawBottom; 1.4234 + switch (mCalibration.coverageCalibration) { 1.4235 + case Calibration::COVERAGE_CALIBRATION_BOX: 1.4236 + rawLeft = (in.toolMinor & 0xffff0000) >> 16; 1.4237 + rawRight = in.toolMinor & 0x0000ffff; 1.4238 + rawBottom = in.toolMajor & 0x0000ffff; 1.4239 + rawTop = (in.toolMajor & 0xffff0000) >> 16; 1.4240 + break; 1.4241 + default: 1.4242 + rawLeft = rawTop = rawRight = rawBottom = 0; 1.4243 + break; 1.4244 + } 1.4245 + 1.4246 + // X, Y, and the bounding box for coverage information 1.4247 + // Adjust coords for surface orientation. 1.4248 + float x, y, left, top, right, bottom; 1.4249 + switch (mSurfaceOrientation) { 1.4250 + case DISPLAY_ORIENTATION_90: 1.4251 + x = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; 1.4252 + y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate; 1.4253 + left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; 1.4254 + right = float(rawBottom- mRawPointerAxes.y.minValue) * mYScale + mYTranslate; 1.4255 + bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate; 1.4256 + top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate; 1.4257 + orientation -= M_PI_2; 1.4258 + if (orientation < - M_PI_2) { 1.4259 + orientation += M_PI; 1.4260 + } 1.4261 + break; 1.4262 + case DISPLAY_ORIENTATION_180: 1.4263 + x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate; 1.4264 + y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate; 1.4265 + left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate; 1.4266 + right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate; 1.4267 + bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate; 1.4268 + top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate; 1.4269 + break; 1.4270 + case DISPLAY_ORIENTATION_270: 1.4271 + x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate; 1.4272 + y = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; 1.4273 + left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate; 1.4274 + right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate; 1.4275 + bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; 1.4276 + top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; 1.4277 + orientation += M_PI_2; 1.4278 + if (orientation > M_PI_2) { 1.4279 + orientation -= M_PI; 1.4280 + } 1.4281 + break; 1.4282 + default: 1.4283 + x = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; 1.4284 + y = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; 1.4285 + left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; 1.4286 + right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; 1.4287 + bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; 1.4288 + top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate; 1.4289 + break; 1.4290 + } 1.4291 + 1.4292 + // Write output coords. 1.4293 + PointerCoords& out = mCurrentCookedPointerData.pointerCoords[i]; 1.4294 + out.clear(); 1.4295 + out.setAxisValue(AMOTION_EVENT_AXIS_X, x); 1.4296 + out.setAxisValue(AMOTION_EVENT_AXIS_Y, y); 1.4297 + out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure); 1.4298 + out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size); 1.4299 + out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor); 1.4300 + out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor); 1.4301 + out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation); 1.4302 + out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt); 1.4303 + out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance); 1.4304 + if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) { 1.4305 + out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left); 1.4306 + out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top); 1.4307 + out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right); 1.4308 + out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_4, bottom); 1.4309 + } else { 1.4310 + out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor); 1.4311 + out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor); 1.4312 + } 1.4313 + 1.4314 + // Write output properties. 1.4315 + PointerProperties& properties = mCurrentCookedPointerData.pointerProperties[i]; 1.4316 + uint32_t id = in.id; 1.4317 + properties.clear(); 1.4318 + properties.id = id; 1.4319 + properties.toolType = in.toolType; 1.4320 + 1.4321 + // Write id index. 1.4322 + mCurrentCookedPointerData.idToIndex[id] = i; 1.4323 + } 1.4324 +} 1.4325 + 1.4326 +void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags, 1.4327 + PointerUsage pointerUsage) { 1.4328 + if (pointerUsage != mPointerUsage) { 1.4329 + abortPointerUsage(when, policyFlags); 1.4330 + mPointerUsage = pointerUsage; 1.4331 + } 1.4332 + 1.4333 + switch (mPointerUsage) { 1.4334 + case POINTER_USAGE_GESTURES: 1.4335 + dispatchPointerGestures(when, policyFlags, false /*isTimeout*/); 1.4336 + break; 1.4337 + case POINTER_USAGE_STYLUS: 1.4338 + dispatchPointerStylus(when, policyFlags); 1.4339 + break; 1.4340 + case POINTER_USAGE_MOUSE: 1.4341 + dispatchPointerMouse(when, policyFlags); 1.4342 + break; 1.4343 + default: 1.4344 + break; 1.4345 + } 1.4346 +} 1.4347 + 1.4348 +void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) { 1.4349 + switch (mPointerUsage) { 1.4350 + case POINTER_USAGE_GESTURES: 1.4351 + abortPointerGestures(when, policyFlags); 1.4352 + break; 1.4353 + case POINTER_USAGE_STYLUS: 1.4354 + abortPointerStylus(when, policyFlags); 1.4355 + break; 1.4356 + case POINTER_USAGE_MOUSE: 1.4357 + abortPointerMouse(when, policyFlags); 1.4358 + break; 1.4359 + default: 1.4360 + break; 1.4361 + } 1.4362 + 1.4363 + mPointerUsage = POINTER_USAGE_NONE; 1.4364 +} 1.4365 + 1.4366 +void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, 1.4367 + bool isTimeout) { 1.4368 + // Update current gesture coordinates. 1.4369 + bool cancelPreviousGesture, finishPreviousGesture; 1.4370 + bool sendEvents = preparePointerGestures(when, 1.4371 + &cancelPreviousGesture, &finishPreviousGesture, isTimeout); 1.4372 + if (!sendEvents) { 1.4373 + return; 1.4374 + } 1.4375 + if (finishPreviousGesture) { 1.4376 + cancelPreviousGesture = false; 1.4377 + } 1.4378 + 1.4379 + // Update the pointer presentation and spots. 1.4380 + if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { 1.4381 + mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT); 1.4382 + if (finishPreviousGesture || cancelPreviousGesture) { 1.4383 + mPointerController->clearSpots(); 1.4384 + } 1.4385 + mPointerController->setSpots(mPointerGesture.currentGestureCoords, 1.4386 + mPointerGesture.currentGestureIdToIndex, 1.4387 + mPointerGesture.currentGestureIdBits); 1.4388 + } else { 1.4389 + mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER); 1.4390 + } 1.4391 + 1.4392 + // Show or hide the pointer if needed. 1.4393 + switch (mPointerGesture.currentGestureMode) { 1.4394 + case PointerGesture::NEUTRAL: 1.4395 + case PointerGesture::QUIET: 1.4396 + if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS 1.4397 + && (mPointerGesture.lastGestureMode == PointerGesture::SWIPE 1.4398 + || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)) { 1.4399 + // Remind the user of where the pointer is after finishing a gesture with spots. 1.4400 + mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL); 1.4401 + } 1.4402 + break; 1.4403 + case PointerGesture::TAP: 1.4404 + case PointerGesture::TAP_DRAG: 1.4405 + case PointerGesture::BUTTON_CLICK_OR_DRAG: 1.4406 + case PointerGesture::HOVER: 1.4407 + case PointerGesture::PRESS: 1.4408 + // Unfade the pointer when the current gesture manipulates the 1.4409 + // area directly under the pointer. 1.4410 + mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE); 1.4411 + break; 1.4412 + case PointerGesture::SWIPE: 1.4413 + case PointerGesture::FREEFORM: 1.4414 + // Fade the pointer when the current gesture manipulates a different 1.4415 + // area and there are spots to guide the user experience. 1.4416 + if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { 1.4417 + mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); 1.4418 + } else { 1.4419 + mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE); 1.4420 + } 1.4421 + break; 1.4422 + } 1.4423 + 1.4424 + // Send events! 1.4425 + int32_t metaState = getContext()->getGlobalMetaState(); 1.4426 + int32_t buttonState = mCurrentButtonState; 1.4427 + 1.4428 + // Update last coordinates of pointers that have moved so that we observe the new 1.4429 + // pointer positions at the same time as other pointers that have just gone up. 1.4430 + bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP 1.4431 + || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG 1.4432 + || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG 1.4433 + || mPointerGesture.currentGestureMode == PointerGesture::PRESS 1.4434 + || mPointerGesture.currentGestureMode == PointerGesture::SWIPE 1.4435 + || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM; 1.4436 + bool moveNeeded = false; 1.4437 + if (down && !cancelPreviousGesture && !finishPreviousGesture 1.4438 + && !mPointerGesture.lastGestureIdBits.isEmpty() 1.4439 + && !mPointerGesture.currentGestureIdBits.isEmpty()) { 1.4440 + BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value 1.4441 + & mPointerGesture.lastGestureIdBits.value); 1.4442 + moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties, 1.4443 + mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex, 1.4444 + mPointerGesture.lastGestureProperties, 1.4445 + mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex, 1.4446 + movedGestureIdBits); 1.4447 + if (buttonState != mLastButtonState) { 1.4448 + moveNeeded = true; 1.4449 + } 1.4450 + } 1.4451 + 1.4452 + // Send motion events for all pointers that went up or were canceled. 1.4453 + BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits); 1.4454 + if (!dispatchedGestureIdBits.isEmpty()) { 1.4455 + if (cancelPreviousGesture) { 1.4456 + dispatchMotion(when, policyFlags, mSource, 1.4457 + AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState, 1.4458 + AMOTION_EVENT_EDGE_FLAG_NONE, 1.4459 + mPointerGesture.lastGestureProperties, 1.4460 + mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex, 1.4461 + dispatchedGestureIdBits, -1, 1.4462 + 0, 0, mPointerGesture.downTime); 1.4463 + 1.4464 + dispatchedGestureIdBits.clear(); 1.4465 + } else { 1.4466 + BitSet32 upGestureIdBits; 1.4467 + if (finishPreviousGesture) { 1.4468 + upGestureIdBits = dispatchedGestureIdBits; 1.4469 + } else { 1.4470 + upGestureIdBits.value = dispatchedGestureIdBits.value 1.4471 + & ~mPointerGesture.currentGestureIdBits.value; 1.4472 + } 1.4473 + while (!upGestureIdBits.isEmpty()) { 1.4474 + uint32_t id = upGestureIdBits.clearFirstMarkedBit(); 1.4475 + 1.4476 + dispatchMotion(when, policyFlags, mSource, 1.4477 + AMOTION_EVENT_ACTION_POINTER_UP, 0, 1.4478 + metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, 1.4479 + mPointerGesture.lastGestureProperties, 1.4480 + mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex, 1.4481 + dispatchedGestureIdBits, id, 1.4482 + 0, 0, mPointerGesture.downTime); 1.4483 + 1.4484 + dispatchedGestureIdBits.clearBit(id); 1.4485 + } 1.4486 + } 1.4487 + } 1.4488 + 1.4489 + // Send motion events for all pointers that moved. 1.4490 + if (moveNeeded) { 1.4491 + dispatchMotion(when, policyFlags, mSource, 1.4492 + AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, 1.4493 + mPointerGesture.currentGestureProperties, 1.4494 + mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex, 1.4495 + dispatchedGestureIdBits, -1, 1.4496 + 0, 0, mPointerGesture.downTime); 1.4497 + } 1.4498 + 1.4499 + // Send motion events for all pointers that went down. 1.4500 + if (down) { 1.4501 + BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value 1.4502 + & ~dispatchedGestureIdBits.value); 1.4503 + while (!downGestureIdBits.isEmpty()) { 1.4504 + uint32_t id = downGestureIdBits.clearFirstMarkedBit(); 1.4505 + dispatchedGestureIdBits.markBit(id); 1.4506 + 1.4507 + if (dispatchedGestureIdBits.count() == 1) { 1.4508 + mPointerGesture.downTime = when; 1.4509 + } 1.4510 + 1.4511 + dispatchMotion(when, policyFlags, mSource, 1.4512 + AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0, 1.4513 + mPointerGesture.currentGestureProperties, 1.4514 + mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex, 1.4515 + dispatchedGestureIdBits, id, 1.4516 + 0, 0, mPointerGesture.downTime); 1.4517 + } 1.4518 + } 1.4519 + 1.4520 + // Send motion events for hover. 1.4521 + if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) { 1.4522 + dispatchMotion(when, policyFlags, mSource, 1.4523 + AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 1.4524 + metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, 1.4525 + mPointerGesture.currentGestureProperties, 1.4526 + mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex, 1.4527 + mPointerGesture.currentGestureIdBits, -1, 1.4528 + 0, 0, mPointerGesture.downTime); 1.4529 + } else if (dispatchedGestureIdBits.isEmpty() 1.4530 + && !mPointerGesture.lastGestureIdBits.isEmpty()) { 1.4531 + // Synthesize a hover move event after all pointers go up to indicate that 1.4532 + // the pointer is hovering again even if the user is not currently touching 1.4533 + // the touch pad. This ensures that a view will receive a fresh hover enter 1.4534 + // event after a tap. 1.4535 + float x, y; 1.4536 + mPointerController->getPosition(&x, &y); 1.4537 + 1.4538 + PointerProperties pointerProperties; 1.4539 + pointerProperties.clear(); 1.4540 + pointerProperties.id = 0; 1.4541 + pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; 1.4542 + 1.4543 + PointerCoords pointerCoords; 1.4544 + pointerCoords.clear(); 1.4545 + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x); 1.4546 + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y); 1.4547 + 1.4548 + NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, 1.4549 + AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 1.4550 + metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, 1.4551 + mViewport.displayId, 1, &pointerProperties, &pointerCoords, 1.4552 + 0, 0, mPointerGesture.downTime); 1.4553 + getListener()->notifyMotion(&args); 1.4554 + } 1.4555 + 1.4556 + // Update state. 1.4557 + mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode; 1.4558 + if (!down) { 1.4559 + mPointerGesture.lastGestureIdBits.clear(); 1.4560 + } else { 1.4561 + mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits; 1.4562 + for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) { 1.4563 + uint32_t id = idBits.clearFirstMarkedBit(); 1.4564 + uint32_t index = mPointerGesture.currentGestureIdToIndex[id]; 1.4565 + mPointerGesture.lastGestureProperties[index].copyFrom( 1.4566 + mPointerGesture.currentGestureProperties[index]); 1.4567 + mPointerGesture.lastGestureCoords[index].copyFrom( 1.4568 + mPointerGesture.currentGestureCoords[index]); 1.4569 + mPointerGesture.lastGestureIdToIndex[id] = index; 1.4570 + } 1.4571 + } 1.4572 +} 1.4573 + 1.4574 +void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) { 1.4575 + // Cancel previously dispatches pointers. 1.4576 + if (!mPointerGesture.lastGestureIdBits.isEmpty()) { 1.4577 + int32_t metaState = getContext()->getGlobalMetaState(); 1.4578 + int32_t buttonState = mCurrentButtonState; 1.4579 + dispatchMotion(when, policyFlags, mSource, 1.4580 + AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState, 1.4581 + AMOTION_EVENT_EDGE_FLAG_NONE, 1.4582 + mPointerGesture.lastGestureProperties, 1.4583 + mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex, 1.4584 + mPointerGesture.lastGestureIdBits, -1, 1.4585 + 0, 0, mPointerGesture.downTime); 1.4586 + } 1.4587 + 1.4588 + // Reset the current pointer gesture. 1.4589 + mPointerGesture.reset(); 1.4590 + mPointerVelocityControl.reset(); 1.4591 + 1.4592 + // Remove any current spots. 1.4593 + if (mPointerController != NULL) { 1.4594 + mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); 1.4595 + mPointerController->clearSpots(); 1.4596 + } 1.4597 +} 1.4598 + 1.4599 +bool TouchInputMapper::preparePointerGestures(nsecs_t when, 1.4600 + bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) { 1.4601 + *outCancelPreviousGesture = false; 1.4602 + *outFinishPreviousGesture = false; 1.4603 + 1.4604 + // Handle TAP timeout. 1.4605 + if (isTimeout) { 1.4606 +#if DEBUG_GESTURES 1.4607 + ALOGD("Gestures: Processing timeout"); 1.4608 +#endif 1.4609 + 1.4610 + if (mPointerGesture.lastGestureMode == PointerGesture::TAP) { 1.4611 + if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) { 1.4612 + // The tap/drag timeout has not yet expired. 1.4613 + getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime 1.4614 + + mConfig.pointerGestureTapDragInterval); 1.4615 + } else { 1.4616 + // The tap is finished. 1.4617 +#if DEBUG_GESTURES 1.4618 + ALOGD("Gestures: TAP finished"); 1.4619 +#endif 1.4620 + *outFinishPreviousGesture = true; 1.4621 + 1.4622 + mPointerGesture.activeGestureId = -1; 1.4623 + mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL; 1.4624 + mPointerGesture.currentGestureIdBits.clear(); 1.4625 + 1.4626 + mPointerVelocityControl.reset(); 1.4627 + return true; 1.4628 + } 1.4629 + } 1.4630 + 1.4631 + // We did not handle this timeout. 1.4632 + return false; 1.4633 + } 1.4634 + 1.4635 + const uint32_t currentFingerCount = mCurrentFingerIdBits.count(); 1.4636 + const uint32_t lastFingerCount = mLastFingerIdBits.count(); 1.4637 + 1.4638 + // Update the velocity tracker. 1.4639 + { 1.4640 + VelocityTracker::Position positions[MAX_POINTERS]; 1.4641 + uint32_t count = 0; 1.4642 + for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); count++) { 1.4643 + uint32_t id = idBits.clearFirstMarkedBit(); 1.4644 + const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id); 1.4645 + positions[count].x = pointer.x * mPointerXMovementScale; 1.4646 + positions[count].y = pointer.y * mPointerYMovementScale; 1.4647 + } 1.4648 + mPointerGesture.velocityTracker.addMovement(when, 1.4649 + mCurrentFingerIdBits, positions); 1.4650 + } 1.4651 + 1.4652 + // Pick a new active touch id if needed. 1.4653 + // Choose an arbitrary pointer that just went down, if there is one. 1.4654 + // Otherwise choose an arbitrary remaining pointer. 1.4655 + // This guarantees we always have an active touch id when there is at least one pointer. 1.4656 + // We keep the same active touch id for as long as possible. 1.4657 + bool activeTouchChanged = false; 1.4658 + int32_t lastActiveTouchId = mPointerGesture.activeTouchId; 1.4659 + int32_t activeTouchId = lastActiveTouchId; 1.4660 + if (activeTouchId < 0) { 1.4661 + if (!mCurrentFingerIdBits.isEmpty()) { 1.4662 + activeTouchChanged = true; 1.4663 + activeTouchId = mPointerGesture.activeTouchId = 1.4664 + mCurrentFingerIdBits.firstMarkedBit(); 1.4665 + mPointerGesture.firstTouchTime = when; 1.4666 + } 1.4667 + } else if (!mCurrentFingerIdBits.hasBit(activeTouchId)) { 1.4668 + activeTouchChanged = true; 1.4669 + if (!mCurrentFingerIdBits.isEmpty()) { 1.4670 + activeTouchId = mPointerGesture.activeTouchId = 1.4671 + mCurrentFingerIdBits.firstMarkedBit(); 1.4672 + } else { 1.4673 + activeTouchId = mPointerGesture.activeTouchId = -1; 1.4674 + } 1.4675 + } 1.4676 + 1.4677 + // Determine whether we are in quiet time. 1.4678 + bool isQuietTime = false; 1.4679 + if (activeTouchId < 0) { 1.4680 + mPointerGesture.resetQuietTime(); 1.4681 + } else { 1.4682 + isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval; 1.4683 + if (!isQuietTime) { 1.4684 + if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS 1.4685 + || mPointerGesture.lastGestureMode == PointerGesture::SWIPE 1.4686 + || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM) 1.4687 + && currentFingerCount < 2) { 1.4688 + // Enter quiet time when exiting swipe or freeform state. 1.4689 + // This is to prevent accidentally entering the hover state and flinging the 1.4690 + // pointer when finishing a swipe and there is still one pointer left onscreen. 1.4691 + isQuietTime = true; 1.4692 + } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG 1.4693 + && currentFingerCount >= 2 1.4694 + && !isPointerDown(mCurrentButtonState)) { 1.4695 + // Enter quiet time when releasing the button and there are still two or more 1.4696 + // fingers down. This may indicate that one finger was used to press the button 1.4697 + // but it has not gone up yet. 1.4698 + isQuietTime = true; 1.4699 + } 1.4700 + if (isQuietTime) { 1.4701 + mPointerGesture.quietTime = when; 1.4702 + } 1.4703 + } 1.4704 + } 1.4705 + 1.4706 + // Switch states based on button and pointer state. 1.4707 + if (isQuietTime) { 1.4708 + // Case 1: Quiet time. (QUIET) 1.4709 +#if DEBUG_GESTURES 1.4710 + ALOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime 1.4711 + + mConfig.pointerGestureQuietInterval - when) * 0.000001f); 1.4712 +#endif 1.4713 + if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) { 1.4714 + *outFinishPreviousGesture = true; 1.4715 + } 1.4716 + 1.4717 + mPointerGesture.activeGestureId = -1; 1.4718 + mPointerGesture.currentGestureMode = PointerGesture::QUIET; 1.4719 + mPointerGesture.currentGestureIdBits.clear(); 1.4720 + 1.4721 + mPointerVelocityControl.reset(); 1.4722 + } else if (isPointerDown(mCurrentButtonState)) { 1.4723 + // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG) 1.4724 + // The pointer follows the active touch point. 1.4725 + // Emit DOWN, MOVE, UP events at the pointer location. 1.4726 + // 1.4727 + // Only the active touch matters; other fingers are ignored. This policy helps 1.4728 + // to handle the case where the user places a second finger on the touch pad 1.4729 + // to apply the necessary force to depress an integrated button below the surface. 1.4730 + // We don't want the second finger to be delivered to applications. 1.4731 + // 1.4732 + // For this to work well, we need to make sure to track the pointer that is really 1.4733 + // active. If the user first puts one finger down to click then adds another 1.4734 + // finger to drag then the active pointer should switch to the finger that is 1.4735 + // being dragged. 1.4736 +#if DEBUG_GESTURES 1.4737 + ALOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, " 1.4738 + "currentFingerCount=%d", activeTouchId, currentFingerCount); 1.4739 +#endif 1.4740 + // Reset state when just starting. 1.4741 + if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) { 1.4742 + *outFinishPreviousGesture = true; 1.4743 + mPointerGesture.activeGestureId = 0; 1.4744 + } 1.4745 + 1.4746 + // Switch pointers if needed. 1.4747 + // Find the fastest pointer and follow it. 1.4748 + if (activeTouchId >= 0 && currentFingerCount > 1) { 1.4749 + int32_t bestId = -1; 1.4750 + float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed; 1.4751 + for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); ) { 1.4752 + uint32_t id = idBits.clearFirstMarkedBit(); 1.4753 + float vx, vy; 1.4754 + if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) { 1.4755 + float speed = hypotf(vx, vy); 1.4756 + if (speed > bestSpeed) { 1.4757 + bestId = id; 1.4758 + bestSpeed = speed; 1.4759 + } 1.4760 + } 1.4761 + } 1.4762 + if (bestId >= 0 && bestId != activeTouchId) { 1.4763 + mPointerGesture.activeTouchId = activeTouchId = bestId; 1.4764 + activeTouchChanged = true; 1.4765 +#if DEBUG_GESTURES 1.4766 + ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, " 1.4767 + "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed); 1.4768 +#endif 1.4769 + } 1.4770 + } 1.4771 + 1.4772 + if (activeTouchId >= 0 && mLastFingerIdBits.hasBit(activeTouchId)) { 1.4773 + const RawPointerData::Pointer& currentPointer = 1.4774 + mCurrentRawPointerData.pointerForId(activeTouchId); 1.4775 + const RawPointerData::Pointer& lastPointer = 1.4776 + mLastRawPointerData.pointerForId(activeTouchId); 1.4777 + float deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale; 1.4778 + float deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale; 1.4779 + 1.4780 + rotateDelta(mSurfaceOrientation, &deltaX, &deltaY); 1.4781 + mPointerVelocityControl.move(when, &deltaX, &deltaY); 1.4782 + 1.4783 + // Move the pointer using a relative motion. 1.4784 + // When using spots, the click will occur at the position of the anchor 1.4785 + // spot and all other spots will move there. 1.4786 + mPointerController->move(deltaX, deltaY); 1.4787 + } else { 1.4788 + mPointerVelocityControl.reset(); 1.4789 + } 1.4790 + 1.4791 + float x, y; 1.4792 + mPointerController->getPosition(&x, &y); 1.4793 + 1.4794 + mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG; 1.4795 + mPointerGesture.currentGestureIdBits.clear(); 1.4796 + mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId); 1.4797 + mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0; 1.4798 + mPointerGesture.currentGestureProperties[0].clear(); 1.4799 + mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId; 1.4800 + mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; 1.4801 + mPointerGesture.currentGestureCoords[0].clear(); 1.4802 + mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x); 1.4803 + mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y); 1.4804 + mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f); 1.4805 + } else if (currentFingerCount == 0) { 1.4806 + // Case 3. No fingers down and button is not pressed. (NEUTRAL) 1.4807 + if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) { 1.4808 + *outFinishPreviousGesture = true; 1.4809 + } 1.4810 + 1.4811 + // Watch for taps coming out of HOVER or TAP_DRAG mode. 1.4812 + // Checking for taps after TAP_DRAG allows us to detect double-taps. 1.4813 + bool tapped = false; 1.4814 + if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER 1.4815 + || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) 1.4816 + && lastFingerCount == 1) { 1.4817 + if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) { 1.4818 + float x, y; 1.4819 + mPointerController->getPosition(&x, &y); 1.4820 + if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop 1.4821 + && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) { 1.4822 +#if DEBUG_GESTURES 1.4823 + ALOGD("Gestures: TAP"); 1.4824 +#endif 1.4825 + 1.4826 + mPointerGesture.tapUpTime = when; 1.4827 + getContext()->requestTimeoutAtTime(when 1.4828 + + mConfig.pointerGestureTapDragInterval); 1.4829 + 1.4830 + mPointerGesture.activeGestureId = 0; 1.4831 + mPointerGesture.currentGestureMode = PointerGesture::TAP; 1.4832 + mPointerGesture.currentGestureIdBits.clear(); 1.4833 + mPointerGesture.currentGestureIdBits.markBit( 1.4834 + mPointerGesture.activeGestureId); 1.4835 + mPointerGesture.currentGestureIdToIndex[ 1.4836 + mPointerGesture.activeGestureId] = 0; 1.4837 + mPointerGesture.currentGestureProperties[0].clear(); 1.4838 + mPointerGesture.currentGestureProperties[0].id = 1.4839 + mPointerGesture.activeGestureId; 1.4840 + mPointerGesture.currentGestureProperties[0].toolType = 1.4841 + AMOTION_EVENT_TOOL_TYPE_FINGER; 1.4842 + mPointerGesture.currentGestureCoords[0].clear(); 1.4843 + mPointerGesture.currentGestureCoords[0].setAxisValue( 1.4844 + AMOTION_EVENT_AXIS_X, mPointerGesture.tapX); 1.4845 + mPointerGesture.currentGestureCoords[0].setAxisValue( 1.4846 + AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY); 1.4847 + mPointerGesture.currentGestureCoords[0].setAxisValue( 1.4848 + AMOTION_EVENT_AXIS_PRESSURE, 1.0f); 1.4849 + 1.4850 + tapped = true; 1.4851 + } else { 1.4852 +#if DEBUG_GESTURES 1.4853 + ALOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f", 1.4854 + x - mPointerGesture.tapX, 1.4855 + y - mPointerGesture.tapY); 1.4856 +#endif 1.4857 + } 1.4858 + } else { 1.4859 +#if DEBUG_GESTURES 1.4860 + ALOGD("Gestures: Not a TAP, %0.3fms since down", 1.4861 + (when - mPointerGesture.tapDownTime) * 0.000001f); 1.4862 +#endif 1.4863 + } 1.4864 + } 1.4865 + 1.4866 + mPointerVelocityControl.reset(); 1.4867 + 1.4868 + if (!tapped) { 1.4869 +#if DEBUG_GESTURES 1.4870 + ALOGD("Gestures: NEUTRAL"); 1.4871 +#endif 1.4872 + mPointerGesture.activeGestureId = -1; 1.4873 + mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL; 1.4874 + mPointerGesture.currentGestureIdBits.clear(); 1.4875 + } 1.4876 + } else if (currentFingerCount == 1) { 1.4877 + // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG) 1.4878 + // The pointer follows the active touch point. 1.4879 + // When in HOVER, emit HOVER_MOVE events at the pointer location. 1.4880 + // When in TAP_DRAG, emit MOVE events at the pointer location. 1.4881 + ALOG_ASSERT(activeTouchId >= 0); 1.4882 + 1.4883 + mPointerGesture.currentGestureMode = PointerGesture::HOVER; 1.4884 + if (mPointerGesture.lastGestureMode == PointerGesture::TAP) { 1.4885 + if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) { 1.4886 + float x, y; 1.4887 + mPointerController->getPosition(&x, &y); 1.4888 + if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop 1.4889 + && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) { 1.4890 + mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG; 1.4891 + } else { 1.4892 +#if DEBUG_GESTURES 1.4893 + ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f", 1.4894 + x - mPointerGesture.tapX, 1.4895 + y - mPointerGesture.tapY); 1.4896 +#endif 1.4897 + } 1.4898 + } else { 1.4899 +#if DEBUG_GESTURES 1.4900 + ALOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up", 1.4901 + (when - mPointerGesture.tapUpTime) * 0.000001f); 1.4902 +#endif 1.4903 + } 1.4904 + } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) { 1.4905 + mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG; 1.4906 + } 1.4907 + 1.4908 + if (mLastFingerIdBits.hasBit(activeTouchId)) { 1.4909 + const RawPointerData::Pointer& currentPointer = 1.4910 + mCurrentRawPointerData.pointerForId(activeTouchId); 1.4911 + const RawPointerData::Pointer& lastPointer = 1.4912 + mLastRawPointerData.pointerForId(activeTouchId); 1.4913 + float deltaX = (currentPointer.x - lastPointer.x) 1.4914 + * mPointerXMovementScale; 1.4915 + float deltaY = (currentPointer.y - lastPointer.y) 1.4916 + * mPointerYMovementScale; 1.4917 + 1.4918 + rotateDelta(mSurfaceOrientation, &deltaX, &deltaY); 1.4919 + mPointerVelocityControl.move(when, &deltaX, &deltaY); 1.4920 + 1.4921 + // Move the pointer using a relative motion. 1.4922 + // When using spots, the hover or drag will occur at the position of the anchor spot. 1.4923 + mPointerController->move(deltaX, deltaY); 1.4924 + } else { 1.4925 + mPointerVelocityControl.reset(); 1.4926 + } 1.4927 + 1.4928 + bool down; 1.4929 + if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) { 1.4930 +#if DEBUG_GESTURES 1.4931 + ALOGD("Gestures: TAP_DRAG"); 1.4932 +#endif 1.4933 + down = true; 1.4934 + } else { 1.4935 +#if DEBUG_GESTURES 1.4936 + ALOGD("Gestures: HOVER"); 1.4937 +#endif 1.4938 + if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) { 1.4939 + *outFinishPreviousGesture = true; 1.4940 + } 1.4941 + mPointerGesture.activeGestureId = 0; 1.4942 + down = false; 1.4943 + } 1.4944 + 1.4945 + float x, y; 1.4946 + mPointerController->getPosition(&x, &y); 1.4947 + 1.4948 + mPointerGesture.currentGestureIdBits.clear(); 1.4949 + mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId); 1.4950 + mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0; 1.4951 + mPointerGesture.currentGestureProperties[0].clear(); 1.4952 + mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId; 1.4953 + mPointerGesture.currentGestureProperties[0].toolType = 1.4954 + AMOTION_EVENT_TOOL_TYPE_FINGER; 1.4955 + mPointerGesture.currentGestureCoords[0].clear(); 1.4956 + mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x); 1.4957 + mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y); 1.4958 + mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.4959 + down ? 1.0f : 0.0f); 1.4960 + 1.4961 + if (lastFingerCount == 0 && currentFingerCount != 0) { 1.4962 + mPointerGesture.resetTap(); 1.4963 + mPointerGesture.tapDownTime = when; 1.4964 + mPointerGesture.tapX = x; 1.4965 + mPointerGesture.tapY = y; 1.4966 + } 1.4967 + } else { 1.4968 + // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM) 1.4969 + // We need to provide feedback for each finger that goes down so we cannot wait 1.4970 + // for the fingers to move before deciding what to do. 1.4971 + // 1.4972 + // The ambiguous case is deciding what to do when there are two fingers down but they 1.4973 + // have not moved enough to determine whether they are part of a drag or part of a 1.4974 + // freeform gesture, or just a press or long-press at the pointer location. 1.4975 + // 1.4976 + // When there are two fingers we start with the PRESS hypothesis and we generate a 1.4977 + // down at the pointer location. 1.4978 + // 1.4979 + // When the two fingers move enough or when additional fingers are added, we make 1.4980 + // a decision to transition into SWIPE or FREEFORM mode accordingly. 1.4981 + ALOG_ASSERT(activeTouchId >= 0); 1.4982 + 1.4983 + bool settled = when >= mPointerGesture.firstTouchTime 1.4984 + + mConfig.pointerGestureMultitouchSettleInterval; 1.4985 + if (mPointerGesture.lastGestureMode != PointerGesture::PRESS 1.4986 + && mPointerGesture.lastGestureMode != PointerGesture::SWIPE 1.4987 + && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) { 1.4988 + *outFinishPreviousGesture = true; 1.4989 + } else if (!settled && currentFingerCount > lastFingerCount) { 1.4990 + // Additional pointers have gone down but not yet settled. 1.4991 + // Reset the gesture. 1.4992 +#if DEBUG_GESTURES 1.4993 + ALOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, " 1.4994 + "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime 1.4995 + + mConfig.pointerGestureMultitouchSettleInterval - when) 1.4996 + * 0.000001f); 1.4997 +#endif 1.4998 + *outCancelPreviousGesture = true; 1.4999 + } else { 1.5000 + // Continue previous gesture. 1.5001 + mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode; 1.5002 + } 1.5003 + 1.5004 + if (*outFinishPreviousGesture || *outCancelPreviousGesture) { 1.5005 + mPointerGesture.currentGestureMode = PointerGesture::PRESS; 1.5006 + mPointerGesture.activeGestureId = 0; 1.5007 + mPointerGesture.referenceIdBits.clear(); 1.5008 + mPointerVelocityControl.reset(); 1.5009 + 1.5010 + // Use the centroid and pointer location as the reference points for the gesture. 1.5011 +#if DEBUG_GESTURES 1.5012 + ALOGD("Gestures: Using centroid as reference for MULTITOUCH, " 1.5013 + "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime 1.5014 + + mConfig.pointerGestureMultitouchSettleInterval - when) 1.5015 + * 0.000001f); 1.5016 +#endif 1.5017 + mCurrentRawPointerData.getCentroidOfTouchingPointers( 1.5018 + &mPointerGesture.referenceTouchX, 1.5019 + &mPointerGesture.referenceTouchY); 1.5020 + mPointerController->getPosition(&mPointerGesture.referenceGestureX, 1.5021 + &mPointerGesture.referenceGestureY); 1.5022 + } 1.5023 + 1.5024 + // Clear the reference deltas for fingers not yet included in the reference calculation. 1.5025 + for (BitSet32 idBits(mCurrentFingerIdBits.value 1.5026 + & ~mPointerGesture.referenceIdBits.value); !idBits.isEmpty(); ) { 1.5027 + uint32_t id = idBits.clearFirstMarkedBit(); 1.5028 + mPointerGesture.referenceDeltas[id].dx = 0; 1.5029 + mPointerGesture.referenceDeltas[id].dy = 0; 1.5030 + } 1.5031 + mPointerGesture.referenceIdBits = mCurrentFingerIdBits; 1.5032 + 1.5033 + // Add delta for all fingers and calculate a common movement delta. 1.5034 + float commonDeltaX = 0, commonDeltaY = 0; 1.5035 + BitSet32 commonIdBits(mLastFingerIdBits.value 1.5036 + & mCurrentFingerIdBits.value); 1.5037 + for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) { 1.5038 + bool first = (idBits == commonIdBits); 1.5039 + uint32_t id = idBits.clearFirstMarkedBit(); 1.5040 + const RawPointerData::Pointer& cpd = mCurrentRawPointerData.pointerForId(id); 1.5041 + const RawPointerData::Pointer& lpd = mLastRawPointerData.pointerForId(id); 1.5042 + PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; 1.5043 + delta.dx += cpd.x - lpd.x; 1.5044 + delta.dy += cpd.y - lpd.y; 1.5045 + 1.5046 + if (first) { 1.5047 + commonDeltaX = delta.dx; 1.5048 + commonDeltaY = delta.dy; 1.5049 + } else { 1.5050 + commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx); 1.5051 + commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy); 1.5052 + } 1.5053 + } 1.5054 + 1.5055 + // Consider transitions from PRESS to SWIPE or MULTITOUCH. 1.5056 + if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) { 1.5057 + float dist[MAX_POINTER_ID + 1]; 1.5058 + int32_t distOverThreshold = 0; 1.5059 + for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) { 1.5060 + uint32_t id = idBits.clearFirstMarkedBit(); 1.5061 + PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; 1.5062 + dist[id] = hypotf(delta.dx * mPointerXZoomScale, 1.5063 + delta.dy * mPointerYZoomScale); 1.5064 + if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) { 1.5065 + distOverThreshold += 1; 1.5066 + } 1.5067 + } 1.5068 + 1.5069 + // Only transition when at least two pointers have moved further than 1.5070 + // the minimum distance threshold. 1.5071 + if (distOverThreshold >= 2) { 1.5072 + if (currentFingerCount > 2) { 1.5073 + // There are more than two pointers, switch to FREEFORM. 1.5074 +#if DEBUG_GESTURES 1.5075 + ALOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2", 1.5076 + currentFingerCount); 1.5077 +#endif 1.5078 + *outCancelPreviousGesture = true; 1.5079 + mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; 1.5080 + } else { 1.5081 + // There are exactly two pointers. 1.5082 + BitSet32 idBits(mCurrentFingerIdBits); 1.5083 + uint32_t id1 = idBits.clearFirstMarkedBit(); 1.5084 + uint32_t id2 = idBits.firstMarkedBit(); 1.5085 + const RawPointerData::Pointer& p1 = mCurrentRawPointerData.pointerForId(id1); 1.5086 + const RawPointerData::Pointer& p2 = mCurrentRawPointerData.pointerForId(id2); 1.5087 + float mutualDistance = distance(p1.x, p1.y, p2.x, p2.y); 1.5088 + if (mutualDistance > mPointerGestureMaxSwipeWidth) { 1.5089 + // There are two pointers but they are too far apart for a SWIPE, 1.5090 + // switch to FREEFORM. 1.5091 +#if DEBUG_GESTURES 1.5092 + ALOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f", 1.5093 + mutualDistance, mPointerGestureMaxSwipeWidth); 1.5094 +#endif 1.5095 + *outCancelPreviousGesture = true; 1.5096 + mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; 1.5097 + } else { 1.5098 + // There are two pointers. Wait for both pointers to start moving 1.5099 + // before deciding whether this is a SWIPE or FREEFORM gesture. 1.5100 + float dist1 = dist[id1]; 1.5101 + float dist2 = dist[id2]; 1.5102 + if (dist1 >= mConfig.pointerGestureMultitouchMinDistance 1.5103 + && dist2 >= mConfig.pointerGestureMultitouchMinDistance) { 1.5104 + // Calculate the dot product of the displacement vectors. 1.5105 + // When the vectors are oriented in approximately the same direction, 1.5106 + // the angle betweeen them is near zero and the cosine of the angle 1.5107 + // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2). 1.5108 + PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1]; 1.5109 + PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2]; 1.5110 + float dx1 = delta1.dx * mPointerXZoomScale; 1.5111 + float dy1 = delta1.dy * mPointerYZoomScale; 1.5112 + float dx2 = delta2.dx * mPointerXZoomScale; 1.5113 + float dy2 = delta2.dy * mPointerYZoomScale; 1.5114 + float dot = dx1 * dx2 + dy1 * dy2; 1.5115 + float cosine = dot / (dist1 * dist2); // denominator always > 0 1.5116 + if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) { 1.5117 + // Pointers are moving in the same direction. Switch to SWIPE. 1.5118 +#if DEBUG_GESTURES 1.5119 + ALOGD("Gestures: PRESS transitioned to SWIPE, " 1.5120 + "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, " 1.5121 + "cosine %0.3f >= %0.3f", 1.5122 + dist1, mConfig.pointerGestureMultitouchMinDistance, 1.5123 + dist2, mConfig.pointerGestureMultitouchMinDistance, 1.5124 + cosine, mConfig.pointerGestureSwipeTransitionAngleCosine); 1.5125 +#endif 1.5126 + mPointerGesture.currentGestureMode = PointerGesture::SWIPE; 1.5127 + } else { 1.5128 + // Pointers are moving in different directions. Switch to FREEFORM. 1.5129 +#if DEBUG_GESTURES 1.5130 + ALOGD("Gestures: PRESS transitioned to FREEFORM, " 1.5131 + "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, " 1.5132 + "cosine %0.3f < %0.3f", 1.5133 + dist1, mConfig.pointerGestureMultitouchMinDistance, 1.5134 + dist2, mConfig.pointerGestureMultitouchMinDistance, 1.5135 + cosine, mConfig.pointerGestureSwipeTransitionAngleCosine); 1.5136 +#endif 1.5137 + *outCancelPreviousGesture = true; 1.5138 + mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; 1.5139 + } 1.5140 + } 1.5141 + } 1.5142 + } 1.5143 + } 1.5144 + } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) { 1.5145 + // Switch from SWIPE to FREEFORM if additional pointers go down. 1.5146 + // Cancel previous gesture. 1.5147 + if (currentFingerCount > 2) { 1.5148 +#if DEBUG_GESTURES 1.5149 + ALOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2", 1.5150 + currentFingerCount); 1.5151 +#endif 1.5152 + *outCancelPreviousGesture = true; 1.5153 + mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; 1.5154 + } 1.5155 + } 1.5156 + 1.5157 + // Move the reference points based on the overall group motion of the fingers 1.5158 + // except in PRESS mode while waiting for a transition to occur. 1.5159 + if (mPointerGesture.currentGestureMode != PointerGesture::PRESS 1.5160 + && (commonDeltaX || commonDeltaY)) { 1.5161 + for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) { 1.5162 + uint32_t id = idBits.clearFirstMarkedBit(); 1.5163 + PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; 1.5164 + delta.dx = 0; 1.5165 + delta.dy = 0; 1.5166 + } 1.5167 + 1.5168 + mPointerGesture.referenceTouchX += commonDeltaX; 1.5169 + mPointerGesture.referenceTouchY += commonDeltaY; 1.5170 + 1.5171 + commonDeltaX *= mPointerXMovementScale; 1.5172 + commonDeltaY *= mPointerYMovementScale; 1.5173 + 1.5174 + rotateDelta(mSurfaceOrientation, &commonDeltaX, &commonDeltaY); 1.5175 + mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY); 1.5176 + 1.5177 + mPointerGesture.referenceGestureX += commonDeltaX; 1.5178 + mPointerGesture.referenceGestureY += commonDeltaY; 1.5179 + } 1.5180 + 1.5181 + // Report gestures. 1.5182 + if (mPointerGesture.currentGestureMode == PointerGesture::PRESS 1.5183 + || mPointerGesture.currentGestureMode == PointerGesture::SWIPE) { 1.5184 + // PRESS or SWIPE mode. 1.5185 +#if DEBUG_GESTURES 1.5186 + ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d," 1.5187 + "activeGestureId=%d, currentTouchPointerCount=%d", 1.5188 + activeTouchId, mPointerGesture.activeGestureId, currentFingerCount); 1.5189 +#endif 1.5190 + ALOG_ASSERT(mPointerGesture.activeGestureId >= 0); 1.5191 + 1.5192 + mPointerGesture.currentGestureIdBits.clear(); 1.5193 + mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId); 1.5194 + mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0; 1.5195 + mPointerGesture.currentGestureProperties[0].clear(); 1.5196 + mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId; 1.5197 + mPointerGesture.currentGestureProperties[0].toolType = 1.5198 + AMOTION_EVENT_TOOL_TYPE_FINGER; 1.5199 + mPointerGesture.currentGestureCoords[0].clear(); 1.5200 + mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 1.5201 + mPointerGesture.referenceGestureX); 1.5202 + mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 1.5203 + mPointerGesture.referenceGestureY); 1.5204 + mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f); 1.5205 + } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) { 1.5206 + // FREEFORM mode. 1.5207 +#if DEBUG_GESTURES 1.5208 + ALOGD("Gestures: FREEFORM activeTouchId=%d," 1.5209 + "activeGestureId=%d, currentTouchPointerCount=%d", 1.5210 + activeTouchId, mPointerGesture.activeGestureId, currentFingerCount); 1.5211 +#endif 1.5212 + ALOG_ASSERT(mPointerGesture.activeGestureId >= 0); 1.5213 + 1.5214 + mPointerGesture.currentGestureIdBits.clear(); 1.5215 + 1.5216 + BitSet32 mappedTouchIdBits; 1.5217 + BitSet32 usedGestureIdBits; 1.5218 + if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) { 1.5219 + // Initially, assign the active gesture id to the active touch point 1.5220 + // if there is one. No other touch id bits are mapped yet. 1.5221 + if (!*outCancelPreviousGesture) { 1.5222 + mappedTouchIdBits.markBit(activeTouchId); 1.5223 + usedGestureIdBits.markBit(mPointerGesture.activeGestureId); 1.5224 + mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] = 1.5225 + mPointerGesture.activeGestureId; 1.5226 + } else { 1.5227 + mPointerGesture.activeGestureId = -1; 1.5228 + } 1.5229 + } else { 1.5230 + // Otherwise, assume we mapped all touches from the previous frame. 1.5231 + // Reuse all mappings that are still applicable. 1.5232 + mappedTouchIdBits.value = mLastFingerIdBits.value 1.5233 + & mCurrentFingerIdBits.value; 1.5234 + usedGestureIdBits = mPointerGesture.lastGestureIdBits; 1.5235 + 1.5236 + // Check whether we need to choose a new active gesture id because the 1.5237 + // current went went up. 1.5238 + for (BitSet32 upTouchIdBits(mLastFingerIdBits.value 1.5239 + & ~mCurrentFingerIdBits.value); 1.5240 + !upTouchIdBits.isEmpty(); ) { 1.5241 + uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit(); 1.5242 + uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId]; 1.5243 + if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) { 1.5244 + mPointerGesture.activeGestureId = -1; 1.5245 + break; 1.5246 + } 1.5247 + } 1.5248 + } 1.5249 + 1.5250 +#if DEBUG_GESTURES 1.5251 + ALOGD("Gestures: FREEFORM follow up " 1.5252 + "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, " 1.5253 + "activeGestureId=%d", 1.5254 + mappedTouchIdBits.value, usedGestureIdBits.value, 1.5255 + mPointerGesture.activeGestureId); 1.5256 +#endif 1.5257 + 1.5258 + BitSet32 idBits(mCurrentFingerIdBits); 1.5259 + for (uint32_t i = 0; i < currentFingerCount; i++) { 1.5260 + uint32_t touchId = idBits.clearFirstMarkedBit(); 1.5261 + uint32_t gestureId; 1.5262 + if (!mappedTouchIdBits.hasBit(touchId)) { 1.5263 + gestureId = usedGestureIdBits.markFirstUnmarkedBit(); 1.5264 + mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId; 1.5265 +#if DEBUG_GESTURES 1.5266 + ALOGD("Gestures: FREEFORM " 1.5267 + "new mapping for touch id %d -> gesture id %d", 1.5268 + touchId, gestureId); 1.5269 +#endif 1.5270 + } else { 1.5271 + gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId]; 1.5272 +#if DEBUG_GESTURES 1.5273 + ALOGD("Gestures: FREEFORM " 1.5274 + "existing mapping for touch id %d -> gesture id %d", 1.5275 + touchId, gestureId); 1.5276 +#endif 1.5277 + } 1.5278 + mPointerGesture.currentGestureIdBits.markBit(gestureId); 1.5279 + mPointerGesture.currentGestureIdToIndex[gestureId] = i; 1.5280 + 1.5281 + const RawPointerData::Pointer& pointer = 1.5282 + mCurrentRawPointerData.pointerForId(touchId); 1.5283 + float deltaX = (pointer.x - mPointerGesture.referenceTouchX) 1.5284 + * mPointerXZoomScale; 1.5285 + float deltaY = (pointer.y - mPointerGesture.referenceTouchY) 1.5286 + * mPointerYZoomScale; 1.5287 + rotateDelta(mSurfaceOrientation, &deltaX, &deltaY); 1.5288 + 1.5289 + mPointerGesture.currentGestureProperties[i].clear(); 1.5290 + mPointerGesture.currentGestureProperties[i].id = gestureId; 1.5291 + mPointerGesture.currentGestureProperties[i].toolType = 1.5292 + AMOTION_EVENT_TOOL_TYPE_FINGER; 1.5293 + mPointerGesture.currentGestureCoords[i].clear(); 1.5294 + mPointerGesture.currentGestureCoords[i].setAxisValue( 1.5295 + AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX); 1.5296 + mPointerGesture.currentGestureCoords[i].setAxisValue( 1.5297 + AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY + deltaY); 1.5298 + mPointerGesture.currentGestureCoords[i].setAxisValue( 1.5299 + AMOTION_EVENT_AXIS_PRESSURE, 1.0f); 1.5300 + } 1.5301 + 1.5302 + if (mPointerGesture.activeGestureId < 0) { 1.5303 + mPointerGesture.activeGestureId = 1.5304 + mPointerGesture.currentGestureIdBits.firstMarkedBit(); 1.5305 +#if DEBUG_GESTURES 1.5306 + ALOGD("Gestures: FREEFORM new " 1.5307 + "activeGestureId=%d", mPointerGesture.activeGestureId); 1.5308 +#endif 1.5309 + } 1.5310 + } 1.5311 + } 1.5312 + 1.5313 + mPointerController->setButtonState(mCurrentButtonState); 1.5314 + 1.5315 +#if DEBUG_GESTURES 1.5316 + ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, " 1.5317 + "currentGestureMode=%d, currentGestureIdBits=0x%08x, " 1.5318 + "lastGestureMode=%d, lastGestureIdBits=0x%08x", 1.5319 + toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture), 1.5320 + mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value, 1.5321 + mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value); 1.5322 + for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) { 1.5323 + uint32_t id = idBits.clearFirstMarkedBit(); 1.5324 + uint32_t index = mPointerGesture.currentGestureIdToIndex[id]; 1.5325 + const PointerProperties& properties = mPointerGesture.currentGestureProperties[index]; 1.5326 + const PointerCoords& coords = mPointerGesture.currentGestureCoords[index]; 1.5327 + ALOGD(" currentGesture[%d]: index=%d, toolType=%d, " 1.5328 + "x=%0.3f, y=%0.3f, pressure=%0.3f", 1.5329 + id, index, properties.toolType, 1.5330 + coords.getAxisValue(AMOTION_EVENT_AXIS_X), 1.5331 + coords.getAxisValue(AMOTION_EVENT_AXIS_Y), 1.5332 + coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE)); 1.5333 + } 1.5334 + for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) { 1.5335 + uint32_t id = idBits.clearFirstMarkedBit(); 1.5336 + uint32_t index = mPointerGesture.lastGestureIdToIndex[id]; 1.5337 + const PointerProperties& properties = mPointerGesture.lastGestureProperties[index]; 1.5338 + const PointerCoords& coords = mPointerGesture.lastGestureCoords[index]; 1.5339 + ALOGD(" lastGesture[%d]: index=%d, toolType=%d, " 1.5340 + "x=%0.3f, y=%0.3f, pressure=%0.3f", 1.5341 + id, index, properties.toolType, 1.5342 + coords.getAxisValue(AMOTION_EVENT_AXIS_X), 1.5343 + coords.getAxisValue(AMOTION_EVENT_AXIS_Y), 1.5344 + coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE)); 1.5345 + } 1.5346 +#endif 1.5347 + return true; 1.5348 +} 1.5349 + 1.5350 +void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) { 1.5351 + mPointerSimple.currentCoords.clear(); 1.5352 + mPointerSimple.currentProperties.clear(); 1.5353 + 1.5354 + bool down, hovering; 1.5355 + if (!mCurrentStylusIdBits.isEmpty()) { 1.5356 + uint32_t id = mCurrentStylusIdBits.firstMarkedBit(); 1.5357 + uint32_t index = mCurrentCookedPointerData.idToIndex[id]; 1.5358 + float x = mCurrentCookedPointerData.pointerCoords[index].getX(); 1.5359 + float y = mCurrentCookedPointerData.pointerCoords[index].getY(); 1.5360 + mPointerController->setPosition(x, y); 1.5361 + 1.5362 + hovering = mCurrentCookedPointerData.hoveringIdBits.hasBit(id); 1.5363 + down = !hovering; 1.5364 + 1.5365 + mPointerController->getPosition(&x, &y); 1.5366 + mPointerSimple.currentCoords.copyFrom(mCurrentCookedPointerData.pointerCoords[index]); 1.5367 + mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x); 1.5368 + mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y); 1.5369 + mPointerSimple.currentProperties.id = 0; 1.5370 + mPointerSimple.currentProperties.toolType = 1.5371 + mCurrentCookedPointerData.pointerProperties[index].toolType; 1.5372 + } else { 1.5373 + down = false; 1.5374 + hovering = false; 1.5375 + } 1.5376 + 1.5377 + dispatchPointerSimple(when, policyFlags, down, hovering); 1.5378 +} 1.5379 + 1.5380 +void TouchInputMapper::abortPointerStylus(nsecs_t when, uint32_t policyFlags) { 1.5381 + abortPointerSimple(when, policyFlags); 1.5382 +} 1.5383 + 1.5384 +void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) { 1.5385 + mPointerSimple.currentCoords.clear(); 1.5386 + mPointerSimple.currentProperties.clear(); 1.5387 + 1.5388 + bool down, hovering; 1.5389 + if (!mCurrentMouseIdBits.isEmpty()) { 1.5390 + uint32_t id = mCurrentMouseIdBits.firstMarkedBit(); 1.5391 + uint32_t currentIndex = mCurrentRawPointerData.idToIndex[id]; 1.5392 + if (mLastMouseIdBits.hasBit(id)) { 1.5393 + uint32_t lastIndex = mCurrentRawPointerData.idToIndex[id]; 1.5394 + float deltaX = (mCurrentRawPointerData.pointers[currentIndex].x 1.5395 + - mLastRawPointerData.pointers[lastIndex].x) 1.5396 + * mPointerXMovementScale; 1.5397 + float deltaY = (mCurrentRawPointerData.pointers[currentIndex].y 1.5398 + - mLastRawPointerData.pointers[lastIndex].y) 1.5399 + * mPointerYMovementScale; 1.5400 + 1.5401 + rotateDelta(mSurfaceOrientation, &deltaX, &deltaY); 1.5402 + mPointerVelocityControl.move(when, &deltaX, &deltaY); 1.5403 + 1.5404 + mPointerController->move(deltaX, deltaY); 1.5405 + } else { 1.5406 + mPointerVelocityControl.reset(); 1.5407 + } 1.5408 + 1.5409 + down = isPointerDown(mCurrentButtonState); 1.5410 + hovering = !down; 1.5411 + 1.5412 + float x, y; 1.5413 + mPointerController->getPosition(&x, &y); 1.5414 + mPointerSimple.currentCoords.copyFrom( 1.5415 + mCurrentCookedPointerData.pointerCoords[currentIndex]); 1.5416 + mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x); 1.5417 + mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y); 1.5418 + mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.5419 + hovering ? 0.0f : 1.0f); 1.5420 + mPointerSimple.currentProperties.id = 0; 1.5421 + mPointerSimple.currentProperties.toolType = 1.5422 + mCurrentCookedPointerData.pointerProperties[currentIndex].toolType; 1.5423 + } else { 1.5424 + mPointerVelocityControl.reset(); 1.5425 + 1.5426 + down = false; 1.5427 + hovering = false; 1.5428 + } 1.5429 + 1.5430 + dispatchPointerSimple(when, policyFlags, down, hovering); 1.5431 +} 1.5432 + 1.5433 +void TouchInputMapper::abortPointerMouse(nsecs_t when, uint32_t policyFlags) { 1.5434 + abortPointerSimple(when, policyFlags); 1.5435 + 1.5436 + mPointerVelocityControl.reset(); 1.5437 +} 1.5438 + 1.5439 +void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, 1.5440 + bool down, bool hovering) { 1.5441 + int32_t metaState = getContext()->getGlobalMetaState(); 1.5442 + 1.5443 + if (mPointerController != NULL) { 1.5444 + if (down || hovering) { 1.5445 + mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER); 1.5446 + mPointerController->clearSpots(); 1.5447 + mPointerController->setButtonState(mCurrentButtonState); 1.5448 + mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE); 1.5449 + } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) { 1.5450 + mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); 1.5451 + } 1.5452 + } 1.5453 + 1.5454 + if (mPointerSimple.down && !down) { 1.5455 + mPointerSimple.down = false; 1.5456 + 1.5457 + // Send up. 1.5458 + NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, 1.5459 + AMOTION_EVENT_ACTION_UP, 0, metaState, mLastButtonState, 0, 1.5460 + mViewport.displayId, 1.5461 + 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords, 1.5462 + mOrientedXPrecision, mOrientedYPrecision, 1.5463 + mPointerSimple.downTime); 1.5464 + getListener()->notifyMotion(&args); 1.5465 + } 1.5466 + 1.5467 + if (mPointerSimple.hovering && !hovering) { 1.5468 + mPointerSimple.hovering = false; 1.5469 + 1.5470 + // Send hover exit. 1.5471 + NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, 1.5472 + AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0, 1.5473 + mViewport.displayId, 1.5474 + 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords, 1.5475 + mOrientedXPrecision, mOrientedYPrecision, 1.5476 + mPointerSimple.downTime); 1.5477 + getListener()->notifyMotion(&args); 1.5478 + } 1.5479 + 1.5480 + if (down) { 1.5481 + if (!mPointerSimple.down) { 1.5482 + mPointerSimple.down = true; 1.5483 + mPointerSimple.downTime = when; 1.5484 + 1.5485 + // Send down. 1.5486 + NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, 1.5487 + AMOTION_EVENT_ACTION_DOWN, 0, metaState, mCurrentButtonState, 0, 1.5488 + mViewport.displayId, 1.5489 + 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, 1.5490 + mOrientedXPrecision, mOrientedYPrecision, 1.5491 + mPointerSimple.downTime); 1.5492 + getListener()->notifyMotion(&args); 1.5493 + } 1.5494 + 1.5495 + // Send move. 1.5496 + NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, 1.5497 + AMOTION_EVENT_ACTION_MOVE, 0, metaState, mCurrentButtonState, 0, 1.5498 + mViewport.displayId, 1.5499 + 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, 1.5500 + mOrientedXPrecision, mOrientedYPrecision, 1.5501 + mPointerSimple.downTime); 1.5502 + getListener()->notifyMotion(&args); 1.5503 + } 1.5504 + 1.5505 + if (hovering) { 1.5506 + if (!mPointerSimple.hovering) { 1.5507 + mPointerSimple.hovering = true; 1.5508 + 1.5509 + // Send hover enter. 1.5510 + NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, 1.5511 + AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0, 1.5512 + mViewport.displayId, 1.5513 + 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, 1.5514 + mOrientedXPrecision, mOrientedYPrecision, 1.5515 + mPointerSimple.downTime); 1.5516 + getListener()->notifyMotion(&args); 1.5517 + } 1.5518 + 1.5519 + // Send hover move. 1.5520 + NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, 1.5521 + AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0, 1.5522 + mViewport.displayId, 1.5523 + 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, 1.5524 + mOrientedXPrecision, mOrientedYPrecision, 1.5525 + mPointerSimple.downTime); 1.5526 + getListener()->notifyMotion(&args); 1.5527 + } 1.5528 + 1.5529 + if (mCurrentRawVScroll || mCurrentRawHScroll) { 1.5530 + float vscroll = mCurrentRawVScroll; 1.5531 + float hscroll = mCurrentRawHScroll; 1.5532 + mWheelYVelocityControl.move(when, NULL, &vscroll); 1.5533 + mWheelXVelocityControl.move(when, &hscroll, NULL); 1.5534 + 1.5535 + // Send scroll. 1.5536 + PointerCoords pointerCoords; 1.5537 + pointerCoords.copyFrom(mPointerSimple.currentCoords); 1.5538 + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll); 1.5539 + pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll); 1.5540 + 1.5541 + NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, 1.5542 + AMOTION_EVENT_ACTION_SCROLL, 0, metaState, mCurrentButtonState, 0, 1.5543 + mViewport.displayId, 1.5544 + 1, &mPointerSimple.currentProperties, &pointerCoords, 1.5545 + mOrientedXPrecision, mOrientedYPrecision, 1.5546 + mPointerSimple.downTime); 1.5547 + getListener()->notifyMotion(&args); 1.5548 + } 1.5549 + 1.5550 + // Save state. 1.5551 + if (down || hovering) { 1.5552 + mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords); 1.5553 + mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties); 1.5554 + } else { 1.5555 + mPointerSimple.reset(); 1.5556 + } 1.5557 +} 1.5558 + 1.5559 +void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) { 1.5560 + mPointerSimple.currentCoords.clear(); 1.5561 + mPointerSimple.currentProperties.clear(); 1.5562 + 1.5563 + dispatchPointerSimple(when, policyFlags, false, false); 1.5564 +} 1.5565 + 1.5566 +void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source, 1.5567 + int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags, 1.5568 + const PointerProperties* properties, const PointerCoords* coords, 1.5569 + const uint32_t* idToIndex, BitSet32 idBits, 1.5570 + int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) { 1.5571 + PointerCoords pointerCoords[MAX_POINTERS]; 1.5572 + PointerProperties pointerProperties[MAX_POINTERS]; 1.5573 + uint32_t pointerCount = 0; 1.5574 + while (!idBits.isEmpty()) { 1.5575 + uint32_t id = idBits.clearFirstMarkedBit(); 1.5576 + uint32_t index = idToIndex[id]; 1.5577 + pointerProperties[pointerCount].copyFrom(properties[index]); 1.5578 + pointerCoords[pointerCount].copyFrom(coords[index]); 1.5579 + 1.5580 + if (changedId >= 0 && id == uint32_t(changedId)) { 1.5581 + action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; 1.5582 + } 1.5583 + 1.5584 + pointerCount += 1; 1.5585 + } 1.5586 + 1.5587 + ALOG_ASSERT(pointerCount != 0); 1.5588 + 1.5589 + if (changedId >= 0 && pointerCount == 1) { 1.5590 + // Replace initial down and final up action. 1.5591 + // We can compare the action without masking off the changed pointer index 1.5592 + // because we know the index is 0. 1.5593 + if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) { 1.5594 + action = AMOTION_EVENT_ACTION_DOWN; 1.5595 + } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) { 1.5596 + action = AMOTION_EVENT_ACTION_UP; 1.5597 + } else { 1.5598 + // Can't happen. 1.5599 + ALOG_ASSERT(false); 1.5600 + } 1.5601 + } 1.5602 + 1.5603 + NotifyMotionArgs args(when, getDeviceId(), source, policyFlags, 1.5604 + action, flags, metaState, buttonState, edgeFlags, 1.5605 + mViewport.displayId, pointerCount, pointerProperties, pointerCoords, 1.5606 + xPrecision, yPrecision, downTime); 1.5607 + getListener()->notifyMotion(&args); 1.5608 +} 1.5609 + 1.5610 +bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties, 1.5611 + const PointerCoords* inCoords, const uint32_t* inIdToIndex, 1.5612 + PointerProperties* outProperties, PointerCoords* outCoords, const uint32_t* outIdToIndex, 1.5613 + BitSet32 idBits) const { 1.5614 + bool changed = false; 1.5615 + while (!idBits.isEmpty()) { 1.5616 + uint32_t id = idBits.clearFirstMarkedBit(); 1.5617 + uint32_t inIndex = inIdToIndex[id]; 1.5618 + uint32_t outIndex = outIdToIndex[id]; 1.5619 + 1.5620 + const PointerProperties& curInProperties = inProperties[inIndex]; 1.5621 + const PointerCoords& curInCoords = inCoords[inIndex]; 1.5622 + PointerProperties& curOutProperties = outProperties[outIndex]; 1.5623 + PointerCoords& curOutCoords = outCoords[outIndex]; 1.5624 + 1.5625 + if (curInProperties != curOutProperties) { 1.5626 + curOutProperties.copyFrom(curInProperties); 1.5627 + changed = true; 1.5628 + } 1.5629 + 1.5630 + if (curInCoords != curOutCoords) { 1.5631 + curOutCoords.copyFrom(curInCoords); 1.5632 + changed = true; 1.5633 + } 1.5634 + } 1.5635 + return changed; 1.5636 +} 1.5637 + 1.5638 +void TouchInputMapper::fadePointer() { 1.5639 + if (mPointerController != NULL) { 1.5640 + mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); 1.5641 + } 1.5642 +} 1.5643 + 1.5644 +bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) { 1.5645 + return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue 1.5646 + && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue; 1.5647 +} 1.5648 + 1.5649 +const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit( 1.5650 + int32_t x, int32_t y) { 1.5651 + size_t numVirtualKeys = mVirtualKeys.size(); 1.5652 + for (size_t i = 0; i < numVirtualKeys; i++) { 1.5653 + const VirtualKey& virtualKey = mVirtualKeys[i]; 1.5654 + 1.5655 +#if DEBUG_VIRTUAL_KEYS 1.5656 + ALOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, " 1.5657 + "left=%d, top=%d, right=%d, bottom=%d", 1.5658 + x, y, 1.5659 + virtualKey.keyCode, virtualKey.scanCode, 1.5660 + virtualKey.hitLeft, virtualKey.hitTop, 1.5661 + virtualKey.hitRight, virtualKey.hitBottom); 1.5662 +#endif 1.5663 + 1.5664 + if (virtualKey.isHit(x, y)) { 1.5665 + return & virtualKey; 1.5666 + } 1.5667 + } 1.5668 + 1.5669 + return NULL; 1.5670 +} 1.5671 + 1.5672 +void TouchInputMapper::assignPointerIds() { 1.5673 + uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount; 1.5674 + uint32_t lastPointerCount = mLastRawPointerData.pointerCount; 1.5675 + 1.5676 + mCurrentRawPointerData.clearIdBits(); 1.5677 + 1.5678 + if (currentPointerCount == 0) { 1.5679 + // No pointers to assign. 1.5680 + return; 1.5681 + } 1.5682 + 1.5683 + if (lastPointerCount == 0) { 1.5684 + // All pointers are new. 1.5685 + for (uint32_t i = 0; i < currentPointerCount; i++) { 1.5686 + uint32_t id = i; 1.5687 + mCurrentRawPointerData.pointers[i].id = id; 1.5688 + mCurrentRawPointerData.idToIndex[id] = i; 1.5689 + mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(i)); 1.5690 + } 1.5691 + return; 1.5692 + } 1.5693 + 1.5694 + if (currentPointerCount == 1 && lastPointerCount == 1 1.5695 + && mCurrentRawPointerData.pointers[0].toolType 1.5696 + == mLastRawPointerData.pointers[0].toolType) { 1.5697 + // Only one pointer and no change in count so it must have the same id as before. 1.5698 + uint32_t id = mLastRawPointerData.pointers[0].id; 1.5699 + mCurrentRawPointerData.pointers[0].id = id; 1.5700 + mCurrentRawPointerData.idToIndex[id] = 0; 1.5701 + mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(0)); 1.5702 + return; 1.5703 + } 1.5704 + 1.5705 + // General case. 1.5706 + // We build a heap of squared euclidean distances between current and last pointers 1.5707 + // associated with the current and last pointer indices. Then, we find the best 1.5708 + // match (by distance) for each current pointer. 1.5709 + // The pointers must have the same tool type but it is possible for them to 1.5710 + // transition from hovering to touching or vice-versa while retaining the same id. 1.5711 + PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS]; 1.5712 + 1.5713 + uint32_t heapSize = 0; 1.5714 + for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount; 1.5715 + currentPointerIndex++) { 1.5716 + for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount; 1.5717 + lastPointerIndex++) { 1.5718 + const RawPointerData::Pointer& currentPointer = 1.5719 + mCurrentRawPointerData.pointers[currentPointerIndex]; 1.5720 + const RawPointerData::Pointer& lastPointer = 1.5721 + mLastRawPointerData.pointers[lastPointerIndex]; 1.5722 + if (currentPointer.toolType == lastPointer.toolType) { 1.5723 + int64_t deltaX = currentPointer.x - lastPointer.x; 1.5724 + int64_t deltaY = currentPointer.y - lastPointer.y; 1.5725 + 1.5726 + uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY); 1.5727 + 1.5728 + // Insert new element into the heap (sift up). 1.5729 + heap[heapSize].currentPointerIndex = currentPointerIndex; 1.5730 + heap[heapSize].lastPointerIndex = lastPointerIndex; 1.5731 + heap[heapSize].distance = distance; 1.5732 + heapSize += 1; 1.5733 + } 1.5734 + } 1.5735 + } 1.5736 + 1.5737 + // Heapify 1.5738 + for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) { 1.5739 + startIndex -= 1; 1.5740 + for (uint32_t parentIndex = startIndex; ;) { 1.5741 + uint32_t childIndex = parentIndex * 2 + 1; 1.5742 + if (childIndex >= heapSize) { 1.5743 + break; 1.5744 + } 1.5745 + 1.5746 + if (childIndex + 1 < heapSize 1.5747 + && heap[childIndex + 1].distance < heap[childIndex].distance) { 1.5748 + childIndex += 1; 1.5749 + } 1.5750 + 1.5751 + if (heap[parentIndex].distance <= heap[childIndex].distance) { 1.5752 + break; 1.5753 + } 1.5754 + 1.5755 + swap(heap[parentIndex], heap[childIndex]); 1.5756 + parentIndex = childIndex; 1.5757 + } 1.5758 + } 1.5759 + 1.5760 +#if DEBUG_POINTER_ASSIGNMENT 1.5761 + ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize); 1.5762 + for (size_t i = 0; i < heapSize; i++) { 1.5763 + ALOGD(" heap[%d]: cur=%d, last=%d, distance=%lld", 1.5764 + i, heap[i].currentPointerIndex, heap[i].lastPointerIndex, 1.5765 + heap[i].distance); 1.5766 + } 1.5767 +#endif 1.5768 + 1.5769 + // Pull matches out by increasing order of distance. 1.5770 + // To avoid reassigning pointers that have already been matched, the loop keeps track 1.5771 + // of which last and current pointers have been matched using the matchedXXXBits variables. 1.5772 + // It also tracks the used pointer id bits. 1.5773 + BitSet32 matchedLastBits(0); 1.5774 + BitSet32 matchedCurrentBits(0); 1.5775 + BitSet32 usedIdBits(0); 1.5776 + bool first = true; 1.5777 + for (uint32_t i = min(currentPointerCount, lastPointerCount); heapSize > 0 && i > 0; i--) { 1.5778 + while (heapSize > 0) { 1.5779 + if (first) { 1.5780 + // The first time through the loop, we just consume the root element of 1.5781 + // the heap (the one with smallest distance). 1.5782 + first = false; 1.5783 + } else { 1.5784 + // Previous iterations consumed the root element of the heap. 1.5785 + // Pop root element off of the heap (sift down). 1.5786 + heap[0] = heap[heapSize]; 1.5787 + for (uint32_t parentIndex = 0; ;) { 1.5788 + uint32_t childIndex = parentIndex * 2 + 1; 1.5789 + if (childIndex >= heapSize) { 1.5790 + break; 1.5791 + } 1.5792 + 1.5793 + if (childIndex + 1 < heapSize 1.5794 + && heap[childIndex + 1].distance < heap[childIndex].distance) { 1.5795 + childIndex += 1; 1.5796 + } 1.5797 + 1.5798 + if (heap[parentIndex].distance <= heap[childIndex].distance) { 1.5799 + break; 1.5800 + } 1.5801 + 1.5802 + swap(heap[parentIndex], heap[childIndex]); 1.5803 + parentIndex = childIndex; 1.5804 + } 1.5805 + 1.5806 +#if DEBUG_POINTER_ASSIGNMENT 1.5807 + ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize); 1.5808 + for (size_t i = 0; i < heapSize; i++) { 1.5809 + ALOGD(" heap[%d]: cur=%d, last=%d, distance=%lld", 1.5810 + i, heap[i].currentPointerIndex, heap[i].lastPointerIndex, 1.5811 + heap[i].distance); 1.5812 + } 1.5813 +#endif 1.5814 + } 1.5815 + 1.5816 + heapSize -= 1; 1.5817 + 1.5818 + uint32_t currentPointerIndex = heap[0].currentPointerIndex; 1.5819 + if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched 1.5820 + 1.5821 + uint32_t lastPointerIndex = heap[0].lastPointerIndex; 1.5822 + if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched 1.5823 + 1.5824 + matchedCurrentBits.markBit(currentPointerIndex); 1.5825 + matchedLastBits.markBit(lastPointerIndex); 1.5826 + 1.5827 + uint32_t id = mLastRawPointerData.pointers[lastPointerIndex].id; 1.5828 + mCurrentRawPointerData.pointers[currentPointerIndex].id = id; 1.5829 + mCurrentRawPointerData.idToIndex[id] = currentPointerIndex; 1.5830 + mCurrentRawPointerData.markIdBit(id, 1.5831 + mCurrentRawPointerData.isHovering(currentPointerIndex)); 1.5832 + usedIdBits.markBit(id); 1.5833 + 1.5834 +#if DEBUG_POINTER_ASSIGNMENT 1.5835 + ALOGD("assignPointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld", 1.5836 + lastPointerIndex, currentPointerIndex, id, heap[0].distance); 1.5837 +#endif 1.5838 + break; 1.5839 + } 1.5840 + } 1.5841 + 1.5842 + // Assign fresh ids to pointers that were not matched in the process. 1.5843 + for (uint32_t i = currentPointerCount - matchedCurrentBits.count(); i != 0; i--) { 1.5844 + uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit(); 1.5845 + uint32_t id = usedIdBits.markFirstUnmarkedBit(); 1.5846 + 1.5847 + mCurrentRawPointerData.pointers[currentPointerIndex].id = id; 1.5848 + mCurrentRawPointerData.idToIndex[id] = currentPointerIndex; 1.5849 + mCurrentRawPointerData.markIdBit(id, 1.5850 + mCurrentRawPointerData.isHovering(currentPointerIndex)); 1.5851 + 1.5852 +#if DEBUG_POINTER_ASSIGNMENT 1.5853 + ALOGD("assignPointerIds - assigned: cur=%d, id=%d", 1.5854 + currentPointerIndex, id); 1.5855 +#endif 1.5856 + } 1.5857 +} 1.5858 + 1.5859 +int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) { 1.5860 + if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) { 1.5861 + return AKEY_STATE_VIRTUAL; 1.5862 + } 1.5863 + 1.5864 + size_t numVirtualKeys = mVirtualKeys.size(); 1.5865 + for (size_t i = 0; i < numVirtualKeys; i++) { 1.5866 + const VirtualKey& virtualKey = mVirtualKeys[i]; 1.5867 + if (virtualKey.keyCode == keyCode) { 1.5868 + return AKEY_STATE_UP; 1.5869 + } 1.5870 + } 1.5871 + 1.5872 + return AKEY_STATE_UNKNOWN; 1.5873 +} 1.5874 + 1.5875 +int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) { 1.5876 + if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) { 1.5877 + return AKEY_STATE_VIRTUAL; 1.5878 + } 1.5879 + 1.5880 + size_t numVirtualKeys = mVirtualKeys.size(); 1.5881 + for (size_t i = 0; i < numVirtualKeys; i++) { 1.5882 + const VirtualKey& virtualKey = mVirtualKeys[i]; 1.5883 + if (virtualKey.scanCode == scanCode) { 1.5884 + return AKEY_STATE_UP; 1.5885 + } 1.5886 + } 1.5887 + 1.5888 + return AKEY_STATE_UNKNOWN; 1.5889 +} 1.5890 + 1.5891 +bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, 1.5892 + const int32_t* keyCodes, uint8_t* outFlags) { 1.5893 + size_t numVirtualKeys = mVirtualKeys.size(); 1.5894 + for (size_t i = 0; i < numVirtualKeys; i++) { 1.5895 + const VirtualKey& virtualKey = mVirtualKeys[i]; 1.5896 + 1.5897 + for (size_t i = 0; i < numCodes; i++) { 1.5898 + if (virtualKey.keyCode == keyCodes[i]) { 1.5899 + outFlags[i] = 1; 1.5900 + } 1.5901 + } 1.5902 + } 1.5903 + 1.5904 + return true; 1.5905 +} 1.5906 + 1.5907 + 1.5908 +// --- SingleTouchInputMapper --- 1.5909 + 1.5910 +SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) : 1.5911 + TouchInputMapper(device) { 1.5912 +} 1.5913 + 1.5914 +SingleTouchInputMapper::~SingleTouchInputMapper() { 1.5915 +} 1.5916 + 1.5917 +void SingleTouchInputMapper::reset(nsecs_t when) { 1.5918 + mSingleTouchMotionAccumulator.reset(getDevice()); 1.5919 + 1.5920 + TouchInputMapper::reset(when); 1.5921 +} 1.5922 + 1.5923 +void SingleTouchInputMapper::process(const RawEvent* rawEvent) { 1.5924 + TouchInputMapper::process(rawEvent); 1.5925 + 1.5926 + mSingleTouchMotionAccumulator.process(rawEvent); 1.5927 +} 1.5928 + 1.5929 +void SingleTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) { 1.5930 + if (mTouchButtonAccumulator.isToolActive()) { 1.5931 + mCurrentRawPointerData.pointerCount = 1; 1.5932 + mCurrentRawPointerData.idToIndex[0] = 0; 1.5933 + 1.5934 + bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE 1.5935 + && (mTouchButtonAccumulator.isHovering() 1.5936 + || (mRawPointerAxes.pressure.valid 1.5937 + && mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0)); 1.5938 + mCurrentRawPointerData.markIdBit(0, isHovering); 1.5939 + 1.5940 + RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[0]; 1.5941 + outPointer.id = 0; 1.5942 + outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX(); 1.5943 + outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY(); 1.5944 + outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure(); 1.5945 + outPointer.touchMajor = 0; 1.5946 + outPointer.touchMinor = 0; 1.5947 + outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth(); 1.5948 + outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth(); 1.5949 + outPointer.orientation = 0; 1.5950 + outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance(); 1.5951 + outPointer.tiltX = mSingleTouchMotionAccumulator.getAbsoluteTiltX(); 1.5952 + outPointer.tiltY = mSingleTouchMotionAccumulator.getAbsoluteTiltY(); 1.5953 + outPointer.toolType = mTouchButtonAccumulator.getToolType(); 1.5954 + if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) { 1.5955 + outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; 1.5956 + } 1.5957 + outPointer.isHovering = isHovering; 1.5958 + } 1.5959 +} 1.5960 + 1.5961 +void SingleTouchInputMapper::configureRawPointerAxes() { 1.5962 + TouchInputMapper::configureRawPointerAxes(); 1.5963 + 1.5964 + getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x); 1.5965 + getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y); 1.5966 + getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure); 1.5967 + getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor); 1.5968 + getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance); 1.5969 + getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX); 1.5970 + getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY); 1.5971 +} 1.5972 + 1.5973 +bool SingleTouchInputMapper::hasStylus() const { 1.5974 + return mTouchButtonAccumulator.hasStylus(); 1.5975 +} 1.5976 + 1.5977 + 1.5978 +// --- MultiTouchInputMapper --- 1.5979 + 1.5980 +MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) : 1.5981 + TouchInputMapper(device) { 1.5982 +} 1.5983 + 1.5984 +MultiTouchInputMapper::~MultiTouchInputMapper() { 1.5985 +} 1.5986 + 1.5987 +void MultiTouchInputMapper::reset(nsecs_t when) { 1.5988 + mMultiTouchMotionAccumulator.reset(getDevice()); 1.5989 + 1.5990 + mPointerIdBits.clear(); 1.5991 + 1.5992 + TouchInputMapper::reset(when); 1.5993 +} 1.5994 + 1.5995 +void MultiTouchInputMapper::process(const RawEvent* rawEvent) { 1.5996 + TouchInputMapper::process(rawEvent); 1.5997 + 1.5998 + mMultiTouchMotionAccumulator.process(rawEvent); 1.5999 +} 1.6000 + 1.6001 +void MultiTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) { 1.6002 + size_t inCount = mMultiTouchMotionAccumulator.getSlotCount(); 1.6003 + size_t outCount = 0; 1.6004 + BitSet32 newPointerIdBits; 1.6005 + 1.6006 + for (size_t inIndex = 0; inIndex < inCount; inIndex++) { 1.6007 + const MultiTouchMotionAccumulator::Slot* inSlot = 1.6008 + mMultiTouchMotionAccumulator.getSlot(inIndex); 1.6009 + if (!inSlot->isInUse()) { 1.6010 + continue; 1.6011 + } 1.6012 + 1.6013 + if (outCount >= MAX_POINTERS) { 1.6014 +#if DEBUG_POINTERS 1.6015 + ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; " 1.6016 + "ignoring the rest.", 1.6017 + getDeviceName().string(), MAX_POINTERS); 1.6018 +#endif 1.6019 + break; // too many fingers! 1.6020 + } 1.6021 + 1.6022 + RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[outCount]; 1.6023 + outPointer.x = inSlot->getX(); 1.6024 + outPointer.y = inSlot->getY(); 1.6025 + outPointer.pressure = inSlot->getPressure(); 1.6026 + outPointer.touchMajor = inSlot->getTouchMajor(); 1.6027 + outPointer.touchMinor = inSlot->getTouchMinor(); 1.6028 + outPointer.toolMajor = inSlot->getToolMajor(); 1.6029 + outPointer.toolMinor = inSlot->getToolMinor(); 1.6030 + outPointer.orientation = inSlot->getOrientation(); 1.6031 + outPointer.distance = inSlot->getDistance(); 1.6032 + outPointer.tiltX = 0; 1.6033 + outPointer.tiltY = 0; 1.6034 + 1.6035 + outPointer.toolType = inSlot->getToolType(); 1.6036 + if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) { 1.6037 + outPointer.toolType = mTouchButtonAccumulator.getToolType(); 1.6038 + if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) { 1.6039 + outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; 1.6040 + } 1.6041 + } 1.6042 + 1.6043 + bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE 1.6044 + && (mTouchButtonAccumulator.isHovering() 1.6045 + || (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0)); 1.6046 + outPointer.isHovering = isHovering; 1.6047 + 1.6048 + // Assign pointer id using tracking id if available. 1.6049 + if (*outHavePointerIds) { 1.6050 + int32_t trackingId = inSlot->getTrackingId(); 1.6051 + int32_t id = -1; 1.6052 + if (trackingId >= 0) { 1.6053 + for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) { 1.6054 + uint32_t n = idBits.clearFirstMarkedBit(); 1.6055 + if (mPointerTrackingIdMap[n] == trackingId) { 1.6056 + id = n; 1.6057 + } 1.6058 + } 1.6059 + 1.6060 + if (id < 0 && !mPointerIdBits.isFull()) { 1.6061 + id = mPointerIdBits.markFirstUnmarkedBit(); 1.6062 + mPointerTrackingIdMap[id] = trackingId; 1.6063 + } 1.6064 + } 1.6065 + if (id < 0) { 1.6066 + *outHavePointerIds = false; 1.6067 + mCurrentRawPointerData.clearIdBits(); 1.6068 + newPointerIdBits.clear(); 1.6069 + } else { 1.6070 + outPointer.id = id; 1.6071 + mCurrentRawPointerData.idToIndex[id] = outCount; 1.6072 + mCurrentRawPointerData.markIdBit(id, isHovering); 1.6073 + newPointerIdBits.markBit(id); 1.6074 + } 1.6075 + } 1.6076 + 1.6077 + outCount += 1; 1.6078 + } 1.6079 + 1.6080 + mCurrentRawPointerData.pointerCount = outCount; 1.6081 + mPointerIdBits = newPointerIdBits; 1.6082 + 1.6083 + mMultiTouchMotionAccumulator.finishSync(); 1.6084 +} 1.6085 + 1.6086 +void MultiTouchInputMapper::configureRawPointerAxes() { 1.6087 + TouchInputMapper::configureRawPointerAxes(); 1.6088 + 1.6089 + getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x); 1.6090 + getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y); 1.6091 + getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor); 1.6092 + getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor); 1.6093 + getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor); 1.6094 + getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor); 1.6095 + getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation); 1.6096 + getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure); 1.6097 + getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance); 1.6098 + getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId); 1.6099 + getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot); 1.6100 + 1.6101 + if (mRawPointerAxes.trackingId.valid 1.6102 + && mRawPointerAxes.slot.valid 1.6103 + && mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) { 1.6104 + size_t slotCount = mRawPointerAxes.slot.maxValue + 1; 1.6105 + if (slotCount > MAX_SLOTS) { 1.6106 + ALOGW("MultiTouch Device %s reported %d slots but the framework " 1.6107 + "only supports a maximum of %d slots at this time.", 1.6108 + getDeviceName().string(), slotCount, MAX_SLOTS); 1.6109 + slotCount = MAX_SLOTS; 1.6110 + } 1.6111 + mMultiTouchMotionAccumulator.configure(getDevice(), 1.6112 + slotCount, true /*usingSlotsProtocol*/); 1.6113 + } else { 1.6114 + mMultiTouchMotionAccumulator.configure(getDevice(), 1.6115 + MAX_POINTERS, false /*usingSlotsProtocol*/); 1.6116 + } 1.6117 +} 1.6118 + 1.6119 +bool MultiTouchInputMapper::hasStylus() const { 1.6120 + return mMultiTouchMotionAccumulator.hasStylus() 1.6121 + || mTouchButtonAccumulator.hasStylus(); 1.6122 +} 1.6123 + 1.6124 + 1.6125 +// --- JoystickInputMapper --- 1.6126 + 1.6127 +JoystickInputMapper::JoystickInputMapper(InputDevice* device) : 1.6128 + InputMapper(device) { 1.6129 +} 1.6130 + 1.6131 +JoystickInputMapper::~JoystickInputMapper() { 1.6132 +} 1.6133 + 1.6134 +uint32_t JoystickInputMapper::getSources() { 1.6135 + return AINPUT_SOURCE_JOYSTICK; 1.6136 +} 1.6137 + 1.6138 +void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) { 1.6139 + InputMapper::populateDeviceInfo(info); 1.6140 + 1.6141 + for (size_t i = 0; i < mAxes.size(); i++) { 1.6142 + const Axis& axis = mAxes.valueAt(i); 1.6143 + addMotionRange(axis.axisInfo.axis, axis, info); 1.6144 + 1.6145 + if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) { 1.6146 + addMotionRange(axis.axisInfo.highAxis, axis, info); 1.6147 + 1.6148 + } 1.6149 + } 1.6150 +} 1.6151 + 1.6152 +void JoystickInputMapper::addMotionRange(int32_t axisId, const Axis& axis, 1.6153 + InputDeviceInfo* info) { 1.6154 + info->addMotionRange(axisId, AINPUT_SOURCE_JOYSTICK, 1.6155 + axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution); 1.6156 + /* In order to ease the transition for developers from using the old axes 1.6157 + * to the newer, more semantically correct axes, we'll continue to register 1.6158 + * the old axes as duplicates of their corresponding new ones. */ 1.6159 + int32_t compatAxis = getCompatAxis(axisId); 1.6160 + if (compatAxis >= 0) { 1.6161 + info->addMotionRange(compatAxis, AINPUT_SOURCE_JOYSTICK, 1.6162 + axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution); 1.6163 + } 1.6164 +} 1.6165 + 1.6166 +/* A mapping from axes the joystick actually has to the axes that should be 1.6167 + * artificially created for compatibility purposes. 1.6168 + * Returns -1 if no compatibility axis is needed. */ 1.6169 +int32_t JoystickInputMapper::getCompatAxis(int32_t axis) { 1.6170 + switch(axis) { 1.6171 + case AMOTION_EVENT_AXIS_LTRIGGER: 1.6172 + return AMOTION_EVENT_AXIS_BRAKE; 1.6173 + case AMOTION_EVENT_AXIS_RTRIGGER: 1.6174 + return AMOTION_EVENT_AXIS_GAS; 1.6175 + } 1.6176 + return -1; 1.6177 +} 1.6178 + 1.6179 +void JoystickInputMapper::dump(String8& dump) { 1.6180 + dump.append(INDENT2 "Joystick Input Mapper:\n"); 1.6181 + 1.6182 + dump.append(INDENT3 "Axes:\n"); 1.6183 + size_t numAxes = mAxes.size(); 1.6184 + for (size_t i = 0; i < numAxes; i++) { 1.6185 + const Axis& axis = mAxes.valueAt(i); 1.6186 + const char* label = getAxisLabel(axis.axisInfo.axis); 1.6187 + if (label) { 1.6188 + dump.appendFormat(INDENT4 "%s", label); 1.6189 + } else { 1.6190 + dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis); 1.6191 + } 1.6192 + if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) { 1.6193 + label = getAxisLabel(axis.axisInfo.highAxis); 1.6194 + if (label) { 1.6195 + dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue); 1.6196 + } else { 1.6197 + dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis, 1.6198 + axis.axisInfo.splitValue); 1.6199 + } 1.6200 + } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) { 1.6201 + dump.append(" (invert)"); 1.6202 + } 1.6203 + 1.6204 + dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f, resolution=%0.5f\n", 1.6205 + axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution); 1.6206 + dump.appendFormat(INDENT4 " scale=%0.5f, offset=%0.5f, " 1.6207 + "highScale=%0.5f, highOffset=%0.5f\n", 1.6208 + axis.scale, axis.offset, axis.highScale, axis.highOffset); 1.6209 + dump.appendFormat(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, " 1.6210 + "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n", 1.6211 + mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue, 1.6212 + axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, axis.rawAxisInfo.resolution); 1.6213 + } 1.6214 +} 1.6215 + 1.6216 +void JoystickInputMapper::configure(nsecs_t when, 1.6217 + const InputReaderConfiguration* config, uint32_t changes) { 1.6218 + InputMapper::configure(when, config, changes); 1.6219 + 1.6220 + if (!changes) { // first time only 1.6221 + // Collect all axes. 1.6222 + for (int32_t abs = 0; abs <= ABS_MAX; abs++) { 1.6223 + if (!(getAbsAxisUsage(abs, getDevice()->getClasses()) 1.6224 + & INPUT_DEVICE_CLASS_JOYSTICK)) { 1.6225 + continue; // axis must be claimed by a different device 1.6226 + } 1.6227 + 1.6228 + RawAbsoluteAxisInfo rawAxisInfo; 1.6229 + getAbsoluteAxisInfo(abs, &rawAxisInfo); 1.6230 + if (rawAxisInfo.valid) { 1.6231 + // Map axis. 1.6232 + AxisInfo axisInfo; 1.6233 + bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo); 1.6234 + if (!explicitlyMapped) { 1.6235 + // Axis is not explicitly mapped, will choose a generic axis later. 1.6236 + axisInfo.mode = AxisInfo::MODE_NORMAL; 1.6237 + axisInfo.axis = -1; 1.6238 + } 1.6239 + 1.6240 + // Apply flat override. 1.6241 + int32_t rawFlat = axisInfo.flatOverride < 0 1.6242 + ? rawAxisInfo.flat : axisInfo.flatOverride; 1.6243 + 1.6244 + // Calculate scaling factors and limits. 1.6245 + Axis axis; 1.6246 + if (axisInfo.mode == AxisInfo::MODE_SPLIT) { 1.6247 + float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue); 1.6248 + float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue); 1.6249 + axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, 1.6250 + scale, 0.0f, highScale, 0.0f, 1.6251 + 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale, 1.6252 + rawAxisInfo.resolution * scale); 1.6253 + } else if (isCenteredAxis(axisInfo.axis)) { 1.6254 + float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue); 1.6255 + float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale; 1.6256 + axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, 1.6257 + scale, offset, scale, offset, 1.6258 + -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale, 1.6259 + rawAxisInfo.resolution * scale); 1.6260 + } else { 1.6261 + float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue); 1.6262 + axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, 1.6263 + scale, 0.0f, scale, 0.0f, 1.6264 + 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale, 1.6265 + rawAxisInfo.resolution * scale); 1.6266 + } 1.6267 + 1.6268 + // To eliminate noise while the joystick is at rest, filter out small variations 1.6269 + // in axis values up front. 1.6270 + axis.filter = axis.flat * 0.25f; 1.6271 + 1.6272 + mAxes.add(abs, axis); 1.6273 + } 1.6274 + } 1.6275 + 1.6276 + // If there are too many axes, start dropping them. 1.6277 + // Prefer to keep explicitly mapped axes. 1.6278 + if (mAxes.size() > PointerCoords::MAX_AXES) { 1.6279 + ALOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.", 1.6280 + getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES); 1.6281 + pruneAxes(true); 1.6282 + pruneAxes(false); 1.6283 + } 1.6284 + 1.6285 + // Assign generic axis ids to remaining axes. 1.6286 + int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1; 1.6287 + size_t numAxes = mAxes.size(); 1.6288 + for (size_t i = 0; i < numAxes; i++) { 1.6289 + Axis& axis = mAxes.editValueAt(i); 1.6290 + if (axis.axisInfo.axis < 0) { 1.6291 + while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16 1.6292 + && haveAxis(nextGenericAxisId)) { 1.6293 + nextGenericAxisId += 1; 1.6294 + } 1.6295 + 1.6296 + if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) { 1.6297 + axis.axisInfo.axis = nextGenericAxisId; 1.6298 + nextGenericAxisId += 1; 1.6299 + } else { 1.6300 + ALOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids " 1.6301 + "have already been assigned to other axes.", 1.6302 + getDeviceName().string(), mAxes.keyAt(i)); 1.6303 + mAxes.removeItemsAt(i--); 1.6304 + numAxes -= 1; 1.6305 + } 1.6306 + } 1.6307 + } 1.6308 + } 1.6309 +} 1.6310 + 1.6311 +bool JoystickInputMapper::haveAxis(int32_t axisId) { 1.6312 + size_t numAxes = mAxes.size(); 1.6313 + for (size_t i = 0; i < numAxes; i++) { 1.6314 + const Axis& axis = mAxes.valueAt(i); 1.6315 + if (axis.axisInfo.axis == axisId 1.6316 + || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT 1.6317 + && axis.axisInfo.highAxis == axisId)) { 1.6318 + return true; 1.6319 + } 1.6320 + } 1.6321 + return false; 1.6322 +} 1.6323 + 1.6324 +void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) { 1.6325 + size_t i = mAxes.size(); 1.6326 + while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) { 1.6327 + if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) { 1.6328 + continue; 1.6329 + } 1.6330 + ALOGI("Discarding joystick '%s' axis %d because there are too many axes.", 1.6331 + getDeviceName().string(), mAxes.keyAt(i)); 1.6332 + mAxes.removeItemsAt(i); 1.6333 + } 1.6334 +} 1.6335 + 1.6336 +bool JoystickInputMapper::isCenteredAxis(int32_t axis) { 1.6337 + switch (axis) { 1.6338 + case AMOTION_EVENT_AXIS_X: 1.6339 + case AMOTION_EVENT_AXIS_Y: 1.6340 + case AMOTION_EVENT_AXIS_Z: 1.6341 + case AMOTION_EVENT_AXIS_RX: 1.6342 + case AMOTION_EVENT_AXIS_RY: 1.6343 + case AMOTION_EVENT_AXIS_RZ: 1.6344 + case AMOTION_EVENT_AXIS_HAT_X: 1.6345 + case AMOTION_EVENT_AXIS_HAT_Y: 1.6346 + case AMOTION_EVENT_AXIS_ORIENTATION: 1.6347 + case AMOTION_EVENT_AXIS_RUDDER: 1.6348 + case AMOTION_EVENT_AXIS_WHEEL: 1.6349 + return true; 1.6350 + default: 1.6351 + return false; 1.6352 + } 1.6353 +} 1.6354 + 1.6355 +void JoystickInputMapper::reset(nsecs_t when) { 1.6356 + // Recenter all axes. 1.6357 + size_t numAxes = mAxes.size(); 1.6358 + for (size_t i = 0; i < numAxes; i++) { 1.6359 + Axis& axis = mAxes.editValueAt(i); 1.6360 + axis.resetValue(); 1.6361 + } 1.6362 + 1.6363 + InputMapper::reset(when); 1.6364 +} 1.6365 + 1.6366 +void JoystickInputMapper::process(const RawEvent* rawEvent) { 1.6367 + switch (rawEvent->type) { 1.6368 + case EV_ABS: { 1.6369 + ssize_t index = mAxes.indexOfKey(rawEvent->code); 1.6370 + if (index >= 0) { 1.6371 + Axis& axis = mAxes.editValueAt(index); 1.6372 + float newValue, highNewValue; 1.6373 + switch (axis.axisInfo.mode) { 1.6374 + case AxisInfo::MODE_INVERT: 1.6375 + newValue = (axis.rawAxisInfo.maxValue - rawEvent->value) 1.6376 + * axis.scale + axis.offset; 1.6377 + highNewValue = 0.0f; 1.6378 + break; 1.6379 + case AxisInfo::MODE_SPLIT: 1.6380 + if (rawEvent->value < axis.axisInfo.splitValue) { 1.6381 + newValue = (axis.axisInfo.splitValue - rawEvent->value) 1.6382 + * axis.scale + axis.offset; 1.6383 + highNewValue = 0.0f; 1.6384 + } else if (rawEvent->value > axis.axisInfo.splitValue) { 1.6385 + newValue = 0.0f; 1.6386 + highNewValue = (rawEvent->value - axis.axisInfo.splitValue) 1.6387 + * axis.highScale + axis.highOffset; 1.6388 + } else { 1.6389 + newValue = 0.0f; 1.6390 + highNewValue = 0.0f; 1.6391 + } 1.6392 + break; 1.6393 + default: 1.6394 + newValue = rawEvent->value * axis.scale + axis.offset; 1.6395 + highNewValue = 0.0f; 1.6396 + break; 1.6397 + } 1.6398 + axis.newValue = newValue; 1.6399 + axis.highNewValue = highNewValue; 1.6400 + } 1.6401 + break; 1.6402 + } 1.6403 + 1.6404 + case EV_SYN: 1.6405 + switch (rawEvent->code) { 1.6406 + case SYN_REPORT: 1.6407 + sync(rawEvent->when, false /*force*/); 1.6408 + break; 1.6409 + } 1.6410 + break; 1.6411 + } 1.6412 +} 1.6413 + 1.6414 +void JoystickInputMapper::sync(nsecs_t when, bool force) { 1.6415 + if (!filterAxes(force)) { 1.6416 + return; 1.6417 + } 1.6418 + 1.6419 + int32_t metaState = mContext->getGlobalMetaState(); 1.6420 + int32_t buttonState = 0; 1.6421 + 1.6422 + PointerProperties pointerProperties; 1.6423 + pointerProperties.clear(); 1.6424 + pointerProperties.id = 0; 1.6425 + pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN; 1.6426 + 1.6427 + PointerCoords pointerCoords; 1.6428 + pointerCoords.clear(); 1.6429 + 1.6430 + size_t numAxes = mAxes.size(); 1.6431 + for (size_t i = 0; i < numAxes; i++) { 1.6432 + const Axis& axis = mAxes.valueAt(i); 1.6433 + setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.axis, axis.currentValue); 1.6434 + if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) { 1.6435 + setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.highAxis, 1.6436 + axis.highCurrentValue); 1.6437 + } 1.6438 + } 1.6439 + 1.6440 + // Moving a joystick axis should not wake the device because joysticks can 1.6441 + // be fairly noisy even when not in use. On the other hand, pushing a gamepad 1.6442 + // button will likely wake the device. 1.6443 + // TODO: Use the input device configuration to control this behavior more finely. 1.6444 + uint32_t policyFlags = 0; 1.6445 + 1.6446 + NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags, 1.6447 + AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, 1.6448 + ADISPLAY_ID_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, 0); 1.6449 + getListener()->notifyMotion(&args); 1.6450 +} 1.6451 + 1.6452 +void JoystickInputMapper::setPointerCoordsAxisValue(PointerCoords* pointerCoords, 1.6453 + int32_t axis, float value) { 1.6454 + pointerCoords->setAxisValue(axis, value); 1.6455 + /* In order to ease the transition for developers from using the old axes 1.6456 + * to the newer, more semantically correct axes, we'll continue to produce 1.6457 + * values for the old axes as mirrors of the value of their corresponding 1.6458 + * new axes. */ 1.6459 + int32_t compatAxis = getCompatAxis(axis); 1.6460 + if (compatAxis >= 0) { 1.6461 + pointerCoords->setAxisValue(compatAxis, value); 1.6462 + } 1.6463 +} 1.6464 + 1.6465 +bool JoystickInputMapper::filterAxes(bool force) { 1.6466 + bool atLeastOneSignificantChange = force; 1.6467 + size_t numAxes = mAxes.size(); 1.6468 + for (size_t i = 0; i < numAxes; i++) { 1.6469 + Axis& axis = mAxes.editValueAt(i); 1.6470 + if (force || hasValueChangedSignificantly(axis.filter, 1.6471 + axis.newValue, axis.currentValue, axis.min, axis.max)) { 1.6472 + axis.currentValue = axis.newValue; 1.6473 + atLeastOneSignificantChange = true; 1.6474 + } 1.6475 + if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) { 1.6476 + if (force || hasValueChangedSignificantly(axis.filter, 1.6477 + axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) { 1.6478 + axis.highCurrentValue = axis.highNewValue; 1.6479 + atLeastOneSignificantChange = true; 1.6480 + } 1.6481 + } 1.6482 + } 1.6483 + return atLeastOneSignificantChange; 1.6484 +} 1.6485 + 1.6486 +bool JoystickInputMapper::hasValueChangedSignificantly( 1.6487 + float filter, float newValue, float currentValue, float min, float max) { 1.6488 + if (newValue != currentValue) { 1.6489 + // Filter out small changes in value unless the value is converging on the axis 1.6490 + // bounds or center point. This is intended to reduce the amount of information 1.6491 + // sent to applications by particularly noisy joysticks (such as PS3). 1.6492 + if (fabs(newValue - currentValue) > filter 1.6493 + || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min) 1.6494 + || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max) 1.6495 + || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) { 1.6496 + return true; 1.6497 + } 1.6498 + } 1.6499 + return false; 1.6500 +} 1.6501 + 1.6502 +bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange( 1.6503 + float filter, float newValue, float currentValue, float thresholdValue) { 1.6504 + float newDistance = fabs(newValue - thresholdValue); 1.6505 + if (newDistance < filter) { 1.6506 + float oldDistance = fabs(currentValue - thresholdValue); 1.6507 + if (newDistance < oldDistance) { 1.6508 + return true; 1.6509 + } 1.6510 + } 1.6511 + return false; 1.6512 +} 1.6513 + 1.6514 +} // namespace android