summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2012-05-14 18:46:18 -0700
committerJeff Brown <jeffbrown@google.com>2012-05-14 18:57:05 -0700
commit90729403d50488566eb4ae0e09bb1be21979a633 (patch)
tree52f3abce5411493e204de30f273bfa955c95af59
parentdcab190bd23f632f278af448b0c85b4cadcc6692 (diff)
downloadframeworks_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.h6
-rw-r--r--libs/androidfw/VelocityTracker.cpp31
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;