Interim quick settings update.

Make existing QS panel available via pulldown from header
(or keyguard status view on keyguard), update the affordances
as a hint.

Don't allow QS to scroll, cap to max rows.

Add scrim over panel to indicate that this is purely temporary.

Bug:14081801
Bug:14059974
Change-Id: I166033975cbc44b91f45ee70ea5c7540390670dd
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png
index 092b561..3c0dc4e 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png
index 064860d..3b1944d 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_open_normal.png
deleted file mode 100644
index 13f6b7f..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_open_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_quicksettings_normal.png
deleted file mode 100644
index ecdb240..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_quicksettings_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_open_normal.png
deleted file mode 100644
index c98911c..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_open_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_quicksettings_normal.png
deleted file mode 100644
index bb99022..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_quicksettings_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_open_normal.png
deleted file mode 100644
index d9d8b13..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_open_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_quicksettings_normal.png
deleted file mode 100644
index 09e0a3c..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_quicksettings_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_open_normal.png
deleted file mode 100644
index c0855b5..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_open_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_quicksettings_normal.png
deleted file mode 100644
index e3fb992..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_quicksettings_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png
index ae5d263..8010ce7 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png
index 32fbed4..807f607 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png
index 990f8bb..6d46fdd 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png
index 96eaafe..e562bc2 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-xxhdpi/ic_notify_open_normal.png
index 60579f9..7742207 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_notify_open_normal.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_notify_open_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-xxhdpi/ic_notify_quicksettings_normal.png
index abb9b18..a2e8fe1 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_notify_quicksettings_normal.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_notify_quicksettings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/flip_settings.xml b/packages/SystemUI/res/layout/flip_settings.xml
index 1b8898c5..28d9625 100644
--- a/packages/SystemUI/res/layout/flip_settings.xml
+++ b/packages/SystemUI/res/layout/flip_settings.xml
@@ -14,18 +14,12 @@
      limitations under the License.
 -->
 
-<com.android.systemui.statusbar.phone.QuickSettingsScrollView
+<com.android.systemui.statusbar.phone.QuickSettingsContainerView
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/quick_settings_container"
+    android:padding="@dimen/notification_side_padding"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:layout_marginBottom="@dimen/close_handle_underlap"
-    android:overScrollMode="ifContentScrolls"
-    >
-    <com.android.systemui.statusbar.phone.QuickSettingsContainerView
-        android:id="@+id/quick_settings_container"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:animateLayoutChanges="true"
-        android:columnCount="@integer/quick_settings_num_columns"
-        />
-</com.android.systemui.statusbar.phone.QuickSettingsScrollView>
\ No newline at end of file
+    android:background="#5f000000"
+    android:animateLayoutChanges="true"
+    android:columnCount="@integer/quick_settings_num_columns" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 8f4417e..8a3f090 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -41,7 +41,7 @@
         android:layout_width="50dp"
         android:layout_height="50dp"
         android:layout_gravity="right|top"
-        android:layout_marginTop="@*android:dimen/status_bar_height"
+        android:layout_marginTop="@dimen/status_bar_height"
         android:visibility="gone" />
 
     <LinearLayout
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 9176d24..2b01a06 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -27,14 +27,14 @@
 
     <include layout="@layout/status_bar"
         android:layout_width="match_parent"
-        android:layout_height="@*android:dimen/status_bar_height" />
+        android:layout_height="@dimen/status_bar_height" />
 
     <com.android.systemui.statusbar.phone.PanelHolder
         android:id="@+id/panel_holder"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_marginTop="@dimen/panel_holder_padding_top"
-        android:layout_marginBottom="@*android:dimen/navigation_bar_height">
+        android:layout_marginBottom="@dimen/navigation_bar_height">
         <include layout="@layout/status_bar_expanded"
             android:layout_width="@dimen/notification_panel_width"
             android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/values-land/config.xml b/packages/SystemUI/res/values-land/config.xml
index 6476d88..7223773 100644
--- a/packages/SystemUI/res/values-land/config.xml
+++ b/packages/SystemUI/res/values-land/config.xml
@@ -27,6 +27,9 @@
     <!-- The number of columns in the QuickSettings -->
     <integer name="quick_settings_num_columns">6</integer>
 
+    <!-- The maximum number of rows in the QuickSettings -->
+    <integer name="quick_settings_max_rows">2</integer>
+
     <!-- The number of columns that the top level tiles span in the QuickSettings -->
     <integer name="quick_settings_user_time_settings_tile_span">2</integer>
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index 440ead6..c6bc44d 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -26,6 +26,9 @@
     <!-- The number of columns in the QuickSettings -->
     <integer name="quick_settings_num_columns">3</integer>
 
+    <!-- The maximum number of rows in the QuickSettings -->
+    <integer name="quick_settings_max_rows">4</integer>
+
     <!-- The number of columns that the top level tiles span in the QuickSettings -->
     <integer name="quick_settings_user_time_settings_tile_span">1</integer>
 
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 73e3e05..f908a1e 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -81,6 +81,12 @@
     <!-- The number of columns in the QuickSettings -->
     <integer name="quick_settings_num_columns">3</integer>
 
