Panel physics changes.

- You can start pulling down another panel before the first
  one has fully expanded. (Protip: tap many times on the
  statusbar to invoke Schwarzenegger Mode.)
- When starting to pull down a panel, other panels are
  immediately sent running (rather than placing them on a
  literal seesaw).
- Rubberbanding is a little less aggressive: if it looks
  like you're moving your finger upward, we'll just close
  the panel outright rather than sticking to the bottom of
  the visible content. (tablets only)
- This has some implications for the background fade; you'll
  see a brief increase in brightness as you swap panels
  because the fade fraction is based on the sum of all the
  panels' fractional visibility. At times there will not be
  enough "panel" visible, in the aggregate, to justify
  holding the fade steady.

Bug: 7260868 // can't pull down panel, possibly fixed
Bug: 7204435 // double-swipe for QS
Bug: 7179458 // fling & rubberbanding heuristics
Bug: 7172453 // collapse other panels when dragging a new one
Bug: 7221970 // grabbing a flying panel causes twitching
Change-Id: Iad7c1f92c4edab9102cdda45605ef0ead4cc16c5
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 d94dbe4..0550771 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -9,14 +9,9 @@
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
 import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.BluetoothController;
-import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.NetworkController;
 
 public class PanelView extends FrameLayout {
     public static final boolean DEBUG = PanelBar.DEBUG;
@@ -70,12 +65,16 @@
         }
     };
 
-    private final Runnable mStopAnimator = new Runnable() { public void run() {
-        if (mTimeAnimator.isStarted()) {
-            mTimeAnimator.end();
-            mRubberbanding = false;
+    private final Runnable mStopAnimator = new Runnable() {
+        @Override
+        public void run() {
+            if (mTimeAnimator.isStarted()) {
+                mTimeAnimator.end();
+                mRubberbanding = false;
+                mClosing = false;
+            }
         }
-    }};
+    };
 
     private float mVel, mAccel;
     private int mFullHeight = 0;
@@ -90,20 +89,22 @@
             mTimeAnimator.setTimeListener(mAnimationCallback);
 
             mTimeAnimator.start();
-            
-            mRubberbanding = STRETCH_PAST_CONTENTS && mExpandedHeight > getFullHeight();
+
+            mRubberbanding = STRETCH_PAST_CONTENTS // is it enabled at all?
+                    && mExpandedHeight > getFullHeight() // are we past the end?
+                    && mVel >= -mFlingGestureMinDistPx; // was this not possibly a "close" gesture?
             if (mRubberbanding) {
                 mClosing = true;
             } else if (mVel == 0) {
-                // if the panel is less than halfway open, close it 
+                // if the panel is less than halfway open, close it
                 mClosing = (mFinalTouchY / getFullHeight()) < 0.5f;
             } else {
                 mClosing = mExpandedHeight > 0 && mVel < 0;
             }
         } else if (dtms > 0) {
             final float dt = dtms * 0.001f;                  // ms -> s
-            LOG("tick: v=%.2fpx/s dt=%.4fs", mVel, dt);
-            LOG("tick: before: h=%d", (int) mExpandedHeight);
+            if (DEBUG) LOG("tick: v=%.2fpx/s dt=%.4fs", mVel, dt);
+            if (DEBUG) LOG("tick: before: h=%d", (int) mExpandedHeight);
 
             final float fh = getFullHeight();
             boolean braking = false;
@@ -136,12 +137,12 @@
             }
 
             float h = mExpandedHeight + mVel * dt;
-            
+
             if (mRubberbanding && h < fh) {
                 h = fh;
             }
 
-            LOG("tick: new h=%d closing=%s", (int) h, mClosing?"true":"false");
+            if (DEBUG) LOG("tick: new h=%d closing=%s", (int) h, mClosing?"true":"false");
 
             setExpandedHeightInternal(h);
 
@@ -205,14 +206,14 @@
         loadDimens();
 
         mHandleView = findViewById(R.id.handle);
