summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Lee Shombert <shombert@google.com> 2022-12-07 00:47:13 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-12-07 00:47:13 +0000
commit6b2178aaf15b23b3409cc29c27b92ce7b18b6bf8 (patch)
tree5120c0a1eae781358f30bb162f82ca35746ff0fc
parent37ce063511dfac8f31c2e458799da5e07365c8e1 (diff)
parentecacd186f9ebc9ab9ed554bba0a021859ba35fce (diff)
Merge "Minor refactoring to the modern queue"
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueueModernImpl.java105
1 files changed, 81 insertions, 24 deletions
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index 5d5dbbbed03f..e9340e9b8ecb 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -220,10 +220,19 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
private void enqueueFinishReceiver(@NonNull BroadcastProcessQueue queue,
@DeliveryState int deliveryState, @NonNull String reason) {
+ enqueueFinishReceiver(queue, queue.getActive(), queue.getActiveIndex(),
+ deliveryState, reason);
+ }
+
+ private void enqueueFinishReceiver(@NonNull BroadcastProcessQueue queue,
+ @NonNull BroadcastRecord r, int index,
+ @DeliveryState int deliveryState, @NonNull String reason) {
final SomeArgs args = SomeArgs.obtain();
args.arg1 = queue;
args.argi1 = deliveryState;
args.arg2 = reason;
+ args.arg3 = r;
+ args.argi2 = index;
mLocalHandler.sendMessage(Message.obtain(mLocalHandler, MSG_FINISH_RECEIVER, args));
}
@@ -271,8 +280,10 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
final BroadcastProcessQueue queue = (BroadcastProcessQueue) args.arg1;
final int deliveryState = args.argi1;
final String reason = (String) args.arg2;
+ final BroadcastRecord r = (BroadcastRecord) args.arg3;
+ final int index = args.argi2;
args.recycle();
- finishReceiverLocked(queue, deliveryState, reason);
+ finishReceiverLocked(queue, deliveryState, reason, r, index);
}
return true;
}
@@ -729,10 +740,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
private void scheduleReceiverWarmLocked(@NonNull BroadcastProcessQueue queue) {
checkState(queue.isActive(), "isActive");
- final ProcessRecord app = queue.app;
final BroadcastRecord r = queue.getActive();
final int index = queue.getActiveIndex();
- final Object receiver = r.receivers.get(index);
if (r.terminalCount == 0) {
r.dispatchTime = SystemClock.uptimeMillis();
@@ -740,26 +749,40 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
r.dispatchClockTime = System.currentTimeMillis();
}
- // If someone already finished this broadcast, finish immediately
+ if (maybeSkipReceiver(queue, r, index)) {
+ return;
+ }
+ dispatchReceivers(queue, r, index);
+ }
+
+ /**
+ * 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(BroadcastProcessQueue queue, BroadcastRecord r, int index) {
final int oldDeliveryState = getDeliveryState(r, index);
+ final ProcessRecord app = queue.app;
+ final Object receiver = r.receivers.get(index);
+
+ // If someone already finished this broadcast, finish immediately
if (isDeliveryStateTerminal(oldDeliveryState)) {
enqueueFinishReceiver(queue, oldDeliveryState, "already terminal state");
- return;
+ return true;
}
// Consider additional cases where we'd want to finish immediately
if (app.isInFullBackup()) {
enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_SKIPPED, "isInFullBackup");
- return;
+ return true;
}
if (mSkipPolicy.shouldSkip(r, receiver)) {
enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_SKIPPED, "mSkipPolicy");
- return;
+ return true;
}
final Intent receiverIntent = r.getReceiverIntent(receiver);
if (receiverIntent == null) {
enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_SKIPPED, "getReceiverIntent");
- return;
+ return true;
}
// Ignore registered receivers from a previous PID
@@ -767,12 +790,29 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
&& ((BroadcastFilter) receiver).receiverList.pid != app.getPid()) {
enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_SKIPPED,
"BroadcastFilter for mismatched PID");
- return;
+ return true;
}
+ // The receiver was not handled in this method.
+ return false;
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * A receiver is about to be dispatched. Start ANR timers, if necessary.
+ */
+ private void dispatchReceivers(BroadcastProcessQueue queue, 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 = (receiver instanceof BroadcastFilter) && !r.ordered;
+ final boolean assumeDelivered = isAssumedDelivered(r, index);
if (mService.mProcessesReady && !r.timeoutExempt && !assumeDelivered) {
queue.lastCpuDelayTime = queue.app.getCpuDelayTime();
@@ -805,6 +845,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
setDeliveryState(queue, app, r, index, receiver, BroadcastRecord.DELIVERY_SCHEDULED,
"scheduleReceiverWarmLocked");
+ final Intent receiverIntent = r.getReceiverIntent(receiver);
final IApplicationThread thread = app.getOnewayThread();
if (thread != null) {
try {
@@ -920,6 +961,19 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
return finishReceiverLocked(queue, BroadcastRecord.DELIVERY_DELIVERED, "remote app");
}
+ /**
+ * Return true if there are more broadcasts in the queue and the queue is runnable.
+ */
+ private boolean shouldContinueScheduling(@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);
+
+ return queue.isRunnable() && queue.isProcessWarm() && !shouldRetire;
+ }
+
private boolean finishReceiverLocked(@NonNull BroadcastProcessQueue queue,
@DeliveryState int deliveryState, @NonNull String reason) {
if (!queue.isActive()) {
@@ -927,10 +981,21 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
return false;
}
- final int cookie = traceBegin("finishReceiver");
- final ProcessRecord app = queue.app;
final BroadcastRecord r = queue.getActive();
final int index = queue.getActiveIndex();
+ return finishReceiverLocked(queue, deliveryState, reason, r, index);
+ }
+
+ private boolean finishReceiverLocked(@NonNull BroadcastProcessQueue queue,
+ @DeliveryState int deliveryState, @NonNull String reason,
+ BroadcastRecord r, int index) {
+ if (!queue.isActive()) {
+ logw("Ignoring finish; no active broadcast for " + queue);
+ return false;
+ }
+
+ final int cookie = traceBegin("finishReceiver");
+ final ProcessRecord app = queue.app;
final Object receiver = r.receivers.get(index);
setDeliveryState(queue, app, r, index, receiver, deliveryState, reason);
@@ -945,18 +1010,11 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
mLocalHandler.removeMessages(MSG_DELIVERY_TIMEOUT_HARD, 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 res;
- if (queue.isRunnable() && queue.isProcessWarm() && !shouldRetire) {
+ final boolean res = shouldContinueScheduling(queue);
+ if (res) {
// We're on a roll; move onto the next broadcast for this process
queue.makeActiveNextPending();
scheduleReceiverWarmLocked(queue);
- res = true;
} else {
// We've drained running broadcasts; maybe move back to runnable
queue.makeActiveIdle();
@@ -970,7 +1028,6 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
// Tell other OS components that app is not actively running, giving
// a chance to update OOM adjustment
notifyStoppedRunning(queue);
- res = false;
}
traceEnd(cookie);
return res;
@@ -1442,10 +1499,10 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
private void notifyFinishBroadcast(@NonNull BroadcastRecord r) {
mService.notifyBroadcastFinishedLocked(r);
- mHistory.addBroadcastToHistoryLocked(r);
-
r.finishTime = SystemClock.uptimeMillis();
r.nextReceiver = r.receivers.size();
+ mHistory.addBroadcastToHistoryLocked(r);
+
BroadcastQueueImpl.logBootCompletedBroadcastCompletionLatencyIfPossible(r);
if (r.intent.getComponent() == null && r.intent.getPackage() == null