+    <!-- The maximum number of rows in the QuickSettings -->
+    <integer name="quick_settings_max_rows">4</integer>
+
+    <!-- The maximum number of rows in the QuickSettings when on the keyguard -->
+    <integer name="quick_settings_max_rows_keyguard">3</integer>
+
     <!-- The number of columns that the top level tiles span in the QuickSettings -->
     <integer name="quick_settings_user_time_settings_tile_span">1</integer>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index e7959ab..9aacf42 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -269,4 +269,7 @@
 
     <!-- Camera affordance drag distance -->
     <dimen name="camera_drag_distance">100dp</dimen>
+
+    <dimen name="quick_settings_tmp_scrim_stroke_width">8dp</dimen>
+    <dimen name="quick_settings_tmp_scrim_text_size">30dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/internal.xml b/packages/SystemUI/res/values/internal.xml
new file mode 100644
index 0000000..ddaab942
--- /dev/null
+++ b/packages/SystemUI/res/values/internal.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<resources>
+    <dimen name="status_bar_height">@*android:dimen/status_bar_height</dimen>
+    <dimen name="navigation_bar_height">@*android:dimen/navigation_bar_height</dimen>
+    <drawable name="notification_quantum_bg">@*android:drawable/notification_quantum_bg</drawable>
+</resources>
+
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 6f93bed..45ac50b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -30,11 +30,14 @@
     public static final boolean DEBUG_GESTURES = true;
 
     PhoneStatusBar mStatusBar;
+    private View mHeader;
+    private View mKeyguardStatusView;
+
     private NotificationStackScrollLayout mNotificationStackScroller;
     private int[] mTempLocation = new int[2];
     private int[] mTempChildLocation = new int[2];
     private View mNotificationParent;
-
+    private boolean mTrackingSettings;
 
     public NotificationPanelView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -59,6 +62,8 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
 
+        mHeader = findViewById(R.id.header);
+        mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
         mNotificationStackScroller = (NotificationStackScrollLayout)
                 findViewById(R.id.notification_stack_scroller);
         mNotificationParent = findViewById(R.id.notification_container_parent);
@@ -99,9 +104,38 @@
     }
 
     @Override
+    public boolean onInterceptTouchEvent(MotionEvent event) {
+        // intercept for quick settings
+        if (event.getAction() == MotionEvent.ACTION_DOWN) {
+            final View target = mStatusBar.isOnKeyguard() ?  mKeyguardStatusView : mHeader;
+            final boolean inTarget = PhoneStatusBar.inBounds(target, event, true);
+            if (inTarget && !isInSettings()) {
+                mTrackingSettings = true;
+                return true;
+            }
+            if (!inTarget && isInSettings()) {
+                mTrackingSettings = true;
+                return true;
+            }
+        }
+        return super.onInterceptTouchEvent(event);
+    }
+
+    @Override
     public boolean onTouchEvent(MotionEvent event) {
         // TODO: Handle doublefinger swipe to notifications again. Look at history for a reference
         // implementation.
+        if (mTrackingSettings) {
+            mStatusBar.onSettingsEvent(event);
+            if (event.getAction() == MotionEvent.ACTION_UP
+                    || event.getAction() == MotionEvent.ACTION_CANCEL) {
+                mTrackingSettings = false;
+            }
+            return true;
+        }
+        if (isInSettings()) {
+            return true;
+        }
         return super.onTouchEvent(event);
     }
 
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 5f71516..d577070 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -73,6 +73,7 @@
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.ViewPropertyAnimator;
@@ -97,11 +98,9 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.InterceptedNotifications;
-import com.android.systemui.statusbar.LatestItemView;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.NotificationData.Entry;
 import com.android.systemui.statusbar.NotificationOverflowContainer;
-import com.android.systemui.statusbar.NotificationOverflowIconsView;
 import com.android.systemui.statusbar.SignalClusterView;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.policy.BatteryController;
@@ -233,8 +232,7 @@
     int mKeyguardMaxNotificationCount;
     View mDateTimeView;
     View mClearButton;
-    ImageView mSettingsButton, mNotificationButton;
-    View mKeyguardSettingsFlipButton;
+    FlipperButton mHeaderFlipper, mKeyguardFlipper;
 
     // carrier/wifi label
     private TextView mCarrierLabel;
@@ -314,9 +312,9 @@
             if (MULTIUSER_DEBUG) Log.d(TAG, String.format("User setup changed: " +
                     "selfChange=%s userSetup=%s mUserSetup=%s",
                     selfChange, userSetup, mUserSetup));
-            if (mSettingsButton != null && mHasFlipSettings) {
-                mSettingsButton.setVisibility(userSetup ? View.VISIBLE : View.INVISIBLE);
-            }
+            mHeaderFlipper.userSetup(userSetup);
+            mKeyguardFlipper.userSetup(userSetup);
+
             if (mSettingsPanel != null) {
                 mSettingsPanel.setEnabled(userSetup);
             }
