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