Require the STATUS_BAR_SERVICE permission for something to be the status bar.

Change-Id: I57b2d296e0d0cef0d256ae6697fffc47188d14df
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index be3ded1..e3862ff 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -32,6 +32,7 @@
     void removeIcon(String slot);
 
     // ---- Methods below are for use by the status bar policy services ----
+    // You need the STATUS_BAR_SERVICE permission
     void registerStatusBar(IStatusBar callbacks, out StatusBarIconList iconList,
             out List<IBinder> notificationKeys, out List<StatusBarNotification> notifications);
     void visibilityChanged(boolean visible);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 2ddb6b9..aff9453 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -908,6 +908,13 @@
         android:description="@string/permdesc_statusBar"
         android:protectionLevel="signatureOrSystem" />
 
+    <!-- Allows an application to be the status bar.  Currently used only by SystemUI.apk
+    @hide -->
+    <permission android:name="android.permission.STATUS_BAR_SERVICE"
+        android:label="@string/permlab_statusBarService"
+        android:description="@string/permdesc_statusBarService"
+        android:protectionLevel="signature" />
+
     <!-- Allows an application to force a BACK operation on whatever is the
          top activity. -->
     <permission android:name="android.permission.FORCE_BACK"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e7f892a..fc1db18 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -393,6 +393,11 @@
         the status bar or add and remove system icons.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_statusBarService">status bar</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_statusBarService">Allows the application to be the status bar.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_expandStatusBar">expand/collapse status bar</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_expandStatusBar">Allows application to
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index aba5e05..d8e05bb 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -2,6 +2,8 @@
         package="com.android.systemui"
         android:sharedUserId="android.uid.system">
 
+    <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
+
     <application
         android:allowClearUserData="false"
         android:label="@string/app_label"
diff --git a/policy/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/com/android/internal/policy/impl/PhoneWindowManager.java
index 73a57ee..d152bc4 100755
--- a/policy/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -957,12 +957,20 @@
     public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
         switch (attrs.type) {
             case TYPE_STATUS_BAR:
+                mContext.enforceCallingOrSelfPermission(
+                        android.Manifest.permission.STATUS_BAR_SERVICE,
+                        "PhoneWindowManager");
+                // TODO: Need to handle the race condition of the status bar proc
+                // dying and coming back before the removeWindowLw cleanup has happened.
                 if (mStatusBar != null) {
                     return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
                 }
                 mStatusBar = win;
                 break;
             case TYPE_STATUS_BAR_PANEL:
+                mContext.enforceCallingOrSelfPermission(
+                        android.Manifest.permission.STATUS_BAR_SERVICE,
+                        "PhoneWindowManager");
                 mStatusBarPanels.add(win);
                 break;
             case TYPE_KEYGUARD:
diff --git a/services/java/com/android/server/status/StatusBarManagerService.java b/services/java/com/android/server/status/StatusBarManagerService.java
index 925a6eb..198e363 100644
--- a/services/java/com/android/server/status/StatusBarManagerService.java
+++ b/services/java/com/android/server/status/StatusBarManagerService.java
@@ -249,12 +249,19 @@
                 "StatusBarManagerService");
     }
 
+    private void enforceStatusBarService() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
+                "StatusBarManagerService");
+    }
+
 
     // ================================================================================
     // Callbacks from the status bar service.
     // ================================================================================
     public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList,
             List<IBinder> notificationKeys, List<StatusBarNotification> notifications) {
+        enforceStatusBarService();
+
         Slog.i(TAG, "registerStatusBar bar=" + bar);
         mBar = bar;
         synchronized (mIcons) {
@@ -273,20 +280,27 @@
      * the status bar is visible or not.
      */
     public void visibilityChanged(boolean visible) {
+        enforceStatusBarService();
+
         //Slog.d(TAG, "visibilityChanged visible=" + visible);
     }
 
     public void onNotificationClick(String pkg, String tag, int id) {
+        enforceStatusBarService();
+
         mNotificationCallbacks.onNotificationClick(pkg, tag, id);
     }
 
     public void onNotificationError(String pkg, String tag, int id, String message) {
-        Slog.d(TAG, "onNotificationError message=" + message);
+        enforceStatusBarService();
+
         // WARNING: this will call back into us to do the remove.  Don't hold any locks.
         mNotificationCallbacks.onNotificationError(pkg, tag, id, message);
     }
 
     public void onClearAllNotifications() {
+        enforceStatusBarService();
+
         mNotificationCallbacks.onClearAll();
     }