Merge "Add device_config cmds for disabling syncs" into sc-dev
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user