Loading services/core/java/com/android/server/am/ActiveServices.java +29 −3 Original line number Diff line number Diff line Loading @@ -131,6 +131,7 @@ import android.util.PrintWriterPrinter; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.SparseLongArray; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; import android.webkit.WebViewZygote; Loading Loading @@ -224,6 +225,11 @@ public final class ActiveServices { */ final ArrayList<ServiceRecord> mPendingFgsNotifications = new ArrayList<>(); /** * Uptime at which a given uid becomes eliglible again for FGS notification deferral */ final SparseLongArray mFgsDeferralEligible = new SparseLongArray(); /** * Map of services that are asked to be brought up (start/binding) but not ready to. */ Loading Loading @@ -1965,11 +1971,30 @@ public final class ActiveServices { } } private boolean withinFgsDeferRateLimit(final int uid, final long now) { final long eligible = mFgsDeferralEligible.get(uid, 0L); if (DEBUG_FOREGROUND_SERVICE) { if (now < eligible) { Slog.d(TAG_SERVICE, "FGS transition for uid " + uid + " within rate limit, showing immediately"); } } return now < eligible; } // TODO: remove as part of fixing b/173627642 @SuppressWarnings("AndroidFrameworkCompatChange") private void postFgsNotificationLocked(ServiceRecord r) { final int uid = r.appInfo.uid; final long now = SystemClock.uptimeMillis(); final boolean isLegacyApp = (r.appInfo.targetSdkVersion < Build.VERSION_CODES.S); boolean showNow = !mAm.mConstants.mFlagFgsNotificationDeferralEnabled; boolean showNow = withinFgsDeferRateLimit(uid, now); if (!showNow) { final boolean showLegacyNow = isLegacyApp && mAm.mConstants.mFlagFgsNotificationDeferralApiGated; showNow = !mAm.mConstants.mFlagFgsNotificationDeferralEnabled || showLegacyNow; } if (!showNow) { // Legacy apps' FGS notifications are not deferred unless the relevant // DeviceConfig element has been set Loading Loading @@ -2014,8 +2039,6 @@ public final class ActiveServices { } // schedule the actual notification post final int uid = r.appInfo.uid; final long now = SystemClock.uptimeMillis(); long when = now + mAm.mConstants.mFgsNotificationDeferralInterval; // If there are already deferred FGS notifications for this app, // inherit that deferred-show timestamp Loading @@ -2033,6 +2056,9 @@ public final class ActiveServices { when = Math.min(when, pending.fgDisplayTime); } } final long nextEligible = when + mAm.mConstants.mFgsNotificationDeferralExclusionTime; mFgsDeferralEligible.put(uid, nextEligible); r.fgDisplayTime = when; mPendingFgsNotifications.add(r); if (DEBUG_FOREGROUND_SERVICE) { Loading services/core/java/com/android/server/am/ActivityManagerConstants.java +23 −0 Original line number Diff line number Diff line Loading @@ -199,6 +199,15 @@ final class ActivityManagerConstants extends ContentObserver { private static final String KEY_DEFERRED_FGS_NOTIFICATION_INTERVAL = "deferred_fgs_notification_interval"; /** * Time in milliseconds; once an FGS notification for a given uid has been * deferred, no subsequent FGS notification from that uid will be deferred * until this amount of time has passed. Default is two minutes * (2 * 60 * 1000) unless overridden. */ private static final String KEY_DEFERRED_FGS_NOTIFICATION_EXCLUSION_TIME = "deferred_fgs_notification_exclusion_time"; // Maximum number of cached processes we will allow. public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES; Loading Loading @@ -398,6 +407,10 @@ final class ActivityManagerConstants extends ContentObserver { // the foreground state. volatile long mFgsNotificationDeferralInterval = 10_000; // Rate limit: minimum time after an app's FGS notification is deferred // before another FGS notifiction from that app can be deferred. volatile long mFgsNotificationDeferralExclusionTime = 2 * 60 * 1000L; /* * At boot time, broadcast receiver ACTION_BOOT_COMPLETED, ACTION_LOCKED_BOOT_COMPLETED and * ACTION_PRE_BOOT_COMPLETED are temp allowlisted to start FGS for a duration of time in Loading Loading @@ -580,6 +593,9 @@ final class ActivityManagerConstants extends ContentObserver { case KEY_DEFERRED_FGS_NOTIFICATION_INTERVAL: updateFgsNotificationDeferralInterval(); break; case KEY_DEFERRED_FGS_NOTIFICATION_EXCLUSION_TIME: updateFgsNotificationDeferralExclusionTime(); break; case KEY_OOMADJ_UPDATE_POLICY: updateOomAdjUpdatePolicy(); break; Loading Loading @@ -874,6 +890,13 @@ final class ActivityManagerConstants extends ContentObserver { /*default value*/ 10_000L); } private void updateFgsNotificationDeferralExclusionTime() { mFgsNotificationDeferralExclusionTime = DeviceConfig.getLong( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_DEFERRED_FGS_NOTIFICATION_EXCLUSION_TIME, /*default value*/ 2 * 60 * 1000L); } private void updateOomAdjUpdatePolicy() { OOMADJ_UPDATE_QUICK = DeviceConfig.getInt( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, Loading Loading
services/core/java/com/android/server/am/ActiveServices.java +29 −3 Original line number Diff line number Diff line Loading @@ -131,6 +131,7 @@ import android.util.PrintWriterPrinter; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.SparseLongArray; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; import android.webkit.WebViewZygote; Loading Loading @@ -224,6 +225,11 @@ public final class ActiveServices { */ final ArrayList<ServiceRecord> mPendingFgsNotifications = new ArrayList<>(); /** * Uptime at which a given uid becomes eliglible again for FGS notification deferral */ final SparseLongArray mFgsDeferralEligible = new SparseLongArray(); /** * Map of services that are asked to be brought up (start/binding) but not ready to. */ Loading Loading @@ -1965,11 +1971,30 @@ public final class ActiveServices { } } private boolean withinFgsDeferRateLimit(final int uid, final long now) { final long eligible = mFgsDeferralEligible.get(uid, 0L); if (DEBUG_FOREGROUND_SERVICE) { if (now < eligible) { Slog.d(TAG_SERVICE, "FGS transition for uid " + uid + " within rate limit, showing immediately"); } } return now < eligible; } // TODO: remove as part of fixing b/173627642 @SuppressWarnings("AndroidFrameworkCompatChange") private void postFgsNotificationLocked(ServiceRecord r) { final int uid = r.appInfo.uid; final long now = SystemClock.uptimeMillis(); final boolean isLegacyApp = (r.appInfo.targetSdkVersion < Build.VERSION_CODES.S); boolean showNow = !mAm.mConstants.mFlagFgsNotificationDeferralEnabled; boolean showNow = withinFgsDeferRateLimit(uid, now); if (!showNow) { final boolean showLegacyNow = isLegacyApp && mAm.mConstants.mFlagFgsNotificationDeferralApiGated; showNow = !mAm.mConstants.mFlagFgsNotificationDeferralEnabled || showLegacyNow; } if (!showNow) { // Legacy apps' FGS notifications are not deferred unless the relevant // DeviceConfig element has been set Loading Loading @@ -2014,8 +2039,6 @@ public final class ActiveServices { } // schedule the actual notification post final int uid = r.appInfo.uid; final long now = SystemClock.uptimeMillis(); long when = now + mAm.mConstants.mFgsNotificationDeferralInterval; // If there are already deferred FGS notifications for this app, // inherit that deferred-show timestamp Loading @@ -2033,6 +2056,9 @@ public final class ActiveServices { when = Math.min(when, pending.fgDisplayTime); } } final long nextEligible = when + mAm.mConstants.mFgsNotificationDeferralExclusionTime; mFgsDeferralEligible.put(uid, nextEligible); r.fgDisplayTime = when; mPendingFgsNotifications.add(r); if (DEBUG_FOREGROUND_SERVICE) { Loading
services/core/java/com/android/server/am/ActivityManagerConstants.java +23 −0 Original line number Diff line number Diff line Loading @@ -199,6 +199,15 @@ final class ActivityManagerConstants extends ContentObserver { private static final String KEY_DEFERRED_FGS_NOTIFICATION_INTERVAL = "deferred_fgs_notification_interval"; /** * Time in milliseconds; once an FGS notification for a given uid has been * deferred, no subsequent FGS notification from that uid will be deferred * until this amount of time has passed. Default is two minutes * (2 * 60 * 1000) unless overridden. */ private static final String KEY_DEFERRED_FGS_NOTIFICATION_EXCLUSION_TIME = "deferred_fgs_notification_exclusion_time"; // Maximum number of cached processes we will allow. public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES; Loading Loading @@ -398,6 +407,10 @@ final class ActivityManagerConstants extends ContentObserver { // the foreground state. volatile long mFgsNotificationDeferralInterval = 10_000; // Rate limit: minimum time after an app's FGS notification is deferred // before another FGS notifiction from that app can be deferred. volatile long mFgsNotificationDeferralExclusionTime = 2 * 60 * 1000L; /* * At boot time, broadcast receiver ACTION_BOOT_COMPLETED, ACTION_LOCKED_BOOT_COMPLETED and * ACTION_PRE_BOOT_COMPLETED are temp allowlisted to start FGS for a duration of time in Loading Loading @@ -580,6 +593,9 @@ final class ActivityManagerConstants extends ContentObserver { case KEY_DEFERRED_FGS_NOTIFICATION_INTERVAL: updateFgsNotificationDeferralInterval(); break; case KEY_DEFERRED_FGS_NOTIFICATION_EXCLUSION_TIME: updateFgsNotificationDeferralExclusionTime(); break; case KEY_OOMADJ_UPDATE_POLICY: updateOomAdjUpdatePolicy(); break; Loading Loading @@ -874,6 +890,13 @@ final class ActivityManagerConstants extends ContentObserver { /*default value*/ 10_000L); } private void updateFgsNotificationDeferralExclusionTime() { mFgsNotificationDeferralExclusionTime = DeviceConfig.getLong( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_DEFERRED_FGS_NOTIFICATION_EXCLUSION_TIME, /*default value*/ 2 * 60 * 1000L); } private void updateOomAdjUpdatePolicy() { OOMADJ_UPDATE_QUICK = DeviceConfig.getInt( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, Loading