Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 917d8821 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android Git Automerger
Browse files

am fde7fdd3: am 50395e80: Merge "Fix a fun bug with multiple service bindings...

am fde7fdd3: am 50395e80: Merge "Fix a fun bug with multiple service bindings from an activity." into gingerbread

Merge commit 'fde7fdd3'

* commit 'fde7fdd3':
  Fix a fun bug with multiple service bindings from an activity.
parents dcde3a8a fde7fdd3
Loading
Loading
Loading
Loading
+191 −138
Original line number Diff line number Diff line
@@ -610,8 +610,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
     * 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,
@@ -7404,12 +7404,14 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
            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;
            }
@@ -7687,10 +7689,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                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();
                            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);
@@ -7706,6 +7710,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                    }
                }
            }
        }

        // Clean up any connections this application has to other services.
        if (app.connections.size() > 0) {
@@ -7728,7 +7733,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                }
                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) {
@@ -7781,6 +7788,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
            ServiceRecord sr = mStoppingServices.get(i);
            if (sr.app == app) {
                mStoppingServices.remove(i);
                if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
            }
        }
        
@@ -8044,11 +8052,15 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
        if (r.app != null && r.app.persistent) {
            info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
        }
        for (ConnectionRecord conn : r.connections.values()) {

        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;
                break;
                    return info;
                }
            }
        }
        return info;
@@ -8083,9 +8095,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
        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;
                        }
                    }
                }
            }
@@ -8262,8 +8276,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
        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.
@@ -8276,6 +8290,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                    grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
                            r.packageName, si.intent, si);
                }
                if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r);
                bumpServiceExecutingLocked(r);
                if (!oomAdjusted) {
                    oomAdjusted = true;
@@ -8292,6 +8307,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
            } 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);
@@ -8308,9 +8324,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
        }
        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;
@@ -8318,6 +8334,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                i.hasBound = true;
                i.doRebind = false;
            } catch (RemoteException e) {
                if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
                return false;
            }
        }
@@ -8344,13 +8361,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
        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,
@@ -8510,8 +8526,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
            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.
@@ -8562,27 +8577,30 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
            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) {
                    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();
                ArrayList<ConnectionRecord> c = it.next();
                for (int i=0; i<c.size(); i++) {
                    try {
                    // todo: shouldn't be a synchronous call!
                    c.conn.connected(r.name, null);
                        c.get(i).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);
                              " to connection " + c.get(i).conn.asBinder() +
                              " (in " + c.get(i).binding.client.processName + ")", e);
                    }
                }
            }
        }
@@ -8596,6 +8614,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                        + ": 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;
@@ -8610,15 +8630,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
            }
        }

        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);

@@ -8627,8 +8645,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
        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--;
            }
@@ -8650,8 +8667,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
            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);
@@ -8664,11 +8684,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                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);
        }
    }

@@ -8703,8 +8723,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
            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;
@@ -8998,7 +9017,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen

            if (unscheduleServiceRestartLocked(s)) {
                if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
                        + s.shortName);
                        + s);
            }

            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
@@ -9006,7 +9025,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                    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) {
@@ -9015,7 +9039,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                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();
@@ -9066,7 +9095,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
        IBinder binder = c.conn.asBinder();
        AppBindRecord b = c.binding;
        ServiceRecord s = b.service;
        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) {
@@ -9076,7 +9111,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
        if (b.client != skipApp) {
            b.client.connections.remove(c);
        }
        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);
@@ -9087,6 +9128,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
        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;
@@ -9109,8 +9152,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
        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;
@@ -9118,12 +9161,15 @@ public final class ActivityManagerService extends ActivityManagerNative implemen

            final long origId = Binder.clearCallingIdentity();

            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);
                }
            }

            Binder.restoreCallingIdentity(origId);
        }
@@ -9145,7 +9191,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen

            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
@@ -9156,10 +9202,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                    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();
                            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);
@@ -9180,6 +9228,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                            }
                        }
                    }
                }

                serviceDoneExecutingLocked(r, mStoppingServices.contains(r));

@@ -9236,9 +9285,6 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
            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
@@ -9295,13 +9341,16 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                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);
@@ -9309,6 +9358,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                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);
@@ -11099,12 +11149,14 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                }
                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) {
                        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 = kt.next();
                            ConnectionRecord cr = clist.get(i);
                            if (cr.binding.client == app) {
                                // Binding to ourself is not interesting.
                                continue;
@@ -11158,6 +11210,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                        }
                    }
                }
            }
            
            // Finally, f this process has active services running in it, we
            // would like to avoid killing it unless it would prevent the current
+7 −5
Original line number Diff line number Diff line
@@ -72,8 +72,8 @@ class ServiceRecord extends Binder {
    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 @@ class ServiceRecord extends Binder {
        }
        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));
                }
            }
        }
    }