From 7800278203eae2e224f01579539498eb3df26413 Mon Sep 17 00:00:00 2001 From: Hui Yu Date: Fri, 15 Apr 2022 18:17:04 -0700 Subject: [PATCH] Deferred BOOT_COMPLETED broadcast does not mean queue is not idle. "adb shell am wait-for-broadcast-idle" calls BroadcastDispatcher's isEmpty() method, which return false if there is any deferred BOOT_COMPLETED broadcast. This is wrong because deferred BOOT_COMPLETED is deferred until first time the uid's process is started, this can be indefinitely. The fix is to create a BroadcastDispatcher.isIdle() method which does not count deferred BOOT_COMPLETED broadcast. Bug: 229426300 Test: restart device, unlock screen, issue "adb shell am wait-for-broadcast-idle" Change-Id: Ic660982e0d6daa0728b9eabfd4808f137677e037 --- .../server/am/ActivityManagerService.java | 2 +- .../android/server/am/BroadcastDispatcher.java | 18 +++++++++++++++--- .../com/android/server/am/BroadcastQueue.java | 2 +- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 35f7e064e3587..7cee203d0bf0c 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -15093,7 +15093,7 @@ public class ActivityManagerService extends IActivityManager.Stub @GuardedBy("this") final boolean canGcNowLocked() { for (BroadcastQueue q : mBroadcastQueues) { - if (!q.mParallelBroadcasts.isEmpty() || !q.mDispatcher.isEmpty()) { + if (!q.mParallelBroadcasts.isEmpty() || !q.mDispatcher.isIdle()) { return false; } } diff --git a/services/core/java/com/android/server/am/BroadcastDispatcher.java b/services/core/java/com/android/server/am/BroadcastDispatcher.java index 872531a47bc94..49477ad75302a 100644 --- a/services/core/java/com/android/server/am/BroadcastDispatcher.java +++ b/services/core/java/com/android/server/am/BroadcastDispatcher.java @@ -511,13 +511,25 @@ public class BroadcastDispatcher { * Standard contents-are-empty check */ public boolean isEmpty() { + synchronized (mLock) { + return isIdle() + && getBootCompletedBroadcastsUidsSize(Intent.ACTION_LOCKED_BOOT_COMPLETED) == 0 + && getBootCompletedBroadcastsUidsSize(Intent.ACTION_BOOT_COMPLETED) == 0; + } + } + + /** + * Have less check than {@link #isEmpty()}. + * The dispatcher is considered as idle even with deferred LOCKED_BOOT_COMPLETED/BOOT_COMPLETED + * broadcasts because those can be deferred until the first time the uid's process is started. + * @return + */ + public boolean isIdle() { synchronized (mLock) { return mCurrentBroadcast == null && mOrderedBroadcasts.isEmpty() && isDeferralsListEmpty(mDeferredBroadcasts) - && isDeferralsListEmpty(mAlarmBroadcasts) - && getBootCompletedBroadcastsUidsSize(Intent.ACTION_LOCKED_BOOT_COMPLETED) == 0 - && getBootCompletedBroadcastsUidsSize(Intent.ACTION_BOOT_COMPLETED) == 0; + && isDeferralsListEmpty(mAlarmBroadcasts); } } diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 8a7fece5905c3..3ba99a8ee42c8 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -2218,7 +2218,7 @@ public final class BroadcastQueue { } boolean isIdle() { - return mParallelBroadcasts.isEmpty() && mDispatcher.isEmpty() + return mParallelBroadcasts.isEmpty() && mDispatcher.isIdle() && (mPendingBroadcast == null); }