@@ -371,6 +369,11 @@
 
     private Runnable mOnFlipRunnable;
     private InterceptedNotifications mIntercepted;
+    private VelocityTracker mSettingsTracker;
+    private float mSettingsDownY;
+    private boolean mSettingsCancelled;
+    private boolean mSettingsClosing;
+    private int mNotificationPadding;
 
     private final OnChildLocationsChangedListener mOnChildLocationsChangedListener =
             new OnChildLocationsChangedListener() {
@@ -631,35 +634,10 @@
             mDateTimeView.setEnabled(true);
         }
 
-        mSettingsButton = (ImageView) mStatusBarWindow.findViewById(R.id.settings_button);
-        if (mSettingsButton != null) {
-            mSettingsButton.setOnClickListener(mSettingsButtonListener);
-            if (mHasSettingsPanel) {
-                if (mStatusBarView.hasFullWidthNotifications()) {
-                    // the settings panel is hiding behind this button
-                    mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings);
-                    mSettingsButton.setVisibility(View.VISIBLE);
-                } else {
-                    // there is a settings panel, but it's on the other side of the (large) screen
-                    final View buttonHolder = mStatusBarWindow.findViewById(
-                            R.id.settings_button_holder);
-                    if (buttonHolder != null) {
-                        buttonHolder.setVisibility(View.GONE);
-                    }
-                }
-            } else {
-                // no settings panel, go straight to settings
-                mSettingsButton.setVisibility(View.VISIBLE);
-                mSettingsButton.setImageResource(R.drawable.ic_notify_settings);
-            }
-        }
-        if (mHasFlipSettings) {
-            mNotificationButton = (ImageView) mStatusBarWindow.findViewById(
-                    R.id.notification_button);
-            if (mNotificationButton != null) {
-                mNotificationButton.setOnClickListener(mNotificationButtonListener);
-            }
-        }
+        mHeaderFlipper = new FlipperButton(mNotificationPanelHeader
+                .findViewById(R.id.settings_button_holder));
+        ViewStub flipStub = (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_flip_stub);
+        mKeyguardFlipper = new FlipperButton(flipStub.inflate());
 
         if (!mNotificationPanelIsFullScreenWidth) {
             mNotificationPanel.setSystemUiVisibility(
@@ -735,6 +713,8 @@
         }
 
         // Quick Settings (where available, some restrictions apply)
+        mNotificationPadding = mContext.getResources()
+                .getDimensionPixelSize(R.dimen.notification_side_padding);
         if (mHasSettingsPanel) {
             // first, figure out where quick settings should be inflated
             final View settings_stub;
@@ -803,6 +783,87 @@
         return mStatusBarView;
     }
 
+    public boolean onSettingsEvent(MotionEvent event) {
+        if (mSettingsTracker != null) {
+            mSettingsTracker.addMovement(event);
+        }
+
+        if (event.getAction() == MotionEvent.ACTION_DOWN) {
+            mSettingsTracker = VelocityTracker.obtain();
+            mSettingsDownY = event.getY();
+            mSettingsCancelled = false;
+            mSettingsClosing = mFlipSettingsView.getVisibility() == View.VISIBLE;
+            mFlipSettingsView.setVisibility(View.VISIBLE);
+            mStackScroller.setVisibility(View.VISIBLE);
+            positionSettings(0);
+            if (!mSettingsClosing) {
+                mFlipSettingsView.setTranslationY(-mNotificationPanel.getMeasuredHeight());
+            }
+            dispatchSettingsEvent(event);
+        } else if (mSettingsTracker != null && (event.getAction() == MotionEvent.ACTION_UP
+                || event.getAction() == MotionEvent.ACTION_CANCEL)) {
+            final float dy = event.getY() - mSettingsDownY;
+            final FlipperButton flipper = mOnKeyguard ? mKeyguardFlipper : mHeaderFlipper;
+            final boolean inButton = flipper.inHolderBounds(event);
+            final int slop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+            final boolean qsTap = mSettingsClosing &&  Math.abs(dy) < slop;
+            if (!qsTap && !inButton) {
+                mSettingsTracker.computeCurrentVelocity(1000);
+                final float vy = mSettingsTracker.getYVelocity();
+                if (dy <= slop || vy <= 0) {
+                    flipToNotifications();
+                } else {
+                    flipToSettings();
+                }
+            }
+            mSettingsTracker.recycle();
+            mSettingsTracker = null;
+            dispatchSettingsEvent(event);
+        } else if (mSettingsTracker != null && event.getAction() == MotionEvent.ACTION_MOVE) {
+            final float dy = event.getY() - mSettingsDownY;
+            positionSettings(dy);
+            if (mSettingsClosing) {
+                final boolean qsTap =
+                        Math.abs(dy) < ViewConfiguration.get(mContext).getScaledTouchSlop();
+                if (!mSettingsCancelled && !qsTap) {
+                    MotionEvent cancelEvent = MotionEvent.obtainNoHistory(event);
+                    cancelEvent.setAction(MotionEvent.ACTION_CANCEL);
+                    dispatchSettingsEvent(cancelEvent);
+                    mSettingsCancelled = true;
+                }
+            } else {
+                dispatchSettingsEvent(event);
+            }
+        }
+        return true;
+    }
+
+    private void dispatchSettingsEvent(MotionEvent event) {
+        final View target = mSettingsClosing ? mFlipSettingsView : mNotificationPanelHeader;
+        final int[] targetLoc = new int[2];
+        target.getLocationInWindow(targetLoc);
+        final int[] panelLoc = new int[2];
+        mNotificationPanel.getLocationInWindow(panelLoc);
+        final int dx = targetLoc[0] - panelLoc[0];
+        final int dy = targetLoc[1] - panelLoc[1];
+        event.offsetLocation(-dx, -dy);
+        target.dispatchTouchEvent(event);
+    }
+
+    private void positionSettings(float dy) {
+        final int h = mFlipSettingsView.getMeasuredHeight();
+        final int ph = mNotificationPanel.getMeasuredHeight();
+        if (mSettingsClosing) {
+            dy = Math.min(Math.max(-ph, dy), 0);
+            mFlipSettingsView.setTranslationY(dy);
+            mStackScroller.setTranslationY(ph + dy);
+        } else {
+            dy = Math.min(Math.max(0, dy), ph);
+            mFlipSettingsView.setTranslationY(-h + dy - mNotificationPadding * 2);
+            mStackScroller.setTranslationY(dy);
+        }
+    }
+
     private void startKeyguard() {
         KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
         mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
@@ -1163,17 +1224,8 @@
             ((ImageView)mClearButton).setImageResource(R.drawable.ic_notify_clear);
         }
 
-        if (mSettingsButton != null) {
-            // Force asset reloading
-            mSettingsButton.setImageDrawable(null);
-            mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings);
-        }
-
-        if (mNotificationButton != null) {
-            // Force asset reloading
-            mNotificationButton.setImageDrawable(null);
-            mNotificationButton.setImageResource(R.drawable.ic_notifications);
-        }
+        mHeaderFlipper.refreshLayout();
+        mKeyguardFlipper.refreshLayout();
 
         refreshAllStatusBarIcons();
     }
