Merge "Rate-limit FGS notification visibility deferral" into sc-dev

This commit is contained in:
Chris Tate
2021-03-30 22:30:34 +00:00
committed by Android (Google) Code Review
2 changed files with 52 additions and 3 deletions

View File

@@ -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;
@@ -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.
*/
@@ -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
@@ -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
@@ -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) {

View File

@@ -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;
@@ -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
@@ -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;
@@ -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,