From b3168101a2071baa718c5c5bba8fdd0c85370462 Mon Sep 17 00:00:00 2001 From: Songchun Fan Date: Tue, 27 Jun 2023 16:32:52 -0700 Subject: [PATCH] [SettingsProvider] new APIs to set and reset System settings to default As requested, adding system APIs to 1) set system settings values as default before a test and 2) reset the values to default after the test. BUG: 279083734 Test: atest android.provider.cts.settings.Settings_SystemTest#testResetToDefaults Change-Id: I675b6388cde78fcacf8b70e187dfefcb2a416fad --- core/api/system-current.txt | 2 + core/java/android/provider/Settings.java | 77 +++++++++++++++++++ .../providers/settings/SettingsProvider.java | 35 +++++++-- 3 files changed, 108 insertions(+), 6 deletions(-) diff --git a/core/api/system-current.txt b/core/api/system-current.txt index cf24f201315c3..58ceaccf8377c 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -11676,6 +11676,8 @@ package android.provider { public static final class Settings.System extends android.provider.Settings.NameValueTable { method @RequiresPermission(android.Manifest.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE) public static boolean putString(@NonNull android.content.ContentResolver, @NonNull String, @Nullable String, boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE) public static boolean putString(@NonNull android.content.ContentResolver, @NonNull String, @Nullable String, boolean, boolean); + method public static void resetToDefaults(@NonNull android.content.ContentResolver, @Nullable String); } public static final class SimPhonebookContract.SimRecords { diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 7a0556840275f..d69c484b69418 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2785,6 +2785,9 @@ public final class Settings { /** @hide - Private call() method to reset to defaults the 'configuration' table */ public static final String CALL_METHOD_DELETE_CONFIG = "DELETE_config"; + /** @hide - Private call() method to reset to defaults the 'system' table */ + public static final String CALL_METHOD_RESET_SYSTEM = "RESET_system"; + /** @hide - Private call() method to reset to defaults the 'secure' table */ public static final String CALL_METHOD_RESET_SECURE = "RESET_secure"; @@ -4000,6 +4003,26 @@ public final class Settings { overrideableByRestore); } + /** + * Store a name/value pair into the database. + * + * @param resolver to access the database with + * @param name to store + * @param value to associate with the name + * @param makeDefault whether to make the value the default one + * @param overrideableByRestore whether restore can override this value + * @return true if the value was set, false on database errors + * + * @hide + */ + @RequiresPermission(Manifest.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE) + @SystemApi + public static boolean putString(@NonNull ContentResolver resolver, @NonNull String name, + @Nullable String value, boolean makeDefault, boolean overrideableByRestore) { + return putStringForUser(resolver, name, value, /* tag= */ null, + makeDefault, resolver.getUserId(), overrideableByRestore); + } + /** @hide */ @UnsupportedAppUsage public static boolean putStringForUser(ContentResolver resolver, String name, String value, @@ -4034,6 +4057,60 @@ public final class Settings { userHandle, overrideableByRestore); } + /** + * Reset the settings to their defaults. This would reset only + * settings set by the caller's package. Think of it of a way to undo your own + * changes to the system settings. Passing in the optional tag will reset only + * settings changed by your package and associated with this tag. + * + * @param resolver Handle to the content resolver. + * @param tag Optional tag which should be associated with the settings to reset. + * + * @see #putString(ContentResolver, String, String, boolean, boolean) + * + * @hide + */ + @SystemApi + public static void resetToDefaults(@NonNull ContentResolver resolver, + @Nullable String tag) { + resetToDefaultsAsUser(resolver, tag, RESET_MODE_PACKAGE_DEFAULTS, + resolver.getUserId()); + } + + /** + * Reset the settings to their defaults for a given user with a specific mode. The + * optional tag argument is valid only for {@link #RESET_MODE_PACKAGE_DEFAULTS} + * allowing resetting the settings made by a package and associated with the tag. + * + * @param resolver Handle to the content resolver. + * @param tag Optional tag which should be associated with the settings to reset. + * @param mode The reset mode. + * @param userHandle The user for which to reset to defaults. + * + * @see #RESET_MODE_PACKAGE_DEFAULTS + * @see #RESET_MODE_UNTRUSTED_DEFAULTS + * @see #RESET_MODE_UNTRUSTED_CHANGES + * @see #RESET_MODE_TRUSTED_DEFAULTS + * + * @hide + */ + public static void resetToDefaultsAsUser(@NonNull ContentResolver resolver, + @Nullable String tag, @ResetMode int mode, @IntRange(from = 0) int userHandle) { + try { + Bundle arg = new Bundle(); + arg.putInt(CALL_METHOD_USER_KEY, userHandle); + if (tag != null) { + arg.putString(CALL_METHOD_TAG_KEY, tag); + } + arg.putInt(CALL_METHOD_RESET_MODE_KEY, mode); + IContentProvider cp = sProviderHolder.getProvider(resolver); + cp.call(resolver.getAttributionSource(), + sProviderHolder.mUri.getAuthority(), CALL_METHOD_RESET_SYSTEM, null, arg); + } catch (RemoteException e) { + Log.w(TAG, "Can't reset do defaults for " + CONTENT_URI, e); + } + } + /** * Construct the content URI for a particular name/value pair, * useful for monitoring changes with a ContentObserver. diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 1784e48401519..7a60507af2acd 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -520,6 +520,13 @@ public class SettingsProvider extends ContentProvider { break; } + case Settings.CALL_METHOD_RESET_SYSTEM: { + final int mode = getResetModeEnforcingPermission(args); + String tag = getSettingTag(args); + resetSystemSetting(requestingUserId, mode, tag); + break; + } + case Settings.CALL_METHOD_DELETE_CONFIG: { int rows = deleteConfigSetting(name) ? 1 : 0; Bundle result = new Bundle(); @@ -1875,8 +1882,8 @@ public class SettingsProvider extends ContentProvider { + requestingUserId + ")"); } - return mutateSystemSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT, - overrideableByRestore); + return mutateSystemSetting(name, value, /* tag= */ null, requestingUserId, + MUTATION_OPERATION_INSERT, /* mode= */ 0, overrideableByRestore); } private boolean deleteSystemSetting(String name, int requestingUserId) { @@ -1896,15 +1903,25 @@ public class SettingsProvider extends ContentProvider { return mutateSystemSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE); } + private void resetSystemSetting(int requestingUserId, int mode, String tag) { + if (DEBUG) { + Slog.v(LOG_TAG, "resetSystemSetting(" + requestingUserId + ", " + + mode + ", " + tag + ")"); + } + + mutateSystemSetting(null, null, tag, requestingUserId, MUTATION_OPERATION_RESET, mode, + false); + } + private boolean mutateSystemSetting(String name, String value, int runAsUserId, int operation) { // overrideableByRestore = false as by default settings values shouldn't be overrideable by // restore. - return mutateSystemSetting(name, value, runAsUserId, operation, - /* overrideableByRestore */ false); + return mutateSystemSetting(name, value, /* tag= */ null, runAsUserId, operation, + /* mode= */ 0, /* overrideableByRestore */ false); } - private boolean mutateSystemSetting(String name, String value, int runAsUserId, int operation, - boolean overrideableByRestore) { + private boolean mutateSystemSetting(String name, String value, String tag, int runAsUserId, + int operation, int mode, boolean overrideableByRestore) { final String callingPackage = getCallingPackage(); if (!hasWriteSecureSettingsPermission()) { // If the caller doesn't hold WRITE_SECURE_SETTINGS, we verify whether this @@ -1976,6 +1993,12 @@ public class SettingsProvider extends ContentProvider { owningUserId, name, value, null, false, callingPackage, false, null); } + + case MUTATION_OPERATION_RESET: { + mSettingsRegistry.resetSettingsLocked(SETTINGS_TYPE_SYSTEM, + UserHandle.USER_SYSTEM, callingPackage, mode, tag); + return true; + } } Slog.e(LOG_TAG, "Unknown operation code: " + operation); return false;