diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 12debbff3e909..521b39305d9d2 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -57,6 +57,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
@@ -81,6 +82,22 @@ public class PackageWatchdog {
static final String PROPERTY_WATCHDOG_EXPLICIT_HEALTH_CHECK_ENABLED =
"watchdog_explicit_health_check_enabled";
+ public static final int FAILURE_REASON_UNKNOWN = 0;
+ public static final int FAILURE_REASON_NATIVE_CRASH = 1;
+ public static final int FAILURE_REASON_EXPLICIT_HEALTH_CHECK = 2;
+ public static final int FAILURE_REASON_APP_CRASH = 3;
+ public static final int FAILURE_REASON_APP_NOT_RESPONDING = 4;
+
+ @IntDef(prefix = { "FAILURE_REASON_" }, value = {
+ FAILURE_REASON_UNKNOWN,
+ FAILURE_REASON_NATIVE_CRASH,
+ FAILURE_REASON_EXPLICIT_HEALTH_CHECK,
+ FAILURE_REASON_APP_CRASH,
+ FAILURE_REASON_APP_NOT_RESPONDING
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FailureReasons {}
+
// Duration to count package failures before it resets to 0
@VisibleForTesting
static final int DEFAULT_TRIGGER_FAILURE_DURATION_MS =
@@ -305,14 +322,15 @@ public class PackageWatchdog {
}
/**
- * Called when a process fails either due to a crash or ANR.
+ * Called when a process fails due to a crash, ANR or explicit health check.
*
*
For each package contained in the process, one registered observer with the least user
* impact will be notified for mitigation.
*
*
This method could be called frequently if there is a severe problem on the device.
*/
- public void onPackageFailure(List packages) {
+ public void onPackageFailure(List packages,
+ @FailureReasons int failureReason) {
mLongTaskHandler.post(() -> {
synchronized (mLock) {
if (mAllObservers.isEmpty()) {
@@ -343,7 +361,7 @@ public class PackageWatchdog {
// Execute action with least user impact
if (currentObserverToNotify != null) {
- currentObserverToNotify.execute(versionedPackage);
+ currentObserverToNotify.execute(versionedPackage, failureReason);
}
}
}
@@ -414,7 +432,7 @@ public class PackageWatchdog {
*
* @return {@code true} if action was executed successfully, {@code false} otherwise
*/
- boolean execute(VersionedPackage versionedPackage);
+ boolean execute(VersionedPackage versionedPackage, @FailureReasons int failureReason);
// TODO(b/120598832): Ensure uniqueness?
/**
@@ -659,7 +677,8 @@ public class PackageWatchdog {
while (it.hasNext()) {
VersionedPackage versionedPkg = it.next().mPackage;
Slog.i(TAG, "Explicit health check failed for package " + versionedPkg);
- registeredObserver.execute(versionedPkg);
+ registeredObserver.execute(versionedPkg,
+ PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK);
}
}
}
@@ -770,7 +789,7 @@ public class PackageWatchdog {
final List pkgList = Collections.singletonList(pkg);
final long failureCount = getTriggerFailureCount();
for (int i = 0; i < failureCount; i++) {
- onPackageFailure(pkgList);
+ onPackageFailure(pkgList, FAILURE_REASON_EXPLICIT_HEALTH_CHECK);
}
});
}
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 51e1718d4c981..83a7341923faa 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -446,7 +446,8 @@ class AppErrors {
RescueParty.noteAppCrash(mContext, r.uid);
}
- mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode());
+ mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode(),
+ PackageWatchdog.FAILURE_REASON_APP_CRASH);
}
final int relaunchReason = r != null
@@ -900,7 +901,8 @@ class AppErrors {
}
// Notify PackageWatchdog without the lock held
if (packageList != null) {
- mPackageWatchdog.onPackageFailure(packageList);
+ mPackageWatchdog.onPackageFailure(packageList,
+ PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING);
}
}
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 83891f60d4f76..bd29d6a5450ab 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -41,6 +41,7 @@ import android.util.StatsLog;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.server.PackageWatchdog;
+import com.android.server.PackageWatchdog.FailureReasons;
import com.android.server.PackageWatchdog.PackageHealthObserver;
import com.android.server.PackageWatchdog.PackageHealthObserverImpact;
@@ -106,7 +107,7 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
}
@Override
- public boolean execute(VersionedPackage failedPackage) {
+ public boolean execute(VersionedPackage failedPackage, @FailureReasons int rollbackReason) {
RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
VersionedPackage moduleMetadataPackage = getModuleMetadataPackage();
RollbackInfo rollback = getAvailableRollback(rollbackManager, failedPackage);
@@ -371,7 +372,7 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
mNumberOfNativeCrashPollsRemaining--;
// Check if native watchdog reported a crash
if ("1".equals(SystemProperties.get("sys.init.updatable_crashing"))) {
- execute(getModuleMetadataPackage());
+ execute(getModuleMetadataPackage(), PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
// we stop polling after an attempt to execute rollback, regardless of whether the
// attempt succeeds or not
} else {
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index e30878157a26e..ef8facec97521 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -118,7 +118,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// The failed packages should be the same as the registered ones to ensure registration is
// done successfully
@@ -135,7 +136,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer2, Arrays.asList(APP_A, APP_B), SHORT_DURATION);
raiseFatalFailureAndDispatch(watchdog,
Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
- new VersionedPackage(APP_B, VERSION_CODE)));
+ new VersionedPackage(APP_B, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// The failed packages should be the same as the registered ones to ensure registration is
// done successfully
@@ -151,7 +153,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
watchdog.unregisterHealthObserver(observer);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// We should have no failed packages to ensure unregistration is done successfully
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
@@ -167,7 +170,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION);
watchdog.unregisterHealthObserver(observer2);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// observer1 should receive failed packages as intended.
assertThat(observer1.mHealthCheckFailedPackages).containsExactly(APP_A);
@@ -183,7 +187,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
moveTimeForwardAndDispatch(SHORT_DURATION);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// We should have no failed packages for the fatal failure is raised after expiration
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
@@ -199,7 +204,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), LONG_DURATION);
moveTimeForwardAndDispatch(SHORT_DURATION);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// We should have no failed packages for the fatal failure is raised after expiration
assertThat(observer1.mHealthCheckFailedPackages).isEmpty();
@@ -226,7 +232,8 @@ public class PackageWatchdogTest {
moveTimeForwardAndDispatch((SHORT_DURATION / 2) + 1);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify that we receive failed packages as expected for APP_A not expired
assertThat(observer.mHealthCheckFailedPackages).containsExactly(APP_A);
@@ -252,7 +259,8 @@ public class PackageWatchdogTest {
watchdog2.registerHealthObserver(observer2);
raiseFatalFailureAndDispatch(watchdog2,
Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
- new VersionedPackage(APP_B, VERSION_CODE)));
+ new VersionedPackage(APP_B, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// We should receive failed packages as expected to ensure observers are persisted and
// resumed correctly
@@ -274,7 +282,8 @@ public class PackageWatchdogTest {
// Then fail APP_A below the threshold
for (int i = 0; i < watchdog.getTriggerFailureCount() - 1; i++) {
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
}
// Run handler so package failures are dispatched to observers
@@ -301,7 +310,8 @@ public class PackageWatchdogTest {
// Then fail APP_C (not observed) above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_C, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_C, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify that observers are not notified
assertThat(observer1.mHealthCheckFailedPackages).isEmpty();
@@ -331,7 +341,8 @@ public class PackageWatchdogTest {
// Then fail APP_A (different version) above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, differentVersionCode)));
+ Arrays.asList(new VersionedPackage(APP_A, differentVersionCode)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify that observers are not notified
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
@@ -368,7 +379,8 @@ public class PackageWatchdogTest {
Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
new VersionedPackage(APP_B, VERSION_CODE),
new VersionedPackage(APP_C, VERSION_CODE),
- new VersionedPackage(APP_D, VERSION_CODE)));
+ new VersionedPackage(APP_D, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify least impact observers are notifed of package failures
List observerNonePackages = observerNone.mMitigatedPackages;
@@ -411,7 +423,8 @@ public class PackageWatchdogTest {
// Then fail APP_A above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify only observerFirst is notifed
assertThat(observerFirst.mMitigatedPackages).containsExactly(APP_A);
@@ -424,7 +437,8 @@ public class PackageWatchdogTest {
// Then fail APP_A again above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify only observerSecond is notifed cos it has least impact
assertThat(observerSecond.mMitigatedPackages).containsExactly(APP_A);
@@ -437,7 +451,8 @@ public class PackageWatchdogTest {
// Then fail APP_A again above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify only observerFirst is notifed cos it has the only action
assertThat(observerFirst.mMitigatedPackages).containsExactly(APP_A);
@@ -450,7 +465,8 @@ public class PackageWatchdogTest {
// Then fail APP_A again above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify no observer is notified cos no actions left
assertThat(observerFirst.mMitigatedPackages).isEmpty();
@@ -474,7 +490,8 @@ public class PackageWatchdogTest {
// Then fail APP_A above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify only one observer is notifed
assertThat(observer1.mMitigatedPackages).containsExactly(APP_A);
@@ -746,13 +763,15 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
// Fail APP_A below the threshold which should not trigger package failures
for (int i = 0; i < PackageWatchdog.DEFAULT_TRIGGER_FAILURE_COUNT - 1; i++) {
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
}
mTestLooper.dispatchAll();
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
// One more to trigger the package failure
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
assertThat(observer.mHealthCheckFailedPackages).containsExactly(APP_A);
}
@@ -773,20 +792,24 @@ public class PackageWatchdogTest {
TestObserver observer = new TestObserver(OBSERVER_NAME_1);
watchdog.startObservingHealth(observer, Arrays.asList(APP_A, APP_B), Long.MAX_VALUE);
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_TRIGGER_FAILURE_DURATION_MS + 1);
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
// We shouldn't receive APP_A since the interval of 2 failures is greater than
// DEFAULT_TRIGGER_FAILURE_DURATION_MS.
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_TRIGGER_FAILURE_DURATION_MS - 1);
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
// We should receive APP_B since the interval of 2 failures is less than
@@ -809,7 +832,8 @@ public class PackageWatchdogTest {
// small timeouts.
moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_OBSERVING_DURATION_MS - 100);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// We should receive APP_A since the observer hasn't expired
assertThat(observer.mHealthCheckFailedPackages).containsExactly(APP_A);
@@ -827,7 +851,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), -1);
moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_OBSERVING_DURATION_MS + 1);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// We should receive nothing since the observer has expired
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
@@ -850,22 +875,59 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), Long.MAX_VALUE);
// Raise 2 failures at t=0 and t=900 respectively
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
moveTimeForwardAndDispatch(900);
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
// Raise 2 failures at t=1100
moveTimeForwardAndDispatch(200);
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
// We should receive APP_A since there are 3 failures within 1000ms window
assertThat(observer.mHealthCheckFailedPackages).containsExactly(APP_A);
}
+ /** Test that observers execute correctly for different failure reasons */
+ @Test
+ public void testFailureReasons() {
+ PackageWatchdog watchdog = createWatchdog();
+ TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
+ TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
+ TestObserver observer3 = new TestObserver(OBSERVER_NAME_3);
+ TestObserver observer4 = new TestObserver(OBSERVER_NAME_4);
+
+ watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION);
+ watchdog.startObservingHealth(observer2, Arrays.asList(APP_B), SHORT_DURATION);
+ watchdog.startObservingHealth(observer3, Arrays.asList(APP_C), SHORT_DURATION);
+ watchdog.startObservingHealth(observer4, Arrays.asList(APP_D), SHORT_DURATION);
+
+ raiseFatalFailureAndDispatch(watchdog, Arrays.asList(new VersionedPackage(APP_A,
+ VERSION_CODE)), PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
+ raiseFatalFailureAndDispatch(watchdog, Arrays.asList(new VersionedPackage(APP_B,
+ VERSION_CODE)), PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK);
+ raiseFatalFailureAndDispatch(watchdog, Arrays.asList(new VersionedPackage(APP_C,
+ VERSION_CODE)), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+ raiseFatalFailureAndDispatch(watchdog, Arrays.asList(new VersionedPackage(APP_D,
+ VERSION_CODE)), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING);
+
+ assertThat(observer1.getLastFailureReason()).isEqualTo(
+ PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
+ assertThat(observer2.getLastFailureReason()).isEqualTo(
+ PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK);
+ assertThat(observer3.getLastFailureReason()).isEqualTo(
+ PackageWatchdog.FAILURE_REASON_APP_CRASH);
+ assertThat(observer4.getLastFailureReason()).isEqualTo(
+ PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING);
+ }
+
private void adoptShellPermissions(String... permissions) {
InstrumentationRegistry
.getInstrumentation()
@@ -900,9 +962,9 @@ public class PackageWatchdogTest {
/** Trigger package failures above the threshold. */
private void raiseFatalFailureAndDispatch(PackageWatchdog watchdog,
- List packages) {
+ List packages, int failureReason) {
for (int i = 0; i < watchdog.getTriggerFailureCount(); i++) {
- watchdog.onPackageFailure(packages);
+ watchdog.onPackageFailure(packages, failureReason);
}
mTestLooper.dispatchAll();
}
@@ -936,6 +998,7 @@ public class PackageWatchdogTest {
private static class TestObserver implements PackageHealthObserver {
private final String mName;
private int mImpact;
+ private int mLastFailureReason;
final List mHealthCheckFailedPackages = new ArrayList<>();
final List mMitigatedPackages = new ArrayList<>();
@@ -954,14 +1017,19 @@ public class PackageWatchdogTest {
return mImpact;
}
- public boolean execute(VersionedPackage versionedPackage) {
+ public boolean execute(VersionedPackage versionedPackage, int failureReason) {
mMitigatedPackages.add(versionedPackage.getPackageName());
+ mLastFailureReason = failureReason;
return true;
}
public String getName() {
return mName;
}
+
+ public int getLastFailureReason() {
+ return mLastFailureReason;
+ }
}
private static class TestController extends ExplicitHealthCheckController {