SysUI: Use SBN keys instead of IBinder keys DO NOT MERGE

In preparation of migrating to NotificationListenerService,
remove dependence on IBinder keys for notifications and switch
to SBN.getKey() instead.

Bug: 15131411
Change-Id: Ic272e4a05fde6481c734144c5b34c49b2f021649
(cherry picked from commit 7c96ae873d9a54ebaeb5b7ef21b48224dc42d094)
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 1366499..a01e9b7 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -24,9 +24,9 @@
 {
     void setIcon(int index, in StatusBarIcon icon);
     void removeIcon(int index);
-    void addNotification(IBinder key, in StatusBarNotification notification);
-    void updateNotification(IBinder key, in StatusBarNotification notification);
-    void removeNotification(IBinder key);
+    void addNotification(in StatusBarNotification notification);
+    void updateNotification(in StatusBarNotification notification);
+    void removeNotification(String key);
     void disable(int state);
     void animateExpandNotificationsPanel();
     void animateExpandSettingsPanel();
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 2d6cf2e..a3b417f 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -39,8 +39,8 @@
     // ---- 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,
-            out int[] switches, out List<IBinder> binders);
+            out List<StatusBarNotification> notifications, out int[] switches,
+            out List<IBinder> binders);
     void onPanelRevealed();
     void onPanelHidden();
     void onNotificationClick(String key);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 457d32e..0495f46 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -299,14 +299,13 @@
 
         // 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);
 
         int[] switches = new int[8];
         ArrayList<IBinder> binders = new ArrayList<IBinder>();
         try {
-            mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications,
+            mBarService.registerStatusBar(mCommandQueue, iconList, notifications,
                     switches, binders);
         } catch (RemoteException ex) {
             // If the system process isn't there we're doomed anyway.
@@ -332,15 +331,10 @@
             }
         }
 
