Input.cpp revision 2ed2462aa29c564f5231f317c27b3188da875e52
1// 2// Copyright 2010 The Android Open Source Project 3// 4// Provides a pipe-based transport for native events in the NDK. 5// 6#define LOG_TAG "Input" 7 8//#define LOG_NDEBUG 0 9 10// Log debug messages about keymap probing. 11#define DEBUG_PROBE 0 12 13// Log debug messages about velocity tracking. 14#define DEBUG_VELOCITY 0 15 16#include <stdlib.h> 17#include <unistd.h> 18#include <ctype.h> 19 20#include <ui/Input.h> 21 22#include <math.h> 23 24#ifdef HAVE_ANDROID_OS 25#include <binder/Parcel.h> 26 27#include "SkPoint.h" 28#include "SkMatrix.h" 29#include "SkScalar.h" 30#endif 31 32namespace android { 33 34static const char* CONFIGURATION_FILE_DIR[] = { 35 "idc/", 36 "keylayout/", 37 "keychars/", 38}; 39 40static const char* CONFIGURATION_FILE_EXTENSION[] = { 41 ".idc", 42 ".kl", 43 ".kcm", 44}; 45 46static bool isValidNameChar(char ch) { 47 return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_'); 48} 49 50static void appendInputDeviceConfigurationFileRelativePath(String8& path, 51 const String8& name, InputDeviceConfigurationFileType type) { 52 path.append(CONFIGURATION_FILE_DIR[type]); 53 for (size_t i = 0; i < name.length(); i++) { 54 char ch = name[i]; 55 if (!isValidNameChar(ch)) { 56 ch = '_'; 57 } 58 path.append(&ch, 1); 59 } 60 path.append(CONFIGURATION_FILE_EXTENSION[type]); 61} 62 63String8 getInputDeviceConfigurationFilePathByDeviceIdentifier( 64 const InputDeviceIdentifier& deviceIdentifier, 65 InputDeviceConfigurationFileType type) { 66 if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) { 67 if (deviceIdentifier.version != 0) { 68 // Try vendor product version. 69 String8 versionPath(getInputDeviceConfigurationFilePathByName( 70 String8::format("Vendor_%04x_Product_%04x_Version_%04x", 71 deviceIdentifier.vendor, deviceIdentifier.product, 72 deviceIdentifier.version), 73 type)); 74 if (!versionPath.isEmpty()) { 75 return versionPath; 76 } 77 } 78 79 // Try vendor product. 80 String8 productPath(getInputDeviceConfigurationFilePathByName( 81 String8::format("Vendor_%04x_Product_%04x", 82 deviceIdentifier.vendor, deviceIdentifier.product), 83 type)); 84 if (!productPath.isEmpty()) { 85 return productPath; 86 } 87 } 88 89 // Try device name. 90 return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type); 91} 92 93String8 getInputDeviceConfigurationFilePathByName( 94 const String8& name, InputDeviceConfigurationFileType type) { 95 // Search system repository. 96 String8 path; 97 path.setTo(getenv("ANDROID_ROOT")); 98 path.append("/usr/"); 99 appendInputDeviceConfigurationFileRelativePath(path, name, type); 100#if DEBUG_PROBE 101 LOGD("Probing for system provided input device configuration file: path='%s'", path.string()); 102#endif 103 if (!access(path.string(), R_OK)) { 104#if DEBUG_PROBE 105 LOGD("Found"); 106#endif 107 return path; 108 } 109 110 // Search user repository. 111 // TODO Should only look here if not in safe mode. 112 path.setTo(getenv("ANDROID_DATA")); 113 path.append("/system/devices/"); 114 appendInputDeviceConfigurationFileRelativePath(path, name, type); 115#if DEBUG_PROBE 116 LOGD("Probing for system user input device configuration file: path='%s'", path.string()); 117#endif 118 if (!access(path.string(), R_OK)) { 119#if DEBUG_PROBE 120 LOGD("Found"); 121#endif 122 return path; 123 } 124 125 // Not found. 126#if DEBUG_PROBE 127 LOGD("Probe failed to find input device configuration file: name='%s', type=%d", 128 name.string(), type); 129#endif 130 return String8(); 131} 132 133 134// --- InputEvent --- 135 136void InputEvent::initialize(int32_t deviceId, int32_t source) { 137 mDeviceId = deviceId; 138 mSource = source; 139} 140 141void InputEvent::initialize(const InputEvent& from) { 142 mDeviceId = from.mDeviceId; 143 mSource = from.mSource; 144} 145 146// --- KeyEvent --- 147 148bool KeyEvent::hasDefaultAction(int32_t keyCode) { 149 switch (keyCode) { 150 case AKEYCODE_HOME: 151 case AKEYCODE_BACK: 152 case AKEYCODE_CALL: 153 case AKEYCODE_ENDCALL: 154 case AKEYCODE_VOLUME_UP: 155 case AKEYCODE_VOLUME_DOWN: 156 case AKEYCODE_VOLUME_MUTE: 157 case AKEYCODE_POWER: 158 case AKEYCODE_CAMERA: 159 case AKEYCODE_HEADSETHOOK: 160 case AKEYCODE_MENU: 161 case AKEYCODE_NOTIFICATION: 162 case AKEYCODE_FOCUS: 163 case AKEYCODE_SEARCH: 164 case AKEYCODE_MEDIA_PLAY: 165 case AKEYCODE_MEDIA_PAUSE: 166 case AKEYCODE_MEDIA_PLAY_PAUSE: 167 case AKEYCODE_MEDIA_STOP: 168 case AKEYCODE_MEDIA_NEXT: 169 case AKEYCODE_MEDIA_PREVIOUS: 170 case AKEYCODE_MEDIA_REWIND: 171 case AKEYCODE_MEDIA_RECORD: 172 case AKEYCODE_MEDIA_FAST_FORWARD: 173 case AKEYCODE_MUTE: 174 return true; 175 } 176 177 return false; 178} 179 180bool KeyEvent::hasDefaultAction() const { 181 return hasDefaultAction(getKeyCode()); 182} 183 184bool KeyEvent::isSystemKey(int32_t keyCode) { 185 switch (keyCode) { 186 case AKEYCODE_MENU: 187 case AKEYCODE_SOFT_RIGHT: 188 case AKEYCODE_HOME: 189 case AKEYCODE_BACK: 190 case AKEYCODE_CALL: 191 case AKEYCODE_ENDCALL: 192 case AKEYCODE_VOLUME_UP: 193 case AKEYCODE_VOLUME_DOWN: 194 case AKEYCODE_VOLUME_MUTE: 195 case AKEYCODE_MUTE: 196 case AKEYCODE_POWER: 197 case AKEYCODE_HEADSETHOOK: 198 case AKEYCODE_MEDIA_PLAY: 199 case AKEYCODE_MEDIA_PAUSE: 200 case AKEYCODE_MEDIA_PLAY_PAUSE: 201 case AKEYCODE_MEDIA_STOP: 202 case AKEYCODE_MEDIA_NEXT: 203 case AKEYCODE_MEDIA_PREVIOUS: 204 case AKEYCODE_MEDIA_REWIND: 205 case AKEYCODE_MEDIA_RECORD: 206 case AKEYCODE_MEDIA_FAST_FORWARD: 207 case AKEYCODE_CAMERA: 208 case AKEYCODE_FOCUS: 209 case AKEYCODE_SEARCH: 210 return true; 211 } 212 213 return false; 214} 215 216bool KeyEvent::isSystemKey() const { 217 return isSystemKey(getKeyCode()); 218} 219 220void KeyEvent::initialize( 221 int32_t deviceId, 222 int32_t source, 223 int32_t action, 224 int32_t flags, 225 int32_t keyCode, 226 int32_t scanCode, 227 int32_t metaState, 228 int32_t repeatCount, 229 nsecs_t downTime, 230 nsecs_t eventTime) { 231 InputEvent::initialize(deviceId, source); 232 mAction = action; 233 mFlags = flags; 234 mKeyCode = keyCode; 235 mScanCode = scanCode; 236 mMetaState = metaState; 237 mRepeatCount = repeatCount; 238 mDownTime = downTime; 239 mEventTime = eventTime; 240} 241 242void KeyEvent::initialize(const KeyEvent& from) { 243 InputEvent::initialize(from); 244 mAction = from.mAction; 245 mFlags = from.mFlags; 246 mKeyCode = from.mKeyCode; 247 mScanCode = from.mScanCode; 248 mMetaState = from.mMetaState; 249 mRepeatCount = from.mRepeatCount; 250 mDownTime = from.mDownTime; 251 mEventTime = from.mEventTime; 252} 253 254 255// --- PointerCoords --- 256 257float PointerCoords::getAxisValue(int32_t axis) const { 258 if (axis < 0 || axis > 63) { 259 return 0; 260 } 261 262 uint64_t axisBit = 1LL << axis; 263 if (!(bits & axisBit)) { 264 return 0; 265 } 266 uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL)); 267 return values[index]; 268} 269 270status_t PointerCoords::setAxisValue(int32_t axis, float value) { 271 if (axis < 0 || axis > 63) { 272 return NAME_NOT_FOUND; 273 } 274 275 uint64_t axisBit = 1LL << axis; 276 uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL)); 277 if (!(bits & axisBit)) { 278 uint32_t count = __builtin_popcountll(bits); 279 if (count >= MAX_AXES) { 280 tooManyAxes(axis); 281 return NO_MEMORY; 282 } 283 bits |= axisBit; 284 for (uint32_t i = count; i > index; i--) { 285 values[i] = values[i - 1]; 286 } 287 } 288 values[index] = value; 289 return OK; 290} 291 292float* PointerCoords::editAxisValue(int32_t axis) { 293 if (axis < 0 || axis > 63) { 294 return NULL; 295 } 296 297 uint64_t axisBit = 1LL << axis; 298 if (!(bits & axisBit)) { 299 return NULL; 300 } 301 uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL)); 302 return &values[index]; 303} 304 305#ifdef HAVE_ANDROID_OS 306status_t PointerCoords::readFromParcel(Parcel* parcel) { 307 bits = parcel->readInt64(); 308 309 uint32_t count = __builtin_popcountll(bits); 310 if (count > MAX_AXES) { 311 return BAD_VALUE; 312 } 313 314 for (uint32_t i = 0; i < count; i++) { 315 values[i] = parcel->readInt32(); 316 } 317 return OK; 318} 319 320status_t PointerCoords::writeToParcel(Parcel* parcel) const { 321 parcel->writeInt64(bits); 322 323 uint32_t count = __builtin_popcountll(bits); 324 for (uint32_t i = 0; i < count; i++) { 325 parcel->writeInt32(values[i]); 326 } 327 return OK; 328} 329#endif 330 331void PointerCoords::tooManyAxes(int axis) { 332 LOGW("Could not set value for axis %d because the PointerCoords structure is full and " 333 "cannot contain more than %d axis values.", axis, int(MAX_AXES)); 334} 335 336bool PointerCoords::operator==(const PointerCoords& other) const { 337 if (bits != other.bits) { 338 return false; 339 } 340 uint32_t count = __builtin_popcountll(bits); 341 for (uint32_t i = 0; i < count; i++) { 342 if (values[i] != other.values[i]) { 343 return false; 344 } 345 } 346 return true; 347} 348 349void PointerCoords::copyFrom(const PointerCoords& other) { 350 bits = other.bits; 351 uint32_t count = __builtin_popcountll(bits); 352 for (uint32_t i = 0; i < count; i++) { 353 values[i] = other.values[i]; 354 } 355} 356 357 358// --- MotionEvent --- 359 360void MotionEvent::initialize( 361 int32_t deviceId, 362 int32_t source, 363 int32_t action, 364 int32_t flags, 365 int32_t edgeFlags, 366 int32_t metaState, 367 float xOffset, 368 float yOffset, 369 float xPrecision, 370 float yPrecision, 371 nsecs_t downTime, 372 nsecs_t eventTime, 373 size_t pointerCount, 374 const int32_t* pointerIds, 375 const PointerCoords* pointerCoords) { 376 InputEvent::initialize(deviceId, source); 377 mAction = action; 378 mFlags = flags; 379 mEdgeFlags = edgeFlags; 380 mMetaState = metaState; 381 mXOffset = xOffset; 382 mYOffset = yOffset; 383 mXPrecision = xPrecision; 384 mYPrecision = yPrecision; 385 mDownTime = downTime; 386 mPointerIds.clear(); 387 mPointerIds.appendArray(pointerIds, pointerCount); 388 mSampleEventTimes.clear(); 389 mSamplePointerCoords.clear(); 390 addSample(eventTime, pointerCoords); 391} 392 393void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) { 394 InputEvent::initialize(other->mDeviceId, other->mSource); 395 mAction = other->mAction; 396 mFlags = other->mFlags; 397 mEdgeFlags = other->mEdgeFlags; 398 mMetaState = other->mMetaState; 399 mXOffset = other->mXOffset; 400 mYOffset = other->mYOffset; 401 mXPrecision = other->mXPrecision; 402 mYPrecision = other->mYPrecision; 403 mDownTime = other->mDownTime; 404 mPointerIds = other->mPointerIds; 405 406 if (keepHistory) { 407 mSampleEventTimes = other->mSampleEventTimes; 408 mSamplePointerCoords = other->mSamplePointerCoords; 409 } else { 410 mSampleEventTimes.clear(); 411 mSampleEventTimes.push(other->getEventTime()); 412 mSamplePointerCoords.clear(); 413 size_t pointerCount = other->getPointerCount(); 414 size_t historySize = other->getHistorySize(); 415 mSamplePointerCoords.appendArray(other->mSamplePointerCoords.array() 416 + (historySize * pointerCount), pointerCount); 417 } 418} 419 420void MotionEvent::addSample( 421 int64_t eventTime, 422 const PointerCoords* pointerCoords) { 423 mSampleEventTimes.push(eventTime); 424 mSamplePointerCoords.appendArray(pointerCoords, getPointerCount()); 425} 426 427const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const { 428 return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex]; 429} 430 431float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const { 432 return getRawPointerCoords(pointerIndex)->getAxisValue(axis); 433} 434 435float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const { 436 float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis); 437 switch (axis) { 438 case AMOTION_EVENT_AXIS_X: 439 value += mXOffset; 440 break; 441 case AMOTION_EVENT_AXIS_Y: 442 value += mYOffset; 443 break; 444 } 445 return value; 446} 447 448const PointerCoords* MotionEvent::getHistoricalRawPointerCoords( 449 size_t pointerIndex, size_t historicalIndex) const { 450 return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex]; 451} 452 453float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex, 454 size_t historicalIndex) const { 455 return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis); 456} 457 458float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex, 459 size_t historicalIndex) const { 460 float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis); 461 switch (axis) { 462 case AMOTION_EVENT_AXIS_X: 463 value += mXOffset; 464 break; 465 case AMOTION_EVENT_AXIS_Y: 466 value += mYOffset; 467 break; 468 } 469 return value; 470} 471 472ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const { 473 size_t pointerCount = mPointerIds.size(); 474 for (size_t i = 0; i < pointerCount; i++) { 475 if (mPointerIds.itemAt(i) == pointerId) { 476 return i; 477 } 478 } 479 return -1; 480} 481 482void MotionEvent::offsetLocation(float xOffset, float yOffset) { 483 mXOffset += xOffset; 484 mYOffset += yOffset; 485} 486 487static inline void scaleAxisValue(PointerCoords& c, int axis, float scaleFactor) { 488 float* value = c.editAxisValue(axis); 489 if (value) { 490 *value *= scaleFactor; 491 } 492} 493 494void MotionEvent::scale(float scaleFactor) { 495 mXOffset *= scaleFactor; 496 mYOffset *= scaleFactor; 497 mXPrecision *= scaleFactor; 498 mYPrecision *= scaleFactor; 499 500 size_t numSamples = mSamplePointerCoords.size(); 501 for (size_t i = 0; i < numSamples; i++) { 502 PointerCoords& c = mSamplePointerCoords.editItemAt(i); 503 // No need to scale pressure or size since they are normalized. 504 // No need to scale orientation since it is meaningless to do so. 505 scaleAxisValue(c, AMOTION_EVENT_AXIS_X, scaleFactor); 506 scaleAxisValue(c, AMOTION_EVENT_AXIS_Y, scaleFactor); 507 scaleAxisValue(c, AMOTION_EVENT_AXIS_TOUCH_MAJOR, scaleFactor); 508 scaleAxisValue(c, AMOTION_EVENT_AXIS_TOUCH_MINOR, scaleFactor); 509 scaleAxisValue(c, AMOTION_EVENT_AXIS_TOOL_MAJOR, scaleFactor); 510 scaleAxisValue(c, AMOTION_EVENT_AXIS_TOOL_MINOR, scaleFactor); 511 } 512} 513 514#ifdef HAVE_ANDROID_OS 515static inline float transformAngle(const SkMatrix* matrix, float angleRadians) { 516 // Construct and transform a vector oriented at the specified clockwise angle from vertical. 517 // Coordinate system: down is increasing Y, right is increasing X. 518 SkPoint vector; 519 vector.fX = SkFloatToScalar(sinf(angleRadians)); 520 vector.fY = SkFloatToScalar(-cosf(angleRadians)); 521 matrix->mapVectors(& vector, 1); 522 523 // Derive the transformed vector's clockwise angle from vertical. 524 float result = atan2f(SkScalarToFloat(vector.fX), SkScalarToFloat(-vector.fY)); 525 if (result < - M_PI_2) { 526 result += M_PI; 527 } else if (result > M_PI_2) { 528 result -= M_PI; 529 } 530 return result; 531} 532 533void MotionEvent::transform(const SkMatrix* matrix) { 534 float oldXOffset = mXOffset; 535 float oldYOffset = mYOffset; 536 537 // The tricky part of this implementation is to preserve the value of 538 // rawX and rawY. So we apply the transformation to the first point 539 // then derive an appropriate new X/Y offset that will preserve rawX and rawY. 540 SkPoint point; 541 float rawX = getRawX(0); 542 float rawY = getRawY(0); 543 matrix->mapXY(SkFloatToScalar(rawX + oldXOffset), SkFloatToScalar(rawY + oldYOffset), 544 & point); 545 float newX = SkScalarToFloat(point.fX); 546 float newY = SkScalarToFloat(point.fY); 547 float newXOffset = newX - rawX; 548 float newYOffset = newY - rawY; 549 550 mXOffset = newXOffset; 551 mYOffset = newYOffset; 552 553 // Apply the transformation to all samples. 554 size_t numSamples = mSamplePointerCoords.size(); 555 for (size_t i = 0; i < numSamples; i++) { 556 PointerCoords& c = mSamplePointerCoords.editItemAt(i); 557 float* xPtr = c.editAxisValue(AMOTION_EVENT_AXIS_X); 558 float* yPtr = c.editAxisValue(AMOTION_EVENT_AXIS_Y); 559 if (xPtr && yPtr) { 560 float x = *xPtr + oldXOffset; 561 float y = *yPtr + oldYOffset; 562 matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), & point); 563 *xPtr = SkScalarToFloat(point.fX) - newXOffset; 564 *yPtr = SkScalarToFloat(point.fY) - newYOffset; 565 } 566 567 float* orientationPtr = c.editAxisValue(AMOTION_EVENT_AXIS_ORIENTATION); 568 if (orientationPtr) { 569 *orientationPtr = transformAngle(matrix, *orientationPtr); 570 } 571 } 572} 573 574status_t MotionEvent::readFromParcel(Parcel* parcel) { 575 size_t pointerCount = parcel->readInt32(); 576 size_t sampleCount = parcel->readInt32(); 577 if (pointerCount == 0 || pointerCount > MAX_POINTERS || sampleCount == 0) { 578 return BAD_VALUE; 579 } 580 581 mDeviceId = parcel->readInt32(); 582 mSource = parcel->readInt32(); 583 mAction = parcel->readInt32(); 584 mFlags = parcel->readInt32(); 585 mEdgeFlags = parcel->readInt32(); 586 mMetaState = parcel->readInt32(); 587 mXOffset = parcel->readFloat(); 588 mYOffset = parcel->readFloat(); 589 mXPrecision = parcel->readFloat(); 590 mYPrecision = parcel->readFloat(); 591 mDownTime = parcel->readInt64(); 592 593 mPointerIds.clear(); 594 mPointerIds.setCapacity(pointerCount); 595 mSampleEventTimes.clear(); 596 mSampleEventTimes.setCapacity(sampleCount); 597 mSamplePointerCoords.clear(); 598 mSamplePointerCoords.setCapacity(sampleCount * pointerCount); 599 600 for (size_t i = 0; i < pointerCount; i++) { 601 mPointerIds.push(parcel->readInt32()); 602 } 603 604 while (sampleCount-- > 0) { 605 mSampleEventTimes.push(parcel->readInt64()); 606 for (size_t i = 0; i < pointerCount; i++) { 607 mSamplePointerCoords.push(); 608 status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel); 609 if (status) { 610 return status; 611 } 612 } 613 } 614 return OK; 615} 616 617status_t MotionEvent::writeToParcel(Parcel* parcel) const { 618 size_t pointerCount = mPointerIds.size(); 619 size_t sampleCount = mSampleEventTimes.size(); 620 621 parcel->writeInt32(pointerCount); 622 parcel->writeInt32(sampleCount); 623 624 parcel->writeInt32(mDeviceId); 625 parcel->writeInt32(mSource); 626 parcel->writeInt32(mAction); 627 parcel->writeInt32(mFlags); 628 parcel->writeInt32(mEdgeFlags); 629 parcel->writeInt32(mMetaState); 630 parcel->writeFloat(mXOffset); 631 parcel->writeFloat(mYOffset); 632 parcel->writeFloat(mXPrecision); 633 parcel->writeFloat(mYPrecision); 634 parcel->writeInt64(mDownTime); 635 636 for (size_t i = 0; i < pointerCount; i++) { 637 parcel->writeInt32(mPointerIds.itemAt(i)); 638 } 639 640 const PointerCoords* pc = mSamplePointerCoords.array(); 641 for (size_t h = 0; h < sampleCount; h++) { 642 parcel->writeInt64(mSampleEventTimes.itemAt(h)); 643 for (size_t i = 0; i < pointerCount; i++) { 644 status_t status = (pc++)->writeToParcel(parcel); 645 if (status) { 646 return status; 647 } 648 } 649 } 650 return OK; 651} 652#endif 653 654bool MotionEvent::isTouchEvent(int32_t source, int32_t action) { 655 if (source & AINPUT_SOURCE_CLASS_POINTER) { 656 // Specifically excludes HOVER_MOVE and SCROLL. 657 switch (action & AMOTION_EVENT_ACTION_MASK) { 658 case AMOTION_EVENT_ACTION_DOWN: 659 case AMOTION_EVENT_ACTION_MOVE: 660 case AMOTION_EVENT_ACTION_UP: 661 case AMOTION_EVENT_ACTION_POINTER_DOWN: 662 case AMOTION_EVENT_ACTION_POINTER_UP: 663 case AMOTION_EVENT_ACTION_CANCEL: 664 case AMOTION_EVENT_ACTION_OUTSIDE: 665 return true; 666 } 667 } 668 return false; 669} 670 671 672// --- VelocityTracker --- 673 674VelocityTracker::VelocityTracker() { 675 clear(); 676} 677 678void VelocityTracker::clear() { 679 mIndex = 0; 680 mMovements[0].idBits.clear(); 681 mActivePointerId = -1; 682} 683 684void VelocityTracker::clearPointers(BitSet32 idBits) { 685 BitSet32 remainingIdBits(mMovements[mIndex].idBits.value & ~idBits.value); 686 mMovements[mIndex].idBits = remainingIdBits; 687 688 if (mActivePointerId >= 0 && idBits.hasBit(mActivePointerId)) { 689 mActivePointerId = !remainingIdBits.isEmpty() ? remainingIdBits.firstMarkedBit() : -1; 690 } 691} 692 693void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, const Position* positions) { 694 if (++mIndex == HISTORY_SIZE) { 695 mIndex = 0; 696 } 697 698 while (idBits.count() > MAX_POINTERS) { 699 idBits.clearBit(idBits.lastMarkedBit()); 700 } 701 702 Movement& movement = mMovements[mIndex]; 703 movement.eventTime = eventTime; 704 movement.idBits = idBits; 705 uint32_t count = idBits.count(); 706 for (uint32_t i = 0; i < count; i++) { 707 movement.positions[i] = positions[i]; 708 } 709 710 if (mActivePointerId < 0 || !idBits.hasBit(mActivePointerId)) { 711 mActivePointerId = count != 0 ? idBits.firstMarkedBit() : -1; 712 } 713 714#if DEBUG_VELOCITY 715 LOGD("VelocityTracker: addMovement eventTime=%lld, idBits=0x%08x, activePointerId=%d", 716 eventTime, idBits.value, mActivePointerId); 717 for (BitSet32 iterBits(idBits); !iterBits.isEmpty(); ) { 718 uint32_t id = iterBits.firstMarkedBit(); 719 uint32_t index = idBits.getIndexOfBit(id); 720 iterBits.clearBit(id); 721 float vx, vy; 722 bool available = getVelocity(id, &vx, &vy); 723 if (available) { 724 LOGD(" %d: position (%0.3f, %0.3f), vx=%0.3f, vy=%0.3f, speed=%0.3f", 725 id, positions[index].x, positions[index].y, vx, vy, sqrtf(vx * vx + vy * vy)); 726 } else { 727 assert(vx == 0 && vy == 0); 728 LOGD(" %d: position (%0.3f, %0.3f), velocity not available", 729 id, positions[index].x, positions[index].y); 730 } 731 } 732#endif 733} 734 735void VelocityTracker::addMovement(const MotionEvent* event) { 736 int32_t actionMasked = event->getActionMasked(); 737 738 switch (actionMasked) { 739 case AMOTION_EVENT_ACTION_DOWN: 740 // Clear all pointers on down before adding the new movement. 741 clear(); 742 break; 743 case AMOTION_EVENT_ACTION_POINTER_DOWN: { 744 // Start a new movement trace for a pointer that just went down. 745 // We do this on down instead of on up because the client may want to query the 746 // final velocity for a pointer that just went up. 747 BitSet32 downIdBits; 748 downIdBits.markBit(event->getActionIndex()); 749 clearPointers(downIdBits); 750 break; 751 } 752 case AMOTION_EVENT_ACTION_OUTSIDE: 753 case AMOTION_EVENT_ACTION_CANCEL: 754 case AMOTION_EVENT_ACTION_SCROLL: 755 case AMOTION_EVENT_ACTION_UP: 756 case AMOTION_EVENT_ACTION_POINTER_UP: 757 // Ignore these actions because they do not convey any new information about 758 // pointer movement. We also want to preserve the last known velocity of the pointers. 759 // Note that ACTION_UP and ACTION_POINTER_UP always report the last known position 760 // of the pointers that went up. ACTION_POINTER_UP does include the new position of 761 // pointers that remained down but we will also receive an ACTION_MOVE with this 762 // information if any of them actually moved. Since we don't know how many pointers 763 // will be going up at once it makes sense to just wait for the following ACTION_MOVE 764 // before adding the movement. 765 return; 766 } 767 768 size_t pointerCount = event->getPointerCount(); 769 if (pointerCount > MAX_POINTERS) { 770 pointerCount = MAX_POINTERS; 771 } 772 773 BitSet32 idBits; 774 for (size_t i = 0; i < pointerCount; i++) { 775 idBits.markBit(event->getPointerId(i)); 776 } 777 778 nsecs_t eventTime; 779 Position positions[pointerCount]; 780 781 size_t historySize = event->getHistorySize(); 782 for (size_t h = 0; h < historySize; h++) { 783 eventTime = event->getHistoricalEventTime(h); 784 for (size_t i = 0; i < pointerCount; i++) { 785 positions[i].x = event->getHistoricalX(i, h); 786 positions[i].y = event->getHistoricalY(i, h); 787 } 788 addMovement(eventTime, idBits, positions); 789 } 790 791 eventTime = event->getEventTime(); 792 for (size_t i = 0; i < pointerCount; i++) { 793 positions[i].x = event->getX(i); 794 positions[i].y = event->getY(i); 795 } 796 addMovement(eventTime, idBits, positions); 797} 798 799bool VelocityTracker::getVelocity(uint32_t id, float* outVx, float* outVy) const { 800 const Movement& newestMovement = mMovements[mIndex]; 801 if (newestMovement.idBits.hasBit(id)) { 802 // Find the oldest sample that contains the pointer and that is not older than MAX_AGE. 803 nsecs_t minTime = newestMovement.eventTime - MAX_AGE; 804 uint32_t oldestIndex = mIndex; 805 uint32_t numTouches = 1; 806 do { 807 uint32_t nextOldestIndex = (oldestIndex == 0 ? HISTORY_SIZE : oldestIndex) - 1; 808 const Movement& nextOldestMovement = mMovements[nextOldestIndex]; 809 if (!nextOldestMovement.idBits.hasBit(id) 810 || nextOldestMovement.eventTime < minTime) { 811 break; 812 } 813 oldestIndex = nextOldestIndex; 814 } while (++numTouches < HISTORY_SIZE); 815 816 // Calculate an exponentially weighted moving average of the velocity estimate 817 // at different points in time measured relative to the oldest sample. 818 // This is essentially an IIR filter. Newer samples are weighted more heavily 819 // than older samples. Samples at equal time points are weighted more or less 820 // equally. 821 // 822 // One tricky problem is that the sample data may be poorly conditioned. 823 // Sometimes samples arrive very close together in time which can cause us to 824 // overestimate the velocity at that time point. Most samples might be measured 825 // 16ms apart but some consecutive samples could be only 0.5sm apart because 826 // the hardware or driver reports them irregularly or in bursts. 827 float accumVx = 0; 828 float accumVy = 0; 829 uint32_t index = oldestIndex; 830 uint32_t samplesUsed = 0; 831 const Movement& oldestMovement = mMovements[oldestIndex]; 832 const Position& oldestPosition = 833 oldestMovement.positions[oldestMovement.idBits.getIndexOfBit(id)]; 834 nsecs_t lastDuration = 0; 835 while (numTouches-- > 1) { 836 if (++index == HISTORY_SIZE) { 837 index = 0; 838 } 839 const Movement& movement = mMovements[index]; 840 nsecs_t duration = movement.eventTime - oldestMovement.eventTime; 841 842 // If the duration between samples is small, we may significantly overestimate 843 // the velocity. Consequently, we impose a minimum duration constraint on the 844 // samples that we include in the calculation. 845 if (duration >= MIN_DURATION) { 846 const Position& position = movement.positions[movement.idBits.getIndexOfBit(id)]; 847 float scale = 1000000000.0f / duration; // one over time delta in seconds 848 float vx = (position.x - oldestPosition.x) * scale; 849 float vy = (position.y - oldestPosition.y) * scale; 850 851 accumVx = (accumVx * lastDuration + vx * duration) / (duration + lastDuration); 852 accumVy = (accumVy * lastDuration + vy * duration) / (duration + lastDuration); 853 854 lastDuration = duration; 855 samplesUsed += 1; 856 } 857 } 858 859 // Make sure we used at least one sample. 860 if (samplesUsed != 0) { 861 *outVx = accumVx; 862 *outVy = accumVy; 863 return true; 864 } 865 } 866 867 // No data available for this pointer. 868 *outVx = 0; 869 *outVy = 0; 870 return false; 871} 872 873 874// --- InputDeviceInfo --- 875 876InputDeviceInfo::InputDeviceInfo() { 877 initialize(-1, String8("uninitialized device info")); 878} 879 880InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) : 881 mId(other.mId), mName(other.mName), mSources(other.mSources), 882 mKeyboardType(other.mKeyboardType), 883 mMotionRanges(other.mMotionRanges) { 884} 885 886InputDeviceInfo::~InputDeviceInfo() { 887} 888 889void InputDeviceInfo::initialize(int32_t id, const String8& name) { 890 mId = id; 891 mName = name; 892 mSources = 0; 893 mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE; 894 mMotionRanges.clear(); 895} 896 897const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange( 898 int32_t axis, uint32_t source) const { 899 size_t numRanges = mMotionRanges.size(); 900 for (size_t i = 0; i < numRanges; i++) { 901 const MotionRange& range = mMotionRanges.itemAt(i); 902 if (range.axis == axis && range.source == source) { 903 return ⦥ 904 } 905 } 906 return NULL; 907} 908 909void InputDeviceInfo::addSource(uint32_t source) { 910 mSources |= source; 911} 912 913void InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max, 914 float flat, float fuzz) { 915 MotionRange range = { axis, source, min, max, flat, fuzz }; 916 mMotionRanges.add(range); 917} 918 919void InputDeviceInfo::addMotionRange(const MotionRange& range) { 920 mMotionRanges.add(range); 921} 922 923} // namespace android 924