diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index a580f985dd137..3b299a201b7ac 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -192,6 +192,7 @@ import java.util.Comparator; import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Predicate; public final class ActiveServices { @@ -222,6 +223,11 @@ public final class ActiveServices { | ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE | ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION; + // Keep track of number of foreground services and number of apps that have foreground + // services in the device. This field is made to be directly accessed without holding AMS lock. + static final AtomicReference> sNumForegroundServices = + new AtomicReference(new Pair<>(0, 0)); + // Foreground service is stopped for unknown reason. static final int FGS_STOP_REASON_UNKNOWN = 0; // Foreground service is stopped by app calling Service.stopForeground(). @@ -456,6 +462,7 @@ public final class ActiveServices { final ArrayList mStartingBackground = new ArrayList<>(); final ArrayMap mActiveForegroundApps = new ArrayMap<>(); + boolean mActiveForegroundAppsChanged; static final int MSG_BG_START_TIMEOUT = 1; @@ -2027,6 +2034,7 @@ public final class ActiveServices { logFGSStateChangeLocked(r, FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER, 0, FGS_STOP_REASON_UNKNOWN); + updateNumForegroundServicesLocked(); } // Even if the service is already a FGS, we need to update the notification, // so we need to call it again. @@ -2118,6 +2126,7 @@ public final class ActiveServices { mAm.updateLruProcessLocked(r.app, false, null); updateServiceForegroundLocked(r.app.mServices, true); } + updateNumForegroundServicesLocked(); } } } @@ -4836,6 +4845,7 @@ public final class ActiveServices { } smap.ensureNotStartingBackgroundLocked(r); + updateNumForegroundServicesLocked(); } private void dropFgsNotificationStateLocked(ServiceRecord r) { @@ -7040,6 +7050,10 @@ public final class ActiveServices { fgsStopReasonToString(fgsStopReason)); } + private void updateNumForegroundServicesLocked() { + sNumForegroundServices.set(mAm.mProcessList.getNumForegroundServices()); + } + boolean canAllowWhileInUsePermissionInFgsLocked(int callingPid, int callingUid, String callingPackage) { return shouldAllowFgsWhileInUsePermissionLocked(callingPackage, callingPid, callingUid, diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index ccbca76d18683..a7048a7e27bb9 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -814,12 +814,14 @@ public final class ProcessList { < LmkdStatsReporter.KILL_OCCURRED_MSG_SIZE) { return false; } - Pair temp = getNumForegroundServices(); - final int totalForegroundServices = temp.first; - final int procsWithForegroundServices = temp.second; + // Note: directly access + // ActiveServices.sNumForegroundServices, do not try to + // hold AMS lock here, otherwise it is a potential deadlock. + Pair foregroundServices = + ActiveServices.sNumForegroundServices.get(); LmkdStatsReporter.logKillOccurred(inputData, - totalForegroundServices, - procsWithForegroundServices); + foregroundServices.first, + foregroundServices.second); return true; case LMK_STATE_CHANGED: if (receivedLen