diff --git a/services/core/java/com/android/server/am/BroadcastConstants.java b/services/core/java/com/android/server/am/BroadcastConstants.java index dfac82cbe91b8..04ba757d03e71 100644 --- a/services/core/java/com/android/server/am/BroadcastConstants.java +++ b/services/core/java/com/android/server/am/BroadcastConstants.java @@ -136,14 +136,23 @@ public class BroadcastConstants { private static final boolean DEFAULT_MODERN_QUEUE_ENABLED = true; /** - * For {@link BroadcastQueueModernImpl}: Maximum number of process queues to - * dispatch broadcasts to simultaneously. + * For {@link BroadcastQueueModernImpl}: Maximum dispatch parallelism + * that we'll tolerate for ordinary broadcast dispatch. */ public int MAX_RUNNING_PROCESS_QUEUES = DEFAULT_MAX_RUNNING_PROCESS_QUEUES; private static final String KEY_MAX_RUNNING_PROCESS_QUEUES = "bcast_max_running_process_queues"; private static final int DEFAULT_MAX_RUNNING_PROCESS_QUEUES = ActivityManager.isLowRamDeviceStatic() ? 2 : 4; + /** + * For {@link BroadcastQueueModernImpl}: Additional running process queue parallelism beyond + * {@link #MAX_RUNNING_PROCESS_QUEUES} for dispatch of "urgent" broadcasts. + */ + public int EXTRA_RUNNING_URGENT_PROCESS_QUEUES = DEFAULT_EXTRA_RUNNING_URGENT_PROCESS_QUEUES; + private static final String KEY_EXTRA_RUNNING_URGENT_PROCESS_QUEUES = + "bcast_extra_running_urgent_process_queues"; + private static final int DEFAULT_EXTRA_RUNNING_URGENT_PROCESS_QUEUES = 1; + /** * For {@link BroadcastQueueModernImpl}: Maximum number of active broadcasts * to dispatch to a "running" process queue before we retire them back to @@ -250,6 +259,10 @@ public class BroadcastConstants { updateDeviceConfigConstants(); } + public int getMaxRunningQueues() { + return MAX_RUNNING_PROCESS_QUEUES + EXTRA_RUNNING_URGENT_PROCESS_QUEUES; + } + private void updateSettingsConstants() { synchronized (this) { try { @@ -317,6 +330,9 @@ public class BroadcastConstants { DEFAULT_MODERN_QUEUE_ENABLED); MAX_RUNNING_PROCESS_QUEUES = getDeviceConfigInt(KEY_MAX_RUNNING_PROCESS_QUEUES, DEFAULT_MAX_RUNNING_PROCESS_QUEUES); + EXTRA_RUNNING_URGENT_PROCESS_QUEUES = getDeviceConfigInt( + KEY_EXTRA_RUNNING_URGENT_PROCESS_QUEUES, + DEFAULT_EXTRA_RUNNING_URGENT_PROCESS_QUEUES); MAX_RUNNING_ACTIVE_BROADCASTS = getDeviceConfigInt(KEY_MAX_RUNNING_ACTIVE_BROADCASTS, DEFAULT_MAX_RUNNING_ACTIVE_BROADCASTS); MAX_PENDING_BROADCASTS = getDeviceConfigInt(KEY_MAX_PENDING_BROADCASTS, diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java index 7d9b4776bf372..0f9c775751af7 100644 --- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java +++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java @@ -583,6 +583,14 @@ class BroadcastProcessQueue { return mCountManifest > 0; } + /** + * Report whether this queue is currently handling an urgent broadcast. + */ + public boolean isPendingUrgent() { + BroadcastRecord next = peekNextBroadcastRecord(); + return (next != null) ? next.isUrgent() : false; + } + /** * Quickly determine if this queue has broadcasts that are still waiting to * be delivered at some point in the future. diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java index a7d843361762b..765acf49c38d3 100644 --- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java +++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java @@ -138,7 +138,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue { // We configure runnable size only once at boot; it'd be too complex to // try resizing dynamically at runtime - mRunning = new BroadcastProcessQueue[mConstants.MAX_RUNNING_PROCESS_QUEUES]; + mRunning = new BroadcastProcessQueue[mConstants.getMaxRunningQueues()]; } /** @@ -292,6 +292,19 @@ class BroadcastQueueModernImpl extends BroadcastQueue { return size; } + /** + * Return the number of active queues that are delivering "urgent" broadcasts + */ + private int getRunningUrgentCount() { + int count = 0; + for (int i = 0; i < mRunning.length; i++) { + if (mRunning[i] != null && mRunning[i].getActive().isUrgent()) { + count++; + } + } + return count; + } + /** * Return the first index of the given value contained inside * {@link #mRunning}, otherwise {@code -1}. @@ -356,7 +369,15 @@ class BroadcastQueueModernImpl extends BroadcastQueue { */ @GuardedBy("mService") private void updateRunningListLocked() { - int avail = mRunning.length - getRunningSize(); + // Allocated size here implicitly includes the extra reservation for urgent + // dispatches beyond the MAX_RUNNING_QUEUES soft limit for normal + // parallelism. If we're already dispatching some urgent broadcasts, + // count that against the extra first - its role is to permit progress of + // urgent broadcast traffic when the normal reservation is fully occupied + // with less-urgent dispatches, not to generally expand parallelism. + final int usedExtra = Math.min(getRunningUrgentCount(), + mConstants.EXTRA_RUNNING_URGENT_PROCESS_QUEUES); + int avail = mRunning.length - getRunningSize() - usedExtra; if (avail == 0) return; final int cookie = traceBegin("updateRunningList"); @@ -382,6 +403,15 @@ class BroadcastQueueModernImpl extends BroadcastQueue { continue; } + // If we've hit the soft limit for non-urgent dispatch parallelism, + // only consider delivering from queues whose ready broadcast is urgent + if (getRunningSize() >= mConstants.MAX_RUNNING_PROCESS_QUEUES) { + if (!queue.isPendingUrgent()) { + queue = nextQueue; + continue; + } + } + // If queues beyond this point aren't ready to run yet, schedule // another pass when they'll be runnable if (runnableAt > now && !waitingFor) {