Merge "Increase the active broadcast delivery limit to core components." into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
dad2f513c4
@@ -179,10 +179,38 @@ public class BroadcastConstants {
|
||||
* being "runnable" to give other processes a chance to run.
|
||||
*/
|
||||
public int MAX_RUNNING_ACTIVE_BROADCASTS = DEFAULT_MAX_RUNNING_ACTIVE_BROADCASTS;
|
||||
private static final String KEY_MAX_RUNNING_ACTIVE_BROADCASTS = "bcast_max_running_active_broadcasts";
|
||||
private static final String KEY_MAX_RUNNING_ACTIVE_BROADCASTS =
|
||||
"bcast_max_running_active_broadcasts";
|
||||
private static final int DEFAULT_MAX_RUNNING_ACTIVE_BROADCASTS =
|
||||
ActivityManager.isLowRamDeviceStatic() ? 8 : 16;
|
||||
|
||||
/**
|
||||
* For {@link BroadcastQueueModernImpl}: Maximum number of active "blocking" broadcasts
|
||||
* to dispatch to a "running" System process queue before we retire them back to
|
||||
* being "runnable" to give other processes a chance to run. Here "blocking" refers to
|
||||
* whether or not we are going to block on the finishReceiver() to be called before moving
|
||||
* to the next broadcast.
|
||||
*/
|
||||
public int MAX_CORE_RUNNING_BLOCKING_BROADCASTS = DEFAULT_MAX_CORE_RUNNING_BLOCKING_BROADCASTS;
|
||||
private static final String KEY_CORE_MAX_RUNNING_BLOCKING_BROADCASTS =
|
||||
"bcast_max_core_running_blocking_broadcasts";
|
||||
private static final int DEFAULT_MAX_CORE_RUNNING_BLOCKING_BROADCASTS =
|
||||
ActivityManager.isLowRamDeviceStatic() ? 8 : 16;
|
||||
|
||||
/**
|
||||
* For {@link BroadcastQueueModernImpl}: Maximum number of active non-"blocking" broadcasts
|
||||
* to dispatch to a "running" System process queue before we retire them back to
|
||||
* being "runnable" to give other processes a chance to run. Here "blocking" refers to
|
||||
* whether or not we are going to block on the finishReceiver() to be called before moving
|
||||
* to the next broadcast.
|
||||
*/
|
||||
public int MAX_CORE_RUNNING_NON_BLOCKING_BROADCASTS =
|
||||
DEFAULT_MAX_CORE_RUNNING_NON_BLOCKING_BROADCASTS;
|
||||
private static final String KEY_CORE_MAX_RUNNING_NON_BLOCKING_BROADCASTS =
|
||||
"bcast_max_core_running_non_blocking_broadcasts";
|
||||
private static final int DEFAULT_MAX_CORE_RUNNING_NON_BLOCKING_BROADCASTS =
|
||||
ActivityManager.isLowRamDeviceStatic() ? 32 : 64;
|
||||
|
||||
/**
|
||||
* For {@link BroadcastQueueModernImpl}: Maximum number of pending
|
||||
* broadcasts to hold for a process before we ignore any delays that policy
|
||||
@@ -369,6 +397,12 @@ public class BroadcastConstants {
|
||||
DEFAULT_MAX_CONSECUTIVE_NORMAL_DISPATCHES);
|
||||
MAX_RUNNING_ACTIVE_BROADCASTS = getDeviceConfigInt(KEY_MAX_RUNNING_ACTIVE_BROADCASTS,
|
||||
DEFAULT_MAX_RUNNING_ACTIVE_BROADCASTS);
|
||||
MAX_CORE_RUNNING_BLOCKING_BROADCASTS = getDeviceConfigInt(
|
||||
KEY_CORE_MAX_RUNNING_BLOCKING_BROADCASTS,
|
||||
DEFAULT_MAX_CORE_RUNNING_BLOCKING_BROADCASTS);
|
||||
MAX_CORE_RUNNING_NON_BLOCKING_BROADCASTS = getDeviceConfigInt(
|
||||
KEY_CORE_MAX_RUNNING_NON_BLOCKING_BROADCASTS,
|
||||
DEFAULT_MAX_CORE_RUNNING_NON_BLOCKING_BROADCASTS);
|
||||
MAX_PENDING_BROADCASTS = getDeviceConfigInt(KEY_MAX_PENDING_BROADCASTS,
|
||||
DEFAULT_MAX_PENDING_BROADCASTS);
|
||||
DELAY_NORMAL_MILLIS = getDeviceConfigLong(KEY_DELAY_NORMAL_MILLIS,
|
||||
@@ -418,6 +452,10 @@ public class BroadcastConstants {
|
||||
pw.print(KEY_MODERN_QUEUE_ENABLED, MODERN_QUEUE_ENABLED).println();
|
||||
pw.print(KEY_MAX_RUNNING_PROCESS_QUEUES, MAX_RUNNING_PROCESS_QUEUES).println();
|
||||
pw.print(KEY_MAX_RUNNING_ACTIVE_BROADCASTS, MAX_RUNNING_ACTIVE_BROADCASTS).println();
|
||||
pw.print(KEY_CORE_MAX_RUNNING_BLOCKING_BROADCASTS,
|
||||
MAX_CORE_RUNNING_BLOCKING_BROADCASTS).println();
|
||||
pw.print(KEY_CORE_MAX_RUNNING_NON_BLOCKING_BROADCASTS,
|
||||
MAX_CORE_RUNNING_NON_BLOCKING_BROADCASTS).println();
|
||||
pw.print(KEY_MAX_PENDING_BROADCASTS, MAX_PENDING_BROADCASTS).println();
|
||||
pw.print(KEY_DELAY_NORMAL_MILLIS,
|
||||
TimeUtils.formatDuration(DELAY_NORMAL_MILLIS)).println();
|
||||
|
||||
@@ -142,6 +142,12 @@ class BroadcastProcessQueue {
|
||||
*/
|
||||
private int mActiveCountSinceIdle;
|
||||
|
||||
/**
|
||||
* Count of {@link #mActive} broadcasts with assumed delivery that have been dispatched
|
||||
* since this queue was last idle.
|
||||
*/
|
||||
private int mActiveAssumedDeliveryCountSinceIdle;
|
||||
|
||||
/**
|
||||
* Flag indicating that the currently active broadcast is being dispatched
|
||||
* was scheduled via a cold start.
|
||||
@@ -499,6 +505,14 @@ class BroadcastProcessQueue {
|
||||
return mActiveCountSinceIdle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count of {@link #mActive} broadcasts with assumed delivery that have been dispatched
|
||||
* since this queue was last idle.
|
||||
*/
|
||||
public int getActiveAssumedDeliveryCountSinceIdle() {
|
||||
return mActiveAssumedDeliveryCountSinceIdle;
|
||||
}
|
||||
|
||||
public void setActiveViaColdStart(boolean activeViaColdStart) {
|
||||
mActiveViaColdStart = activeViaColdStart;
|
||||
}
|
||||
@@ -532,6 +546,8 @@ class BroadcastProcessQueue {
|
||||
mActive = (BroadcastRecord) next.arg1;
|
||||
mActiveIndex = next.argi1;
|
||||
mActiveCountSinceIdle++;
|
||||
mActiveAssumedDeliveryCountSinceIdle +=
|
||||
(mActive.isAssumedDelivered(mActiveIndex) ? 1 : 0);
|
||||
mActiveViaColdStart = false;
|
||||
mActiveWasStopped = false;
|
||||
next.recycle();
|
||||
@@ -545,6 +561,7 @@ class BroadcastProcessQueue {
|
||||
mActive = null;
|
||||
mActiveIndex = 0;
|
||||
mActiveCountSinceIdle = 0;
|
||||
mActiveAssumedDeliveryCountSinceIdle = 0;
|
||||
mActiveViaColdStart = false;
|
||||
invalidateRunnableAt();
|
||||
}
|
||||
@@ -1369,6 +1386,7 @@ class BroadcastProcessQueue {
|
||||
pw.print(" m:"); pw.print(mCountManifest);
|
||||
|
||||
pw.print(" csi:"); pw.print(mActiveCountSinceIdle);
|
||||
pw.print(" adcsi:"); pw.print(mActiveAssumedDeliveryCountSinceIdle);
|
||||
pw.print(" ccu:"); pw.print(mActiveCountConsecutiveUrgent);
|
||||
pw.print(" ccn:"); pw.print(mActiveCountConsecutiveNormal);
|
||||
pw.println();
|
||||
|
||||
@@ -40,6 +40,7 @@ import static com.android.server.am.BroadcastRecord.getReceiverProcessName;
|
||||
import static com.android.server.am.BroadcastRecord.getReceiverUid;
|
||||
import static com.android.server.am.BroadcastRecord.isDeliveryStateTerminal;
|
||||
|
||||
import android.annotation.CheckResult;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UptimeMillisLong;
|
||||
@@ -446,43 +447,29 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
|
||||
if (DEBUG_BROADCAST) logv("Promoting " + queue
|
||||
+ " from runnable to running; process is " + queue.app);
|
||||
|
||||
// Allocate this available permit and start running!
|
||||
final int queueIndex = getRunningIndexOf(null);
|
||||
mRunning[queueIndex] = queue;
|
||||
avail--;
|
||||
|
||||
// Remove ourselves from linked list of runnable things
|
||||
mRunnableHead = removeFromRunnableList(mRunnableHead, queue);
|
||||
|
||||
// Emit all trace events for this process into a consistent track
|
||||
queue.runningTraceTrackName = TAG + ".mRunning[" + queueIndex + "]";
|
||||
queue.runningOomAdjusted = queue.isPendingManifest()
|
||||
|| queue.isPendingOrdered()
|
||||
|| queue.isPendingResultTo();
|
||||
|
||||
// If already warm, we can make OOM adjust request immediately;
|
||||
// otherwise we need to wait until process becomes warm
|
||||
promoteToRunningLocked(queue);
|
||||
final boolean completed;
|
||||
if (processWarm) {
|
||||
notifyStartedRunning(queue);
|
||||
updateOomAdj |= queue.runningOomAdjusted;
|
||||
}
|
||||
|
||||
// If we're already warm, schedule next pending broadcast now;
|
||||
// otherwise we'll wait for the cold start to circle back around
|
||||
queue.makeActiveNextPending();
|
||||
if (processWarm) {
|
||||
queue.traceProcessRunningBegin();
|
||||
scheduleReceiverWarmLocked(queue);
|
||||
completed = scheduleReceiverWarmLocked(queue);
|
||||
} else {
|
||||
queue.traceProcessStartingBegin();
|
||||
scheduleReceiverColdLocked(queue);
|
||||
completed = scheduleReceiverColdLocked(queue);
|
||||
}
|
||||
// If we are done with delivering the broadcasts to the process, we can demote it
|
||||
// from the "running" list.
|
||||
if (completed) {
|
||||
demoteFromRunningLocked(queue);
|
||||
}
|
||||
// TODO: If delivering broadcasts to a process is finished, we don't have to hold
|
||||
// a slot for it.
|
||||
avail--;
|
||||
|
||||
// Move to considering next runnable queue
|
||||
queue = nextQueue;
|
||||
}
|
||||
|
||||
// TODO: We need to update oomAdj early as this currently doesn't guarantee that the
|
||||
// procState is updated correctly when the app is handling a broadcast.
|
||||
if (updateOomAdj) {
|
||||
mService.updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_START_RECEIVER);
|
||||
}
|
||||
@@ -514,7 +501,9 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
|
||||
queue.traceProcessEnd();
|
||||
queue.traceProcessRunningBegin();
|
||||
scheduleReceiverWarmLocked(queue);
|
||||
if (scheduleReceiverWarmLocked(queue)) {
|
||||
demoteFromRunningLocked(queue);
|
||||
}
|
||||
|
||||
// We might be willing to kick off another cold start
|
||||
enqueueUpdateRunningList();
|
||||
@@ -558,6 +547,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
if (queue.isActive()) {
|
||||
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE,
|
||||
"onApplicationCleanupLocked");
|
||||
demoteFromRunningLocked(queue);
|
||||
}
|
||||
|
||||
// Skip any pending registered receivers, since the old process
|
||||
@@ -695,8 +685,13 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
* Schedule the currently active broadcast on the given queue when we know
|
||||
* the process is cold. This kicks off a cold start and will eventually call
|
||||
* through to {@link #scheduleReceiverWarmLocked} once it's ready.
|
||||
*
|
||||
* @return {@code true} if the broadcast delivery is finished and the process queue can
|
||||
* be demoted from the running list. Otherwise {@code false}.
|
||||
*/
|
||||
private void scheduleReceiverColdLocked(@NonNull BroadcastProcessQueue queue) {
|
||||
@CheckResult
|
||||
@GuardedBy("mService")
|
||||
private boolean scheduleReceiverColdLocked(@NonNull BroadcastProcessQueue queue) {
|
||||
checkState(queue.isActive(), "isActive");
|
||||
|
||||
// Remember that active broadcast was scheduled via a cold start
|
||||
@@ -711,12 +706,14 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
mRunningColdStart = null;
|
||||
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_SKIPPED,
|
||||
"BroadcastFilter for cold app");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (maybeSkipReceiver(queue, r, index)) {
|
||||
final String skipReason = shouldSkipReceiver(queue, r, index);
|
||||
if (skipReason != null) {
|
||||
mRunningColdStart = null;
|
||||
return;
|
||||
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_SKIPPED, skipReason);
|
||||
return true;
|
||||
}
|
||||
|
||||
final ApplicationInfo info = ((ResolveInfo) receiver).activityInfo.applicationInfo;
|
||||
@@ -742,8 +739,9 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
mRunningColdStart = null;
|
||||
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE,
|
||||
"startProcessLocked failed");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -754,38 +752,46 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
* results by calling through to {@link #finishReceiverLocked}, both in the
|
||||
* case where a broadcast is handled by a remote app, and the case where the
|
||||
* broadcast was finished locally without the remote app being involved.
|
||||
*
|
||||
* @return {@code true} if the broadcast delivery is finished and the process queue can
|
||||
* be demoted from the running list. Otherwise {@code false}.
|
||||
*/
|
||||
@CheckResult
|
||||
@GuardedBy("mService")
|
||||
private void scheduleReceiverWarmLocked(@NonNull BroadcastProcessQueue queue) {
|
||||
private boolean scheduleReceiverWarmLocked(@NonNull BroadcastProcessQueue queue) {
|
||||
checkState(queue.isActive(), "isActive");
|
||||
|
||||
final BroadcastRecord r = queue.getActive();
|
||||
final int index = queue.getActiveIndex();
|
||||
final int cookie = traceBegin("scheduleReceiverWarmLocked");
|
||||
while (queue.isActive()) {
|
||||
final BroadcastRecord r = queue.getActive();
|
||||
final int index = queue.getActiveIndex();
|
||||
|
||||
if (r.terminalCount == 0) {
|
||||
r.dispatchTime = SystemClock.uptimeMillis();
|
||||
r.dispatchRealTime = SystemClock.elapsedRealtime();
|
||||
r.dispatchClockTime = System.currentTimeMillis();
|
||||
}
|
||||
if (r.terminalCount == 0) {
|
||||
r.dispatchTime = SystemClock.uptimeMillis();
|
||||
r.dispatchRealTime = SystemClock.elapsedRealtime();
|
||||
r.dispatchClockTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
if (maybeSkipReceiver(queue, r, index)) {
|
||||
return;
|
||||
}
|
||||
dispatchReceivers(queue, r, index);
|
||||
}
|
||||
final String skipReason = shouldSkipReceiver(queue, r, index);
|
||||
if (skipReason == null) {
|
||||
final boolean isBlockingDispatch = dispatchReceivers(queue, r, index);
|
||||
if (isBlockingDispatch) {
|
||||
traceEnd(cookie);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_SKIPPED, skipReason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Examine a receiver and possibly skip it. The method returns true if the receiver is
|
||||
* skipped (and therefore no more work is required).
|
||||
*/
|
||||
private boolean maybeSkipReceiver(@NonNull BroadcastProcessQueue queue,
|
||||
@NonNull BroadcastRecord r, int index) {
|
||||
final String reason = shouldSkipReceiver(queue, r, index);
|
||||
if (reason != null) {
|
||||
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_SKIPPED, reason);
|
||||
return true;
|
||||
if (shouldRetire(queue)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// We're on a roll; move onto the next broadcast for this process
|
||||
queue.makeActiveNextPending();
|
||||
}
|
||||
return false;
|
||||
traceEnd(cookie);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -825,25 +831,22 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this receiver should be assumed to have been delivered.
|
||||
*/
|
||||
private boolean isAssumedDelivered(BroadcastRecord r, int index) {
|
||||
return (r.receivers.get(index) instanceof BroadcastFilter) && !r.ordered
|
||||
&& (r.resultTo == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* A receiver is about to be dispatched. Start ANR timers, if necessary.
|
||||
*
|
||||
* @return {@code true} if this a blocking delivery. That is, we are going to block on the
|
||||
* finishReceiver() to be called before moving to the next broadcast. Otherwise,
|
||||
* {@code false}.
|
||||
*/
|
||||
private void dispatchReceivers(@NonNull BroadcastProcessQueue queue,
|
||||
@CheckResult
|
||||
private boolean dispatchReceivers(@NonNull BroadcastProcessQueue queue,
|
||||
@NonNull BroadcastRecord r, int index) {
|
||||
final ProcessRecord app = queue.app;
|
||||
final Object receiver = r.receivers.get(index);
|
||||
|
||||
// Skip ANR tracking early during boot, when requested, or when we
|
||||
// immediately assume delivery success
|
||||
final boolean assumeDelivered = isAssumedDelivered(r, index);
|
||||
final boolean assumeDelivered = r.isAssumedDelivered(index);
|
||||
if (mService.mProcessesReady && !r.timeoutExempt && !assumeDelivered) {
|
||||
queue.lastCpuDelayTime = queue.app.getCpuDelayTime();
|
||||
|
||||
@@ -898,6 +901,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
if (assumeDelivered) {
|
||||
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_DELIVERED,
|
||||
"assuming delivered");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
notifyScheduleReceiver(app, r, (ResolveInfo) receiver);
|
||||
@@ -908,17 +912,21 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
r.shareIdentity ? r.callingUid : Process.INVALID_UID,
|
||||
r.shareIdentity ? r.callerPackage : null);
|
||||
}
|
||||
return true;
|
||||
} catch (RemoteException e) {
|
||||
final String msg = "Failed to schedule " + r + " to " + receiver
|
||||
+ " via " + app + ": " + e;
|
||||
logw(msg);
|
||||
app.killLocked("Can't deliver broadcast", ApplicationExitInfo.REASON_OTHER,
|
||||
ApplicationExitInfo.SUBREASON_UNDELIVERED_BROADCAST, true);
|
||||
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE, "remote app");
|
||||
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE,
|
||||
"remote app");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE,
|
||||
"missing IApplicationThread");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -989,6 +997,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
private void deliveryTimeoutHardLocked(@NonNull BroadcastProcessQueue queue) {
|
||||
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_TIMEOUT,
|
||||
"deliveryTimeoutHardLocked");
|
||||
demoteFromRunningLocked(queue);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1015,7 +1024,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
// To ensure that "beyond" high-water marks are updated in a monotonic
|
||||
// way, we finish this receiver before possibly skipping any remaining
|
||||
// aborted receivers
|
||||
final boolean res = finishReceiverActiveLocked(queue,
|
||||
finishReceiverActiveLocked(queue,
|
||||
BroadcastRecord.DELIVERY_DELIVERED, "remote app");
|
||||
|
||||
// When the caller aborted an ordered broadcast, we mark all
|
||||
@@ -1027,30 +1036,52 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
if (shouldRetire(queue)) {
|
||||
demoteFromRunningLocked(queue);
|
||||
return true;
|
||||
}
|
||||
|
||||
// We're on a roll; move onto the next broadcast for this process
|
||||
queue.makeActiveNextPending();
|
||||
if (scheduleReceiverWarmLocked(queue)) {
|
||||
demoteFromRunningLocked(queue);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if there are more broadcasts in the queue and the queue is runnable.
|
||||
* Return true if there are no more broadcasts in the queue or if the queue is not runnable.
|
||||
*/
|
||||
private boolean shouldContinueScheduling(@NonNull BroadcastProcessQueue queue) {
|
||||
private boolean shouldRetire(@NonNull BroadcastProcessQueue queue) {
|
||||
// If we've made reasonable progress, periodically retire ourselves to
|
||||
// avoid starvation of other processes and stack overflow when a
|
||||
// broadcast is immediately finished without waiting
|
||||
final boolean shouldRetire =
|
||||
(queue.getActiveCountSinceIdle() >= mConstants.MAX_RUNNING_ACTIVE_BROADCASTS);
|
||||
final boolean shouldRetire;
|
||||
if (UserHandle.isCore(queue.uid)) {
|
||||
final int nonBlockingDeliveryCount = queue.getActiveAssumedDeliveryCountSinceIdle();
|
||||
final int blockingDeliveryCount = (queue.getActiveCountSinceIdle()
|
||||
- queue.getActiveAssumedDeliveryCountSinceIdle());
|
||||
shouldRetire = (blockingDeliveryCount
|
||||
>= mConstants.MAX_CORE_RUNNING_BLOCKING_BROADCASTS) || (nonBlockingDeliveryCount
|
||||
>= mConstants.MAX_CORE_RUNNING_NON_BLOCKING_BROADCASTS);
|
||||
} else {
|
||||
shouldRetire =
|
||||
(queue.getActiveCountSinceIdle() >= mConstants.MAX_RUNNING_ACTIVE_BROADCASTS);
|
||||
}
|
||||
|
||||
return queue.isRunnable() && queue.isProcessWarm() && !shouldRetire;
|
||||
return !queue.isRunnable() || !queue.isProcessWarm() || shouldRetire;
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate all active broadcasts on the queue.
|
||||
*/
|
||||
private boolean finishReceiverActiveLocked(@NonNull BroadcastProcessQueue queue,
|
||||
private void finishReceiverActiveLocked(@NonNull BroadcastProcessQueue queue,
|
||||
@DeliveryState int deliveryState, @NonNull String reason) {
|
||||
if (!queue.isActive()) {
|
||||
logw("Ignoring finish; no active broadcast for " + queue);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
final int cookie = traceBegin("finishReceiver");
|
||||
@@ -1077,27 +1108,63 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
// Given that a receiver just finished, check if the "waitingFor" conditions are met.
|
||||
checkAndRemoveWaitingFor();
|
||||
|
||||
final boolean res = shouldContinueScheduling(queue);
|
||||
if (res) {
|
||||
// We're on a roll; move onto the next broadcast for this process
|
||||
queue.makeActiveNextPending();
|
||||
scheduleReceiverWarmLocked(queue);
|
||||
} else {
|
||||
// We've drained running broadcasts; maybe move back to runnable
|
||||
queue.makeActiveIdle();
|
||||
queue.traceProcessEnd();
|
||||
|
||||
final int queueIndex = getRunningIndexOf(queue);
|
||||
mRunning[queueIndex] = null;
|
||||
updateRunnableList(queue);
|
||||
enqueueUpdateRunningList();
|
||||
|
||||
// Tell other OS components that app is not actively running, giving
|
||||
// a chance to update OOM adjustment
|
||||
notifyStoppedRunning(queue);
|
||||
}
|
||||
traceEnd(cookie);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Promote a process to the "running" list.
|
||||
*/
|
||||
@GuardedBy("mService")
|
||||
private void promoteToRunningLocked(@NonNull BroadcastProcessQueue queue) {
|
||||
// Allocate this available permit and start running!
|
||||
final int queueIndex = getRunningIndexOf(null);
|
||||
mRunning[queueIndex] = queue;
|
||||
|
||||
// Remove ourselves from linked list of runnable things
|
||||
mRunnableHead = removeFromRunnableList(mRunnableHead, queue);
|
||||
|
||||
// Emit all trace events for this process into a consistent track
|
||||
queue.runningTraceTrackName = TAG + ".mRunning[" + queueIndex + "]";
|
||||
queue.runningOomAdjusted = queue.isPendingManifest()
|
||||
|| queue.isPendingOrdered()
|
||||
|| queue.isPendingResultTo();
|
||||
|
||||
// If already warm, we can make OOM adjust request immediately;
|
||||
// otherwise we need to wait until process becomes warm
|
||||
final boolean processWarm = queue.isProcessWarm();
|
||||
if (processWarm) {
|
||||
notifyStartedRunning(queue);
|
||||
}
|
||||
|
||||
// If we're already warm, schedule next pending broadcast now;
|
||||
// otherwise we'll wait for the cold start to circle back around
|
||||
queue.makeActiveNextPending();
|
||||
if (processWarm) {
|
||||
queue.traceProcessRunningBegin();
|
||||
} else {
|
||||
queue.traceProcessStartingBegin();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Demote a process from the "running" list.
|
||||
*/
|
||||
@GuardedBy("mService")
|
||||
private void demoteFromRunningLocked(@NonNull BroadcastProcessQueue queue) {
|
||||
final int cookie = traceBegin("demoteFromRunning");
|
||||
// We've drained running broadcasts; maybe move back to runnable
|
||||
queue.makeActiveIdle();
|
||||
queue.traceProcessEnd();
|
||||
|
||||
final int queueIndex = getRunningIndexOf(queue);
|
||||
mRunning[queueIndex] = null;
|
||||
updateRunnableList(queue);
|
||||
enqueueUpdateRunningList();
|
||||
|
||||
// Tell other OS components that app is not actively running, giving
|
||||
// a chance to update OOM adjustment
|
||||
notifyStoppedRunning(queue);
|
||||
traceEnd(cookie);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -237,6 +237,14 @@ final class BroadcastRecord extends Binder {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this receiver should be assumed to have been delivered.
|
||||
*/
|
||||
boolean isAssumedDelivered(int index) {
|
||||
return (receivers.get(index) instanceof BroadcastFilter) && !ordered
|
||||
&& (resultTo == null);
|
||||
}
|
||||
|
||||
ProcessRecord curApp; // hosting application of current receiver.
|
||||
ComponentName curComponent; // the receiver class that is currently running.
|
||||
ActivityInfo curReceiver; // the manifest receiver that is currently running.
|
||||
|
||||
Reference in New Issue
Block a user