diff options
author | Jeff Brown <jeffbrown@google.com> | 2012-05-14 18:46:18 -0700 |
---|---|---|
committer | Jeff Brown <jeffbrown@google.com> | 2012-05-14 18:57:05 -0700 |
commit | 90729403d50488566eb4ae0e09bb1be21979a633 (patch) | |
tree | 52f3abce5411493e204de30f273bfa955c95af59 | |
parent | dcab190bd23f632f278af448b0c85b4cadcc6692 (diff) | |
download | frameworks_base-90729403d50488566eb4ae0e09bb1be21979a633.zip frameworks_base-90729403d50488566eb4ae0e09bb1be21979a633.tar.gz frameworks_base-90729403d50488566eb4ae0e09bb1be21979a633.tar.bz2 |
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
-rw-r--r-- | include/androidfw/VelocityTracker.h | 6 | ||||
-rw-r--r-- | 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 6964588..cbb0782 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 a212948..5dbafd8 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; |