diff options
| -rw-r--r-- | services/core/java/com/android/server/am/BroadcastProcessQueue.java | 7 | ||||
| -rw-r--r-- | services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java | 27 |
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); |