Allow status bar panels to be on top of the status bar.

Change-Id: I3c74ece5f7042e6302717f4263746d59d5447ec9
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 784951f..e658df4 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -171,6 +171,7 @@
             @ViewDebug.IntToString(from = TYPE_SYSTEM_OVERLAY, to = "TYPE_SYSTEM_OVERLAY"),
             @ViewDebug.IntToString(from = TYPE_PRIORITY_PHONE, to = "TYPE_PRIORITY_PHONE"),
             @ViewDebug.IntToString(from = TYPE_STATUS_BAR_PANEL, to = "TYPE_STATUS_BAR_PANEL"),
+            @ViewDebug.IntToString(from = TYPE_STATUS_BAR_SUB_PANEL, to = "TYPE_STATUS_BAR_SUB_PANEL"),
             @ViewDebug.IntToString(from = TYPE_SYSTEM_DIALOG, to = "TYPE_SYSTEM_DIALOG"),
             @ViewDebug.IntToString(from = TYPE_KEYGUARD_DIALOG, to = "TYPE_KEYGUARD_DIALOG"),
             @ViewDebug.IntToString(from = TYPE_SYSTEM_ERROR, to = "TYPE_SYSTEM_ERROR"),
@@ -351,7 +352,7 @@
         public static final int TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13;
 
         /**
-         * Window type: panel that slides out from the status bar
+         * Window type: panel that slides out from over the status bar
          */
         public static final int TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW+14;
 
@@ -375,6 +376,12 @@
         public static final int TYPE_DRAG               = FIRST_SYSTEM_WINDOW+16;
 
         /**
+         * Window type: panel that slides out from under the status bar
+         */
+        public static final int TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17;
+
+
+        /**
          * End of types of system windows.
          */
         public static final int LAST_SYSTEM_WINDOW      = 2999;
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
index 15a3925..d0812de 100644
--- a/include/ui/InputDispatcher.h
+++ b/include/ui/InputDispatcher.h
@@ -179,8 +179,10 @@
         TYPE_INPUT_METHOD       = FIRST_SYSTEM_WINDOW+11,
         TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
         TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13,
-        TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW+14,
+        TYPE_STATUS_BAR_SUB_PANEL  = FIRST_SYSTEM_WINDOW+14,
         TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15,
+        TYPE_DRAG               = FIRST_SYSTEM_WINDOW+16,
+        TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW+17,
         LAST_SYSTEM_WINDOW      = 2999,
     };
 
diff --git a/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml b/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml
index 5fa8b3b..e9e23a5 100644
--- a/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml
+++ b/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml
@@ -20,9 +20,8 @@
     android:layout_height="match_parent"
     android:layout_width="match_parent"
     android:animateLayoutChanges="true"
-    android:background="@drawable/bg_scrim_notification"
     android:paddingTop="32dp"
-    android:paddingBottom="32dp"
+    android:paddingBottom="@dimen/status_bar_panel_bottom_offset"
     android:orientation="vertical"
     android:gravity="right"
     >
diff --git a/packages/SystemUI/res/values-xlarge/dimens.xml b/packages/SystemUI/res/values-xlarge/dimens.xml
index 009b7a8..5ae3982 100644
--- a/packages/SystemUI/res/values-xlarge/dimens.xml
+++ b/packages/SystemUI/res/values-xlarge/dimens.xml
@@ -22,6 +22,8 @@
     <dimen name="notification_large_icon_height">60dp</dimen>
     <!-- The width of the ticker, including the icon -->
     <dimen name="notification_ticker_width">360dp</dimen>
+    <!-- Status bar panel bottom offset (height of status bar - overlap) -->
+    <dimen name="status_bar_panel_bottom_offset">36dp</dimen>
 </resources>
 
 
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 2dad81c..915fa2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -294,7 +294,7 @@
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.WRAP_CONTENT,
-                WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
+                WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                     | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                     | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
@@ -1254,7 +1254,7 @@
         lp = new WindowManager.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.MATCH_PARENT,
-                WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
+                WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
@@ -1282,7 +1282,7 @@
         lp.height = getExpandedHeight();
         lp.x = 0;
         mTrackingPosition = lp.y = -disph; // sufficiently large negative
-        lp.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
+        lp.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
         lp.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
index 7f743b2..b05fe1a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
@@ -163,6 +163,7 @@
                 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                     | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                    | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                     | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
                 PixelFormat.TRANSLUCENT);
         lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 1c1a46e..5c8d88b 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -103,6 +103,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
@@ -148,31 +149,32 @@
     static final int APPLICATION_LAYER = 2;
     static final int PHONE_LAYER = 3;
     static final int SEARCH_BAR_LAYER = 4;
-    static final int STATUS_BAR_PANEL_LAYER = 5;
+    static final int STATUS_BAR_SUB_PANEL_LAYER = 5;
     static final int SYSTEM_DIALOG_LAYER = 6;
     // toasts and the plugged-in battery thing
     static final int TOAST_LAYER = 7;
     static final int STATUS_BAR_LAYER = 8;