@@ -1228,9 +1280,8 @@
             }
         }
 
-        if (mSettingsButton != null) {
-            mSettingsButton.setEnabled(isDeviceProvisioned());
-        }
+        mHeaderFlipper.provisionCheck(provisioned);
+        mKeyguardFlipper.provisionCheck(provisioned);
     }
 
     @Override
@@ -1647,6 +1698,9 @@
 
             mStatusBarWindow.cancelExpandHelper();
             mStatusBarView.collapseAllPanels(true);
+            if (isFlippedToSettings()) {
+                flipToNotifications();
+            }
         }
     }
 
@@ -1694,8 +1748,7 @@
     final int FLIP_DURATION_IN = 225;
     final int FLIP_DURATION = (FLIP_DURATION_IN + FLIP_DURATION_OUT);
 
-    Animator mScrollViewAnim, mFlipSettingsViewAnim, mNotificationButtonAnim,
-        mSettingsButtonAnim, mClearButtonAnim;
+    Animator mScrollViewAnim, mFlipSettingsViewAnim, mClearButtonAnim;
 
     @Override
     public void animateExpandNotificationsPanel() {
@@ -1715,33 +1768,29 @@
     public void flipToNotifications() {
         if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
         if (mScrollViewAnim != null) mScrollViewAnim.cancel();
-        if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
-        if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
+        mHeaderFlipper.cancel();
+        mKeyguardFlipper.cancel();
         if (mClearButtonAnim != null) mClearButtonAnim.cancel();
 
         mStackScroller.setVisibility(View.VISIBLE);
+        final int h = mNotificationPanel.getMeasuredHeight();
+        final float settingsY = mSettingsTracker != null ? mFlipSettingsView.getTranslationY() : 0;
+        final float scrollerY = mSettingsTracker != null ? mStackScroller.getTranslationY() : h;
         mScrollViewAnim = start(
-            startDelay(FLIP_DURATION_OUT,
+            startDelay(0,
                 interpolator(mDecelerateInterpolator,
-                    ObjectAnimator.ofFloat(mStackScroller, View.SCALE_X, 0f, 1f)
-                        .setDuration(FLIP_DURATION_IN)
+                    ObjectAnimator.ofFloat(mStackScroller, View.TRANSLATION_Y, scrollerY, 0)
+                        .setDuration(FLIP_DURATION)
                     )));
         mFlipSettingsViewAnim = start(
             setVisibilityWhenDone(
-                interpolator(mAccelerateInterpolator,
-                        ObjectAnimator.ofFloat(mFlipSettingsView, View.SCALE_X, 1f, 0f)
+                interpolator(mDecelerateInterpolator,
+                        ObjectAnimator.ofFloat(mFlipSettingsView, View.TRANSLATION_Y, settingsY, -h)
                         )
-                    .setDuration(FLIP_DURATION_OUT),
-                mFlipSettingsView, View.INVISIBLE));
-        mNotificationButtonAnim = start(
-            setVisibilityWhenDone(
-                ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 0f)
                     .setDuration(FLIP_DURATION),
-                mNotificationButton, View.INVISIBLE));
-        mSettingsButton.setVisibility(View.VISIBLE);
-        mSettingsButtonAnim = start(
-            ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 1f)
-                .setDuration(FLIP_DURATION));
+                mFlipSettingsView, View.INVISIBLE));
+        mHeaderFlipper.flipToNotifications();
+        mKeyguardFlipper.flipToNotifications();
         mClearButton.setVisibility(View.VISIBLE);
         mClearButton.setAlpha(0f);
         setAreThereNotifications(); // this will show/hide the button as necessary
