Merge "Store "cached" state separate from ProcessRecord." into udc-dev

This commit is contained in:
Jeff Sharkey
2023-04-04 00:08:59 +00:00
committed by Android (Google) Code Review
4 changed files with 61 additions and 33 deletions

View File

@@ -188,7 +188,7 @@ class BroadcastProcessQueue {
private @Reason int mRunnableAtReason = REASON_EMPTY;
private boolean mRunnableAtInvalidated;
private boolean mProcessCached;
private boolean mUidCached;
private boolean mProcessInstrumented;
private boolean mProcessPersistent;
@@ -382,14 +382,14 @@ class BroadcastProcessQueue {
/**
* Update the actively running "warm" process for this process.
*/
public void setProcess(@Nullable ProcessRecord app) {
public void setProcessAndUidCached(@Nullable ProcessRecord app, boolean uidCached) {
this.app = app;
if (app != null) {
setProcessCached(app.isCached());
setUidCached(uidCached);
setProcessInstrumented(app.getActiveInstrumentation() != null);
setProcessPersistent(app.isPersistent());
} else {
setProcessCached(false);
setUidCached(uidCached);
setProcessInstrumented(false);
setProcessPersistent(false);
}
@@ -403,10 +403,9 @@ class BroadcastProcessQueue {
* Update if this process is in the "cached" state, typically signaling that
* broadcast dispatch should be paused or delayed.
*/
@VisibleForTesting
void setProcessCached(boolean cached) {
if (mProcessCached != cached) {
mProcessCached = cached;
private void setUidCached(boolean uidCached) {
if (mUidCached != uidCached) {
mUidCached = uidCached;
invalidateRunnableAt();
}
}
@@ -416,7 +415,7 @@ class BroadcastProcessQueue {
* signaling that broadcast dispatch should bypass all pauses or delays, to
* avoid holding up test suites.
*/
public void setProcessInstrumented(boolean instrumented) {
private void setProcessInstrumented(boolean instrumented) {
if (mProcessInstrumented != instrumented) {
mProcessInstrumented = instrumented;
invalidateRunnableAt();
@@ -427,7 +426,7 @@ class BroadcastProcessQueue {
* Update if this process is in the "persistent" state, which signals broadcast dispatch should
* bypass all pauses or delays to prevent the system from becoming out of sync with itself.
*/
public void setProcessPersistent(boolean persistent) {
private void setProcessPersistent(boolean persistent) {
if (mProcessPersistent != persistent) {
mProcessPersistent = persistent;
invalidateRunnableAt();
@@ -986,7 +985,7 @@ class BroadcastProcessQueue {
} else if (mProcessPersistent) {
mRunnableAt = runnableAt;
mRunnableAtReason = REASON_PERSISTENT;
} else if (mProcessCached) {
} else if (mUidCached) {
if (r.deferUntilActive) {
// All enqueued broadcasts are deferrable, defer
if (mCountDeferred == mCountEnqueued) {
@@ -1195,7 +1194,7 @@ class BroadcastProcessQueue {
@NeverCompile
private void dumpProcessState(@NonNull IndentingPrintWriter pw) {
final StringBuilder sb = new StringBuilder();
if (mProcessCached) {
if (mUidCached) {
sb.append("CACHED");
}
if (mProcessInstrumented) {

View File

@@ -72,6 +72,7 @@ import android.util.MathUtils;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
@@ -209,6 +210,16 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
private final AtomicReference<ArraySet<BroadcastRecord>> mReplacedBroadcastsCache =
new AtomicReference<>();
/**
* Map from UID to its last known "cached" state.
* <p>
* We manually maintain this data structure since the lifecycle of
* {@link ProcessRecord} and {@link BroadcastProcessQueue} can be
* mismatched.
*/
@GuardedBy("mService")
private final SparseBooleanArray mUidCached = new SparseBooleanArray();
private final BroadcastConstants mConstants;
private final BroadcastConstants mFgConstants;
private final BroadcastConstants mBgConstants;
@@ -485,7 +496,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
// relevant per-process queue
final BroadcastProcessQueue queue = getProcessQueue(app);
if (queue != null) {
queue.setProcess(app);
setQueueProcess(queue, app);
}
boolean didSomething = false;
@@ -526,7 +537,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
// relevant per-process queue
final BroadcastProcessQueue queue = getProcessQueue(app);
if (queue != null) {
queue.setProcess(null);
setQueueProcess(queue, null);
}
if ((mRunningColdStart != null) && (mRunningColdStart == queue)) {
@@ -1332,11 +1343,17 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
@Override
public void onUidCachedChanged(int uid, boolean cached) {
synchronized (mService) {
if (cached) {
mUidCached.put(uid, true);
} else {
mUidCached.delete(uid);
}
BroadcastProcessQueue leaf = mProcessQueues.get(uid);
while (leaf != null) {
// Update internal state by refreshing values previously
// read from any known running process
leaf.setProcess(leaf.app);
setQueueProcess(leaf, leaf.app);
updateQueueDeferred(leaf);
updateRunnableList(leaf);
leaf = leaf.processNameNext;
@@ -1498,10 +1515,19 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
private void updateWarmProcess(@NonNull BroadcastProcessQueue queue) {
if (!queue.isProcessWarm()) {
queue.setProcess(mService.getProcessRecordLocked(queue.processName, queue.uid));
setQueueProcess(queue, mService.getProcessRecordLocked(queue.processName, queue.uid));
}
}
/**
* Update the {@link ProcessRecord} associated with the given
* {@link BroadcastProcessQueue}.
*/
private void setQueueProcess(@NonNull BroadcastProcessQueue queue,
@Nullable ProcessRecord app) {
queue.setProcessAndUidCached(app, mUidCached.get(queue.uid, false));
}
/**
* Inform other parts of OS that the given broadcast queue has started
* running, typically for internal bookkeeping.
@@ -1692,7 +1718,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
}
BroadcastProcessQueue created = new BroadcastProcessQueue(mConstants, processName, uid);
created.setProcess(mService.getProcessRecordLocked(processName, uid));
setQueueProcess(created, mService.getProcessRecordLocked(processName, uid));
if (leaf == null) {
mProcessQueues.put(uid, created);
@@ -1815,12 +1841,18 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
ipw.decreaseIndent();
ipw.println();
ipw.println(" Broadcasts with ignored delivery group policies:");
ipw.println("Broadcasts with ignored delivery group policies:");
ipw.increaseIndent();
mService.dumpDeliveryGroupPolicyIgnoredActions(ipw);
ipw.decreaseIndent();
ipw.println();
ipw.println("Cached UIDs:");
ipw.increaseIndent();
ipw.println(mUidCached.toString());
ipw.decreaseIndent();
ipw.println();
if (dumpConstants) {
mConstants.dump(ipw);
}

View File

@@ -372,9 +372,9 @@ public final class BroadcastQueueModernImplTest {
List.of(makeMockRegisteredReceiver()), false);
queue.enqueueOrReplaceBroadcast(airplaneRecord, 0, false);
queue.setProcessCached(false);
queue.setProcessAndUidCached(null, false);
final long notCachedRunnableAt = queue.getRunnableAt();
queue.setProcessCached(true);
queue.setProcessAndUidCached(null, true);
final long cachedRunnableAt = queue.getRunnableAt();
assertThat(cachedRunnableAt).isGreaterThan(notCachedRunnableAt);
assertFalse(queue.isRunnable());
@@ -399,9 +399,9 @@ public final class BroadcastQueueModernImplTest {
List.of(makeMockRegisteredReceiver()), false);
queue.enqueueOrReplaceBroadcast(airplaneRecord, 0, false);
queue.setProcessCached(false);
queue.setProcessAndUidCached(null, false);
final long notCachedRunnableAt = queue.getRunnableAt();
queue.setProcessCached(true);
queue.setProcessAndUidCached(null, true);
final long cachedRunnableAt = queue.getRunnableAt();
assertThat(cachedRunnableAt).isGreaterThan(notCachedRunnableAt);
assertTrue(queue.isRunnable());
@@ -431,13 +431,13 @@ public final class BroadcastQueueModernImplTest {
// verify that:
// (a) the queue is immediately runnable by existence of a fg-priority broadcast
// (b) the next one up is the fg-priority broadcast despite its later enqueue time
queue.setProcessCached(false);
queue.setProcessAndUidCached(null, false);
assertTrue(queue.isRunnable());
assertThat(queue.getRunnableAt()).isAtMost(airplaneRecord.enqueueClockTime);
assertEquals(ProcessList.SCHED_GROUP_DEFAULT, queue.getPreferredSchedulingGroupLocked());
assertEquals(queue.peekNextBroadcastRecord(), airplaneRecord);
queue.setProcessCached(true);
queue.setProcessAndUidCached(null, true);
assertTrue(queue.isRunnable());
assertThat(queue.getRunnableAt()).isAtMost(airplaneRecord.enqueueClockTime);
assertEquals(ProcessList.SCHED_GROUP_DEFAULT, queue.getPreferredSchedulingGroupLocked());
@@ -500,7 +500,7 @@ public final class BroadcastQueueModernImplTest {
private void doRunnableAt_Cached(BroadcastRecord testRecord, int testRunnableAtReason) {
final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants,
PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN));
queue.setProcessCached(true);
queue.setProcessAndUidCached(null, true);
final BroadcastRecord lazyRecord = makeBroadcastRecord(
new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED),

View File

@@ -1659,8 +1659,8 @@ public class BroadcastQueueTest {
final ProcessRecord receiverYellowApp = makeActiveProcessRecord(PACKAGE_YELLOW);
final ProcessRecord receiverOrangeApp = makeActiveProcessRecord(PACKAGE_ORANGE);
receiverGreenApp.setCached(true);
receiverBlueApp.setCached(true);
mUidObserver.onUidCachedChanged(getUidForPackage(PACKAGE_GREEN), true);
mUidObserver.onUidCachedChanged(getUidForPackage(PACKAGE_BLUE), true);
final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK);
final BroadcastOptions opts = BroadcastOptions.makeBasic()
@@ -1704,13 +1704,11 @@ public class BroadcastQueueTest {
eq(UserHandle.USER_SYSTEM), anyInt(), anyInt(), any());
// Shift blue to be active and confirm that deferred broadcast is delivered
receiverBlueApp.setCached(false);
mUidObserver.onUidCachedChanged(getUidForPackage(PACKAGE_BLUE), false);
waitForIdle();
verifyScheduleRegisteredReceiver(times(1), receiverBlueApp, timeTick);
// Shift green to be active and confirm that deferred broadcast is delivered
receiverGreenApp.setCached(false);
mUidObserver.onUidCachedChanged(getUidForPackage(PACKAGE_GREEN), false);
waitForIdle();
verifyScheduleRegisteredReceiver(times(1), receiverGreenApp, timeTick);
@@ -2044,9 +2042,9 @@ public class BroadcastQueueTest {
final ProcessRecord receiverBlueApp = makeActiveProcessRecord(PACKAGE_BLUE);
final ProcessRecord receiverYellowApp = makeActiveProcessRecord(PACKAGE_YELLOW);
receiverGreenApp.setCached(true);
receiverBlueApp.setCached(true);
receiverYellowApp.setCached(false);
mUidObserver.onUidCachedChanged(getUidForPackage(PACKAGE_GREEN), true);
mUidObserver.onUidCachedChanged(getUidForPackage(PACKAGE_BLUE), true);
mUidObserver.onUidCachedChanged(getUidForPackage(PACKAGE_YELLOW), false);
final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
final BroadcastOptions opts = BroadcastOptions.makeBasic()
@@ -2069,7 +2067,6 @@ public class BroadcastQueueTest {
verifyScheduleRegisteredReceiver(times(1), receiverYellowApp, airplane);
// Shift green to be active and confirm that deferred broadcast is delivered
receiverGreenApp.setCached(false);
mUidObserver.onUidCachedChanged(getUidForPackage(PACKAGE_GREEN), false);
waitForIdle();
verifyScheduleRegisteredReceiver(times(1), receiverGreenApp, airplane);