+    static final int STATUS_BAR_PANEL_LAYER = 9;
     // SIM errors and unlock.  Not sure if this really should be in a high layer.
-    static final int PRIORITY_PHONE_LAYER = 9;
+    static final int PRIORITY_PHONE_LAYER = 10;
     // like the ANR / app crashed dialogs
-    static final int SYSTEM_ALERT_LAYER = 10;
+    static final int SYSTEM_ALERT_LAYER = 11;
     // system-level error dialogs
-    static final int SYSTEM_ERROR_LAYER = 11;
+    static final int SYSTEM_ERROR_LAYER = 12;
     // on-screen keyboards and other such input method user interfaces go here.
-    static final int INPUT_METHOD_LAYER = 12;
+    static final int INPUT_METHOD_LAYER = 13;
     // on-screen keyboards and other such input method user interfaces go here.
-    static final int INPUT_METHOD_DIALOG_LAYER = 13;
+    static final int INPUT_METHOD_DIALOG_LAYER = 14;
     // the keyguard; nothing on top of these can take focus, since they are
     // responsible for power management when displayed.
-    static final int KEYGUARD_LAYER = 14;
-    static final int KEYGUARD_DIALOG_LAYER = 15;
+    static final int KEYGUARD_LAYER = 15;
+    static final int KEYGUARD_DIALOG_LAYER = 16;
     // the drag layer: input for drag-and-drop is associated with this window,
     // which sits above all other focusable windows
-    static final int DRAG_LAYER = 16;
+    static final int DRAG_LAYER = 17;
     // things in here CAN NOT take focus, but are shown on top of everything else.
-    static final int SYSTEM_OVERLAY_LAYER = 17;
-    static final int SECURE_SYSTEM_OVERLAY_LAYER = 18;
+    static final int SYSTEM_OVERLAY_LAYER = 18;
+    static final int SECURE_SYSTEM_OVERLAY_LAYER = 19;
 
     static final int APPLICATION_MEDIA_SUBLAYER = -2;
     static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
@@ -274,10 +276,15 @@
         }
     };
     
+    // The current size of the screen; really; (ir)regardless of whether the status
+    // bar can be hidden or not
+    int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
+    int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight;
     // The current size of the screen; these may be different than (0,0)-(dw,dh)
     // if the status bar can't be hidden; in that case it effectively carves out
     // that area of the display from all other windows.
-    int mScreenLeft, mScreenTop, mScreenWidth, mScreenHeight;
+    int mRestrictedScreenLeft, mRestrictedScreenTop;
+    int mRestrictedScreenWidth, mRestrictedScreenHeight;
     // During layout, the current screen borders with all outer decoration
     // (status bar, input method dock) accounted for.
     int mCurLeft, mCurTop, mCurRight, mCurBottom;
@@ -906,6 +913,8 @@
             return STATUS_BAR_LAYER;
         case TYPE_STATUS_BAR_PANEL:
             return STATUS_BAR_PANEL_LAYER;
+        case TYPE_STATUS_BAR_SUB_PANEL:
+            return STATUS_BAR_SUB_PANEL_LAYER;
         case TYPE_SYSTEM_DIALOG:
             return SYSTEM_DIALOG_LAYER;
         case TYPE_SEARCH_BAR:
@@ -1126,6 +1135,12 @@
                         "PhoneWindowManager");
                 mStatusBarPanels.add(win);
                 break;
+            case TYPE_STATUS_BAR_SUB_PANEL:
+                mContext.enforceCallingOrSelfPermission(
+                        android.Manifest.permission.STATUS_BAR_SERVICE,
+                        "PhoneWindowManager");
+                mStatusBarPanels.add(win);
+                break;
             case TYPE_KEYGUARD:
                 if (mKeyguard != null) {
                     return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
@@ -1401,8 +1416,8 @@
         if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
                 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
             contentInset.set(mCurLeft, mCurTop,
-                    (mScreenLeft+mScreenWidth) - mCurRight,
-                    (mScreenTop+mScreenHeight) - mCurBottom);
+                    (mRestrictedScreenLeft+mRestrictedScreenWidth) - mCurRight,
+                    (mRestrictedScreenTop+mRestrictedScreenHeight) - mCurBottom);
         } else {
             contentInset.setEmpty();
         }
