Skip to content

Commit 0e23c2e

Browse files
Jeff BrownAndroid (Google) Code Review
authored andcommitted
Merge "Tweak VelocityTracker. Bug: 5265529"
2 parents 5132273 + 581761d commit 0e23c2e

File tree

2 files changed

+36
-64
lines changed

2 files changed

+36
-64
lines changed

include/ui/Input.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,15 +660,19 @@ class VelocityTracker {
660660
static const uint32_t HISTORY_SIZE = 10;
661661

662662
// Oldest sample to consider when calculating the velocity.
663-
static const nsecs_t MAX_AGE = 200 * 1000000; // 200 ms
663+
static const nsecs_t MAX_AGE = 100 * 1000000; // 100 ms
664664

665665
// The minimum duration between samples when estimating velocity.
666-
static const nsecs_t MIN_DURATION = 10 * 1000000; // 10 ms
666+
static const nsecs_t MIN_DURATION = 5 * 1000000; // 5 ms
667667

668668
struct Movement {
669669
nsecs_t eventTime;
670670
BitSet32 idBits;
671671
Position positions[MAX_POINTERS];
672+
673+
inline const Position& getPosition(uint32_t id) const {
674+
return positions[idBits.getIndexOfBit(id)];
675+
}
672676
};
673677

674678
uint32_t mIndex;

libs/ui/Input.cpp

Lines changed: 30 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,7 @@ void VelocityTracker::addMovement(const MotionEvent* event) {
752752

753753
switch (actionMasked) {
754754
case AMOTION_EVENT_ACTION_DOWN:
755+
case AMOTION_EVENT_ACTION_HOVER_ENTER:
755756
// Clear all pointers on down before adding the new movement.
756757
clear();
757758
break;
@@ -764,12 +765,11 @@ void VelocityTracker::addMovement(const MotionEvent* event) {
764765
clearPointers(downIdBits);
765766
break;
766767
}
767-
case AMOTION_EVENT_ACTION_OUTSIDE:
768-
case AMOTION_EVENT_ACTION_CANCEL:
769-
case AMOTION_EVENT_ACTION_SCROLL:
770-
case AMOTION_EVENT_ACTION_UP:
771-
case AMOTION_EVENT_ACTION_POINTER_UP:
772-
// Ignore these actions because they do not convey any new information about
768+
case AMOTION_EVENT_ACTION_MOVE:
769+
case AMOTION_EVENT_ACTION_HOVER_MOVE:
770+
break;
771+
default:
772+
// Ignore all other actions because they do not convey any new information about
773773
// pointer movement. We also want to preserve the last known velocity of the pointers.
774774
// Note that ACTION_UP and ACTION_POINTER_UP always report the last known position
775775
// of the pointers that went up. ACTION_POINTER_UP does include the new position of
@@ -814,68 +814,36 @@ void VelocityTracker::addMovement(const MotionEvent* event) {
814814
bool VelocityTracker::getVelocity(uint32_t id, float* outVx, float* outVy) const {
815815
const Movement& newestMovement = mMovements[mIndex];
816816
if (newestMovement.idBits.hasBit(id)) {
817-
// Find the oldest sample that contains the pointer and that is not older than MAX_AGE.
818-
nsecs_t minTime = newestMovement.eventTime - MAX_AGE;
819-
uint32_t oldestIndex = mIndex;
820-
uint32_t numTouches = 1;
821-
do {
822-
uint32_t nextOldestIndex = (oldestIndex == 0 ? HISTORY_SIZE : oldestIndex) - 1;
823-
const Movement& nextOldestMovement = mMovements[nextOldestIndex];
824-
if (!nextOldestMovement.idBits.hasBit(id)
825-
|| nextOldestMovement.eventTime < minTime) {
826-
break;
827-
}
828-
oldestIndex = nextOldestIndex;
829-
} while (++numTouches < HISTORY_SIZE);
830-
831-
// Calculate an exponentially weighted moving average of the velocity estimate
832-
// at different points in time measured relative to the oldest sample.
833-
// This is essentially an IIR filter. Newer samples are weighted more heavily
834-
// than older samples. Samples at equal time points are weighted more or less
835-
// equally.
836-
//
837-
// One tricky problem is that the sample data may be poorly conditioned.
838-
// Sometimes samples arrive very close together in time which can cause us to
839-
// overestimate the velocity at that time point. Most samples might be measured
840-
// 16ms apart but some consecutive samples could be only 0.5sm apart because
841-
// the hardware or driver reports them irregularly or in bursts.
817+
const Position& newestPosition = newestMovement.getPosition(id);
842818
float accumVx = 0;
843819
float accumVy = 0;
844-
uint32_t index = oldestIndex;
845-
uint32_t samplesUsed = 0;
846-
const Movement& oldestMovement = mMovements[oldestIndex];
847-
const Position& oldestPosition =
848-
oldestMovement.positions[oldestMovement.idBits.getIndexOfBit(id)];
849-
nsecs_t lastDuration = 0;
850-
851-
while (numTouches-- > 1) {
852-
if (++index == HISTORY_SIZE) {
853-
index = 0;
854-
}
820+
float duration = 0;
821+
822+
// Iterate over movement samples in reverse time order and accumulate velocity.
823+
uint32_t index = mIndex;
824+
do {
825+
index = (index == 0 ? HISTORY_SIZE : index) - 1;
855826
const Movement& movement = mMovements[index];
856-
nsecs_t duration = movement.eventTime - oldestMovement.eventTime;
857-
858-
// If the duration between samples is small, we may significantly overestimate
859-
// the velocity. Consequently, we impose a minimum duration constraint on the
860-
// samples that we include in the calculation.
861-
if (duration >= MIN_DURATION) {
862-
const Position& position = movement.positions[movement.idBits.getIndexOfBit(id)];
863-
float scale = 1000000000.0f / duration; // one over time delta in seconds
864-
float vx = (position.x - oldestPosition.x) * scale;
865-
float vy = (position.y - oldestPosition.y) * scale;
866-
867-
accumVx = (accumVx * lastDuration + vx * duration) / (duration + lastDuration);
868-
accumVy = (accumVy * lastDuration + vy * duration) / (duration + lastDuration);
869-
870-
lastDuration = duration;
871-
samplesUsed += 1;
827+
if (!movement.idBits.hasBit(id)) {
828+
break;
872829
}
873-
}
830+
831+
nsecs_t age = newestMovement.eventTime - movement.eventTime;
832+
if (age > MAX_AGE) {
833+
break;
834+
}
835+
836+
const Position& position = movement.getPosition(id);
837+
accumVx += newestPosition.x - position.x;
838+
accumVy += newestPosition.y - position.y;
839+
duration += age;
840+
} while (index != mIndex);
874841

875842
// Make sure we used at least one sample.
876-
if (samplesUsed != 0) {
877-
*outVx = accumVx;
878-
*outVy = accumVy;
843+
if (duration >= MIN_DURATION) {
844+
float scale = 1000000000.0f / duration; // one over time delta in seconds
845+
*outVx = accumVx * scale;
846+
*outVy = accumVy * scale;
879847
return true;
880848
}
881849
}

0 commit comments

Comments
 (0)