Allow closing the whole panel when QS is open

If the user drags below the notifications, we close everything. Only
implemented for the SHADE, and not on Keyguard because of
time constraints.

Bug: 15414856
Change-Id: I4cf656484bc1217d552211c2bfdd7598eb52dad7
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index fa2e361..aa68b0a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -450,7 +450,13 @@
                 mIntercepting = false;
                 break;
         }
-        return !mQsExpanded && super.onInterceptTouchEvent(event);
+
+        // Allow closing the whole panel when in SHADE state.
+        if (mStatusBarState == StatusBarState.SHADE) {
+            return super.onInterceptTouchEvent(event);
+        } else {
+            return !mQsExpanded && super.onInterceptTouchEvent(event);
+        }
     }
 
     private void resetDownStates(MotionEvent event) {
@@ -503,7 +509,7 @@
             return true;
         }
         if (event.getActionMasked() == MotionEvent.ACTION_DOWN && getExpandedFraction() == 1f
-                && mStatusBar.getBarState() != StatusBarState.KEYGUARD) {
+                && mStatusBar.getBarState() != StatusBarState.KEYGUARD && !mQsExpanded) {
 
             // Down in the empty area while fully expanded - go to QS.
             mQsTracking = true;
@@ -516,7 +522,7 @@
         if (mExpandedHeight != 0) {
             handleQsDown(event);
         }
-        if (!mTwoFingerQsExpand && (mQsTracking || mQsExpanded)) {
+        if (!mTwoFingerQsExpand && mQsTracking) {
             onQsTouch(event);
             if (!mConflictingQsExpansionGesture) {
                 return true;
@@ -539,9 +545,15 @@
         return true;
     }
 
+    private boolean isInQsArea(float x, float y) {
+        return mStatusBarState != StatusBarState.SHADE
+                || y <= mNotificationStackScroller.getBottomMostNotificationBottom()
+                || y <= mQsContainer.getY() + mQsContainer.getHeight();
+    }
+
     private void handleQsDown(MotionEvent event) {
         if (event.getActionMasked() == MotionEvent.ACTION_DOWN
-                && shouldQuickSettingsIntercept(event.getX(), event.getY(), 0)) {
+                && shouldQuickSettingsIntercept(event.getX(), event.getY(), -1)) {
             mQsTracking = true;
             onQsExpansionStarted();
             mInitialHeightOnTouch = mQsExpansionHeight;
@@ -627,8 +639,9 @@
     }
 
     @Override
-    public void onOverscrolled(int amount) {
-        if (mIntercepting) {
+    public void onOverscrolled(float lastTouchX, float lastTouchY, int amount) {
+        if (mIntercepting && shouldQuickSettingsIntercept(lastTouchX, lastTouchY,
+                -1 /* yDiff: Not relevant here */)) {
             onQsExpansionStarted(amount);
             mInitialHeightOnTouch = mQsExpansionHeight;
             mInitialTouchY = mLastTouchY;
@@ -1037,7 +1050,7 @@
         boolean onHeader = x >= header.getLeft() && x <= header.getRight()
                 && y >= header.getTop() && y <= header.getBottom();
         if (mQsExpanded) {
-            return onHeader || (mScrollView.isScrolledToBottom() && yDiff < 0);
+            return onHeader || (mScrollView.isScrolledToBottom() && yDiff < 0) && isInQsArea(x, y);
         } else {
             return onHeader;
         }
@@ -1087,8 +1100,9 @@
         }
         if (!isInSettings()) {
             return mNotificationStackScroller.isScrolledToBottom();
+        } else {
+            return mScrollView.isScrolledToBottom();
         }
-        return super.isScrolledToBottom();
     }
 
     @Override
@@ -1354,6 +1368,9 @@
                 || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) {
             mAfforanceHelper.animateHideLeftRightIcon();
         }
+        if (mQsExpanded) {
+            mTwoFingerQsExpand = true;
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
index 5920580..ee6b1a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
@@ -31,6 +31,8 @@
     private int mLastOverscrollAmount;
     private boolean mTouchEnabled = true;
     private boolean mHandlingTouchEvent;
+    private float mLastX;
+    private float mLastY;
 
     public ObservableScrollView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -65,6 +67,8 @@
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         mHandlingTouchEvent = true;
+        mLastX = ev.getX();
+        mLastY = ev.getY();
         boolean result = super.onTouchEvent(ev);
         mHandlingTouchEvent = false;
         return result;
@@ -73,6 +77,8 @@
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         mHandlingTouchEvent = true;
+        mLastX = ev.getX();
+        mLastY = ev.getY();
         boolean result = super.onInterceptTouchEvent(ev);
         mHandlingTouchEvent = false;
         return result;
@@ -107,12 +113,12 @@
     protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
         super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
         if (mListener != null && mLastOverscrollAmount > 0) {
-            mListener.onOverscrolled(mLastOverscrollAmount);
+            mListener.onOverscrolled(mLastX, mLastY, mLastOverscrollAmount);
         }
     }
 
     public interface Listener {
         void onScrollChanged();
-        void onOverscrolled(int amount);
+        void onOverscrolled(float lastX, float lastY, int amount);
     }
 }