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