diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java | 324 |
1 files changed, 323 insertions, 1 deletions
diff --git a/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java b/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java index 3722fefb12ad..c0e90f9232d6 100644 --- a/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java +++ b/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java @@ -35,6 +35,7 @@ import static org.mockito.Mockito.when; import android.Manifest; import android.content.Context; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.VersionedPackage; @@ -77,6 +78,7 @@ import org.mockito.stubbing.Answer; import java.io.File; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -413,6 +415,311 @@ public class CrashRecoveryTest { verify(rescuePartyObserver, never()).executeBootLoopMitigation(2); } + @Test + @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS) + public void testCrashLoopWithRescuePartyAndRollbackObserver() throws Exception { + PackageWatchdog watchdog = createWatchdog(); + RescuePartyObserver rescuePartyObserver = setUpRescuePartyObserver(watchdog); + RollbackPackageHealthObserver rollbackObserver = + setUpRollbackPackageHealthObserver(watchdog); + VersionedPackage versionedPackageA = new VersionedPackage(APP_A, VERSION_CODE); + + when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).then(inv -> { + ApplicationInfo info = new ApplicationInfo(); + info.flags |= ApplicationInfo.FLAG_PERSISTENT + | ApplicationInfo.FLAG_SYSTEM; + return info; + }); + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // Mitigation: SCOPED_DEVICE_CONFIG_RESET + verify(rescuePartyObserver).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 1); + verify(rescuePartyObserver, never()).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + verify(rollbackObserver, never()).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 1); + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // Mitigation: ALL_DEVICE_CONFIG_RESET + verify(rescuePartyObserver).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + verify(rescuePartyObserver, never()).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 3); + verify(rollbackObserver, never()).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 1); + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // Mitigation: WARM_REBOOT + verify(rescuePartyObserver).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 3); + verify(rescuePartyObserver, never()).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 4); + verify(rollbackObserver, never()).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 1); + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // Mitigation: Low impact rollback + verify(rollbackObserver).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 1); + verify(rescuePartyObserver, never()).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 4); + + // update available rollbacks to mock rollbacks being applied after the call to + // rollbackObserver.execute + when(mRollbackManager.getAvailableRollbacks()).thenReturn( + List.of(ROLLBACK_INFO_HIGH, ROLLBACK_INFO_MANUAL)); + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // DEFAULT_MAJOR_USER_IMPACT_LEVEL_THRESHOLD reached. No more mitigations applied + verify(rescuePartyObserver, never()).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 4); + verify(rollbackObserver, never()).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + } + + @Test + @EnableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS) + public void testCrashLoopWithRescuePartyAndRollbackObserverEnableDeprecateFlagReset() + throws Exception { + PackageWatchdog watchdog = createWatchdog(); + RescuePartyObserver rescuePartyObserver = setUpRescuePartyObserver(watchdog); + RollbackPackageHealthObserver rollbackObserver = + setUpRollbackPackageHealthObserver(watchdog); + VersionedPackage versionedPackageA = new VersionedPackage(APP_A, VERSION_CODE); + + when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).then(inv -> { + ApplicationInfo info = new ApplicationInfo(); + info.flags |= ApplicationInfo.FLAG_PERSISTENT + | ApplicationInfo.FLAG_SYSTEM; + return info; + }); + + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // Mitigation: WARM_REBOOT + verify(rescuePartyObserver).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 1); + verify(rescuePartyObserver, never()).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + verify(rollbackObserver, never()).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 1); + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // Mitigation: Low impact rollback + verify(rollbackObserver).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 1); + verify(rescuePartyObserver, never()).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + + // update available rollbacks to mock rollbacks being applied after the call to + // rollbackObserver.execute + when(mRollbackManager.getAvailableRollbacks()).thenReturn( + List.of(ROLLBACK_INFO_HIGH, ROLLBACK_INFO_MANUAL)); + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // DEFAULT_MAJOR_USER_IMPACT_LEVEL_THRESHOLD reached. No more mitigations applied + verify(rescuePartyObserver, never()).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + verify(rollbackObserver, never()).execute(versionedPackageA, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + } + + @Test + @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS) + public void testCrashLoopSystemUIWithRescuePartyAndRollbackObserver() throws Exception { + PackageWatchdog watchdog = createWatchdog(); + RescuePartyObserver rescuePartyObserver = setUpRescuePartyObserver(watchdog); + RollbackPackageHealthObserver rollbackObserver = + setUpRollbackPackageHealthObserver(watchdog); + String systemUi = "com.android.systemui"; + VersionedPackage versionedPackageUi = new VersionedPackage( + systemUi, VERSION_CODE); + RollbackInfo rollbackInfoUi = getRollbackInfo(systemUi, VERSION_CODE, 1, + PackageManager.ROLLBACK_USER_IMPACT_LOW); + when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(ROLLBACK_INFO_LOW, + ROLLBACK_INFO_HIGH, ROLLBACK_INFO_MANUAL, rollbackInfoUi)); + + when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).then(inv -> { + ApplicationInfo info = new ApplicationInfo(); + info.flags |= ApplicationInfo.FLAG_PERSISTENT + | ApplicationInfo.FLAG_SYSTEM; + return info; + }); + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // Mitigation: SCOPED_DEVICE_CONFIG_RESET + verify(rescuePartyObserver).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 1); + verify(rescuePartyObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + verify(rollbackObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 1); + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // Mitigation: ALL_DEVICE_CONFIG_RESET + verify(rescuePartyObserver).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + verify(rescuePartyObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 3); + verify(rollbackObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 1); + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // Mitigation: WARM_REBOOT + verify(rescuePartyObserver).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 3); + verify(rescuePartyObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 4); + verify(rollbackObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 1); + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // Mitigation: Low impact rollback + verify(rollbackObserver).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 1); + verify(rescuePartyObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 4); + verify(rollbackObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + + // update available rollbacks to mock rollbacks being applied after the call to + // rollbackObserver.execute + when(mRollbackManager.getAvailableRollbacks()).thenReturn( + List.of(ROLLBACK_INFO_HIGH, ROLLBACK_INFO_MANUAL)); + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // Mitigation: RESET_SETTINGS_UNTRUSTED_DEFAULTS + verify(rescuePartyObserver).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 4); + verify(rescuePartyObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 5); + verify(rollbackObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // Mitigation: RESET_SETTINGS_UNTRUSTED_CHANGES + verify(rescuePartyObserver).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 5); + verify(rescuePartyObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 6); + verify(rollbackObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // Mitigation: RESET_SETTINGS_TRUSTED_DEFAULTS + verify(rescuePartyObserver).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 6); + verify(rescuePartyObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 7); + verify(rollbackObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // Mitigation: Factory reset. High impact rollbacks are performed only for boot loops. + verify(rescuePartyObserver).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 7); + verify(rescuePartyObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 8); + verify(rollbackObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + } + + @Test + @EnableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS) + public void testCrashLoopSystemUIWithRescuePartyAndRollbackObserverEnableDeprecateFlagReset() + throws Exception { + PackageWatchdog watchdog = createWatchdog(); + RescuePartyObserver rescuePartyObserver = setUpRescuePartyObserver(watchdog); + RollbackPackageHealthObserver rollbackObserver = + setUpRollbackPackageHealthObserver(watchdog); + String systemUi = "com.android.systemui"; + VersionedPackage versionedPackageUi = new VersionedPackage( + systemUi, VERSION_CODE); + RollbackInfo rollbackInfoUi = getRollbackInfo(systemUi, VERSION_CODE, 1, + PackageManager.ROLLBACK_USER_IMPACT_LOW); + when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(ROLLBACK_INFO_LOW, + ROLLBACK_INFO_HIGH, ROLLBACK_INFO_MANUAL, rollbackInfoUi)); + + when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).then(inv -> { + ApplicationInfo info = new ApplicationInfo(); + info.flags |= ApplicationInfo.FLAG_PERSISTENT + | ApplicationInfo.FLAG_SYSTEM; + return info; + }); + + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // Mitigation: WARM_REBOOT + verify(rescuePartyObserver).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 1); + verify(rescuePartyObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + verify(rollbackObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 1); + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // Mitigation: Low impact rollback + verify(rollbackObserver).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 1); + verify(rescuePartyObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + verify(rollbackObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + + // update available rollbacks to mock rollbacks being applied after the call to + // rollbackObserver.execute + when(mRollbackManager.getAvailableRollbacks()).thenReturn( + List.of(ROLLBACK_INFO_HIGH, ROLLBACK_INFO_MANUAL)); + + raiseFatalFailureAndDispatch(watchdog, + Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + // Mitigation: Factory reset. High impact rollbacks are performed only for boot loops. + verify(rescuePartyObserver).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + verify(rescuePartyObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 3); + verify(rollbackObserver, never()).execute(versionedPackageUi, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2); + } + RollbackPackageHealthObserver setUpRollbackPackageHealthObserver(PackageWatchdog watchdog) { RollbackPackageHealthObserver rollbackObserver = spy(new RollbackPackageHealthObserver(mSpyContext, mApexManager)); @@ -424,7 +731,6 @@ public class CrashRecoveryTest { watchdog.registerHealthObserver(rollbackObserver); return rollbackObserver; } - RescuePartyObserver setUpRescuePartyObserver(PackageWatchdog watchdog) { setCrashRecoveryPropRescueBootCount(0); RescuePartyObserver rescuePartyObserver = spy(RescuePartyObserver.getInstance(mSpyContext)); @@ -686,4 +992,20 @@ public class CrashRecoveryTest { mTestLooper.moveTimeForward(milliSeconds); mTestLooper.dispatchAll(); } + + private void raiseFatalFailureAndDispatch(PackageWatchdog watchdog, + List<VersionedPackage> packages, int failureReason) { + long triggerFailureCount = watchdog.getTriggerFailureCount(); + if (failureReason == PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK + || failureReason == PackageWatchdog.FAILURE_REASON_NATIVE_CRASH) { + triggerFailureCount = 1; + } + for (int i = 0; i < triggerFailureCount; i++) { + watchdog.onPackageFailure(packages, failureReason); + } + mTestLooper.dispatchAll(); + if (Flags.recoverabilityDetection()) { + moveTimeForwardAndDispatch(watchdog.DEFAULT_MITIGATION_WINDOW_MS); + } + } } |