/*
 * 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 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
/** * 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 ComponentName. Use NULLABLE_COMPONENT_NAME_VALIDATOR instead if a setting can have a nullable ComponentName.
/** * 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 ComponentName.
/** * 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; } }; public interface Validator {
Returns whether the input value is valid. Subclasses should handle the case where the input value is null.
/** * 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; } } }