diff options
3 files changed, 386 insertions, 344 deletions
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java index dfd148dfc0ec..a4026eb151b9 100644 --- a/services/core/java/com/android/server/RescueParty.java +++ b/services/core/java/com/android/server/RescueParty.java @@ -241,12 +241,14 @@ public class RescueParty { * opportunity to reset any settings depending on our rescue level. */ public static void onSettingsProviderPublished(Context context) { - handleNativeRescuePartyResets(); - ContentResolver contentResolver = context.getContentResolver(); - DeviceConfig.setMonitorCallback( - contentResolver, - Executors.newSingleThreadExecutor(), - new RescuePartyMonitorCallback(context)); + if (!Flags.deprecateFlagsAndSettingsResets()) { + handleNativeRescuePartyResets(); + ContentResolver contentResolver = context.getContentResolver(); + DeviceConfig.setMonitorCallback( + contentResolver, + Executors.newSingleThreadExecutor(), + new RescuePartyMonitorCallback(context)); + } } @@ -256,75 +258,81 @@ public class RescueParty { * on modules of newer versions. */ public static void resetDeviceConfigForPackages(List<String> packageNames) { - if (packageNames == null) { - return; - } - Set<String> namespacesToReset = new ArraySet<String>(); - Iterator<String> it = packageNames.iterator(); - RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstanceIfCreated(); - // Get runtime package to namespace mapping if created. - if (rescuePartyObserver != null) { - while (it.hasNext()) { - String packageName = it.next(); - Set<String> runtimeAffectedNamespaces = - rescuePartyObserver.getAffectedNamespaceSet(packageName); - if (runtimeAffectedNamespaces != null) { - namespacesToReset.addAll(runtimeAffectedNamespaces); + if (!Flags.deprecateFlagsAndSettingsResets()) { + if (packageNames == null) { + return; + } + Set<String> namespacesToReset = new ArraySet<String>(); + Iterator<String> it = packageNames.iterator(); + RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstanceIfCreated(); + // Get runtime package to namespace mapping if created. + if (rescuePartyObserver != null) { + while (it.hasNext()) { + String packageName = it.next(); + Set<String> runtimeAffectedNamespaces = + rescuePartyObserver.getAffectedNamespaceSet(packageName); + if (runtimeAffectedNamespaces != null) { + namespacesToReset.addAll(runtimeAffectedNamespaces); + } } } - } - // Get preset package to namespace mapping if created. - Set<String> presetAffectedNamespaces = getPresetNamespacesForPackages( - packageNames); - if (presetAffectedNamespaces != null) { - namespacesToReset.addAll(presetAffectedNamespaces); - } + // Get preset package to namespace mapping if created. + Set<String> presetAffectedNamespaces = getPresetNamespacesForPackages( + packageNames); + if (presetAffectedNamespaces != null) { + namespacesToReset.addAll(presetAffectedNamespaces); + } - // Clear flags under the namespaces mapped to these packages. - // Using setProperties since DeviceConfig.resetToDefaults bans the current flag set. - Iterator<String> namespaceIt = namespacesToReset.iterator(); - while (namespaceIt.hasNext()) { - String namespaceToReset = namespaceIt.next(); - Properties properties = new Properties.Builder(namespaceToReset).build(); - try { - if (!DeviceConfig.setProperties(properties)) { - logCriticalInfo(Log.ERROR, "Failed to clear properties under " + // Clear flags under the namespaces mapped to these packages. + // Using setProperties since DeviceConfig.resetToDefaults bans the current flag set. + Iterator<String> namespaceIt = namespacesToReset.iterator(); + while (namespaceIt.hasNext()) { + String namespaceToReset = namespaceIt.next(); + Properties properties = new Properties.Builder(namespaceToReset).build(); + try { + if (!DeviceConfig.setProperties(properties)) { + logCriticalInfo(Log.ERROR, "Failed to clear properties under " + namespaceToReset + ". Running `device_config get_sync_disabled_for_tests` will confirm" + " if config-bulk-update is enabled."); + } + } catch (DeviceConfig.BadConfigException exception) { + logCriticalInfo(Log.WARN, "namespace " + namespaceToReset + + " is already banned, skip reset."); } - } catch (DeviceConfig.BadConfigException exception) { - logCriticalInfo(Log.WARN, "namespace " + namespaceToReset - + " is already banned, skip reset."); } } } private static Set<String> getPresetNamespacesForPackages(List<String> packageNames) { Set<String> resultSet = new ArraySet<String>(); - try { - String flagVal = DeviceConfig.getString(NAMESPACE_CONFIGURATION, - NAMESPACE_TO_PACKAGE_MAPPING_FLAG, ""); - String[] mappingEntries = flagVal.split(","); - for (int i = 0; i < mappingEntries.length; i++) { - if (TextUtils.isEmpty(mappingEntries[i])) { - continue; - } - String[] splittedEntry = mappingEntries[i].split(":"); - if (splittedEntry.length != 2) { - throw new RuntimeException("Invalid mapping entry: " + mappingEntries[i]); - } - String namespace = splittedEntry[0]; - String packageName = splittedEntry[1]; + if (!Flags.deprecateFlagsAndSettingsResets()) { + try { + String flagVal = DeviceConfig.getString(NAMESPACE_CONFIGURATION, + NAMESPACE_TO_PACKAGE_MAPPING_FLAG, ""); + String[] mappingEntries = flagVal.split(","); + for (int i = 0; i < mappingEntries.length; i++) { + if (TextUtils.isEmpty(mappingEntries[i])) { + continue; + } + String[] splitEntry = mappingEntries[i].split(":"); + if (splitEntry.length != 2) { + throw new RuntimeException("Invalid mapping entry: " + mappingEntries[i]); + } + String namespace = splitEntry[0]; + String packageName = splitEntry[1]; - if (packageNames.contains(packageName)) { - resultSet.add(namespace); + if (packageNames.contains(packageName)) { + resultSet.add(namespace); + } } + } catch (Exception e) { + resultSet.clear(); + Slog.e(TAG, "Failed to read preset package to namespaces mapping.", e); + } finally { + return resultSet; } - } catch (Exception e) { - resultSet.clear(); - Slog.e(TAG, "Failed to read preset package to namespaces mapping.", e); - } finally { + } else { return resultSet; } } @@ -342,43 +350,54 @@ public class RescueParty { } public void onNamespaceUpdate(@NonNull String updatedNamespace) { - startObservingPackages(mContext, updatedNamespace); + if (!Flags.deprecateFlagsAndSettingsResets()) { + startObservingPackages(mContext, updatedNamespace); + } } public void onDeviceConfigAccess(@NonNull String callingPackage, @NonNull String namespace) { - RescuePartyObserver.getInstance(mContext).recordDeviceConfigAccess( - callingPackage, - namespace); + + if (!Flags.deprecateFlagsAndSettingsResets()) { + RescuePartyObserver.getInstance(mContext).recordDeviceConfigAccess( + callingPackage, + namespace); + } } } private static void startObservingPackages(Context context, @NonNull String updatedNamespace) { - RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstance(context); - Set<String> callingPackages = rescuePartyObserver.getCallingPackagesSet(updatedNamespace); - if (callingPackages == null) { - return; + if (!Flags.deprecateFlagsAndSettingsResets()) { + RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstance(context); + Set<String> callingPackages = rescuePartyObserver.getCallingPackagesSet( + updatedNamespace); + if (callingPackages == null) { + return; + } + List<String> callingPackageList = new ArrayList<>(); + callingPackageList.addAll(callingPackages); + Slog.i(TAG, "Starting to observe: " + callingPackageList + ", updated namespace: " + + updatedNamespace); + PackageWatchdog.getInstance(context).startObservingHealth( + rescuePartyObserver, + callingPackageList, + DEFAULT_OBSERVING_DURATION_MS); } - List<String> callingPackageList = new ArrayList<>(); - callingPackageList.addAll(callingPackages); - Slog.i(TAG, "Starting to observe: " + callingPackageList + ", updated namespace: " - + updatedNamespace); - PackageWatchdog.getInstance(context).startObservingHealth( - rescuePartyObserver, - callingPackageList, - DEFAULT_OBSERVING_DURATION_MS); } private static void handleNativeRescuePartyResets() { - if (SettingsToPropertiesMapper.isNativeFlagsResetPerformed()) { - String[] resetNativeCategories = SettingsToPropertiesMapper.getResetNativeCategories(); - for (int i = 0; i < resetNativeCategories.length; i++) { - // Don't let RescueParty reset the namespace for RescueParty switches. - if (NAMESPACE_CONFIGURATION.equals(resetNativeCategories[i])) { - continue; + if (!Flags.deprecateFlagsAndSettingsResets()) { + if (SettingsToPropertiesMapper.isNativeFlagsResetPerformed()) { + String[] resetNativeCategories = + SettingsToPropertiesMapper.getResetNativeCategories(); + for (int i = 0; i < resetNativeCategories.length; i++) { + // Don't let RescueParty reset the namespace for RescueParty switches. + if (NAMESPACE_CONFIGURATION.equals(resetNativeCategories[i])) { + continue; + } + DeviceConfig.resetToDefaults(DEVICE_CONFIG_RESET_MODE, + resetNativeCategories[i]); } - DeviceConfig.resetToDefaults(DEVICE_CONFIG_RESET_MODE, - resetNativeCategories[i]); } } } @@ -400,6 +419,13 @@ public class RescueParty { } } + private static int getMaxRescueLevel() { + if (!SystemProperties.getBoolean(PROP_DISABLE_FACTORY_RESET_FLAG, false)) { + return Level.factoryReset(); + } + return Level.reboot(); + } + /** * Get the rescue level to perform if this is the n-th attempt at mitigating failure. * @@ -409,19 +435,30 @@ public class RescueParty { * @return the rescue level for the n-th mitigation attempt. */ private static int getRescueLevel(int mitigationCount, boolean mayPerformReboot) { - if (mitigationCount == 1) { - return LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS; - } else if (mitigationCount == 2) { - return LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES; - } else if (mitigationCount == 3) { - return LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS; - } else if (mitigationCount == 4) { - return Math.min(getMaxRescueLevel(mayPerformReboot), LEVEL_WARM_REBOOT); - } else if (mitigationCount >= 5) { - return Math.min(getMaxRescueLevel(mayPerformReboot), LEVEL_FACTORY_RESET); + if (!Flags.deprecateFlagsAndSettingsResets()) { + if (mitigationCount == 1) { + return LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS; + } else if (mitigationCount == 2) { + return LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES; + } else if (mitigationCount == 3) { + return LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS; + } else if (mitigationCount == 4) { + return Math.min(getMaxRescueLevel(mayPerformReboot), LEVEL_WARM_REBOOT); + } else if (mitigationCount >= 5) { + return Math.min(getMaxRescueLevel(mayPerformReboot), LEVEL_FACTORY_RESET); + } else { + Slog.w(TAG, "Expected positive mitigation count, was " + mitigationCount); + return LEVEL_NONE; + } } else { - Slog.w(TAG, "Expected positive mitigation count, was " + mitigationCount); - return LEVEL_NONE; + if (mitigationCount == 1) { + return Level.reboot(); + } else if (mitigationCount >= 2) { + return Math.min(getMaxRescueLevel(), Level.factoryReset()); + } else { + Slog.w(TAG, "Expected positive mitigation count, was " + mitigationCount); + return LEVEL_NONE; + } } } @@ -451,13 +488,13 @@ public class RescueParty { return Math.min(getMaxRescueLevel(mayPerformReboot), RESCUE_LEVEL_WARM_REBOOT); } else if (mitigationCount == 4) { return Math.min(getMaxRescueLevel(mayPerformReboot), - RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS); + RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS); } else if (mitigationCount == 5) { return Math.min(getMaxRescueLevel(mayPerformReboot), - RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES); + RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES); } else if (mitigationCount == 6) { return Math.min(getMaxRescueLevel(mayPerformReboot), - RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS); + RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS); } else if (mitigationCount >= 7) { return Math.min(getMaxRescueLevel(mayPerformReboot), RESCUE_LEVEL_FACTORY_RESET); } else { @@ -465,6 +502,22 @@ 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.). + * @return the rescue level for the n-th mitigation attempt. + */ + private static @RescueLevels int getRescueLevel(int mitigationCount) { + if (mitigationCount == 1) { + return Level.reboot(); + } else if (mitigationCount >= 2) { + return Math.min(getMaxRescueLevel(), Level.factoryReset()); + } else { + return Level.none(); + } + } + private static void executeRescueLevel(Context context, @Nullable String failedPackage, int level) { Slog.w(TAG, "Attempting rescue level " + levelToString(level)); @@ -537,13 +590,22 @@ public class RescueParty { executeWarmReboot(context, level, failedPackage); break; case RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS: - resetAllSettingsIfNecessary(context, Settings.RESET_MODE_UNTRUSTED_DEFAULTS, level); + if (!Flags.deprecateFlagsAndSettingsResets()) { + resetAllSettingsIfNecessary(context, Settings.RESET_MODE_UNTRUSTED_DEFAULTS, + level); + } break; case RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES: - resetAllSettingsIfNecessary(context, Settings.RESET_MODE_UNTRUSTED_CHANGES, level); + if (!Flags.deprecateFlagsAndSettingsResets()) { + resetAllSettingsIfNecessary(context, Settings.RESET_MODE_UNTRUSTED_CHANGES, + level); + } break; case RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS: - resetAllSettingsIfNecessary(context, Settings.RESET_MODE_TRUSTED_DEFAULTS, level); + if (!Flags.deprecateFlagsAndSettingsResets()) { + resetAllSettingsIfNecessary(context, Settings.RESET_MODE_TRUSTED_DEFAULTS, + level); + } break; case RESCUE_LEVEL_FACTORY_RESET: // Before the completion of Reboot, if any crash happens then PackageWatchdog @@ -560,6 +622,12 @@ public class RescueParty { private static void executeWarmReboot(Context context, int level, @Nullable String failedPackage) { + if (Flags.deprecateFlagsAndSettingsResets()) { + if (shouldThrottleReboot()) { + return; + } + } + // Request the reboot from a separate thread to avoid deadlock on PackageWatchdog // when device shutting down. setRebootProperty(true); @@ -579,6 +647,11 @@ public class RescueParty { private static void executeFactoryReset(Context context, int level, @Nullable String failedPackage) { + if (Flags.deprecateFlagsAndSettingsResets()) { + if (shouldThrottleReboot()) { + return; + } + } setFactoryResetProperty(true); long now = System.currentTimeMillis(); setLastFactoryResetTimeMs(now); @@ -655,30 +728,32 @@ public class RescueParty { private static void resetAllSettingsIfNecessary(Context context, int mode, int level) throws Exception { - // No need to reset Settings again if they are already reset in the current level once. - if (getMaxRescueLevelAttempted() >= level) { - return; - } - setMaxRescueLevelAttempted(level); - // Try our best to reset all settings possible, and once finished - // rethrow any exception that we encountered - Exception res = null; - final ContentResolver resolver = context.getContentResolver(); - try { - Settings.Global.resetToDefaultsAsUser(resolver, null, mode, - UserHandle.SYSTEM.getIdentifier()); - } catch (Exception e) { - res = new RuntimeException("Failed to reset global settings", e); - } - for (int userId : getAllUserIds()) { + if (!Flags.deprecateFlagsAndSettingsResets()) { + // No need to reset Settings again if they are already reset in the current level once. + if (getMaxRescueLevelAttempted() >= level) { + return; + } + setMaxRescueLevelAttempted(level); + // Try our best to reset all settings possible, and once finished + // rethrow any exception that we encountered + Exception res = null; + final ContentResolver resolver = context.getContentResolver(); try { - Settings.Secure.resetToDefaultsAsUser(resolver, null, mode, userId); + Settings.Global.resetToDefaultsAsUser(resolver, null, mode, + UserHandle.SYSTEM.getIdentifier()); } catch (Exception e) { - res = new RuntimeException("Failed to reset secure settings for " + userId, e); + res = new RuntimeException("Failed to reset global settings", e); + } + for (int userId : getAllUserIds()) { + try { + Settings.Secure.resetToDefaultsAsUser(resolver, null, mode, userId); + } catch (Exception e) { + res = new RuntimeException("Failed to reset secure settings for " + userId, e); + } + } + if (res != null) { + throw res; } - } - if (res != null) { - throw res; } } @@ -731,11 +806,15 @@ public class RescueParty { if (!isDisabled() && (failureReason == PackageWatchdog.FAILURE_REASON_APP_CRASH || failureReason == PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING)) { if (Flags.recoverabilityDetection()) { - return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount, - mayPerformReboot(failedPackage), failedPackage)); + if (!Flags.deprecateFlagsAndSettingsResets()) { + return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount, + mayPerformReboot(failedPackage), failedPackage)); + } else { + return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount)); + } } else { return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount, - mayPerformReboot(failedPackage))); + mayPerformReboot(failedPackage))); } } else { return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0; @@ -750,10 +829,17 @@ public class RescueParty { } if (failureReason == PackageWatchdog.FAILURE_REASON_APP_CRASH || failureReason == PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING) { - final int level = Flags.recoverabilityDetection() ? getRescueLevel(mitigationCount, - mayPerformReboot(failedPackage), failedPackage) - : getRescueLevel(mitigationCount, - mayPerformReboot(failedPackage)); + final int level; + if (Flags.recoverabilityDetection()) { + if (!Flags.deprecateFlagsAndSettingsResets()) { + level = getRescueLevel(mitigationCount, mayPerformReboot(failedPackage), + failedPackage); + } else { + level = getRescueLevel(mitigationCount); + } + } else { + level = getRescueLevel(mitigationCount, mayPerformReboot(failedPackage)); + } executeRescueLevel(mContext, failedPackage == null ? null : failedPackage.getPackageName(), level); return true; @@ -787,8 +873,12 @@ public class RescueParty { return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0; } if (Flags.recoverabilityDetection()) { - return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount, - true, /*failedPackage=*/ null)); + if (!Flags.deprecateFlagsAndSettingsResets()) { + return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount, + true, /*failedPackage=*/ null)); + } else { + return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount)); + } } else { return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount, true)); } @@ -800,9 +890,17 @@ public class RescueParty { return false; } boolean mayPerformReboot = !shouldThrottleReboot(); - final int level = Flags.recoverabilityDetection() ? getRescueLevel(mitigationCount, - mayPerformReboot, /*failedPackage=*/ null) - : getRescueLevel(mitigationCount, mayPerformReboot); + final int level; + if (Flags.recoverabilityDetection()) { + if (!Flags.deprecateFlagsAndSettingsResets()) { + level = getRescueLevel(mitigationCount, mayPerformReboot, + /*failedPackage=*/ null); + } else { + level = getRescueLevel(mitigationCount); + } + } else { + level = getRescueLevel(mitigationCount, mayPerformReboot); + } executeRescueLevel(mContext, /*failedPackage=*/ null, level); return true; } @@ -828,18 +926,6 @@ public class RescueParty { 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 = getLastFactoryResetTimeMs(); - long now = System.currentTimeMillis(); - long throttleDurationMin = SystemProperties.getLong(PROP_THROTTLE_DURATION_MIN_FLAG, - DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN); - return now < lastResetTime + TimeUnit.MINUTES.toMillis(throttleDurationMin); - } - private boolean isPersistentSystemApp(@NonNull String packageName) { PackageManager pm = mContext.getPackageManager(); try { @@ -852,20 +938,22 @@ public class RescueParty { private synchronized void recordDeviceConfigAccess(@NonNull String callingPackage, @NonNull String namespace) { - // Record it in calling packages to namespace map - Set<String> namespaceSet = mCallingPackageNamespaceSetMap.get(callingPackage); - if (namespaceSet == null) { - namespaceSet = new ArraySet<>(); - mCallingPackageNamespaceSetMap.put(callingPackage, namespaceSet); - } - namespaceSet.add(namespace); - // Record it in namespace to calling packages map - Set<String> callingPackageSet = mNamespaceCallingPackageSetMap.get(namespace); - if (callingPackageSet == null) { - callingPackageSet = new ArraySet<>(); + if (!Flags.deprecateFlagsAndSettingsResets()) { + // Record it in calling packages to namespace map + Set<String> namespaceSet = mCallingPackageNamespaceSetMap.get(callingPackage); + if (namespaceSet == null) { + namespaceSet = new ArraySet<>(); + mCallingPackageNamespaceSetMap.put(callingPackage, namespaceSet); + } + namespaceSet.add(namespace); + // Record it in namespace to calling packages map + Set<String> callingPackageSet = mNamespaceCallingPackageSetMap.get(namespace); + if (callingPackageSet == null) { + callingPackageSet = new ArraySet<>(); + } + callingPackageSet.add(callingPackage); + mNamespaceCallingPackageSetMap.put(namespace, callingPackageSet); } - callingPackageSet.add(callingPackage); - mNamespaceCallingPackageSetMap.put(namespace, callingPackageSet); } private synchronized Set<String> getAffectedNamespaceSet(String failedPackage) { @@ -881,6 +969,18 @@ public class RescueParty { } } + /** + * 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 static boolean shouldThrottleReboot() { + Long lastResetTime = getLastFactoryResetTimeMs(); + long now = System.currentTimeMillis(); + long throttleDurationMin = SystemProperties.getLong(PROP_THROTTLE_DURATION_MIN_FLAG, + DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN); + return now < lastResetTime + TimeUnit.MINUTES.toMillis(throttleDurationMin); + } + private static int[] getAllUserIds() { int systemUserId = UserHandle.SYSTEM.getIdentifier(); int[] userIds = { systemUserId }; @@ -919,6 +1019,22 @@ public class RescueParty { } } + private static class Level { + static int none() { + return Flags.recoverabilityDetection() ? RESCUE_LEVEL_NONE : LEVEL_NONE; + } + + static int reboot() { + return Flags.recoverabilityDetection() ? RESCUE_LEVEL_WARM_REBOOT : LEVEL_WARM_REBOOT; + } + + static int factoryReset() { + return Flags.recoverabilityDetection() + ? RESCUE_LEVEL_FACTORY_RESET + : LEVEL_FACTORY_RESET; + } + } + private static String levelToString(int level) { if (Flags.recoverabilityDetection()) { switch (level) { diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java index 8f39ffb3f53c..685ab3a9424f 100644 --- a/services/core/java/com/android/server/rollback/Rollback.java +++ b/services/core/java/com/android/server/rollback/Rollback.java @@ -16,6 +16,8 @@ package com.android.server.rollback; +import static android.crashrecovery.flags.Flags.deprecateFlagsAndSettingsResets; + import static com.android.server.rollback.RollbackManagerServiceImpl.sendFailure; import android.Manifest; @@ -623,8 +625,10 @@ class Rollback { parentSession.addChildSessionId(sessionId); } - // Clear flags. - RescueParty.resetDeviceConfigForPackages(packageNames); + if (!deprecateFlagsAndSettingsResets()) { + // Clear flags. + RescueParty.resetDeviceConfigForPackages(packageNames); + } Consumer<Intent> onResult = result -> { mHandler.post(() -> { diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java index 337789950a32..f2acbc31b008 100644 --- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java @@ -27,7 +27,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static com.android.server.RescueParty.DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN; import static com.android.server.RescueParty.LEVEL_FACTORY_RESET; -import static com.android.server.RescueParty.RESCUE_LEVEL_FACTORY_RESET; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -36,7 +35,6 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; import android.content.ContentResolver; import android.content.Context; @@ -47,6 +45,9 @@ import android.crashrecovery.flags.Flags; import android.os.RecoverySystem; import android.os.SystemProperties; import android.os.UserHandle; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.FlagsParameterization; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.DeviceConfig; import android.provider.Settings; @@ -61,6 +62,9 @@ import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; import org.mockito.Answers; import org.mockito.ArgumentCaptor; import org.mockito.Captor; @@ -77,10 +81,14 @@ import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; + /** * Test RescueParty. */ +@RunWith(Parameterized.class) public class RescuePartyTest { + @Rule + public SetFlagsRule mSetFlagsRule; private static final long CURRENT_NETWORK_TIME_MILLIS = 0L; private static final String FAKE_NATIVE_NAMESPACE1 = "native1"; private static final String FAKE_NATIVE_NAMESPACE2 = "native2"; @@ -103,9 +111,6 @@ public class RescuePartyTest { private static final String PROP_DISABLE_FACTORY_RESET_FLAG = "persist.device_config.configuration.disable_rescue_party_factory_reset"; - @Rule - public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); - private MockitoSession mSession; private HashMap<String, String> mSystemSettingsMap; private HashMap<String, String> mCrashRecoveryPropertiesMap; @@ -129,6 +134,17 @@ public class RescuePartyTest { @Captor private ArgumentCaptor<List<String>> mPackageListCaptor; + @Parameters(name = "{0}") + public static List<FlagsParameterization> getFlags() { + return FlagsParameterization.allCombinationsOf( + Flags.FLAG_RECOVERABILITY_DETECTION, + Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS); + } + + public RescuePartyTest(FlagsParameterization flags) { + mSetFlagsRule = new SetFlagsRule(flags); + } + @Before public void setUp() throws Exception { mSession = @@ -234,10 +250,10 @@ public class RescuePartyTest { } @Test - public void testBootLoopDetectionWithExecutionForAllRescueLevels() { + @DisableFlags({Flags.FLAG_RECOVERABILITY_DETECTION, + Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS}) + public void testBootLoop() { // this is old test where the flag needs to be disabled - mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); - RescueParty.onSettingsProviderPublished(mMockContext); verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver), any(Executor.class), @@ -264,10 +280,22 @@ public class RescuePartyTest { noteBoot(5); assertTrue(RescueParty.isFactoryResetPropertySet()); } + @Test + @EnableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS) + public void testBootLoopNoFlags() { + // this is old test where the flag needs to be disabled + noteBoot(1); + assertTrue(RescueParty.isRebootPropertySet()); + + setCrashRecoveryPropAttemptingReboot(false); + noteBoot(2); + assertTrue(RescueParty.isFactoryResetPropertySet()); + } @Test - public void testBootLoopDetectionWithExecutionForAllRescueLevelsRecoverabilityDetection() { - mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); + @EnableFlags(Flags.FLAG_RECOVERABILITY_DETECTION) + @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS) + public void testBootLoopRecoverability() { RescueParty.onSettingsProviderPublished(mMockContext); verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver), any(Executor.class), @@ -281,12 +309,14 @@ public class RescuePartyTest { final String[] expectedAllResetNamespaces = new String[]{NAMESPACE1, NAMESPACE2}; + noteBoot(1); noteBoot(2); assertTrue(RescueParty.isRebootPropertySet()); noteBoot(3); + verifyOnlySettingsReset(Settings.RESET_MODE_UNTRUSTED_DEFAULTS); noteBoot(4); @@ -301,10 +331,10 @@ public class RescuePartyTest { } @Test - public void testPersistentAppCrashDetectionWithExecutionForAllRescueLevels() { + @DisableFlags({Flags.FLAG_RECOVERABILITY_DETECTION, + Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS}) + public void testPersistentAppCrash() { // this is old test where the flag needs to be disabled - mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); - noteAppCrash(1, true); noteAppCrash(2, true); noteAppCrash(3, true); @@ -318,8 +348,21 @@ public class RescuePartyTest { } @Test - public void testPersistentAppCrashDetectionWithExecutionForAllRescueLevelsRecoverability() { - mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); + @EnableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS) + public void testPersistentAppCrashNoFlags() { + // this is old test where the flag needs to be disabled + noteAppCrash(1, true); + assertTrue(RescueParty.isRebootPropertySet()); + + setCrashRecoveryPropAttemptingReboot(false); + noteAppCrash(2, true); + assertTrue(RescueParty.isFactoryResetPropertySet()); + } + + @Test + @EnableFlags(Flags.FLAG_RECOVERABILITY_DETECTION) + @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS) + public void testPersistentAppCrashRecoverability() { RescueParty.onSettingsProviderPublished(mMockContext); verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver), any(Executor.class), @@ -357,10 +400,10 @@ public class RescuePartyTest { } @Test - public void testNonPersistentAppDoesntDoAnything() { + @DisableFlags({Flags.FLAG_RECOVERABILITY_DETECTION, + Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS}) + public void testNonPersistentApp() { // this is old test where the flag needs to be disabled - mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); - noteAppCrash(1, false); noteAppCrash(2, false); noteAppCrash(3, false); @@ -371,8 +414,9 @@ public class RescuePartyTest { } @Test + @EnableFlags(Flags.FLAG_RECOVERABILITY_DETECTION) + @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS) public void testNonPersistentAppOnlyPerformsFlagResetsRecoverabilityDetection() { - mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); RescueParty.onSettingsProviderPublished(mMockContext); verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver), any(Executor.class), @@ -408,60 +452,6 @@ public class RescuePartyTest { } @Test - public void testNonPersistentAppCrashDetectionWithScopedResets() { - // this is old test where the flag needs to be disabled - mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); - - RescueParty.onSettingsProviderPublished(mMockContext); - verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver), - any(Executor.class), - mMonitorCallbackCaptor.capture())); - - // Record DeviceConfig accesses - RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext); - DeviceConfig.MonitorCallback monitorCallback = mMonitorCallbackCaptor.getValue(); - monitorCallback.onDeviceConfigAccess(CALLING_PACKAGE1, NAMESPACE1); - monitorCallback.onDeviceConfigAccess(CALLING_PACKAGE1, NAMESPACE2); - monitorCallback.onDeviceConfigAccess(CALLING_PACKAGE2, NAMESPACE2); - monitorCallback.onDeviceConfigAccess(CALLING_PACKAGE2, NAMESPACE3); - - // Fake DeviceConfig value changes - monitorCallback.onNamespaceUpdate(NAMESPACE1); - verify(mMockPackageWatchdog).startObservingHealth(observer, - Arrays.asList(CALLING_PACKAGE1), RescueParty.DEFAULT_OBSERVING_DURATION_MS); - monitorCallback.onNamespaceUpdate(NAMESPACE2); - verify(mMockPackageWatchdog, times(2)).startObservingHealth(eq(observer), - mPackageListCaptor.capture(), - eq(RescueParty.DEFAULT_OBSERVING_DURATION_MS)); - monitorCallback.onNamespaceUpdate(NAMESPACE3); - verify(mMockPackageWatchdog).startObservingHealth(observer, - Arrays.asList(CALLING_PACKAGE2), RescueParty.DEFAULT_OBSERVING_DURATION_MS); - assertTrue(mPackageListCaptor.getValue().containsAll( - Arrays.asList(CALLING_PACKAGE1, CALLING_PACKAGE2))); - // Perform and verify scoped resets - final String[] expectedResetNamespaces = new String[]{NAMESPACE1, NAMESPACE2}; - final String[] expectedAllResetNamespaces = - new String[]{NAMESPACE1, NAMESPACE2, NAMESPACE3}; - HashMap<String, Integer> verifiedTimesMap = new HashMap<String, Integer>(); - observer.execute(new VersionedPackage( - CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_CRASH, 1); - - observer.execute(new VersionedPackage( - CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 2); - - observer.execute(new VersionedPackage( - CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 3); - - observer.execute(new VersionedPackage( - CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 4); - assertFalse(RescueParty.isRebootPropertySet()); - - observer.execute(new VersionedPackage( - CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 5); - assertFalse(RescueParty.isFactoryResetPropertySet()); - } - - @Test public void testIsRecoveryTriggeredReboot() { for (int i = 0; i < LEVEL_FACTORY_RESET; i++) { noteBoot(i + 1); @@ -474,19 +464,6 @@ public class RescuePartyTest { } @Test - public void testIsRecoveryTriggeredRebootRecoverabilityDetection() { - mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); - for (int i = 0; i < RESCUE_LEVEL_FACTORY_RESET; i++) { - noteBoot(i + 1); - } - assertFalse(RescueParty.isFactoryResetPropertySet()); - setCrashRecoveryPropAttemptingReboot(false); - noteBoot(RESCUE_LEVEL_FACTORY_RESET + 1); - assertTrue(RescueParty.isRecoveryTriggeredReboot()); - assertTrue(RescueParty.isFactoryResetPropertySet()); - } - - @Test public void testIsRecoveryTriggeredRebootOnlyAfterRebootCompleted() { for (int i = 0; i < LEVEL_FACTORY_RESET; i++) { noteBoot(i + 1); @@ -505,25 +482,6 @@ public class RescuePartyTest { } @Test - public void testIsRecoveryTriggeredRebootOnlyAfterRebootCompletedRecoverabilityDetection() { - mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); - for (int i = 0; i < RESCUE_LEVEL_FACTORY_RESET; i++) { - noteBoot(i + 1); - } - int mitigationCount = RESCUE_LEVEL_FACTORY_RESET + 1; - assertFalse(RescueParty.isFactoryResetPropertySet()); - noteBoot(mitigationCount++); - assertFalse(RescueParty.isFactoryResetPropertySet()); - noteBoot(mitigationCount++); - assertFalse(RescueParty.isFactoryResetPropertySet()); - noteBoot(mitigationCount++); - setCrashRecoveryPropAttemptingReboot(false); - noteBoot(mitigationCount + 1); - assertTrue(RescueParty.isRecoveryTriggeredReboot()); - assertTrue(RescueParty.isFactoryResetPropertySet()); - } - - @Test public void testThrottlingOnBootFailures() { setCrashRecoveryPropAttemptingReboot(false); long now = System.currentTimeMillis(); @@ -537,20 +495,6 @@ public class RescuePartyTest { } @Test - public void testThrottlingOnBootFailuresRecoverabilityDetection() { - mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); - setCrashRecoveryPropAttemptingReboot(false); - long now = System.currentTimeMillis(); - long beforeTimeout = now - TimeUnit.MINUTES.toMillis( - DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN - 1); - setCrashRecoveryPropLastFactoryReset(beforeTimeout); - for (int i = 1; i <= RESCUE_LEVEL_FACTORY_RESET; i++) { - noteBoot(i); - } - assertFalse(RescueParty.isRecoveryTriggeredReboot()); - } - - @Test public void testThrottlingOnAppCrash() { setCrashRecoveryPropAttemptingReboot(false); long now = System.currentTimeMillis(); @@ -564,20 +508,6 @@ public class RescuePartyTest { } @Test - public void testThrottlingOnAppCrashRecoverabilityDetection() { - mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); - setCrashRecoveryPropAttemptingReboot(false); - long now = System.currentTimeMillis(); - long beforeTimeout = now - TimeUnit.MINUTES.toMillis( - DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN - 1); - setCrashRecoveryPropLastFactoryReset(beforeTimeout); - for (int i = 0; i <= RESCUE_LEVEL_FACTORY_RESET; i++) { - noteAppCrash(i + 1, true); - } - assertFalse(RescueParty.isRecoveryTriggeredReboot()); - } - - @Test public void testNotThrottlingAfterTimeoutOnBootFailures() { setCrashRecoveryPropAttemptingReboot(false); long now = System.currentTimeMillis(); @@ -591,20 +521,6 @@ public class RescuePartyTest { } @Test - public void testNotThrottlingAfterTimeoutOnBootFailuresRecoverabilityDetection() { - mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); - setCrashRecoveryPropAttemptingReboot(false); - long now = System.currentTimeMillis(); - long afterTimeout = now - TimeUnit.MINUTES.toMillis( - DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN + 1); - setCrashRecoveryPropLastFactoryReset(afterTimeout); - for (int i = 1; i <= RESCUE_LEVEL_FACTORY_RESET; i++) { - noteBoot(i); - } - assertTrue(RescueParty.isRecoveryTriggeredReboot()); - } - - @Test public void testNotThrottlingAfterTimeoutOnAppCrash() { setCrashRecoveryPropAttemptingReboot(false); long now = System.currentTimeMillis(); @@ -618,20 +534,7 @@ public class RescuePartyTest { } @Test - public void testNotThrottlingAfterTimeoutOnAppCrashRecoverabilityDetection() { - mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); - setCrashRecoveryPropAttemptingReboot(false); - long now = System.currentTimeMillis(); - long afterTimeout = now - TimeUnit.MINUTES.toMillis( - DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN + 1); - setCrashRecoveryPropLastFactoryReset(afterTimeout); - for (int i = 0; i <= RESCUE_LEVEL_FACTORY_RESET; i++) { - noteAppCrash(i + 1, true); - } - assertTrue(RescueParty.isRecoveryTriggeredReboot()); - } - - @Test + @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS) public void testNativeRescuePartyResets() { doReturn(true).when(() -> SettingsToPropertiesMapper.isNativeFlagsResetPerformed()); doReturn(FAKE_RESET_NATIVE_NAMESPACES).when( @@ -647,7 +550,6 @@ public class RescuePartyTest { @Test public void testExplicitlyEnablingAndDisablingRescue() { - mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); SystemProperties.set(RescueParty.PROP_ENABLE_RESCUE, Boolean.toString(false)); SystemProperties.set(PROP_DISABLE_RESCUE, Boolean.toString(true)); assertEquals(RescuePartyObserver.getInstance(mMockContext).execute(sFailingPackage, @@ -660,7 +562,6 @@ public class RescuePartyTest { @Test public void testDisablingRescueByDeviceConfigFlag() { - mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); SystemProperties.set(RescueParty.PROP_ENABLE_RESCUE, Boolean.toString(false)); SystemProperties.set(PROP_DEVICE_CONFIG_DISABLE_FLAG, Boolean.toString(true)); @@ -686,24 +587,10 @@ public class RescuePartyTest { } @Test - public void testDisablingFactoryResetByDeviceConfigFlagRecoverabilityDetection() { - mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); - SystemProperties.set(PROP_DISABLE_FACTORY_RESET_FLAG, Boolean.toString(true)); - - for (int i = 0; i < RESCUE_LEVEL_FACTORY_RESET; i++) { - noteBoot(i + 1); - } - assertFalse(RescueParty.isFactoryResetPropertySet()); - - // Restore the property value initialized in SetUp() - SystemProperties.set(PROP_DISABLE_FACTORY_RESET_FLAG, ""); - } - - @Test + @DisableFlags({Flags.FLAG_RECOVERABILITY_DETECTION, + Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS}) public void testHealthCheckLevels() { // this is old test where the flag needs to be disabled - mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); - RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext); // Ensure that no action is taken for cases where the failure reason is unknown @@ -729,8 +616,9 @@ public class RescuePartyTest { } @Test + @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS) + @EnableFlags(Flags.FLAG_RECOVERABILITY_DETECTION) public void testHealthCheckLevelsRecoverabilityDetection() { - mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext); // Ensure that no action is taken for cases where the failure reason is unknown @@ -767,11 +655,31 @@ public class RescuePartyTest { PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 7), PackageHealthObserverImpact.USER_IMPACT_LEVEL_40); } + @Test + @EnableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS) + public void testHealthCheckLevelsNoFlags() { + // this is old test where the flag needs to be disabled + RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext); + + // Ensure that no action is taken for cases where the failure reason is unknown + assertEquals(observer.onHealthCheckFailed(null, PackageWatchdog.FAILURE_REASON_UNKNOWN, 1), + PackageHealthObserverImpact.USER_IMPACT_LEVEL_0); + + // Ensure the correct user impact is returned for each mitigation count. + assertEquals(observer.onHealthCheckFailed(null, + PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 1), + PackageHealthObserverImpact.USER_IMPACT_LEVEL_50); + assertEquals(observer.onHealthCheckFailed(null, + PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 2), + PackageHealthObserverImpact.USER_IMPACT_LEVEL_100); + } @Test + @DisableFlags({Flags.FLAG_RECOVERABILITY_DETECTION, + Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS}) public void testBootLoopLevels() { // this is old test where the flag needs to be disabled - mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); + RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext); @@ -784,8 +692,9 @@ public class RescuePartyTest { } @Test + @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS) + @EnableFlags(Flags.FLAG_RECOVERABILITY_DETECTION) public void testBootLoopLevelsRecoverabilityDetection() { - mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION); RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext); assertEquals(observer.onBootLoop(1), PackageHealthObserverImpact.USER_IMPACT_LEVEL_40); @@ -797,6 +706,16 @@ public class RescuePartyTest { } @Test + @EnableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS) + public void testBootLoopLevelsNoFlags() { + RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext); + + assertEquals(observer.onBootLoop(1), PackageHealthObserverImpact.USER_IMPACT_LEVEL_50); + assertEquals(observer.onBootLoop(2), PackageHealthObserverImpact.USER_IMPACT_LEVEL_100); + } + + @Test + @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS) public void testResetDeviceConfigForPackagesOnlyRuntimeMap() { RescueParty.onSettingsProviderPublished(mMockContext); verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver), @@ -827,6 +746,7 @@ public class RescuePartyTest { } @Test + @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS) public void testResetDeviceConfigForPackagesOnlyPresetMap() { RescueParty.onSettingsProviderPublished(mMockContext); verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver), @@ -835,7 +755,7 @@ public class RescuePartyTest { String presetMapping = NAMESPACE1 + ":" + CALLING_PACKAGE1 + "," + NAMESPACE2 + ":" + CALLING_PACKAGE2 + "," - + NAMESPACE3 + ":" + CALLING_PACKAGE1; + + NAMESPACE3 + ":" + CALLING_PACKAGE1; doReturn(presetMapping).when(() -> DeviceConfig.getString( eq(RescueParty.NAMESPACE_CONFIGURATION), eq(RescueParty.NAMESPACE_TO_PACKAGE_MAPPING_FLAG), @@ -848,6 +768,7 @@ public class RescuePartyTest { } @Test + @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS) public void testResetDeviceConfigForPackagesBothMaps() { RescueParty.onSettingsProviderPublished(mMockContext); verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver), @@ -884,6 +805,7 @@ public class RescuePartyTest { } @Test + @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS) public void testResetDeviceConfigNoExceptionWhenFlagMalformed() { RescueParty.onSettingsProviderPublished(mMockContext); verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver), |