@@ -1767,7 +1816,8 @@
 
         if (mHasFlipSettings) {
             mNotificationPanel.expand();
-            if (mFlipSettingsView.getVisibility() != View.VISIBLE) {
+            if (mFlipSettingsView.getVisibility() != View.VISIBLE
+                    || mFlipSettingsView.getTranslationY() < 0) {
                 flipToSettings();
             }
         } else if (mSettingsPanel != null) {
@@ -1777,23 +1827,6 @@
         if (false) postStartTracing();
     }
 
-    public void switchToSettings() {
-        // Settings are not available in setup
-        if (!mUserSetup) return;
-
-        mFlipSettingsView.setScaleX(1f);
-        mFlipSettingsView.setVisibility(View.VISIBLE);
-        mSettingsButton.setVisibility(View.GONE);
-        mStackScroller.setVisibility(View.GONE);
-        mStackScroller.setScaleX(0f);
-        mNotificationButton.setVisibility(View.VISIBLE);
-        mNotificationButton.setAlpha(1f);
-        mClearButton.setVisibility(View.GONE);
-        if (mOnFlipRunnable != null) {
-            mOnFlipRunnable.run();
-        }
-    }
-
     public boolean isFlippedToSettings() {
         if (mFlipSettingsView != null) {
             return mFlipSettingsView.getVisibility() == View.VISIBLE;
@@ -1807,34 +1840,29 @@
 
         if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
         if (mScrollViewAnim != null) mScrollViewAnim.cancel();
-        if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
-        if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
+        mHeaderFlipper.cancel();
+        mKeyguardFlipper.cancel();
         if (mClearButtonAnim != null) mClearButtonAnim.cancel();
 
         mFlipSettingsView.setVisibility(View.VISIBLE);
-        mFlipSettingsView.setScaleX(0f);
+        final int h = mNotificationPanel.getMeasuredHeight();
+        final float settingsY = mSettingsTracker != null ? mFlipSettingsView.getTranslationY() : -h;
+        final float scrollerY = mSettingsTracker != null ? mStackScroller.getTranslationY() : 0;
         mFlipSettingsViewAnim = start(
-            startDelay(FLIP_DURATION_OUT,
-                interpolator(mDecelerateInterpolator,
-                    ObjectAnimator.ofFloat(mFlipSettingsView, View.SCALE_X, 0f, 1f)
-                        .setDuration(FLIP_DURATION_IN)
-                    )));
+                startDelay(0,
+                    interpolator(mDecelerateInterpolator,
+                        ObjectAnimator.ofFloat(mFlipSettingsView, View.TRANSLATION_Y, settingsY, 0f)
+                            .setDuration(FLIP_DURATION)
+                        )));
         mScrollViewAnim = start(
             setVisibilityWhenDone(
-                interpolator(mAccelerateInterpolator,
-                        ObjectAnimator.ofFloat(mStackScroller, View.SCALE_X, 1f, 0f)
+                interpolator(mDecelerateInterpolator,
+                        ObjectAnimator.ofFloat(mStackScroller, View.TRANSLATION_Y, scrollerY, h)
                         )
-                    .setDuration(FLIP_DURATION_OUT),
-                    mStackScroller, View.INVISIBLE));
-        mSettingsButtonAnim = start(
-            setVisibilityWhenDone(
-                ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f)
                     .setDuration(FLIP_DURATION),
                     mStackScroller, View.INVISIBLE));
-        mNotificationButton.setVisibility(View.VISIBLE);
-        mNotificationButtonAnim = start(
-            ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f)
-                .setDuration(FLIP_DURATION));
+        mHeaderFlipper.flipToSettings();
+        mKeyguardFlipper.flipToSettings();
         mClearButtonAnim = start(
             setVisibilityWhenDone(
                 ObjectAnimator.ofFloat(mClearButton, View.ALPHA, 0f)
@@ -1883,18 +1911,16 @@
             // reset things to their proper state
             if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
             if (mScrollViewAnim != null) mScrollViewAnim.cancel();
-            if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
-            if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
             if (mClearButtonAnim != null) mClearButtonAnim.cancel();
 
-            mStackScroller.setScaleX(1f);
             mStackScroller.setVisibility(View.VISIBLE);
-            mSettingsButton.setAlpha(1f);
-            mSettingsButton.setVisibility(View.VISIBLE);
             mNotificationPanel.setVisibility(View.GONE);
             mFlipSettingsView.setVisibility(View.GONE);
-            mNotificationButton.setVisibility(View.GONE);
+
             setAreThereNotifications(); // show the clear button
+
+            mHeaderFlipper.reset();
+            mKeyguardFlipper.reset();
         }
 
         mExpandedVisible = false;
@@ -2947,15 +2973,9 @@
         }
         mKeyguardStatusView.setVisibility(View.VISIBLE);
         mNotificationPanelHeader.setVisibility(View.GONE);
-        if (mKeyguardSettingsFlipButton == null) {
-            ViewStub flipStub = (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_flip_stub);
-            mKeyguardSettingsFlipButton = flipStub.inflate();
-            installSettingsButton(mKeyguardSettingsFlipButton);
-        }
-        mKeyguardSettingsFlipButton.setVisibility(View.VISIBLE);
-        mKeyguardSettingsFlipButton.findViewById(R.id.settings_button).setVisibility(View.VISIBLE);
-        mKeyguardSettingsFlipButton.findViewById(R.id.notification_button)
-                .setVisibility(View.INVISIBLE);
+
+        mKeyguardFlipper.setVisibility(View.VISIBLE);
+        mSettingsContainer.setKeyguardShowing(true);
         updateRowStates();
     }
 
