CMSettings: Add secure validators and relocate protected apps validator
Move validators from CMSettings.System into CMSettings, add validators for CMSettings.Secure, and move protected apps validator from CMSettings.System to CMSettings.Secure Change-Id: I9f4e1bef7ff5be100376d2d03d34483d12938158
This commit is contained in:
parent
0fa8756f31
commit
fc97734c06
|
@ -522,9 +522,11 @@ public class CMSettingsProvider extends ContentProvider {
|
||||||
|
|
||||||
// Validate value if inserting int System table
|
// Validate value if inserting int System table
|
||||||
final String name = values.getAsString(Settings.NameValueTable.NAME);
|
final String name = values.getAsString(Settings.NameValueTable.NAME);
|
||||||
|
final String value = values.getAsString(Settings.NameValueTable.VALUE);
|
||||||
if (CMDatabaseHelper.CMTableNames.TABLE_SYSTEM.equals(tableName)) {
|
if (CMDatabaseHelper.CMTableNames.TABLE_SYSTEM.equals(tableName)) {
|
||||||
final String value = values.getAsString(Settings.NameValueTable.VALUE);
|
|
||||||
validateSystemSettingNameValue(name, value);
|
validateSystemSettingNameValue(name, value);
|
||||||
|
} else if (CMDatabaseHelper.CMTableNames.TABLE_SECURE.equals(tableName)) {
|
||||||
|
validateSecureSettingValue(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLiteDatabase db = dbHelper.getWritableDatabase();
|
SQLiteDatabase db = dbHelper.getWritableDatabase();
|
||||||
|
@ -591,9 +593,11 @@ public class CMSettingsProvider extends ContentProvider {
|
||||||
|
|
||||||
// Validate value if updating System table
|
// Validate value if updating System table
|
||||||
final String name = values.getAsString(Settings.NameValueTable.NAME);
|
final String name = values.getAsString(Settings.NameValueTable.NAME);
|
||||||
|
final String value = values.getAsString(Settings.NameValueTable.VALUE);
|
||||||
if (CMDatabaseHelper.CMTableNames.TABLE_SYSTEM.equals(tableName)) {
|
if (CMDatabaseHelper.CMTableNames.TABLE_SYSTEM.equals(tableName)) {
|
||||||
final String value = values.getAsString(Settings.NameValueTable.VALUE);
|
|
||||||
validateSystemSettingNameValue(name, value);
|
validateSystemSettingNameValue(name, value);
|
||||||
|
} else if (CMDatabaseHelper.CMTableNames.TABLE_SECURE.equals(tableName)) {
|
||||||
|
validateSecureSettingValue(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
int callingUserId = UserHandle.getCallingUserId();
|
int callingUserId = UserHandle.getCallingUserId();
|
||||||
|
@ -792,7 +796,7 @@ public class CMSettingsProvider extends ContentProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateSystemSettingNameValue(String name, String value) {
|
private void validateSystemSettingNameValue(String name, String value) {
|
||||||
CMSettings.System.Validator validator = CMSettings.System.VALIDATORS.get(name);
|
CMSettings.Validator validator = CMSettings.System.VALIDATORS.get(name);
|
||||||
if (validator == null) {
|
if (validator == null) {
|
||||||
throw new IllegalArgumentException("Invalid setting: " + name);
|
throw new IllegalArgumentException("Invalid setting: " + name);
|
||||||
}
|
}
|
||||||
|
@ -803,5 +807,16 @@ public class CMSettingsProvider extends ContentProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateSecureSettingValue(String name, String value) {
|
||||||
|
CMSettings.Validator validator = CMSettings.Secure.VALIDATORS.get(name);
|
||||||
|
|
||||||
|
// Not all secure settings have validators, but if a validator exists, the validate method
|
||||||
|
// should return true
|
||||||
|
if (validator != null && !validator.validate(value)) {
|
||||||
|
throw new IllegalArgumentException("Invalid value: " + value
|
||||||
|
+ " for setting: " + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO Add caching
|
// TODO Add caching
|
||||||
}
|
}
|
||||||
|
|
|
@ -269,6 +269,140 @@ public final class CMSettings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// region Validators
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public static interface Validator {
|
||||||
|
public boolean validate(String value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Validator sBooleanValidator =
|
||||||
|
new DiscreteValueValidator(new String[] {"0", "1"});
|
||||||
|
|
||||||
|
private static final Validator sNonNegativeIntegerValidator = new Validator() {
|
||||||
|
@Override
|
||||||
|
public boolean validate(String value) {
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(value) >= 0;
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final Validator sUriValidator = new Validator() {
|
||||||
|
@Override
|
||||||
|
public boolean validate(String value) {
|
||||||
|
try {
|
||||||
|
Uri.decode(value);
|
||||||
|
return true;
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final Validator sColorValidator =
|
||||||
|
new InclusiveIntegerRangeValidator(Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||||
|
|
||||||
|
private static final Validator sAlwaysTrueValidator = new Validator() {
|
||||||
|
@Override
|
||||||
|
public boolean validate(String value) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class DelimitedListValidator implements Validator {
|
||||||
|
private final ArraySet<String> mValidValueSet;
|
||||||
|
private final String mDelimiter;
|
||||||
|
private final boolean mAllowEmptyList;
|
||||||
|
|
||||||
|
public DelimitedListValidator(String[] validValues, String delimiter,
|
||||||
|
boolean allowEmptyList) {
|
||||||
|
mValidValueSet = new ArraySet<String>(Arrays.asList(validValues));
|
||||||
|
mDelimiter = delimiter;
|
||||||
|
mAllowEmptyList = allowEmptyList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validate(String value) {
|
||||||
|
ArraySet<String> values = new ArraySet<String>();
|
||||||
|
if (!TextUtils.isEmpty(value)) {
|
||||||
|
final String[] array = TextUtils.split(value, Pattern.quote(mDelimiter));
|
||||||
|
for (String item : array) {
|
||||||
|
if (TextUtils.isEmpty(item)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
values.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (values.size() > 0) {
|
||||||
|
values.removeAll(mValidValueSet);
|
||||||
|
// values.size() will be non-zero if it contains any values not in
|
||||||
|
// mValidValueSet
|
||||||
|
return values.size() == 0;
|
||||||
|
} else if (mAllowEmptyList) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// endregion Validators
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* System settings, containing miscellaneous CM system preferences. This table holds simple
|
* System settings, containing miscellaneous CM system preferences. This table holds simple
|
||||||
* name/value pairs. There are convenience functions for accessing individual settings entries.
|
* name/value pairs. There are convenience functions for accessing individual settings entries.
|
||||||
|
@ -278,53 +412,12 @@ public final class CMSettings {
|
||||||
|
|
||||||
public static final String SYS_PROP_CM_SETTING_VERSION = "sys.cm_settings_system_version";
|
public static final String SYS_PROP_CM_SETTING_VERSION = "sys.cm_settings_system_version";
|
||||||
|
|
||||||
/** @hide */
|
|
||||||
public static interface Validator {
|
|
||||||
public boolean validate(String value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final NameValueCache sNameValueCache = new NameValueCache(
|
private static final NameValueCache sNameValueCache = new NameValueCache(
|
||||||
SYS_PROP_CM_SETTING_VERSION,
|
SYS_PROP_CM_SETTING_VERSION,
|
||||||
CONTENT_URI,
|
CONTENT_URI,
|
||||||
CALL_METHOD_GET_SYSTEM,
|
CALL_METHOD_GET_SYSTEM,
|
||||||
CALL_METHOD_PUT_SYSTEM);
|
CALL_METHOD_PUT_SYSTEM);
|
||||||
|
|
||||||
private static final Validator sBooleanValidator =
|
|
||||||
new DiscreteValueValidator(new String[] {"0", "1"});
|
|
||||||
|
|
||||||
private static final Validator sNonNegativeIntegerValidator = new Validator() {
|
|
||||||
@Override
|
|
||||||
public boolean validate(String value) {
|
|
||||||
try {
|
|
||||||
return Integer.parseInt(value) >= 0;
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final Validator sUriValidator = new Validator() {
|
|
||||||
@Override
|
|
||||||
public boolean validate(String value) {
|
|
||||||
try {
|
|
||||||
Uri.decode(value);
|
|
||||||
return true;
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final Validator sColorValidator =
|
|
||||||
new InclusiveIntegerRangeValidator(Integer.MIN_VALUE, Integer.MAX_VALUE);
|
|
||||||
|
|
||||||
private static final Validator sAlwaysTrueValidator = new Validator() {
|
|
||||||
@Override
|
|
||||||
public boolean validate(String value) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// region Methods
|
// region Methods
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -671,116 +764,6 @@ public final class CMSettings {
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
private 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class DelimitedListValidator implements Validator {
|
|
||||||
private final ArraySet<String> mValidValueSet;
|
|
||||||
private final String mDelimiter;
|
|
||||||
private final boolean mAllowEmptyList;
|
|
||||||
|
|
||||||
public DelimitedListValidator(String[] validValues, String delimiter,
|
|
||||||
boolean allowEmptyList) {
|
|
||||||
mValidValueSet = new ArraySet<String>(Arrays.asList(validValues));
|
|
||||||
mDelimiter = delimiter;
|
|
||||||
mAllowEmptyList = allowEmptyList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean validate(String value) {
|
|
||||||
ArraySet<String> values = new ArraySet<String>();
|
|
||||||
if (!TextUtils.isEmpty(value)) {
|
|
||||||
final String[] array = TextUtils.split(value, Pattern.quote(mDelimiter));
|
|
||||||
for (String item : array) {
|
|
||||||
if (TextUtils.isEmpty(item)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
values.add(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (values.size() > 0) {
|
|
||||||
values.removeAll(mValidValueSet);
|
|
||||||
// values.size() will be non-zero if it contains any values not in
|
|
||||||
// mValidValueSet
|
|
||||||
return values.size() == 0;
|
|
||||||
} else if (mAllowEmptyList) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public static final Validator PROTECTED_COMPONENTS_VALIDATOR = new Validator() {
|
|
||||||
private final String mDelimiter = "|";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean validate(String value) {
|
|
||||||
if (!TextUtils.isEmpty(value)) {
|
|
||||||
final String[] array = TextUtils.split(value, Pattern.quote(mDelimiter));
|
|
||||||
for (String item : array) {
|
|
||||||
if (TextUtils.isEmpty(item)) {
|
|
||||||
return false; // Empty components not allowed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true; // Empty list is allowed though.
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// region System Settings
|
// region System Settings
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2024,7 +2007,6 @@ public final class CMSettings {
|
||||||
NOTIFICATION_LIGHT_PULSE_CUSTOM_ENABLE_VALIDATOR);
|
NOTIFICATION_LIGHT_PULSE_CUSTOM_ENABLE_VALIDATOR);
|
||||||
VALIDATORS.put(NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES,
|
VALIDATORS.put(NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES,
|
||||||
NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES_VALIDATOR);
|
NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES_VALIDATOR);
|
||||||
VALIDATORS.put(Secure.PROTECTED_COMPONENTS, PROTECTED_COMPONENTS_VALIDATOR);
|
|
||||||
};
|
};
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
||||||
|
@ -2047,7 +2029,6 @@ public final class CMSettings {
|
||||||
|
|
||||||
// region Methods
|
// region Methods
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Put a delimited list as a string
|
* Put a delimited list as a string
|
||||||
* @param resolver to access the database with
|
* @param resolver to access the database with
|
||||||
|
@ -2668,6 +2649,41 @@ public final class CMSettings {
|
||||||
public static boolean isLegacySetting(String key) {
|
public static boolean isLegacySetting(String key) {
|
||||||
return ArrayUtils.contains(LEGACY_SECURE_SETTINGS, key);
|
return ArrayUtils.contains(LEGACY_SECURE_SETTINGS, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final Validator PROTECTED_COMPONENTS_VALIDATOR = new Validator() {
|
||||||
|
private final String mDelimiter = "|";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validate(String value) {
|
||||||
|
if (!TextUtils.isEmpty(value)) {
|
||||||
|
final String[] array = TextUtils.split(value, Pattern.quote(mDelimiter));
|
||||||
|
for (String item : array) {
|
||||||
|
if (TextUtils.isEmpty(item)) {
|
||||||
|
return false; // Empty components not allowed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true; // Empty list is allowed though.
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapping of validators for all secure settings. This map is used to validate both valid
|
||||||
|
* keys as well as validating the values for those keys.
|
||||||
|
*
|
||||||
|
* Note: Make sure if you add a new Secure setting you create a Validator for it and add
|
||||||
|
* it to this map.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final Map<String, Validator> VALIDATORS =
|
||||||
|
new ArrayMap<String, Validator>();
|
||||||
|
static {
|
||||||
|
VALIDATORS.put(PROTECTED_COMPONENTS, PROTECTED_COMPONENTS_VALIDATOR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue