summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/am/BroadcastConstants.java20
-rw-r--r--services/core/java/com/android/server/am/BroadcastProcessQueue.java8
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueueModernImpl.java34
3 files changed, 58 insertions, 4 deletions
diff --git a/services/core/java/com/android/server/am/BroadcastConstants.java b/services/core/java/com/android/server/am/BroadcastConstants.java
index dfac82cbe91b..04ba757d03e7 100644
--- a/services/core/java/com/android/server/am/BroadcastConstants.java
+++ b/services/core/java/com/android/server/am/BroadcastConstants.java
@@ -136,8 +136,8 @@ 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";
@@ -145,6 +145,15 @@ public class BroadcastConstants {
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
* being "runnable" to give other processes a chance to run.
@@ -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 7d9b4776bf37..0f9c775751af 100644
--- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
@@ -584,6 +584,14 @@ class BroadcastProcessQueue {
}
/**
+ * 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 a7d843361762..765acf49c38d 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()];
}
/**
@@ -293,6 +293,19 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
}
/**
+ * 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) {