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