Add validators for all Settings.Global settings that are backed up
And extend the unit test to fail if new ones are added without
a validator. Also fail to boot in that case.
Ref: go/android-p-backed-up-settings
Test: atest frameworks/base/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
Bug: 64988620
Change-Id: Ibd4a2bad0c6a1f2a9e1beec1a4ec8e6972fd86a4
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b685aef..ce06367 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -16,10 +16,12 @@
package android.provider;
+import static android.provider.SettingsValidators.ANY_STRING_VALIDATOR;
import static android.provider.SettingsValidators.BOOLEAN_VALIDATOR;
import static android.provider.SettingsValidators.COMPONENT_NAME_VALIDATOR;
import static android.provider.SettingsValidators.LENIENT_IP_ADDRESS_VALIDATOR;
import static android.provider.SettingsValidators.NON_NEGATIVE_INTEGER_VALIDATOR;
+import static android.provider.SettingsValidators.PACKAGE_NAME_VALIDATOR;
import static android.provider.SettingsValidators.URI_VALIDATOR;
import android.Manifest;
@@ -4279,6 +4281,8 @@
@Deprecated
public static final String BLUETOOTH_ON = Global.BLUETOOTH_ON;
+ private static final Validator BLUETOOTH_ON_VALIDATOR = BOOLEAN_VALIDATOR;
+
/**
* @deprecated Use {@link android.provider.Settings.Global#DATA_ROAMING} instead
*/
@@ -4356,6 +4360,8 @@
@Deprecated
public static final String USB_MASS_STORAGE_ENABLED = Global.USB_MASS_STORAGE_ENABLED;
+ private static final Validator USB_MASS_STORAGE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
/**
* @deprecated Use {@link android.provider.Settings.Global#USE_GOOGLE_MAIL} instead
*/
@@ -4385,6 +4391,9 @@
public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON =
Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON;
+ private static final Validator WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR =
+ BOOLEAN_VALIDATOR;
+
/**
* @deprecated Use
* {@link android.provider.Settings.Global#WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY} instead
@@ -5162,6 +5171,8 @@
@Deprecated
public static final String BUGREPORT_IN_POWER_MENU = "bugreport_in_power_menu";
+ private static final Validator BUGREPORT_IN_POWER_MENU_VALIDATOR = BOOLEAN_VALIDATOR;
+
/**
* @deprecated Use {@link android.provider.Settings.Global#ADB_ENABLED} instead
*/
@@ -5224,6 +5235,8 @@
@Deprecated
public static final String BLUETOOTH_ON = Global.BLUETOOTH_ON;
+ private static final Validator BLUETOOTH_ON_VALIDATOR = BOOLEAN_VALIDATOR;
+
/**
* @deprecated Use {@link android.provider.Settings.Global#DATA_ROAMING} instead
*/
@@ -5651,6 +5664,8 @@
@Deprecated
public static final String USB_MASS_STORAGE_ENABLED = Global.USB_MASS_STORAGE_ENABLED;
+ private static final Validator USB_MASS_STORAGE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
/**
* @deprecated Use {@link android.provider.Settings.Global#USE_GOOGLE_MAIL} instead
*/
@@ -6118,6 +6133,9 @@
public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON =
Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON;
+ private static final Validator WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR =
+ BOOLEAN_VALIDATOR;
+
/**
* @deprecated Use {@link android.provider.Settings.Global#WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY}
* instead.
@@ -7834,6 +7852,8 @@
*/
public static final String CHARGING_SOUNDS_ENABLED = "charging_sounds_enabled";
+ private static final Validator CHARGING_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
/**
* Whether we keep the device on while the device is plugged in.
* Supported values are:
@@ -7878,6 +7898,8 @@
*/
public static final String BUGREPORT_IN_POWER_MENU = "bugreport_in_power_menu";
+ private static final Validator BUGREPORT_IN_POWER_MENU_VALIDATOR = BOOLEAN_VALIDATOR;
+
/**
* Whether ADB is enabled.
*/
@@ -7901,6 +7923,8 @@
*/
public static final String BLUETOOTH_ON = "bluetooth_on";
+ private static final Validator BLUETOOTH_ON_VALIDATOR = BOOLEAN_VALIDATOR;
+
/**
* CDMA Cell Broadcast SMS
* 0 = CDMA Cell Broadcast SMS disabled
@@ -8519,6 +8543,8 @@
*/
public static final String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
+ private static final Validator USB_MASS_STORAGE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
/**
* If this setting is set (to anything), then all references
* to Gmail on the device must change to Google Mail.
@@ -8655,6 +8681,9 @@
public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON =
"wifi_networks_available_notification_on";
+ private static final Validator WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR =
+ BOOLEAN_VALIDATOR;
+
/**
* {@hide}
*/
@@ -8717,6 +8746,8 @@
*/
public static final String SOFT_AP_TIMEOUT_ENABLED = "soft_ap_timeout_enabled";
+ private static final Validator SOFT_AP_TIMEOUT_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
/**
* Value to specify if Wi-Fi Wakeup feature is enabled.
*
@@ -8726,6 +8757,8 @@
@SystemApi
public static final String WIFI_WAKEUP_ENABLED = "wifi_wakeup_enabled";
+ private static final Validator WIFI_WAKEUP_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
/**
* Value to specify if Wi-Fi Wakeup is available.
*
@@ -8772,6 +8805,9 @@
public static final String NETWORK_RECOMMENDATIONS_ENABLED =
"network_recommendations_enabled";
+ private static final Validator NETWORK_RECOMMENDATIONS_ENABLED_VALIDATOR =
+ new SettingsValidators.DiscreteValueValidator(new String[] {"-1", "0", "1"});
+
/**
* Which package name to use for network recommendations. If null, network recommendations
* will neither be requested nor accepted.
@@ -8795,6 +8831,13 @@
@TestApi
public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
+ private static final Validator USE_OPEN_WIFI_PACKAGE_VALIDATOR = new Validator() {
+ @Override
+ public boolean validate(String value) {
+ return (value == null) || PACKAGE_NAME_VALIDATOR.validate(value);
+ }
+ };
+
/**
* The number of milliseconds the {@link com.android.server.NetworkScoreService}
* will give a recommendation request to complete before returning a default response.
@@ -8874,6 +8917,9 @@
public static final String WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED =
"wifi_watchdog_poor_network_test_enabled";
+ private static final Validator WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED_VALIDATOR =
+ ANY_STRING_VALIDATOR;
+
/**
* Setting to turn on suspend optimizations at screen off on Wi-Fi. Enabled by default and
* needs to be set to 0 to disable it.
@@ -9409,11 +9455,16 @@
* @hide
*/
public static final String PRIVATE_DNS_MODE = "private_dns_mode";
+
+ private static final Validator PRIVATE_DNS_MODE_VALIDATOR = ANY_STRING_VALIDATOR;
+
/**
* @hide
*/
public static final String PRIVATE_DNS_SPECIFIER = "private_dns_specifier";
+ private static final Validator PRIVATE_DNS_SPECIFIER_VALIDATOR = ANY_STRING_VALIDATOR;
+
/** {@hide} */
public static final String
BLUETOOTH_HEADSET_PRIORITY_PREFIX = "bluetooth_headset_priority_";
@@ -9987,6 +10038,9 @@
*/
public static final String EMERGENCY_TONE = "emergency_tone";
+ private static final Validator EMERGENCY_TONE_VALIDATOR =
+ new SettingsValidators.DiscreteValueValidator(new String[] {"0", "1", "2"});
+
/**
* CDMA only settings
* Whether the auto retry is enabled. The value is
@@ -9995,6 +10049,8 @@
*/
public static final String CALL_AUTO_RETRY = "call_auto_retry";
+ private static final Validator CALL_AUTO_RETRY_VALIDATOR = BOOLEAN_VALIDATOR;
+
/**
* A setting that can be read whether the emergency affordance is currently needed.
* The value is a boolean (1 or 0).
@@ -10064,6 +10120,9 @@
*/
public static final String LOW_POWER_MODE_TRIGGER_LEVEL = "low_power_trigger_level";
+ private static final Validator LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR =
+ new SettingsValidators.InclusiveIntegerRangeValidator(0, 99);
+
/**
* If not 0, the activity manager will aggressively finish activities and
* processes as soon as they are no longer needed. If 0, the normal
@@ -10079,6 +10138,8 @@
*/
public static final String DOCK_AUDIO_MEDIA_ENABLED = "dock_audio_media_enabled";
+ private static final Validator DOCK_AUDIO_MEDIA_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
/**
* The surround sound formats AC3, DTS or IEC61937 are
* available for use if they are detected.
@@ -10125,6 +10186,9 @@
*/
public static final String ENCODED_SURROUND_OUTPUT = "encoded_surround_output";
+ private static final Validator ENCODED_SURROUND_OUTPUT_VALIDATOR =
+ new SettingsValidators.DiscreteValueValidator(new String[] {"0", "1", "2"});
+
/**
* Persisted safe headphone volume management state by AudioService
* @hide
@@ -10665,6 +10729,41 @@
};
/**
+ * All settings in {@link SETTINGS_TO_BACKUP} array *must* have a non-null validator,
+ * otherwise they won't be restored.
+ *
+ * @hide
+ */
+ public static final Map<String, Validator> VALIDATORS = new ArrayMap<>();
+ static {
+ VALIDATORS.put(BUGREPORT_IN_POWER_MENU, BUGREPORT_IN_POWER_MENU_VALIDATOR);
+ VALIDATORS.put(STAY_ON_WHILE_PLUGGED_IN, STAY_ON_WHILE_PLUGGED_IN_VALIDATOR);
+ VALIDATORS.put(AUTO_TIME, AUTO_TIME_VALIDATOR);
+ VALIDATORS.put(AUTO_TIME_ZONE, AUTO_TIME_ZONE_VALIDATOR);
+ VALIDATORS.put(POWER_SOUNDS_ENABLED, POWER_SOUNDS_ENABLED_VALIDATOR);
+ VALIDATORS.put(DOCK_SOUNDS_ENABLED, DOCK_SOUNDS_ENABLED_VALIDATOR);
+ VALIDATORS.put(CHARGING_SOUNDS_ENABLED, CHARGING_SOUNDS_ENABLED_VALIDATOR);
+ VALIDATORS.put(USB_MASS_STORAGE_ENABLED, USB_MASS_STORAGE_ENABLED_VALIDATOR);
+ VALIDATORS.put(NETWORK_RECOMMENDATIONS_ENABLED,
+ NETWORK_RECOMMENDATIONS_ENABLED_VALIDATOR);
+ VALIDATORS.put(WIFI_WAKEUP_ENABLED, WIFI_WAKEUP_ENABLED_VALIDATOR);
+ VALIDATORS.put(WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
+ WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR);
+ VALIDATORS.put(USE_OPEN_WIFI_PACKAGE, USE_OPEN_WIFI_PACKAGE_VALIDATOR);
+ VALIDATORS.put(WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED,
+ WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED_VALIDATOR);
+ VALIDATORS.put(EMERGENCY_TONE, EMERGENCY_TONE_VALIDATOR);
+ VALIDATORS.put(CALL_AUTO_RETRY, CALL_AUTO_RETRY_VALIDATOR);
+ VALIDATORS.put(DOCK_AUDIO_MEDIA_ENABLED, DOCK_AUDIO_MEDIA_ENABLED_VALIDATOR);
+ VALIDATORS.put(ENCODED_SURROUND_OUTPUT, ENCODED_SURROUND_OUTPUT_VALIDATOR);
+ VALIDATORS.put(LOW_POWER_MODE_TRIGGER_LEVEL, LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR);
+ VALIDATORS.put(BLUETOOTH_ON, BLUETOOTH_ON_VALIDATOR);
+ VALIDATORS.put(PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_VALIDATOR);
+ VALIDATORS.put(PRIVATE_DNS_SPECIFIER, PRIVATE_DNS_SPECIFIER_VALIDATOR);
+ VALIDATORS.put(SOFT_AP_TIMEOUT_ENABLED, SOFT_AP_TIMEOUT_ENABLED_VALIDATOR);
+ }
+
+ /**
* Global settings that shouldn't be persisted.
*
* @hide
diff --git a/core/java/android/provider/SettingsValidators.java b/core/java/android/provider/SettingsValidators.java
index af82452..22ef3b6 100644
--- a/core/java/android/provider/SettingsValidators.java
+++ b/core/java/android/provider/SettingsValidators.java
@@ -32,6 +32,13 @@
public static final Validator BOOLEAN_VALIDATOR =
new DiscreteValueValidator(new String[] {"0", "1"});
+ public static final Validator ANY_STRING_VALIDATOR = new Validator() {
+ @Override
+ public boolean validate(String value) {
+ return true;
+ }
+ };
+
public static final Validator NON_NEGATIVE_INTEGER_VALIDATOR = new Validator() {
@Override
public boolean validate(String value) {
@@ -62,6 +69,38 @@
}
};
+ public static final Validator PACKAGE_NAME_VALIDATOR = new Validator() {
+ @Override
+ public boolean validate(String value) {
+ return value != null && isStringPackageName(value);
+ }
+
+ private boolean isStringPackageName(String value) {
+ // The name may contain uppercase or lowercase letters ('A' through 'Z'), numbers,
+ // and underscores ('_'). However, individual package name parts may only
+ // start with letters.
+ // (https://developer.android.com/guide/topics/manifest/manifest-element.html#package)
+ String[] subparts = value.split(".");
+ boolean isValidPackageName = true;
+ for (String subpart : subparts) {
+ isValidPackageName |= isSubpartValidForPackageName(subpart);
+ if (!isValidPackageName) break;
+ }
+ return isValidPackageName;
+ }
+
+ private boolean isSubpartValidForPackageName(String subpart) {
+ if (subpart.length() == 0) return false;
+ boolean isValidSubpart = Character.isLetter(subpart.charAt(0));
+ for (int i = 1; i < subpart.length(); i++) {
+ isValidSubpart |= (Character.isLetterOrDigit(subpart.charAt(i))
+ || (subpart.charAt(i) == '_'));
+ if (!isValidSubpart) break;
+ }
+ return isValidSubpart;
+ }
+ };
+
public static final Validator LENIENT_IP_ADDRESS_VALIDATOR = new Validator() {
private static final int MAX_IPV6_LENGTH = 45;
diff --git a/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java b/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
index 6b613dd..00732b0 100644
--- a/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
@@ -19,12 +19,15 @@
import static org.junit.Assert.fail;
import android.platform.test.annotations.Presubmit;
+import android.provider.SettingsValidators.Validator;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Map;
+
/** Tests that ensure all backed up settings have non-null validators. */
@Presubmit
@RunWith(AndroidJUnit4.class)
@@ -33,18 +36,34 @@
@Test
public void ensureAllBackedUpSystemSettingsHaveValidators() {
+ String offenders = getOffenders(Settings.System.SETTINGS_TO_BACKUP,
+ Settings.System.VALIDATORS);
+
+ failIfOffendersPresent(offenders, "Settings.System");
+ }
+
+ @Test
+ public void ensureAllBackedUpGlobalSettingsHaveValidators() {
+ String offenders = getOffenders(Settings.Global.SETTINGS_TO_BACKUP,
+ Settings.Global.VALIDATORS);
+
+ failIfOffendersPresent(offenders, "Settings.Global");
+ }
+
+ private void failIfOffendersPresent(String offenders, String settingsType) {
+ if (offenders.length() > 0) {
+ fail("All " + settingsType + " settings that are backed up have to have a non-null"
+ + " validator, but those don't: " + offenders);
+ }
+ }
+
+ private String getOffenders(String[] settingsToBackup, Map<String, Validator> validators) {
StringBuilder offenders = new StringBuilder();
- for (String setting : Settings.System.SETTINGS_TO_BACKUP) {
- if (Settings.System.VALIDATORS.get(setting) == null) {
+ for (String setting : settingsToBackup) {
+ if (validators.get(setting) == null) {
offenders.append(setting).append(" ");
}
}
-
- // if there're any offenders fail the test and report them
- String offendersStr = offenders.toString();
- if (offendersStr.length() > 0) {
- fail("All Settings.System settings that are backed up have to have a non-null"
- + " validator, but those don't: " + offendersStr);
- }
+ return offenders.toString();
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 01e0d52..9ee205f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -301,6 +301,7 @@
// fail to boot if there're any backed up settings that don't have a non-null validator
ensureAllBackedUpSystemSettingsHaveValidators();
+ ensureAllBackedUpGlobalSettingsHaveValidators();
synchronized (mLock) {
mUserManager = UserManager.get(getContext());
@@ -320,18 +321,35 @@
}
private void ensureAllBackedUpSystemSettingsHaveValidators() {
+ String offenders = getOffenders(Settings.System.SETTINGS_TO_BACKUP,
+ Settings.System.VALIDATORS);
+
+ failToBootIfOffendersPresent(offenders, "Settings.System");
+ }
+
+ private void ensureAllBackedUpGlobalSettingsHaveValidators() {
+ String offenders = getOffenders(Settings.Global.SETTINGS_TO_BACKUP,
+ Settings.Global.VALIDATORS);
+
+ failToBootIfOffendersPresent(offenders, "Settings.Global");
+ }
+
+ private void failToBootIfOffendersPresent(String offenders, String settingsType) {
+ if (offenders.length() > 0) {
+ throw new RuntimeException("All " + settingsType + " settings that are backed up"
+ + " have to have a non-null validator, but those don't: " + offenders);
+ }
+ }
+
+ private String getOffenders(String[] settingsToBackup, Map<String,
+ SettingsValidators.Validator> validators) {
StringBuilder offenders = new StringBuilder();
- for (String setting : Settings.System.SETTINGS_TO_BACKUP) {
- if (Settings.System.VALIDATORS.get(setting) == null) {
+ for (String setting : settingsToBackup) {
+ if (validators.get(setting) == null) {
offenders.append(setting).append(" ");
}
}
-
- String offendersStr = offenders.toString();
- if (offendersStr.length() > 0) {
- throw new RuntimeException("All Settings.System settings that are backed up must"
- + " have a non-null validator, but those don't: " + offendersStr);
- }
+ return offenders.toString();
}
@Override