am b8145002: am 9f2532bf: Merge "Reduce false swipe-closed gestures in status bar panels." into jb-mr1.1-dev

* commit 'b814500269324bc24de13f974f9564ff176a578f':
  Reduce false swipe-closed gestures in status bar panels.
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 @@
 
     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 @@
                             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);