Merge "Adding reboot throttling" into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
38b109a4c9
@@ -79,6 +79,7 @@ public class RescueParty {
|
||||
static final String PROP_ATTEMPTING_FACTORY_RESET = "sys.attempting_factory_reset";
|
||||
static final String PROP_ATTEMPTING_REBOOT = "sys.attempting_reboot";
|
||||
static final String PROP_MAX_RESCUE_LEVEL_ATTEMPTED = "sys.max_rescue_level_attempted";
|
||||
static final String PROP_LAST_FACTORY_RESET_TIME_MS = "persist.sys.last_factory_reset";
|
||||
@VisibleForTesting
|
||||
static final int LEVEL_NONE = 0;
|
||||
@VisibleForTesting
|
||||
@@ -105,10 +106,11 @@ public class RescueParty {
|
||||
@VisibleForTesting
|
||||
static final String NAMESPACE_TO_PACKAGE_MAPPING_FLAG =
|
||||
"namespace_to_package_mapping";
|
||||
@VisibleForTesting
|
||||
static final long FACTORY_RESET_THROTTLE_DURATION_MS = TimeUnit.MINUTES.toMillis(10);
|
||||
|
||||
private static final String NAME = "rescue-party-observer";
|
||||
|
||||
|
||||
private static final String PROP_DISABLE_RESCUE = "persist.sys.disable_rescue";
|
||||
private static final String PROP_VIRTUAL_DEVICE = "ro.hardware.virtual_device";
|
||||
private static final String PROP_DEVICE_CONFIG_DISABLE_FLAG =
|
||||
@@ -327,8 +329,8 @@ public class RescueParty {
|
||||
}
|
||||
}
|
||||
|
||||
private static int getMaxRescueLevel(boolean mayPerformFactoryReset) {
|
||||
if (!mayPerformFactoryReset
|
||||
private static int getMaxRescueLevel(boolean mayPerformReboot) {
|
||||
if (!mayPerformReboot
|
||||
|| SystemProperties.getBoolean(PROP_DISABLE_FACTORY_RESET_FLAG, false)) {
|
||||
return LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS;
|
||||
}
|
||||
@@ -339,11 +341,11 @@ public class RescueParty {
|
||||
* Get the rescue level to perform if this is the n-th attempt at mitigating failure.
|
||||
*
|
||||
* @param mitigationCount: the mitigation attempt number (1 = first attempt etc.)
|
||||
* @param mayPerformFactoryReset: whether or not a factory reset may be performed for the given
|
||||
* failure.
|
||||
* @param mayPerformReboot: whether or not a reboot and factory reset may be performed
|
||||
* for the given failure.
|
||||
* @return the rescue level for the n-th mitigation attempt.
|
||||
*/
|
||||
private static int getRescueLevel(int mitigationCount, boolean mayPerformFactoryReset) {
|
||||
private static int getRescueLevel(int mitigationCount, boolean mayPerformReboot) {
|
||||
if (mitigationCount == 1) {
|
||||
return LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS;
|
||||
} else if (mitigationCount == 2) {
|
||||
@@ -351,9 +353,9 @@ public class RescueParty {
|
||||
} else if (mitigationCount == 3) {
|
||||
return LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS;
|
||||
} else if (mitigationCount == 4) {
|
||||
return Math.min(getMaxRescueLevel(mayPerformFactoryReset), LEVEL_WARM_REBOOT);
|
||||
return Math.min(getMaxRescueLevel(mayPerformReboot), LEVEL_WARM_REBOOT);
|
||||
} else if (mitigationCount >= 5) {
|
||||
return Math.min(getMaxRescueLevel(mayPerformFactoryReset), LEVEL_FACTORY_RESET);
|
||||
return Math.min(getMaxRescueLevel(mayPerformReboot), LEVEL_FACTORY_RESET);
|
||||
} else {
|
||||
Slog.w(TAG, "Expected positive mitigation count, was " + mitigationCount);
|
||||
return LEVEL_NONE;
|
||||
@@ -450,6 +452,8 @@ public class RescueParty {
|
||||
break;
|
||||
}
|
||||
SystemProperties.set(PROP_ATTEMPTING_FACTORY_RESET, "true");
|
||||
long now = System.currentTimeMillis();
|
||||
SystemProperties.set(PROP_LAST_FACTORY_RESET_TIME_MS, Long.toString(now));
|
||||
runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -627,7 +631,7 @@ public class RescueParty {
|
||||
if (!isDisabled() && (failureReason == PackageWatchdog.FAILURE_REASON_APP_CRASH
|
||||
|| failureReason == PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING)) {
|
||||
return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount,
|
||||
mayPerformFactoryReset(failedPackage)));
|
||||
mayPerformReboot(failedPackage)));
|
||||
} else {
|
||||
return PackageHealthObserverImpact.USER_IMPACT_NONE;
|
||||
}
|
||||
@@ -642,7 +646,7 @@ public class RescueParty {
|
||||
if (failureReason == PackageWatchdog.FAILURE_REASON_APP_CRASH
|
||||
|| failureReason == PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING) {
|
||||
final int level = getRescueLevel(mitigationCount,
|
||||
mayPerformFactoryReset(failedPackage));
|
||||
mayPerformReboot(failedPackage));
|
||||
executeRescueLevel(mContext,
|
||||
failedPackage == null ? null : failedPackage.getPackageName(), level);
|
||||
return true;
|
||||
@@ -683,8 +687,9 @@ public class RescueParty {
|
||||
if (isDisabled()) {
|
||||
return false;
|
||||
}
|
||||
boolean mayPerformReboot = !shouldThrottleReboot();
|
||||
executeRescueLevel(mContext, /*failedPackage=*/ null,
|
||||
getRescueLevel(mitigationCount, true));
|
||||
getRescueLevel(mitigationCount, mayPerformReboot));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -698,14 +703,27 @@ public class RescueParty {
|
||||
* prompting a factory reset is an acceptable mitigation strategy for the package's
|
||||
* failure, {@code false} otherwise.
|
||||
*/
|
||||
private boolean mayPerformFactoryReset(@Nullable VersionedPackage failingPackage) {
|
||||
private boolean mayPerformReboot(@Nullable VersionedPackage failingPackage) {
|
||||
if (failingPackage == null) {
|
||||
return false;
|
||||
}
|
||||
if (shouldThrottleReboot()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isPersistentSystemApp(failingPackage.getPackageName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if Rescue Party is allowed to attempt a reboot or factory reset.
|
||||
* Will return {@code false} if a factory reset was already offered recently.
|
||||
*/
|
||||
private boolean shouldThrottleReboot() {
|
||||
Long lastResetTime = SystemProperties.getLong(PROP_LAST_FACTORY_RESET_TIME_MS, 0);
|
||||
long now = System.currentTimeMillis();
|
||||
return now < lastResetTime + FACTORY_RESET_THROTTLE_DURATION_MS;
|
||||
}
|
||||
|
||||
private boolean isPersistentSystemApp(@NonNull String packageName) {
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
try {
|
||||
|
||||
@@ -68,6 +68,7 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Test RescueParty.
|
||||
@@ -94,6 +95,9 @@ public class RescuePartyTest {
|
||||
"persist.device_config.configuration.disable_rescue_party";
|
||||
private static final String PROP_DISABLE_FACTORY_RESET_FLAG =
|
||||
"persist.device_config.configuration.disable_rescue_party_factory_reset";
|
||||
private static final String PROP_LAST_FACTORY_RESET_TIME_MS = "persist.sys.last_factory_reset";
|
||||
|
||||
private static final int THROTTLING_DURATION_MIN = 10;
|
||||
|
||||
private MockitoSession mSession;
|
||||
private HashMap<String, String> mSystemSettingsMap;
|
||||
@@ -458,6 +462,53 @@ public class RescuePartyTest {
|
||||
assertTrue(RescueParty.isFactoryResetPropertySet());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThrottlingOnBootFailures() {
|
||||
SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false));
|
||||
long now = System.currentTimeMillis();
|
||||
long beforeTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN - 1);
|
||||
SystemProperties.set(PROP_LAST_FACTORY_RESET_TIME_MS, Long.toString(beforeTimeout));
|
||||
for (int i = 1; i <= LEVEL_FACTORY_RESET; i++) {
|
||||
noteBoot(i);
|
||||
}
|
||||
assertFalse(RescueParty.isAttemptingFactoryReset());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThrottlingOnAppCrash() {
|
||||
SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false));
|
||||
long now = System.currentTimeMillis();
|
||||
long beforeTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN - 1);
|
||||
SystemProperties.set(PROP_LAST_FACTORY_RESET_TIME_MS, Long.toString(beforeTimeout));
|
||||
for (int i = 0; i <= LEVEL_FACTORY_RESET; i++) {
|
||||
noteAppCrash(i + 1, true);
|
||||
}
|
||||
assertFalse(RescueParty.isAttemptingFactoryReset());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotThrottlingAfterTimeoutOnBootFailures() {
|
||||
SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false));
|
||||
long now = System.currentTimeMillis();
|
||||
long afterTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN + 1);
|
||||
SystemProperties.set(PROP_LAST_FACTORY_RESET_TIME_MS, Long.toString(afterTimeout));
|
||||
for (int i = 1; i <= LEVEL_FACTORY_RESET; i++) {
|
||||
noteBoot(i);
|
||||
}
|
||||
assertTrue(RescueParty.isAttemptingFactoryReset());
|
||||
}
|
||||
@Test
|
||||
public void testNotThrottlingAfterTimeoutOnAppCrash() {
|
||||
SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false));
|
||||
long now = System.currentTimeMillis();
|
||||
long afterTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN + 1);
|
||||
SystemProperties.set(PROP_LAST_FACTORY_RESET_TIME_MS, Long.toString(afterTimeout));
|
||||
for (int i = 0; i <= LEVEL_FACTORY_RESET; i++) {
|
||||
noteAppCrash(i + 1, true);
|
||||
}
|
||||
assertTrue(RescueParty.isAttemptingFactoryReset());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNativeRescuePartyResets() {
|
||||
doReturn(true).when(() -> SettingsToPropertiesMapper.isNativeFlagsResetPerformed());
|
||||
|
||||
Reference in New Issue
Block a user