From 98fdd791c7bbff1bbab41e4d57528247a489dc9e Mon Sep 17 00:00:00 2001 From: Siim Sammul Date: Thu, 18 May 2023 14:29:42 +0100 Subject: [PATCH] Make DropboxRateLimiter params flag-controllable. Bug: N/A Test: N/A Change-Id: I14b66bba17b352df25c0b08946839e4563081d2c --- .../java/com/android/server/BootReceiver.java | 5 ++ .../server/am/ActivityManagerConstants.java | 2 + .../server/am/ActivityManagerService.java | 5 ++ .../android/server/am/DropboxRateLimiter.java | 58 ++++++++++++++++--- .../server/os/NativeTombstoneManager.java | 2 + 5 files changed, 63 insertions(+), 9 deletions(-) diff --git a/services/core/java/com/android/server/BootReceiver.java b/services/core/java/com/android/server/BootReceiver.java index 7d016c82adc56..26421b75c2976 100644 --- a/services/core/java/com/android/server/BootReceiver.java +++ b/services/core/java/com/android/server/BootReceiver.java @@ -313,6 +313,11 @@ public class BootReceiver extends BroadcastReceiver { private static final DropboxRateLimiter sDropboxRateLimiter = new DropboxRateLimiter(); + /** Initialize the rate limiter. */ + public static void initDropboxRateLimiter() { + sDropboxRateLimiter.init(); + } + /** * Reset the dropbox rate limiter. */ diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index 44e198b537617..ee7791461cc5d 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -1345,6 +1345,8 @@ final class ActivityManagerConstants extends ContentObserver { // The following read from Settings. updateActivityStartsLoggingEnabled(); updateForegroundServiceStartsLoggingEnabled(); + // Read DropboxRateLimiter params from flags. + mService.initDropboxRateLimiter(); } private void loadDeviceConfigConstants() { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index a6debf6f3d51c..3be746b5f9f8c 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -9206,6 +9206,11 @@ public class ActivityManagerService extends IActivityManager.Stub private final DropboxRateLimiter mDropboxRateLimiter = new DropboxRateLimiter(); + /** Initializes the Dropbox Rate Limiter parameters from flags. */ + public void initDropboxRateLimiter() { + mDropboxRateLimiter.init(); + } + /** * Write a description of an error (crash, WTF, ANR) to the drop box. * @param eventType to include in the drop box tag ("crash", "wtf", etc.) diff --git a/services/core/java/com/android/server/am/DropboxRateLimiter.java b/services/core/java/com/android/server/am/DropboxRateLimiter.java index b5c7215df899a..003e6141aeb05 100644 --- a/services/core/java/com/android/server/am/DropboxRateLimiter.java +++ b/services/core/java/com/android/server/am/DropboxRateLimiter.java @@ -17,6 +17,7 @@ package com.android.server.am; import android.os.SystemClock; +import android.provider.DeviceConfig; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.Slog; @@ -30,17 +31,26 @@ public class DropboxRateLimiter { // After RATE_LIMIT_ALLOWED_ENTRIES have been collected (for a single breakdown of // process/eventType) further entries will be rejected until RATE_LIMIT_BUFFER_DURATION has // elapsed, after which the current count for this breakdown will be reset. - private static final long RATE_LIMIT_BUFFER_DURATION = 10 * DateUtils.MINUTE_IN_MILLIS; + private static final long RATE_LIMIT_BUFFER_DURATION_DEFAULT = 10 * DateUtils.MINUTE_IN_MILLIS; // Indicated how many buffer durations to wait before the rate limit buffer will be cleared. // E.g. if set to 3 will wait 3xRATE_LIMIT_BUFFER_DURATION before clearing the buffer. - private static final long RATE_LIMIT_BUFFER_EXPIRY_FACTOR = 3; + private static final long RATE_LIMIT_BUFFER_EXPIRY_FACTOR_DEFAULT = 3; // The number of entries to keep per breakdown of process/eventType. - private static final int RATE_LIMIT_ALLOWED_ENTRIES = 6; + private static final int RATE_LIMIT_ALLOWED_ENTRIES_DEFAULT = 6; // If a process is rate limited twice in a row we consider it crash-looping and rate limit it // more aggressively. - private static final int STRICT_RATE_LIMIT_ALLOWED_ENTRIES = 1; - private static final long STRICT_RATE_LIMIT_BUFFER_DURATION = 20 * DateUtils.MINUTE_IN_MILLIS; + private static final int STRICT_RATE_LIMIT_ALLOWED_ENTRIES_DEFAULT = 1; + private static final long STRICT_RATE_LIMIT_BUFFER_DURATION_DEFAULT = + 20 * DateUtils.MINUTE_IN_MILLIS; + + private static final String FLAG_NAMESPACE = "dropbox"; + + private long mRateLimitBufferDuration; + private long mRateLimitBufferExpiryFactor; + private int mRateLimitAllowedEntries; + private int mStrictRatelimitAllowedEntries; + private long mStrictRateLimitBufferDuration; @GuardedBy("mErrorClusterRecords") private final ArrayMap mErrorClusterRecords = new ArrayMap<>(); @@ -54,6 +64,36 @@ public class DropboxRateLimiter { public DropboxRateLimiter(Clock clock) { mClock = clock; + + mRateLimitBufferDuration = RATE_LIMIT_BUFFER_DURATION_DEFAULT; + mRateLimitBufferExpiryFactor = RATE_LIMIT_BUFFER_EXPIRY_FACTOR_DEFAULT; + mRateLimitAllowedEntries = RATE_LIMIT_ALLOWED_ENTRIES_DEFAULT; + mStrictRatelimitAllowedEntries = STRICT_RATE_LIMIT_ALLOWED_ENTRIES_DEFAULT; + mStrictRateLimitBufferDuration = STRICT_RATE_LIMIT_BUFFER_DURATION_DEFAULT; + } + + /** Initializes the rate limiter parameters from flags. */ + public void init() { + mRateLimitBufferDuration = DeviceConfig.getLong( + FLAG_NAMESPACE, + "DropboxRateLimiter__rate_limit_buffer_duration", + RATE_LIMIT_BUFFER_DURATION_DEFAULT); + mRateLimitBufferExpiryFactor = DeviceConfig.getLong( + FLAG_NAMESPACE, + "DropboxRateLimiter__rate_limit_buffer_expiry_factor", + RATE_LIMIT_BUFFER_EXPIRY_FACTOR_DEFAULT); + mRateLimitAllowedEntries = DeviceConfig.getInt( + FLAG_NAMESPACE, + "DropboxRateLimiter__rate_limit_allowed_entries", + RATE_LIMIT_ALLOWED_ENTRIES_DEFAULT); + mStrictRatelimitAllowedEntries = DeviceConfig.getInt( + FLAG_NAMESPACE, + "DropboxRateLimiter__strict_rate_limit_allowed_entries", + STRICT_RATE_LIMIT_ALLOWED_ENTRIES_DEFAULT); + mStrictRateLimitBufferDuration = DeviceConfig.getLong( + FLAG_NAMESPACE, + "DropboxRateLimiter__strict_rate_limit_buffer_duration", + STRICT_RATE_LIMIT_BUFFER_DURATION_DEFAULT); } /** The interface clock to use for tracking the time elapsed. */ @@ -116,7 +156,7 @@ public class DropboxRateLimiter { private void maybeRemoveExpiredRecords(long currentTime) { if (currentTime - mLastMapCleanUp - <= RATE_LIMIT_BUFFER_EXPIRY_FACTOR * RATE_LIMIT_BUFFER_DURATION) { + <= mRateLimitBufferExpiryFactor * mRateLimitBufferDuration) { return; } @@ -219,15 +259,15 @@ public class DropboxRateLimiter { } public int getAllowedEntries() { - return isRepeated() ? STRICT_RATE_LIMIT_ALLOWED_ENTRIES : RATE_LIMIT_ALLOWED_ENTRIES; + return isRepeated() ? mStrictRatelimitAllowedEntries : mRateLimitAllowedEntries; } public long getBufferDuration() { - return isRepeated() ? STRICT_RATE_LIMIT_BUFFER_DURATION : RATE_LIMIT_BUFFER_DURATION; + return isRepeated() ? mStrictRateLimitBufferDuration : mRateLimitBufferDuration; } public boolean hasExpired(long currentTime) { - long bufferExpiry = RATE_LIMIT_BUFFER_EXPIRY_FACTOR * getBufferDuration(); + long bufferExpiry = mRateLimitBufferExpiryFactor * getBufferDuration(); return currentTime - mStartTime > bufferExpiry; } } diff --git a/services/core/java/com/android/server/os/NativeTombstoneManager.java b/services/core/java/com/android/server/os/NativeTombstoneManager.java index d3d1cc5d05cb7..f8ee6b04e9a2f 100644 --- a/services/core/java/com/android/server/os/NativeTombstoneManager.java +++ b/services/core/java/com/android/server/os/NativeTombstoneManager.java @@ -96,6 +96,8 @@ public final class NativeTombstoneManager { registerForUserRemoval(); registerForPackageRemoval(); + BootReceiver.initDropboxRateLimiter(); + // Scan existing tombstones. mHandler.post(() -> { final File[] tombstoneFiles = TOMBSTONE_DIR.listFiles();