| /* |
| * 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.content.ComponentName; |
| import android.net.Uri; |
| |
| import com.android.internal.util.ArrayUtils; |
| |
| 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(String value) { |
| return true; |
| } |
| }; |
| |
| public static final Validator NON_NEGATIVE_INTEGER_VALIDATOR = new Validator() { |
| @Override |
| public boolean validate(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(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(String value) { |
| try { |
| Uri.decode(value); |
| return true; |
| } catch (IllegalArgumentException e) { |
| return false; |
| } |
| } |
| }; |
| |
| public static final Validator COMPONENT_NAME_VALIDATOR = new Validator() { |
| @Override |
| public boolean validate(String value) { |
| return ComponentName.unflattenFromString(value) != null; |
| } |
| }; |
| |
| public static final Validator PACKAGE_NAME_VALIDATOR = new Validator() { |
| @Override |
| public boolean validate(String value) { |
| return value != null && isStringPackageName(value); |
| } |
| |
| private boolean isStringPackageName(String value) { |
| // The name may contain uppercase or lowercase letters ('A' through 'Z'), numbers, |
| // and underscores ('_'). However, individual package name parts may only |
| // start with letters. |
| // (https://developer.android.com/guide/topics/manifest/manifest-element.html#package) |
| 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(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(String value) { |
| if (value == null) { |
| return false; |
| } |
| Locale[] validLocales = Locale.getAvailableLocales(); |
| for (Locale locale : validLocales) { |
| if (value.equals(locale.toString())) { |
| return true; |
| } |
| } |
| return false; |
| } |
| }; |
| |
| public interface Validator { |
| boolean validate(String value); |
| } |
| |
| public static final class DiscreteValueValidator implements Validator { |
| private final String[] mValues; |
| |
| public DiscreteValueValidator(String[] values) { |
| mValues = values; |
| } |
| |
| @Override |
| public boolean validate(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(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(String value) { |
| try { |
| final float floatValue = Float.parseFloat(value); |
| return floatValue >= mMin && floatValue <= mMax; |
| } catch (NumberFormatException e) { |
| return false; |
| } |
| } |
| } |
| |
| public static final class ComponentNameListValidator implements Validator { |
| private final String mSeparator; |
| |
| public ComponentNameListValidator(String separator) { |
| mSeparator = separator; |
| } |
| |
| @Override |
| public boolean validate(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(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; |
| } |
| } |
| } |