Move validators out to their own package

Move the settings validators out to their own package so we can
reason about them more easily. This is the first step in a journey
which will end up with us not initialising them inside the Settings
object which, in turn, will reduce boot times.

Bug: 139449903
Test: atest RunBackupFrameworksServicesRoboTests CtsBackupTestCases CtsBackupHostTestCases GtsBackupTestCases GtsBackupHostTestCases
Change-Id: I611d9855fa91bbbbb6b0996e8ed6d765dca74717
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 213a125..bfafa2f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -16,16 +16,19 @@
 
 package android.provider;
 
-import static android.provider.SettingsValidators.ANY_INTEGER_VALIDATOR;
-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.LOCALE_VALIDATOR;
-import static android.provider.SettingsValidators.NON_NEGATIVE_INTEGER_VALIDATOR;
-import static android.provider.SettingsValidators.NULLABLE_COMPONENT_NAME_VALIDATOR;
-import static android.provider.SettingsValidators.PACKAGE_NAME_VALIDATOR;
-import static android.provider.SettingsValidators.URI_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.ANY_INTEGER_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.ANY_STRING_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.BOOLEAN_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.COMPONENT_NAME_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.JSON_OBJECT_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.LENIENT_IP_ADDRESS_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.LOCALE_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.NON_NEGATIVE_INTEGER_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.NULLABLE_COMPONENT_NAME_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.PACKAGE_NAME_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.TILE_LIST_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.TTS_LIST_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.URI_VALIDATOR;
 
 import android.Manifest;
 import android.annotation.IntDef;
@@ -80,7 +83,12 @@
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
 import android.os.UserHandle;
-import android.provider.SettingsValidators.Validator;
+import android.provider.settings.validators.ComponentNameListValidator;
+import android.provider.settings.validators.DiscreteValueValidator;
+import android.provider.settings.validators.InclusiveFloatRangeValidator;
+import android.provider.settings.validators.InclusiveIntegerRangeValidator;
+import android.provider.settings.validators.PackageNameListValidator;
+import android.provider.settings.validators.Validator;
 import android.speech.tts.TextToSpeech;
 import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
@@ -3149,7 +3157,7 @@
         public static final String END_BUTTON_BEHAVIOR = "end_button_behavior";
 
         private static final Validator END_BUTTON_BEHAVIOR_VALIDATOR =
-                new SettingsValidators.InclusiveIntegerRangeValidator(0, 3);
+                new InclusiveIntegerRangeValidator(0, 3);
 
         /**
          * END_BUTTON_BEHAVIOR value for "go home".
@@ -3351,7 +3359,7 @@
             "bluetooth_discoverability";
 
         private static final Validator BLUETOOTH_DISCOVERABILITY_VALIDATOR =
-                new SettingsValidators.InclusiveIntegerRangeValidator(0, 2);
+                new InclusiveIntegerRangeValidator(0, 2);
 
         /**
          * Bluetooth discoverability timeout.  If this value is nonzero, then
@@ -3495,7 +3503,7 @@
         public static final String PEAK_REFRESH_RATE = "peak_refresh_rate";
 
         private static final Validator PEAK_REFRESH_RATE_VALIDATOR =
-                new SettingsValidators.InclusiveFloatRangeValidator(24f, Float.MAX_VALUE);
+                new InclusiveFloatRangeValidator(24f, Float.MAX_VALUE);
 
         /**
          * The amount of time in milliseconds before the device goes to sleep or begins
@@ -3524,7 +3532,7 @@
         public static final String SCREEN_BRIGHTNESS_FOR_VR = "screen_brightness_for_vr";
 
         private static final Validator SCREEN_BRIGHTNESS_FOR_VR_VALIDATOR =
-                new SettingsValidators.InclusiveIntegerRangeValidator(0, 255);
+                new InclusiveIntegerRangeValidator(0, 255);
 
         /**
          * Control whether to enable automatic brightness mode.
@@ -3542,7 +3550,7 @@
         public static final String SCREEN_AUTO_BRIGHTNESS_ADJ = "screen_auto_brightness_adj";
 
         private static final Validator SCREEN_AUTO_BRIGHTNESS_ADJ_VALIDATOR =
-                new SettingsValidators.InclusiveFloatRangeValidator(-1, 1);
+                new InclusiveFloatRangeValidator(-1, 1);
 
         /**
          * SCREEN_BRIGHTNESS_MODE value for manual mode.
@@ -3676,7 +3684,7 @@
                 "haptic_feedback_intensity";
 
         private static final Validator VIBRATION_INTENSITY_VALIDATOR =
-                new SettingsValidators.InclusiveIntegerRangeValidator(0, 3);
+                new InclusiveIntegerRangeValidator(0, 3);
 
         /**
          * Ringer volume. This is used internally, changing this value will not
@@ -3766,7 +3774,7 @@
         public static final String MASTER_BALANCE = "master_balance";
 
         private static final Validator MASTER_BALANCE_VALIDATOR =
-                new SettingsValidators.InclusiveFloatRangeValidator(-1.f, 1.f);
+                new InclusiveFloatRangeValidator(-1.f, 1.f);
 
         /**
          * Whether the notifications should use the ring volume (value of 1) or
@@ -4004,7 +4012,7 @@
 
         /** @hide */
         public static final Validator TIME_12_24_VALIDATOR =
-                new SettingsValidators.DiscreteValueValidator(new String[] {"12", "24", null});
+                new DiscreteValueValidator(new String[] {"12", "24", null});
 
         /**
          * Date format string
@@ -4090,7 +4098,7 @@
 
         /** @hide */
         public static final Validator USER_ROTATION_VALIDATOR =
-                new SettingsValidators.InclusiveIntegerRangeValidator(0, 3);
+                new InclusiveIntegerRangeValidator(0, 3);
 
         /**
          * Control whether the rotation lock toggle in the System UI should be hidden.
@@ -4179,7 +4187,7 @@
 
         /** @hide */
         public static final Validator TTY_MODE_VALIDATOR =
