Merge "Add code OWNERS to test OWNERS for internal widgets"
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 0a5b91f..95fc7ec 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -8705,6 +8705,7 @@
public final class DeviceConfig {
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static void addOnPropertiesChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
+ method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean deleteProperty(@NonNull String, @NonNull String);
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static boolean getBoolean(@NonNull String, @NonNull String, boolean);
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static float getFloat(@NonNull String, @NonNull String, float);
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static int getInt(@NonNull String, @NonNull String, int);
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 2d40219..93c1c20 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -815,7 +815,7 @@
}
/**
- * Create a new property with the the provided name and value in the provided namespace, or
+ * Create a new property with the provided name and value in the provided namespace, or
* update the value of such a property if it already exists. The same name can exist in multiple
* namespaces and might have different values in any or all namespaces.
* <p>
@@ -865,6 +865,22 @@
}
/**
+ * Delete a property with the provided name and value in the provided namespace
+ *
+ * @param namespace The namespace containing the property to create or update.
+ * @param name The name of the property to create or update.
+ * @return True if the property was deleted or it did not exist in the first place.
+ * False if the storage implementation throws errors.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(WRITE_DEVICE_CONFIG)
+ public static boolean deleteProperty(@NonNull String namespace, @NonNull String name) {
+ ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
+ return Settings.Config.deleteString(contentResolver, namespace, name);
+ }
+
+ /**
* Reset properties to their default values by removing the underlying values.
* <p>
* The method accepts an optional namespace parameter. If provided, only properties set within
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4372f19..b7fcc03 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2829,6 +2829,7 @@
// for the fast path of retrieving settings.
private final String mCallGetCommand;
private final String mCallSetCommand;
+ private final String mCallDeleteCommand;
private final String mCallListCommand;
private final String mCallSetAllCommand;
@@ -2840,17 +2841,19 @@
private GenerationTracker mGenerationTracker;
<T extends NameValueTable> NameValueCache(Uri uri, String getCommand,
- String setCommand, ContentProviderHolder providerHolder, Class<T> callerClass) {
- this(uri, getCommand, setCommand, null, null, providerHolder,
+ String setCommand, String deleteCommand, ContentProviderHolder providerHolder,
+ Class<T> callerClass) {
+ this(uri, getCommand, setCommand, deleteCommand, null, null, providerHolder,
callerClass);
}
private <T extends NameValueTable> NameValueCache(Uri uri, String getCommand,
- String setCommand, String listCommand, String setAllCommand,
+ String setCommand, String deleteCommand, String listCommand, String setAllCommand,
ContentProviderHolder providerHolder, Class<T> callerClass) {
mUri = uri;
mCallGetCommand = getCommand;
mCallSetCommand = setCommand;
+ mCallDeleteCommand = deleteCommand;
mCallListCommand = listCommand;
mCallSetAllCommand = setAllCommand;
mProviderHolder = providerHolder;
@@ -2908,6 +2911,20 @@
}
}
+ public boolean deleteStringForUser(ContentResolver cr, String name, final int userHandle) {
+ try {
+ Bundle arg = new Bundle();
+ arg.putInt(CALL_METHOD_USER_KEY, userHandle);
+ IContentProvider cp = mProviderHolder.getProvider(cr);
+ cp.call(cr.getAttributionSource(),
+ mProviderHolder.mUri.getAuthority(), mCallDeleteCommand, name, arg);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Can't delete key " + name + " in " + mUri, e);
+ return false;
+ }
+ return true;
+ }
+
@UnsupportedAppUsage
public String getStringForUser(ContentResolver cr, String name, final int userHandle) {
// Check if the target settings key is readable. Reject if the caller is not system and
@@ -3370,6 +3387,7 @@
CONTENT_URI,
CALL_METHOD_GET_SYSTEM,
CALL_METHOD_PUT_SYSTEM,
+ CALL_METHOD_DELETE_SYSTEM,
sProviderHolder,
System.class);
@@ -5690,6 +5708,7 @@
CONTENT_URI,
CALL_METHOD_GET_SECURE,
CALL_METHOD_PUT_SECURE,
+ CALL_METHOD_DELETE_SECURE,
sProviderHolder,
Secure.class);
@@ -15159,6 +15178,7 @@
CONTENT_URI,
CALL_METHOD_GET_GLOBAL,
CALL_METHOD_PUT_GLOBAL,
+ CALL_METHOD_DELETE_GLOBAL,
sProviderHolder,
Global.class);
@@ -16391,6 +16411,7 @@
DeviceConfig.CONTENT_URI,
CALL_METHOD_GET_CONFIG,
CALL_METHOD_PUT_CONFIG,
+ CALL_METHOD_DELETE_CONFIG,
CALL_METHOD_LIST_CONFIG,
CALL_METHOD_SET_ALL_CONFIG,
sProviderHolder,
@@ -16500,6 +16521,26 @@
}
/**
+ * Delete a name/value pair from the database for the specified namespace.
+ *
+ * @param resolver to access the database with.
+ * @param namespace to delete the name/value pair from.
+ * @param name to delete.
+ * @return true if the value was deleted, false on database errors. If the name/value pair
+ * did not exist, return True.
+ *
+ * @see #resetToDefaults(ContentResolver, int, String)
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.WRITE_DEVICE_CONFIG)
+ static boolean deleteString(@NonNull ContentResolver resolver, @NonNull String namespace,
+ @NonNull String name) {
+ return sNameValueCache.deleteStringForUser(resolver,
+ createCompositeName(namespace, name), resolver.getUserId());
+ }
+
+ /**
* Reset the values to their defaults.
* <p>
* The method accepts an optional prefix parameter. If provided, only pairs with a name that
diff --git a/core/tests/coretests/src/android/provider/DeviceConfigTest.java b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
index fd39cde..8d4f29a 100644
--- a/core/tests/coretests/src/android/provider/DeviceConfigTest.java
+++ b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
@@ -827,4 +827,80 @@
return compositeName.equals(result.getString(Settings.NameValueTable.VALUE));
}
+ @Test
+ public void deleteProperty_nullNamespace() {
+ try {
+ DeviceConfig.deleteProperty(null, KEY);
+ Assert.fail("Null namespace should have resulted in an NPE.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void deleteProperty_nullName() {
+ try {
+ DeviceConfig.deleteProperty(NAMESPACE, null);
+ Assert.fail("Null name should have resulted in an NPE.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void deletePropertyString() {
+ final String value = "new_value";
+ final String default_value = "default";
+ DeviceConfig.setProperty(NAMESPACE, KEY, value, false);
+ DeviceConfig.deleteProperty(NAMESPACE, KEY);
+ final String result = DeviceConfig.getString(NAMESPACE, KEY, default_value);
+ assertThat(result).isEqualTo(default_value);
+ }
+
+ @Test
+ public void deletePropertyBoolean() {
+ final boolean value = true;
+ final boolean default_value = false;
+ DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false);
+ DeviceConfig.deleteProperty(NAMESPACE, KEY);
+ final boolean result = DeviceConfig.getBoolean(NAMESPACE, KEY, default_value);
+ assertThat(result).isEqualTo(default_value);
+ }
+
+ @Test
+ public void deletePropertyInt() {
+ final int value = 123;
+ final int default_value = 999;
+ DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false);
+ DeviceConfig.deleteProperty(NAMESPACE, KEY);
+ final int result = DeviceConfig.getInt(NAMESPACE, KEY, default_value);
+ assertThat(result).isEqualTo(default_value);
+ }
+
+ @Test
+ public void deletePropertyLong() {
+ final long value = 456789;
+ final long default_value = 123456;
+ DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false);
+ DeviceConfig.deleteProperty(NAMESPACE, KEY);
+ final long result = DeviceConfig.getLong(NAMESPACE, KEY, default_value);
+ assertThat(result).isEqualTo(default_value);
+ }
+
+ @Test
+ public void deletePropertyFloat() {
+ final float value = 456.789f;
+ final float default_value = 123.456f;
+ DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false);
+ DeviceConfig.deleteProperty(NAMESPACE, KEY);
+ final float result = DeviceConfig.getFloat(NAMESPACE, KEY, default_value);
+ assertThat(result).isEqualTo(default_value);
+ }
+
+ @Test
+ public void deleteProperty_empty() {
+ assertThat(DeviceConfig.deleteProperty(NAMESPACE, KEY)).isTrue();
+ final String result = DeviceConfig.getString(NAMESPACE, KEY, null);
+ assertThat(result).isNull();
+ }
}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index feee4a1..c03ed03 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -471,6 +471,9 @@
<!-- Permission needed for CTS test - MatchContentFrameRateTest -->
<uses-permission android:name="android.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE" />
+ <!-- Permissions needed for manual testing telephony time zone detector behavior -->
+ <uses-permission android:name="android.permission.SUGGEST_TELEPHONY_TIME_AND_ZONE" />
+
<!-- Permissions needed for CTS test - TimeManagerTest -->
<uses-permission android:name="android.permission.MANAGE_TIME_AND_ZONE_DETECTION" />
<uses-permission android:name="android.permission.SUGGEST_EXTERNAL_TIME" />
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index a6da4a6..35217db 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -2692,6 +2692,9 @@
return; // VPN has been shut down.
}
+ // Clear mInterface to prevent Ikev2VpnRunner being cleared when
+ // interfaceRemoved() is called.
+ mInterface = null;
// Without MOBIKE, we have no way to seamlessly migrate. Close on old
// (non-default) network, and start the new one.
resetIkeState();