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