Make QS panel peek below the header.

Bug: 15210059

Change-Id: I84e45092b3c9c397da8b458dbaa136fd52e665a6
diff --git a/packages/SystemUI/res/drawable/notification_header_bg.xml b/packages/SystemUI/res/drawable/notification_header_bg.xml
index 09d0d7d..5daec20 100644
--- a/packages/SystemUI/res/drawable/notification_header_bg.xml
+++ b/packages/SystemUI/res/drawable/notification_header_bg.xml
@@ -19,13 +19,11 @@
     <item android:state_pressed="true">
         <shape>
             <solid android:color="@color/background_color_1_press" />
-            <corners android:radius="@*android:dimen/notification_quantum_rounded_rect_radius" />
         </shape>
     </item>
     <item>
         <shape>
             <solid android:color="@color/background_color_1" />
-            <corners android:radius="@*android:dimen/notification_quantum_rounded_rect_radius" />
         </shape>
     </item>
 </selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_panel_background.xml b/packages/SystemUI/res/drawable/qs_panel_background.xml
index c324976..a1a5362 100644
--- a/packages/SystemUI/res/drawable/qs_panel_background.xml
+++ b/packages/SystemUI/res/drawable/qs_panel_background.xml
@@ -13,11 +13,8 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-        android:insetLeft="@dimen/notification_side_padding"
-        android:insetRight="@dimen/notification_side_padding">
-    <shape>
-        <solid android:color="@color/system_primary_color" />
-        <corners android:radius="@*android:dimen/notification_quantum_rounded_rect_radius" />
-    </shape>
-</inset>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/system_primary_color" />
+    <corners
+        android:radius="@*android:dimen/notification_quantum_rounded_rect_radius"/>
+</shape>
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 85de645..398787f 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -16,11 +16,10 @@
 <FrameLayout
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/quick_settings_container"
-        android:paddingLeft="@dimen/notification_side_padding"
-        android:paddingRight="@dimen/notification_side_padding"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:background="@drawable/qs_panel_background" >
+        android:background="@drawable/qs_panel_background"
+        android:elevation="2dp">
     <com.android.systemui.qs.QSPanel
             android:id="@+id/quick_settings_panel"
             android:background="#0000"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index d683162..cde83bf 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -59,7 +59,6 @@
             android:id="@+id/scroll_view"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:visibility="invisible"
             android:scrollbars="none"
             android:overScrollMode="never"
             android:fillViewport="true">
@@ -71,7 +70,9 @@
                     layout="@layout/qs_panel"
                     android:layout_marginTop="@dimen/status_bar_header_height_expanded"
                     android:layout_width="match_parent"
-                    android:layout_height="wrap_content"/>
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="@dimen/notification_side_padding"
+                    android:layout_marginRight="@dimen/notification_side_padding"/>
 
                 <!-- A view to reserve space for the collapsed stack -->
                 <View
@@ -80,7 +81,6 @@
             </LinearLayout>
         </com.android.systemui.statusbar.phone.ObservableScrollView>
 
-
         <com.android.systemui.statusbar.stack.NotificationStackScrollLayout
             android:id="@+id/notification_stack_scroller"
             android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 89fa988..9c4f619 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -25,7 +25,7 @@
     android:paddingStart="@dimen/notification_side_padding"
     android:paddingEnd="@dimen/notification_side_padding"
     android:baselineAligned="false"
-    android:elevation="10dp"
+    android:elevation="4dp"
     >
 
     <View
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index e9dcea2..bf0cb68 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -196,6 +196,9 @@
     <dimen name="qs_dual_tile_height">109dp</dimen>
     <dimen name="qs_dual_tile_padding">12dp</dimen>
 
+    <!-- How far the expanded QS panel peeks from the header in collapsed state. -->
+    <dimen name="qs_peek_height">8dp</dimen>
+
     <!-- used by DessertCase -->
     <dimen name="dessert_case_cell_size">192dp</dimen>
 
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 2f2a5df..66b8cdf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -50,6 +50,7 @@
     PhoneStatusBar mStatusBar;
     private StatusBarHeaderView mHeader;
     private View mQsContainer;
