From 90729403d50488566eb4ae0e09bb1be21979a633 Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Mon, 14 May 2012 18:46:18 -0700 Subject: [PATCH] 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 --- include/androidfw/VelocityTracker.h | 6 +++++- libs/androidfw/VelocityTracker.cpp | 31 +++++++++++++++++++++++++------ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/include/androidfw/VelocityTracker.h b/include/androidfw/VelocityTracker.h index 69645889dc92..cbb078299c2e 100644 --- a/include/androidfw/VelocityTracker.h +++ b/include/androidfw/VelocityTracker.h @@ -37,6 +37,9 @@ public: struct Estimator { static const size_t MAX_DEGREE = 2; + // Estimator time base. + nsecs_t time; + // Polynomial coefficients describing motion in X and Y. float xCoeff[MAX_DEGREE + 1], yCoeff[MAX_DEGREE + 1]; @@ -48,6 +51,7 @@ public: float confidence; inline void clear() { + time = 0; degree = 0; confidence = 0; for (size_t i = 0; i <= MAX_DEGREE; i++) { @@ -58,7 +62,6 @@ public: }; VelocityTracker(); - VelocityTracker(VelocityTrackerStrategy* strategy); ~VelocityTracker(); // Resets the velocity tracker state. @@ -96,6 +99,7 @@ public: inline BitSet32 getCurrentPointerIdBits() const { return mCurrentPointerIdBits; } private: + nsecs_t mLastEventTime; BitSet32 mCurrentPointerIdBits; int32_t mActivePointerId; VelocityTrackerStrategy* mStrategy; diff --git a/libs/androidfw/VelocityTracker.cpp b/libs/androidfw/VelocityTracker.cpp index a212948f5631..5dbafd8ebafb 100644 --- a/libs/androidfw/VelocityTracker.cpp +++ b/libs/androidfw/VelocityTracker.cpp @@ -33,6 +33,16 @@ namespace android { +// Nanoseconds per milliseconds. +static const nsecs_t NANOS_PER_MS = 1000000; + +// Threshold for determining that a pointer has stopped moving. +// Some input devices do not send ACTION_MOVE events in the case where a pointer has +// stopped. We need to detect this case so that we can accurately predict the +// velocity after the pointer starts moving again. +static const nsecs_t ASSUME_POINTER_STOPPED_TIME = 40 * NANOS_PER_MS; + + static float vectorDot(const float* a, const float* b, uint32_t m) { float r = 0; while (m--) { @@ -89,15 +99,10 @@ static String8 matrixToString(const float* a, uint32_t m, uint32_t n, bool rowMa // --- VelocityTracker --- VelocityTracker::VelocityTracker() : - mCurrentPointerIdBits(0), mActivePointerId(-1), + mLastEventTime(0), mCurrentPointerIdBits(0), mActivePointerId(-1), mStrategy(new LeastSquaresVelocityTrackerStrategy()) { } -VelocityTracker::VelocityTracker(VelocityTrackerStrategy* strategy) : - mCurrentPointerIdBits(0), mActivePointerId(-1), - mStrategy(strategy) { -} - VelocityTracker::~VelocityTracker() { delete mStrategy; } @@ -125,6 +130,18 @@ void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, const Posi idBits.clearLastMarkedBit(); } + if ((mCurrentPointerIdBits.value & idBits.value) + && eventTime >= mLastEventTime + ASSUME_POINTER_STOPPED_TIME) { +#if DEBUG_VELOCITY + ALOGD("VelocityTracker: stopped for %0.3f ms, clearing state.", + (eventTime - mLastEventTime) * 0.000001f); +#endif + // We have not received any movements for too long. Assume that all pointers + // have stopped. + mStrategy->clear(); + } + mLastEventTime = eventTime; + mCurrentPointerIdBits = idBits; if (mActivePointerId < 0 || !idBits.hasBit(mActivePointerId)) { mActivePointerId = idBits.isEmpty() ? -1 : idBits.firstMarkedBit(); @@ -467,6 +484,7 @@ bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id, uint32_t n = degree + 1; if (solveLeastSquares(time, x, m, n, outEstimator->xCoeff, &xdet) && solveLeastSquares(time, y, m, n, outEstimator->yCoeff, &ydet)) { + outEstimator->time = newestMovement.eventTime; outEstimator->degree = degree; outEstimator->confidence = xdet * ydet; #if DEBUG_LEAST_SQUARES @@ -483,6 +501,7 @@ bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id, // No velocity data available for this pointer, but we do have its current position. outEstimator->xCoeff[0] = x[0]; outEstimator->yCoeff[0] = y[0]; + outEstimator->time = newestMovement.eventTime; outEstimator->degree = 0; outEstimator->confidence = 1; return true; -- 2.11.0