BroadcastQueue: constants via DeviceConfig.
Move our initial set of configuration knobs to be loaded and updated via DeviceConfig inside BroadcastConstants. This leaves BroadcastConstants with a mix of queue-specific values and global values; we leave TODOs to detangle this in the future. Bug: 245771249 Test: atest FrameworksMockingServicesTests:BroadcastQueueTest Change-Id: I367d23eedacf132759cc7e4b6dab0e07da6e2253
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package com.android.server.am;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.compat.annotation.ChangeId;
|
||||
import android.compat.annotation.EnabledAfter;
|
||||
import android.compat.annotation.Overridable;
|
||||
@@ -24,6 +25,8 @@ import android.content.ContentResolver;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerExecutor;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.Settings;
|
||||
import android.util.KeyValueListParser;
|
||||
import android.util.Slog;
|
||||
@@ -39,6 +42,9 @@ import java.lang.annotation.RetentionPolicy;
|
||||
public class BroadcastConstants {
|
||||
private static final String TAG = "BroadcastConstants";
|
||||
|
||||
// TODO: migrate remaining constants to be loaded from DeviceConfig
|
||||
// TODO: migrate fg/bg values into single constants instance
|
||||
|
||||
// Value element names within the Settings record
|
||||
static final String KEY_TIMEOUT = "bcast_timeout";
|
||||
static final String KEY_SLOW_TIME = "bcast_slow_time";
|
||||
@@ -115,6 +121,35 @@ public class BroadcastConstants {
|
||||
// started its process can start a background activity.
|
||||
public long ALLOW_BG_ACTIVITY_START_TIMEOUT = DEFAULT_ALLOW_BG_ACTIVITY_START_TIMEOUT;
|
||||
|
||||
/**
|
||||
* For {@link BroadcastQueueModernImpl}: Maximum number of process queues to
|
||||
* dispatch broadcasts to simultaneously.
|
||||
*/
|
||||
public int MAX_RUNNING_PROCESS_QUEUES = DEFAULT_MAX_RUNNING_PROCESS_QUEUES;
|
||||
private static final int DEFAULT_MAX_RUNNING_PROCESS_QUEUES = 4;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public int MAX_RUNNING_ACTIVE_BROADCASTS = DEFAULT_MAX_RUNNING_ACTIVE_BROADCASTS;
|
||||
private static final int DEFAULT_MAX_RUNNING_ACTIVE_BROADCASTS = 16;
|
||||
|
||||
/**
|
||||
* For {@link BroadcastQueueModernImpl}: Default delay to apply to normal
|
||||
* broadcasts, giving a chance for debouncing of rapidly changing events.
|
||||
*/
|
||||
public long DELAY_NORMAL_MILLIS = DEFAULT_DELAY_NORMAL_MILLIS;
|
||||
private static final long DEFAULT_DELAY_NORMAL_MILLIS = 10_000 * Build.HW_TIMEOUT_MULTIPLIER;
|
||||
|
||||
/**
|
||||
* For {@link BroadcastQueueModernImpl}: Default delay to apply to
|
||||
* broadcasts targeting cached applications.
|
||||
*/
|
||||
public long DELAY_CACHED_MILLIS = DEFAULT_DELAY_CACHED_MILLIS;
|
||||
private static final long DEFAULT_DELAY_CACHED_MILLIS = 30_000 * Build.HW_TIMEOUT_MULTIPLIER;
|
||||
|
||||
// Settings override tracking for this instance
|
||||
private String mSettingsKey;
|
||||
private SettingsObserver mSettingsObserver;
|
||||
@@ -128,7 +163,7 @@ public class BroadcastConstants {
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
updateConstants();
|
||||
updateSettingsConstants();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,11 +183,15 @@ public class BroadcastConstants {
|
||||
mSettingsObserver = new SettingsObserver(handler);
|
||||
mResolver.registerContentObserver(Settings.Global.getUriFor(mSettingsKey),
|
||||
false, mSettingsObserver);
|
||||
updateSettingsConstants();
|
||||
|
||||
updateConstants();
|
||||
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
new HandlerExecutor(handler), this::updateDeviceConfigConstants);
|
||||
updateDeviceConfigConstants(
|
||||
DeviceConfig.getProperties(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER));
|
||||
}
|
||||
|
||||
private void updateConstants() {
|
||||
private void updateSettingsConstants() {
|
||||
synchronized (mParser) {
|
||||
try {
|
||||
mParser.setString(Settings.Global.getString(mResolver, mSettingsKey));
|
||||
@@ -173,6 +212,17 @@ public class BroadcastConstants {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateDeviceConfigConstants(@NonNull DeviceConfig.Properties properties) {
|
||||
MAX_RUNNING_PROCESS_QUEUES = properties.getInt("bcast_max_running_process_queues",
|
||||
DEFAULT_MAX_RUNNING_PROCESS_QUEUES);
|
||||
MAX_RUNNING_ACTIVE_BROADCASTS = properties.getInt("bcast_max_running_active_broadcasts",
|
||||
DEFAULT_MAX_RUNNING_ACTIVE_BROADCASTS);
|
||||
DELAY_NORMAL_MILLIS = properties.getLong("bcast_delay_normal_millis",
|
||||
DEFAULT_DELAY_NORMAL_MILLIS);
|
||||
DELAY_CACHED_MILLIS = properties.getLong("bcast_delay_cached_millis",
|
||||
DEFAULT_DELAY_CACHED_MILLIS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard dumpsys support; invoked from BroadcastQueue dump
|
||||
*/
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.android.server.am.BroadcastRecord.DeliveryState;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
/**
|
||||
@@ -47,19 +48,7 @@ import java.util.function.BiPredicate;
|
||||
* dispatched.
|
||||
*/
|
||||
class BroadcastProcessQueue {
|
||||
/**
|
||||
* Default delay to apply to background broadcasts, giving a chance for
|
||||
* debouncing of rapidly changing events.
|
||||
*/
|
||||
// TODO: shift hard-coded defaults to BroadcastConstants
|
||||
private static final long DELAY_DEFAULT_MILLIS = 10_000;
|
||||
|
||||
/**
|
||||
* Default delay to apply to broadcasts targeting cached applications.
|
||||
*/
|
||||
// TODO: shift hard-coded defaults to BroadcastConstants
|
||||
private static final long DELAY_CACHED_MILLIS = 30_000;
|
||||
|
||||
final @NonNull BroadcastConstants constants;
|
||||
final @NonNull String processName;
|
||||
final int uid;
|
||||
|
||||
@@ -129,8 +118,10 @@ class BroadcastProcessQueue {
|
||||
|
||||
private boolean mProcessCached;
|
||||
|
||||
public BroadcastProcessQueue(@NonNull String processName, int uid) {
|
||||
this.processName = processName;
|
||||
public BroadcastProcessQueue(@NonNull BroadcastConstants constants,
|
||||
@NonNull String processName, int uid) {
|
||||
this.constants = Objects.requireNonNull(constants);
|
||||
this.processName = Objects.requireNonNull(processName);
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
@@ -401,9 +392,9 @@ class BroadcastProcessQueue {
|
||||
} else if (mCountAlarm > 0) {
|
||||
mRunnableAt = runnableAt;
|
||||
} else if (mProcessCached) {
|
||||
mRunnableAt = runnableAt + DELAY_CACHED_MILLIS;
|
||||
mRunnableAt = runnableAt + constants.DELAY_CACHED_MILLIS;
|
||||
} else {
|
||||
mRunnableAt = runnableAt + DELAY_DEFAULT_MILLIS;
|
||||
mRunnableAt = runnableAt + constants.DELAY_NORMAL_MILLIS;
|
||||
}
|
||||
} else {
|
||||
mRunnableAt = Long.MAX_VALUE;
|
||||
|
||||
@@ -111,9 +111,17 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
BroadcastConstants fgConstants, BroadcastConstants bgConstants,
|
||||
BroadcastSkipPolicy skipPolicy, BroadcastHistory history) {
|
||||
super(service, handler, "modern", skipPolicy, history);
|
||||
|
||||
// For the moment, read agnostic constants from foreground
|
||||
mConstants = Objects.requireNonNull(fgConstants);
|
||||
mFgConstants = Objects.requireNonNull(fgConstants);
|
||||
mBgConstants = Objects.requireNonNull(bgConstants);
|
||||
|
||||
mLocalHandler = new Handler(handler.getLooper(), mLocalCallback);
|
||||
|
||||
// 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];
|
||||
}
|
||||
|
||||
// TODO: add support for replacing pending broadcasts
|
||||
@@ -124,21 +132,6 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
// TODO: pause queues when background services are running
|
||||
// TODO: pause queues when processes are frozen
|
||||
|
||||
/**
|
||||
* Maximum number of process queues to dispatch broadcasts to
|
||||
* simultaneously.
|
||||
*/
|
||||
// TODO: shift hard-coded defaults to BroadcastConstants
|
||||
private static final int MAX_RUNNING_PROCESS_QUEUES = 4;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
// TODO: shift hard-coded defaults to BroadcastConstants
|
||||
private static final int MAX_RUNNING_ACTIVE_BROADCASTS = 16;
|
||||
|
||||
/**
|
||||
* Map from UID to per-process broadcast queues. If a UID hosts more than
|
||||
* one process, each additional process is stored as a linked list using
|
||||
@@ -168,8 +161,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
* @see #getRunningIndexOf
|
||||
*/
|
||||
@GuardedBy("mService")
|
||||
private final BroadcastProcessQueue[] mRunning =
|
||||
new BroadcastProcessQueue[MAX_RUNNING_PROCESS_QUEUES];
|
||||
private final BroadcastProcessQueue[] mRunning;
|
||||
|
||||
/**
|
||||
* Single queue which is "running" but is awaiting a cold start to be
|
||||
@@ -185,6 +177,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
@GuardedBy("mService")
|
||||
private final ArrayList<CountDownLatch> mWaitingForIdle = new ArrayList<>();
|
||||
|
||||
private final BroadcastConstants mConstants;
|
||||
private final BroadcastConstants mFgConstants;
|
||||
private final BroadcastConstants mBgConstants;
|
||||
|
||||
@@ -299,12 +292,12 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
* Consider updating the list of "running" queues.
|
||||
* <p>
|
||||
* This method can promote "runnable" queues to become "running", subject to
|
||||
* a maximum of {@link #MAX_RUNNING_PROCESS_QUEUES} warm processes and only
|
||||
* one pending cold-start.
|
||||
* a maximum of {@link BroadcastConstants#MAX_RUNNING_PROCESS_QUEUES} warm
|
||||
* processes and only one pending cold-start.
|
||||
*/
|
||||
@GuardedBy("mService")
|
||||
private void updateRunningList() {
|
||||
int avail = MAX_RUNNING_PROCESS_QUEUES - getRunningSize();
|
||||
int avail = mRunning.length - getRunningSize();
|
||||
if (avail == 0) return;
|
||||
|
||||
final int cookie = traceBegin(TAG, "updateRunningList");
|
||||
@@ -714,7 +707,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
// Even if we have more broadcasts, if we've made reasonable progress
|
||||
// and someone else is waiting, retire ourselves to avoid starvation
|
||||
final boolean shouldRetire = (mRunnableHead != null)
|
||||
&& (queue.getActiveCountSinceIdle() > MAX_RUNNING_ACTIVE_BROADCASTS);
|
||||
&& (queue.getActiveCountSinceIdle() > mConstants.MAX_RUNNING_ACTIVE_BROADCASTS);
|
||||
|
||||
if (queue.isRunnable() && queue.isProcessWarm() && !shouldRetire) {
|
||||
// We're on a roll; move onto the next broadcast for this process
|
||||
@@ -1034,7 +1027,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
leaf = leaf.processNameNext;
|
||||
}
|
||||
|
||||
BroadcastProcessQueue created = new BroadcastProcessQueue(processName, uid);
|
||||
BroadcastProcessQueue created = new BroadcastProcessQueue(mConstants, processName, uid);
|
||||
created.app = mService.getProcessRecordLocked(processName, uid);
|
||||
|
||||
if (leaf == null) {
|
||||
|
||||
@@ -65,6 +65,8 @@ public class BroadcastQueueModernImplTest {
|
||||
@Mock BroadcastProcessQueue mQueue4;
|
||||
|
||||
HandlerThread mHandlerThread;
|
||||
|
||||
BroadcastConstants mConstants;
|
||||
BroadcastQueueModernImpl mImpl;
|
||||
|
||||
BroadcastProcessQueue mHead;
|
||||
@@ -75,9 +77,10 @@ public class BroadcastQueueModernImplTest {
|
||||
|
||||
mHandlerThread = new HandlerThread(getClass().getSimpleName());
|
||||
mHandlerThread.start();
|
||||
|
||||
mConstants = new BroadcastConstants(Settings.Global.BROADCAST_FG_CONSTANTS);
|
||||
mImpl = new BroadcastQueueModernImpl(mAms, mHandlerThread.getThreadHandler(),
|
||||
new BroadcastConstants(Settings.Global.BROADCAST_FG_CONSTANTS),
|
||||
new BroadcastConstants(Settings.Global.BROADCAST_BG_CONSTANTS));
|
||||
mConstants, mConstants);
|
||||
|
||||
doReturn(1L).when(mQueue1).getRunnableAt();
|
||||
doReturn(2L).when(mQueue2).getRunnableAt();
|
||||
@@ -240,8 +243,8 @@ public class BroadcastQueueModernImplTest {
|
||||
*/
|
||||
@Test
|
||||
public void testRunnableAt_Empty() {
|
||||
BroadcastProcessQueue queue = new BroadcastProcessQueue(PACKAGE_GREEN,
|
||||
getUidForPackage(PACKAGE_GREEN));
|
||||
BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants,
|
||||
PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN));
|
||||
assertFalse(queue.isRunnable());
|
||||
assertEquals(Long.MAX_VALUE, queue.getRunnableAt());
|
||||
}
|
||||
@@ -252,8 +255,8 @@ public class BroadcastQueueModernImplTest {
|
||||
*/
|
||||
@Test
|
||||
public void testRunnableAt_Normal() {
|
||||
BroadcastProcessQueue queue = new BroadcastProcessQueue(PACKAGE_GREEN,
|
||||
getUidForPackage(PACKAGE_GREEN));
|
||||
BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants,
|
||||
PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN));
|
||||
|
||||
final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
|
||||
final BroadcastRecord airplaneRecord = makeBroadcastRecord(airplane);
|
||||
@@ -272,8 +275,8 @@ public class BroadcastQueueModernImplTest {
|
||||
*/
|
||||
@Test
|
||||
public void testRunnableAt_Foreground() {
|
||||
BroadcastProcessQueue queue = new BroadcastProcessQueue(PACKAGE_GREEN,
|
||||
getUidForPackage(PACKAGE_GREEN));
|
||||
BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants,
|
||||
PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN));
|
||||
|
||||
final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
|
||||
airplane.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
|
||||
|
||||
Reference in New Issue
Block a user