Skip to content

Commit 9072940

Browse files
author
Jeff Brown
committed
Detect when pointer has stopped moving.
Some input devices do not generate ACTION_MOVE events while all pointers have stopped, thereby lulling the VelocityTracker into a false sense of complacency. Before handling the following sample, reset the VelocityTracker state so as not to be influenced by earlier samples before the pointer stopped. The velocity after stopping is assumed to be discontinuous. Bug: 6413587 Change-Id: I6387bc036ff141d083d3d17a89e37eeaa3188349
1 parent dcab190 commit 9072940

File tree

2 files changed

+30
-7
lines changed

2 files changed

+30
-7
lines changed

include/androidfw/VelocityTracker.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ class VelocityTracker {
3737
struct Estimator {
3838
static const size_t MAX_DEGREE = 2;
3939

40+
// Estimator time base.
41+
nsecs_t time;
42+
4043
// Polynomial coefficients describing motion in X and Y.
4144
float xCoeff[MAX_DEGREE + 1], yCoeff[MAX_DEGREE + 1];
4245

@@ -48,6 +51,7 @@ class VelocityTracker {
4851
float confidence;
4952

5053
inline void clear() {
54+
time = 0;
5155
degree = 0;
5256
confidence = 0;
5357
for (size_t i = 0; i <= MAX_DEGREE; i++) {
@@ -58,7 +62,6 @@ class VelocityTracker {
5862
};
5963

6064
VelocityTracker();
61-
VelocityTracker(VelocityTrackerStrategy* strategy);
6265
~VelocityTracker();
6366

6467
// Resets the velocity tracker state.
@@ -96,6 +99,7 @@ class VelocityTracker {
9699
inline BitSet32 getCurrentPointerIdBits() const { return mCurrentPointerIdBits; }
97100

98101
private:
102+
nsecs_t mLastEventTime;
99103
BitSet32 mCurrentPointerIdBits;
100104
int32_t mActivePointerId;
101105
VelocityTrackerStrategy* mStrategy;

libs/androidfw/VelocityTracker.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@
3333

3434
namespace android {
3535

36+
// Nanoseconds per milliseconds.
37+
static const nsecs_t NANOS_PER_MS = 1000000;
38+
39+
// Threshold for determining that a pointer has stopped moving.
40+
// Some input devices do not send ACTION_MOVE events in the case where a pointer has
41+
// stopped. We need to detect this case so that we can accurately predict the
42+
// velocity after the pointer starts moving again.
43+
static const nsecs_t ASSUME_POINTER_STOPPED_TIME = 40 * NANOS_PER_MS;
44+
45+
3646
static float vectorDot(const float* a, const float* b, uint32_t m) {
3747
float r = 0;
3848
while (m--) {
@@ -89,15 +99,10 @@ static String8 matrixToString(const float* a, uint32_t m, uint32_t n, bool rowMa
8999
// --- VelocityTracker ---
90100

91101
VelocityTracker::VelocityTracker() :
92-
mCurrentPointerIdBits(0), mActivePointerId(-1),
102+
mLastEventTime(0), mCurrentPointerIdBits(0), mActivePointerId(-1),
93103
mStrategy(new LeastSquaresVelocityTrackerStrategy()) {
94104
}
95105

96-
VelocityTracker::VelocityTracker(VelocityTrackerStrategy* strategy) :
97-
mCurrentPointerIdBits(0), mActivePointerId(-1),
98-
mStrategy(strategy) {
99-
}
100-
101106
VelocityTracker::~VelocityTracker() {
102107
delete mStrategy;
103108
}
@@ -125,6 +130,18 @@ void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, const Posi
125130
idBits.clearLastMarkedBit();
126131
}
127132

133+
if ((mCurrentPointerIdBits.value & idBits.value)
134+
&& eventTime >= mLastEventTime + ASSUME_POINTER_STOPPED_TIME) {
135+
#if DEBUG_VELOCITY
136+
ALOGD("VelocityTracker: stopped for %0.3f ms, clearing state.",
137+
(eventTime - mLastEventTime) * 0.000001f);
138+
#endif
139+
// We have not received any movements for too long. Assume that all pointers
140+
// have stopped.
141+
mStrategy->clear();
142+
}
143+
mLastEventTime = eventTime;
144+
128145
mCurrentPointerIdBits = idBits;
129146
if (mActivePointerId < 0 || !idBits.hasBit(mActivePointerId)) {
130147
mActivePointerId = idBits.isEmpty() ? -1 : idBits.firstMarkedBit();
@@ -467,6 +484,7 @@ bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id,
467484
uint32_t n = degree + 1;
468485
if (solveLeastSquares(time, x, m, n, outEstimator->xCoeff, &xdet)
469486
&& solveLeastSquares(time, y, m, n, outEstimator->yCoeff, &ydet)) {
487+
outEstimator->time = newestMovement.eventTime;
470488
outEstimator->degree = degree;
471489
outEstimator->confidence = xdet * ydet;
472490
#if DEBUG_LEAST_SQUARES
@@ -483,6 +501,7 @@ bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id,
483501
// No velocity data available for this pointer, but we do have its current position.
484502
outEstimator->xCoeff[0] = x[0];
485503
outEstimator->yCoeff[0] = y[0];
504+
outEstimator->time = newestMovement.eventTime;
486505
outEstimator->degree = 0;
487506
outEstimator->confidence = 1;
488507
return true;

0 commit comments

Comments
 (0)