-                new SettingsValidators.InclusiveIntegerRangeValidator(0, 3);
+                new InclusiveIntegerRangeValidator(0, 3);
 
         /**
          * Whether the sounds effects (key clicks, lid open ...) are enabled. The value is
@@ -4381,7 +4389,7 @@
 
         /** @hide */
         public static final Validator SIP_CALL_OPTIONS_VALIDATOR =
-                new SettingsValidators.DiscreteValueValidator(
+                new DiscreteValueValidator(
                         new String[] {"SIP_ALWAYS", "SIP_ADDRESS_ONLY"});
 
         /**
@@ -4428,7 +4436,7 @@
 
         /** @hide */
         public static final Validator POINTER_SPEED_VALIDATOR =
-                new SettingsValidators.InclusiveFloatRangeValidator(-7, 7);
+                new InclusiveFloatRangeValidator(-7, 7);
 
         /**
          * Whether lock-to-app will be triggered by long-press on recents.
@@ -6352,7 +6360,7 @@
         public static final String LOCK_SCREEN_CUSTOM_CLOCK_FACE = "lock_screen_custom_clock_face";
 
         private static final Validator LOCK_SCREEN_CUSTOM_CLOCK_FACE_VALIDATOR =
-                SettingsValidators.JSON_OBJECT_VALIDATOR;
+                JSON_OBJECT_VALIDATOR;
 
         /**
          * Indicates which clock face to show on lock screen and AOD while docked.
@@ -6509,7 +6517,7 @@
             "enabled_accessibility_services";
 
         private static final Validator ENABLED_ACCESSIBILITY_SERVICES_VALIDATOR =
-                new SettingsValidators.ComponentNameListValidator(":");
+                new ComponentNameListValidator(":");
 
         /**
          * List of the accessibility services to which the user has granted
@@ -6521,7 +6529,7 @@
             "touch_exploration_granted_accessibility_services";
 
         private static final Validator TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES_VALIDATOR =
-                new SettingsValidators.ComponentNameListValidator(":");
+                new ComponentNameListValidator(":");
 
         /**
          * Whether the Global Actions Panel is enabled.
@@ -6696,7 +6704,7 @@
                 "accessibility_display_magnification_scale";
 
         private static final Validator ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE_VALIDATOR =
-                new SettingsValidators.InclusiveFloatRangeValidator(1.0f, Float.MAX_VALUE);
+                new InclusiveFloatRangeValidator(1.0f, Float.MAX_VALUE);
 
         /**
          * Unused mangnification setting
@@ -6780,7 +6788,7 @@
                 "accessibility_captioning_preset";
 
         private static final Validator ACCESSIBILITY_CAPTIONING_PRESET_VALIDATOR =
-                new SettingsValidators.DiscreteValueValidator(new String[]{"-1", "0", "1", "2",
+                new DiscreteValueValidator(new String[]{"-1", "0", "1", "2",
                         "3", "4"});
 
         /**
@@ -6824,7 +6832,7 @@
                 "accessibility_captioning_edge_type";
 
         private static final Validator ACCESSIBILITY_CAPTIONING_EDGE_TYPE_VALIDATOR =
-                new SettingsValidators.DiscreteValueValidator(new String[]{"0", "1", "2"});
+                new DiscreteValueValidator(new String[]{"0", "1", "2"});
 
         /**
          * Integer property that specifes the edge color for captions as a
@@ -6870,7 +6878,7 @@
                 "accessibility_captioning_typeface";
 
         private static final Validator ACCESSIBILITY_CAPTIONING_TYPEFACE_VALIDATOR =
-                new SettingsValidators.DiscreteValueValidator(new String[]{"DEFAULT",
+                new DiscreteValueValidator(new String[]{"DEFAULT",
                         "MONOSPACE", "SANS_SERIF", "SERIF"});
 
         /**
@@ -6882,7 +6890,7 @@
                 "accessibility_captioning_font_scale";
 
         private static final Validator ACCESSIBILITY_CAPTIONING_FONT_SCALE_VALIDATOR =
-                new SettingsValidators.InclusiveFloatRangeValidator(0.5f, 2.0f);
+                new InclusiveFloatRangeValidator(0.5f, 2.0f);
 
         /**
          * Setting that specifies whether display color inversion is enabled.
@@ -6923,7 +6931,7 @@
                 "accessibility_display_daltonizer";
 
         private static final Validator ACCESSIBILITY_DISPLAY_DALTONIZER_VALIDATOR =
-                new SettingsValidators.DiscreteValueValidator(
+                new DiscreteValueValidator(
                         new String[] {"-1", "0", "11", "12", "13"});
 
         /**
@@ -7112,8 +7120,7 @@
          */
         public static final String TTS_DEFAULT_LOCALE = "tts_default_locale";
 
-        private static final Validator TTS_DEFAULT_LOCALE_VALIDATOR =
-                new SettingsValidators.TTSListValidator();
+        private static final Validator TTS_DEFAULT_LOCALE_VALIDATOR = TTS_LIST_VALIDATOR;
 
         /**
          * Space delimited list of plugin packages that are enabled.
@@ -7121,7 +7128,7 @@
         public static final String TTS_ENABLED_PLUGINS = "tts_enabled_plugins";
 
         private static final Validator TTS_ENABLED_PLUGINS_VALIDATOR =
-                new SettingsValidators.PackageNameListValidator(" ");
+                new PackageNameListValidator(" ");
 
         /**
          * @deprecated Use {@link android.provider.Settings.Global#WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON}
@@ -7315,7 +7322,7 @@
                 "preferred_tty_mode";
 
         private static final Validator PREFERRED_TTY_MODE_VALIDATOR =
-                new SettingsValidators.DiscreteValueValidator(new String[]{"0", "1", "2", "3"});
+                new DiscreteValueValidator(new String[]{"0", "1", "2", "3"});
 
         /**
          * Whether the enhanced voice privacy mode is enabled.
@@ -7630,7 +7637,7 @@
         public static final String INCALL_POWER_BUTTON_BEHAVIOR = "incall_power_button_behavior";
 
         private static final Validator INCALL_POWER_BUTTON_BEHAVIOR_VALIDATOR =
-                new SettingsValidators.DiscreteValueValidator(new String[]{"1", "2"});
+                new DiscreteValueValidator(new String[]{"1", "2"});
 
         /**
          * INCALL_POWER_BUTTON_BEHAVIOR value for "turn off screen".
@@ -7851,7 +7858,7 @@
         public static final String UI_NIGHT_MODE = "ui_night_mode";
 
         private static final Validator UI_NIGHT_MODE_VALIDATOR =
-                new SettingsValidators.InclusiveIntegerRangeValidator(0, 2);
+                new InclusiveIntegerRangeValidator(0, 2);
 
         /**
          * Whether screensavers are enabled.
@@ -7871,7 +7878,7 @@
         public static final String SCREENSAVER_COMPONENTS = "screensaver_components";
 
         private static final Validator SCREENSAVER_COMPONENTS_VALIDATOR =
-                new SettingsValidators.ComponentNameListValidator(",");
+                new ComponentNameListValidator(",");
 
         /**
          * If screensavers are enabled, whether the screensaver should be automatically launched
@@ -8023,7 +8030,7 @@
                 "enabled_notification_assistant";
 
         private static final Validator ENABLED_NOTIFICATION_ASSISTANT_VALIDATOR =
-                new SettingsValidators.ComponentNameListValidator(":");
+                new ComponentNameListValidator(":");
 
         /**
          * Read only list of the service components that the current user has explicitly allowed to
@@ -8038,7 +8045,7 @@
         public static final String ENABLED_NOTIFICATION_LISTENERS = "enabled_notification_listeners";
 
         private static final Validator ENABLED_NOTIFICATION_LISTENERS_VALIDATOR =
-                new SettingsValidators.ComponentNameListValidator(":");
+                new ComponentNameListValidator(":");
 
         /**
          * Read only list of the packages that the current user has explicitly allowed to
@@ -8053,7 +8060,7 @@
                 "enabled_notification_policy_access_packages";
 
         private static final Validator ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES_VALIDATOR =
-                new SettingsValidators.PackageNameListValidator(":");
+                new PackageNameListValidator(":");
 
         /**
          * Defines whether managed profile ringtones should be synced from it's parent profile
@@ -8436,7 +8443,7 @@
         public static final String NIGHT_DISPLAY_AUTO_MODE = "night_display_auto_mode";
 
         private static final Validator NIGHT_DISPLAY_AUTO_MODE_VALIDATOR =
-                new SettingsValidators.InclusiveIntegerRangeValidator(0, 2);
+                new InclusiveIntegerRangeValidator(0, 2);
 
         /**
          * Control the color temperature of Night Display, represented in Kelvin.
@@ -8497,7 +8504,7 @@
         public static final String ENABLED_VR_LISTENERS = "enabled_vr_listeners";
 
         private static final Validator ENABLED_VR_LISTENERS_VALIDATOR =
-                new SettingsValidators.ComponentNameListValidator(":");
+                new ComponentNameListValidator(":");
 
         /**
          * Behavior of the display while in VR mode.
@@ -8509,7 +8516,7 @@
         public static final String VR_DISPLAY_MODE = "vr_display_mode";
 
         private static final Validator VR_DISPLAY_MODE_VALIDATOR =
-                new SettingsValidators.DiscreteValueValidator(new String[]{"0", "1"});
+                new DiscreteValueValidator(new String[]{"0", "1"});
 
         /**
          * Lower the display persistence while the system is in VR mode.
@@ -8628,8 +8635,7 @@
          */
         public static final String QS_TILES = "sysui_qs_tiles";
 
-        private static final Validator QS_TILES_VALIDATOR =
-                new SettingsValidators.TileListValidator();
+        private static final Validator QS_TILES_VALIDATOR = TILE_LIST_VALIDATOR;
 
         /**
          * Specifies whether the web action API is enabled.
@@ -8695,8 +8701,7 @@
          */
         public static final String QS_AUTO_ADDED_TILES = "qs_auto_tiles";
 
-        private static final Validator QS_AUTO_ADDED_TILES_VALIDATOR =
-                new SettingsValidators.TileListValidator();
+        private static final Validator QS_AUTO_ADDED_TILES_VALIDATOR = TILE_LIST_VALIDATOR;
 
         /**
          * Whether the Lockdown button should be shown in the power menu.
@@ -8857,7 +8862,7 @@
                 "theme_customization_overlay_packages";
 
         private static final Validator THEME_CUSTOMIZATION_OVERLAY_PACKAGES_VALIDATOR =
-                SettingsValidators.JSON_OBJECT_VALIDATOR;
+                JSON_OBJECT_VALIDATOR;
 
         /**
          * Navigation bar mode.
@@ -8869,7 +8874,7 @@
         public static final String NAVIGATION_MODE =
                 "navigation_mode";
         private static final Validator NAVIGATION_MODE_VALIDATOR =
-                new SettingsValidators.DiscreteValueValidator(new String[] {"0", "1", "2"});
+                new DiscreteValueValidator(new String[] {"0", "1", "2"});
 
         /**
          * Controls whether aware is enabled.
@@ -10721,7 +10726,7 @@
                 "network_recommendations_enabled";
 
         private static final Validator NETWORK_RECOMMENDATIONS_ENABLED_VALIDATOR =
-                new SettingsValidators.DiscreteValueValidator(new String[] {"-1", "0", "1"});
+                new DiscreteValueValidator(new String[] {"-1", "0", "1"});
 
         /**
          * Which package name to use for network recommendations. If null, network recommendations
@@ -12572,7 +12577,7 @@
         public static final String EMERGENCY_TONE = "emergency_tone";
 
         private static final Validator EMERGENCY_TONE_VALIDATOR =
-                new SettingsValidators.DiscreteValueValidator(new String[] {"0", "1", "2"});
+                new DiscreteValueValidator(new String[] {"0", "1", "2"});
 
         /**
          * CDMA only settings
@@ -12602,7 +12607,7 @@
                 "enable_automatic_system_server_heap_dumps";
 
         private static final Validator ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS_VALIDATOR =
-                new SettingsValidators.DiscreteValueValidator(new String[] {"0", "1"});
+                new DiscreteValueValidator(new String[] {"0", "1"});
 
         /**
          * See RIL_PreferredNetworkType in ril.h
@@ -12796,7 +12801,7 @@
                 "low_power_sticky_auto_disable_level";
 
         private static final Validator LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL_VALIDATOR =
-                new SettingsValidators.InclusiveIntegerRangeValidator(0, 100);
+                new InclusiveIntegerRangeValidator(0, 100);
 
         /**
          * Whether sticky battery saver should be deactivated once the battery level has reached the
@@ -12808,7 +12813,7 @@
                 "low_power_sticky_auto_disable_enabled";
 
         private static final Validator LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED_VALIDATOR =
-                new SettingsValidators.DiscreteValueValidator(new String[] {"0", "1"});
+                new DiscreteValueValidator(new String[] {"0", "1"});
 
         /**
          * Battery level [1-100] at which low power mode automatically turns on.
@@ -12823,7 +12828,7 @@
         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, 100);
+                new InclusiveIntegerRangeValidator(0, 100);
 
         /**
          * Whether battery saver is currently set to trigger based on percentage, dynamic power
@@ -12836,7 +12841,7 @@
         public static final String AUTOMATIC_POWER_SAVE_MODE = "automatic_power_save_mode";
 
         private static final Validator AUTOMATIC_POWER_SAVE_MODE_VALIDATOR =
-                new SettingsValidators.DiscreteValueValidator(new String[] {"0", "1"});
+                new DiscreteValueValidator(new String[] {"0", "1"});
 
         /**
          * The setting that backs the disable threshold for the setPowerSavingsWarning api in
@@ -12849,7 +12854,7 @@
         public static final String DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD =
                 "dynamic_power_savings_disable_threshold";
         private static final Validator DYNAMIC_POWER_SAVINGS_VALIDATOR =
-                new SettingsValidators.InclusiveIntegerRangeValidator(0, 100);
+                new InclusiveIntegerRangeValidator(0, 100);
 
         /**
          * The setting which backs the setDynamicPowerSaveHint api in PowerManager.
@@ -12999,7 +13004,7 @@
         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", "3"});
+                new DiscreteValueValidator(new String[] {"0", "1", "2", "3"});
 
         /**
          * Surround sounds formats that are enabled when ENCODED_SURROUND_OUTPUT is set to
@@ -13750,7 +13755,7 @@
         public static final String POWER_BUTTON_LONG_PRESS =
                 "power_button_long_press";
         private static final Validator POWER_BUTTON_LONG_PRESS_VALIDATOR =
-                new SettingsValidators.InclusiveIntegerRangeValidator(0, 5);
+                new InclusiveIntegerRangeValidator(0, 5);
 
         /**
          * Overrides internal R.integer.config_veryLongPressOnPowerBehavior.
@@ -13761,7 +13766,7 @@
         public static final String POWER_BUTTON_VERY_LONG_PRESS =
                 "power_button_very_long_press";
         private static final Validator POWER_BUTTON_VERY_LONG_PRESS_VALIDATOR =
-                new SettingsValidators.InclusiveIntegerRangeValidator(0, 1);
+                new InclusiveIntegerRangeValidator(0, 1);
 
         /**
          * Settings to backup. This is here so that it's in the same place as the settings
diff --git a/core/java/android/provider/SettingsValidators.java b/core/java/android/provider/SettingsValidators.java
deleted file mode 100644
index e4cf9fd..0000000
--- a/core/java/android/provider/SettingsValidators.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.net.Uri;
-import android.text.TextUtils;
-
-import com.android.internal.util.ArrayUtils;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.util.Locale;
-
-/**
- * This class provides both interface for validation and common validators
- * used to ensure Settings have meaningful values.
- *
- * @hide
- */
-public class SettingsValidators {
-
-    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(@Nullable String value) {
-            return true;
-        }
-    };
-
-    public static final Validator NON_NEGATIVE_INTEGER_VALIDATOR = new Validator() {
-        @Override
-        public boolean validate(@Nullable String value) {
-            try {
-                return Integer.parseInt(value) >= 0;
-            } catch (NumberFormatException e) {
-                return false;
-            }
-        }
-    };
-
-    public static final Validator ANY_INTEGER_VALIDATOR = new Validator() {
-        @Override
-        public boolean validate(@Nullable String value) {
-            try {
-                Integer.parseInt(value);
-                return true;
-            } catch (NumberFormatException e) {
-                return false;
-            }
-        }
-    };
-
-    public static final Validator URI_VALIDATOR = new Validator() {
-        @Override
-        public boolean validate(@Nullable String value) {
-            try {
-                Uri.decode(value);
-                return true;
-            } catch (IllegalArgumentException e) {
-                return false;
-            }
-        }
-    };
-
-    /**
-     * Does not allow a setting to have a null {@link ComponentName}. Use {@link
-     * SettingsValidators#NULLABLE_COMPONENT_NAME_VALIDATOR} instead if a setting can have a
-     * nullable {@link ComponentName}.
-     */
-    public static final Validator COMPONENT_NAME_VALIDATOR = new Validator() {
-        @Override
-        public boolean validate(@Nullable String value) {
-            return value != null && ComponentName.unflattenFromString(value) != null;
-        }
-    };
-
-    /**
-     * Allows a setting to have a null {@link ComponentName}.
-     */
-    public static final Validator NULLABLE_COMPONENT_NAME_VALIDATOR = new Validator() {
-        @Override
-        public boolean validate(@Nullable String value) {
-            return value == null || COMPONENT_NAME_VALIDATOR.validate(value);
-        }
-    };
-
-    public static final Validator PACKAGE_NAME_VALIDATOR = new Validator() {
-        @Override
-        public boolean validate(@Nullable 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)
-            if (value == null) {
-                return false;
-            }
-            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;
-
-        @Override
-        public boolean validate(@Nullable String value) {
-            if (value == null) {
-                return false;
-            }
-            return value.length() <= MAX_IPV6_LENGTH;
-        }
-    };
-
-    public static final Validator LOCALE_VALIDATOR = new Validator() {
-        @Override
-        public boolean validate(@Nullable String value) {
-            if (value == null) {
-                return false;
-            }
-            Locale[] validLocales = Locale.getAvailableLocales();
-            for (Locale locale : validLocales) {
-                if (value.equals(locale.toString())) {
-                    return true;
-                }
-            }
-            return false;
-        }
-    };
-
-    /** {@link Validator} that checks whether a value is a valid {@link JSONObject}. */
-    public static final Validator JSON_OBJECT_VALIDATOR = (value) -> {
-        if (TextUtils.isEmpty(value)) {
-            return false;
-        }
-        try {
-            new JSONObject(value);
-            return true;
-        } catch (JSONException e) {
-            return false;
-        }
-    };
-
-    public interface Validator {
-        /**
-         * Returns whether the input value is valid. Subclasses should handle the case where the
-         * input value is {@code null}.
-         */
-        boolean validate(@Nullable String value);
-    }
-
-    public static final class DiscreteValueValidator implements Validator {
-        private final String[] mValues;
-
-        public DiscreteValueValidator(String[] values) {
-            mValues = values;
-        }
-
-        @Override
-        public boolean validate(@Nullable String value) {
-            return ArrayUtils.contains(mValues, value);
-        }
-    }
-
-    public static final class InclusiveIntegerRangeValidator implements Validator {
-        private final int mMin;
-        private final int mMax;
-
-        public InclusiveIntegerRangeValidator(int min, int max) {
-            mMin = min;
-            mMax = max;
-        }
-
-        @Override
-        public boolean validate(@Nullable String value) {
-            try {
-                final int intValue = Integer.parseInt(value);
-                return intValue >= mMin && intValue <= mMax;
-            } catch (NumberFormatException e) {
-                return false;
-            }
-        }
-    }
-
-    public static final class InclusiveFloatRangeValidator implements Validator {
-        private final float mMin;
-        private final float mMax;
-
-        public InclusiveFloatRangeValidator(float min, float max) {
-            mMin = min;
-            mMax = max;
-        }
-
-        @Override
-        public boolean validate(@Nullable String value) {
-            try {
-                final float floatValue = Float.parseFloat(value);
-                return floatValue >= mMin && floatValue <= mMax;
-            } catch (NumberFormatException | NullPointerException e) {
-                return false;
-            }
-        }
-    }
-
-    public static final class ComponentNameListValidator implements Validator {
-        private final String mSeparator;
-
-        public ComponentNameListValidator(String separator) {
-            mSeparator = separator;
-        }
-
-        @Override
-        public boolean validate(@Nullable String value) {
-            if (value == null) {
-                return false;
-            }
-            String[] elements = value.split(mSeparator);
-            for (String element : elements) {
-                if (!COMPONENT_NAME_VALIDATOR.validate(element)) {
-                    return false;
-                }
-            }
-            return true;
-        }
-    }
-
-    public static final class PackageNameListValidator implements Validator {
-        private final String mSeparator;
-
-        public PackageNameListValidator(String separator) {
-            mSeparator = separator;
-        }
-
-        @Override
-        public boolean validate(@Nullable String value) {
-            if (value == null) {
-                return false;
-            }
-            String[] elements = value.split(mSeparator);
-            for (String element : elements) {
-                if (!PACKAGE_NAME_VALIDATOR.validate(element)) {
-                    return false;
-                }
-            }
-            return true;
-        }
-    }
-
-    private abstract static class ListValidator implements Validator {
-        public boolean validate(@Nullable String value) {
-            if (!isEntryValid(value)) {
-                return false;
-            }
-            String[] items = value.split(",");
-            for (String item : items) {
-                if (!isItemValid(item)) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        protected abstract boolean isEntryValid(String entry);
-
-        protected abstract boolean isItemValid(String item);
-    }
-
-    /** Ensure a restored value is a string in the format the text-to-speech system handles */
-    public static final class TTSListValidator extends ListValidator {
-        protected boolean isEntryValid(String entry) {
-            return entry != null && entry.length() > 0;
-        }
-
-        protected boolean isItemValid(String item) {
-            String[] parts = item.split(":");
-            // Replaces any old language separator (-) with the new one (_)
-            return ((parts.length == 2)
-                    && (parts[0].length() > 0)
-                    && ANY_STRING_VALIDATOR.validate(parts[0])
-                    && LOCALE_VALIDATOR.validate(parts[1].replace('-', '_')));
-        }
-    }
-
-    /** Ensure a restored value is suitable to be used as a tile name */
-    public static final class TileListValidator extends ListValidator {
-        protected boolean isEntryValid(String entry) {
-            return entry != null;
-        }
-
-        protected boolean isItemValid(String item) {
-            return item.length() > 0 && ANY_STRING_VALIDATOR.validate(item);
-        }
-    }
-}
diff --git a/core/java/android/provider/settings/validators/ComponentNameListValidator.java b/core/java/android/provider/settings/validators/ComponentNameListValidator.java
new file mode 100644
index 0000000..b6b867a
--- /dev/null
+++ b/core/java/android/provider/settings/validators/ComponentNameListValidator.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.settings.validators;
+
+import static android.provider.settings.validators.SettingsValidators.COMPONENT_NAME_VALIDATOR;
+
+/**
+ * Validate a list of compoments.
+ *
+ * @hide
+ */
+public final class ComponentNameListValidator extends ListValidator {
+    public ComponentNameListValidator(String separator) {
+        super(separator);
+    }
+
+    @Override
+    protected boolean isEntryValid(String entry) {
+        return entry != null;
+    }
+
+    @Override
+    protected boolean isItemValid(String item) {
+        return COMPONENT_NAME_VALIDATOR.validate(item);
+    }
+}
diff --git a/core/java/android/provider/settings/validators/DiscreteValueValidator.java b/core/java/android/provider/settings/validators/DiscreteValueValidator.java
new file mode 100644
index 0000000..183651f
--- /dev/null
+++ b/core/java/android/provider/settings/validators/DiscreteValueValidator.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.settings.validators;
+
+import android.annotation.Nullable;
+
+import com.android.internal.util.ArrayUtils;
+
+/**
+ * Validate a value exists in an array of known good values
+ *
+ * @hide
+ */
+public final class DiscreteValueValidator implements Validator {
+    private final String[] mValues;
+
+    public DiscreteValueValidator(String[] values) {
+        mValues = values;
+    }
+
+    @Override
+    public boolean validate(@Nullable String value) {
+        return ArrayUtils.contains(mValues, value);
+    }
+}
diff --git a/core/java/android/provider/settings/validators/InclusiveFloatRangeValidator.java b/core/java/android/provider/settings/validators/InclusiveFloatRangeValidator.java
new file mode 100644
index 0000000..38400ac
--- /dev/null
+++ b/core/java/android/provider/settings/validators/InclusiveFloatRangeValidator.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.settings.validators;
+
+import android.annotation.Nullable;
+
+/**
+ * Validate a float value lies within a given (boundary inclusive) range.
+ *
+ * @hide
+ */
+public final class InclusiveFloatRangeValidator implements Validator {
+    private final float mMin;
+    private final float mMax;
+
+    public InclusiveFloatRangeValidator(float min, float max) {
+        mMin = min;
+        mMax = max;
+    }
+
+    @Override
+    public boolean validate(@Nullable String value) {
+        try {
+            final float floatValue = Float.parseFloat(value);
+            return floatValue >= mMin && floatValue <= mMax;
+        } catch (NumberFormatException | NullPointerException e) {
+            return false;
+        }
+    }
+}
diff --git a/core/java/android/provider/settings/validators/InclusiveIntegerRangeValidator.java b/core/java/android/provider/settings/validators/InclusiveIntegerRangeValidator.java
new file mode 100644
index 0000000..e53c252
--- /dev/null
+++ b/core/java/android/provider/settings/validators/InclusiveIntegerRangeValidator.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.settings.validators;
+
+import android.annotation.Nullable;
+
+/**
+ * Validate an integer value lies within a given (boundary inclusive) range.
+ *
+ * @hide
+ */
+public final class InclusiveIntegerRangeValidator implements Validator {
+    private final int mMin;
+    private final int mMax;
+
+    public InclusiveIntegerRangeValidator(int min, int max) {
+        mMin = min;
+        mMax = max;
+    }
+
+    @Override
+    public boolean validate(@Nullable String value) {
+        try {
+            final int intValue = Integer.parseInt(value);
+            return intValue >= mMin && intValue <= mMax;
+        } catch (NumberFormatException e) {
+            return false;
+        }
+    }
+}
diff --git a/core/java/android/provider/settings/validators/ListValidator.java b/core/java/android/provider/settings/validators/ListValidator.java
new file mode 100644
index 0000000..a6001d2
--- /dev/null
+++ b/core/java/android/provider/settings/validators/ListValidator.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.settings.validators;
+
+import android.annotation.Nullable;
+
+/**
+ * Validate the elements in a list.
+ *
+ * @hide
+ */
+abstract class ListValidator implements Validator {
+
+    private String mListSplitRegex;
+
+    ListValidator(String listSplitRegex) {
+        mListSplitRegex = listSplitRegex;
+    }
+
+    public boolean validate(@Nullable String value) {
+        if (!isEntryValid(value)) {
+            return false;
+        }
+        String[] items = value.split(",");
+        for (String item : items) {
+            if (!isItemValid(item)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    protected abstract boolean isEntryValid(String entry);
+
+    protected abstract boolean isItemValid(String item);
+}
+
diff --git a/core/java/android/provider/settings/validators/PackageNameListValidator.java b/core/java/android/provider/settings/validators/PackageNameListValidator.java
new file mode 100644
index 0000000..bc7fc13
--- /dev/null
+++ b/core/java/android/provider/settings/validators/PackageNameListValidator.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.settings.validators;
+
+import static android.provider.settings.validators.SettingsValidators.PACKAGE_NAME_VALIDATOR;
+
+/**
+ * Validate a list of package names.
+ *
+ * @hide
+ */
+public final class PackageNameListValidator extends ListValidator {
+    public PackageNameListValidator(String separator) {
+        super(separator);
+    }
+
+    @Override
+    protected boolean isEntryValid(String entry) {
+        return entry != null;
+    }
+
+    @Override
+    protected boolean isItemValid(String item) {
+        return PACKAGE_NAME_VALIDATOR.validate(item);
+    }
+}
diff --git a/core/java/android/provider/settings/validators/SettingsValidators.java b/core/java/android/provider/settings/validators/SettingsValidators.java
new file mode 100644
index 0000000..562c638
--- /dev/null
+++ b/core/java/android/provider/settings/validators/SettingsValidators.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.settings.validators;
+
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.net.Uri;
+import android.text.TextUtils;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.Locale;
+
+/**
+ * This class provides both interface for validation and common validators
+ * used to ensure Settings have meaningful values.
+ *
+ * @hide
+ */
+public class SettingsValidators {
+
+    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(@Nullable String value) {
+            return true;
+        }
+    };
+
+    public static final Validator NON_NEGATIVE_INTEGER_VALIDATOR = new Validator() {
+        @Override
+        public boolean validate(@Nullable String value) {
+            try {
+                return Integer.parseInt(value) >= 0;
+            } catch (NumberFormatException e) {
+                return false;
+            }
+        }
+    };
+
+    public static final Validator ANY_INTEGER_VALIDATOR = new Validator() {
+        @Override
+        public boolean validate(@Nullable String value) {
+            try {
+                Integer.parseInt(value);
+                return true;
+            } catch (NumberFormatException e) {
+                return false;
+            }
+        }
+    };
+
+    public static final Validator URI_VALIDATOR = new Validator() {
+        @Override
+        public boolean validate(@Nullable String value) {
+            try {
+                Uri.decode(value);
+                return true;
+            } catch (IllegalArgumentException e) {
+                return false;
+            }
+        }
+    };
+
+    /**
+     * Does not allow a setting to have a null {@link ComponentName}. Use {@link
+     * SettingsValidators#NULLABLE_COMPONENT_NAME_VALIDATOR} instead if a setting can have a
+     * nullable {@link ComponentName}.
+     */
+    public static final Validator COMPONENT_NAME_VALIDATOR = new Validator() {
+        @Override
+        public boolean validate(@Nullable String value) {
+            return value != null && ComponentName.unflattenFromString(value) != null;
+        }
+    };
+
+    /**
+     * Allows a setting to have a null {@link ComponentName}.
+     */
+    public static final Validator NULLABLE_COMPONENT_NAME_VALIDATOR = new Validator() {
+        @Override
+        public boolean validate(@Nullable String value) {
+            return value == null || COMPONENT_NAME_VALIDATOR.validate(value);
+        }
+    };
+
+    public static final Validator PACKAGE_NAME_VALIDATOR = new Validator() {
+        @Override
+        public boolean validate(@Nullable 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)
+            if (value == null) {
+                return false;
+            }
+            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;
+
+        @Override
+        public boolean validate(@Nullable String value) {
+            if (value == null) {
+                return false;
+            }
+            return value.length() <= MAX_IPV6_LENGTH;
+        }
+    };
+
+    public static final Validator LOCALE_VALIDATOR = new Validator() {
+        @Override
+        public boolean validate(@Nullable String value) {
+            if (value == null) {
+                return false;
+            }
+            Locale[] validLocales = Locale.getAvailableLocales();
+            for (Locale locale : validLocales) {
+                if (value.equals(locale.toString())) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    };
+
+    /** {@link Validator} that checks whether a value is a valid {@link JSONObject}. */
+    public static final Validator JSON_OBJECT_VALIDATOR = (value) -> {
+        if (TextUtils.isEmpty(value)) {
+            return false;
+        }
+        try {
+            new JSONObject(value);
+            return true;
+        } catch (JSONException e) {
+            return false;
+        }
+    };
+
+    public static final Validator TTS_LIST_VALIDATOR = new TTSListValidator();
+
+    public static final Validator TILE_LIST_VALIDATOR = new TileListValidator();
+}
diff --git a/core/java/android/provider/settings/validators/TTSListValidator.java b/core/java/android/provider/settings/validators/TTSListValidator.java
new file mode 100644
index 0000000..6c73471
--- /dev/null
+++ b/core/java/android/provider/settings/validators/TTSListValidator.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.settings.validators;
+
+import static android.provider.settings.validators.SettingsValidators.ANY_STRING_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.LOCALE_VALIDATOR;
+
+/**
+ * Ensure a restored value is a string in the format the text-to-speech system handles
+ *
+ * @hide
+ */
+final class TTSListValidator extends ListValidator {
+
+    TTSListValidator() {
+        super(",");
+    }
+
+    protected boolean isEntryValid(String entry) {
+        return entry != null && entry.length() > 0;
+    }
+
+    protected boolean isItemValid(String item) {
+        String[] parts = item.split(":");
+        // Replaces any old language separator (-) with the new one (_)
+        return ((parts.length == 2)
+                && (parts[0].length() > 0)
+                && ANY_STRING_VALIDATOR.validate(parts[0])
+                && LOCALE_VALIDATOR.validate(parts[1].replace('-', '_')));
+    }
+}
diff --git a/core/java/android/provider/settings/validators/TileListValidator.java b/core/java/android/provider/settings/validators/TileListValidator.java
new file mode 100644
index 0000000..c696442
--- /dev/null
+++ b/core/java/android/provider/settings/validators/TileListValidator.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.settings.validators;
+
+import static android.provider.settings.validators.SettingsValidators.ANY_STRING_VALIDATOR;
+
+/**
+ * Ensure a restored value is suitable to be used as a tile name
+ *
+ * @hide
+ */
+final class TileListValidator extends ListValidator {
+    TileListValidator() {
+        super(",");
+    }
+
+    protected boolean isEntryValid(String entry) {
+        return entry != null;
+    }
+
+    protected boolean isItemValid(String item) {
+        return item.length() > 0 && ANY_STRING_VALIDATOR.validate(item);
+    }
+}
diff --git a/core/java/android/provider/settings/validators/Validator.java b/core/java/android/provider/settings/validators/Validator.java
new file mode 100644
index 0000000..393a03d
--- /dev/null
+++ b/core/java/android/provider/settings/validators/Validator.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.settings.validators;
+
+import android.annotation.Nullable;
+
+/**
+ * Interface for a settings value validator.
+ *
+ * @hide
+ */
+public interface Validator {
+    /**
+     * Returns whether the input value is valid. Subclasses should handle the case where the
+     * input value is {@code null}.
+     */
+    boolean validate(@Nullable String value);
+}
diff --git a/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java b/core/tests/coretests/src/android/provider/settings/validators/SettingsValidatorsTest.java
similarity index 85%
rename from core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
rename to core/tests/coretests/src/android/provider/settings/validators/SettingsValidatorsTest.java
index eea8c83..5f042d3 100644
--- a/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
+++ b/core/tests/coretests/src/android/provider/settings/validators/SettingsValidatorsTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.provider;
+package android.provider.settings.validators;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -23,7 +23,7 @@
 import static org.junit.Assert.fail;
 
 import android.platform.test.annotations.Presubmit;
-import android.provider.SettingsValidators.Validator;
+import android.provider.Settings;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -138,7 +138,7 @@
     @Test
     public void testDiscreteValueValidator() {
         String[] beerTypes = new String[]{"Ale", "American IPA", "Stout"};
-        Validator v = new SettingsValidators.DiscreteValueValidator(beerTypes);
+        Validator v = new DiscreteValueValidator(beerTypes);
         assertTrue(v.validate("Ale"));
         assertTrue(v.validate("American IPA"));
         assertTrue(v.validate("Stout"));
@@ -148,14 +148,14 @@
     @Test
     public void testDiscreteValueValidator_onNullValue_returnsFalse() {
         String[] discreteTypes = new String[]{"Type1", "Type2"};
-        Validator v = new SettingsValidators.DiscreteValueValidator(discreteTypes);
+        Validator v = new DiscreteValueValidator(discreteTypes);
 
         assertFalse(v.validate(null));
     }
 
     @Test
     public void testInclusiveIntegerRangeValidator() {
-        Validator v = new SettingsValidators.InclusiveIntegerRangeValidator(0, 5);
+        Validator v = new InclusiveIntegerRangeValidator(0, 5);
         assertTrue(v.validate("0"));
         assertTrue(v.validate("2"));
         assertTrue(v.validate("5"));
@@ -165,14 +165,14 @@
 
     @Test
     public void testInclusiveIntegerRangeValidator_onNullValue_returnsFalse() {
-        Validator v = new SettingsValidators.InclusiveIntegerRangeValidator(0, 5);
+        Validator v = new InclusiveIntegerRangeValidator(0, 5);
 
         assertFalse(v.validate(null));
     }
 
     @Test
     public void testInclusiveFloatRangeValidator() {
-        Validator v = new SettingsValidators.InclusiveFloatRangeValidator(0.0f, 5.0f);
+        Validator v = new InclusiveFloatRangeValidator(0.0f, 5.0f);
         assertTrue(v.validate("0.0"));
         assertTrue(v.validate("2.0"));
         assertTrue(v.validate("5.0"));
@@ -182,14 +182,14 @@
 
     @Test
     public void testInclusiveFloatRangeValidator_onNullValue_returnsFalse() {
-        Validator v = new SettingsValidators.InclusiveFloatRangeValidator(0.0f, 5.0f);
+        Validator v = new InclusiveFloatRangeValidator(0.0f, 5.0f);
 
         assertFalse(v.validate(null));
     }
 
     @Test
     public void testComponentNameListValidator() {
-        Validator v = new SettingsValidators.ComponentNameListValidator(",");
+        Validator v = new ComponentNameListValidator(",");
         assertTrue(v.validate("com.android.localtransport/.LocalTransport,"
                 + "com.google.android.gms/.backup.migrate.service.D2dTransport"));
         assertFalse(v.validate("com.google.5android,android"));
@@ -197,21 +197,21 @@
 
     @Test
     public void testComponentNameListValidator_onNullValue_returnsFalse() {
-        Validator v = new SettingsValidators.ComponentNameListValidator(",");
+        Validator v = new ComponentNameListValidator(",");
 
         assertFalse(v.validate(null));
     }
 
     @Test
     public void testPackageNameListValidator() {
-        Validator v = new SettingsValidators.PackageNameListValidator(",");
+        Validator v = new PackageNameListValidator(",");
         assertTrue(v.validate("com.android.localtransport.LocalTransport,com.google.android.gms"));
         assertFalse(v.validate("5com.android.internal.backup.LocalTransport,android"));
     }
 
     @Test
     public void testPackageNameListValidator_onNullValue_returnsFalse() {
-        Validator v = new SettingsValidators.PackageNameListValidator(",");
+        Validator v = new PackageNameListValidator(",");
 
         assertFalse(v.validate(null));
     }
@@ -256,51 +256,41 @@
 
     @Test
     public void testTTSListValidator_withValidInput_returnsTrue() {
-        Validator v = new SettingsValidators.TTSListValidator();
-
-        assertTrue(v.validate("com.foo.ttsengine:en-US,com.bar.ttsengine:es_ES"));
+        assertTrue(
+                SettingsValidators.TTS_LIST_VALIDATOR.validate(
+                        "com.foo.ttsengine:en-US,com.bar.ttsengine:es_ES"));
     }
 
     @Test
     public void testTTSListValidator_withInvalidInput_returnsFalse() {
-        Validator v = new SettingsValidators.TTSListValidator();
-
-        assertFalse(v.validate("com.foo.ttsengine:eng-USA,INVALID"));
+        assertFalse(
+                SettingsValidators.TTS_LIST_VALIDATOR.validate(
+                        "com.foo.ttsengine:eng-USA,INVALID"));
     }
 
     @Test
     public void testTTSListValidator_withEmptyInput_returnsFalse() {
-        Validator v = new SettingsValidators.TTSListValidator();
-
-        assertFalse(v.validate(""));
+        assertFalse(SettingsValidators.TTS_LIST_VALIDATOR.validate(""));
     }
 
     @Test
     public void testTTSListValidator_withNullInput_returnsFalse() {
-        Validator v = new SettingsValidators.TTSListValidator();
-
-        assertFalse(v.validate(null));
+        assertFalse(SettingsValidators.TTS_LIST_VALIDATOR.validate(null));
     }
 
     @Test
     public void testTileListValidator_withValidInput_returnsTrue() {
-        Validator v = new SettingsValidators.TileListValidator();
-
-        assertTrue(v.validate("1,2,3,4"));
+        assertTrue(SettingsValidators.TILE_LIST_VALIDATOR.validate("1,2,3,4"));
     }
 
     @Test
     public void testTileListValidator_withMissingValue_returnsFalse() {
-        Validator v = new SettingsValidators.TileListValidator();
-
-        assertFalse(v.validate("1,,3"));
+        assertFalse(SettingsValidators.TILE_LIST_VALIDATOR.validate("1,,3"));
     }
 
     @Test
     public void testTileListValidator_withNullInput_returnsFalse() {
-        Validator v = new SettingsValidators.TileListValidator();
-
-        assertFalse(v.validate(null));
+        assertFalse(SettingsValidators.TILE_LIST_VALIDATOR.validate(null));
     }
 
     @Test
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 2286f4c..36e945f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -34,7 +34,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.UserHandle;
 import android.provider.Settings;
-import android.provider.SettingsValidators.Validator;
+import android.provider.settings.validators.Validator;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.BackupUtils;
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index c1aa0f9..e492e28 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -70,7 +70,7 @@
 import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.provider.Settings.Secure;
-import android.provider.SettingsValidators;
+import android.provider.settings.validators.Validator;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -1717,7 +1717,7 @@
     }
 
     private void validateSystemSettingValue(String name, String value) {
-        SettingsValidators.Validator validator = Settings.System.VALIDATORS.get(name);
+        Validator validator = Settings.System.VALIDATORS.get(name);
         if (validator != null && !validator.validate(value)) {
             throw new IllegalArgumentException("Invalid value: " + value
                     + " for setting: " + name);