Loading core/api/module-lib-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -529,6 +529,7 @@ package android.provider { public static final class Settings.Config extends android.provider.Settings.NameValueTable { method @RequiresPermission(android.Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS) public static void clearMonitorCallback(@NonNull android.content.ContentResolver); method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean deleteString(@NonNull String, @NonNull String); method @NonNull public static java.util.Map<java.lang.String,java.lang.String> getAllStrings(); method @Nullable @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getString(@NonNull String); method @NonNull @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static java.util.Map<java.lang.String,java.lang.String> getStrings(@NonNull String, @NonNull java.util.List<java.lang.String>); method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static int getSyncDisabledMode(); Loading core/java/android/provider/Settings.java +31 −1 Original line number Diff line number Diff line Loading @@ -2831,7 +2831,7 @@ public final class Settings { /** @hide - Private call() method to query the 'global' table */ public static final String CALL_METHOD_LIST_GLOBAL = "LIST_global"; /** @hide - Private call() method to reset to defaults the 'configuration' table */ /** @hide - Private call() method to query 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 */ Loading Loading @@ -19408,6 +19408,36 @@ public final class Settings { return getStrings(getContentResolver(), namespace, names); } /** * Return all stored flags. * * The keys take the form {@code namespace/flag}, and the values are the flag values. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @NonNull public static Map<String, String> getAllStrings() { HashMap<String, String> allFlags = new HashMap<String, String>(); try { ContentResolver resolver = getContentResolver(); Bundle arg = new Bundle(); arg.putInt(Settings.CALL_METHOD_USER_KEY, resolver.getUserId()); IContentProvider cp = sProviderHolder.getProvider(resolver); Bundle b = cp.call(resolver.getAttributionSource(), sProviderHolder.mUri.getAuthority(), CALL_METHOD_LIST_CONFIG, null, arg); if (b != null) { Map<String, String> flagsToValues = (HashMap) b.getSerializable(Settings.NameValueTable.VALUE, java.util.HashMap.class); allFlags.putAll(flagsToValues); } } catch (RemoteException e) { Log.w(TAG, "Can't query configuration table for " + CONTENT_URI, e); } return allFlags; } /** * Look up a list of names in the database, within the specified namespace. * core/tests/coretests/src/android/provider/DeviceConfigTest.java +84 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ public class DeviceConfigTest { private static final long WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS = 2000; // 2 sec private static final String DEFAULT_VALUE = "test_default_value"; private static final String NAMESPACE = "namespace1"; private static final String NAMESPACE2 = "namespace2"; private static final String KEY = "key1"; private static final String KEY2 = "key2"; private static final String KEY3 = "key3"; Loading @@ -67,6 +68,89 @@ public class DeviceConfigTest { deleteViaContentProvider(NAMESPACE, KEY); deleteViaContentProvider(NAMESPACE, KEY2); deleteViaContentProvider(NAMESPACE, KEY3); DeviceConfig.clearAllLocalOverrides(); } /** * Test that creating a sticky local override for a flag prevents further writes to that flag. */ @Test public void testAddStickyLocalOverridePreventsWrites() { DeviceConfig.setLocalOverride(NAMESPACE, KEY, VALUE); String key1Value = DeviceConfig.getProperty(NAMESPACE, KEY); assertThat(key1Value).isEqualTo(VALUE); DeviceConfig.setProperty(NAMESPACE, KEY, VALUE2, /* makeDefault= */ false); key1Value = DeviceConfig.getProperty(NAMESPACE, KEY); assertThat(key1Value).isEqualTo(VALUE); } /** * Test that when we locally override a flag, we can still write other flags. */ @Test public void testAddStickyLocalOverrideDoesNotAffectOtherFlags() { DeviceConfig.setLocalOverride(NAMESPACE, KEY, VALUE); DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE2, /* makeDefault= */ false); String key2Value = DeviceConfig.getProperty(NAMESPACE, KEY2); assertThat(key2Value).isEqualTo(VALUE2); } /** * Test that when we apply some overrides, they show up in the override list. */ @Test public void testGetStickyLocalOverrides() { DeviceConfig.setProperty(NAMESPACE, KEY, VALUE2, false); DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE, false); DeviceConfig.setLocalOverride(NAMESPACE, KEY, VALUE); DeviceConfig.setLocalOverride(NAMESPACE, KEY2, VALUE2); Map<String, Map<String, String>> expectedOverrides = new HashMap<>(); Map<String, String> expectedInnerMap = new HashMap<>(); expectedInnerMap.put(KEY, VALUE2); expectedInnerMap.put(KEY2, VALUE); expectedOverrides.put(NAMESPACE, expectedInnerMap); assertThat(DeviceConfig.getUnderlyingValuesForOverriddenFlags()) .isEqualTo(expectedOverrides); } /** * Test that when we clear all overrides, the override list is empty. */ @Test public void testClearStickyLocalOverrides() { DeviceConfig.setLocalOverride(NAMESPACE2, KEY, VALUE); DeviceConfig.setLocalOverride(NAMESPACE2, KEY2, VALUE2); DeviceConfig.clearAllLocalOverrides(); Map<String, Map<String, String>> overrides = DeviceConfig.getUnderlyingValuesForOverriddenFlags(); assertThat(overrides).isEmpty(); } /** * Test that when we clear a single override, it doesn't appear in the list. */ @Test public void testClearStickyLocalOverride() { DeviceConfig.setProperty(NAMESPACE, KEY, VALUE2, false); DeviceConfig.setProperty(NAMESPACE2, KEY2, VALUE, false); DeviceConfig.setLocalOverride(NAMESPACE, KEY, VALUE); DeviceConfig.setLocalOverride(NAMESPACE2, KEY2, VALUE2); DeviceConfig.clearLocalOverride(NAMESPACE, KEY); Map<String, Map<String, String>> expectedOverrides = new HashMap<>(); Map<String, String> expectedInnerMap = new HashMap<>(); expectedInnerMap.put(KEY2, VALUE); expectedOverrides.put(NAMESPACE2, expectedInnerMap); assertThat(DeviceConfig.getUnderlyingValuesForOverriddenFlags()) .isEqualTo(expectedOverrides); } @Test Loading Loading
core/api/module-lib-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -529,6 +529,7 @@ package android.provider { public static final class Settings.Config extends android.provider.Settings.NameValueTable { method @RequiresPermission(android.Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS) public static void clearMonitorCallback(@NonNull android.content.ContentResolver); method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean deleteString(@NonNull String, @NonNull String); method @NonNull public static java.util.Map<java.lang.String,java.lang.String> getAllStrings(); method @Nullable @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getString(@NonNull String); method @NonNull @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static java.util.Map<java.lang.String,java.lang.String> getStrings(@NonNull String, @NonNull java.util.List<java.lang.String>); method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static int getSyncDisabledMode(); Loading
core/java/android/provider/Settings.java +31 −1 Original line number Diff line number Diff line Loading @@ -2831,7 +2831,7 @@ public final class Settings { /** @hide - Private call() method to query the 'global' table */ public static final String CALL_METHOD_LIST_GLOBAL = "LIST_global"; /** @hide - Private call() method to reset to defaults the 'configuration' table */ /** @hide - Private call() method to query 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 */ Loading Loading @@ -19408,6 +19408,36 @@ public final class Settings { return getStrings(getContentResolver(), namespace, names); } /** * Return all stored flags. * * The keys take the form {@code namespace/flag}, and the values are the flag values. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @NonNull public static Map<String, String> getAllStrings() { HashMap<String, String> allFlags = new HashMap<String, String>(); try { ContentResolver resolver = getContentResolver(); Bundle arg = new Bundle(); arg.putInt(Settings.CALL_METHOD_USER_KEY, resolver.getUserId()); IContentProvider cp = sProviderHolder.getProvider(resolver); Bundle b = cp.call(resolver.getAttributionSource(), sProviderHolder.mUri.getAuthority(), CALL_METHOD_LIST_CONFIG, null, arg); if (b != null) { Map<String, String> flagsToValues = (HashMap) b.getSerializable(Settings.NameValueTable.VALUE, java.util.HashMap.class); allFlags.putAll(flagsToValues); } } catch (RemoteException e) { Log.w(TAG, "Can't query configuration table for " + CONTENT_URI, e); } return allFlags; } /** * Look up a list of names in the database, within the specified namespace. *
core/tests/coretests/src/android/provider/DeviceConfigTest.java +84 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ public class DeviceConfigTest { private static final long WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS = 2000; // 2 sec private static final String DEFAULT_VALUE = "test_default_value"; private static final String NAMESPACE = "namespace1"; private static final String NAMESPACE2 = "namespace2"; private static final String KEY = "key1"; private static final String KEY2 = "key2"; private static final String KEY3 = "key3"; Loading @@ -67,6 +68,89 @@ public class DeviceConfigTest { deleteViaContentProvider(NAMESPACE, KEY); deleteViaContentProvider(NAMESPACE, KEY2); deleteViaContentProvider(NAMESPACE, KEY3); DeviceConfig.clearAllLocalOverrides(); } /** * Test that creating a sticky local override for a flag prevents further writes to that flag. */ @Test public void testAddStickyLocalOverridePreventsWrites() { DeviceConfig.setLocalOverride(NAMESPACE, KEY, VALUE); String key1Value = DeviceConfig.getProperty(NAMESPACE, KEY); assertThat(key1Value).isEqualTo(VALUE); DeviceConfig.setProperty(NAMESPACE, KEY, VALUE2, /* makeDefault= */ false); key1Value = DeviceConfig.getProperty(NAMESPACE, KEY); assertThat(key1Value).isEqualTo(VALUE); } /** * Test that when we locally override a flag, we can still write other flags. */ @Test public void testAddStickyLocalOverrideDoesNotAffectOtherFlags() { DeviceConfig.setLocalOverride(NAMESPACE, KEY, VALUE); DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE2, /* makeDefault= */ false); String key2Value = DeviceConfig.getProperty(NAMESPACE, KEY2); assertThat(key2Value).isEqualTo(VALUE2); } /** * Test that when we apply some overrides, they show up in the override list. */ @Test public void testGetStickyLocalOverrides() { DeviceConfig.setProperty(NAMESPACE, KEY, VALUE2, false); DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE, false); DeviceConfig.setLocalOverride(NAMESPACE, KEY, VALUE); DeviceConfig.setLocalOverride(NAMESPACE, KEY2, VALUE2); Map<String, Map<String, String>> expectedOverrides = new HashMap<>(); Map<String, String> expectedInnerMap = new HashMap<>(); expectedInnerMap.put(KEY, VALUE2); expectedInnerMap.put(KEY2, VALUE); expectedOverrides.put(NAMESPACE, expectedInnerMap); assertThat(DeviceConfig.getUnderlyingValuesForOverriddenFlags()) .isEqualTo(expectedOverrides); } /** * Test that when we clear all overrides, the override list is empty. */ @Test public void testClearStickyLocalOverrides() { DeviceConfig.setLocalOverride(NAMESPACE2, KEY, VALUE); DeviceConfig.setLocalOverride(NAMESPACE2, KEY2, VALUE2); DeviceConfig.clearAllLocalOverrides(); Map<String, Map<String, String>> overrides = DeviceConfig.getUnderlyingValuesForOverriddenFlags(); assertThat(overrides).isEmpty(); } /** * Test that when we clear a single override, it doesn't appear in the list. */ @Test public void testClearStickyLocalOverride() { DeviceConfig.setProperty(NAMESPACE, KEY, VALUE2, false); DeviceConfig.setProperty(NAMESPACE2, KEY2, VALUE, false); DeviceConfig.setLocalOverride(NAMESPACE, KEY, VALUE); DeviceConfig.setLocalOverride(NAMESPACE2, KEY2, VALUE2); DeviceConfig.clearLocalOverride(NAMESPACE, KEY); Map<String, Map<String, String>> expectedOverrides = new HashMap<>(); Map<String, String> expectedInnerMap = new HashMap<>(); expectedInnerMap.put(KEY2, VALUE); expectedOverrides.put(NAMESPACE2, expectedInnerMap); assertThat(DeviceConfig.getUnderlyingValuesForOverriddenFlags()) .isEqualTo(expectedOverrides); } @Test Loading