Preserve failure history when calling startObservingHealth
Instead of always creating a new MonitoredPackage every time
PackageWatchdog#startObservingHealth is called, just update
the duration of an existing MonitoredPackage if one exists. This
means that the failure history will be preserved.
Test: atest PackageWatchdogTest
Bug: 150114865
Change-Id: I6d6e3e0e893a603fda50df833bc5b6ce1757b6ec
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 41a104c..d9e7c38 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -1062,7 +1062,12 @@
public void updatePackagesLocked(List<MonitoredPackage> packages) {
for (int pIndex = 0; pIndex < packages.size(); pIndex++) {
MonitoredPackage p = packages.get(pIndex);
- this.packages.put(p.getName(), p);
+ MonitoredPackage existingPackage = this.packages.get(p.getName());
+ if (existingPackage != null) {
+ existingPackage.updateHealthCheckDuration(p.mDurationMs);
+ } else {
+ this.packages.put(p.getName(), p);
+ }
}
}
@@ -1331,6 +1336,12 @@
return updateHealthCheckStateLocked();
}
+ /** Explicitly update the monitoring duration of the package. */
+ @GuardedBy("mLock")
+ public void updateHealthCheckDuration(long newDurationMs) {
+ mDurationMs = newDurationMs;
+ }
+
/**
* Marks the health check as passed and transitions to {@link HealthCheckState.PASSED}
* if not yet {@link HealthCheckState.FAILED}.
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index 2957192..d011dbb 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -1123,6 +1123,28 @@
assertThat(testController.getSyncRequests()).isEqualTo(expectedSyncRequests);
}
+ /**
+ * Ensure that the failure history of a package is preserved when making duplicate calls to
+ * observe the package.
+ */
+ @Test
+ public void testFailureHistoryIsPreserved() {
+ PackageWatchdog watchdog = createWatchdog();
+ TestObserver observer = new TestObserver(OBSERVER_NAME_1);
+ watchdog.startObservingHealth(observer, List.of(APP_A), SHORT_DURATION);
+ for (int i = 0; i < PackageWatchdog.DEFAULT_TRIGGER_FAILURE_COUNT - 1; i++) {
+ watchdog.onPackageFailure(List.of(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
+ }
+ mTestLooper.dispatchAll();
+ assertThat(observer.mMitigatedPackages).isEmpty();
+ watchdog.startObservingHealth(observer, List.of(APP_A), LONG_DURATION);
+ watchdog.onPackageFailure(List.of(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
+ mTestLooper.dispatchAll();
+ assertThat(observer.mMitigatedPackages).isEqualTo(List.of(APP_A));
+ }
+
private void adoptShellPermissions(String... permissions) {
InstrumentationRegistry
.getInstrumentation()