summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/provider/Settings.java73
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java51
2 files changed, 96 insertions, 28 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e3302d1ca9a0..13e5cda7cca3 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2773,6 +2773,7 @@ public final class Settings {
private final ArraySet<String> mReadableFields;
private final ArraySet<String> mAllFields;
+ private final ArrayMap<String, Integer> mReadableFieldsWithMaxTargetSdk;
@GuardedBy("this")
private GenerationTracker mGenerationTracker;
@@ -2794,7 +2795,9 @@ public final class Settings {
mProviderHolder = providerHolder;
mReadableFields = new ArraySet<>();
mAllFields = new ArraySet<>();
- getPublicSettingsForClass(callerClass, mAllFields, mReadableFields);
+ mReadableFieldsWithMaxTargetSdk = new ArrayMap<>();
+ getPublicSettingsForClass(callerClass, mAllFields, mReadableFields,
+ mReadableFieldsWithMaxTargetSdk);
}
public boolean putStringForUser(ContentResolver cr, String name, String value,
@@ -2851,13 +2854,34 @@ public final class Settings {
// Settings.Global and is not annotated as @Readable.
// Notice that a key string that is not defined in any of the Settings.* classes will
// still be regarded as readable.
- if (!isCallerExemptFromReadableRestriction()
- && mAllFields.contains(name) && !mReadableFields.contains(name)) {
- throw new SecurityException(
- "Settings key: <" + name + "> is not readable. From S+, settings keys "
- + "annotated with @hide are restricted to system_server and system "
- + "apps only, unless they are annotated with @Readable.");
+ if (!isCallerExemptFromReadableRestriction() && mAllFields.contains(name)) {
+ if (!mReadableFields.contains(name)) {
+ throw new SecurityException(
+ "Settings key: <" + name + "> is not readable. From S+, settings keys "
+ + "annotated with @hide are restricted to system_server and "
+ + "system apps only, unless they are annotated with @Readable."
+ );
+ } else {
+ // When the target settings key has @Readable annotation, if the caller app's
+ // target sdk is higher than the maxTargetSdk of the annotation, reject access.
+ if (mReadableFieldsWithMaxTargetSdk.containsKey(name)) {
+ final int maxTargetSdk = mReadableFieldsWithMaxTargetSdk.get(name);
+ final Application application = ActivityThread.currentApplication();
+ final boolean targetSdkCheckOk = application != null
+ && application.getApplicationInfo() != null
+ && application.getApplicationInfo().targetSdkVersion
+ <= maxTargetSdk;
+ if (!targetSdkCheckOk) {
+ throw new SecurityException(
+ "Settings key: <" + name + "> is only readable to apps with "
+ + "targetSdkVersion lower than or equal to: "
+ + maxTargetSdk
+ );
+ }
+ }
+ }
}
+
final boolean isSelf = (userHandle == UserHandle.myUserId());
int currentGeneration = -1;
if (isSelf) {
@@ -3225,10 +3249,12 @@ public final class Settings {
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
private @interface Readable {
+ int maxTargetSdk() default 0;
}
private static <T extends NameValueTable> void getPublicSettingsForClass(
- Class<T> callerClass, Set<String> allKeys, Set<String> readableKeys) {
+ Class<T> callerClass, Set<String> allKeys, Set<String> readableKeys,
+ ArrayMap<String, Integer> keysWithMaxTargetSdk) {
final Field[] allFields = callerClass.getDeclaredFields();
try {
for (int i = 0; i < allFields.length; i++) {
@@ -3241,8 +3267,15 @@ public final class Settings {
continue;
}
allKeys.add((String) value);
- if (field.getAnnotation(Readable.class) != null) {
- readableKeys.add((String) value);
+ final Readable annotation = field.getAnnotation(Readable.class);
+
+ if (annotation != null) {
+ final String key = (String) value;
+ final int maxTargetSdk = annotation.maxTargetSdk();
+ readableKeys.add(key);
+ if (maxTargetSdk != 0) {
+ keysWithMaxTargetSdk.put(key, maxTargetSdk);
+ }
}
}
} catch (IllegalAccessException ignored) {
@@ -3404,8 +3437,10 @@ public final class Settings {
}
/** @hide */
- public static void getPublicSettings(Set<String> allKeys, Set<String> readableKeys) {
- getPublicSettingsForClass(System.class, allKeys, readableKeys);
+ public static void getPublicSettings(Set<String> allKeys, Set<String> readableKeys,
+ ArrayMap<String, Integer> readableKeysWithMaxTargetSdk) {
+ getPublicSettingsForClass(System.class, allKeys, readableKeys,
+ readableKeysWithMaxTargetSdk);
}
/**
@@ -5734,8 +5769,10 @@ public final class Settings {
}
/** @hide */
- public static void getPublicSettings(Set<String> allKeys, Set<String> readableKeys) {
- getPublicSettingsForClass(Secure.class, allKeys, readableKeys);
+ public static void getPublicSettings(Set<String> allKeys, Set<String> readableKeys,
+ ArrayMap<String, Integer> readableKeysWithMaxTargetSdk) {
+ getPublicSettingsForClass(Secure.class, allKeys, readableKeys,
+ readableKeysWithMaxTargetSdk);
}
/**
@@ -11023,7 +11060,7 @@ public final class Settings {
* @hide
*/
@UnsupportedAppUsage
- @Readable
+ @Readable(maxTargetSdk = Build.VERSION_CODES.R)
public static final String MOBILE_DATA = "mobile_data";
/**
@@ -14965,8 +15002,10 @@ public final class Settings {
}
/** @hide */
- public static void getPublicSettings(Set<String> allKeys, Set<String> readableKeys) {
- getPublicSettingsForClass(Global.class, allKeys, readableKeys);
+ public static void getPublicSettings(Set<String> allKeys, Set<String> readableKeys,
+ ArrayMap<String, Integer> readableKeysWithMaxTargetSdk) {
+ getPublicSettingsForClass(Global.class, allKeys, readableKeys,
+ readableKeysWithMaxTargetSdk);
}
/**
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index bce576d1e1d8..dd9a6eee7327 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -310,20 +310,29 @@ public class SettingsProvider extends ContentProvider {
private static final Set<String> sAllSecureSettings = new ArraySet<>();
private static final Set<String> sReadableSecureSettings = new ArraySet<>();
+ private static final ArrayMap<String, Integer> sReadableSecureSettingsWithMaxTargetSdk =
+ new ArrayMap<>();
static {
- Settings.Secure.getPublicSettings(sAllSecureSettings, sReadableSecureSettings);
+ Settings.Secure.getPublicSettings(sAllSecureSettings, sReadableSecureSettings,
+ sReadableSecureSettingsWithMaxTargetSdk);
}
private static final Set<String> sAllSystemSettings = new ArraySet<>();
private static final Set<String> sReadableSystemSettings = new ArraySet<>();
+ private static final ArrayMap<String, Integer> sReadableSystemSettingsWithMaxTargetSdk =
+ new ArrayMap<>();
static {
- Settings.System.getPublicSettings(sAllSystemSettings, sReadableSystemSettings);
+ Settings.System.getPublicSettings(sAllSystemSettings, sReadableSystemSettings,
+ sReadableSystemSettingsWithMaxTargetSdk);
}
private static final Set<String> sAllGlobalSettings = new ArraySet<>();
private static final Set<String> sReadableGlobalSettings = new ArraySet<>();
+ private static final ArrayMap<String, Integer> sReadableGlobalSettingsWithMaxTargetSdk =
+ new ArrayMap<>();
static {
- Settings.Global.getPublicSettings(sAllGlobalSettings, sReadableGlobalSettings);
+ Settings.Global.getPublicSettings(sAllGlobalSettings, sReadableGlobalSettings,
+ sReadableGlobalSettingsWithMaxTargetSdk);
}
private final Object mLock = new Object();
@@ -2065,7 +2074,7 @@ public class SettingsProvider extends ContentProvider {
}
if ((ai.flags & ApplicationInfo.FLAG_TEST_ONLY) == 0) {
// Skip checking readable annotations for test_only apps
- checkReadableAnnotation(settingsType, settingName);
+ checkReadableAnnotation(settingsType, settingName, ai.targetSandboxVersion);
}
/**
* some settings need additional permission check, this is to have a matching security
@@ -2101,35 +2110,55 @@ public class SettingsProvider extends ContentProvider {
/**
* Check if the target settings key is readable. Reject if the caller app is trying to access a
* settings key defined in the Settings.Secure, Settings.System or Settings.Global and is not
- * annotated as @Readable.
+ * annotated as @Readable. Reject if the caller app is targeting an SDK level that is higher
+ * than the maxTargetSdk specified in the @Readable annotation.
* Notice that a key string that is not defined in any of the Settings.* classes will still be
* regarded as readable.
*/
- private void checkReadableAnnotation(int settingsType, String settingName) {
+ private void checkReadableAnnotation(int settingsType, String settingName,
+ int targetSdkVersion) {
final Set<String> allFields;
final Set<String> readableFields;
+ final ArrayMap<String, Integer> readableFieldsWithMaxTargetSdk;
switch (settingsType) {
case SETTINGS_TYPE_GLOBAL:
allFields = sAllGlobalSettings;
readableFields = sReadableGlobalSettings;
+ readableFieldsWithMaxTargetSdk = sReadableGlobalSettingsWithMaxTargetSdk;
break;
case SETTINGS_TYPE_SYSTEM:
allFields = sAllSystemSettings;
readableFields = sReadableSystemSettings;
+ readableFieldsWithMaxTargetSdk = sReadableSystemSettingsWithMaxTargetSdk;
break;
case SETTINGS_TYPE_SECURE:
allFields = sAllSecureSettings;
readableFields = sReadableSecureSettings;
+ readableFieldsWithMaxTargetSdk = sReadableSecureSettingsWithMaxTargetSdk;
break;
default:
throw new IllegalArgumentException("Invalid settings type: " + settingsType);
}
- if (allFields.contains(settingName) && !readableFields.contains(settingName)) {
- throw new SecurityException(
- "Settings key: <" + settingName + "> is not readable. From S+, settings keys "
- + "annotated with @hide are restricted to system_server and system "
- + "apps only, unless they are annotated with @Readable.");
+ if (allFields.contains(settingName)) {
+ if (!readableFields.contains(settingName)) {
+ throw new SecurityException(
+ "Settings key: <" + settingName + "> is not readable. From S+, settings "
+ + "keys annotated with @hide are restricted to system_server and "
+ + "system apps only, unless they are annotated with @Readable."
+ );
+ } else {
+ if (readableFieldsWithMaxTargetSdk.containsKey(settingName)) {
+ final int maxTargetSdk = readableFieldsWithMaxTargetSdk.get(settingName);
+ if (targetSdkVersion > maxTargetSdk) {
+ throw new SecurityException(
+ "Settings key: <" + settingName + "> is only readable to apps with "
+ + "targetSdkVersion lower than or equal to: "
+ + maxTargetSdk
+ );
+ }
+ }
+ }
}
}