diff options
| author | 2019-03-05 11:27:28 +0000 | |
|---|---|---|
| committer | 2019-03-05 11:27:28 +0000 | |
| commit | 3f4b5d08abb38044672758d59fc21b07441b26c4 (patch) | |
| tree | bafaa82f01785a7d8e09d3bd748466b432b44766 | |
| parent | 60998a59e0b7ef65bf25f04ec81b007c4779c6aa (diff) | |
| parent | 93075f45e0c684bea71ef458730b9d68fc2b155f (diff) | |
Merge "Add handling of NativeRescueParty resets to RescueParty."
4 files changed, 78 insertions, 9 deletions
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java index 18c272202990..d26663520850 100644 --- a/services/core/java/com/android/server/RescueParty.java +++ b/services/core/java/com/android/server/RescueParty.java @@ -38,9 +38,11 @@ import android.util.StatsLog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; +import com.android.server.am.SettingsToPropertiesMapper; import com.android.server.utils.FlagNamespaceUtils; import java.io.File; +import java.util.Arrays; /** * Utilities to help rescue the system from crash loops. Callers are expected to @@ -158,6 +160,7 @@ public class RescueParty { * opportunity to reset any settings depending on our rescue level. */ public static void onSettingsProviderPublished(Context context) { + handleNativeRescuePartyResets(); executeRescueLevel(context); } @@ -176,6 +179,13 @@ public class RescueParty { return SystemClock.elapsedRealtime(); } + private static void handleNativeRescuePartyResets() { + if (SettingsToPropertiesMapper.isNativeFlagsResetPerformed()) { + FlagNamespaceUtils.resetDeviceConfig(Settings.RESET_MODE_TRUSTED_DEFAULTS, + Arrays.asList(SettingsToPropertiesMapper.getResetNativeCategories())); + } + } + /** * Escalate to the next rescue level. After incrementing the level you'll * probably want to call {@link #executeRescueLevel(Context)}. diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java index 5da1ce610079..194549f15ecf 100644 --- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java +++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java @@ -16,6 +16,7 @@ package com.android.server.am; +import android.annotation.NonNull; import android.content.ContentResolver; import android.database.ContentObserver; import android.net.Uri; @@ -167,7 +168,7 @@ public class SettingsToPropertiesMapper { * booting. * @return */ - public static String[] getResetNativeCategories() { + public static @NonNull String[] getResetNativeCategories() { if (!isNativeFlagsResetPerformed()) { return new String[0]; } diff --git a/services/core/java/com/android/server/utils/FlagNamespaceUtils.java b/services/core/java/com/android/server/utils/FlagNamespaceUtils.java index f26121eac939..f8c7447fc55d 100644 --- a/services/core/java/com/android/server/utils/FlagNamespaceUtils.java +++ b/services/core/java/com/android/server/utils/FlagNamespaceUtils.java @@ -19,6 +19,7 @@ package com.android.server.utils; import android.annotation.Nullable; import android.provider.DeviceConfig; +import com.android.internal.annotations.VisibleForTesting; import com.android.server.RescueParty; import java.util.ArrayList; @@ -41,20 +42,23 @@ public final class FlagNamespaceUtils { /** * Name of the special namespace in DeviceConfig table used for communicating resets. */ - private static final String NAMESPACE_RESCUE_PARTY = "rescue_party_namespace"; + @VisibleForTesting + public static final String NAMESPACE_RESCUE_PARTY = "rescue_party_namespace"; /** * Flag in the {@link DeviceConfig} in {@link #NAMESPACE_RESCUE_PARTY}, holding all known {@link * DeviceConfig} namespaces, as a {@link #DELIMITER} separated String. It's updated after the * first time flags are written to the new namespace in the {@link DeviceConfig}. */ - private static final String ALL_KNOWN_NAMESPACES_FLAG = "all_known_namespaces"; + @VisibleForTesting + public static final String ALL_KNOWN_NAMESPACES_FLAG = "all_known_namespaces"; /** * Flag in the {@link DeviceConfig} in {@link #NAMESPACE_RESCUE_PARTY} with integer counter * suffix added to it, holding {@link DeviceConfig} namespace value whose flags were recently * reset by the {@link RescueParty}. It's updated by {@link RescueParty} every time given * namespace flags are reset. */ - private static final String RESET_PLATFORM_PACKAGE_FLAG = "reset_platform_package"; + @VisibleForTesting + public static final String RESET_PLATFORM_PACKAGE_FLAG = "reset_platform_package"; private static final String DELIMITER = ":"; /** * Maximum value of the counter used in combination with {@link #RESET_PLATFORM_PACKAGE_FLAG} @@ -97,11 +101,25 @@ public final class FlagNamespaceUtils { * Reset all namespaces in DeviceConfig with consumed resetMode. */ public static void resetDeviceConfig(int resetMode) { - List<String> allKnownNamespaces = getAllKnownDeviceConfigNamespacesList(); - for (String namespace : allKnownNamespaces) { + resetDeviceConfig(resetMode, getAllKnownDeviceConfigNamespacesList()); + } + + /** + * Reset all consumed namespaces in DeviceConfig with consumed resetMode. + */ + public static void resetDeviceConfig(int resetMode, List<String> namespacesList) { + for (String namespace : namespacesList) { DeviceConfig.resetToDefaults(resetMode, namespace); } - addToKnownResetNamespaces(allKnownNamespaces); + addToKnownResetNamespaces(namespacesList); + } + + /** + * Resets known reset namespaces flag counter for tests only. + */ + @VisibleForTesting + public static void resetKnownResetNamespacesFlagCounterForTest() { + sKnownResetNamespacesFlagCounter = -1; } /** diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java index b13735cbf3b7..36825af527b1 100644 --- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java @@ -35,9 +35,12 @@ import android.content.Context; import android.os.RecoverySystem; import android.os.SystemProperties; import android.os.UserHandle; +import android.provider.DeviceConfig; import android.provider.Settings; import com.android.dx.mockito.inline.extended.ExtendedMockito; +import com.android.server.am.SettingsToPropertiesMapper; +import com.android.server.utils.FlagNamespaceUtils; import org.junit.After; import org.junit.Before; @@ -56,6 +59,10 @@ import java.util.HashMap; public class RescuePartyTest { private static final int PERSISTENT_APP_UID = 12; 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"; + private static final String[] FAKE_RESET_NATIVE_NAMESPACES = + {FAKE_NATIVE_NAMESPACE1, FAKE_NATIVE_NAMESPACE2}; private MockitoSession mSession; @@ -73,9 +80,11 @@ public class RescuePartyTest { ExtendedMockito.mockitoSession().initMocks( this) .strictness(Strictness.LENIENT) + .spyStatic(DeviceConfig.class) .spyStatic(SystemProperties.class) .spyStatic(Settings.Global.class) .spyStatic(Settings.Secure.class) + .spyStatic(SettingsToPropertiesMapper.class) .spyStatic(RecoverySystem.class) .spyStatic(RescueParty.class) .startMocking(); @@ -121,8 +130,17 @@ public class RescuePartyTest { } ).when(() -> SystemProperties.getLong(anyString(), anyLong())); + // Mock DeviceConfig + doAnswer((Answer<Boolean>) invocationOnMock -> true) + .when(() -> DeviceConfig.setProperty(anyString(), anyString(), anyString(), + anyBoolean())); + doAnswer((Answer<Void>) invocationOnMock -> null) + .when(() -> DeviceConfig.resetToDefaults(anyInt(), anyString())); + + doReturn(CURRENT_NETWORK_TIME_MILLIS).when(() -> RescueParty.getElapsedRealtime()); RescueParty.resetAllThresholds(); + FlagNamespaceUtils.resetKnownResetNamespacesFlagCounterForTest(); SystemProperties.set(RescueParty.PROP_RESCUE_LEVEL, Integer.toString(RescueParty.LEVEL_NONE)); @@ -278,10 +296,32 @@ public class RescuePartyTest { SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE)); } + @Test + public void testNativeRescuePartyResets() { + doReturn(true).when(() -> SettingsToPropertiesMapper.isNativeFlagsResetPerformed()); + doReturn(FAKE_RESET_NATIVE_NAMESPACES).when( + () -> SettingsToPropertiesMapper.getResetNativeCategories()); + + RescueParty.onSettingsProviderPublished(mMockContext); + + verify(() -> DeviceConfig.resetToDefaults(Settings.RESET_MODE_TRUSTED_DEFAULTS, + FAKE_NATIVE_NAMESPACE1)); + verify(() -> DeviceConfig.resetToDefaults(Settings.RESET_MODE_TRUSTED_DEFAULTS, + FAKE_NATIVE_NAMESPACE2)); + + ExtendedMockito.verify( + () -> DeviceConfig.setProperty(FlagNamespaceUtils.NAMESPACE_RESCUE_PARTY, + FlagNamespaceUtils.RESET_PLATFORM_PACKAGE_FLAG + 0, + FAKE_NATIVE_NAMESPACE1, /*makeDefault=*/true)); + ExtendedMockito.verify( + () -> DeviceConfig.setProperty(FlagNamespaceUtils.NAMESPACE_RESCUE_PARTY, + FlagNamespaceUtils.RESET_PLATFORM_PACKAGE_FLAG + 1, + FAKE_NATIVE_NAMESPACE2, /*makeDefault=*/true)); + } + private void verifySettingsResets(int resetMode) { verify(() -> Settings.Global.resetToDefaultsAsUser(mMockContentResolver, null, - resetMode, - UserHandle.USER_SYSTEM)); + resetMode, UserHandle.USER_SYSTEM)); verify(() -> Settings.Secure.resetToDefaultsAsUser(eq(mMockContentResolver), isNull(), eq(resetMode), anyInt())); } |