Loading services/core/java/com/android/server/am/BroadcastQueueModernImpl.java +81 −24 Original line number Diff line number Diff line Loading @@ -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)); } Loading Loading @@ -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; } Loading Loading @@ -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(); Loading @@ -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 Loading @@ -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(); Loading Loading @@ -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 { Loading Loading @@ -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()) { Loading @@ -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); Loading @@ -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(); Loading @@ -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; Loading Loading @@ -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 Loading Loading
services/core/java/com/android/server/am/BroadcastQueueModernImpl.java +81 −24 Original line number Diff line number Diff line Loading @@ -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)); } Loading Loading @@ -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; } Loading Loading @@ -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(); Loading @@ -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 Loading @@ -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(); Loading Loading @@ -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 { Loading Loading @@ -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()) { Loading @@ -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); Loading @@ -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(); Loading @@ -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; Loading Loading @@ -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 Loading