Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 30ca8700 authored by Chris Tate's avatar Chris Tate Committed by Automerger Merge Worker
Browse files

Merge "Rate-limit FGS notification visibility deferral" into sc-dev am: 525bf2cc

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13985549

Change-Id: Ic3e010be75df5a478e64cd12e384fbbbf3c2df07
parents 8dd92643 525bf2cc
Loading
Loading
Loading
Loading
+29 −3
Original line number Diff line number Diff line
@@ -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) {
+23 −0
Original line number Diff line number Diff line
@@ -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,