diff options
3 files changed, 34 insertions, 29 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index eb5bf228b852..c985a5853b5d 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -9522,7 +9522,7 @@ public final class ActivityManagerService extends ActivityManagerNative 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. @@ -18903,26 +18903,28 @@ public final class ActivityManagerService extends ActivityManagerNative // 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, @@ -19085,7 +19087,7 @@ public final class ActivityManagerService extends ActivityManagerNative 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; @@ -19099,13 +19101,13 @@ public final class ActivityManagerService extends ActivityManagerNative 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; @@ -20115,7 +20117,7 @@ public final class ActivityManagerService extends ActivityManagerNative 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; @@ -20985,7 +20987,7 @@ public final class ActivityManagerService extends ActivityManagerNative 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() + " (" diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index a279290a34be..8e33c4f4bc35 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -265,7 +265,7 @@ public final class BroadcastQueue { 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(); @@ -293,7 +293,7 @@ public final class BroadcastQueue { "Process cur broadcast " + r + ": NOT STARTED!"); r.receiver = null; r.curApp = null; - app.curReceiver = null; + app.curReceivers.remove(r); } } } @@ -389,8 +389,8 @@ public final class BroadcastQueue { } 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; @@ -643,7 +643,7 @@ public final class BroadcastQueue { // 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); } } @@ -671,7 +671,7 @@ public final class BroadcastQueue { r.curFilter = null; filter.receiverList.curBroadcast = null; if (filter.receiverList.app != null) { - filter.receiverList.app.curReceiver = null; + filter.receiverList.app.curReceivers.remove(r); } } } diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 8911a3e94979..68de95fbfe98 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -138,7 +138,7 @@ final class ProcessRecord { 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 @@ -421,8 +421,11 @@ final class ProcessRecord { 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:"); |