Merge "Add device_config cmds for disabling syncs" into sc-dev

This commit is contained in:
Neil Fuller
2021-05-17 16:17:12 +00:00
committed by Android (Google) Code Review
8 changed files with 425 additions and 22 deletions

View File

@@ -31,6 +31,7 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.net.Uri;
import android.provider.Settings.Config.SyncDisabledMode;
import android.provider.Settings.ResetMode;
import android.util.ArrayMap;
import android.util.Log;
@@ -845,6 +846,37 @@ public final class DeviceConfig {
Settings.Config.resetToDefaults(contentResolver, resetMode, namespace);
}
/**
* Disables or re-enables bulk modifications ({@link #setProperties(Properties)}) to device
* config values. This is intended for use during tests to prevent a sync operation clearing
* config values, which could influence the outcome of the tests, i.e. by changing behavior.
*
* @param syncDisabledMode the mode to use, see {@link Settings.Config#SYNC_DISABLED_MODE_NONE},
* {@link Settings.Config#SYNC_DISABLED_MODE_PERSISTENT} and {@link
* Settings.Config#SYNC_DISABLED_MODE_UNTIL_REBOOT}
*
* @see #isSyncDisabled()
* @hide
*/
@RequiresPermission(WRITE_DEVICE_CONFIG)
public static void setSyncDisabled(@SyncDisabledMode int syncDisabledMode) {
ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
Settings.Config.setSyncDisabled(contentResolver, syncDisabledMode);
}
/**
* Returns the current state of sync disabling, {@code true} when disabled, {@code false}
* otherwise.
*
* @see #setSyncDisabled(int)
* @hide
*/
@RequiresPermission(WRITE_DEVICE_CONFIG)
public static boolean isSyncDisabled() {
ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
return Settings.Config.isSyncDisabled(contentResolver);
}
/**
* Add a listener for property changes.
* <p>

View File

@@ -267,8 +267,40 @@ public final class Settings {
/** @hide */
public static final String EXTRA_NETWORK_TEMPLATE = "network_template";
/**
* The return values for {@link Settings.Config#set}
* @hide
*/
@IntDef(prefix = "SET_ALL_RESULT_",
value = { SET_ALL_RESULT_FAILURE, SET_ALL_RESULT_SUCCESS, SET_ALL_RESULT_DISABLED })
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
public @interface SetAllResult {}
/**
* A return value for {@link #KEY_CONFIG_SET_ALL_RETURN}, indicates failure.
* @hide
*/
public static final int SET_ALL_RESULT_FAILURE = 0;
/**
* A return value for {@link #KEY_CONFIG_SET_ALL_RETURN}, indicates success.
* @hide
*/
public static final int SET_ALL_RESULT_SUCCESS = 1;
/**
* A return value for {@link #KEY_CONFIG_SET_ALL_RETURN}, indicates a set all is disabled.
* @hide
*/
public static final int SET_ALL_RESULT_DISABLED = 2;
/** @hide */
public static final String KEY_CONFIG_SET_RETURN = "config_set_return";
public static final String KEY_CONFIG_SET_ALL_RETURN = "config_set_all_return";
/** @hide */
public static final String KEY_CONFIG_IS_SYNC_DISABLED_RETURN =
"config_is_sync_disabled_return";
/**
* An int extra specifying a subscription ID.
@@ -2323,6 +2355,11 @@ public final class Settings {
*/
public static final String CALL_METHOD_PREFIX_KEY = "_prefix";
/**
* @hide - String argument extra to the fast-path call()-based requests
*/
public static final String CALL_METHOD_SYNC_DISABLED_MODE_KEY = "_disabled_mode";
/**
* @hide - RemoteCallback monitor callback argument extra to the fast-path call()-based requests
*/
@@ -2386,6 +2423,15 @@ public final class Settings {
/** @hide - Private call() method to reset to defaults the 'configuration' table */
public static final String CALL_METHOD_LIST_CONFIG = "LIST_config";
/** @hide - Private call() method to disable / re-enable syncs to the 'configuration' table */
public static final String CALL_METHOD_SET_SYNC_DISABLED_CONFIG = "SET_SYNC_DISABLED_config";
/**
* @hide - Private call() method to return whether syncs are disabled for the 'configuration'
* table
*/
public static final String CALL_METHOD_IS_SYNC_DISABLED_CONFIG = "IS_SYNC_DISABLED_config";
/** @hide - Private call() method to register monitor callback for 'configuration' table */
public static final String CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG =
"REGISTER_MONITOR_CALLBACK_config";
@@ -2762,11 +2808,11 @@ public final class Settings {
return true;
}
public boolean setStringsForPrefix(ContentResolver cr, String prefix,
public @SetAllResult int setStringsForPrefix(ContentResolver cr, String prefix,
HashMap<String, String> keyValues) {
if (mCallSetAllCommand == null) {
// This NameValueCache does not support atomically setting multiple flags
return false;
return SET_ALL_RESULT_FAILURE;
}
try {
Bundle args = new Bundle();
@@ -2776,10 +2822,10 @@ public final class Settings {
Bundle bundle = cp.call(cr.getAttributionSource(),
mProviderHolder.mUri.getAuthority(),
mCallSetAllCommand, null, args);
return bundle.getBoolean(KEY_CONFIG_SET_RETURN);
return bundle.getInt(KEY_CONFIG_SET_ALL_RETURN);
} catch (RemoteException e) {
// Not supported by the remote side
return false;
return SET_ALL_RESULT_FAILURE;
}
}
@@ -14199,6 +14245,15 @@ public final class Settings {
public static final String ARE_USER_DISABLED_HDR_FORMATS_ALLOWED =
"are_user_disabled_hdr_formats_allowed";
/**
* Whether or not syncs (bulk set operations) for {@link DeviceConfig} are disabled
* currently. The value is boolean (1 or 0). The value '1' means that {@link
* DeviceConfig#setProperties(DeviceConfig.Properties)} will return {@code false}.
*
* @hide
*/
public static final String DEVICE_CONFIG_SYNC_DISABLED = "device_config_sync_disabled";
/** @hide */ public static String zenModeToString(int mode) {
if (mode == ZEN_MODE_IMPORTANT_INTERRUPTIONS) return "ZEN_MODE_IMPORTANT_INTERRUPTIONS";
if (mode == ZEN_MODE_ALARMS) return "ZEN_MODE_ALARMS";
@@ -16033,6 +16088,39 @@ public final class Settings {
* @hide
*/
public static final class Config extends NameValueTable {
/**
* The modes that can be used when disabling syncs to the 'config' settings.
* @hide
*/
@IntDef(prefix = "DISABLE_SYNC_MODE_",
value = { SYNC_DISABLED_MODE_NONE, SYNC_DISABLED_MODE_PERSISTENT,
SYNC_DISABLED_MODE_UNTIL_REBOOT })
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
public @interface SyncDisabledMode {}
/**
* Sync is not not disabled.
*
* @hide
*/
public static final int SYNC_DISABLED_MODE_NONE = 0;
/**
* Disabling of Config bulk update / syncing is persistent, i.e. it survives a device
* reboot.
* @hide
*/
public static final int SYNC_DISABLED_MODE_PERSISTENT = 1;
/**
* Disabling of Config bulk update / syncing is not persistent, i.e. it will not survive a
* device reboot.
* @hide
*/
public static final int SYNC_DISABLED_MODE_UNTIL_REBOOT = 2;
private static final ContentProviderHolder sProviderHolder =
new ContentProviderHolder(DeviceConfig.CONTENT_URI);
@@ -16125,7 +16213,7 @@ public final class Settings {
* @param resolver to access the database with.
* @param namespace to which the names should be set.
* @param keyValues map of key names (without the prefix) to values.
* @return
* @return true if the name/value pairs were set, false if setting was blocked
*
* @hide
*/
@@ -16138,12 +16226,15 @@ public final class Settings {
compositeKeyValueMap.put(
createCompositeName(namespace, entry.getKey()), entry.getValue());
}
// If can't set given configuration that means it's bad
if (!sNameValueCache.setStringsForPrefix(resolver, createPrefix(namespace),
compositeKeyValueMap)) {
throw new DeviceConfig.BadConfigException();
int result = sNameValueCache.setStringsForPrefix(
resolver, createPrefix(namespace), compositeKeyValueMap);
if (result == SET_ALL_RESULT_SUCCESS) {
return true;
} else if (result == SET_ALL_RESULT_DISABLED) {
return false;
}
return true;
// If can't set given configuration that means it's bad
throw new DeviceConfig.BadConfigException();
}
/**
@@ -16178,6 +16269,50 @@ public final class Settings {
}
}
/**
* Bridge method between {@link DeviceConfig#setSyncDisabled(int)} and the
* {@link com.android.providers.settings.SettingsProvider} implementation.
*
* @hide
*/
@SuppressLint("AndroidFrameworkRequiresPermission")
@RequiresPermission(Manifest.permission.WRITE_DEVICE_CONFIG)
static void setSyncDisabled(
@NonNull ContentResolver resolver, @SyncDisabledMode int disableSyncMode) {
try {
Bundle args = new Bundle();
args.putInt(CALL_METHOD_SYNC_DISABLED_MODE_KEY, disableSyncMode);
IContentProvider cp = sProviderHolder.getProvider(resolver);
cp.call(resolver.getAttributionSource(),
sProviderHolder.mUri.getAuthority(), CALL_METHOD_SET_SYNC_DISABLED_CONFIG,
null, args);
} catch (RemoteException e) {
Log.w(TAG, "Can't set sync disabled " + DeviceConfig.CONTENT_URI, e);
}
}
/**
* Bridge method between {@link DeviceConfig#isSyncDisabled()} and the
* {@link com.android.providers.settings.SettingsProvider} implementation.
*
* @hide
*/
@SuppressLint("AndroidFrameworkRequiresPermission")
@RequiresPermission(Manifest.permission.WRITE_DEVICE_CONFIG)
static boolean isSyncDisabled(@NonNull ContentResolver resolver) {
try {
Bundle args = Bundle.EMPTY;
IContentProvider cp = sProviderHolder.getProvider(resolver);
Bundle bundle = cp.call(resolver.getAttributionSource(),
sProviderHolder.mUri.getAuthority(), CALL_METHOD_IS_SYNC_DISABLED_CONFIG,
null, args);
return bundle.getBoolean(KEY_CONFIG_IS_SYNC_DISABLED_RETURN);
} catch (RemoteException e) {
Log.w(TAG, "Can't query sync disabled " + DeviceConfig.CONTENT_URI, e);
}
return false;
}
/**
* Register callback for monitoring Config table.
*

View File

@@ -762,6 +762,62 @@ public class DeviceConfigTest {
// }
// }
@Test
public void syncDisabling() throws Exception {
Properties properties1 = new Properties.Builder(NAMESPACE)
.setString(KEY, VALUE)
.build();
Properties properties2 = new Properties.Builder(NAMESPACE)
.setString(KEY, VALUE2)
.build();
try {
// Ensure the device starts in a known state.
DeviceConfig.setSyncDisabled(Settings.Config.SYNC_DISABLED_MODE_NONE);
// Assert starting state.
assertThat(DeviceConfig.isSyncDisabled()).isFalse();
assertThat(DeviceConfig.setProperties(properties1)).isTrue();
assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
.isEqualTo(VALUE);
// Test disabled (persistent). Persistence is not actually tested, that would require
// a host test.
DeviceConfig.setSyncDisabled(Settings.Config.SYNC_DISABLED_MODE_PERSISTENT);
assertThat(DeviceConfig.isSyncDisabled()).isTrue();
assertThat(DeviceConfig.setProperties(properties2)).isFalse();
assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
.isEqualTo(VALUE);
// Return to not disabled.
DeviceConfig.setSyncDisabled(Settings.Config.SYNC_DISABLED_MODE_NONE);
assertThat(DeviceConfig.isSyncDisabled()).isFalse();
assertThat(DeviceConfig.setProperties(properties2)).isTrue();
assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
.isEqualTo(VALUE2);
// Test disabled (persistent). Absence of persistence is not actually tested, that would
// require a host test.
DeviceConfig.setSyncDisabled(Settings.Config.SYNC_DISABLED_MODE_UNTIL_REBOOT);
assertThat(DeviceConfig.isSyncDisabled()).isTrue();
assertThat(DeviceConfig.setProperties(properties1)).isFalse();
assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
.isEqualTo(VALUE2);
// Return to not disabled.
DeviceConfig.setSyncDisabled(Settings.Config.SYNC_DISABLED_MODE_NONE);
assertThat(DeviceConfig.isSyncDisabled()).isFalse();
assertThat(DeviceConfig.setProperties(properties1)).isTrue();
assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
.isEqualTo(VALUE);
} finally {
// Try to return to the default sync disabled state in case of failure.
DeviceConfig.setSyncDisabled(Settings.Config.SYNC_DISABLED_MODE_NONE);
// NAMESPACE will be cleared by cleanUp()
}
}
private static boolean deleteViaContentProvider(String namespace, String key) {
ContentResolver resolver = InstrumentationRegistry.getContext().getContentResolver();
String compositeName = namespace + "/" + key;

View File

@@ -96,7 +96,8 @@ public class NameValueCacheTest {
mCacheGenerationStore.set(0, ++mCurrentGeneration);
Bundle result = new Bundle();
result.putBoolean(Settings.KEY_CONFIG_SET_RETURN, true);
result.putInt(Settings.KEY_CONFIG_SET_ALL_RETURN,
Settings.SET_ALL_RESULT_SUCCESS);
return result;
});

View File

@@ -73,6 +73,7 @@ public class GlobalSettings {
Settings.Global.CUSTOM_BUGREPORT_HANDLER_USER,
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED,
Settings.Global.USER_DISABLED_HDR_FORMATS,
Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED
Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED,
Settings.Global.DEVICE_CONFIG_SYNC_DISABLED,
};
}

View File

@@ -139,6 +139,7 @@ public class GlobalSettingsValidators {
/* first= */Global.ONE_HANDED_KEYGUARD_SIDE_LEFT,
/* last= */Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT));
VALIDATORS.put(Global.DISABLE_WINDOW_BLURS, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.DEVICE_CONFIG_SYNC_DISABLED, BOOLEAN_VALIDATOR);
}
}

View File

@@ -16,7 +16,11 @@
package com.android.providers.settings;
import android.annotation.SystemApi;
import static android.provider.Settings.Config.SYNC_DISABLED_MODE_NONE;
import static android.provider.Settings.Config.SYNC_DISABLED_MODE_PERSISTENT;
import static android.provider.Settings.Config.SYNC_DISABLED_MODE_UNTIL_REBOOT;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.content.AttributionSource;
import android.content.IContentProvider;
@@ -41,10 +45,7 @@ import java.util.Map;
/**
* Receives shell commands from the command line related to device config flags, and dispatches them
* to the SettingsProvider.
*
* @hide
*/
@SystemApi
public final class DeviceConfigService extends Binder {
final SettingsProvider mProvider;
@@ -62,18 +63,20 @@ public final class DeviceConfigService extends Binder {
final SettingsProvider mProvider;
enum CommandVerb {
UNSPECIFIED,
GET,
PUT,
DELETE,
LIST,
RESET,
SET_SYNC_DISABLED_FOR_TESTS,
IS_SYNC_DISABLED_FOR_TESTS,
}
MyShellCommand(SettingsProvider provider) {
mProvider = provider;
}
@SuppressLint("AndroidFrameworkRequiresPermission")
@Override
public int onCommand(String cmd) {
if (cmd == null || "help".equals(cmd) || "-h".equals(cmd)) {
@@ -83,6 +86,7 @@ public final class DeviceConfigService extends Binder {
final PrintWriter perr = getErrPrintWriter();
boolean isValid = false;
CommandVerb verb;
if ("get".equalsIgnoreCase(cmd)) {
verb = CommandVerb.GET;
@@ -97,21 +101,33 @@ public final class DeviceConfigService extends Binder {
}
} else if ("reset".equalsIgnoreCase(cmd)) {
verb = CommandVerb.RESET;
} else if ("set_sync_disabled_for_tests".equalsIgnoreCase(cmd)) {
verb = CommandVerb.SET_SYNC_DISABLED_FOR_TESTS;
} else if ("is_sync_disabled_for_tests".equalsIgnoreCase(cmd)) {
verb = CommandVerb.IS_SYNC_DISABLED_FOR_TESTS;
if (peekNextArg() != null) {
perr.println("Bad arguments");
return -1;
}
isValid = true;
} else {
// invalid
perr.println("Invalid command: " + cmd);
return -1;
}
// Parse args for those commands that have them.
int disableSyncMode = -1;
int resetMode = -1;
boolean makeDefault = false;
String namespace = null;
String key = null;
String value = null;
String arg = null;
String arg;
while ((arg = getNextArg()) != null) {
if (verb == CommandVerb.RESET) {
if (resetMode == -1) {
// RESET 1st arg (required)
if ("untrusted_defaults".equalsIgnoreCase(arg)) {
resetMode = Settings.RESET_MODE_UNTRUSTED_DEFAULTS;
} else if ("untrusted_clear".equalsIgnoreCase(arg)) {
@@ -127,6 +143,7 @@ public final class DeviceConfigService extends Binder {
isValid = true;
}
} else {
// RESET 2nd arg (optional)
namespace = arg;
if (peekNextArg() == null) {
isValid = true;
@@ -136,7 +153,26 @@ public final class DeviceConfigService extends Binder {
return -1;
}
}
} else if (verb == CommandVerb.SET_SYNC_DISABLED_FOR_TESTS) {
if (disableSyncMode == -1) {
// DISABLE_SYNC_FOR_TESTS 1st arg (required)
if ("none".equalsIgnoreCase(arg)) {
disableSyncMode = SYNC_DISABLED_MODE_NONE;
} else if ("persistent".equalsIgnoreCase(arg)) {
disableSyncMode = SYNC_DISABLED_MODE_PERSISTENT;
} else if ("until_reboot".equalsIgnoreCase(arg)) {
disableSyncMode = SYNC_DISABLED_MODE_UNTIL_REBOOT;
} else {
// invalid
perr.println("Invalid sync disabled mode: " + arg);
return -1;
}
if (peekNextArg() == null) {
isValid = true;
}
}
} else if (namespace == null) {
// GET, PUT, DELETE, LIST 1st arg
namespace = arg;
if (verb == CommandVerb.LIST) {
if (peekNextArg() == null) {
@@ -148,8 +184,10 @@ public final class DeviceConfigService extends Binder {
}
}
} else if (key == null) {
// GET, PUT, DELETE 2nd arg
key = arg;
if ((verb == CommandVerb.GET || verb == CommandVerb.DELETE)) {
// GET, DELETE only have 2 args
if (peekNextArg() == null) {
isValid = true;
} else {
@@ -159,11 +197,13 @@ public final class DeviceConfigService extends Binder {
}
}
} else if (value == null) {
// PUT 3rd arg (required)
value = arg;
if (verb == CommandVerb.PUT && peekNextArg() == null) {
isValid = true;
}
} else if ("default".equalsIgnoreCase(arg)) {
// PUT 4th arg (optional)
makeDefault = true;
if (verb == CommandVerb.PUT && peekNextArg() == null) {
isValid = true;
@@ -211,6 +251,12 @@ public final class DeviceConfigService extends Binder {
case RESET:
DeviceConfig.resetToDefaults(resetMode, namespace);
break;
case SET_SYNC_DISABLED_FOR_TESTS:
DeviceConfig.setSyncDisabled(disableSyncMode);
break;
case IS_SYNC_DISABLED_FOR_TESTS:
pout.println(DeviceConfig.isSyncDisabled());
break;
default:
perr.println("Unspecified command");
return -1;
@@ -241,6 +287,16 @@ public final class DeviceConfigService extends Binder {
+ "trusted_defaults}");
pw.println(" NAMESPACE limits which flags are reset if provided, otherwise all "
+ "flags are reset");
pw.println(" set_sync_disabled_for_tests SYNC_DISABLED_MODE");
pw.println(" Modifies bulk property setting behavior for tests. When in one of the"
+ " disabled modes this ensures that config isn't overwritten.");
pw.println(" SYNC_DISABLED_MODE is one of:");
pw.println(" none: Sync is not disabled. A reboot may be required to restart"
+ " syncing.");
pw.println(" persistent: Sync is disabled, this state will survive a reboot.");
pw.println(" until_reboot: Sync is disabled until the next reboot.");
pw.println(" is_sync_disabled_for_tests");
pw.println(" Prints 'true' if sync is disabled, 'false' otherwise.");
}
private boolean delete(IContentProvider provider, String namespace, String key) {

View File

@@ -19,6 +19,12 @@ package com.android.providers.settings;
import static android.os.Process.ROOT_UID;
import static android.os.Process.SHELL_UID;
import static android.os.Process.SYSTEM_UID;
import static android.provider.Settings.Config.SYNC_DISABLED_MODE_NONE;
import static android.provider.Settings.Config.SYNC_DISABLED_MODE_PERSISTENT;
import static android.provider.Settings.Config.SYNC_DISABLED_MODE_UNTIL_REBOOT;
import static android.provider.Settings.SET_ALL_RESULT_DISABLED;
import static android.provider.Settings.SET_ALL_RESULT_FAILURE;
import static android.provider.Settings.SET_ALL_RESULT_SUCCESS;
import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_MAGNIFICATION_CONTROLLER;
import static android.provider.Settings.Secure.NOTIFICATION_BUBBLES;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY;
@@ -83,8 +89,10 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.provider.Settings.Config.SyncDisabledMode;
import android.provider.Settings.Global;
import android.provider.Settings.Secure;
import android.provider.Settings.SetAllResult;
import android.provider.settings.validators.SystemSettingsValidators;
import android.provider.settings.validators.Validator;
import android.text.TextUtils;
@@ -338,6 +346,9 @@ public class SettingsProvider extends ContentProvider {
// We have to call in the package manager with no lock held,
private volatile IPackageManager mPackageManager;
@GuardedBy("mLock")
private boolean mSyncConfigDisabledUntilReboot;
public static int makeKey(int type, int userId) {
return SettingsState.makeKey(type, userId);
}
@@ -446,11 +457,24 @@ public class SettingsProvider extends ContentProvider {
String prefix = getSettingPrefix(args);
Map<String, String> flags = getSettingFlags(args);
Bundle result = new Bundle();
result.putBoolean(Settings.KEY_CONFIG_SET_RETURN,
result.putInt(Settings.KEY_CONFIG_SET_ALL_RETURN,
setAllConfigSettings(prefix, flags));
return result;
}
case Settings.CALL_METHOD_SET_SYNC_DISABLED_CONFIG: {
final int mode = getSyncDisabledMode(args);
setSyncDisabledConfig(mode);
break;
}
case Settings.CALL_METHOD_IS_SYNC_DISABLED_CONFIG: {
Bundle result = new Bundle();
result.putBoolean(Settings.KEY_CONFIG_IS_SYNC_DISABLED_RETURN,
isSyncDisabledConfig());
return result;
}
case Settings.CALL_METHOD_RESET_CONFIG: {
final int mode = getResetModeEnforcingPermission(args);
String prefix = getSettingPrefix(args);
@@ -1105,7 +1129,8 @@ public class SettingsProvider extends ContentProvider {
MUTATION_OPERATION_INSERT, 0);
}
private boolean setAllConfigSettings(String prefix, Map<String, String> keyValues) {
private @SetAllResult int setAllConfigSettings(String prefix, Map<String, String> keyValues) {
if (DEBUG) {
Slog.v(LOG_TAG, "setAllConfigSettings for prefix: " + prefix);
}
@@ -1113,9 +1138,95 @@ public class SettingsProvider extends ContentProvider {
enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG);
synchronized (mLock) {
if (isSyncDisabledConfigLocked()) {
return SET_ALL_RESULT_DISABLED;
}
final int key = makeKey(SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM);
return mSettingsRegistry.setConfigSettingsLocked(key, prefix, keyValues,
boolean success = mSettingsRegistry.setConfigSettingsLocked(key, prefix, keyValues,
resolveCallingPackage());
return success ? SET_ALL_RESULT_SUCCESS : SET_ALL_RESULT_FAILURE;
}
}
private void setSyncDisabledConfig(@SyncDisabledMode int syncDisabledMode) {
if (DEBUG) {
Slog.v(LOG_TAG, "setSyncDisabledConfig(" + syncDisabledMode + ")");
}
enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG);
synchronized (mLock) {
setSyncDisabledConfigLocked(syncDisabledMode);
}
}
private boolean isSyncDisabledConfig() {
if (DEBUG) {
Slog.v(LOG_TAG, "isSyncDisabledConfig");
}
enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG);
synchronized (mLock) {
return isSyncDisabledConfigLocked();
}
}
@GuardedBy("mLock")
private void setSyncDisabledConfigLocked(@SyncDisabledMode int syncDisabledMode) {
boolean persistentValue;
boolean inMemoryValue;
if (syncDisabledMode == SYNC_DISABLED_MODE_NONE) {
persistentValue = false;
inMemoryValue = false;
} else if (syncDisabledMode == SYNC_DISABLED_MODE_PERSISTENT) {
persistentValue = true;
inMemoryValue = false;
} else if (syncDisabledMode == SYNC_DISABLED_MODE_UNTIL_REBOOT) {
persistentValue = false;
inMemoryValue = true;
} else {
throw new IllegalArgumentException(Integer.toString(syncDisabledMode));
}
mSyncConfigDisabledUntilReboot = inMemoryValue;
CallingIdentity callingIdentity = clearCallingIdentity();
try {
String globalSettingValue = persistentValue ? "1" : "0";
mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_GLOBAL,
UserHandle.USER_SYSTEM, Settings.Global.DEVICE_CONFIG_SYNC_DISABLED,
globalSettingValue, /*tag=*/null, /*makeDefault=*/false,
SettingsState.SYSTEM_PACKAGE_NAME, /*forceNotify=*/false,
/*criticalSettings=*/null, Settings.DEFAULT_OVERRIDEABLE_BY_RESTORE);
} finally {
restoreCallingIdentity(callingIdentity);
}
}
@GuardedBy("mLock")
private boolean isSyncDisabledConfigLocked() {
// Check the values used for both SYNC_DISABLED_MODE_PERSISTENT and
// SYNC_DISABLED_MODE_UNTIL_REBOOT.
// The SYNC_DISABLED_MODE_UNTIL_REBOOT value is cheap to check first.
if (mSyncConfigDisabledUntilReboot) {
return true;
}
// Now check the global setting used to implement SYNC_DISABLED_MODE_PERSISTENT.
CallingIdentity callingIdentity = clearCallingIdentity();
try {
Setting settingLocked = mSettingsRegistry.getSettingLocked(
SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM,
Global.DEVICE_CONFIG_SYNC_DISABLED);
if (settingLocked == null) {
return false;
}
String settingValue = settingLocked.getValue();
return settingValue != null && !"0".equals(settingValue);
} finally {
restoreCallingIdentity(callingIdentity);
}
}
@@ -2227,6 +2338,16 @@ public class SettingsProvider extends ContentProvider {
return (args != null) && args.getBoolean(Settings.CALL_METHOD_OVERRIDEABLE_BY_RESTORE_KEY);
}
private static int getSyncDisabledMode(Bundle args) {
final int mode = (args != null)
? args.getInt(Settings.CALL_METHOD_SYNC_DISABLED_MODE_KEY) : -1;
if (mode == SYNC_DISABLED_MODE_NONE || mode == SYNC_DISABLED_MODE_UNTIL_REBOOT
|| mode == SYNC_DISABLED_MODE_PERSISTENT) {
return mode;
}
throw new IllegalArgumentException("Invalid sync disabled mode: " + mode);
}
private static int getResetModeEnforcingPermission(Bundle args) {
final int mode = (args != null) ? args.getInt(Settings.CALL_METHOD_RESET_MODE_KEY) : 0;
switch (mode) {