From 9621b244f9a77efbb9c55e729f96bc1c4c25b86c Mon Sep 17 00:00:00 2001 From: Sudheer Shanka Date: Fri, 17 Mar 2023 16:15:30 -0700 Subject: [PATCH] Verify prioritized receivers are WAI with deferrable broadcasts. Bug: 272149552 Test: atest services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java Test: atest services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java Change-Id: Ic1bab3909750ca4b3add06648583cbe9f241025d --- .../server/am/BroadcastProcessQueue.java | 3 +- .../android/server/am/BroadcastQueueTest.java | 73 +++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java index 1f6573076d512..0cdd4e9041e96 100644 --- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java +++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java @@ -399,7 +399,8 @@ class BroadcastProcessQueue { * Update if this process is in the "cached" state, typically signaling that * broadcast dispatch should be paused or delayed. */ - public void setProcessCached(boolean cached) { + @VisibleForTesting + void setProcessCached(boolean cached) { if (mProcessCached != cached) { mProcessCached = cached; invalidateRunnableAt(); 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 2d4f5ca2f71da..bca39ae648239 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java @@ -1645,6 +1645,79 @@ public class BroadcastQueueTest { Set.of(mScheduledBroadcasts.remove(0))); } + /** + * Verify prioritized receivers work as expected with deferrable broadcast - broadcast to + * app in cached state should be deferred and the rest should be delivered as per the priority + * order. + */ + @Test + public void testPrioritized_withDeferrableBroadcasts() throws Exception { + // Legacy stack doesn't support deferral + Assume.assumeTrue(mImpl == Impl.MODERN); + + final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED); + final ProcessRecord receiverGreenApp = makeActiveProcessRecord(PACKAGE_GREEN); + final ProcessRecord receiverBlueApp = makeActiveProcessRecord(PACKAGE_BLUE); + final ProcessRecord receiverYellowApp = makeActiveProcessRecord(PACKAGE_YELLOW); + final ProcessRecord receiverOrangeApp = makeActiveProcessRecord(PACKAGE_ORANGE); + + receiverGreenApp.setCached(true); + receiverBlueApp.setCached(true); + + final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); + final BroadcastOptions opts = BroadcastOptions.makeBasic() + .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE); + final List receivers = List.of( + makeRegisteredReceiver(callerApp, 10), + makeRegisteredReceiver(receiverGreenApp, 9), + makeRegisteredReceiver(receiverBlueApp, 8), + makeRegisteredReceiver(receiverYellowApp, 8), + makeRegisteredReceiver(receiverOrangeApp, 7) + ); + enqueueBroadcast(makeBroadcastRecord(timeTick, callerApp, opts, receivers)); + waitForIdle(); + + // Green ignored since it's in cached state + verifyScheduleRegisteredReceiver(never(), receiverGreenApp, timeTick); + // Blue ignored since it's in cached state + verifyScheduleRegisteredReceiver(never(), receiverBlueApp, timeTick); + + final IApplicationThread redThread = mAms.getProcessRecordLocked(PACKAGE_RED, + getUidForPackage(PACKAGE_RED)).getThread(); + final IApplicationThread yellowThread = mAms.getProcessRecordLocked(PACKAGE_YELLOW, + getUidForPackage(PACKAGE_YELLOW)).getThread(); + final IApplicationThread orangeThread = mAms.getProcessRecordLocked(PACKAGE_ORANGE, + getUidForPackage(PACKAGE_ORANGE)).getThread(); + + // Verify apps that are not in cached state will receive the broadcast in the order + // we expect. + final InOrder inOrder = inOrder(redThread, yellowThread, orangeThread); + inOrder.verify(redThread).scheduleRegisteredReceiver( + any(), argThat(filterEqualsIgnoringComponent(timeTick)), + anyInt(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean(), + eq(UserHandle.USER_SYSTEM), anyInt(), anyInt(), any()); + inOrder.verify(yellowThread).scheduleRegisteredReceiver( + any(), argThat(filterEqualsIgnoringComponent(timeTick)), + anyInt(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean(), + eq(UserHandle.USER_SYSTEM), anyInt(), anyInt(), any()); + inOrder.verify(orangeThread).scheduleRegisteredReceiver( + any(), argThat(filterEqualsIgnoringComponent(timeTick)), + anyInt(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean(), + 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); + } + /** * Verify that we handle replacing a pending broadcast. */