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