@@ -2963,9 +2983,9 @@
         mOnKeyguard = false;
         mKeyguardStatusView.setVisibility(View.GONE);
         mNotificationPanelHeader.setVisibility(View.VISIBLE);
-        if (mKeyguardSettingsFlipButton != null) {
-            mKeyguardSettingsFlipButton.setVisibility(View.GONE);
-        }
+
+        mKeyguardFlipper.setVisibility(View.GONE);
+        mSettingsContainer.setKeyguardShowing(false);
         updateRowStates();
         instantCollapseNotificationPanel();
     }
@@ -3030,39 +3050,112 @@
         }
     }
 
-    private void installSettingsButton(View parent) {
-        final ImageView settingsButton =
-                (ImageView) mStatusBarWindow.findViewById(R.id.settings_button);
-        final ImageView notificationButton =
-                (ImageView) mStatusBarWindow.findViewById(R.id.notification_button);
-        if (settingsButton != null) {
-            settingsButton.setOnClickListener(new View.OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    animateExpandSettingsPanel();
-                    v.setVisibility(View.INVISIBLE);
-                    notificationButton.setVisibility(View.VISIBLE);
+    public static boolean inBounds(View view, MotionEvent event, boolean orAbove) {
+        final int[] location = new int[2];
+        view.getLocationInWindow(location);
+        final int rx = (int) event.getRawX();
+        final int ry = (int) event.getRawY();
+        return rx >= location[0] && rx <= location[0] + view.getMeasuredWidth()
+                && (orAbove || ry >= location[1]) && ry <= location[1] + view.getMeasuredHeight();
+    }
+
+    private final class FlipperButton {
+        private final View mHolder;
+
+        private ImageView mSettingsButton, mNotificationButton;
+        private Animator mSettingsButtonAnim, mNotificationButtonAnim;
+
+        public FlipperButton(View holder) {
+            mHolder = holder;
+            mSettingsButton = (ImageView) holder.findViewById(R.id.settings_button);
+            if (mSettingsButton != null) {
+                mSettingsButton.setOnClickListener(mSettingsButtonListener);
+                if (mHasSettingsPanel) {
+                    // the settings panel is hiding behind this button
+                    mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings);
+                    mSettingsButton.setVisibility(View.VISIBLE);
+                } else {
+                    // no settings panel, go straight to settings
+                    mSettingsButton.setVisibility(View.VISIBLE);
+                    mSettingsButton.setImageResource(R.drawable.ic_notify_settings);
                 }
-            });
-            settingsButton.setVisibility(View.VISIBLE);
-            if (mHasSettingsPanel) {
-                // the settings panel is hiding behind this button
-                settingsButton.setImageResource(R.drawable.ic_notify_quicksettings);
-            } else {
-                // no settings panel, go straight to settings
-                settingsButton.setImageResource(R.drawable.ic_notify_settings);
+            }
+            if (mHasFlipSettings) {
+                mNotificationButton = (ImageView) holder.findViewById(R.id.notification_button);
+                if (mNotificationButton != null) {
+                    mNotificationButton.setOnClickListener(mNotificationButtonListener);
+                }
             }
         }
-        if (notificationButton != null) {
-            notificationButton.setVisibility(View.INVISIBLE);
-            notificationButton.setOnClickListener(new View.OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    flipToNotifications();
-                    v.setVisibility(View.INVISIBLE);
-                    settingsButton.setVisibility(View.VISIBLE);
-                }
-            });
+
+        public boolean inHolderBounds(MotionEvent event) {
+            return inBounds(mHolder, event, false);
+        }
+
+        public void provisionCheck(boolean provisioned) {
+            if (mSettingsButton != null) {
+                mSettingsButton.setEnabled(provisioned);
+            }
+        }
+
+        public void userSetup(boolean userSetup) {
+            if (mSettingsButton != null && mHasFlipSettings) {
+                mSettingsButton.setVisibility(userSetup ? View.VISIBLE : View.INVISIBLE);
+            }
+        }
+
+        public void reset() {
+            cancel();
+            mSettingsButton.setVisibility(View.VISIBLE);
+            mNotificationButton.setVisibility(View.GONE);
+        }
+
+        public void refreshLayout() {
+            if (mSettingsButton != null) {
+                // Force asset reloading
+                mSettingsButton.setImageDrawable(null);
+                mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings);
+            }
+
+            if (mNotificationButton != null) {
+                // Force asset reloading
+                mNotificationButton.setImageDrawable(null);
+                mNotificationButton.setImageResource(R.drawable.ic_notifications);
+            }
+        }
+
+        public void flipToSettings() {
+            mSettingsButtonAnim = start(
+                setVisibilityWhenDone(
+                    ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f)
+                        .setDuration(FLIP_DURATION),
+                    mStackScroller, View.INVISIBLE));
+            mNotificationButton.setVisibility(View.VISIBLE);
+            mNotificationButtonAnim = start(
+                ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f)
+                    .setDuration(FLIP_DURATION));
+        }
+
+        public void flipToNotifications() {
+            mNotificationButtonAnim = start(
+                setVisibilityWhenDone(
+                    ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 0f)
+                        .setDuration(FLIP_DURATION),
+                    mNotificationButton, View.INVISIBLE));
+
+            mSettingsButton.setVisibility(View.VISIBLE);
+            mSettingsButtonAnim = start(
+                ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 1f)
+                    .setDuration(FLIP_DURATION));
+        }
+
+        public void cancel() {
+            if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
+            if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
+        }
+
+        public void setVisibility(int vis) {
+            mHolder.setVisibility(vis);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java
index 17ee017..02e9c0d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java
@@ -19,7 +19,13 @@
 import android.animation.LayoutTransition;
 import android.content.Context;
 import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.graphics.Typeface;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
@@ -31,30 +37,58 @@
  */
 class QuickSettingsContainerView extends FrameLayout {
 
+    private static boolean sShowScrim = true;
+
+    private final Context mContext;
+
     // The number of columns in the QuickSettings grid
     private int mNumColumns;
 
+    private boolean mKeyguardShowing;
+    private int mMaxRows;
+    private int mMaxRowsOnKeyguard;
+
     // The gap between tiles in the QuickSettings grid
     private float mCellGap;
 
+    private ScrimView mScrim;
+
     public QuickSettingsContainerView(Context context, AttributeSet attrs) {
         super(context, attrs);
-
+        mContext = context;
         updateResources();
     }
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-
+        mScrim = new ScrimView(mContext);
+        addView(mScrim);
+        mScrim.setAlpha(sShowScrim ? 1 : 0);
         // TODO: Setup the layout transitions
         LayoutTransition transitions = getLayoutTransition();
     }
 
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (mScrim.getAlpha() == 1) {
+            mScrim.animate().alpha(0).setDuration(1000).start();
+            sShowScrim = false;
+        }
+        return super.onTouchEvent(event);
+    }
+
     void updateResources() {
         Resources r = getContext().getResources();
         mCellGap = r.getDimension(R.dimen.quick_settings_cell_gap);
         mNumColumns = r.getInteger(R.integer.quick_settings_num_columns);
+        mMaxRows = r.getInteger(R.integer.quick_settings_max_rows);
+        mMaxRowsOnKeyguard = r.getInteger(R.integer.quick_settings_max_rows_keyguard);
+        requestLayout();
+    }
+
+    void setKeyguardShowing(boolean showing) {
+        mKeyguardShowing = showing;
         requestLayout();
     }
 
