Fix issue #2364506: Phone locked up while listening to music and attempting to download an update

Make sure calls into the notification manager are not done with the
activity manager lock held.

Change-Id: Ib53c3b9f46160d94ee1e7079b1a5123e0d1225d8
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index f3cba69..20ccfdc 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -10276,7 +10276,7 @@
                                 sInfo.applicationInfo.uid, sInfo.packageName,
                                 sInfo.name);
                     }
-                    r = new ServiceRecord(ss, name, filter, sInfo, res);
+                    r = new ServiceRecord(this, ss, name, filter, sInfo, res);
                     res.setService(r);
                     mServices.put(name, r);
                     mServicesByIntent.put(filter, r);
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 2534410..89761a8 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -40,6 +40,7 @@
  * A running application service.
  */
 class ServiceRecord extends Binder {
+    final ActivityManagerService ams;
     final BatteryStatsImpl.Uid.Pkg.Serv stats;
     final ComponentName name; // service component.
     final String shortName; // name.flattenToShortString().
@@ -192,8 +193,10 @@
         }
     }
 
-    ServiceRecord(BatteryStatsImpl.Uid.Pkg.Serv servStats, ComponentName name,
+    ServiceRecord(ActivityManagerService ams,
+            BatteryStatsImpl.Uid.Pkg.Serv servStats, ComponentName name,
             Intent.FilterComparison intent, ServiceInfo sInfo, Runnable restarter) {
+        this.ams = ams;
         this.stats = servStats;
         this.name = name;
         shortName = name.flattenToShortString();
@@ -249,27 +252,46 @@
     
     public void postNotification() {
         if (foregroundId != 0 && foregroundNoti != null) {
-            INotificationManager inm = NotificationManager.getService();
-            if (inm != null) {
-                try {
-                    int[] outId = new int[1];
-                    inm.enqueueNotification(packageName, foregroundId,
-                            foregroundNoti, outId);
-                } catch (RemoteException e) {
+            // Do asynchronous communication with notification manager to
+            // avoid deadlocks.
+            final String localPackageName = packageName;
+            final int localForegroundId = foregroundId;
+            final Notification localForegroundNoti = foregroundNoti;
+            ams.mHandler.post(new Runnable() {
+                public void run() {
+                    INotificationManager inm = NotificationManager.getService();
+                    if (inm == null) {
+                        return;
+                    }
+                    try {
+                        int[] outId = new int[1];
+                        inm.enqueueNotification(localPackageName, localForegroundId,
+                                localForegroundNoti, outId);
+                    } catch (RemoteException e) {
+                    }
                 }
-            }
+            });
         }
     }
     
     public void cancelNotification() {
         if (foregroundId != 0) {
-            INotificationManager inm = NotificationManager.getService();
-            if (inm != null) {
-                try {
-                    inm.cancelNotification(packageName, foregroundId);
-                } catch (RemoteException e) {
+            // Do asynchronous communication with notification manager to
+            // avoid deadlocks.
+            final String localPackageName = packageName;
+            final int localForegroundId = foregroundId;
+            ams.mHandler.post(new Runnable() {
+                public void run() {
+                    INotificationManager inm = NotificationManager.getService();
+                    if (inm == null) {
+                        return;
+                    }
+                    try {
+                        inm.cancelNotification(localPackageName, localForegroundId);
+                    } catch (RemoteException e) {
+                    }
                 }
-            }
+            });
         }
     }