summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/am/BroadcastProcessQueue.java23
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueueModernImpl.java44
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java14
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java13
4 files changed, 61 insertions, 33 deletions
diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
index 48ab96cee562..d5b8bb44e853 100644
--- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
@@ -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) {
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index 40ae6e211235..b18997a8d21f 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -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,11 +1515,20 @@ 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);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
index 41a5ddb60a7f..0c512d2a0bd3 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
@@ -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),
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
index 3b964bcb78ac..cbc259797c12 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
@@ -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);