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