@@ -71,10 +105,18 @@
         final int N = getChildCount();
         int cellHeight = 0;
         int cursor = 0;
+        int maxRows = mKeyguardShowing ? mMaxRowsOnKeyguard : mMaxRows;
+
         for (int i = 0; i < N; ++i) {
+            if (getChildAt(i).equals(mScrim)) {
+                continue;
+            }
             // Update the child's width
             QuickSettingsTileView v = (QuickSettingsTileView) getChildAt(i);
             if (v.getVisibility() != View.GONE) {
+                int row = (int) (cursor / mNumColumns);
+                if (row >= maxRows) continue;
+
                 ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
                 int colSpan = v.getColumnSpan();
                 lp.width = (int) ((colSpan * cellWidth) + (colSpan - 1) * mCellGap);
@@ -102,6 +144,7 @@
 
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        mScrim.bringToFront();
         final int N = getChildCount();
         final boolean isLayoutRtl = isLayoutRtl();
         final int width = getWidth();
@@ -109,8 +152,18 @@
         int x = getPaddingStart();
         int y = getPaddingTop();
         int cursor = 0;
+        int maxRows = mKeyguardShowing ? mMaxRowsOnKeyguard : mMaxRows;
 
         for (int i = 0; i < N; ++i) {
+            if (getChildAt(i).equals(mScrim)) {
+                int w = right - left - getPaddingLeft() - getPaddingRight();
+                int h = bottom - top - getPaddingTop() - getPaddingBottom();
+                mScrim.measure(
+                        MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY),
+                        MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY));
+                mScrim.layout(getPaddingLeft(), getPaddingTop(), right, bottom);
+                continue;
+            }
             QuickSettingsTileView child = (QuickSettingsTileView) getChildAt(i);
             ViewGroup.LayoutParams lp = child.getLayoutParams();
             if (child.getVisibility() != GONE) {
@@ -121,6 +174,7 @@
                 final int childHeight = lp.height;
 
                 int row = (int) (cursor / mNumColumns);
+                if (row >= maxRows) continue;
 
                 // Push the item to the next row if it can't fit on this one
                 if ((col + colSpan) > mNumColumns) {
@@ -150,4 +204,87 @@
             }
         }
     }
