12c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski/* 22c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski * Copyright (C) 2018 The Android Open Source Project 32c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski * 42c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski * Licensed under the Apache License, Version 2.0 (the "License"); 52c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski * you may not use this file except in compliance with the License. 62c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski * You may obtain a copy of the License at 72c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski * 82c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski * http://www.apache.org/licenses/LICENSE-2.0 92c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski * 102c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski * Unless required by applicable law or agreed to in writing, software 112c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski * distributed under the License is distributed on an "AS IS" BASIS, 122c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski * See the License for the specific language governing permissions and 142c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski * limitations under the License. 152c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski */ 162c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 172c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinskipackage android.provider; 182c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 19eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Mengimport android.annotation.Nullable; 202c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinskiimport android.content.ComponentName; 212c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinskiimport android.net.Uri; 222c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 232c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinskiimport com.android.internal.util.ArrayUtils; 242c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 25964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinskiimport java.util.Locale; 26964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski 272c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski/** 282c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski * This class provides both interface for validation and common validators 292c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski * used to ensure Settings have meaningful values. 302c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski * 312c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski * @hide 322c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski */ 332c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinskipublic class SettingsValidators { 342c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 352c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski public static final Validator BOOLEAN_VALIDATOR = 362c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski new DiscreteValueValidator(new String[] {"0", "1"}); 372c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 385db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski public static final Validator ANY_STRING_VALIDATOR = new Validator() { 395db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski @Override 40eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng public boolean validate(@Nullable String value) { 415db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski return true; 425db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski } 435db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski }; 445db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski 452c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski public static final Validator NON_NEGATIVE_INTEGER_VALIDATOR = new Validator() { 462c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski @Override 47eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng public boolean validate(@Nullable String value) { 482c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski try { 492c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski return Integer.parseInt(value) >= 0; 502c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } catch (NumberFormatException e) { 512c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski return false; 522c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } 532c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } 542c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski }; 552c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 56964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski public static final Validator ANY_INTEGER_VALIDATOR = new Validator() { 57964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski @Override 58eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng public boolean validate(@Nullable String value) { 59964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski try { 60964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski Integer.parseInt(value); 61964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski return true; 62964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } catch (NumberFormatException e) { 63964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski return false; 64964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 65964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 66964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski }; 67964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski 682c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski public static final Validator URI_VALIDATOR = new Validator() { 692c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski @Override 70eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng public boolean validate(@Nullable String value) { 712c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski try { 722c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski Uri.decode(value); 732c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski return true; 742c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } catch (IllegalArgumentException e) { 752c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski return false; 762c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } 772c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } 782c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski }; 792c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 804451179411f4a84d2b64c5306371b186e510ad3cAnnie Meng /** 814451179411f4a84d2b64c5306371b186e510ad3cAnnie Meng * Does not allow a setting to have a null {@link ComponentName}. Use {@link 824451179411f4a84d2b64c5306371b186e510ad3cAnnie Meng * SettingsValidators#NULLABLE_COMPONENT_NAME_VALIDATOR} instead if a setting can have a 834451179411f4a84d2b64c5306371b186e510ad3cAnnie Meng * nullable {@link ComponentName}. 844451179411f4a84d2b64c5306371b186e510ad3cAnnie Meng */ 852c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski public static final Validator COMPONENT_NAME_VALIDATOR = new Validator() { 862c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski @Override 87eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng public boolean validate(@Nullable String value) { 885d26b8c03a1e11076e41699fd54259ef5ff4a1e0Annie Meng return value != null && ComponentName.unflattenFromString(value) != null; 892c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } 902c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski }; 912c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 924451179411f4a84d2b64c5306371b186e510ad3cAnnie Meng /** 934451179411f4a84d2b64c5306371b186e510ad3cAnnie Meng * Allows a setting to have a null {@link ComponentName}. 944451179411f4a84d2b64c5306371b186e510ad3cAnnie Meng */ 954451179411f4a84d2b64c5306371b186e510ad3cAnnie Meng public static final Validator NULLABLE_COMPONENT_NAME_VALIDATOR = new Validator() { 964451179411f4a84d2b64c5306371b186e510ad3cAnnie Meng @Override 974451179411f4a84d2b64c5306371b186e510ad3cAnnie Meng public boolean validate(@Nullable String value) { 984451179411f4a84d2b64c5306371b186e510ad3cAnnie Meng return value == null || COMPONENT_NAME_VALIDATOR.validate(value); 994451179411f4a84d2b64c5306371b186e510ad3cAnnie Meng } 1004451179411f4a84d2b64c5306371b186e510ad3cAnnie Meng }; 1014451179411f4a84d2b64c5306371b186e510ad3cAnnie Meng 1025db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski public static final Validator PACKAGE_NAME_VALIDATOR = new Validator() { 1035db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski @Override 104eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng public boolean validate(@Nullable String value) { 1055db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski return value != null && isStringPackageName(value); 1065db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski } 1075db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski 1085db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski private boolean isStringPackageName(String value) { 1095db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski // The name may contain uppercase or lowercase letters ('A' through 'Z'), numbers, 1105db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski // and underscores ('_'). However, individual package name parts may only 1115db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski // start with letters. 1125db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski // (https://developer.android.com/guide/topics/manifest/manifest-element.html#package) 113964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski if (value == null) { 114964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski return false; 115964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 11629a7472974d4c90c1668eb24db83f27ca17012cdMichal Karpinski String[] subparts = value.split("\\."); 1175db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski boolean isValidPackageName = true; 1185db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski for (String subpart : subparts) { 1196fe6c8ef02df1c394cab1316248e1ffb88c598a1Michal Karpinski isValidPackageName &= isSubpartValidForPackageName(subpart); 1205db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski if (!isValidPackageName) break; 1215db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski } 1225db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski return isValidPackageName; 1235db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski } 1245db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski 1255db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski private boolean isSubpartValidForPackageName(String subpart) { 1265db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski if (subpart.length() == 0) return false; 1275db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski boolean isValidSubpart = Character.isLetter(subpart.charAt(0)); 1285db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski for (int i = 1; i < subpart.length(); i++) { 1296fe6c8ef02df1c394cab1316248e1ffb88c598a1Michal Karpinski isValidSubpart &= (Character.isLetterOrDigit(subpart.charAt(i)) 1305db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski || (subpart.charAt(i) == '_')); 1315db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski if (!isValidSubpart) break; 1325db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski } 1335db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski return isValidSubpart; 1345db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski } 1355db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski }; 1365db1e430f9d774a5b203eda5ec53f065bb1ec5b3Michal Karpinski 1372c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski public static final Validator LENIENT_IP_ADDRESS_VALIDATOR = new Validator() { 1382c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski private static final int MAX_IPV6_LENGTH = 45; 1392c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 1402c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski @Override 141eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng public boolean validate(@Nullable String value) { 142964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski if (value == null) { 143964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski return false; 144964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 1452c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski return value.length() <= MAX_IPV6_LENGTH; 1462c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } 1472c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski }; 1482c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 149964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski public static final Validator LOCALE_VALIDATOR = new Validator() { 150964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski @Override 151eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng public boolean validate(@Nullable String value) { 152964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski if (value == null) { 153964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski return false; 154964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 155964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski Locale[] validLocales = Locale.getAvailableLocales(); 156964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski for (Locale locale : validLocales) { 157964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski if (value.equals(locale.toString())) { 158964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski return true; 159964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 160964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 161964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski return false; 162964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 163964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski }; 164964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski 1652c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski public interface Validator { 166eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng /** 167eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng * Returns whether the input value is valid. Subclasses should handle the case where the 168eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng * input value is {@code null}. 169eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng */ 170eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng boolean validate(@Nullable String value); 1712c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } 1722c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 1732c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski public static final class DiscreteValueValidator implements Validator { 1742c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski private final String[] mValues; 1752c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 1762c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski public DiscreteValueValidator(String[] values) { 1772c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski mValues = values; 1782c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } 1792c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 1802c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski @Override 181eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng public boolean validate(@Nullable String value) { 1822c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski return ArrayUtils.contains(mValues, value); 1832c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } 1842c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } 1852c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 1862c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski public static final class InclusiveIntegerRangeValidator implements Validator { 1872c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski private final int mMin; 1882c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski private final int mMax; 1892c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 1902c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski public InclusiveIntegerRangeValidator(int min, int max) { 1912c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski mMin = min; 1922c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski mMax = max; 1932c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } 1942c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 1952c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski @Override 196eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng public boolean validate(@Nullable String value) { 1972c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski try { 1982c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski final int intValue = Integer.parseInt(value); 1992c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski return intValue >= mMin && intValue <= mMax; 2002c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } catch (NumberFormatException e) { 2012c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski return false; 2022c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } 2032c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } 2042c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } 2052c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 2062c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski public static final class InclusiveFloatRangeValidator implements Validator { 2072c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski private final float mMin; 2082c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski private final float mMax; 2092c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 2102c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski public InclusiveFloatRangeValidator(float min, float max) { 2112c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski mMin = min; 2122c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski mMax = max; 2132c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } 2142c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski 2152c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski @Override 216eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng public boolean validate(@Nullable String value) { 2172c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski try { 2182c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski final float floatValue = Float.parseFloat(value); 2192c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski return floatValue >= mMin && floatValue <= mMax; 220eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng } catch (NumberFormatException | NullPointerException e) { 2212c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski return false; 2222c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } 2232c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } 2242c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski } 225964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski 226964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski public static final class ComponentNameListValidator implements Validator { 227964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski private final String mSeparator; 228964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski 229964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski public ComponentNameListValidator(String separator) { 230964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski mSeparator = separator; 231964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 232964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski 233964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski @Override 234eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng public boolean validate(@Nullable String value) { 235964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski if (value == null) { 236964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski return false; 237964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 238964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski String[] elements = value.split(mSeparator); 239964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski for (String element : elements) { 240964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski if (!COMPONENT_NAME_VALIDATOR.validate(element)) { 241964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski return false; 242964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 243964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 244964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski return true; 245964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 246964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 247964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski 248964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski public static final class PackageNameListValidator implements Validator { 249964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski private final String mSeparator; 250964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski 251964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski public PackageNameListValidator(String separator) { 252964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski mSeparator = separator; 253964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 254964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski 255964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski @Override 256eed1b812a4ad38c6815f3066e41a95d7f5358838Annie Meng public boolean validate(@Nullable String value) { 257964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski if (value == null) { 258964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski return false; 259964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 260964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski String[] elements = value.split(mSeparator); 261964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski for (String element : elements) { 262964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski if (!PACKAGE_NAME_VALIDATOR.validate(element)) { 263964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski return false; 264964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 265964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 266964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski return true; 267964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 268964943ab98874a91be04f9ea2137861c93f6ffd3Michal Karpinski } 2692c37b08510877af06542ad21eb5b63c8f9824584Michal Karpinski} 270