for (int i = 0; i < procsToKill.size(); i++) {
ProcessRecord pr = procsToKill.get(i);
if (pr.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND
- && pr.curReceiver == null) {
+ && pr.curReceivers.isEmpty()) {
pr.kill("remove task", true);
} else {
// We delay killing processes that are not in the background or running a receiver.
// LIFETIME MANAGEMENT
// =========================================================
- // Returns which broadcast queue the app is the current [or imminent] receiver
- // on, or 'null' if the app is not an active broadcast recipient.
- private BroadcastQueue isReceivingBroadcast(ProcessRecord app) {
- BroadcastRecord r = app.curReceiver;
- if (r != null) {
- return r.queue;
+ // Returns whether the app is receiving broadcast.
+ // If receiving, fetch all broadcast queues which the app is
+ // the current [or imminent] receiver on.
+ private boolean isReceivingBroadcastLocked(ProcessRecord app,
+ ArraySet<BroadcastQueue> receivingQueues) {
+ if (!app.curReceivers.isEmpty()) {
+ for (BroadcastRecord r : app.curReceivers) {
+ receivingQueues.add(r.queue);
+ }
+ return true;
}
// It's not the current receiver, but it might be starting up to become one
- synchronized (this) {
- for (BroadcastQueue queue : mBroadcastQueues) {
- r = queue.mPendingBroadcast;
- if (r != null && r.curApp == app) {
- // found it; report which queue it's in
- return queue;
- }
+ for (BroadcastQueue queue : mBroadcastQueues) {
+ final BroadcastRecord r = queue.mPendingBroadcast;
+ if (r != null && r.curApp == app) {
+ // found it; report which queue it's in
+ receivingQueues.add(queue);
}
}
- return null;
+ return !receivingQueues.isEmpty();
}
Association startAssociationLocked(int sourceUid, String sourceProcess, int sourceState,
int schedGroup;
int procState;
boolean foregroundActivities = false;
- BroadcastQueue queue;
+ final ArraySet<BroadcastQueue> queues = new ArraySet<BroadcastQueue>();
if (app == TOP_APP) {
// The last app on the list is the foreground app.
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.adjType = "instrumentation";
procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
- } else if ((queue = isReceivingBroadcast(app)) != null) {
+ } else if (isReceivingBroadcastLocked(app, queues)) {
// An app that is currently receiving a broadcast also
// counts as being in the foreground for OOM killer purposes.
// It's placed in a sched group based on the nature of the
// broadcast as reflected by which queue it's active in.
adj = ProcessList.FOREGROUND_APP_ADJ;
- schedGroup = (queue == mFgBroadcastQueue)
+ schedGroup = (queues.contains(mFgBroadcastQueue))
? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
app.adjType = "broadcast";
procState = ActivityManager.PROCESS_STATE_RECEIVER;
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
"Setting sched group of " + app.processName
+ " to " + app.curSchedGroup);
- if (app.waitingToKill != null && app.curReceiver == null
+ if (app.waitingToKill != null && app.curReceivers.isEmpty()
&& app.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND) {
app.kill(app.waitingToKill, true);
success = false;
for (i=mRemovedProcesses.size()-1; i>=0; i--) {
final ProcessRecord app = mRemovedProcesses.get(i);
if (app.activities.size() == 0
- && app.curReceiver == null && app.services.size() == 0) {
+ && app.curReceivers.isEmpty() && app.services.size() == 0) {
Slog.i(
TAG, "Exiting empty application process "
+ app.toShortString() + " ("
r.receiver = app.thread.asBinder();
r.curApp = app;
- app.curReceiver = r;
+ app.curReceivers.add(r);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
mService.updateLruProcessLocked(app, false, null);
mService.updateOomAdjLocked();
"Process cur broadcast " + r + ": NOT STARTED!");
r.receiver = null;
r.curApp = null;
- app.curReceiver = null;
+ app.curReceivers.remove(r);
}
}
}
}
r.receiver = null;
r.intent.setComponent(null);
- if (r.curApp != null && r.curApp.curReceiver == r) {
- r.curApp.curReceiver = null;
+ if (r.curApp != null && r.curApp.curReceivers.contains(r)) {
+ r.curApp.curReceivers.remove(r);
}
if (r.curFilter != null) {
r.curFilter.receiverList.curBroadcast = null;
// things that directly call the IActivityManager API, which
// are already core system stuff so don't matter for this.
r.curApp = filter.receiverList.app;
- filter.receiverList.app.curReceiver = r;
+ filter.receiverList.app.curReceivers.add(r);
mService.updateOomAdjLocked(r.curApp);
}
}
r.curFilter = null;
filter.receiverList.curBroadcast = null;
if (filter.receiverList.app != null) {
- filter.receiverList.app.curReceiver = null;
+ filter.receiverList.app.curReceivers.remove(r);
}
}
}
Bundle instrumentationArguments;// as given to us
ComponentName instrumentationResultClass;// copy of instrumentationClass
boolean usingWrapper; // Set to true when process was launched with a wrapper attached
- BroadcastRecord curReceiver;// receiver currently running in the app
+ final ArraySet<BroadcastRecord> curReceivers = new ArraySet<BroadcastRecord>();// receivers currently running in the app
long lastWakeTime; // How long proc held wake lock at last check
long lastCpuTime; // How long proc has run CPU at last check
long curCpuTime; // How long proc has run CPU most recently
pw.print(prefix); pw.print(" - "); pw.println(conProviders.get(i).toShortString());
}
}
- if (curReceiver != null) {
- pw.print(prefix); pw.print("curReceiver="); pw.println(curReceiver);
+ if (!curReceivers.isEmpty()) {
+ pw.print(prefix); pw.println("Current Receivers:");
+ for (int i=0; i < curReceivers.size(); i++) {
+ pw.print(prefix); pw.print(" - "); pw.println(curReceivers.valueAt(i));
+ }
}
if (receivers.size() > 0) {
pw.print(prefix); pw.println("Receivers:");