+
+    private static final class ScrimView extends View {
+        private static final int COLOR = 0xaf4285f4;
+
+        private final Paint mLinePaint;
+        private final int mStrokeWidth;
+        private final Rect mTmp = new Rect();
+        private final Paint mTextPaint;
+        private final int mTextSize;
+
+        public ScrimView(Context context) {
+            super(context);
+            setFocusable(false);
+            final Resources res = context.getResources();
+            mStrokeWidth = res.getDimensionPixelSize(R.dimen.quick_settings_tmp_scrim_stroke_width);
+            mTextSize = res.getDimensionPixelSize(R.dimen.quick_settings_tmp_scrim_text_size);
+
+            mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            mLinePaint.setColor(COLOR);
+            mLinePaint.setStrokeWidth(mStrokeWidth);
+            mLinePaint.setStrokeJoin(Paint.Join.ROUND);
+            mLinePaint.setStrokeCap(Paint.Cap.ROUND);
+            mLinePaint.setStyle(Paint.Style.STROKE);
+
+            mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            mTextPaint.setColor(COLOR);
+            mTextPaint.setTextSize(mTextSize);
+            mTextPaint.setTypeface(Typeface.create("sans-serif-condensed", Typeface.BOLD));
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            final int w = getMeasuredWidth();
+            final int h = getMeasuredHeight();
+            final int f = mStrokeWidth * 3 / 4;
+
+            canvas.drawPath(line(f, h / 2, w - f, h / 2), mLinePaint);
+            canvas.drawPath(line(w / 2, f, w / 2, h - f), mLinePaint);
+
+            final int s = mStrokeWidth;
+            mTextPaint.setTextAlign(Paint.Align.RIGHT);
+            canvas.drawText("FUTURE", w / 2 - s, h / 2 - s, mTextPaint);
+            mTextPaint.setTextAlign(Paint.Align.LEFT);
+            canvas.drawText("SITE OF", w / 2 + s, h / 2 - s , mTextPaint);
+            mTextPaint.setTextAlign(Paint.Align.RIGHT);
+            drawUnder(canvas, "QUANTUM", w / 2 - s, h / 2 + s);
+            mTextPaint.setTextAlign(Paint.Align.LEFT);
+            drawUnder(canvas, "SETTINGS", w / 2 + s, h / 2 + s);
+        }
+
+        private void drawUnder(Canvas c, String text, float x, float y) {
+            if (mTmp.isEmpty()) {
+                mTextPaint.getTextBounds(text, 0, text.length(), mTmp);
+            }
+            c.drawText(text, x, y + mTmp.height() * .85f, mTextPaint);
+        }
+
+        private Path line(float x1, float y1, float x2, float y2) {
+            final int a = mStrokeWidth * 2;
+            final Path p = new Path();
+            p.moveTo(x1, y1);
+            p.lineTo(x2, y2);
+            if (y1 == y2) {
+                p.moveTo(x1 + a, y1 + a);
+                p.lineTo(x1, y1);
+                p.lineTo(x1 + a, y1 - a);
+
+                p.moveTo(x2 - a, y2 - a);
+                p.lineTo(x2, y2);
+                p.lineTo(x2 - a, y2 + a);
+            }
+            if (x1 == x2) {
+                p.moveTo(x1 - a, y1 + a);
+                p.lineTo(x1, y1);
+                p.lineTo(x1 + a, y1 + a);
+
+                p.moveTo(x2 - a, y2 - a);
+                p.lineTo(x2, y2);
+                p.lineTo(x2 + a, y2 - a);
+            }
+            return p;
+        }
+    }
 }
\ No newline at end of file