Loading core/java/android/provider/Settings.java +93 −2 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import android.net.ConnectivityManager; import android.net.Uri; import android.net.wifi.WifiManager; import android.os.BatteryManager; import android.os.Binder; import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.DropBoxManager; Loading Loading @@ -1596,6 +1597,24 @@ public final class Settings { // with a partial enable/disable state in multi-threaded situations. private static final Object mLocationSettingsLock = new Object(); // Used in system server calling uid workaround in call() private static boolean sInSystemServer = false; private static final Object sInSystemServerLock = new Object(); /** @hide */ public static void setInSystemServer() { synchronized (sInSystemServerLock) { sInSystemServer = true; } } /** @hide */ public static boolean isInSystemServer() { synchronized (sInSystemServerLock) { return sInSystemServer; } } public static class SettingNotFoundException extends AndroidException { public SettingNotFoundException(String msg) { super(msg); Loading Loading @@ -1804,7 +1823,23 @@ public final class Settings { } } } Bundle b = cp.call(cr.getPackageName(), mCallGetCommand, name, args); Bundle b; // If we're in system server and in a binder transaction we need to clear the // calling uid. This works around code in system server that did not call // clearCallingIdentity, previously this wasn't needed because reading settings // did not do permission checking but thats no longer the case. // Long term this should be removed and callers should properly call // clearCallingIdentity or use a ContentResolver from the caller as needed. if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) { final long token = Binder.clearCallingIdentity(); try { b = cp.call(cr.getPackageName(), mCallGetCommand, name, args); } finally { Binder.restoreCallingIdentity(token); } } else { b = cp.call(cr.getPackageName(), mCallGetCommand, name, args); } if (b != null) { String value = b.getString(Settings.NameValueTable.VALUE); // Don't update our cache for reads of other users' data Loading Loading @@ -1864,7 +1899,19 @@ public final class Settings { try { Bundle queryArgs = ContentResolver.createSqlQueryBundle( NAME_EQ_PLACEHOLDER, new String[]{name}, null); c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE_PROJECTION, queryArgs, null); // Same workaround as above. if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) { final long token = Binder.clearCallingIdentity(); try { c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE_PROJECTION, queryArgs, null); } finally { Binder.restoreCallingIdentity(token); } } else { c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE_PROJECTION, queryArgs, null); } if (c == null) { Log.w(TAG, "Can't get key " + name + " from " + mUri); return null; Loading Loading @@ -4020,6 +4067,22 @@ public final class Settings { outMap.putAll(CLONE_FROM_PARENT_ON_VALUE); } /** * System settings which can be accessed by ephemeral apps. * @hide */ public static final Set<String> EPHEMERAL_SETTINGS = new ArraySet<>(); static { EPHEMERAL_SETTINGS.add(TEXT_AUTO_REPLACE); EPHEMERAL_SETTINGS.add(TEXT_AUTO_CAPS); EPHEMERAL_SETTINGS.add(TEXT_AUTO_PUNCTUATE); EPHEMERAL_SETTINGS.add(TEXT_SHOW_PASSWORD); EPHEMERAL_SETTINGS.add(DATE_FORMAT); EPHEMERAL_SETTINGS.add(FONT_SCALE); EPHEMERAL_SETTINGS.add(HAPTIC_FEEDBACK_ENABLED); EPHEMERAL_SETTINGS.add(TIME_12_24); } /** * When to use Wi-Fi calling * Loading Loading @@ -6898,6 +6961,20 @@ public final class Settings { outKeySet.addAll(CLONE_TO_MANAGED_PROFILE); } /** * Secure settings which can be accessed by ephemeral apps. * @hide */ public static final Set<String> EPHEMERAL_SETTINGS = new ArraySet<>(); static { EPHEMERAL_SETTINGS.add(ENABLED_ACCESSIBILITY_SERVICES); EPHEMERAL_SETTINGS.add(ACCESSIBILITY_SPEAK_PASSWORD); EPHEMERAL_SETTINGS.add(ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); EPHEMERAL_SETTINGS.add(DEFAULT_INPUT_METHOD); EPHEMERAL_SETTINGS.add(ENABLED_INPUT_METHODS); } /** * Helper method for determining if a location provider is enabled. * Loading Loading @@ -9906,6 +9983,20 @@ public final class Settings { * @hide */ public static final String CELL_ON = "cell_on"; /** * Global settings which can be accessed by ephemeral apps. * @hide */ public static final Set<String> EPHEMERAL_SETTINGS = new ArraySet<>(); static { EPHEMERAL_SETTINGS.add(WAIT_FOR_DEBUGGER); EPHEMERAL_SETTINGS.add(DEVICE_PROVISIONED); EPHEMERAL_SETTINGS.add(DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES); EPHEMERAL_SETTINGS.add(DEVELOPMENT_FORCE_RTL); EPHEMERAL_SETTINGS.add(EPHEMERAL_COOKIE_MAX_SIZE_BYTES); } } /** Loading packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +73 −9 Original line number Diff line number Diff line Loading @@ -271,6 +271,7 @@ public class SettingsProvider extends ContentProvider { @Override public boolean onCreate() { Settings.setInSystemServer(); synchronized (mLock) { mUserManager = UserManager.get(getContext()); mPackageManager = AppGlobals.getPackageManager(); Loading Loading @@ -829,7 +830,8 @@ public class SettingsProvider extends ContentProvider { SettingsState settingsState = mSettingsRegistry.getSettingsLocked( SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM); List<String> names = settingsState.getSettingNamesLocked(); List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM); final int nameCount = names.size(); Loading @@ -852,6 +854,9 @@ public class SettingsProvider extends ContentProvider { Slog.v(LOG_TAG, "getGlobalSetting(" + name + ")"); } // Ensure the caller can access the setting. enforceSettingReadable(name, SETTINGS_TYPE_GLOBAL, UserHandle.getCallingUserId()); // Get the value. synchronized (mLock) { return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_GLOBAL, Loading Loading @@ -954,8 +959,7 @@ public class SettingsProvider extends ContentProvider { final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId); synchronized (mLock) { List<String> names = mSettingsRegistry.getSettingsNamesLocked( SETTINGS_TYPE_SECURE, callingUserId); List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_SECURE, callingUserId); final int nameCount = names.size(); Loading Loading @@ -997,6 +1001,9 @@ public class SettingsProvider extends ContentProvider { // Resolve the userId on whose behalf the call is made. final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); // Ensure the caller can access the setting. enforceSettingReadable(name, SETTINGS_TYPE_SECURE, callingUserId); // Determine the owning user as some profile settings are cloned from the parent. final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name); Loading Loading @@ -1159,8 +1166,7 @@ public class SettingsProvider extends ContentProvider { final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId); synchronized (mLock) { List<String> names = mSettingsRegistry.getSettingsNamesLocked( SETTINGS_TYPE_SYSTEM, callingUserId); List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_SYSTEM, callingUserId); final int nameCount = names.size(); Loading Loading @@ -1191,6 +1197,9 @@ public class SettingsProvider extends ContentProvider { // Resolve the userId on whose behalf the call is made. final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); // Ensure the caller can access the setting. enforceSettingReadable(name, SETTINGS_TYPE_SYSTEM, callingUserId); // Determine the owning user as some profile settings are cloned from the parent. final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name); Loading Loading @@ -1409,10 +1418,16 @@ public class SettingsProvider extends ContentProvider { && (parentId = getGroupParentLocked(userId)) != userId) { // The setting has a dependency and the profile has a parent String dependency = sSystemCloneFromParentOnDependency.get(setting); // Lookup the dependency setting as ourselves, some callers may not have access to it. final long token = Binder.clearCallingIdentity(); try { Setting settingObj = getSecureSetting(dependency, userId); if (settingObj != null && settingObj.getValue().equals("1")) { return parentId; } } finally { Binder.restoreCallingIdentity(token); } } return resolveOwningUserIdLocked(userId, sSystemCloneToManagedSettings, setting); } Loading Loading @@ -1479,6 +1494,55 @@ public class SettingsProvider extends ContentProvider { } } private Set<String> getEphemeralAccessibleSettings(int settingsType) { switch (settingsType) { case SETTINGS_TYPE_GLOBAL: return Settings.Global.EPHEMERAL_SETTINGS; case SETTINGS_TYPE_SECURE: return Settings.Secure.EPHEMERAL_SETTINGS; case SETTINGS_TYPE_SYSTEM: return Settings.System.EPHEMERAL_SETTINGS; default: throw new IllegalArgumentException("Invalid settings type: " + settingsType); } } private List<String> getSettingsNamesLocked(int settingsType, int userId) { ApplicationInfo ai = getCallingApplicationInfoOrThrow(userId); if (ai.isEphemeralApp()) { return new ArrayList<String>(getEphemeralAccessibleSettings(settingsType)); } else { return mSettingsRegistry.getSettingsNamesLocked(settingsType, userId); } } private void enforceSettingReadable(String settingName, int settingsType, int userId) { if (UserHandle.getAppId(Binder.getCallingUid()) < Process.FIRST_APPLICATION_UID) { return; } ApplicationInfo ai = getCallingApplicationInfoOrThrow(userId); if (!ai.isEphemeralApp()) { return; } if (!getEphemeralAccessibleSettings(settingsType).contains(settingName)) { throw new SecurityException("Setting " + settingName + " is not accessible from" + " ephemeral package " + getCallingPackage()); } } private ApplicationInfo getCallingApplicationInfoOrThrow(int userId) { ApplicationInfo ai = null; try { ai = mPackageManager.getApplicationInfo(getCallingPackage(), 0 , userId); } catch (RemoteException ignored) { } if (ai == null) { throw new IllegalStateException("Failed to lookup info for package " + getCallingPackage()); } return ai; } private PackageInfo getCallingPackageInfoOrThrow(int userId) { try { PackageInfo packageInfo = mPackageManager.getPackageInfo( Loading Loading
core/java/android/provider/Settings.java +93 −2 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import android.net.ConnectivityManager; import android.net.Uri; import android.net.wifi.WifiManager; import android.os.BatteryManager; import android.os.Binder; import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.DropBoxManager; Loading Loading @@ -1596,6 +1597,24 @@ public final class Settings { // with a partial enable/disable state in multi-threaded situations. private static final Object mLocationSettingsLock = new Object(); // Used in system server calling uid workaround in call() private static boolean sInSystemServer = false; private static final Object sInSystemServerLock = new Object(); /** @hide */ public static void setInSystemServer() { synchronized (sInSystemServerLock) { sInSystemServer = true; } } /** @hide */ public static boolean isInSystemServer() { synchronized (sInSystemServerLock) { return sInSystemServer; } } public static class SettingNotFoundException extends AndroidException { public SettingNotFoundException(String msg) { super(msg); Loading Loading @@ -1804,7 +1823,23 @@ public final class Settings { } } } Bundle b = cp.call(cr.getPackageName(), mCallGetCommand, name, args); Bundle b; // If we're in system server and in a binder transaction we need to clear the // calling uid. This works around code in system server that did not call // clearCallingIdentity, previously this wasn't needed because reading settings // did not do permission checking but thats no longer the case. // Long term this should be removed and callers should properly call // clearCallingIdentity or use a ContentResolver from the caller as needed. if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) { final long token = Binder.clearCallingIdentity(); try { b = cp.call(cr.getPackageName(), mCallGetCommand, name, args); } finally { Binder.restoreCallingIdentity(token); } } else { b = cp.call(cr.getPackageName(), mCallGetCommand, name, args); } if (b != null) { String value = b.getString(Settings.NameValueTable.VALUE); // Don't update our cache for reads of other users' data Loading Loading @@ -1864,7 +1899,19 @@ public final class Settings { try { Bundle queryArgs = ContentResolver.createSqlQueryBundle( NAME_EQ_PLACEHOLDER, new String[]{name}, null); c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE_PROJECTION, queryArgs, null); // Same workaround as above. if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) { final long token = Binder.clearCallingIdentity(); try { c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE_PROJECTION, queryArgs, null); } finally { Binder.restoreCallingIdentity(token); } } else { c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE_PROJECTION, queryArgs, null); } if (c == null) { Log.w(TAG, "Can't get key " + name + " from " + mUri); return null; Loading Loading @@ -4020,6 +4067,22 @@ public final class Settings { outMap.putAll(CLONE_FROM_PARENT_ON_VALUE); } /** * System settings which can be accessed by ephemeral apps. * @hide */ public static final Set<String> EPHEMERAL_SETTINGS = new ArraySet<>(); static { EPHEMERAL_SETTINGS.add(TEXT_AUTO_REPLACE); EPHEMERAL_SETTINGS.add(TEXT_AUTO_CAPS); EPHEMERAL_SETTINGS.add(TEXT_AUTO_PUNCTUATE); EPHEMERAL_SETTINGS.add(TEXT_SHOW_PASSWORD); EPHEMERAL_SETTINGS.add(DATE_FORMAT); EPHEMERAL_SETTINGS.add(FONT_SCALE); EPHEMERAL_SETTINGS.add(HAPTIC_FEEDBACK_ENABLED); EPHEMERAL_SETTINGS.add(TIME_12_24); } /** * When to use Wi-Fi calling * Loading Loading @@ -6898,6 +6961,20 @@ public final class Settings { outKeySet.addAll(CLONE_TO_MANAGED_PROFILE); } /** * Secure settings which can be accessed by ephemeral apps. * @hide */ public static final Set<String> EPHEMERAL_SETTINGS = new ArraySet<>(); static { EPHEMERAL_SETTINGS.add(ENABLED_ACCESSIBILITY_SERVICES); EPHEMERAL_SETTINGS.add(ACCESSIBILITY_SPEAK_PASSWORD); EPHEMERAL_SETTINGS.add(ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); EPHEMERAL_SETTINGS.add(DEFAULT_INPUT_METHOD); EPHEMERAL_SETTINGS.add(ENABLED_INPUT_METHODS); } /** * Helper method for determining if a location provider is enabled. * Loading Loading @@ -9906,6 +9983,20 @@ public final class Settings { * @hide */ public static final String CELL_ON = "cell_on"; /** * Global settings which can be accessed by ephemeral apps. * @hide */ public static final Set<String> EPHEMERAL_SETTINGS = new ArraySet<>(); static { EPHEMERAL_SETTINGS.add(WAIT_FOR_DEBUGGER); EPHEMERAL_SETTINGS.add(DEVICE_PROVISIONED); EPHEMERAL_SETTINGS.add(DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES); EPHEMERAL_SETTINGS.add(DEVELOPMENT_FORCE_RTL); EPHEMERAL_SETTINGS.add(EPHEMERAL_COOKIE_MAX_SIZE_BYTES); } } /** Loading
packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +73 −9 Original line number Diff line number Diff line Loading @@ -271,6 +271,7 @@ public class SettingsProvider extends ContentProvider { @Override public boolean onCreate() { Settings.setInSystemServer(); synchronized (mLock) { mUserManager = UserManager.get(getContext()); mPackageManager = AppGlobals.getPackageManager(); Loading Loading @@ -829,7 +830,8 @@ public class SettingsProvider extends ContentProvider { SettingsState settingsState = mSettingsRegistry.getSettingsLocked( SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM); List<String> names = settingsState.getSettingNamesLocked(); List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM); final int nameCount = names.size(); Loading @@ -852,6 +854,9 @@ public class SettingsProvider extends ContentProvider { Slog.v(LOG_TAG, "getGlobalSetting(" + name + ")"); } // Ensure the caller can access the setting. enforceSettingReadable(name, SETTINGS_TYPE_GLOBAL, UserHandle.getCallingUserId()); // Get the value. synchronized (mLock) { return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_GLOBAL, Loading Loading @@ -954,8 +959,7 @@ public class SettingsProvider extends ContentProvider { final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId); synchronized (mLock) { List<String> names = mSettingsRegistry.getSettingsNamesLocked( SETTINGS_TYPE_SECURE, callingUserId); List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_SECURE, callingUserId); final int nameCount = names.size(); Loading Loading @@ -997,6 +1001,9 @@ public class SettingsProvider extends ContentProvider { // Resolve the userId on whose behalf the call is made. final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); // Ensure the caller can access the setting. enforceSettingReadable(name, SETTINGS_TYPE_SECURE, callingUserId); // Determine the owning user as some profile settings are cloned from the parent. final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name); Loading Loading @@ -1159,8 +1166,7 @@ public class SettingsProvider extends ContentProvider { final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId); synchronized (mLock) { List<String> names = mSettingsRegistry.getSettingsNamesLocked( SETTINGS_TYPE_SYSTEM, callingUserId); List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_SYSTEM, callingUserId); final int nameCount = names.size(); Loading Loading @@ -1191,6 +1197,9 @@ public class SettingsProvider extends ContentProvider { // Resolve the userId on whose behalf the call is made. final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); // Ensure the caller can access the setting. enforceSettingReadable(name, SETTINGS_TYPE_SYSTEM, callingUserId); // Determine the owning user as some profile settings are cloned from the parent. final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name); Loading Loading @@ -1409,10 +1418,16 @@ public class SettingsProvider extends ContentProvider { && (parentId = getGroupParentLocked(userId)) != userId) { // The setting has a dependency and the profile has a parent String dependency = sSystemCloneFromParentOnDependency.get(setting); // Lookup the dependency setting as ourselves, some callers may not have access to it. final long token = Binder.clearCallingIdentity(); try { Setting settingObj = getSecureSetting(dependency, userId); if (settingObj != null && settingObj.getValue().equals("1")) { return parentId; } } finally { Binder.restoreCallingIdentity(token); } } return resolveOwningUserIdLocked(userId, sSystemCloneToManagedSettings, setting); } Loading Loading @@ -1479,6 +1494,55 @@ public class SettingsProvider extends ContentProvider { } } private Set<String> getEphemeralAccessibleSettings(int settingsType) { switch (settingsType) { case SETTINGS_TYPE_GLOBAL: return Settings.Global.EPHEMERAL_SETTINGS; case SETTINGS_TYPE_SECURE: return Settings.Secure.EPHEMERAL_SETTINGS; case SETTINGS_TYPE_SYSTEM: return Settings.System.EPHEMERAL_SETTINGS; default: throw new IllegalArgumentException("Invalid settings type: " + settingsType); } } private List<String> getSettingsNamesLocked(int settingsType, int userId) { ApplicationInfo ai = getCallingApplicationInfoOrThrow(userId); if (ai.isEphemeralApp()) { return new ArrayList<String>(getEphemeralAccessibleSettings(settingsType)); } else { return mSettingsRegistry.getSettingsNamesLocked(settingsType, userId); } } private void enforceSettingReadable(String settingName, int settingsType, int userId) { if (UserHandle.getAppId(Binder.getCallingUid()) < Process.FIRST_APPLICATION_UID) { return; } ApplicationInfo ai = getCallingApplicationInfoOrThrow(userId); if (!ai.isEphemeralApp()) { return; } if (!getEphemeralAccessibleSettings(settingsType).contains(settingName)) { throw new SecurityException("Setting " + settingName + " is not accessible from" + " ephemeral package " + getCallingPackage()); } } private ApplicationInfo getCallingApplicationInfoOrThrow(int userId) { ApplicationInfo ai = null; try { ai = mPackageManager.getApplicationInfo(getCallingPackage(), 0 , userId); } catch (RemoteException ignored) { } if (ai == null) { throw new IllegalStateException("Failed to lookup info for package " + getCallingPackage()); } return ai; } private PackageInfo getCallingPackageInfoOrThrow(int userId) { try { PackageInfo packageInfo = mPackageManager.getPackageInfo( Loading