From 831334bd5201bf5f98b94c256c4af65cbbd9d53d Mon Sep 17 00:00:00 2001
From: Sanal Buvaev <buvaev@google.com>
Date: Wed, 8 May 2024 01:06:53 +0000
Subject: [PATCH] Add throtling to crashloop mitigations

In case of crash loops with a short time mainline rollbacks don't finish before the next mitigation which is warm reboot.

Change-Id: I77a487cb27e4254865ba2cc045e379dcb7348994
Test: unit and manual tests
Bug: 310236690
---
 .../com/android/server/PackageWatchdog.java   | 23 +++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index a61925732256..c1d59db1f0c7 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -138,6 +138,11 @@ public class PackageWatchdog {
 
     static final long DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS = TimeUnit.MINUTES.toMillis(10);
 
+    // Time needed to apply mitigation
+    private static final String MITIGATION_WINDOW_MS =
+            "persist.device_config.configuration.mitigation_window_ms";
+    private static final long DEFAULT_MITIGATION_WINDOW_MS = TimeUnit.SECONDS.toMillis(5);
+
     // Threshold level at which or above user might experience significant disruption.
     private static final String MAJOR_USER_IMPACT_LEVEL_THRESHOLD =
             "persist.device_config.configuration.major_user_impact_level_threshold";
@@ -210,6 +215,9 @@ public class PackageWatchdog {
     @GuardedBy("mLock")
     private boolean mSyncRequired = false;
 
+    @GuardedBy("mLock")
+    private long mLastMitigation = -1000000;
+
     @FunctionalInterface
     @VisibleForTesting
     interface SystemClock {
@@ -400,6 +408,14 @@ public class PackageWatchdog {
             Slog.w(TAG, "Could not resolve a list of failing packages");
             return;
         }
+        synchronized (mLock) {
+            final long now = mSystemClock.uptimeMillis();
+            if (now >= mLastMitigation
+                    && (now - mLastMitigation) < getMitigationWindowMs()) {
+                Slog.i(TAG, "Skipping onPackageFailure mitigation");
+                return;
+            }
+        }
         mLongTaskHandler.post(() -> {
             synchronized (mLock) {
                 if (mAllObservers.isEmpty()) {
@@ -500,10 +516,17 @@ public class PackageWatchdog {
                               int currentObserverImpact,
                               int mitigationCount) {
         if (currentObserverImpact < getUserImpactLevelLimit()) {
+            synchronized (mLock) {
+                mLastMitigation = mSystemClock.uptimeMillis();
+            }
             currentObserverToNotify.execute(versionedPackage, failureReason, mitigationCount);
         }
     }
 
+    private long getMitigationWindowMs() {
+        return SystemProperties.getLong(MITIGATION_WINDOW_MS, DEFAULT_MITIGATION_WINDOW_MS);
+    }
+
 
     /**
      * Called when the system server boots. If the system server is detected to be in a boot loop,
-- 
GitLab