Quick prototype of new header

 - Has first 4 quick tiles shown in collapsed mode
 - Shows date + settings gear in expanded mode
 - Still has a few gaps (alarms probably don't work)
 - Fix issue with placement of cell data type indicator

Change-Id: I629798b96f4f088fde47c7b67feea304dcc8450c
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
new file mode 100644
index 0000000..d778c98
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+** Copyright 2015, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+-->
+
+<!-- Extends RelativeLayout -->
+<com.android.systemui.statusbar.phone.QuickStatusBarHeader
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/header"
+    android:layout_width="@dimen/notification_panel_width"
+    android:layout_height="@dimen/status_bar_header_height"
+    android:layout_gravity="@integer/notification_panel_layout_gravity"
+    android:baselineAligned="false"
+    android:elevation="4dp"
+    android:background="@drawable/notification_header_bg"
+    android:clickable="true"
+    android:focusable="true"
+    >
+
+    <LinearLayout
+        android:id="@+id/expanded_group"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:paddingEnd="12dp"
+        android:orientation="horizontal">
+
+        <com.android.systemui.statusbar.AlphaOptimizedButton android:id="@+id/alarm_status"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="4dp"
+            android:drawablePadding="6dp"
+            android:drawableStart="@drawable/ic_access_alarms_small"
+            android:textColor="#64ffffff"
+            android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
+            android:paddingEnd="6dp"
+            android:paddingStart="6dp"
+            android:paddingTop="16dp"
+            android:paddingBottom="16dp"
+            android:background="?android:attr/selectableItemBackground"
+            android:visibility="gone"
+            />
+
+        <com.android.systemui.statusbar.policy.DateView android:id="@+id/date"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="16dp"
+            android:singleLine="true"
+            android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
+            android:layout_below="@id/clock"
+            systemui:datePattern="EEE"
+            android:gravity="center_vertical"
+            android:textSize="20sp"
+            android:paddingTop="16dp"
+            android:layout_marginBottom="@dimen/clock_collapsed_bottom_margin" />
+
+        <include layout="@layout/split_clock_view"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginStart="16dp"
+            android:layout_marginTop="16dp"
+            android:id="@+id/clock"
+            />
+
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1" />
+
+        <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
+            android:id="@+id/settings_button_container"
+            android:layout_width="48dp"
+            android:layout_height="@dimen/status_bar_header_height"
+            android:clipChildren="false"
+            android:clipToPadding="false">
+
+            <com.android.systemui.statusbar.phone.SettingsButton android:id="@+id/settings_button"
+                style="@android:style/Widget.Material.Button.Borderless"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:background="@drawable/ripple_drawable"
+                android:src="@drawable/ic_settings"
+                android:contentDescription="@string/accessibility_desc_settings" />
+            <com.android.systemui.statusbar.AlphaOptimizedImageView android:id="@+id/tuner_icon"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:paddingStart="36dp"
+                android:tint="#4DFFFFFF"
+                android:tintMode="src_in"
+                android:visibility="invisible"
+                android:src="@drawable/tuner" />
+
+        </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
+    </LinearLayout>
+
+    <include
+        android:id="@+id/qs_detail_header"
+        layout="@layout/qs_detail_header"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        />
+
+    <com.android.systemui.qs.QuickQSPanel
+        android:id="@+id/quick_qs_panel"
+        android:background="#0000"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <com.android.systemui.statusbar.AlphaOptimizedImageView
+        android:id="@+id/qs_detail_header_progress"
+        android:src="@drawable/indeterminate_anim"
+        android:alpha="0"
+        android:background="@color/qs_detail_progress_track"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        systemui:hasOverlappingRendering="false"
+        />
+
+    <TextView
+        android:id="@+id/header_debug_info"
+        android:visibility="invisible"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:fontFamily="sans-serif-condensed"
+        android:textSize="11dp"
+        android:textStyle="bold"
+        android:textColor="#00A040"
+        android:padding="2dp"
+        />
+
+</com.android.systemui.statusbar.phone.QuickStatusBarHeader>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index f7bbce0..a64dbbd 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -98,7 +98,12 @@
             layout="@layout/keyguard_bottom_area"
             android:visibility="gone" />
 
-    <include layout="@layout/status_bar_expanded_header" />
+    <ViewStub
+        android:id="@+id/status_bar_header"
+        android:layout_width="@dimen/notification_panel_width"
+        android:layout_height="@dimen/status_bar_header_height"
+        android:layout_marginStart="@dimen/notification_side_padding"
+        android:layout_marginEnd="@dimen/notification_side_padding" />
 
     <com.android.systemui.statusbar.AlphaOptimizedView
         android:id="@+id/qs_navbar_scrim"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 5eca471..dd75dbf 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -23,8 +23,6 @@
     android:layout_width="@dimen/notification_panel_width"
     android:layout_height="@dimen/status_bar_header_height"
     android:layout_gravity="@integer/notification_panel_layout_gravity"
-    android:paddingStart="@dimen/notification_side_padding"
-    android:paddingEnd="@dimen/notification_side_padding"
     android:baselineAligned="false"
     android:elevation="4dp"
     android:background="@drawable/notification_header_bg"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index abfd863..5661657 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -556,4 +556,7 @@
     <dimen name="fab_margin">16dp</dimen>
     <dimen name="fab_elevation">12dp</dimen>
     <dimen name="fab_press_translation_z">9dp</dimen>
+
+    <!-- TODO: Remove this -->
+    <dimen name="qs_header_neg_padding">-8dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d567e97..a525fbb 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1156,7 +1156,7 @@
     <!-- Option to show brightness bar in quick settings [CHAR LIMIT=60] -->
     <string name="show_brightness">Show brightness in Quick Settings</string>
     <!-- Option to use new paging layout in quick settings [CHAR LIMIT=60] -->
-    <string name="qs_paging">Use paging in Quick Settings</string>
+    <string name="qs_paging" translatable="false">Use the new Quick Settings</string>
 
     <!-- Category in the System UI Tuner settings, where new/experimental
          settings are -->
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 07e7688d..5980108 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -37,10 +37,6 @@
                 android:key="qs_paged_panel"
                 android:title="@string/qs_paging" />
 
-            <com.android.systemui.tuner.TunerSwitch
-                android:key="qs_allow_customize"
-                android:title="@string/qs_customize" />
-
         </PreferenceCategory>
 
     </PreferenceScreen>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 18af35e..c6bcfc4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -34,7 +34,6 @@
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
-
 import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
@@ -54,8 +53,7 @@
 public class QSPanel extends FrameLayout implements Tunable {
 
     public static final String QS_SHOW_BRIGHTNESS = "qs_show_brightness";
-    public static final String QS_PAGED_PANEL = "qs_paged_panel";
-    public static final String QS_ALLOW_CUSTOMIZE = "qs_allow_customize";
+    public static final String QS_THE_NEW_QS = "qs_paged_panel";
 
     protected final Context mContext;
     protected final ArrayList<TileRecord> mRecords = new ArrayList<TileRecord>();
@@ -135,8 +133,7 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
-        TunerService.get(mContext).addTunable(this,
-                QS_SHOW_BRIGHTNESS, QS_PAGED_PANEL, QS_ALLOW_CUSTOMIZE);
+        TunerService.get(mContext).addTunable(this, QS_SHOW_BRIGHTNESS, QS_THE_NEW_QS);
     }
 
     @Override
@@ -150,14 +147,15 @@
         if (QS_SHOW_BRIGHTNESS.equals(key)) {
             mBrightnessView.setVisibility(newValue == null || Integer.parseInt(newValue) != 0
                     ? VISIBLE : GONE);
-        } else if (QS_PAGED_PANEL.equals(key)) {
+        } else if (QS_THE_NEW_QS.equals(key)) {
+            boolean theNewQs = newValue != null && Integer.parseInt(newValue) != 0;
             if (mTileLayout != null) {
                 for (int i = 0; i < mRecords.size(); i++) {
                     mTileLayout.removeTile(mRecords.get(i));
                 }
                 mQsContainer.removeView((View) mTileLayout);
             }
-            int layout = newValue != null && Integer.parseInt(newValue) != 0
+            int layout = theNewQs
                     ? R.layout.qs_paged_tile_layout : R.layout.qs_tile_layout;
             mTileLayout =
                     (QSTileLayout) LayoutInflater.from(mContext).inflate(layout, mQsContainer, false);
@@ -165,8 +163,7 @@
             for (int i = 0; i < mRecords.size(); i++) {
                 mTileLayout.addTile(mRecords.get(i));
             }
-        } else if (QS_ALLOW_CUSTOMIZE.equals(key)) {
-            if (newValue != null && Integer.parseInt(newValue) != 0) {
+            if (theNewQs) {
                 mCustomizePanel = (QSCustomizer) LayoutInflater.from(mContext)
                         .inflate(R.layout.qs_customize_panel, null);
                 mCustomizePanel.setHost(mHost);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index e575923..d914beb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -267,7 +267,7 @@
         final int w = MeasureSpec.getSize(widthMeasureSpec);
         final int h = MeasureSpec.getSize(heightMeasureSpec);
         final int iconSpec = exactly(mIconSizePx);
-        mIcon.measure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY), iconSpec);
+        mIcon.measure(MeasureSpec.makeMeasureSpec(w, getIconMeasureMode()), iconSpec);
         switch (mType) {
             case QS_TYPE_QUICK:
                 mCircle.measure(
@@ -287,6 +287,10 @@
         setMeasuredDimension(w, h);
     }
 
+    protected int getIconMeasureMode() {
+        return MeasureSpec.EXACTLY;
+    }
+
     private static int exactly(int size) {
         return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
new file mode 100644
index 0000000..53d0402
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import com.android.systemui.R;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Version of QSPanel that only shows 4 Quick Tiles in the QS Header.
+ */
+public class QuickQSPanel extends QSPanel {
+
+    public QuickQSPanel(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        if (mTileLayout != null) {
+            for (int i = 0; i < mRecords.size(); i++) {
+                mTileLayout.removeTile(mRecords.get(i));
+            }
+            mQsContainer.removeView((View) mTileLayout);
+        }
+        mTileLayout = new HeaderTileLayout(context);
+        mQsContainer.addView((View) mTileLayout, 1 /* Between brightness and footer */);
+    }
+
+    @Override
+    public void onTuningChanged(String key, String newValue) {
+        // No tunings for you.
+        if (key.equals(QS_SHOW_BRIGHTNESS)) {
+            // No Brightness for you.
+            super.onTuningChanged(key, "0");
+        }
+    }
+
+    @Override
+    public void setTiles(Collection<QSTile<?>> tiles) {
+        ArrayList<QSTile<?>> quickTiles = new ArrayList<>();
+        for (QSTile<?> tile : tiles) {
+            if (tile.getTileType() == QSTileView.QS_TYPE_QUICK) {
+                quickTiles.add(tile);
+            }
+            if (quickTiles.size() == 4) {
+                break;
+            }
+        }
+        super.setTiles(quickTiles);
+    }
+
+    private static class HeaderTileLayout extends LinearLayout implements QSTileLayout {
+
+        public HeaderTileLayout(Context context) {
+            super(context);
+            setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+            int qsCompensation = (int)
+                    context.getResources().getDimension(R.dimen.qs_header_neg_padding);
+            setPadding(0, qsCompensation, 0, 0);
+            ImageView downArrow = new ImageView(context);
+            downArrow.setImageResource(R.drawable.ic_expand_more);
+            downArrow.setImageTintList(ColorStateList.valueOf(context.getResources().getColor(
+                    android.R.color.white, null)));
+            downArrow.setLayoutParams(generateLayoutParams());
+            downArrow.setPadding(0, -qsCompensation, 0, 0);
+            addView(downArrow);
+            setOrientation(LinearLayout.HORIZONTAL);
+        }
+
+        @Override
+        public void addTile(TileRecord tile) {
+            tile.tileView.setLayoutParams(generateLayoutParams());
+            // These shouldn't be normal tiles, but they will be for now so that the circles don't
+            // show up.
+            tile.tileView.setType(QSTileView.QS_TYPE_NORMAL);
+            addView(tile.tileView, getChildCount() - 1 /* Leave icon at end */);
+        }
+
+        private LayoutParams generateLayoutParams() {
+            LayoutParams lp = new LayoutParams(0, LayoutParams.MATCH_PARENT);
+            lp.weight = 1;
+            return lp;
+        }
+
+        @Override
+        public void removeTile(TileRecord tile) {
+            removeView(tile.tileView);
+        }
+
+        @Override
+        public void setTileVisibility(TileRecord tile, int visibility) {
+            tile.tileView.setVisibility(visibility);
+        }
+
+        @Override
+        public int getOffsetTop(TileRecord tile) {
+            return 0;
+        }
+
+        @Override
+        public void updateResources() {
+            // No resources here.
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
index 9ac7944..a2e1296 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
@@ -83,6 +83,11 @@
         layoutIndicator(mOut);
     }
 
+    @Override
+    protected int getIconMeasureMode() {
+        return MeasureSpec.AT_MOST;
+    }
+
     private void layoutIndicator(View indicator) {
         boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
         int left, right;
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 3453652..79701ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -35,6 +35,7 @@
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
+import android.view.ViewStub;
 import android.view.ViewTreeObserver;
 import android.view.WindowInsets;
 import android.view.accessibility.AccessibilityEvent;
@@ -43,7 +44,6 @@
 import android.view.animation.PathInterpolator;
 import android.widget.FrameLayout;
 import android.widget.TextView;
-
 import com.android.internal.logging.MetricsLogger;
 import com.android.keyguard.KeyguardStatusView;
 import com.android.systemui.DejankUtils;
@@ -64,6 +64,7 @@
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.stack.StackStateAnimator;
+import com.android.systemui.tuner.TunerService;
 
 import java.util.List;
 
@@ -71,7 +72,7 @@
         ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener,
         View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
         KeyguardAffordanceHelper.Callback, NotificationStackScrollLayout.OnEmptySpaceClickListener,
-        HeadsUpManager.OnHeadsUpChangedListener {
+        HeadsUpManager.OnHeadsUpChangedListener, TunerService.Tunable {
 
     private static final boolean DEBUG = false;
 
@@ -219,10 +220,13 @@
     private final Interpolator mTouchResponseInterpolator =
             new PathInterpolator(0.3f, 0f, 0.1f, 1f);
 
+    private boolean mNewQs;
+
     public NotificationPanelView(Context context, AttributeSet attrs) {
         super(context, attrs);
         setWillNotDraw(!DEBUG);
         mFalsingManager = FalsingManager.getInstance(context);
+        TunerService.get(context).addTunable(this, QSPanel.QS_THE_NEW_QS);
     }
 
     public void setStatusBar(PhoneStatusBar bar) {
@@ -230,9 +234,27 @@
     }
 
     @Override
+    public void onTuningChanged(String key, String newValue) {
+        if (QSPanel.QS_THE_NEW_QS.equals(key)) {
+            boolean b = newValue != null && Integer.parseInt(newValue) != 0;
+            if (mNewQs != b) {
+                if (mHeader != null) {
+                    // We are too late, no good way to re-initialize yet, just die and come back up.
+                    android.os.Process.killProcess(android.os.Process.myPid());
+                } else {
+                    mNewQs = b;
+                }
+            }
+        }
+    }
+
+    @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mHeader = (BaseStatusBarHeader) findViewById(R.id.header);
+        ViewStub stub = (ViewStub) findViewById(R.id.status_bar_header);
+        stub.setLayoutResource(mNewQs
+                ? R.layout.quick_status_bar_expanded_header : R.layout.status_bar_expanded_header);
+        mHeader = (BaseStatusBarHeader) stub.inflate();
         mHeader.setOnClickListener(this);
         mKeyguardStatusBar = (KeyguardStatusBarView) findViewById(R.id.keyguard_header);
         mKeyguardStatusView = (KeyguardStatusView) findViewById(R.id.keyguard_status_view);
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 05e8488..1c1a1d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -868,13 +868,15 @@
                 (SignalClusterView) mHeader.findViewById(R.id.signal_cluster);
         mNetworkController.addSignalCallback(signalCluster);
         mNetworkController.addSignalCallback(signalClusterKeyguard);
-        mNetworkController.addSignalCallback(signalClusterQs);
         signalCluster.setSecurityController(mSecurityController);
         signalCluster.setNetworkController(mNetworkController);
         signalClusterKeyguard.setSecurityController(mSecurityController);
         signalClusterKeyguard.setNetworkController(mNetworkController);
-        signalClusterQs.setSecurityController(mSecurityController);
-        signalClusterQs.setNetworkController(mNetworkController);
+        if (signalClusterQs != null) {
+            mNetworkController.addSignalCallback(signalClusterQs);
+            signalClusterQs.setSecurityController(mSecurityController);
+            signalClusterQs.setNetworkController(mNetworkController);
+        }
         final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
         if (isAPhone) {
             mNetworkController.addEmergencyListener(mHeader);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 6ec9494..6906a52 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -97,6 +97,10 @@
         TunerService.get(mContext).addTunable(this, TILES_SETTING);
     }
 
+    PhoneStatusBar getPhoneStatusBar() {
+        return mStatusBar;
+    }
+
     public void destroy() {
         TunerService.get(mContext).removeTunable(this);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
new file mode 100644
index 0000000..01f0667
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Animatable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.Switch;
+import android.widget.TextView;
+import android.widget.Toast;
+import com.android.systemui.R;
+import com.android.systemui.qs.QSPanel;
+import com.android.systemui.qs.QSTile;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.tuner.TunerService;
+
+public class QuickStatusBarHeader extends BaseStatusBarHeader implements
+        NextAlarmController.NextAlarmChangeCallback, View.OnClickListener {
+
+    private ActivityStarter mActivityStarter;
+    private NextAlarmController mNextAlarmController;
+    private SettingsButton mSettingsButton;
+    private View mSettingsContainer;
+    private TextView mAlarmStatus;
+    private View mQsDetailHeader;
+
+    private ImageView mQsDetailHeaderProgress;
+    private QSPanel mQsPanel;
+    private Switch mQsDetailHeaderSwitch;
+
+    private boolean mExpanded;
+    private boolean mAlarmShowing;
+    private boolean mShowingDetail;
+
+    private boolean mDetailTransitioning;
+    private ViewGroup mExpandedGroup;
+    private TextView mQsDetailHeaderTitle;
+    private boolean mListening;
+    private AlarmManager.AlarmClockInfo mNextAlarm;
+
+    private QSPanel mHeaderQsPanel;
+
+    public QuickStatusBarHeader(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mExpandedGroup = (ViewGroup) findViewById(R.id.expanded_group);
+
+        mHeaderQsPanel = (QSPanel) findViewById(R.id.quick_qs_panel);
+
+        mSettingsButton = (SettingsButton) findViewById(R.id.settings_button);
+        mSettingsContainer = findViewById(R.id.settings_button_container);
+        mSettingsButton.setOnClickListener(this);
+
+        mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
+        mAlarmStatus.setOnClickListener(this);
+
+        mQsDetailHeader = findViewById(R.id.qs_detail_header);
+        mQsDetailHeader.setAlpha(0);
+        mQsDetailHeaderTitle = (TextView) mQsDetailHeader.findViewById(android.R.id.title);
+        mQsDetailHeaderSwitch = (Switch) mQsDetailHeader.findViewById(android.R.id.toggle);
+        mQsDetailHeaderProgress = (ImageView) findViewById(R.id.qs_detail_header_progress);
+    }
+
+    @Override
+    public int getCollapsedHeight() {
+        return getHeight();
+    }
+
+    @Override
+    public int getExpandedHeight() {
+        return getHeight();
+    }
+
+    @Override
+    public void setExpanded(boolean expanded) {
+        mExpanded = expanded;
+    }
+
+    @Override
+    public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
+        mNextAlarm = nextAlarm;
+        if (nextAlarm != null) {
+            // TODO:...
+//            mAlarmStatus.setText(KeyguardStatusView.formatNextAlarm(getContext(), nextAlarm));
+        }
+        mAlarmShowing = nextAlarm != null;
+        updateEverything();
+    }
+
+    @Override
+    public void setExpansion(float headerExpansionFraction) {
+        float offset = getHeight() * headerExpansionFraction;
+        mExpandedGroup.setTranslationY(offset - getHeight());
+        mHeaderQsPanel.setTranslationY(offset);
+    }
+
+    public void setListening(boolean listening) {
+        if (listening == mListening) {
+            return;
+        }
+        mHeaderQsPanel.setListening(listening);
+        mListening = listening;
+        updateListeners();
+    }
+
+    @Override
+    public void updateEverything() {
+        updateVisibilities();
+    }
+
+    private void updateVisibilities() {
+        mAlarmStatus.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.GONE);
+        mQsDetailHeader.setVisibility(mExpanded && mShowingDetail ? View.VISIBLE : View.INVISIBLE);
+        mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
+                TunerService.isTunerEnabled(mContext) ? View.VISIBLE : View.INVISIBLE);
+    }
+
+    private void updateListeners() {
+        if (mListening) {
+            mNextAlarmController.addStateChangedCallback(this);
+        } else {
+            mNextAlarmController.removeStateChangedCallback(this);
+        }
+    }
+
+    @Override
+    public void setActivityStarter(ActivityStarter activityStarter) {
+        mActivityStarter = activityStarter;
+    }
+
+    @Override
+    public void setQSPanel(final QSPanel qsPanel) {
+        mQsPanel = qsPanel;
+        setupHost(qsPanel.getHost());
+        if (mQsPanel != null) {
+            mQsPanel.setCallback(mQsPanelCallback);
+        }
+    }
+
+    public void setupHost(QSTileHost host) {
+        final QSTileHost myHost = new QSTileHost(host.getContext(), host.getPhoneStatusBar(),
+                host.getBluetoothController(), host.getLocationController(),
+                host.getRotationLockController(), host.getNetworkController(),
+                host.getZenModeController(), host.getHotspotController(),
+                host.getCastController(), host.getFlashlightController(),
+                host.getUserSwitcherController(), host.getUserInfoController(),
+                host.getKeyguardMonitor(), host.getSecurityController(),
+                host.getBatteryController());
+        mHeaderQsPanel.setHost(myHost);
+        mHeaderQsPanel.setTiles(myHost.getTiles());
+        myHost.setCallback(new QSTile.Host.Callback() {
+            @Override
+            public void onTilesChanged() {
+                mHeaderQsPanel.setTiles(myHost.getTiles());
+            }
+        });
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v == mSettingsButton) {
+            if (mSettingsButton.isTunerClick()) {
+                if (TunerService.isTunerEnabled(mContext)) {
+                    TunerService.showResetRequest(mContext, new Runnable() {
+                        @Override
+                        public void run() {
+                            // Relaunch settings so that the tuner disappears.
+                            startSettingsActivity();
+                        }
+                    });
+                } else {
+                    Toast.makeText(getContext(), R.string.tuner_toast, Toast.LENGTH_LONG).show();
+                    TunerService.setTunerEnabled(mContext, true);
+                }
+            }
+            startSettingsActivity();
+        } else if (v == mAlarmStatus && mNextAlarm != null) {
+            PendingIntent showIntent = mNextAlarm.getShowIntent();
+            if (showIntent != null && showIntent.isActivity()) {
+                mActivityStarter.startActivity(showIntent.getIntent(), true /* dismissShade */);
+            }
+        }
+    }
+
+    private void startSettingsActivity() {
+        mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
+                true /* dismissShade */);
+    }
+
+    @Override
+    public void setNextAlarmController(NextAlarmController nextAlarmController) {
+        mNextAlarmController = nextAlarmController;
+    }
+
+    @Override
+    public void setBatteryController(BatteryController batteryController) {
+        // Don't care
+    }
+
+    @Override
+    public void setUserInfoController(UserInfoController userInfoController) {
+        // Don't care.
+    }
+
+    @Override
+    public void setEmergencyCallsOnly(boolean emergencyOnly) {
+        // Don't care.
+    }
+
+    private final QSPanel.Callback mQsPanelCallback = new QSPanel.Callback() {
+        private boolean mScanState;
+
+        @Override
+        public void onShowingDetail(final QSTile.DetailAdapter detail) {
+            mDetailTransitioning = true;
+            post(new Runnable() {
+                @Override
+                public void run() {
+                    handleShowingDetail(detail);
+                }
+            });
+        }
+
+        @Override
+        public void onToggleStateChanged(final boolean state) {
+            post(new Runnable() {
+                @Override
+                public void run() {
+                    handleToggleStateChanged(state);
+                }
+            });
+
+        }
+
+        @Override
+        public void onScanStateChanged(final boolean state) {
+            post(new Runnable() {
+                @Override
+                public void run() {
+                    handleScanStateChanged(state);
+                }
+            });
+        }
+
+        private void handleToggleStateChanged(boolean state) {
+            mQsDetailHeaderSwitch.setChecked(state);
+        }
+
+        private void handleScanStateChanged(boolean state) {
+            if (mScanState == state) return;
+            mScanState = state;
+            final Animatable anim = (Animatable) mQsDetailHeaderProgress.getDrawable();
+            if (state) {
+                mQsDetailHeaderProgress.animate().alpha(1f);
+                anim.start();
+            } else {
+                mQsDetailHeaderProgress.animate().alpha(0f);
+                anim.stop();
+            }
+        }
+
+        private void handleShowingDetail(final QSTile.DetailAdapter detail) {
+            final boolean showingDetail = detail != null;
+            transition(mExpandedGroup, !showingDetail);
+            if (mAlarmShowing) {
+                transition(mAlarmStatus, !showingDetail);
+            }
+            transition(mQsDetailHeader, showingDetail);
+            mShowingDetail = showingDetail;
+            if (showingDetail) {
+                mQsDetailHeaderTitle.setText(detail.getTitle());
+                final Boolean toggleState = detail.getToggleState();
+                if (toggleState == null) {
+                    mQsDetailHeaderSwitch.setVisibility(INVISIBLE);
+                    mQsDetailHeader.setClickable(false);
+                } else {
+                    mQsDetailHeaderSwitch.setVisibility(VISIBLE);
+                    mQsDetailHeaderSwitch.setChecked(toggleState);
+                    mQsDetailHeader.setClickable(true);
+                    mQsDetailHeader.setOnClickListener(new OnClickListener() {
+                        @Override
+                        public void onClick(View v) {
+                            boolean checked = !mQsDetailHeaderSwitch.isChecked();
+                            mQsDetailHeaderSwitch.setChecked(checked);
+                            detail.setToggleState(checked);
+                        }
+                    });
+                }
+            } else {
+                mQsDetailHeader.setClickable(false);
+            }
+        }
+
+        private void transition(final View v, final boolean in) {
+            if (in) {
+                v.bringToFront();
+                v.setVisibility(VISIBLE);
+            }
+            if (v.hasOverlappingRendering()) {
+                v.animate().withLayer();
+            }
+            v.animate()
+                    .alpha(in ? 1 : 0)
+                    .withEndAction(new Runnable() {
+                        @Override
+                        public void run() {
+                            if (!in) {
+                                v.setVisibility(INVISIBLE);
+                            }
+                            mDetailTransitioning = false;
+                        }
+                    })
+                    .start();
+        }
+    };
+}
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 7f5ffaf..65d84e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -237,7 +237,7 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
-        TunerService.get(mContext).addTunable(this, QSPanel.QS_PAGED_PANEL);
+        TunerService.get(mContext).addTunable(this, QSPanel.QS_THE_NEW_QS);
     }
 
     @Override
@@ -248,7 +248,7 @@
 
     @Override
     public void onTuningChanged(String key, String newValue) {
-        if (QSPanel.QS_PAGED_PANEL.equals(key)) {
+        if (QSPanel.QS_THE_NEW_QS.equals(key)) {
             mAllowExpand = newValue == null || Integer.parseInt(newValue) == 0;
             if (!mAllowExpand) {
                 setExpanded(false);
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index 9a78b6c..911d6a2 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -101,7 +101,7 @@
                         }
                     }).show();
         }
-        TunerService.get(getContext()).addTunable(mQsPaging, QSPanel.QS_PAGED_PANEL);
+        TunerService.get(getContext()).addTunable(mQsPaging, QSPanel.QS_THE_NEW_QS);
     }
 
     @Override