@@ -1410,9 +1425,12 @@
     
     /** {@inheritDoc} */
     public void beginLayoutLw(int displayWidth, int displayHeight) {
-        mScreenLeft = mScreenTop = 0;
-        mScreenWidth = displayWidth;
-        mScreenHeight = displayHeight;
+        mUnrestrictedScreenLeft = mUnrestrictedScreenTop = 0;
+        mUnrestrictedScreenWidth = displayWidth;
+        mUnrestrictedScreenHeight = displayHeight;
+        mRestrictedScreenLeft = mRestrictedScreenTop = 0;
+        mRestrictedScreenWidth = displayWidth;
+        mRestrictedScreenHeight = displayHeight;
         mDockLeft = mContentLeft = mCurLeft = 0;
         mDockTop = mContentTop = mCurTop = 0;
         mDockRight = mContentRight = mCurRight = displayWidth;
@@ -1451,16 +1469,18 @@
                 } else {
                     // Status bar can't go away; the part of the screen it
                     // covers does not exist for anything behind it.
-                    if (mScreenTop == r.top) {
-                        mScreenTop = r.bottom;
-                        mScreenHeight -= (r.bottom-r.top);
-                    } else if ((mScreenHeight-mScreenTop) == r.bottom) {
-                        mScreenHeight -= (r.bottom-r.top);
+                    if (mRestrictedScreenTop == r.top) {
+                        mRestrictedScreenTop = r.bottom;
+                        mRestrictedScreenHeight -= (r.bottom-r.top);
+                    } else if ((mRestrictedScreenHeight-mRestrictedScreenTop) == r.bottom) {
+                        mRestrictedScreenHeight -= (r.bottom-r.top);
                     }
-                    mContentTop = mCurTop = mDockTop = mScreenTop;
-                    mContentBottom = mCurBottom = mDockBottom = mScreenTop+mScreenHeight;
-                    if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mScreenTop=" + mScreenTop
-                            + " mScreenHeight=" + mScreenHeight);
+                    mContentTop = mCurTop = mDockTop = mRestrictedScreenTop;
+                    mContentBottom = mCurBottom = mDockBottom
+                            = mRestrictedScreenTop + mRestrictedScreenHeight;
+                    if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mRestrictedScreenTop="
+                            + mRestrictedScreenTop
+                            + " mRestrictedScreenHeight=" + mRestrictedScreenHeight);
                 }
             }
         }
@@ -1552,10 +1572,21 @@
                     // frame is the same as the one we are attached to.
                     setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf);
                 } else {
-                    pf.left = df.left = mScreenLeft;
-                    pf.top = df.top = mScreenTop;
-                    pf.right = df.right = mScreenLeft+mScreenWidth;
-                    pf.bottom = df.bottom = mScreenTop+mScreenHeight;
+                    if (attrs.type == TYPE_STATUS_BAR_PANEL) {
+                        // Status bar panels are the only windows who can go on top of
+                        // the status bar.  They are protected by the STATUS_BAR_SERVICE
+                        // permission, so they have the same privileges as the status
+                        // bar itself.
+                        pf.left = df.left = mUnrestrictedScreenLeft;
+                        pf.top = df.top = mUnrestrictedScreenTop;
+                        pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
+                        pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+                    } else {
+                        pf.left = df.left = mRestrictedScreenLeft;
+                        pf.top = df.top = mRestrictedScreenTop;
+                        pf.right = df.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
+                        pf.bottom = df.bottom = mRestrictedScreenTop+mRestrictedScreenHeight;
+                    }
                     if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
                         cf.left = mDockLeft;
                         cf.top = mDockTop;
@@ -1579,10 +1610,20 @@
             } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0) {
                 // A window that has requested to fill the entire screen just
                 // gets everything, period.
-                pf.left = df.left = cf.left = mScreenLeft;
-                pf.top = df.top = cf.top = mScreenTop;
-                pf.right = df.right = cf.right = mScreenLeft+mScreenWidth;
-                pf.bottom = df.bottom = cf.bottom = mScreenTop+mScreenHeight;
+                if (attrs.type == TYPE_STATUS_BAR_PANEL) {
+                    pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
+                    pf.top = df.top = cf.top = mUnrestrictedScreenTop;
+                    pf.right = df.right = cf.right
+                            = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
+                    pf.bottom = df.bottom = cf.bottom
+                            = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+                } else {
+                    pf.left = df.left = cf.left = mRestrictedScreenLeft;
+                    pf.top = df.top = cf.top = mRestrictedScreenTop;
+                    pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
+                    pf.bottom = df.bottom = cf.bottom
+                            = mRestrictedScreenTop+mRestrictedScreenHeight;
+                }
                 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
                     vf.left = mCurLeft;
                     vf.top = mCurTop;
@@ -1841,9 +1882,10 @@
                     rect.union(w.getShownFrameLw());
                 }
             }
-            final int insetw = mScreenWidth/10;
-            final int inseth = mScreenHeight/10;
-            if (rect.contains(insetw, inseth, mScreenWidth-insetw, mScreenHeight-inseth)) {
+            final int insetw = mRestrictedScreenWidth/10;
+            final int inseth = mRestrictedScreenHeight/10;
+            if (rect.contains(insetw, inseth, mRestrictedScreenWidth-insetw,
+                        mRestrictedScreenHeight-inseth)) {
                 // All of the status bar windows put together cover the
                 // screen, so the app can't be seen.  (Note this test doesn't
                 // work if the rects of these windows are at off offsets or