-        LOG("handle view: " + mHandleView);
+        if (DEBUG) LOG("handle view: " + mHandleView);
         if (mHandleView != null) {
             mHandleView.setOnTouchListener(new View.OnTouchListener() {
                 @Override
                 public boolean onTouch(View v, MotionEvent event) {
                     final float y = event.getY();
                     final float rawY = event.getRawY();
-                    LOG("handle.onTouch: a=%s y=%.1f rawY=%.1f off=%.1f",
+                    if (DEBUG) LOG("handle.onTouch: a=%s y=%.1f rawY=%.1f off=%.1f",
                             MotionEvent.actionToString(event.getAction()),
                             y, rawY, mTouchOffset);
                     PanelView.this.getLocationOnScreen(mAbsPos);
@@ -224,6 +225,7 @@
                             mInitialTouchY = y;
                             mVelocityTracker = VelocityTracker.obtain();
                             trackMovement(event);
+                            mTimeAnimator.cancel(); // end any outstanding animations
                             mBar.onTrackingStarted(PanelView.this);
                             mTouchOffset = (rawY - mAbsPos[1]) - PanelView.this.getExpandedHeight();
                             break;
@@ -263,7 +265,7 @@
 
                             // if you've barely moved your finger, we treat the velocity as 0
                             // preventing spurious flings due to touch screen jitter
-                            final float deltaY = (float)Math.abs(mFinalTouchY - mInitialTouchY);
+                            final float deltaY = Math.abs(mFinalTouchY - mInitialTouchY);
                             if (deltaY < mFlingGestureMinDistPx
                                     || vel < mFlingGestureMinDistPx) {
                                 vel = 0;
@@ -273,7 +275,7 @@
                                 vel = -vel;
                             }
 
-                            LOG("gesture: dy=%f vraw=(%f,%f) vnorm=(%f,%f) vlinear=%f",
+                            if (DEBUG) LOG("gesture: dy=%f vraw=(%f,%f) vnorm=(%f,%f) vlinear=%f",
                                     deltaY,
                                     mVelocityTracker.getXVelocity(),
                                     mVelocityTracker.getYVelocity(),
@@ -312,7 +314,7 @@
 
     @Override
     protected void onViewAdded(View child) {
-        LOG("onViewAdded: " + child);
+        if (DEBUG) LOG("onViewAdded: " + child);
     }
 
     public View getHandle() {
@@ -324,7 +326,7 @@
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
-        LOG("onMeasure(%d, %d) -> (%d, %d)",
+        if (DEBUG) LOG("onMeasure(%d, %d) -> (%d, %d)",
                 widthMeasureSpec, heightMeasureSpec, getMeasuredWidth(), getMeasuredHeight());
 
         // Did one of our children change size?
@@ -332,7 +334,7 @@
         if (newHeight != mFullHeight) {
             mFullHeight = newHeight;
             // If the user isn't actively poking us, let's rubberband to the content
-            if (!mTracking && !mRubberbanding && !mTimeAnimator.isStarted() 
+            if (!mTracking && !mRubberbanding && !mTimeAnimator.isStarted()
                     && mExpandedHeight > 0 && mExpandedHeight != mFullHeight) {
                 mExpandedHeight = mFullHeight;
             }
@@ -351,7 +353,7 @@
 
     @Override
     protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
-        LOG("onLayout: changed=%s, bottom=%d eh=%d fh=%d", changed?"T":"f", bottom, (int)mExpandedHeight, (int)mFullHeight);
+        if (DEBUG) LOG("onLayout: changed=%s, bottom=%d eh=%d fh=%d", changed?"T":"f", bottom, (int)mExpandedHeight, mFullHeight);
         super.onLayout(changed, left, top, right, bottom);
     }
 
@@ -365,7 +367,7 @@
         if (!(STRETCH_PAST_CONTENTS && (mTracking || mRubberbanding)) && h > fh) h = fh;
         mExpandedHeight = h;
 
-        LOG("setExpansion: height=%.1f fh=%.1f tracking=%s rubber=%s", h, fh, mTracking?"T":"f", mRubberbanding?"T":"f");
+        if (DEBUG) LOG("setExpansion: height=%.1f fh=%.1f tracking=%s rubber=%s", h, fh, mTracking?"T":"f", mRubberbanding?"T":"f");
 
         requestLayout();
 //        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
@@ -377,9 +379,9 @@
 
     private float getFullHeight() {
         if (mFullHeight <= 0) {
-            LOG("Forcing measure() since fullHeight=" + mFullHeight);
-            measure(MeasureSpec.makeMeasureSpec(LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY),
-                    MeasureSpec.makeMeasureSpec(LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY));
+            if (DEBUG) LOG("Forcing measure() since fullHeight=" + mFullHeight);
+            measure(MeasureSpec.makeMeasureSpec(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY));
         }
         return mFullHeight;
     }
@@ -397,11 +399,15 @@
     }
 
     public boolean isFullyExpanded() {
-        return mExpandedHeight == getFullHeight();
+        return mExpandedHeight >= getFullHeight();
     }
 
     public boolean isFullyCollapsed() {
-        return mExpandedHeight == 0;
+        return mExpandedHeight <= 0;
+    }
+
+    public boolean isCollapsing() {
+        return mClosing;
     }
 
     public void setBar(PanelBar panelBar) {
@@ -411,6 +417,8 @@
     public void collapse() {
         // TODO: abort animation or ongoing touch
         if (!isFullyCollapsed()) {
+            // collapse() should never be a rubberband, even if an animation is already running
+            mRubberbanding = false;
             fling(-mSelfCollapseVelocityPx, /*always=*/ true);
         }
     }
@@ -418,10 +426,10 @@
     public void expand() {
         if (isFullyCollapsed()) {
             mBar.startOpeningPanel(this);
-            LOG("expand: calling fling(%s, true)", mSelfExpandVelocityPx);
+            if (DEBUG) LOG("expand: calling fling(%s, true)", mSelfExpandVelocityPx);
             fling (mSelfExpandVelocityPx, /*always=*/ true);
         } else if (DEBUG) {
-            LOG("skipping expansion: is expanded");
+            if (DEBUG) LOG("skipping expansion: is expanded");
         }
     }
 }