Loading api/current.txt +2 −0 Original line number Original line Diff line number Diff line Loading @@ -26404,6 +26404,7 @@ package android.provider { public final class Settings { public final class Settings { ctor public Settings(); ctor public Settings(); method public static boolean canDrawOverlays(android.content.Context); field public static final java.lang.String ACTION_ACCESSIBILITY_SETTINGS = "android.settings.ACCESSIBILITY_SETTINGS"; field public static final java.lang.String ACTION_ACCESSIBILITY_SETTINGS = "android.settings.ACCESSIBILITY_SETTINGS"; field public static final java.lang.String ACTION_ADD_ACCOUNT = "android.settings.ADD_ACCOUNT_SETTINGS"; field public static final java.lang.String ACTION_ADD_ACCOUNT = "android.settings.ADD_ACCOUNT_SETTINGS"; field public static final java.lang.String ACTION_AIRPLANE_MODE_SETTINGS = "android.settings.AIRPLANE_MODE_SETTINGS"; field public static final java.lang.String ACTION_AIRPLANE_MODE_SETTINGS = "android.settings.AIRPLANE_MODE_SETTINGS"; Loading Loading @@ -26623,6 +26624,7 @@ package android.provider { public static final class Settings.System extends android.provider.Settings.NameValueTable { public static final class Settings.System extends android.provider.Settings.NameValueTable { ctor public Settings.System(); ctor public Settings.System(); method public static boolean canWrite(android.content.Context); method public static void getConfiguration(android.content.ContentResolver, android.content.res.Configuration); method public static void getConfiguration(android.content.ContentResolver, android.content.res.Configuration); method public static float getFloat(android.content.ContentResolver, java.lang.String, float); method public static float getFloat(android.content.ContentResolver, java.lang.String, float); method public static float getFloat(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException; method public static float getFloat(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException; api/system-current.txt +2 −0 Original line number Original line Diff line number Diff line Loading @@ -28463,6 +28463,7 @@ package android.provider { public final class Settings { public final class Settings { ctor public Settings(); ctor public Settings(); method public static boolean canDrawOverlays(android.content.Context); field public static final java.lang.String ACTION_ACCESSIBILITY_SETTINGS = "android.settings.ACCESSIBILITY_SETTINGS"; field public static final java.lang.String ACTION_ACCESSIBILITY_SETTINGS = "android.settings.ACCESSIBILITY_SETTINGS"; field public static final java.lang.String ACTION_ADD_ACCOUNT = "android.settings.ADD_ACCOUNT_SETTINGS"; field public static final java.lang.String ACTION_ADD_ACCOUNT = "android.settings.ADD_ACCOUNT_SETTINGS"; field public static final java.lang.String ACTION_AIRPLANE_MODE_SETTINGS = "android.settings.AIRPLANE_MODE_SETTINGS"; field public static final java.lang.String ACTION_AIRPLANE_MODE_SETTINGS = "android.settings.AIRPLANE_MODE_SETTINGS"; Loading Loading @@ -28683,6 +28684,7 @@ package android.provider { public static final class Settings.System extends android.provider.Settings.NameValueTable { public static final class Settings.System extends android.provider.Settings.NameValueTable { ctor public Settings.System(); ctor public Settings.System(); method public static boolean canWrite(android.content.Context); method public static void getConfiguration(android.content.ContentResolver, android.content.res.Configuration); method public static void getConfiguration(android.content.ContentResolver, android.content.res.Configuration); method public static float getFloat(android.content.ContentResolver, java.lang.String, float); method public static float getFloat(android.content.ContentResolver, java.lang.String, float); method public static float getFloat(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException; method public static float getFloat(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException; core/java/android/app/AppOpsManager.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -778,7 +778,7 @@ public class AppOpsManager { AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_DEFAULT, // OP_WRITE_SETTINGS AppOpsManager.MODE_DEFAULT, // OP_SYSTEM_ALERT_WINDOW AppOpsManager.MODE_DEFAULT, // OP_SYSTEM_ALERT_WINDOW AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, Loading core/java/android/provider/Settings.java +162 −6 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.annotation.SystemApi; import android.app.ActivityThread; import android.app.ActivityThread; import android.app.AppOpsManager; import android.app.Application; import android.app.Application; import android.app.SearchManager; import android.app.SearchManager; import android.app.WallpaperManager; import android.app.WallpaperManager; Loading @@ -41,6 +42,7 @@ import android.net.ConnectivityManager; import android.net.Uri; import android.net.Uri; import android.net.wifi.WifiManager; import android.net.wifi.WifiManager; import android.os.BatteryManager; import android.os.BatteryManager; import android.os.Binder; import android.os.Bundle; import android.os.Bundle; import android.os.DropBoxManager; import android.os.DropBoxManager; import android.os.IBinder; import android.os.IBinder; Loading Loading @@ -564,13 +566,14 @@ public final class Settings { "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS"; "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS"; /** /** * Activity Action: Show settings to toggle permission to draw on top of * Activity Action: Show screen for controlling which apps can draw on top of other apps. * other apps. * <p> * <p> * In some cases, a matching Activity may not exist, so ensure you * In some cases, a matching Activity may not exist, so ensure you * safeguard against this. * safeguard against this. * <p> * <p> * Input: Nothing. * Input: Optionally, the Intent's data URI can specify the application package name to * directly invoke the management GUI specific to the package name. For example * "package:com.my.app". * <p> * <p> * Output: Nothing. * Output: Nothing. */ */ Loading @@ -579,13 +582,15 @@ public final class Settings { "android.settings.action.MANAGE_OVERLAY_PERMISSION"; "android.settings.action.MANAGE_OVERLAY_PERMISSION"; /** /** * Activity Action: Show settings to toggle apps' capablity to * Activity Action: Show screen for controlling which apps are allowed to write/modify * to read/write system settings. * system settings. * <p> * <p> * In some cases, a matching Activity may not exist, so ensure you * In some cases, a matching Activity may not exist, so ensure you * safeguard against this. * safeguard against this. * <p> * <p> * Input: Nothing. * Input: Optionally, the Intent's data URI can specify the application package name to * directly invoke the management GUI specific to the package name. For example * "package:com.my.app". * <p> * <p> * Output: Nothing. * Output: Nothing. */ */ Loading Loading @@ -1385,6 +1390,23 @@ public final class Settings { } } } } /** * An app can use this method to check if it is currently allowed to draw on top of other * apps. In order to be allowed to do so, an app must first declare the * {@link android.Manifest.permission#SYSTEM_ALERT_WINDOW} permission in its manifest. If it * is currently disallowed, it can prompt the user to grant it this capability through a * management UI by sending an Intent with action * {@link android.provider.Settings#ACTION_MANAGE_OVERLAY_PERMISSION}. * * @param context A context * @return true if the calling app can draw on top of other apps, false otherwise. */ public static boolean canDrawOverlays(Context context) { int uid = Binder.getCallingUid(); return Settings.isCallingPackageAllowedToDrawOverlays(context, uid, Settings .getPackageNameForUid(context, uid), false); } /** /** * System settings, containing miscellaneous system preferences. This * System settings, containing miscellaneous system preferences. This * table holds simple name/value pairs. There are convenience * table holds simple name/value pairs. There are convenience Loading Loading @@ -3658,6 +3680,23 @@ public final class Settings { @Deprecated @Deprecated public static final String WIFI_WATCHDOG_PING_TIMEOUT_MS = public static final String WIFI_WATCHDOG_PING_TIMEOUT_MS = Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS; Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS; /** * An app can use this method to check if it is currently allowed to write or modify system * settings. In order to gain write access to the system settings, an app must declare the * {@link android.Manifest.permission#WRITE_SETTINGS} permission in its manifest. If it is * currently disallowed, it can prompt the user to grant it this capability through a * management UI by sending an Intent with action * {@link android.provider.Settings#ACTION_MANAGE_WRITE_SETTINGS}. * * @param context A context * @return true if the calling app can write to system settings, false otherwise */ public static boolean canWrite(Context context) { int uid = Binder.getCallingUid(); return isCallingPackageAllowedToWriteSettings(context, uid, getPackageNameForUid( context, uid), false); } } } /** /** Loading Loading @@ -8205,4 +8244,121 @@ public final class Settings { public static String getGTalkDeviceId(long androidId) { public static String getGTalkDeviceId(long androidId) { return "android-" + Long.toHexString(androidId); return "android-" + Long.toHexString(androidId); } } /** * Performs a strict and comprehensive check of whether a calling package is allowed to * write/modify system settings, as the condition differs for pre-M, M+, and * privileged/preinstalled apps. If the provided uid does not match the * callingPackage, a negative result will be returned. * @hide */ public static boolean isCallingPackageAllowedToWriteSettings(Context context, int uid, String callingPackage, boolean throwException) { return isCallingPackageAllowedToPerformAppOpsProtectedOperation(context, uid, callingPackage, throwException, AppOpsManager.OP_WRITE_SETTINGS, android.Manifest.permission.WRITE_SETTINGS, false); } /** * Performs a strict and comprehensive check of whether a calling package is allowed to * write/modify system settings, as the condition differs for pre-M, M+, and * privileged/preinstalled apps. If the provided uid does not match the * callingPackage, a negative result will be returned. * * Note: if the check is successful, the operation of this app will be updated to the * current time. * @hide */ public static boolean checkAndNoteWriteSettingsOperation(Context context, int uid, String callingPackage, boolean throwException) { return isCallingPackageAllowedToPerformAppOpsProtectedOperation(context, uid, callingPackage, throwException, AppOpsManager.OP_WRITE_SETTINGS, android.Manifest.permission.WRITE_SETTINGS, true); } /** * Performs a strict and comprehensive check of whether a calling package is allowed to * draw on top of other apps, as the conditions differs for pre-M, M+, and * privileged/preinstalled apps. If the provided uid does not match the callingPackage, * a negative result will be returned. * @hide */ public static boolean isCallingPackageAllowedToDrawOverlays(Context context, int uid, String callingPackage, boolean throwException) { return isCallingPackageAllowedToPerformAppOpsProtectedOperation(context, uid, callingPackage, throwException, AppOpsManager.OP_SYSTEM_ALERT_WINDOW, android.Manifest.permission.SYSTEM_ALERT_WINDOW, false); } /** * Performs a strict and comprehensive check of whether a calling package is allowed to * draw on top of other apps, as the conditions differs for pre-M, M+, and * privileged/preinstalled apps. If the provided uid does not match the callingPackage, * a negative result will be returned. * * Note: if the check is successful, the operation of this app will be updated to the * current time. * @hide */ public static boolean checkAndNoteDrawOverlaysOperation(Context context, int uid, String callingPackage, boolean throwException) { return isCallingPackageAllowedToPerformAppOpsProtectedOperation(context, uid, callingPackage, throwException, AppOpsManager.OP_SYSTEM_ALERT_WINDOW, android.Manifest.permission.SYSTEM_ALERT_WINDOW, true); } /** * Helper method to perform a general and comprehensive check of whether an operation that is * protected by appops can be performed by a caller or not. e.g. OP_SYSTEM_ALERT_WINDOW and * OP_WRITE_SETTINGS * @hide */ public static boolean isCallingPackageAllowedToPerformAppOpsProtectedOperation(Context context, int uid, String callingPackage, boolean throwException, int appOpsOpCode, String permissionName, boolean makeNote) { if (callingPackage == null) { return false; } AppOpsManager appOpsMgr = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); int mode = AppOpsManager.MODE_DEFAULT; if (makeNote) { mode = appOpsMgr.noteOpNoThrow(appOpsOpCode, uid, callingPackage); } else { mode = appOpsMgr.checkOpNoThrow(appOpsOpCode, uid, callingPackage); } switch (mode) { case AppOpsManager.MODE_ALLOWED: return true; case AppOpsManager.MODE_DEFAULT: // this is the default operating mode after an app's installation if (!throwException) { return context.checkCallingOrSelfPermission(permissionName) == PackageManager.PERMISSION_GRANTED; } default: // this is for all other cases trickled down here... if (!throwException) { return false; } } throw new SecurityException(callingPackage + " was not granted " + permissionName + " permission"); } /** * Retrieves a correponding package name for a given uid. It will query all * packages that are associated with the given uid, but it will return only * the zeroth result. * Note: If package could not be found, a null is returned. * @hide */ public static String getPackageNameForUid(Context context, int uid) { String[] packages = context.getPackageManager().getPackagesForUid(uid); if (packages == null) { return null; } return packages[0]; } } } packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +8 −40 Original line number Original line Diff line number Diff line Loading @@ -643,11 +643,6 @@ public class SettingsProvider extends ContentProvider { // Make sure the caller can change the settings - treated as secure. // Make sure the caller can change the settings - treated as secure. enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS); enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS); // Verify whether this operation is allowed for the calling package. if (!isAppOpWriteSettingsAllowedForCallingPackage()) { return false; } // Resolve the userId on whose behalf the call is made. // Resolve the userId on whose behalf the call is made. final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); Loading Loading @@ -773,11 +768,6 @@ public class SettingsProvider extends ContentProvider { // Make sure the caller can change the settings. // Make sure the caller can change the settings. enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS); enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS); // Verify whether this operation is allowed for the calling package. if (!isAppOpWriteSettingsAllowedForCallingPackage()) { return false; } // Resolve the userId on whose behalf the call is made. // Resolve the userId on whose behalf the call is made. final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); Loading Loading @@ -904,14 +894,13 @@ public class SettingsProvider extends ContentProvider { private boolean mutateSystemSetting(String name, String value, int runAsUserId, private boolean mutateSystemSetting(String name, String value, int runAsUserId, int operation) { int operation) { // Check for permissions first. if (!hasWriteSecureSettingsPermission()) { if (!hasPermissionsToMutateSystemSettings()) { // If the caller doesn't hold WRITE_SECURE_SETTINGS, we verify whether this // operation is allowed for the calling package through appops. if (!Settings.checkAndNoteWriteSettingsOperation(getContext(), Binder.getCallingUid(), getCallingPackage(), true)) { return false; return false; } } // Verify whether this operation is allowed for the calling package. if (!isAppOpWriteSettingsAllowedForCallingPackage()) { return false; } } // Enforce what the calling package can mutate the system settings. // Enforce what the calling package can mutate the system settings. Loading Loading @@ -956,25 +945,13 @@ public class SettingsProvider extends ContentProvider { } } } } private boolean hasPermissionsToMutateSystemSettings() { private boolean hasWriteSecureSettingsPermission() { // Write secure settings is a more protected permission. If caller has it we are good. // Write secure settings is a more protected permission. If caller has it we are good. if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS) if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS) == PackageManager.PERMISSION_GRANTED) { == PackageManager.PERMISSION_GRANTED) { return true; return true; } } // The write settings permission gates mutation of system settings. if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SETTINGS) == PackageManager.PERMISSION_GRANTED) { return true; } // Excpet we let system apps change system settings without the permission. PackageInfo packageInfo = getCallingPackageInfoOrThrow(); if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { return true; } return false; return false; } } Loading Loading @@ -1102,15 +1079,6 @@ public class SettingsProvider extends ContentProvider { } } } } private boolean isAppOpWriteSettingsAllowedForCallingPackage() { final int callingUid = Binder.getCallingUid(); mAppOpsManager.checkPackage(Binder.getCallingUid(), getCallingPackage()); return mAppOpsManager.noteOp(AppOpsManager.OP_WRITE_SETTINGS, callingUid, getCallingPackage()) == AppOpsManager.MODE_ALLOWED; } private void enforceWritePermission(String permission) { private void enforceWritePermission(String permission) { if (getContext().checkCallingOrSelfPermission(permission) if (getContext().checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { != PackageManager.PERMISSION_GRANTED) { Loading Loading
api/current.txt +2 −0 Original line number Original line Diff line number Diff line Loading @@ -26404,6 +26404,7 @@ package android.provider { public final class Settings { public final class Settings { ctor public Settings(); ctor public Settings(); method public static boolean canDrawOverlays(android.content.Context); field public static final java.lang.String ACTION_ACCESSIBILITY_SETTINGS = "android.settings.ACCESSIBILITY_SETTINGS"; field public static final java.lang.String ACTION_ACCESSIBILITY_SETTINGS = "android.settings.ACCESSIBILITY_SETTINGS"; field public static final java.lang.String ACTION_ADD_ACCOUNT = "android.settings.ADD_ACCOUNT_SETTINGS"; field public static final java.lang.String ACTION_ADD_ACCOUNT = "android.settings.ADD_ACCOUNT_SETTINGS"; field public static final java.lang.String ACTION_AIRPLANE_MODE_SETTINGS = "android.settings.AIRPLANE_MODE_SETTINGS"; field public static final java.lang.String ACTION_AIRPLANE_MODE_SETTINGS = "android.settings.AIRPLANE_MODE_SETTINGS"; Loading Loading @@ -26623,6 +26624,7 @@ package android.provider { public static final class Settings.System extends android.provider.Settings.NameValueTable { public static final class Settings.System extends android.provider.Settings.NameValueTable { ctor public Settings.System(); ctor public Settings.System(); method public static boolean canWrite(android.content.Context); method public static void getConfiguration(android.content.ContentResolver, android.content.res.Configuration); method public static void getConfiguration(android.content.ContentResolver, android.content.res.Configuration); method public static float getFloat(android.content.ContentResolver, java.lang.String, float); method public static float getFloat(android.content.ContentResolver, java.lang.String, float); method public static float getFloat(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException; method public static float getFloat(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
api/system-current.txt +2 −0 Original line number Original line Diff line number Diff line Loading @@ -28463,6 +28463,7 @@ package android.provider { public final class Settings { public final class Settings { ctor public Settings(); ctor public Settings(); method public static boolean canDrawOverlays(android.content.Context); field public static final java.lang.String ACTION_ACCESSIBILITY_SETTINGS = "android.settings.ACCESSIBILITY_SETTINGS"; field public static final java.lang.String ACTION_ACCESSIBILITY_SETTINGS = "android.settings.ACCESSIBILITY_SETTINGS"; field public static final java.lang.String ACTION_ADD_ACCOUNT = "android.settings.ADD_ACCOUNT_SETTINGS"; field public static final java.lang.String ACTION_ADD_ACCOUNT = "android.settings.ADD_ACCOUNT_SETTINGS"; field public static final java.lang.String ACTION_AIRPLANE_MODE_SETTINGS = "android.settings.AIRPLANE_MODE_SETTINGS"; field public static final java.lang.String ACTION_AIRPLANE_MODE_SETTINGS = "android.settings.AIRPLANE_MODE_SETTINGS"; Loading Loading @@ -28683,6 +28684,7 @@ package android.provider { public static final class Settings.System extends android.provider.Settings.NameValueTable { public static final class Settings.System extends android.provider.Settings.NameValueTable { ctor public Settings.System(); ctor public Settings.System(); method public static boolean canWrite(android.content.Context); method public static void getConfiguration(android.content.ContentResolver, android.content.res.Configuration); method public static void getConfiguration(android.content.ContentResolver, android.content.res.Configuration); method public static float getFloat(android.content.ContentResolver, java.lang.String, float); method public static float getFloat(android.content.ContentResolver, java.lang.String, float); method public static float getFloat(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException; method public static float getFloat(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
core/java/android/app/AppOpsManager.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -778,7 +778,7 @@ public class AppOpsManager { AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_DEFAULT, // OP_WRITE_SETTINGS AppOpsManager.MODE_DEFAULT, // OP_SYSTEM_ALERT_WINDOW AppOpsManager.MODE_DEFAULT, // OP_SYSTEM_ALERT_WINDOW AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, Loading
core/java/android/provider/Settings.java +162 −6 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.annotation.SystemApi; import android.app.ActivityThread; import android.app.ActivityThread; import android.app.AppOpsManager; import android.app.Application; import android.app.Application; import android.app.SearchManager; import android.app.SearchManager; import android.app.WallpaperManager; import android.app.WallpaperManager; Loading @@ -41,6 +42,7 @@ import android.net.ConnectivityManager; import android.net.Uri; import android.net.Uri; import android.net.wifi.WifiManager; import android.net.wifi.WifiManager; import android.os.BatteryManager; import android.os.BatteryManager; import android.os.Binder; import android.os.Bundle; import android.os.Bundle; import android.os.DropBoxManager; import android.os.DropBoxManager; import android.os.IBinder; import android.os.IBinder; Loading Loading @@ -564,13 +566,14 @@ public final class Settings { "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS"; "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS"; /** /** * Activity Action: Show settings to toggle permission to draw on top of * Activity Action: Show screen for controlling which apps can draw on top of other apps. * other apps. * <p> * <p> * In some cases, a matching Activity may not exist, so ensure you * In some cases, a matching Activity may not exist, so ensure you * safeguard against this. * safeguard against this. * <p> * <p> * Input: Nothing. * Input: Optionally, the Intent's data URI can specify the application package name to * directly invoke the management GUI specific to the package name. For example * "package:com.my.app". * <p> * <p> * Output: Nothing. * Output: Nothing. */ */ Loading @@ -579,13 +582,15 @@ public final class Settings { "android.settings.action.MANAGE_OVERLAY_PERMISSION"; "android.settings.action.MANAGE_OVERLAY_PERMISSION"; /** /** * Activity Action: Show settings to toggle apps' capablity to * Activity Action: Show screen for controlling which apps are allowed to write/modify * to read/write system settings. * system settings. * <p> * <p> * In some cases, a matching Activity may not exist, so ensure you * In some cases, a matching Activity may not exist, so ensure you * safeguard against this. * safeguard against this. * <p> * <p> * Input: Nothing. * Input: Optionally, the Intent's data URI can specify the application package name to * directly invoke the management GUI specific to the package name. For example * "package:com.my.app". * <p> * <p> * Output: Nothing. * Output: Nothing. */ */ Loading Loading @@ -1385,6 +1390,23 @@ public final class Settings { } } } } /** * An app can use this method to check if it is currently allowed to draw on top of other * apps. In order to be allowed to do so, an app must first declare the * {@link android.Manifest.permission#SYSTEM_ALERT_WINDOW} permission in its manifest. If it * is currently disallowed, it can prompt the user to grant it this capability through a * management UI by sending an Intent with action * {@link android.provider.Settings#ACTION_MANAGE_OVERLAY_PERMISSION}. * * @param context A context * @return true if the calling app can draw on top of other apps, false otherwise. */ public static boolean canDrawOverlays(Context context) { int uid = Binder.getCallingUid(); return Settings.isCallingPackageAllowedToDrawOverlays(context, uid, Settings .getPackageNameForUid(context, uid), false); } /** /** * System settings, containing miscellaneous system preferences. This * System settings, containing miscellaneous system preferences. This * table holds simple name/value pairs. There are convenience * table holds simple name/value pairs. There are convenience Loading Loading @@ -3658,6 +3680,23 @@ public final class Settings { @Deprecated @Deprecated public static final String WIFI_WATCHDOG_PING_TIMEOUT_MS = public static final String WIFI_WATCHDOG_PING_TIMEOUT_MS = Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS; Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS; /** * An app can use this method to check if it is currently allowed to write or modify system * settings. In order to gain write access to the system settings, an app must declare the * {@link android.Manifest.permission#WRITE_SETTINGS} permission in its manifest. If it is * currently disallowed, it can prompt the user to grant it this capability through a * management UI by sending an Intent with action * {@link android.provider.Settings#ACTION_MANAGE_WRITE_SETTINGS}. * * @param context A context * @return true if the calling app can write to system settings, false otherwise */ public static boolean canWrite(Context context) { int uid = Binder.getCallingUid(); return isCallingPackageAllowedToWriteSettings(context, uid, getPackageNameForUid( context, uid), false); } } } /** /** Loading Loading @@ -8205,4 +8244,121 @@ public final class Settings { public static String getGTalkDeviceId(long androidId) { public static String getGTalkDeviceId(long androidId) { return "android-" + Long.toHexString(androidId); return "android-" + Long.toHexString(androidId); } } /** * Performs a strict and comprehensive check of whether a calling package is allowed to * write/modify system settings, as the condition differs for pre-M, M+, and * privileged/preinstalled apps. If the provided uid does not match the * callingPackage, a negative result will be returned. * @hide */ public static boolean isCallingPackageAllowedToWriteSettings(Context context, int uid, String callingPackage, boolean throwException) { return isCallingPackageAllowedToPerformAppOpsProtectedOperation(context, uid, callingPackage, throwException, AppOpsManager.OP_WRITE_SETTINGS, android.Manifest.permission.WRITE_SETTINGS, false); } /** * Performs a strict and comprehensive check of whether a calling package is allowed to * write/modify system settings, as the condition differs for pre-M, M+, and * privileged/preinstalled apps. If the provided uid does not match the * callingPackage, a negative result will be returned. * * Note: if the check is successful, the operation of this app will be updated to the * current time. * @hide */ public static boolean checkAndNoteWriteSettingsOperation(Context context, int uid, String callingPackage, boolean throwException) { return isCallingPackageAllowedToPerformAppOpsProtectedOperation(context, uid, callingPackage, throwException, AppOpsManager.OP_WRITE_SETTINGS, android.Manifest.permission.WRITE_SETTINGS, true); } /** * Performs a strict and comprehensive check of whether a calling package is allowed to * draw on top of other apps, as the conditions differs for pre-M, M+, and * privileged/preinstalled apps. If the provided uid does not match the callingPackage, * a negative result will be returned. * @hide */ public static boolean isCallingPackageAllowedToDrawOverlays(Context context, int uid, String callingPackage, boolean throwException) { return isCallingPackageAllowedToPerformAppOpsProtectedOperation(context, uid, callingPackage, throwException, AppOpsManager.OP_SYSTEM_ALERT_WINDOW, android.Manifest.permission.SYSTEM_ALERT_WINDOW, false); } /** * Performs a strict and comprehensive check of whether a calling package is allowed to * draw on top of other apps, as the conditions differs for pre-M, M+, and * privileged/preinstalled apps. If the provided uid does not match the callingPackage, * a negative result will be returned. * * Note: if the check is successful, the operation of this app will be updated to the * current time. * @hide */ public static boolean checkAndNoteDrawOverlaysOperation(Context context, int uid, String callingPackage, boolean throwException) { return isCallingPackageAllowedToPerformAppOpsProtectedOperation(context, uid, callingPackage, throwException, AppOpsManager.OP_SYSTEM_ALERT_WINDOW, android.Manifest.permission.SYSTEM_ALERT_WINDOW, true); } /** * Helper method to perform a general and comprehensive check of whether an operation that is * protected by appops can be performed by a caller or not. e.g. OP_SYSTEM_ALERT_WINDOW and * OP_WRITE_SETTINGS * @hide */ public static boolean isCallingPackageAllowedToPerformAppOpsProtectedOperation(Context context, int uid, String callingPackage, boolean throwException, int appOpsOpCode, String permissionName, boolean makeNote) { if (callingPackage == null) { return false; } AppOpsManager appOpsMgr = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); int mode = AppOpsManager.MODE_DEFAULT; if (makeNote) { mode = appOpsMgr.noteOpNoThrow(appOpsOpCode, uid, callingPackage); } else { mode = appOpsMgr.checkOpNoThrow(appOpsOpCode, uid, callingPackage); } switch (mode) { case AppOpsManager.MODE_ALLOWED: return true; case AppOpsManager.MODE_DEFAULT: // this is the default operating mode after an app's installation if (!throwException) { return context.checkCallingOrSelfPermission(permissionName) == PackageManager.PERMISSION_GRANTED; } default: // this is for all other cases trickled down here... if (!throwException) { return false; } } throw new SecurityException(callingPackage + " was not granted " + permissionName + " permission"); } /** * Retrieves a correponding package name for a given uid. It will query all * packages that are associated with the given uid, but it will return only * the zeroth result. * Note: If package could not be found, a null is returned. * @hide */ public static String getPackageNameForUid(Context context, int uid) { String[] packages = context.getPackageManager().getPackagesForUid(uid); if (packages == null) { return null; } return packages[0]; } } }
packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +8 −40 Original line number Original line Diff line number Diff line Loading @@ -643,11 +643,6 @@ public class SettingsProvider extends ContentProvider { // Make sure the caller can change the settings - treated as secure. // Make sure the caller can change the settings - treated as secure. enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS); enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS); // Verify whether this operation is allowed for the calling package. if (!isAppOpWriteSettingsAllowedForCallingPackage()) { return false; } // Resolve the userId on whose behalf the call is made. // Resolve the userId on whose behalf the call is made. final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); Loading Loading @@ -773,11 +768,6 @@ public class SettingsProvider extends ContentProvider { // Make sure the caller can change the settings. // Make sure the caller can change the settings. enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS); enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS); // Verify whether this operation is allowed for the calling package. if (!isAppOpWriteSettingsAllowedForCallingPackage()) { return false; } // Resolve the userId on whose behalf the call is made. // Resolve the userId on whose behalf the call is made. final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); Loading Loading @@ -904,14 +894,13 @@ public class SettingsProvider extends ContentProvider { private boolean mutateSystemSetting(String name, String value, int runAsUserId, private boolean mutateSystemSetting(String name, String value, int runAsUserId, int operation) { int operation) { // Check for permissions first. if (!hasWriteSecureSettingsPermission()) { if (!hasPermissionsToMutateSystemSettings()) { // If the caller doesn't hold WRITE_SECURE_SETTINGS, we verify whether this // operation is allowed for the calling package through appops. if (!Settings.checkAndNoteWriteSettingsOperation(getContext(), Binder.getCallingUid(), getCallingPackage(), true)) { return false; return false; } } // Verify whether this operation is allowed for the calling package. if (!isAppOpWriteSettingsAllowedForCallingPackage()) { return false; } } // Enforce what the calling package can mutate the system settings. // Enforce what the calling package can mutate the system settings. Loading Loading @@ -956,25 +945,13 @@ public class SettingsProvider extends ContentProvider { } } } } private boolean hasPermissionsToMutateSystemSettings() { private boolean hasWriteSecureSettingsPermission() { // Write secure settings is a more protected permission. If caller has it we are good. // Write secure settings is a more protected permission. If caller has it we are good. if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS) if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS) == PackageManager.PERMISSION_GRANTED) { == PackageManager.PERMISSION_GRANTED) { return true; return true; } } // The write settings permission gates mutation of system settings. if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SETTINGS) == PackageManager.PERMISSION_GRANTED) { return true; } // Excpet we let system apps change system settings without the permission. PackageInfo packageInfo = getCallingPackageInfoOrThrow(); if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { return true; } return false; return false; } } Loading Loading @@ -1102,15 +1079,6 @@ public class SettingsProvider extends ContentProvider { } } } } private boolean isAppOpWriteSettingsAllowedForCallingPackage() { final int callingUid = Binder.getCallingUid(); mAppOpsManager.checkPackage(Binder.getCallingUid(), getCallingPackage()); return mAppOpsManager.noteOp(AppOpsManager.OP_WRITE_SETTINGS, callingUid, getCallingPackage()) == AppOpsManager.MODE_ALLOWED; } private void enforceWritePermission(String permission) { private void enforceWritePermission(String permission) { if (getContext().checkCallingOrSelfPermission(permission) if (getContext().checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { != PackageManager.PERMISSION_GRANTED) { Loading