From 7e6ce392cf8bbc963ccf05341ad92df680ebe203 Mon Sep 17 00:00:00 2001 From: Sudheer Shanka Date: Wed, 5 Apr 2023 11:10:31 -0700 Subject: [PATCH] Promote an app to RECEIVER only when handling a broadcast. AMS.isReceivingBroadcastLocked() uses getPreferredSchedulingGroupLocked() to check if a process is handling a broadcast and which scheduling group the process should belong to. With the current implementation, even if an app is not handling a broadcast, it will be promoted to the RECEIVER state as long as it has some broadcasts waiting for it, which is not necessary and prevents some broadcast delays that we added for cached processes from being effective. Bug: 268082390 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: I6e1df941b6e9715add1727fc5cfe0234c5a5a7f6 --- .../server/am/BroadcastProcessQueue.java | 8 ++-- .../am/BroadcastQueueModernImplTest.java | 41 +++++++++++++++++-- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java index dbb351b23c85f..bfc8251d97bbe 100644 --- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java +++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java @@ -441,17 +441,17 @@ class BroadcastProcessQueue { } public int getPreferredSchedulingGroupLocked() { - if (mCountForeground > mCountForegroundDeferred) { + if (!isActive()) { + return ProcessList.SCHED_GROUP_UNDEFINED; + } else if (mCountForeground > mCountForegroundDeferred) { // We have a foreground broadcast somewhere down the queue, so // boost priority until we drain them all return ProcessList.SCHED_GROUP_DEFAULT; } else if ((mActive != null) && mActive.isForeground()) { // We have a foreground broadcast right now, so boost priority return ProcessList.SCHED_GROUP_DEFAULT; - } else if (!isIdle()) { - return ProcessList.SCHED_GROUP_BACKGROUND; } else { - return ProcessList.SCHED_GROUP_UNDEFINED; + return ProcessList.SCHED_GROUP_BACKGROUND; } } 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 318067ee8681b..8211d6fc03a23 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java @@ -406,7 +406,7 @@ public final class BroadcastQueueModernImplTest { assertThat(cachedRunnableAt).isGreaterThan(notCachedRunnableAt); assertTrue(queue.isRunnable()); assertEquals(BroadcastProcessQueue.REASON_CACHED, queue.getRunnableAtReason()); - assertEquals(ProcessList.SCHED_GROUP_BACKGROUND, queue.getPreferredSchedulingGroupLocked()); + assertEquals(ProcessList.SCHED_GROUP_UNDEFINED, queue.getPreferredSchedulingGroupLocked()); } /** @@ -434,13 +434,13 @@ public final class BroadcastQueueModernImplTest { queue.setProcessAndUidCached(null, false); assertTrue(queue.isRunnable()); assertThat(queue.getRunnableAt()).isAtMost(airplaneRecord.enqueueClockTime); - assertEquals(ProcessList.SCHED_GROUP_DEFAULT, queue.getPreferredSchedulingGroupLocked()); + assertEquals(ProcessList.SCHED_GROUP_UNDEFINED, queue.getPreferredSchedulingGroupLocked()); assertEquals(queue.peekNextBroadcastRecord(), airplaneRecord); queue.setProcessAndUidCached(null, true); assertTrue(queue.isRunnable()); assertThat(queue.getRunnableAt()).isAtMost(airplaneRecord.enqueueClockTime); - assertEquals(ProcessList.SCHED_GROUP_DEFAULT, queue.getPreferredSchedulingGroupLocked()); + assertEquals(ProcessList.SCHED_GROUP_UNDEFINED, queue.getPreferredSchedulingGroupLocked()); assertEquals(queue.peekNextBroadcastRecord(), airplaneRecord); } @@ -1154,6 +1154,41 @@ public final class BroadcastQueueModernImplTest { times(1)); } + @Test + public void testGetPreferredSchedulingGroup() throws Exception { + final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, + PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); + + assertEquals(ProcessList.SCHED_GROUP_UNDEFINED, queue.getPreferredSchedulingGroupLocked()); + + final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK) + .addFlags(Intent.FLAG_RECEIVER_FOREGROUND); + queue.enqueueOrReplaceBroadcast(makeBroadcastRecord(timeTick, + List.of(makeMockRegisteredReceiver())), 0, false); + assertEquals(ProcessList.SCHED_GROUP_UNDEFINED, queue.getPreferredSchedulingGroupLocked()); + + // Make the foreground broadcast as active. + queue.makeActiveNextPending(); + assertEquals(ProcessList.SCHED_GROUP_DEFAULT, queue.getPreferredSchedulingGroupLocked()); + + queue.makeActiveIdle(); + assertEquals(ProcessList.SCHED_GROUP_UNDEFINED, queue.getPreferredSchedulingGroupLocked()); + + final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); + queue.enqueueOrReplaceBroadcast(makeBroadcastRecord(airplane, + List.of(makeMockRegisteredReceiver())), 0, false); + + // Make the background broadcast as active. + queue.makeActiveNextPending(); + assertEquals(ProcessList.SCHED_GROUP_BACKGROUND, queue.getPreferredSchedulingGroupLocked()); + + queue.enqueueOrReplaceBroadcast(makeBroadcastRecord(timeTick, + List.of(makeMockRegisteredReceiver())), 0, false); + // Even though the active broadcast is not a foreground one, scheduling group will be + // DEFAULT since there is a foreground broadcast waiting to be delivered. + assertEquals(ProcessList.SCHED_GROUP_DEFAULT, queue.getPreferredSchedulingGroupLocked()); + } + private Intent createPackageChangedIntent(int uid, List componentNameList) { final Intent packageChangedIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED); packageChangedIntent.putExtra(Intent.EXTRA_UID, uid);