summaryrefslogtreecommitdiffstats
path: root/packages/SystemUI/src/com/android/systemui/statusbar/phone
diff options
context:
space:
mode:
authorDaniel Sandler <dsandler@android.com>2012-11-30 15:28:38 -0500
committerDaniel Sandler <dsandler@android.com>2012-11-30 15:28:38 -0500
commit6f7654d6658f1bd0eb9e6658aaf77aae23ac26df (patch)
tree8683557f275eec8987bc4235653b5077d55e9973 /packages/SystemUI/src/com/android/systemui/statusbar/phone
parentbf0e106a7d755355d7ff53a2b319e2e91c154641 (diff)
downloadframeworks_base-6f7654d6658f1bd0eb9e6658aaf77aae23ac26df.zip
frameworks_base-6f7654d6658f1bd0eb9e6658aaf77aae23ac26df.tar.gz
frameworks_base-6f7654d6658f1bd0eb9e6658aaf77aae23ac26df.tar.bz2
Reduce false swipe-closed gestures in status bar panels.
VelocityTracker is a powerful tool---too powerful, in this case, because many devices (I'm looking at you, Nexus 7) have touchscreens that report total garbage on takeoff and landing. PanelView now uses its own incredibly crude velocity tracker called FlingTracker, which implements a short sliding window of the last 8 motion events (7 intervals) over which touch velocity is averaged. There's also a little bias toward more recent touch events so that the overall velocity of small circular gestures will tend to favor the exit tangent. The end result is a primitive low-pass filter on touch velocity that should help us avoid situations where one (or even two!) stray MotionEvents at the end of a gesture won't invalidate the overall thrust. Bug: 7422342 Change-Id: Idae38d1957727e400493324af4eee357ba5baa27
Diffstat (limited to 'packages/SystemUI/src/com/android/systemui/statusbar/phone')
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java94
1 files changed, 92 insertions, 2 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 7035006..5d9c7bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -16,6 +16,10 @@
package com.android.systemui.statusbar.phone;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Iterator;
+
import android.animation.ObjectAnimator;
import android.animation.TimeAnimator;
import android.animation.TimeAnimator.TimeListener;
@@ -73,7 +77,93 @@ public class PanelView extends FrameLayout {
private TimeAnimator mTimeAnimator;
private ObjectAnimator mPeekAnimator;
- private VelocityTracker mVelocityTracker;
+ private FlingTracker mVelocityTracker;
+
+ /**
+ * A very simple low-pass velocity filter for motion events; not nearly as sophisticated as
+ * VelocityTracker but optimized for the kinds of gestures we expect to see in status bar
+ * panels.
+ */
+ private static class FlingTracker {
+ static final boolean DEBUG = false;
+ final int MAX_EVENTS = 8;
+ final float DECAY = 0.75f;
+ ArrayDeque<MotionEventCopy> mEventBuf = new ArrayDeque<MotionEventCopy>(MAX_EVENTS);
+ float mVX, mVY = 0;
+ private static class MotionEventCopy {
+ public MotionEventCopy(float x2, float y2, long eventTime) {
+ this.x = x2;
+ this.y = y2;
+ this.t = eventTime;
+ }
+ public float x, y;
+ public long t;
+ }
+ public FlingTracker() {
+ }
+ public void addMovement(MotionEvent event) {
+ if (mEventBuf.size() == MAX_EVENTS) {
+ mEventBuf.remove();
+ }
+ mEventBuf.add(new MotionEventCopy(event.getX(), event.getY(), event.getEventTime()));
+ }
+ public void computeCurrentVelocity(long timebase) {
+ if (FlingTracker.DEBUG) {
+ Slog.v("FlingTracker", "computing velocities for " + mEventBuf.size() + " events");
+ }
+ mVX = mVY = 0;
+ MotionEventCopy last = null;
+ int i = 0;
+ float totalweight = 0f;
+ float weight = 10f;
+ for (final Iterator<MotionEventCopy> iter = mEventBuf.descendingIterator();
+ iter.hasNext();) {
+ final MotionEventCopy event = iter.next();
+ if (last != null) {
+ final float dt = (float) (event.t - last.t) / timebase;
+ final float dx = (event.x - last.x);
+ final float dy = (event.y - last.y);
+ if (FlingTracker.DEBUG) {
+ Slog.v("FlingTracker", String.format(" [%d] dx=%.1f dy=%.1f dt=%.0f vx=%.1f vy=%.1f",
+ i,
+ dx, dy, dt,
+ (dx/dt),
+ (dy/dt)
+ ));
+ }
+ mVX += weight * dx / dt;
+ mVY += weight * dy / dt;
+ totalweight += weight;
+ weight *= DECAY;
+ }
+ last = event;
+ i++;
+ }
+ mVX /= totalweight;
+ mVY /= totalweight;
+
+ if (FlingTracker.DEBUG) {
+ Slog.v("FlingTracker", "computed: vx=" + mVX + " vy=" + mVY);
+ }
+ }
+ public float getXVelocity() {
+ return mVX;
+ }
+ public float getYVelocity() {
+ return mVY;
+ }
+ public void recycle() {
+ mEventBuf.clear();
+ }
+
+ static FlingTracker sTracker;
+ static FlingTracker obtain() {
+ if (sTracker == null) {
+ sTracker = new FlingTracker();
+ }
+ return sTracker;
+ }
+ }
private int[] mAbsPos = new int[2];
PanelBar mBar;
@@ -268,7 +358,7 @@ public class PanelView extends FrameLayout {
mHandleView.setPressed(true);
postInvalidate(); // catch the press state change
mInitialTouchY = y;
- mVelocityTracker = VelocityTracker.obtain();
+ mVelocityTracker = FlingTracker.obtain();
trackMovement(event);
mTimeAnimator.cancel(); // end any outstanding animations
mBar.onTrackingStarted(PanelView.this);