+    private View mQsPanel;
     private View mKeyguardStatusView;
     private ObservableScrollView mScrollView;
     private View mStackScrollerContainer;
@@ -68,6 +69,7 @@
      */
     private boolean mIntercepting;
     private boolean mQsExpanded;
+    private boolean mKeyguardShowing;
     private float mInitialHeightOnTouch;
     private float mInitialTouchX;
     private float mInitialTouchY;
@@ -77,6 +79,7 @@
     private int mQsMinExpansionHeight;
     private int mQsMaxExpansionHeight;
     private int mMinStackHeight;
+    private int mQsPeekHeight;
     private float mNotificationTranslation;
     private int mStackScrollerIntrinsicPadding;
     private boolean mQsExpansionEnabled = true;
@@ -121,6 +124,7 @@
         mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
         mStackScrollerContainer = findViewById(R.id.notification_container_parent);
         mQsContainer = findViewById(R.id.quick_settings_container);
+        mQsPanel = findViewById(R.id.quick_settings_panel);
         mScrollView = (ObservableScrollView) findViewById(R.id.scroll_view);
         mScrollView.setListener(this);
         mNotificationStackScroller = (NotificationStackScrollLayout)
@@ -139,22 +143,21 @@
         mFlingAnimationUtils = new FlingAnimationUtils(getContext(), 0.4f);
         mStatusBarMinHeight = getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_height);
+        mQsPeekHeight = getResources().getDimensionPixelSize(R.dimen.qs_peek_height);
         mClockPositionAlgorithm.loadDimens(getResources());
     }
 
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
-        if (!mQsExpanded) {
-            positionClockAndNotifications();
-            mNotificationStackScroller.setStackHeight(getExpandedHeight());
-        }
 
         // Calculate quick setting heights.
-        mQsMinExpansionHeight = mHeader.getCollapsedHeight();
+        mQsMinExpansionHeight = mHeader.getCollapsedHeight() + mQsPeekHeight;
         mQsMaxExpansionHeight = mHeader.getExpandedHeight() + mQsContainer.getHeight();
-        if (mQsExpansionHeight == 0) {
-            mQsExpansionHeight = mQsMinExpansionHeight;
+        if (!mQsExpanded) {
+            setQsExpansion(mQsMinExpansionHeight);
+            positionClockAndNotifications();
+            mNotificationStackScroller.setStackHeight(getExpandedHeight());
         }
     }
 
