diff options
| author | 2022-12-07 00:47:13 +0000 | |
|---|---|---|
| committer | 2022-12-07 00:47:13 +0000 | |
| commit | 6b2178aaf15b23b3409cc29c27b92ce7b18b6bf8 (patch) | |
| tree | 5120c0a1eae781358f30bb162f82ca35746ff0fc | |
| parent | 37ce063511dfac8f31c2e458799da5e07365c8e1 (diff) | |
| parent | ecacd186f9ebc9ab9ed554bba0a021859ba35fce (diff) | |
Merge "Minor refactoring to the modern queue"
| -rw-r--r-- | services/core/java/com/android/server/am/BroadcastQueueModernImpl.java | 105 |
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 |