-        // Set up the initial notification state
-        N = notificationKeys.size();
-        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());
+        // Set up the initial notification state.
+        N = notifications.size();
+        for (int i=0; i<N; i++) {
+            addNotification(notifications.get(i));
         }
 
         if (DEBUG) {
@@ -1018,8 +1012,8 @@
      *
      * WARNING: this will call back into us.  Don't hold any locks.
      */
-    void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
-        removeNotification(key);
+    void handleNotificationError(StatusBarNotification n, String message) {
+        removeNotification(n.getKey());
         try {
             mBarService.onNotificationError(n.getPackageName(), n.getTag(), n.getId(), n.getUid(),
                     n.getInitialPid(), message, n.getUserId());
@@ -1028,7 +1022,7 @@
         }
     }
 
-    protected StatusBarNotification removeNotificationViews(IBinder key) {
+    protected StatusBarNotification removeNotificationViews(String key) {
         NotificationData.Entry entry = mNotificationData.remove(key);
         if (entry == null) {
             Log.w(TAG, "removeNotification for unknown key: " + key);
@@ -1043,10 +1037,9 @@
         return entry.notification;
     }
 
-    protected NotificationData.Entry createNotificationViews(IBinder key,
-            StatusBarNotification notification) {
+    protected NotificationData.Entry createNotificationViews(StatusBarNotification notification) {
         if (DEBUG) {
-            Log.d(TAG, "createNotificationViews(key=" + key + ", notification=" + notification);
+            Log.d(TAG, "createNotificationViews(notification=" + notification);
         }
         // Construct the icon.
         final StatusBarIconView iconView = new StatusBarIconView(mContext,
@@ -1061,13 +1054,13 @@
                     notification.getNotification().number,
                     notification.getNotification().tickerText);
         if (!iconView.set(ic)) {
-            handleNotificationError(key, notification, "Couldn't create icon: " + ic);
+            handleNotificationError(notification, "Couldn't create icon: " + ic);
             return null;
         }
         // Construct the expanded view.
-        NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView);
+        NotificationData.Entry entry = new NotificationData.Entry(notification, iconView);
         if (!inflateViews(entry, mStackScroller)) {
-            handleNotificationError(key, notification, "Couldn't expand RemoteViews for: "
+            handleNotificationError(notification, "Couldn't expand RemoteViews for: "
                     + notification);
             return null;
         }
@@ -1087,8 +1080,8 @@
         updateRowStates();
     }
 
-    private void addNotificationViews(IBinder key, StatusBarNotification notification) {
-        addNotificationViews(createNotificationViews(key, notification));
+    private void addNotificationViews(StatusBarNotification notification) {
+        addNotificationViews(createNotificationViews(notification));
     }
 
     /**
@@ -1160,7 +1153,7 @@
     protected abstract void haltTicker();
     protected abstract void setAreThereNotifications();
     protected abstract void updateNotificationIcons();
-    protected abstract void tick(IBinder key, StatusBarNotification n, boolean firstTime);
+    protected abstract void tick(StatusBarNotification n, boolean firstTime);
     protected abstract void updateExpandedViewPos(int expandedPosition);
     protected abstract boolean shouldDisableNavbarGestures();
 
@@ -1168,12 +1161,12 @@
         return parent != null && parent.indexOfChild(entry.row) == 0;
     }
 
-    public void updateNotification(IBinder key, StatusBarNotification notification) {
-        if (DEBUG) Log.d(TAG, "updateNotification(" + key + " -> " + notification + ")");
+    public void updateNotification(StatusBarNotification notification) {
+        if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
 
-        final NotificationData.Entry oldEntry = mNotificationData.findByKey(key);
+        final NotificationData.Entry oldEntry = mNotificationData.findByKey(notification.getKey());
         if (oldEntry == null) {
-            Log.w(TAG, "updateNotification for unknown key: " + key);
+            Log.w(TAG, "updateNotification for unknown key: " + notification.getKey());
             return;
         }
 
@@ -1252,7 +1245,7 @@
         boolean isTopAnyway = isTopNotification(rowParent, oldEntry);
         if (contentsUnchanged && bigContentsUnchanged && headsUpContentsUnchanged && publicUnchanged
                 && (orderUnchanged || isTopAnyway)) {
-            if (DEBUG) Log.d(TAG, "reusing notification for key: " + key);
+            if (DEBUG) Log.d(TAG, "reusing notification for key: " + notification.getKey());
             oldEntry.notification = notification;
             try {
                 updateNotificationViews(oldEntry, notification);
@@ -1276,7 +1269,7 @@
                         notification.getNotification().number,
                         notification.getNotification().tickerText);
                 if (!oldEntry.icon.set(ic)) {
-                    handleNotificationError(key, notification, "Couldn't update icon: " + ic);
+                    handleNotificationError(notification, "Couldn't update icon: " + ic);
                     return;
                 }
                 updateRowStates();
@@ -1284,17 +1277,18 @@
             catch (RuntimeException e) {
                 // It failed to add cleanly.  Log, and remove the view from the panel.
                 Log.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
-                removeNotificationViews(key);
-                addNotificationViews(key, notification);
+                removeNotificationViews(notification.getKey());
+                addNotificationViews(notification);
             }
         } else {
-            if (DEBUG) Log.d(TAG, "not reusing notification for key: " + key);
+            if (DEBUG) Log.d(TAG, "not reusing notification for key: " + notification.getKey());
             if (DEBUG) Log.d(TAG, "contents was " + (contentsUnchanged ? "unchanged" : "changed"));
             if (DEBUG) Log.d(TAG, "order was " + (orderUnchanged ? "unchanged" : "changed"));
             if (DEBUG) Log.d(TAG, "notification is " + (isTopAnyway ? "top" : "not top"));
-            removeNotificationViews(key);
-            addNotificationViews(key, notification);  // will also replace the heads up
-            final NotificationData.Entry newEntry = mNotificationData.findByKey(key);
+            removeNotificationViews(notification.getKey());
+            addNotificationViews(notification);  // will also replace the heads up
+            final NotificationData.Entry newEntry = mNotificationData.findByKey(
+                    notification.getKey());
             final boolean userChangedExpansion = oldEntry.row.hasUserChangedExpansion();
             if (userChangedExpansion) {
                 boolean userExpanded = oldEntry.row.isUserExpanded();
@@ -1314,7 +1308,7 @@
         // Restart the ticker if it's still running
         if (updateTicker && isForCurrentUser) {
             haltTicker();
-            tick(key, notification, false);
+            tick(notification, false);
         }
 
         // Recalculate the position of the sliding windows and the titles.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index b4a347b..aaeadb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -21,7 +21,6 @@
 import android.os.Message;
 import android.service.notification.StatusBarNotification;
 
-import com.android.internal.policy.IKeyguardShowCallback;
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarIconList;
@@ -73,11 +72,6 @@
     private Callbacks mCallbacks;
     private Handler mHandler = new H();
 
-    private class NotificationQueueEntry {
-        IBinder key;
-        StatusBarNotification notification;
-    }
-
     /**
      * These methods are called back on the main thread.
      */
@@ -86,9 +80,9 @@
         public void updateIcon(String slot, int index, int viewIndex,
                 StatusBarIcon old, StatusBarIcon icon);
         public void removeIcon(String slot, int index, int viewIndex);
-        public void addNotification(IBinder key, StatusBarNotification notification);
-        public void updateNotification(IBinder key, StatusBarNotification notification);
-        public void removeNotification(IBinder key);
+        public void addNotification(StatusBarNotification notification);
+        public void updateNotification(StatusBarNotification notification);
+        public void removeNotification(String key);
         public void disable(int state);
         public void animateExpandNotificationsPanel();
         public void animateCollapsePanels(int flags);
@@ -106,7 +100,6 @@
         public void showSearchPanel();
         public void hideSearchPanel();
         public void setWindowState(int window, int state);
-
     }
 
     public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -130,25 +123,21 @@
         }
     }
 
-    public void addNotification(IBinder key, StatusBarNotification notification) {
+    @Override
+    public void addNotification(StatusBarNotification notification) {
         synchronized (mList) {
-            NotificationQueueEntry ne = new NotificationQueueEntry();
-            ne.key = key;
-            ne.notification = notification;
-            mHandler.obtainMessage(MSG_ADD_NOTIFICATION, 0, 0, ne).sendToTarget();
+            mHandler.obtainMessage(MSG_ADD_NOTIFICATION, 0, 0, notification).sendToTarget();
         }
     }
 
-    public void updateNotification(IBinder key, StatusBarNotification notification) {
+    @Override
+    public void updateNotification(StatusBarNotification notification) {
         synchronized (mList) {
-            NotificationQueueEntry ne = new NotificationQueueEntry();
-            ne.key = key;
-            ne.notification = notification;
-            mHandler.obtainMessage(MSG_UPDATE_NOTIFICATION, 0, 0, ne).sendToTarget();
+            mHandler.obtainMessage(MSG_UPDATE_NOTIFICATION, 0, 0, notification).sendToTarget();
         }
     }
 
-    public void removeNotification(IBinder key) {
+    public void removeNotification(String key) {
         synchronized (mList) {
             mHandler.obtainMessage(MSG_REMOVE_NOTIFICATION, 0, 0, key).sendToTarget();
         }
@@ -291,17 +280,15 @@
                     break;
                 }
                 case MSG_ADD_NOTIFICATION: {
-                    final NotificationQueueEntry ne = (NotificationQueueEntry)msg.obj;
-                    mCallbacks.addNotification(ne.key, ne.notification);
+                    mCallbacks.addNotification((StatusBarNotification) msg.obj);
                     break;
                 }
                 case MSG_UPDATE_NOTIFICATION: {
-                    final NotificationQueueEntry ne = (NotificationQueueEntry)msg.obj;
-                    mCallbacks.updateNotification(ne.key, ne.notification);
+                    mCallbacks.updateNotification((StatusBarNotification) msg.obj);
                     break;
                 }
                 case MSG_REMOVE_NOTIFICATION: {
-                    mCallbacks.removeNotification((IBinder)msg.obj);
+                    mCallbacks.removeNotification((String) msg.obj);
                     break;
                 }
                 case MSG_DISABLE:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
index 8440b9f..bd511f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
@@ -18,8 +18,6 @@
 
 import android.app.Notification;
 import android.content.Context;
-import android.os.Binder;
-import android.os.IBinder;
 import android.os.Process;
 import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
@@ -33,13 +31,14 @@
 public class InterceptedNotifications {
     private static final String TAG = "InterceptedNotifications";
     private static final String EXTRA_INTERCEPT = "android.intercept";
+    private static final String SYNTHETIC_KEY = "InterceptedNotifications.SYNTHETIC_KEY";
 
     private final Context mContext;
     private final PhoneStatusBar mBar;
-    private final ArrayMap<IBinder, StatusBarNotification> mIntercepted
-            = new ArrayMap<IBinder, StatusBarNotification>();
+    private final ArrayMap<String, StatusBarNotification> mIntercepted
+            = new ArrayMap<String, StatusBarNotification>();
 
-    private Binder mSynKey;
+    private String mSynKey;
 
     public InterceptedNotifications(Context context, PhoneStatusBar bar) {
         mContext = context;
@@ -49,36 +48,35 @@
     public void releaseIntercepted() {
         final int n = mIntercepted.size();
         for (int i = 0; i < n; i++) {
-            final IBinder key = mIntercepted.keyAt(i);
             final StatusBarNotification sbn = mIntercepted.valueAt(i);
             sbn.getNotification().extras.putBoolean(EXTRA_INTERCEPT, false);
-            mBar.addNotification(key, sbn);
+            mBar.addNotification(sbn);
         }
         mIntercepted.clear();
         updateSyntheticNotification();
     }
 
-    public boolean tryIntercept(IBinder key, StatusBarNotification notification) {
+    public boolean tryIntercept(StatusBarNotification notification) {
         if (!notification.getNotification().extras.getBoolean(EXTRA_INTERCEPT)) return false;
         if (shouldDisplayIntercepted()) return false;
-        mIntercepted.put(key, notification);
+        mIntercepted.put(notification.getKey(), notification);
         updateSyntheticNotification();
         return true;
     }
 
-    public void remove(IBinder key) {
+    public void remove(String key) {
         if (mIntercepted.remove(key) != null) {
             updateSyntheticNotification();
         }
     }
 
     public boolean isSyntheticEntry(Entry ent) {
-        return mSynKey != null && ent.key.equals(mSynKey);
+        return ent.key.equals(SYNTHETIC_KEY);
     }
 
-    public void update(IBinder key, StatusBarNotification notification) {
-        if (mIntercepted.containsKey(key)) {
-            mIntercepted.put(key, notification);
+    public void update(StatusBarNotification notification) {
+        if (mIntercepted.containsKey(notification.getKey())) {
+            mIntercepted.put(notification.getKey(), notification);
         }
     }
 
@@ -108,10 +106,10 @@
                 TAG.hashCode(), TAG, Process.myUid(), Process.myPid(), 0, n,
                 mBar.getCurrentUserHandle());
         if (mSynKey == null) {
-            mSynKey = new Binder();
-            mBar.addNotification(mSynKey, sbn);
+            mSynKey = sbn.getKey();
+            mBar.addNotification(sbn);
         } else {
-           mBar.updateNotification(mSynKey, sbn);
+           mBar.updateNotification(sbn);
         }
         final NotificationData.Entry entry = mBar.mNotificationData.findByKey(mSynKey);
         entry.row.setOnClickListener(mSynClickListener);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index b1a5750..5696246 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar;
 
-import android.os.IBinder;
 import android.service.notification.StatusBarNotification;
 import android.view.View;
 import android.widget.ImageView;
@@ -29,7 +28,7 @@
  */
 public class NotificationData {
     public static final class Entry {
-        public IBinder key;
+        public String key;
         public StatusBarNotification notification;
         public StatusBarIconView icon;
         public ExpandableNotificationRow row; // the outer expanded view
@@ -39,8 +38,8 @@
         public View expandedBig;
         private boolean interruption;
         public Entry() {}
-        public Entry(IBinder key, StatusBarNotification n, StatusBarIconView ic) {
-            this.key = key;
+        public Entry(StatusBarNotification n, StatusBarIconView ic) {
+            this.key = n.getKey();
             this.notification = n;
             this.icon = ic;
         }
@@ -63,6 +62,7 @@
             interruption = true;
         }
     }
+
     private final ArrayList<Entry> mEntries = new ArrayList<Entry>();
     private final Comparator<Entry> mEntryCmp = new Comparator<Entry>() {
         // sort first by score, then by when
@@ -88,9 +88,9 @@
         return mEntries.get(i);
     }
 
-    public Entry findByKey(IBinder key) {
+    public Entry findByKey(String key) {
         for (Entry e : mEntries) {
-            if (e.key == key) {
+            if (e.key.equals(key)) {
                 return e;
             }
         }
@@ -100,7 +100,7 @@
     public int add(Entry entry) {
         int i;
         int N = mEntries.size();
-        for (i=0; i<N; i++) {
+        for (i = 0; i < N; i++) {
             if (mEntryCmp.compare(mEntries.get(i), entry) > 0) {
                 break;
             }
@@ -109,7 +109,7 @@
         return i;
     }
 
-    public Entry remove(IBinder key) {
+    public Entry remove(String key) {
         Entry e = findByKey(key);
         if (e != null) {
             mEntries.remove(e);
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 54af2c5..8735d36 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1027,18 +1027,19 @@
         return new UserHandle(mCurrentUserId);
     }
 
-    public void addNotification(IBinder key, StatusBarNotification notification) {
+    @Override
+    public void addNotification(StatusBarNotification notification) {
         if (DEBUG) Log.d(TAG, "addNotification score=" + notification.getScore());
-        Entry shadeEntry = createNotificationViews(key, notification);
+        Entry shadeEntry = createNotificationViews(notification);
         if (shadeEntry == null) {
             return;
         }
-        if (mZenMode != Global.ZEN_MODE_OFF && mIntercepted.tryIntercept(key, notification)) {
+        if (mZenMode != Global.ZEN_MODE_OFF && mIntercepted.tryIntercept(notification)) {
             return;
         }
         if (mUseHeadsUp && shouldInterrupt(notification)) {
             if (DEBUG) Log.d(TAG, "launching notification in heads up mode");
-            Entry interruptionCandidate = new Entry(key, notification, null);
+            Entry interruptionCandidate = new Entry(notification, null);
             ViewGroup holder = mHeadsUpNotificationView.getHolder();
             if (inflateViewsForHeadsUp(interruptionCandidate, holder)) {
                 mInterruptingNotificationTime = System.currentTimeMillis();
@@ -1070,7 +1071,7 @@
 
             // show the ticker if there isn't already a heads up
             if (mInterruptingNotificationEntry == null) {
-                tick(null, notification, true);
+                tick(notification, true);
             }
         }
         addNotificationViews(shadeEntry);
@@ -1089,12 +1090,13 @@
     }
 
     @Override
-    public void updateNotification(IBinder key, StatusBarNotification notification) {
-        super.updateNotification(key, notification);
-        mIntercepted.update(key, notification);
+    public void updateNotification(StatusBarNotification notification) {
+        super.updateNotification(notification);
+        mIntercepted.update(notification);
     }
 
-    public void removeNotification(IBinder key) {
+    @Override
+    public void removeNotification(String key) {
         StatusBarNotification old = removeNotificationViews(key);
         if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old);
 
@@ -2019,7 +2021,7 @@
     public void setHardKeyboardStatus(boolean available, boolean enabled) {}
 
     @Override
-    protected void tick(IBinder key, StatusBarNotification n, boolean firstTime) {
+    protected void tick(StatusBarNotification n, boolean firstTime) {
         // no ticking in lights-out mode
         if (!areLightsOn()) return;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 9006c9a..846d248 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -46,15 +46,15 @@
     }
 
     @Override
-    public void addNotification(IBinder key, StatusBarNotification notification) {
+    public void addNotification(StatusBarNotification notification) {
     }
 
     @Override
-    public void updateNotification(IBinder key, StatusBarNotification notification) {
+    public void updateNotification(StatusBarNotification notification) {
     }
 
     @Override
-    public void removeNotification(IBinder key) {
+    public void removeNotification(String key) {
     }
 
     @Override
@@ -113,7 +113,7 @@
     }
 
     @Override
-    protected void tick(IBinder key, StatusBarNotification n, boolean firstTime) {
+    protected void tick(StatusBarNotification n, boolean firstTime) {
     }
 
     @Override
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0b3e02a6..b9a69ab 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -457,7 +457,7 @@
     {
         final StatusBarNotification sbn;
         SingleNotificationStats stats;
-        IBinder statusBarKey;
+        boolean isCanceled;
 
         // These members are used by NotificationSignalExtractors
         // to communicate with the ranking module.
@@ -472,6 +472,7 @@
         public Notification getNotification() { return sbn.getNotification(); }
         public int getFlags() { return sbn.getNotification().flags; }
         public int getUserId() { return sbn.getUserId(); }
+        public String getKey() { return sbn.getKey(); }
 
         void dump(PrintWriter pw, String prefix, Context baseContext) {
             final Notification notification = sbn.getNotification();
@@ -1668,7 +1669,7 @@
                         "pkg=" + pkg + " canInterrupt=" + canInterrupt + " intercept=" + intercept);
                 synchronized (mNotificationList) {
                     NotificationRecord old = null;
-                    int index = indexOfNotificationLocked(pkg, tag, id, userId);
+                    int index = indexOfNotificationLocked(n.getKey());
                     if (index < 0) {
                         mNotificationList.add(r);
                         mUsageStats.registerPostedByApp(r);
@@ -1677,12 +1678,8 @@
                         mNotificationList.set(index, r);
                         mUsageStats.registerUpdatedByApp(r, old);
                         // Make sure we don't lose the foreground service state.
-                        if (old != null) {
-                            notification.flags |=
-                                old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE;
-                        }
-                    }
-                    if (old != null) {
+                        notification.flags |=
+                            old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE;
                         mNotificationsByKey.remove(old.sbn.getKey());
                     }
                     mNotificationsByKey.put(n.getKey(), r);
@@ -1705,18 +1702,17 @@
                     }
 
                     if (notification.icon != 0) {
-                        if (old != null && old.statusBarKey != null) {
-                            r.statusBarKey = old.statusBarKey;
+                        if (old != null && !old.isCanceled) {
                             final long identity = Binder.clearCallingIdentity();
                             try {
-                                mStatusBar.updateNotification(r.statusBarKey, n);
+                                mStatusBar.updateNotification(n);
                             } finally {
                                 Binder.restoreCallingIdentity(identity);
                             }
                         } else {
                             final long identity = Binder.clearCallingIdentity();
                             try {
-                                r.statusBarKey = mStatusBar.addNotification(n);
+                                mStatusBar.addNotification(n);
                                 if ((n.getNotification().flags & Notification.FLAG_SHOW_LIGHTS) != 0
                                         && canInterrupt) {
                                     mAttentionLight.pulse();
@@ -1733,10 +1729,10 @@
                         mListeners.notifyPostedLocked(r.sbn, cloneNotificationListLocked());
                     } else {
                         Slog.e(TAG, "Not posting notification with icon==0: " + notification);
-                        if (old != null && old.statusBarKey != null) {
+                        if (old != null && !old.isCanceled) {
                             final long identity = Binder.clearCallingIdentity();
                             try {
-                                mStatusBar.removeNotification(old.statusBarKey);
+                                mStatusBar.removeNotification(r.getKey());
                             } finally {
                                 Binder.restoreCallingIdentity(identity);
                             }
@@ -2120,11 +2116,11 @@
         if (r.getNotification().icon != 0) {
             final long identity = Binder.clearCallingIdentity();
             try {
-                mStatusBar.removeNotification(r.statusBarKey);
+                mStatusBar.removeNotification(r.getKey());
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
-            r.statusBarKey = null;
+            r.isCanceled = true;
             mListeners.notifyRemovedLocked(r.sbn, cloneNotificationListLocked());
         }
 
@@ -2392,6 +2388,18 @@
         return -1;
     }
 
+    // lock on mNotificationList
+    int indexOfNotificationLocked(String key) {
+        NotificationRecord r = mNotificationsByKey.get(key);
+        if (r == null) {
+            return -1;
+        }
+        int index = Collections.binarySearch(mNotificationList, r, mRankingComparator);
+        // Guarantee to return -1 when not found.
+        return (index >= 0) ? index : -1;
+    }
+
+
     private void updateNotificationPulse() {
         synchronized (mNotificationList) {
             updateLightsLocked();
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 4f75189..8d905ba 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -23,7 +23,7 @@
 
 public interface StatusBarManagerInternal {
     void setNotificationDelegate(NotificationDelegate delegate);
-    IBinder addNotification(StatusBarNotification notification);
-    void updateNotification(IBinder key, StatusBarNotification notification);
-    void removeNotification(IBinder key);
+    void addNotification(StatusBarNotification notification);
+    void updateNotification(StatusBarNotification notification);
+    void removeNotification(String key);
 }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 8b8c73d..55b5e3b 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -60,8 +60,8 @@
     private NotificationDelegate mNotificationDelegate;
     private volatile IStatusBar mBar;
     private StatusBarIconList mIcons = new StatusBarIconList();
-    private HashMap<IBinder,StatusBarNotification> mNotifications
-            = new HashMap<IBinder,StatusBarNotification>();
+    private HashMap<String,StatusBarNotification> mNotifications
+            = new HashMap<String,StatusBarNotification>();
 
     // for disabling the status bar
     private final ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>();
@@ -117,30 +117,29 @@
         }
 
         @Override
-        public IBinder addNotification(StatusBarNotification notification) {
+        public void addNotification(StatusBarNotification notification) {
             synchronized (mNotifications) {
-                IBinder key = new Binder();
-                mNotifications.put(key, notification);
+                mNotifications.put(notification.getKey(), notification);
                 if (mBar != null) {
                     try {
-                        mBar.addNotification(key, notification);
+                        mBar.addNotification(notification);
                     } catch (RemoteException ex) {
                     }
                 }
-                return key;
             }
         }
 
         @Override
-        public void updateNotification(IBinder key, StatusBarNotification notification) {
+        public void updateNotification(StatusBarNotification notification) {
             synchronized (mNotifications) {
+                String key = notification.getKey();
                 if (!mNotifications.containsKey(key)) {
                     throw new IllegalArgumentException("updateNotification key not found: " + key);
                 }
-                mNotifications.put(key, notification);
+                mNotifications.put(notification.getKey(), notification);
                 if (mBar != null) {
                     try {
-                        mBar.updateNotification(key, notification);
+                        mBar.updateNotification(notification);
                     } catch (RemoteException ex) {
                     }
                 }
@@ -148,7 +147,7 @@
         }
 
         @Override
-        public void removeNotification(IBinder key) {
+        public void removeNotification(String key) {
             synchronized (mNotifications) {
                 final StatusBarNotification n = mNotifications.remove(key);
                 if (n == null) {
@@ -512,8 +511,7 @@
     // ================================================================================
     @Override
     public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList,
-            List<IBinder> notificationKeys, List<StatusBarNotification> notifications,
-            int switches[], List<IBinder> binders) {
+            List<StatusBarNotification> notifications, int switches[], List<IBinder> binders) {
         enforceStatusBarService();
 
         Slog.i(TAG, "registerStatusBar bar=" + bar);
@@ -522,9 +520,8 @@
             iconList.copyFrom(mIcons);
         }
         synchronized (mNotifications) {
-            for (Map.Entry<IBinder,StatusBarNotification> e: mNotifications.entrySet()) {
-                notificationKeys.add(e.getKey());
-                notifications.add(e.getValue());
+            for (StatusBarNotification sbn : mNotifications.values()) {
+                notifications.add(sbn);
             }
         }
         synchronized (mLock) {
@@ -714,7 +711,7 @@
         synchronized (mNotifications) {
             int i=0;
             pw.println("Notification list:");
-            for (Map.Entry<IBinder,StatusBarNotification> e: mNotifications.entrySet()) {
+            for (Map.Entry<String,StatusBarNotification> e: mNotifications.entrySet()) {
                 pw.printf("  %2d: %s\n", i, e.getValue().toString());
                 i++;
             }