@@ -165,7 +168,8 @@
     private void positionClockAndNotifications() {
         boolean animateClock = mNotificationStackScroller.isAddOrRemoveAnimationPending();
         if (mStatusBar.getBarState() != StatusBarState.KEYGUARD) {
-            mStackScrollerIntrinsicPadding = mHeader.getBottom() + mNotificationTopPadding;
+            mStackScrollerIntrinsicPadding = mHeader.getBottom() + mQsPeekHeight
+                    + mNotificationTopPadding;
             mTopPaddingAdjustment = 0;
         } else {
             mClockPositionAlgorithm.setup(
@@ -455,29 +459,38 @@
         setQsExpansion(height);
     }
 
-    private void expandQs() {
-        mHeader.setExpanded(true);
-        mNotificationStackScroller.setEnabled(false);
-        mScrollView.setVisibility(View.VISIBLE);
-        mQsExpanded = true;
+    private void setQsExpanded(boolean expanded) {
+        boolean changed = mQsExpanded != expanded;
+        if (changed) {
+            mQsExpanded = expanded;
+            updateQsState();
+        }
     }
 
-    private void collapseQs() {
-        mHeader.setExpanded(false);
-        mNotificationStackScroller.setEnabled(true);
-        mScrollView.setVisibility(View.INVISIBLE);
-        mQsExpanded = false;
+    public void setKeyguardShowing(boolean keyguardShowing) {
+        mKeyguardShowing = keyguardShowing;
+        updateQsState();
+    }
+
+    private void updateQsState() {
+        mHeader.setExpanded(mQsExpanded);
+        mNotificationStackScroller.setEnabled(!mQsExpanded);
+        mQsPanel.setVisibility(mQsExpanded ? View.VISIBLE : View.INVISIBLE);
+        mQsContainer.setVisibility(mKeyguardShowing && !mQsExpanded
+                ? View.INVISIBLE
+                : View.VISIBLE);
+        mScrollView.setTouchEnabled(mQsExpanded);
     }
 
     private void setQsExpansion(float height) {
         height = Math.min(Math.max(height, mQsMinExpansionHeight), mQsMaxExpansionHeight);
         if (height > mQsMinExpansionHeight && !mQsExpanded) {
-            expandQs();
+            setQsExpanded(true);
         } else if (height <= mQsMinExpansionHeight && mQsExpanded) {
-            collapseQs();
+            setQsExpanded(false);
         }
         mQsExpansionHeight = height;
-        mHeader.setExpansion(height);
+        mHeader.setExpansion(height - mQsPeekHeight);
         setQsTranslation(height);
         setQsStackScrollerPadding(height);
         mStatusBar.userActivity();
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 c4e61d0..ea5b309 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
@@ -30,6 +30,7 @@
     private Listener mListener;
     private int mLastOverscrollAmount;
     private boolean mDispatchingTouchEvent;
+    private boolean mTouchEnabled = true;
 
     public ObservableScrollView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -39,6 +40,10 @@
         mListener = listener;
     }
 
+    public void setTouchEnabled(boolean touchEnabled) {
+        mTouchEnabled = touchEnabled;
+    }
+
     public boolean isScrolledToBottom() {
         return getScrollY() == getMaxScrollY();
     }
@@ -59,6 +64,9 @@
 
     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
+        if (!mTouchEnabled) {
+            return false;
+        }
         mDispatchingTouchEvent = true;
         boolean result = super.dispatchTouchEvent(ev);
         mDispatchingTouchEvent = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 0922abd..28367d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -2770,9 +2770,11 @@
         if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
             mKeyguardBottomArea.setVisibility(View.VISIBLE);
             mHeader.setKeyguardShowing(true);
+            mNotificationPanel.setKeyguardShowing(true);
         } else {
             mKeyguardBottomArea.setVisibility(View.GONE);
             mHeader.setKeyguardShowing(false);
+            mNotificationPanel.setKeyguardShowing(false);
         }
 
         updateStackScrollerState();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 389e725..3ead5df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -38,6 +38,11 @@
  */
 public class StatusBarHeaderView extends RelativeLayout implements View.OnClickListener {
 
+    /**
+     * How much the header expansion gets rubberbanded while expanding the panel.
+     */
+    private static final float EXPANSION_RUBBERBAND_FACTOR = 0.35f;
+
     private boolean mExpanded;
     private boolean mKeyguardShowing;
 
@@ -128,6 +133,7 @@
             updateVisibilities();
             updateSystemIconsLayoutParams();
             updateBrightnessControllerState();
+            updateZTranslation();
             if (mQSPanel != null) {
                 mQSPanel.setExpanded(expanded);
             }
@@ -202,18 +208,25 @@
         }
     }
 
+    private void updateZTranslation() {
+
+        // If we are on the Keyguard, we need to set our z position to zero, so we don't get
+        // shadows.
+        if (mKeyguardShowing && !mExpanded) {
+            setZ(0);
+        } else {
+            setTranslationZ(0);
+        }
+    }
+
     public void setExpansion(float height) {
+        height = (height - mCollapsedHeight) * EXPANSION_RUBBERBAND_FACTOR + mCollapsedHeight;
         if (height < mCollapsedHeight) {
             height = mCollapsedHeight;
         }
         if (height > mExpandedHeight) {
             height = mExpandedHeight;
         }
-        if (mExpanded) {
-            mBackground.setTranslationY(-(mExpandedHeight - height));
-        } else {
-            mBackground.setTranslationY(0);
-        }
         setClipping(height);
     }
 
@@ -247,14 +260,10 @@
 
     public void setKeyguardShowing(boolean keyguardShowing) {
         mKeyguardShowing = keyguardShowing;
-        if (keyguardShowing) {
-            setZ(0);
-        } else {
-            setTranslationZ(0);
-        }
         updateHeights();
         updateWidth();
         updateVisibilities();
+        updateZTranslation();
     }
 
     public void setUserInfoController(UserInfoController userInfoController) {