SettingsValidators.java revision 5d26b8c03a1e11076e41699fd54259ef5ff4a1e0
1/* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.provider; 18 19import android.content.ComponentName; 20import android.net.Uri; 21 22import com.android.internal.util.ArrayUtils; 23 24import java.util.Locale; 25 26/** 27 * This class provides both interface for validation and common validators 28 * used to ensure Settings have meaningful values. 29 * 30 * @hide 31 */ 32public class SettingsValidators { 33 34 public static final Validator BOOLEAN_VALIDATOR = 35 new DiscreteValueValidator(new String[] {"0", "1"}); 36 37 public static final Validator ANY_STRING_VALIDATOR = new Validator() { 38 @Override 39 public boolean validate(String value) { 40 return true; 41 } 42 }; 43 44 public static final Validator NON_NEGATIVE_INTEGER_VALIDATOR = new Validator() { 45 @Override 46 public boolean validate(String value) { 47 try { 48 return Integer.parseInt(value) >= 0; 49 } catch (NumberFormatException e) { 50 return false; 51 } 52 } 53 }; 54 55 public static final Validator ANY_INTEGER_VALIDATOR = new Validator() { 56 @Override 57 public boolean validate(String value) { 58 try { 59 Integer.parseInt(value); 60 return true; 61 } catch (NumberFormatException e) { 62 return false; 63 } 64 } 65 }; 66 67 public static final Validator URI_VALIDATOR = new Validator() { 68 @Override 69 public boolean validate(String value) { 70 try { 71 Uri.decode(value); 72 return true; 73 } catch (IllegalArgumentException e) { 74 return false; 75 } 76 } 77 }; 78 79 public static final Validator COMPONENT_NAME_VALIDATOR = new Validator() { 80 @Override 81 public boolean validate(String value) { 82 return value != null && ComponentName.unflattenFromString(value) != null; 83 } 84 }; 85 86 public static final Validator PACKAGE_NAME_VALIDATOR = new Validator() { 87 @Override 88 public boolean validate(String value) { 89 return value != null && isStringPackageName(value); 90 } 91 92 private boolean isStringPackageName(String value) { 93 // The name may contain uppercase or lowercase letters ('A' through 'Z'), numbers, 94 // and underscores ('_'). However, individual package name parts may only 95 // start with letters. 96 // (https://developer.android.com/guide/topics/manifest/manifest-element.html#package) 97 if (value == null) { 98 return false; 99 } 100 String[] subparts = value.split("\\."); 101 boolean isValidPackageName = true; 102 for (String subpart : subparts) { 103 isValidPackageName &= isSubpartValidForPackageName(subpart); 104 if (!isValidPackageName) break; 105 } 106 return isValidPackageName; 107 } 108 109 private boolean isSubpartValidForPackageName(String subpart) { 110 if (subpart.length() == 0) return false; 111 boolean isValidSubpart = Character.isLetter(subpart.charAt(0)); 112 for (int i = 1; i < subpart.length(); i++) { 113 isValidSubpart &= (Character.isLetterOrDigit(subpart.charAt(i)) 114 || (subpart.charAt(i) == '_')); 115 if (!isValidSubpart) break; 116 } 117 return isValidSubpart; 118 } 119 }; 120 121 public static final Validator LENIENT_IP_ADDRESS_VALIDATOR = new Validator() { 122 private static final int MAX_IPV6_LENGTH = 45; 123 124 @Override 125 public boolean validate(String value) { 126 if (value == null) { 127 return false; 128 } 129 return value.length() <= MAX_IPV6_LENGTH; 130 } 131 }; 132 133 public static final Validator LOCALE_VALIDATOR = new Validator() { 134 @Override 135 public boolean validate(String value) { 136 if (value == null) { 137 return false; 138 } 139 Locale[] validLocales = Locale.getAvailableLocales(); 140 for (Locale locale : validLocales) { 141 if (value.equals(locale.toString())) { 142 return true; 143 } 144 } 145 return false; 146 } 147 }; 148 149 public interface Validator { 150 boolean validate(String value); 151 } 152 153 public static final class DiscreteValueValidator implements Validator { 154 private final String[] mValues; 155 156 public DiscreteValueValidator(String[] values) { 157 mValues = values; 158 } 159 160 @Override 161 public boolean validate(String value) { 162 return ArrayUtils.contains(mValues, value); 163 } 164 } 165 166 public static final class InclusiveIntegerRangeValidator implements Validator { 167 private final int mMin; 168 private final int mMax; 169 170 public InclusiveIntegerRangeValidator(int min, int max) { 171 mMin = min; 172 mMax = max; 173 } 174 175 @Override 176 public boolean validate(String value) { 177 try { 178 final int intValue = Integer.parseInt(value); 179 return intValue >= mMin && intValue <= mMax; 180 } catch (NumberFormatException e) { 181 return false; 182 } 183 } 184 } 185 186 public static final class InclusiveFloatRangeValidator implements Validator { 187 private final float mMin; 188 private final float mMax; 189 190 public InclusiveFloatRangeValidator(float min, float max) { 191 mMin = min; 192 mMax = max; 193 } 194 195 @Override 196 public boolean validate(String value) { 197 try { 198 final float floatValue = Float.parseFloat(value); 199 return floatValue >= mMin && floatValue <= mMax; 200 } catch (NumberFormatException e) { 201 return false; 202 } 203 } 204 } 205 206 public static final class ComponentNameListValidator implements Validator { 207 private final String mSeparator; 208 209 public ComponentNameListValidator(String separator) { 210 mSeparator = separator; 211 } 212 213 @Override 214 public boolean validate(String value) { 215 if (value == null) { 216 return false; 217 } 218 String[] elements = value.split(mSeparator); 219 for (String element : elements) { 220 if (!COMPONENT_NAME_VALIDATOR.validate(element)) { 221 return false; 222 } 223 } 224 return true; 225 } 226 } 227 228 public static final class PackageNameListValidator implements Validator { 229 private final String mSeparator; 230 231 public PackageNameListValidator(String separator) { 232 mSeparator = separator; 233 } 234 235 @Override 236 public boolean validate(String value) { 237 if (value == null) { 238 return false; 239 } 240 String[] elements = value.split(mSeparator); 241 for (String element : elements) { 242 if (!PACKAGE_NAME_VALIDATOR.validate(element)) { 243 return false; 244 } 245 } 246 return true; 247 } 248 } 249} 250