Populate the notifications at startup of SystemUI.apk.

Change-Id: Ie0b3fd9ed4bc9a012791372e6276f0b5908370a5
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index f713bf9..1f25b37 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -19,6 +19,7 @@
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarIconList;
+import com.android.internal.statusbar.StatusBarNotification;
 
 /** @hide */
 interface IStatusBarService
@@ -31,7 +32,8 @@
     void removeIcon(String slot);
 
     // ---- Methods below are for use by the status bar policy services ----
-    void registerStatusBar(IStatusBar callbacks, out StatusBarIconList state);
+    void registerStatusBar(IStatusBar callbacks, out StatusBarIconList iconList,
+            out List<IBinder> notificationKeys, out List<StatusBarNotification> notifications);
     void visibilityChanged(boolean visible);
     void onNotificationClick(String pkg, String tag, int id);
     void onClearAllNotifications();
diff --git a/core/java/com/android/internal/statusbar/StatusBarNotificationList.java b/core/java/com/android/internal/statusbar/StatusBarNotificationList.java
deleted file mode 100644
index 37f5f63d..0000000
--- a/core/java/com/android/internal/statusbar/StatusBarNotificationList.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2010 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.internal.statusbar;
-
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-
-/**
- * Contains a list of status bar notifications and IBinder keys in no particular order.
- */
-public class StatusBarNotificationList implements Parcelable {
-    private class Entry {
-        IBinder key;
-        public StatusBarNotification notification;
-
-        void writeToParcel(Parcel out, int flags) {
-            out.writeStrongBinder(key);
-            notification.writeToParcel(out, flags);
-        }
-
-        void readFromParcel(Parcel in) {
-            key = in.readStrongBinder();
-            notification = new StatusBarNotification(in);
-        }
-
-        public Entry clone() {
-            Entry that = new Entry();
-            that.key = this.key;
-            that.notification = this.notification.clone();
-            return that;
-        }
-    }
-
-    private ArrayList<Entry> mEntries = new ArrayList<Entry>();
-
-    public StatusBarNotificationList() {
-    }
-
-    public StatusBarNotificationList(Parcel in) {
-        readFromParcel(in);
-    }
-    
-    public void readFromParcel(Parcel in) {
-        final int N = in.readInt();
-        for (int i=0; i<N; i++) {
-            Entry e = new Entry();
-            e.readFromParcel(in);
-            mEntries.add(e);
-        }
-    }
-
-    public void writeToParcel(Parcel out, int flags) {
-        final int N = mEntries.size();
-        out.writeInt(N);
-        for (int i=0; i<N; i++) {
-            mEntries.get(i).writeToParcel(out, flags);
-        }
-    }
-
-    public int describeContents() {
-        return 0;
-    }
-
-    /**
-     * Parcelable.Creator that instantiates StatusBarNotificationList objects
-     */
-    public static final Parcelable.Creator<StatusBarNotificationList> CREATOR
-            = new Parcelable.Creator<StatusBarNotificationList>()
-    {
-        public StatusBarNotificationList createFromParcel(Parcel parcel)
-        {
-            return new StatusBarNotificationList(parcel);
-        }
-
-        public StatusBarNotificationList[] newArray(int size)
-        {
-            return new StatusBarNotificationList[size];
-        }
-    };
-
-    public void copyFrom(StatusBarNotificationList that) {
-        mEntries.clear();
-        final int N = that.mEntries.size();
-        for (int i=0; i<N; i++) {
-            mEntries.add(that.mEntries.get(i).clone());
-        }
-    }
-
-    public void dump(PrintWriter pw) {
-        final int N = mEntries.size();
-        pw.println("Notification list:");
-        for (int i=0; i<N; i++) {
-            Entry e = mEntries.get(i);
-            pw.printf("  %2d: %s\n", i, e.notification.toString());
-        }
-    }
-
-
-    public int size() {
-        return mEntries.size();
-    }
-
-    public void add(IBinder key, StatusBarNotification notification) {
-        if (notification == null) throw new NullPointerException();
-
-        Entry entry = new Entry();
-        entry.key = key;
-        entry.notification = notification.clone();
-
-        mEntries.add(entry);
-    }
-
-    public void update(IBinder key, StatusBarNotification notification) {
-        final int index = getIndex(key);
-        if (index < 0) {
-            throw new IllegalArgumentException("got invalid key: " + key);
-        }
-        mEntries.get(index).notification = notification.clone();
-    }
-
-    public void remove(IBinder key) {
-        final int index = getIndex(key);
-        if (index < 0) {
-            throw new IllegalArgumentException("got invalid key: " + key);
-        }
-        mEntries.remove(index);
-    }
-
-    public int getIndex(IBinder key) {
-        final ArrayList<Entry> entries = mEntries;
-        final int N = entries.size();
-        for (int i=0; i<N; i++) {
-            if (entries.get(i).key == key) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    public StatusBarNotification getNotification(int index) {
-        return mEntries.get(index).notification;
-    }
-}
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 5a888fd..8256442 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -25,7 +25,6 @@
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarIconList;
 import com.android.internal.statusbar.StatusBarNotification;
-import com.android.internal.statusbar.StatusBarNotificationList;
 
 /**
  * This class takes the functions from IStatusBar that come in on
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
index a60a40b..09cec67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
@@ -24,6 +24,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.util.Log;
 import android.util.Slog;
 import android.view.Gravity;
 import android.view.View;
@@ -36,6 +37,10 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarIconList;
+import com.android.internal.statusbar.StatusBarNotification;
+
+import java.util.Arrays;
+import java.util.ArrayList;
 
 public abstract class StatusBarService extends Service implements CommandQueue.Callbacks {
     private static final String TAG = "StatusBarService";
@@ -53,17 +58,19 @@
     public void onCreate() {
         // Connect in to the status bar manager service
         StatusBarIconList iconList = new StatusBarIconList();
+        ArrayList<IBinder> notificationKeys = new ArrayList<IBinder>();
+        ArrayList<StatusBarNotification> notifications = new ArrayList<StatusBarNotification>();
         mCommandQueue = new CommandQueue(this, iconList);
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
         try {
-            mBarService.registerStatusBar(mCommandQueue, iconList);
+            mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications);
         } catch (RemoteException ex) {
             // If the system process isn't there we're doomed anyway.
         }
 
         // Set up the initial icon state
-        final int N = iconList.size();
+        int N = iconList.size();
         int viewIndex = 0;
         for (int i=0; i<N; i++) {
             StatusBarIcon icon = iconList.getIcon(i);
@@ -73,6 +80,18 @@
             }
         }
 
+        // Set up the initial notification state
+        N = notificationKeys.size();
+        Slog.d(TAG, "installing " + N + " initial notifications");
+        if (N == notifications.size()) {
+            for (int i=0; i<N; i++) {
+                addNotification(notificationKeys.get(i), notifications.get(i));
+            }
+        } else {
+            Log.wtf(TAG, "Notification list length mismatch: keys=" + N
+                    + " notifications=" + notifications.size());
+        }
+
         // Put up the view
         addStatusBarView();
     }
diff --git a/services/java/com/android/server/status/StatusBarManagerService.java b/services/java/com/android/server/status/StatusBarManagerService.java
index 26a41f3..fe26697 100644
--- a/services/java/com/android/server/status/StatusBarManagerService.java
+++ b/services/java/com/android/server/status/StatusBarManagerService.java
@@ -37,12 +37,13 @@
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarIconList;
 import com.android.internal.statusbar.StatusBarNotification;
-import com.android.internal.statusbar.StatusBarNotificationList;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 
 /**
@@ -62,7 +63,8 @@
     NotificationCallbacks mNotificationCallbacks;
     volatile IStatusBar mBar;
     StatusBarIconList mIcons = new StatusBarIconList();
-    StatusBarNotificationList mNotifications = new StatusBarNotificationList();
+    HashMap<IBinder,StatusBarNotification> mNotifications
+            = new HashMap<IBinder,StatusBarNotification>();
 
     // for disabling the status bar
     ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>();
@@ -250,10 +252,19 @@
     // ================================================================================
     // Callbacks from the status bar service.
     // ================================================================================
-    public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList) {
+    public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList,
+            List<IBinder> notificationKeys, List<StatusBarNotification> notifications) {
         Slog.i(TAG, "registerStatusBar bar=" + bar);
         mBar = bar;
-        iconList.copyFrom(mIcons);
+        synchronized (mIcons) {
+            iconList.copyFrom(mIcons);
+        }
+        synchronized (mNotifications) {
+            for (Map.Entry<IBinder,StatusBarNotification> e: mNotifications.entrySet()) {
+                notificationKeys.add(e.getKey());
+                notifications.add(e.getValue());
+            }
+        }
     }
 
     /**
@@ -277,8 +288,9 @@
     // ================================================================================
     public IBinder addNotification(StatusBarNotification notification) {
         synchronized (mNotifications) {
+            Slog.d(TAG, "addNotification notification=" + notification);
             IBinder key = new Binder();
-            mNotifications.add(key, notification);
+            mNotifications.put(key, notification);
             if (mBar != null) {
                 try {
                     mBar.addNotification(key, notification);
@@ -291,7 +303,10 @@
 
     public void updateNotification(IBinder key, StatusBarNotification notification) {
         synchronized (mNotifications) {
-            mNotifications.update(key, notification);
+            if (!mNotifications.containsKey(key)) {
+                throw new IllegalArgumentException("updateNotification key not found: " + key);
+            }
+            mNotifications.put(key, notification);
             if (mBar != null) {
                 try {
                     mBar.updateNotification(key, notification);
@@ -303,7 +318,10 @@
 
     public void removeNotification(IBinder key) {
         synchronized (mNotifications) {
-            mNotifications.remove(key);
+            final StatusBarNotification n = mNotifications.remove(key);
+            if (n == null) {
+                throw new IllegalArgumentException("removeNotification key not found: " + key);
+            }
             if (mBar != null) {
                 try {
                     mBar.removeNotification(key);
@@ -386,7 +404,12 @@
         }
 
         synchronized (mNotifications) {
-            mNotifications.dump(pw);
+            int i=0;
+            pw.println("Notification list:");
+            for (Map.Entry<IBinder,StatusBarNotification> e: mNotifications.entrySet()) {
+                pw.printf("  %2d: %s\n", i, e.getValue().toString());
+                i++;
+            }
         }
 
         synchronized (mDisableRecords) {