summaryrefslogtreecommitdiffstats
path: root/libs/androidfw
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2012-06-04 13:13:34 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2012-06-04 13:13:34 -0700
commit78f04a364f8cd7dc3a7a0aaf73c96a6cc84718b6 (patch)
tree8b292f7d036f30087f535c3f617c8aef13b6c8ef /libs/androidfw
parentba58221769575d1129c61fe0da9030986eb899bd (diff)
parent51df04b93e8e362edd867abd7efaf1659b8b8b82 (diff)
downloadframeworks_base-78f04a364f8cd7dc3a7a0aaf73c96a6cc84718b6.zip
frameworks_base-78f04a364f8cd7dc3a7a0aaf73c96a6cc84718b6.tar.gz
frameworks_base-78f04a364f8cd7dc3a7a0aaf73c96a6cc84718b6.tar.bz2
am 51df04b9: Port the legacy velocity tracker strategy.
* commit '51df04b93e8e362edd867abd7efaf1659b8b8b82': Port the legacy velocity tracker strategy.
Diffstat (limited to 'libs/androidfw')
-rw-r--r--libs/androidfw/VelocityTracker.cpp126
1 files changed, 126 insertions, 0 deletions
diff --git a/libs/androidfw/VelocityTracker.cpp b/libs/androidfw/VelocityTracker.cpp
index fc75576..f48ec62 100644
--- a/libs/androidfw/VelocityTracker.cpp
+++ b/libs/androidfw/VelocityTracker.cpp
@@ -190,6 +190,13 @@ VelocityTrackerStrategy* VelocityTracker::createStrategy(const char* strategy) {
// for acceleration but it typically overestimates the effect.
return new IntegratingVelocityTrackerStrategy(2);
}
+ if (!strcmp("legacy", strategy)) {
+ // Legacy velocity tracker algorithm. Quality: POOR.
+ // For comparison purposes only. This algorithm is strongly influenced by
+ // old data points, consistently underestimates velocity and takes a very long
+ // time to adjust to changes in direction.
+ return new LegacyVelocityTrackerStrategy();
+ }
return NULL;
}
@@ -799,4 +806,123 @@ void IntegratingVelocityTrackerStrategy::populateEstimator(const State& state,
outEstimator->yCoeff[2] = state.yaccel / 2;
}
+
+// --- LegacyVelocityTrackerStrategy ---
+
+const nsecs_t LegacyVelocityTrackerStrategy::HORIZON;
+const uint32_t LegacyVelocityTrackerStrategy::HISTORY_SIZE;
+const nsecs_t LegacyVelocityTrackerStrategy::MIN_DURATION;
+
+LegacyVelocityTrackerStrategy::LegacyVelocityTrackerStrategy() {
+ clear();
+}
+
+LegacyVelocityTrackerStrategy::~LegacyVelocityTrackerStrategy() {
+}
+
+void LegacyVelocityTrackerStrategy::clear() {
+ mIndex = 0;
+ mMovements[0].idBits.clear();
+}
+
+void LegacyVelocityTrackerStrategy::clearPointers(BitSet32 idBits) {
+ BitSet32 remainingIdBits(mMovements[mIndex].idBits.value & ~idBits.value);
+ mMovements[mIndex].idBits = remainingIdBits;
+}
+
+void LegacyVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet32 idBits,
+ const VelocityTracker::Position* positions) {
+ if (++mIndex == HISTORY_SIZE) {
+ mIndex = 0;
+ }
+
+ Movement& movement = mMovements[mIndex];
+ movement.eventTime = eventTime;
+ movement.idBits = idBits;
+ uint32_t count = idBits.count();
+ for (uint32_t i = 0; i < count; i++) {
+ movement.positions[i] = positions[i];
+ }
+}
+
+bool LegacyVelocityTrackerStrategy::getEstimator(uint32_t id,
+ VelocityTracker::Estimator* outEstimator) const {
+ outEstimator->clear();
+
+ const Movement& newestMovement = mMovements[mIndex];
+ if (!newestMovement.idBits.hasBit(id)) {
+ return false; // no data
+ }
+
+ // Find the oldest sample that contains the pointer and that is not older than HORIZON.
+ nsecs_t minTime = newestMovement.eventTime - HORIZON;
+ uint32_t oldestIndex = mIndex;
+ uint32_t numTouches = 1;
+ do {
+ uint32_t nextOldestIndex = (oldestIndex == 0 ? HISTORY_SIZE : oldestIndex) - 1;
+ const Movement& nextOldestMovement = mMovements[nextOldestIndex];
+ if (!nextOldestMovement.idBits.hasBit(id)
+ || nextOldestMovement.eventTime < minTime) {
+ break;
+ }
+ oldestIndex = nextOldestIndex;
+ } while (++numTouches < HISTORY_SIZE);
+
+ // Calculate an exponentially weighted moving average of the velocity estimate
+ // at different points in time measured relative to the oldest sample.
+ // This is essentially an IIR filter. Newer samples are weighted more heavily
+ // than older samples. Samples at equal time points are weighted more or less
+ // equally.
+ //
+ // One tricky problem is that the sample data may be poorly conditioned.
+ // Sometimes samples arrive very close together in time which can cause us to
+ // overestimate the velocity at that time point. Most samples might be measured
+ // 16ms apart but some consecutive samples could be only 0.5sm apart because
+ // the hardware or driver reports them irregularly or in bursts.
+ float accumVx = 0;
+ float accumVy = 0;
+ uint32_t index = oldestIndex;
+ uint32_t samplesUsed = 0;
+ const Movement& oldestMovement = mMovements[oldestIndex];
+ const VelocityTracker::Position& oldestPosition = oldestMovement.getPosition(id);
+ nsecs_t lastDuration = 0;
+
+ while (numTouches-- > 1) {
+ if (++index == HISTORY_SIZE) {
+ index = 0;
+ }
+ const Movement& movement = mMovements[index];
+ nsecs_t duration = movement.eventTime - oldestMovement.eventTime;
+
+ // If the duration between samples is small, we may significantly overestimate
+ // the velocity. Consequently, we impose a minimum duration constraint on the
+ // samples that we include in the calculation.
+ if (duration >= MIN_DURATION) {
+ const VelocityTracker::Position& position = movement.getPosition(id);
+ float scale = 1000000000.0f / duration; // one over time delta in seconds
+ float vx = (position.x - oldestPosition.x) * scale;
+ float vy = (position.y - oldestPosition.y) * scale;
+ accumVx = (accumVx * lastDuration + vx * duration) / (duration + lastDuration);
+ accumVy = (accumVy * lastDuration + vy * duration) / (duration + lastDuration);
+ lastDuration = duration;
+ samplesUsed += 1;
+ }
+ }
+
+ // Report velocity.
+ const VelocityTracker::Position& newestPosition = newestMovement.getPosition(id);
+ outEstimator->time = newestMovement.eventTime;
+ outEstimator->confidence = 1;
+ outEstimator->xCoeff[0] = newestPosition.x;
+ outEstimator->yCoeff[0] = newestPosition.y;
+ if (samplesUsed) {
+ outEstimator->xCoeff[1] = accumVx;
+ outEstimator->yCoeff[1] = accumVy;
+ outEstimator->degree = 1;
+ } else {
+ outEstimator->degree = 0;
+ }
+ return true;
+}
+
} // namespace android