summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/am/BroadcastProcessQueue.java7
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java27
2 files changed, 34 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
index e07c2bcaaaed..e41b6ae28e80 100644
--- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
@@ -350,6 +350,13 @@ class BroadcastProcessQueue {
final BroadcastRecord testRecord = (BroadcastRecord) args.arg1;
final int testRecordIndex = args.argi1;
final Object testReceiver = testRecord.receivers.get(testRecordIndex);
+ // If we come across the record that's being enqueued in the queue, then that means
+ // we already enqueued it for a receiver in this process and trying to insert a new
+ // one past this could create priority inversion in the queue, so bail out.
+ if (record == testRecord && record.blockedUntilBeyondCount[recordIndex]
+ > testRecord.blockedUntilBeyondCount[testRecordIndex]) {
+ break;
+ }
if ((record.callingUid == testRecord.callingUid)
&& (record.userId == testRecord.userId)
&& record.intent.filterEquals(testRecord.intent)
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 367e14b37180..1c8e9490435d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
@@ -2008,6 +2008,33 @@ public class BroadcastQueueTest {
}
@Test
+ public void testReplacePending_sameProcess_diffReceivers() throws Exception {
+ final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
+ final ProcessRecord receiverGreenApp = makeActiveProcessRecord(PACKAGE_GREEN);
+ final BroadcastFilter receiverGreenA = makeRegisteredReceiver(receiverGreenApp);
+ final BroadcastFilter receiverGreenB = makeRegisteredReceiver(receiverGreenApp);
+
+ final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED)
+ .addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+
+ enqueueBroadcast(makeBroadcastRecord(airplane, callerApp, List.of(
+ withPriority(receiverGreenA, 5))));
+ enqueueBroadcast(makeBroadcastRecord(airplane, callerApp, List.of(
+ withPriority(receiverGreenB, 10),
+ withPriority(receiverGreenA, 5))));
+
+ waitForIdle();
+ if (mImpl == Impl.DEFAULT) {
+ verifyScheduleRegisteredReceiver(times(2), receiverGreenApp, airplane);
+ } else {
+ // In the modern queue, we don't end up replacing the old broadcast to
+ // avoid creating priority inversion and so the process will receive
+ // both the old and new broadcasts.
+ verifyScheduleRegisteredReceiver(times(3), receiverGreenApp, airplane);
+ }
+ }
+
+ @Test
public void testIdleAndBarrier() throws Exception {
final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
final ProcessRecord receiverApp = makeActiveProcessRecord(PACKAGE_GREEN);