Fix a fun bug with multiple service bindings from an activity.

There was a flaw in the service management, when the same activity
is doing a bindService() for the same service IBinder.  In this case
the activity would correctly keep a list of all generated connections,
however some other data structures would assume there is only one
connection per IBinder, and thus only remember the last.

When that last connection was unbound, the service would be destroyed
since it thought there were no more connections.  Then when the
activity was finished, it would try to destroy the service again and
end up with an ANR because the service was already gone and would
not respond.

Change-Id: I59bde38bc24e78147b90b0a7cd525c2a1d20489f
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index b37cd89..c316074 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -609,8 +609,8 @@
      * All currently bound service connections.  Keys are the IBinder of
      * the client's IServiceConnection.
      */
-    final HashMap<IBinder, ConnectionRecord> mServiceConnections
-            = new HashMap<IBinder, ConnectionRecord>();
+    final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
+            = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
 
     /**
      * List of services that we have been asked to start,
@@ -7376,12 +7376,14 @@
             if (mServiceConnections.size() > 0) {
                 if (needSep) pw.println(" ");
                 pw.println("  Connection bindings to services:");
-                Iterator<ConnectionRecord> it
+                Iterator<ArrayList<ConnectionRecord>> it
                         = mServiceConnections.values().iterator();
                 while (it.hasNext()) {
-                    ConnectionRecord r = it.next();
-                    pw.print("  * "); pw.println(r);
-                    r.dump(pw, "    ");
+                    ArrayList<ConnectionRecord> r = it.next();
+                    for (int i=0; i<r.size(); i++) {
+                        pw.print("  * "); pw.println(r.get(i));
+                        r.get(i).dump(pw, "    ");
+                    }
                 }
                 needSep = true;
             }
@@ -7659,18 +7661,21 @@
                 while (it.hasNext()) {
                     ServiceRecord r = it.next();
                     if (r.connections.size() > 0) {
-                        Iterator<ConnectionRecord> jt
+                        Iterator<ArrayList<ConnectionRecord>> jt
                                 = r.connections.values().iterator();
                         while (jt.hasNext()) {
-                            ConnectionRecord c = jt.next();
-                            if (c.binding.client != app) {
-                                try {
-                                    //c.conn.connected(r.className, null);
-                                } catch (Exception e) {
-                                    // todo: this should be asynchronous!
-                                    Slog.w(TAG, "Exception thrown disconnected servce "
-                                          + r.shortName
-                                          + " from app " + app.processName, e);
+                            ArrayList<ConnectionRecord> cl = jt.next();
+                            for (int i=0; i<cl.size(); i++) {
+                                ConnectionRecord c = cl.get(i);
+                                if (c.binding.client != app) {
+                                    try {
+                                        //c.conn.connected(r.className, null);
+                                    } catch (Exception e) {
+                                        // todo: this should be asynchronous!
+                                        Slog.w(TAG, "Exception thrown disconnected servce "
+                                              + r.shortName
+                                              + " from app " + app.processName, e);
+                                    }
                                 }
                             }
                         }
@@ -7700,7 +7705,9 @@
                 }
                 sr.app = null;
                 sr.executeNesting = 0;
-                mStoppingServices.remove(sr);
+                if (mStoppingServices.remove(sr)) {
+                    if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
+                }
                 
                 boolean hasClients = sr.bindings.size() > 0;
                 if (hasClients) {
@@ -7753,6 +7760,7 @@
             ServiceRecord sr = mStoppingServices.get(i);
             if (sr.app == app) {
                 mStoppingServices.remove(i);
+                if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
             }
         }
         
@@ -8016,11 +8024,15 @@
         if (r.app != null && r.app.persistent) {
             info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
         }
-        for (ConnectionRecord conn : r.connections.values()) {
-            if (conn.clientLabel != 0) {
-                info.clientPackage = conn.binding.client.info.packageName;
-                info.clientLabel = conn.clientLabel;
-                break;
+
+        for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
+            for (int i=0; i<connl.size(); i++) {
+                ConnectionRecord conn = connl.get(i);
+                if (conn.clientLabel != 0) {
+                    info.clientPackage = conn.binding.client.info.packageName;
+                    info.clientLabel = conn.clientLabel;
+                    return info;
+                }
             }
         }
         return info;
@@ -8055,9 +8067,11 @@
         synchronized (this) {
             ServiceRecord r = mServices.get(name);
             if (r != null) {
-                for (ConnectionRecord conn : r.connections.values()) {
-                    if (conn.clientIntent != null) {
-                        return conn.clientIntent;
+                for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
+                    for (int i=0; i<conn.size(); i++) {
+                        if (conn.get(i).clientIntent != null) {
+                            return conn.get(i).clientIntent;
+                        }
                     }
                 }
             }
@@ -8234,8 +8248,8 @@
         while (r.pendingStarts.size() > 0) {
             try {
                 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
-                if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
-                        + r.name + " " + r.intent + " args=" + si.intent);
+                if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
+                        + r + " " + r.intent + " args=" + si.intent);
                 if (si.intent == null) {
                     // If somehow we got a dummy start at the front, then
                     // just drop it here.
@@ -8248,6 +8262,7 @@
                     grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
                             r.packageName, si.intent, si);
                 }
+                if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r);
                 bumpServiceExecutingLocked(r);
                 if (!oomAdjusted) {
                     oomAdjusted = true;
@@ -8264,6 +8279,7 @@
             } catch (RemoteException e) {
                 // Remote process gone...  we'll let the normal cleanup take
                 // care of this.
+                if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
                 break;
             } catch (Exception e) {
                 Slog.w(TAG, "Unexpected exception", e);
@@ -8280,9 +8296,9 @@
         }
         if ((!i.requested || rebind) && i.apps.size() > 0) {
             try {
+                if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bind of " + r
+                        + " in " + i + ": shouldUnbind=" + i.hasBound);
                 bumpServiceExecutingLocked(r);
-                if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
-                        + ": shouldUnbind=" + i.hasBound);
                 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
                 if (!rebind) {
                     i.requested = true;
@@ -8290,6 +8306,7 @@
                 i.hasBound = true;
                 i.doRebind = false;
             } catch (RemoteException e) {
+                if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
                 return false;
             }
         }
@@ -8316,13 +8333,12 @@
         r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
 
         app.services.add(r);
+        if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING create of " + r + " " + r.intent);
         bumpServiceExecutingLocked(r);
         updateLruProcessLocked(app, true, true);
 
         boolean created = false;
         try {
-            if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
-                    + r.name + " " + r.intent);
             mStringBuilder.setLength(0);
             r.intent.getIntent().toShortString(mStringBuilder, false, true);
             EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
@@ -8482,8 +8498,7 @@
             return true;
         }
 
-        if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
-                + " " + r.intent);
+        if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
 
         // We are now bringing the service up, so no longer in the
         // restarting state.
@@ -8534,27 +8549,30 @@
             if (!force) {
                 // XXX should probably keep a count of the number of auto-create
                 // connections directly in the service.
-                Iterator<ConnectionRecord> it = r.connections.values().iterator();
+                Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
                 while (it.hasNext()) {
-                    ConnectionRecord cr = it.next();
-                    if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
-                        return;
+                    ArrayList<ConnectionRecord> cr = it.next();
+                    for (int i=0; i<cr.size(); i++) {
+                        if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
+                            return;
+                        }
                     }
                 }
             }
 
             // Report to all of the connections that the service is no longer
             // available.
-            Iterator<ConnectionRecord> it = r.connections.values().iterator();
+            Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
             while (it.hasNext()) {
-                ConnectionRecord c = it.next();
-                try {
-                    // todo: shouldn't be a synchronous call!
-                    c.conn.connected(r.name, null);
-                } catch (Exception e) {
-                    Slog.w(TAG, "Failure disconnecting service " + r.name +
-                          " to connection " + c.conn.asBinder() +
-                          " (in " + c.binding.client.processName + ")", e);
+                ArrayList<ConnectionRecord> c = it.next();
+                for (int i=0; i<c.size(); i++) {
+                    try {
+                        c.get(i).conn.connected(r.name, null);
+                    } catch (Exception e) {
+                        Slog.w(TAG, "Failure disconnecting service " + r.name +
+                              " to connection " + c.get(i).conn.asBinder() +
+                              " (in " + c.get(i).binding.client.processName + ")", e);
+                    }
                 }
             }
         }
@@ -8568,6 +8586,8 @@
                         + ": hasBound=" + ibr.hasBound);
                 if (r.app != null && r.app.thread != null && ibr.hasBound) {
                     try {
+                        if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bring down unbind of " + r
+                                + " for " + ibr);
                         bumpServiceExecutingLocked(r);
                         updateOomAdjLocked(r.app);
                         ibr.hasBound = false;
@@ -8582,15 +8602,13 @@
             }
         }
 
-        if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
-                 + " " + r.intent);
+        if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
         EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
                 System.identityHashCode(r), r.shortName,
                 (r.app != null) ? r.app.pid : -1);
 
         mServices.remove(r.name);
         mServicesByIntent.remove(r.intent);
-        if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
         r.totalRestartCount = 0;
         unscheduleServiceRestartLocked(r);
 
@@ -8599,8 +8617,7 @@
         for (int i=0; i<N; i++) {
             if (mPendingServices.get(i) == r) {
                 mPendingServices.remove(i);
-                if (DEBUG_SERVICE) Slog.v(
-                    TAG, "Removed pending service: " + r.shortName);
+                if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
                 i--;
                 N--;
             }
@@ -8622,8 +8639,11 @@
             r.app.services.remove(r);
             if (r.app.thread != null) {
                 try {
-                    if (DEBUG_SERVICE) Slog.v(TAG,
-                            "Stopping service: " + r.shortName);
+                    if (DEBUG_SERVICE) {
+                        RuntimeException here = new RuntimeException();
+                        here.fillInStackTrace();
+                        Slog.v(TAG, ">>> EXECUTING stop of " + r, here);
+                    }
                     bumpServiceExecutingLocked(r);
                     mStoppingServices.add(r);
                     updateOomAdjLocked(r.app);
@@ -8636,11 +8656,11 @@
                 updateServiceForegroundLocked(r.app, false);
             } else {
                 if (DEBUG_SERVICE) Slog.v(
-                    TAG, "Removed service that has no process: " + r.shortName);
+                    TAG, "Removed service that has no process: " + r);
             }
         } else {
             if (DEBUG_SERVICE) Slog.v(
-                TAG, "Removed service that is not running: " + r.shortName);
+                TAG, "Removed service that is not running: " + r);
         }
     }
 
@@ -8675,8 +8695,7 @@
             int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
                     callingUid, r.packageName, service);
             if (unscheduleServiceRestartLocked(r)) {
-                if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
-                        + r.shortName);
+                if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
             }
             r.startRequested = true;
             r.callStart = false;
@@ -8970,7 +8989,7 @@
 
             if (unscheduleServiceRestartLocked(s)) {
                 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
-                        + s.shortName);
+                        + s);
             }
 
             AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
@@ -8978,7 +8997,12 @@
                     connection, flags, clientLabel, clientIntent);
 
             IBinder binder = connection.asBinder();
-            s.connections.put(binder, c);
+            ArrayList<ConnectionRecord> clist = s.connections.get(binder);
+            if (clist == null) {
+                clist = new ArrayList<ConnectionRecord>();
+                s.connections.put(binder, clist);
+            }
+            clist.add(c);
             b.connections.add(c);
             if (activity != null) {
                 if (activity.connections == null) {
@@ -8987,7 +9011,12 @@
                 activity.connections.add(c);
             }
             b.client.connections.add(c);
-            mServiceConnections.put(binder, c);
+            clist = mServiceConnections.get(binder);
+            if (clist == null) {
+                clist = new ArrayList<ConnectionRecord>();
+                mServiceConnections.put(binder, clist);
+            }
+            clist.add(c);
 
             if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                 s.lastActivity = SystemClock.uptimeMillis();
@@ -9038,7 +9067,13 @@
         IBinder binder = c.conn.asBinder();
         AppBindRecord b = c.binding;
         ServiceRecord s = b.service;
-        s.connections.remove(binder);
+        ArrayList<ConnectionRecord> clist = s.connections.get(binder);
+        if (clist != null) {
+            clist.remove(c);
+            if (clist.size() == 0) {
+                s.connections.remove(binder);
+            }
+        }
         b.connections.remove(c);
         if (c.activity != null && c.activity != skipAct) {
             if (c.activity.connections != null) {
@@ -9048,7 +9083,13 @@
         if (b.client != skipApp) {
             b.client.connections.remove(c);
         }
-        mServiceConnections.remove(binder);
+        clist = mServiceConnections.get(binder);
+        if (clist != null) {
+            clist.remove(c);
+            if (clist.size() == 0) {
+                mServiceConnections.remove(binder);
+            }
+        }
 
         if (b.connections.size() == 0) {
             b.intent.apps.remove(b.client);
@@ -9059,6 +9100,8 @@
         if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
                 && b.intent.hasBound) {
             try {
+                if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING unbind of " + s
+                        + " from " + b);
                 bumpServiceExecutingLocked(s);
                 updateOomAdjLocked(s.app);
                 b.intent.hasBound = false;
@@ -9081,8 +9124,8 @@
         synchronized (this) {
             IBinder binder = connection.asBinder();
             if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
-            ConnectionRecord r = mServiceConnections.get(binder);
-            if (r == null) {
+            ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
+            if (clist == null) {
                 Slog.w(TAG, "Unbind failed: could not find connection for "
                       + connection.asBinder());
                 return false;
@@ -9090,11 +9133,14 @@
 
             final long origId = Binder.clearCallingIdentity();
 
-            removeConnectionLocked(r, null, null);
+            while (clist.size() > 0) {
+                ConnectionRecord r = clist.get(0);
+                removeConnectionLocked(r, null, null);
 
-            if (r.binding.service.app != null) {
-                // This could have made the service less important.
-                updateOomAdjLocked(r.binding.service.app);
+                if (r.binding.service.app != null) {
+                    // This could have made the service less important.
+                    updateOomAdjLocked(r.binding.service.app);
+                }
             }
 
             Binder.restoreCallingIdentity(origId);
@@ -9117,7 +9163,7 @@
 
             final long origId = Binder.clearCallingIdentity();
 
-            if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
+            if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
                     + " " + intent + ": " + service);
             if (r != null) {
                 Intent.FilterComparison filter
@@ -9128,26 +9174,29 @@
                     b.requested = true;
                     b.received = true;
                     if (r.connections.size() > 0) {
-                        Iterator<ConnectionRecord> it
+                        Iterator<ArrayList<ConnectionRecord>> it
                                 = r.connections.values().iterator();
                         while (it.hasNext()) {
-                            ConnectionRecord c = it.next();
-                            if (!filter.equals(c.binding.intent.intent)) {
-                                if (DEBUG_SERVICE) Slog.v(
-                                        TAG, "Not publishing to: " + c);
-                                if (DEBUG_SERVICE) Slog.v(
-                                        TAG, "Bound intent: " + c.binding.intent.intent);
-                                if (DEBUG_SERVICE) Slog.v(
-                                        TAG, "Published intent: " + intent);
-                                continue;
-                            }
-                            if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
-                            try {
-                                c.conn.connected(r.name, service);
-                            } catch (Exception e) {
-                                Slog.w(TAG, "Failure sending service " + r.name +
-                                      " to connection " + c.conn.asBinder() +
-                                      " (in " + c.binding.client.processName + ")", e);
+                            ArrayList<ConnectionRecord> clist = it.next();
+                            for (int i=0; i<clist.size(); i++) {
+                                ConnectionRecord c = clist.get(i);
+                                if (!filter.equals(c.binding.intent.intent)) {
+                                    if (DEBUG_SERVICE) Slog.v(
+                                            TAG, "Not publishing to: " + c);
+                                    if (DEBUG_SERVICE) Slog.v(
+                                            TAG, "Bound intent: " + c.binding.intent.intent);
+                                    if (DEBUG_SERVICE) Slog.v(
+                                            TAG, "Published intent: " + intent);
+                                    continue;
+                                }
+                                if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
+                                try {
+                                    c.conn.connected(r.name, service);
+                                } catch (Exception e) {
+                                    Slog.w(TAG, "Failure sending service " + r.name +
+                                          " to connection " + c.conn.asBinder() +
+                                          " (in " + c.binding.client.processName + ")", e);
+                                }
                             }
                         }
                     }
@@ -9208,9 +9257,6 @@
             ServiceRecord r = (ServiceRecord)token;
             boolean inStopping = mStoppingServices.contains(token);
             if (r != null) {
-                if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
-                        + ": nesting=" + r.executeNesting
-                        + ", inStopping=" + inStopping);
                 if (r != token) {
                     Slog.w(TAG, "Done executing service " + r.name
                           + " with incorrect token: given " + token
@@ -9267,13 +9313,16 @@
                 serviceDoneExecutingLocked(r, inStopping);
                 Binder.restoreCallingIdentity(origId);
             } else {
-                Slog.w(TAG, "Done executing unknown service " + r.name
-                        + " with token " + token);
+                Slog.w(TAG, "Done executing unknown service from pid "
+                        + Binder.getCallingPid());
             }
         }
     }
 
     public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
+        if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
+                + ": nesting=" + r.executeNesting
+                + ", inStopping=" + inStopping + ", app=" + r.app);
         r.executeNesting--;
         if (r.executeNesting <= 0 && r.app != null) {
             r.app.executingServices.remove(r);
@@ -9281,6 +9330,7 @@
                 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
             }
             if (inStopping) {
+                if (DEBUG_SERVICE) Slog.v(TAG, "doneExecuting remove stopping " + r);
                 mStoppingServices.remove(r);
             }
             updateOomAdjLocked(r.app);
@@ -11071,61 +11121,64 @@
                 }
                 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
                         || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
-                    Iterator<ConnectionRecord> kt
+                    Iterator<ArrayList<ConnectionRecord>> kt
                             = s.connections.values().iterator();
                     while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
-                        // XXX should compute this based on the max of
-                        // all connected clients.
-                        ConnectionRecord cr = kt.next();
-                        if (cr.binding.client == app) {
-                            // Binding to ourself is not interesting.
-                            continue;
-                        }
-                        if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
-                            ProcessRecord client = cr.binding.client;
-                            int myHiddenAdj = hiddenAdj;
-                            if (myHiddenAdj > client.hiddenAdj) {
-                                if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
-                                    myHiddenAdj = client.hiddenAdj;
-                                } else {
-                                    myHiddenAdj = VISIBLE_APP_ADJ;
+                        ArrayList<ConnectionRecord> clist = kt.next();
+                        for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
+                            // XXX should compute this based on the max of
+                            // all connected clients.
+                            ConnectionRecord cr = clist.get(i);
+                            if (cr.binding.client == app) {
+                                // Binding to ourself is not interesting.
+                                continue;
+                            }
+                            if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
+                                ProcessRecord client = cr.binding.client;
+                                int myHiddenAdj = hiddenAdj;
+                                if (myHiddenAdj > client.hiddenAdj) {
+                                    if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
+                                        myHiddenAdj = client.hiddenAdj;
+                                    } else {
+                                        myHiddenAdj = VISIBLE_APP_ADJ;
+                                    }
+                                }
+                                int clientAdj = computeOomAdjLocked(
+                                    client, myHiddenAdj, TOP_APP, true);
+                                if (adj > clientAdj) {
+                                    adj = clientAdj >= VISIBLE_APP_ADJ
+                                            ? clientAdj : VISIBLE_APP_ADJ;
+                                    if (!client.hidden) {
+                                        app.hidden = false;
+                                    }
+                                    app.adjType = "service";
+                                    app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+                                            .REASON_SERVICE_IN_USE;
+                                    app.adjSource = cr.binding.client;
+                                    app.adjTarget = s.name;
+                                }
+                                if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
+                                    if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
+                                        schedGroup = Process.THREAD_GROUP_DEFAULT;
+                                    }
                                 }
                             }
-                            int clientAdj = computeOomAdjLocked(
-                                client, myHiddenAdj, TOP_APP, true);
-                            if (adj > clientAdj) {
-                                adj = clientAdj >= VISIBLE_APP_ADJ
-                                        ? clientAdj : VISIBLE_APP_ADJ;
-                                if (!client.hidden) {
-                                    app.hidden = false;
-                                }
+                            ActivityRecord a = cr.activity;
+                            //if (a != null) {
+                            //    Slog.i(TAG, "Connection to " + a ": state=" + a.state);
+                            //}
+                            if (a != null && adj > FOREGROUND_APP_ADJ &&
+                                    (a.state == ActivityState.RESUMED
+                                     || a.state == ActivityState.PAUSING)) {
+                                adj = FOREGROUND_APP_ADJ;
+                                schedGroup = Process.THREAD_GROUP_DEFAULT;
+                                app.hidden = false;
                                 app.adjType = "service";
                                 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
                                         .REASON_SERVICE_IN_USE;
-                                app.adjSource = cr.binding.client;
+                                app.adjSource = a;
                                 app.adjTarget = s.name;
                             }
-                            if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
-                                if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
-                                    schedGroup = Process.THREAD_GROUP_DEFAULT;
-                                }
-                            }
-                        }
-                        ActivityRecord a = cr.activity;
-                        //if (a != null) {
-                        //    Slog.i(TAG, "Connection to " + a ": state=" + a.state);
-                        //}
-                        if (a != null && adj > FOREGROUND_APP_ADJ &&
-                                (a.state == ActivityState.RESUMED
-                                 || a.state == ActivityState.PAUSING)) {
-                            adj = FOREGROUND_APP_ADJ;
-                            schedGroup = Process.THREAD_GROUP_DEFAULT;
-                            app.hidden = false;
-                            app.adjType = "service";
-                            app.adjTypeCode = ActivityManager.RunningAppProcessInfo
-                                    .REASON_SERVICE_IN_USE;
-                            app.adjSource = a;
-                            app.adjTarget = s.name;
                         }
                     }
                 }
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 255fbe3..d5b050b 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -72,8 +72,8 @@
     final HashMap<Intent.FilterComparison, IntentBindRecord> bindings
             = new HashMap<Intent.FilterComparison, IntentBindRecord>();
                             // All active bindings to the service.
-    final HashMap<IBinder, ConnectionRecord> connections
-            = new HashMap<IBinder, ConnectionRecord>();
+    final HashMap<IBinder, ArrayList<ConnectionRecord>> connections
+            = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
                             // IBinder -> ConnectionRecord of all bound clients
 
     ProcessRecord app;      // where this service is running or null.
@@ -296,10 +296,12 @@
         }
         if (connections.size() > 0) {
             pw.print(prefix); pw.println("All Connections:");
-            Iterator<ConnectionRecord> it = connections.values().iterator();
+            Iterator<ArrayList<ConnectionRecord>> it = connections.values().iterator();
             while (it.hasNext()) {
-                ConnectionRecord c = it.next();
-                pw.print(prefix); pw.print("  "); pw.println(c);
+                ArrayList<ConnectionRecord> c = it.next();
+                for (int i=0; i<c.size(); i++) {
+                    pw.print(prefix); pw.print("  "); pw.println(c.get(i));
+                }
             }
         }
     }