Input.cpp revision ace13b17866dc9136aeecf6dfaf7077f37434469
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 472void MotionEvent::offsetLocation(float xOffset, float yOffset) { 473 mXOffset += xOffset; 474 mYOffset += yOffset; 475} 476 477static inline void scaleAxisValue(PointerCoords& c, int axis, float scaleFactor) { 478 float* value = c.editAxisValue(axis); 479 if (value) { 480 *value *= scaleFactor; 481 } 482} 483 484void MotionEvent::scale(float scaleFactor) { 485 mXOffset *= scaleFactor; 486 mYOffset *= scaleFactor; 487 mXPrecision *= scaleFactor; 488 mYPrecision *= scaleFactor; 489 490 size_t numSamples = mSamplePointerCoords.size(); 491 for (size_t i = 0; i < numSamples; i++) { 492 PointerCoords& c = mSamplePointerCoords.editItemAt(i); 493 // No need to scale pressure or size since they are normalized. 494 // No need to scale orientation since it is meaningless to do so. 495 scaleAxisValue(c, AMOTION_EVENT_AXIS_X, scaleFactor); 496 scaleAxisValue(c, AMOTION_EVENT_AXIS_Y, scaleFactor); 497 scaleAxisValue(c, AMOTION_EVENT_AXIS_TOUCH_MAJOR, scaleFactor); 498 scaleAxisValue(c, AMOTION_EVENT_AXIS_TOUCH_MINOR, scaleFactor); 499 scaleAxisValue(c, AMOTION_EVENT_AXIS_TOOL_MAJOR, scaleFactor); 500 scaleAxisValue(c, AMOTION_EVENT_AXIS_TOOL_MINOR, scaleFactor); 501 } 502} 503 504#ifdef HAVE_ANDROID_OS 505static inline float transformAngle(const SkMatrix* matrix, float angleRadians) { 506 // Construct and transform a vector oriented at the specified clockwise angle from vertical. 507 // Coordinate system: down is increasing Y, right is increasing X. 508 SkPoint vector; 509 vector.fX = SkFloatToScalar(sinf(angleRadians)); 510 vector.fY = SkFloatToScalar(-cosf(angleRadians)); 511 matrix->mapVectors(& vector, 1); 512 513 // Derive the transformed vector's clockwise angle from vertical. 514 float result = atan2f(SkScalarToFloat(vector.fX), SkScalarToFloat(-vector.fY)); 515 if (result < - M_PI_2) { 516 result += M_PI; 517 } else if (result > M_PI_2) { 518 result -= M_PI; 519 } 520 return result; 521} 522 523void MotionEvent::transform(const SkMatrix* matrix) { 524 float oldXOffset = mXOffset; 525 float oldYOffset = mYOffset; 526 527 // The tricky part of this implementation is to preserve the value of 528 // rawX and rawY. So we apply the transformation to the first point 529 // then derive an appropriate new X/Y offset that will preserve rawX and rawY. 530 SkPoint point; 531 float rawX = getRawX(0); 532 float rawY = getRawY(0); 533 matrix->mapXY(SkFloatToScalar(rawX + oldXOffset), SkFloatToScalar(rawY + oldYOffset), 534 & point); 535 float newX = SkScalarToFloat(point.fX); 536 float newY = SkScalarToFloat(point.fY); 537 float newXOffset = newX - rawX; 538 float newYOffset = newY - rawY; 539 540 mXOffset = newXOffset; 541 mYOffset = newYOffset; 542 543 // Apply the transformation to all samples. 544 size_t numSamples = mSamplePointerCoords.size(); 545 for (size_t i = 0; i < numSamples; i++) { 546 PointerCoords& c = mSamplePointerCoords.editItemAt(i); 547 float* xPtr = c.editAxisValue(AMOTION_EVENT_AXIS_X); 548 float* yPtr = c.editAxisValue(AMOTION_EVENT_AXIS_Y); 549 if (xPtr && yPtr) { 550 float x = *xPtr + oldXOffset; 551 float y = *yPtr + oldYOffset; 552 matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), & point); 553 *xPtr = SkScalarToFloat(point.fX) - newXOffset; 554 *yPtr = SkScalarToFloat(point.fY) - newYOffset; 555 } 556 557 float* orientationPtr = c.editAxisValue(AMOTION_EVENT_AXIS_ORIENTATION); 558 if (orientationPtr) { 559 *orientationPtr = transformAngle(matrix, *orientationPtr); 560 } 561 } 562} 563 564status_t MotionEvent::readFromParcel(Parcel* parcel) { 565 size_t pointerCount = parcel->readInt32(); 566 size_t sampleCount = parcel->readInt32(); 567 if (pointerCount == 0 || pointerCount > MAX_POINTERS || sampleCount == 0) { 568 return BAD_VALUE; 569 } 570 571 mDeviceId = parcel->readInt32(); 572 mSource = parcel->readInt32(); 573 mAction = parcel->readInt32(); 574 mFlags = parcel->readInt32(); 575 mEdgeFlags = parcel->readInt32(); 576 mMetaState = parcel->readInt32(); 577 mXOffset = parcel->readFloat(); 578 mYOffset = parcel->readFloat(); 579 mXPrecision = parcel->readFloat(); 580 mYPrecision = parcel->readFloat(); 581 mDownTime = parcel->readInt64(); 582 583 mPointerIds.clear(); 584 mPointerIds.setCapacity(pointerCount); 585 mSampleEventTimes.clear(); 586 mSampleEventTimes.setCapacity(sampleCount); 587 mSamplePointerCoords.clear(); 588 mSamplePointerCoords.setCapacity(sampleCount * pointerCount); 589 590 for (size_t i = 0; i < pointerCount; i++) { 591 mPointerIds.push(parcel->readInt32()); 592 } 593 594 while (sampleCount-- > 0) { 595 mSampleEventTimes.push(parcel->readInt64()); 596 for (size_t i = 0; i < pointerCount; i++) { 597 mSamplePointerCoords.push(); 598 status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel); 599 if (status) { 600 return status; 601 } 602 } 603 } 604 return OK; 605} 606 607status_t MotionEvent::writeToParcel(Parcel* parcel) const { 608 size_t pointerCount = mPointerIds.size(); 609 size_t sampleCount = mSampleEventTimes.size(); 610 611 parcel->writeInt32(pointerCount); 612 parcel->writeInt32(sampleCount); 613 614 parcel->writeInt32(mDeviceId); 615 parcel->writeInt32(mSource); 616 parcel->writeInt32(mAction); 617 parcel->writeInt32(mFlags); 618 parcel->writeInt32(mEdgeFlags); 619 parcel->writeInt32(mMetaState); 620 parcel->writeFloat(mXOffset); 621 parcel->writeFloat(mYOffset); 622 parcel->writeFloat(mXPrecision); 623 parcel->writeFloat(mYPrecision); 624 parcel->writeInt64(mDownTime); 625 626 for (size_t i = 0; i < pointerCount; i++) { 627 parcel->writeInt32(mPointerIds.itemAt(i)); 628 } 629 630 const PointerCoords* pc = mSamplePointerCoords.array(); 631 for (size_t h = 0; h < sampleCount; h++) { 632 parcel->writeInt64(mSampleEventTimes.itemAt(h)); 633 for (size_t i = 0; i < pointerCount; i++) { 634 status_t status = (pc++)->writeToParcel(parcel); 635 if (status) { 636 return status; 637 } 638 } 639 } 640 return OK; 641} 642#endif 643 644bool MotionEvent::isTouchEvent(int32_t source, int32_t action) { 645 if (source & AINPUT_SOURCE_CLASS_POINTER) { 646 // Specifically excludes HOVER_MOVE and SCROLL. 647 switch (action & AMOTION_EVENT_ACTION_MASK) { 648 case AMOTION_EVENT_ACTION_DOWN: 649 case AMOTION_EVENT_ACTION_MOVE: 650 case AMOTION_EVENT_ACTION_UP: 651 case AMOTION_EVENT_ACTION_POINTER_DOWN: 652 case AMOTION_EVENT_ACTION_POINTER_UP: 653 case AMOTION_EVENT_ACTION_CANCEL: 654 case AMOTION_EVENT_ACTION_OUTSIDE: 655 return true; 656 } 657 } 658 return false; 659} 660 661 662// --- VelocityTracker --- 663 664VelocityTracker::VelocityTracker() { 665 clear(); 666} 667 668void VelocityTracker::clear() { 669 mIndex = 0; 670 mMovements[0].idBits.clear(); 671} 672 673void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, const Position* positions) { 674 if (++mIndex == HISTORY_SIZE) { 675 mIndex = 0; 676 } 677 Movement& movement = mMovements[mIndex]; 678 movement.eventTime = eventTime; 679 movement.idBits = idBits; 680 uint32_t count = idBits.count(); 681 for (uint32_t i = 0; i < count; i++) { 682 movement.positions[i] = positions[i]; 683 } 684 685#if DEBUG_VELOCITY 686 LOGD("VelocityTracker: addMovement eventTime=%lld, idBits=0x%08x", eventTime, idBits.value); 687 for (BitSet32 iterBits(idBits); !iterBits.isEmpty(); ) { 688 uint32_t id = iterBits.firstMarkedBit(); 689 uint32_t index = idBits.getIndexOfBit(id); 690 iterBits.clearBit(id); 691 float vx, vy; 692 bool available = getVelocity(id, &vx, &vy); 693 if (available) { 694 LOGD(" %d: position (%0.3f, %0.3f), velocity (%0.3f, %0.3f), speed %0.3f", 695 id, positions[index].x, positions[index].y, vx, vy, sqrtf(vx * vx + vy * vy)); 696 } else { 697 assert(vx == 0 && vy == 0); 698 LOGD(" %d: position (%0.3f, %0.3f), velocity not available", 699 id, positions[index].x, positions[index].y); 700 } 701 } 702#endif 703} 704 705bool VelocityTracker::getVelocity(uint32_t id, float* outVx, float* outVy) const { 706 const Movement& newestMovement = mMovements[mIndex]; 707 if (newestMovement.idBits.hasBit(id)) { 708 // Find the oldest sample that contains the pointer and that is not older than MAX_AGE. 709 nsecs_t minTime = newestMovement.eventTime - MAX_AGE; 710 uint32_t oldestIndex = mIndex; 711 uint32_t numTouches = 1; 712 do { 713 uint32_t nextOldestIndex = (oldestIndex == 0 ? HISTORY_SIZE : oldestIndex) - 1; 714 const Movement& nextOldestMovement = mMovements[nextOldestIndex]; 715 if (!nextOldestMovement.idBits.hasBit(id) 716 || nextOldestMovement.eventTime < minTime) { 717 break; 718 } 719 oldestIndex = nextOldestIndex; 720 } while (++numTouches < HISTORY_SIZE); 721 722 // If we have a lot of samples, skip the last received sample since it is 723 // probably pretty noisy compared to the sum of all of the traces already acquired. 724 // 725 // NOTE: This condition exists in the android.view.VelocityTracker and imposes a 726 // bias against the most recent data. 727 if (numTouches > 3) { 728 numTouches -= 1; 729 } 730 731 // Calculate an exponentially weighted moving average of the velocity at different 732 // points in time measured relative to the oldest samples. This is essentially 733 // an IIR filter. 734 // 735 // One problem with this algorithm is that the sample data may be poorly conditioned. 736 // Sometimes samples arrive very close together in time which can cause us to 737 // overestimate the velocity at that time point. Most samples might be measured 738 // 16ms apart but some consecutive samples could be only 0.5sm apart due to 739 // the way they are reported by the hardware or driver (sometimes in bursts or with 740 // significant jitter). The instantaneous velocity for those samples 0.5ms apart will 741 // be calculated to be 32 times what it should have been. 742 // To work around this effect, we impose a minimum duration on the samples. 743 // 744 // FIXME: Samples close together in time can have an disproportionately large 745 // impact on the result because all samples are equally weighted. The average should 746 // instead take the time factor into account. 747 // 748 // FIXME: The minimum duration condition does not exist in 749 // android.view.VelocityTracker yet. It is less important there because sample times 750 // are truncated to the millisecond so back to back samples will often appear to be 751 // zero milliseconds apart and will be ignored if they are the oldest ones. 752 float accumVx = 0; 753 float accumVy = 0; 754 uint32_t index = oldestIndex; 755 uint32_t samplesUsed = 0; 756 const Movement& oldestMovement = mMovements[oldestIndex]; 757 const Position& oldestPosition = 758 oldestMovement.positions[oldestMovement.idBits.getIndexOfBit(id)]; 759 while (numTouches-- > 1) { 760 if (++index == HISTORY_SIZE) { 761 index = 0; 762 } 763 const Movement& movement = mMovements[index]; 764 nsecs_t duration = movement.eventTime - oldestMovement.eventTime; 765 if (duration > MIN_DURATION) { 766 const Position& position = movement.positions[movement.idBits.getIndexOfBit(id)]; 767 float scale = 1000000000.0f / duration; // one over time delta in seconds 768 float vx = (position.x - oldestPosition.x) * scale; 769 float vy = (position.y - oldestPosition.y) * scale; 770 accumVx = accumVx == 0 ? vx : (accumVx + vx) * 0.5f; 771 accumVy = accumVy == 0 ? vy : (accumVy + vy) * 0.5f; 772 samplesUsed += 1; 773 } 774 } 775 776 // Make sure we used at least one sample. 777 if (samplesUsed != 0) { 778 *outVx = accumVx; 779 *outVy = accumVy; 780 return true; 781 } 782 } 783 784 // No data available for this pointer. 785 *outVx = 0; 786 *outVy = 0; 787 return false; 788} 789 790 791// --- InputDeviceInfo --- 792 793InputDeviceInfo::InputDeviceInfo() { 794 initialize(-1, String8("uninitialized device info")); 795} 796 797InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) : 798 mId(other.mId), mName(other.mName), mSources(other.mSources), 799 mKeyboardType(other.mKeyboardType), 800 mMotionRanges(other.mMotionRanges) { 801} 802 803InputDeviceInfo::~InputDeviceInfo() { 804} 805 806void InputDeviceInfo::initialize(int32_t id, const String8& name) { 807 mId = id; 808 mName = name; 809 mSources = 0; 810 mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE; 811 mMotionRanges.clear(); 812} 813 814const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange( 815 int32_t axis, uint32_t source) const { 816 size_t numRanges = mMotionRanges.size(); 817 for (size_t i = 0; i < numRanges; i++) { 818 const MotionRange& range = mMotionRanges.itemAt(i); 819 if (range.axis == axis && range.source == source) { 820 return ⦥ 821 } 822 } 823 return NULL; 824} 825 826void InputDeviceInfo::addSource(uint32_t source) { 827 mSources |= source; 828} 829 830void InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max, 831 float flat, float fuzz) { 832 MotionRange range = { axis, source, min, max, flat, fuzz }; 833 mMotionRanges.add(range); 834} 835 836void InputDeviceInfo::addMotionRange(const MotionRange& range) { 837 mMotionRanges.add(range); 838} 839 840} // namespace android 841