Loading core/java/android/content/PermissionChecker.java +266 −30 Original line number Diff line number Diff line Loading @@ -50,6 +50,19 @@ import java.lang.annotation.RetentionPolicy; * permission model for which the user had disabled the "permission" * which is achieved by disallowing the corresponding app op. * </p> * <p> * This class has two types of methods and you should be careful which * type to call based on whether permission protected data is being * passed to the app or you are just checking whether the app holds a * permission. The reason is that a permission check requires checking * the runtime permission and if it is granted checking the corresponding * app op as for apps not supporting the runtime mode we never revoke * permissions but disable app ops. Since there are two types of app op * checks, one that does not leave a record an action was performed and * another the does, one needs to call the preflight flavor of the checks * named xxxForPreflight only if no private data is being delivered but * a permission check is what is needed and the xxxForDataDelivery where * the permission check is right before private data delivery. * * @hide */ Loading @@ -63,6 +76,9 @@ public final class PermissionChecker { /** Permission result: The permission is denied because the app op is not allowed. */ public static final int PERMISSION_DENIED_APP_OP = PackageManager.PERMISSION_DENIED - 1; /** Constant when the PID for which we check permissions is unknown. */ public static final int PID_UNKNOWN = -1; /** @hide */ @IntDef({PERMISSION_GRANTED, PERMISSION_DENIED, Loading @@ -78,47 +94,127 @@ public final class PermissionChecker { * Checks whether a given package in a UID and PID has a given permission * and whether the app op that corresponds to this permission is allowed. * * <strong>NOTE:</strong> Use this method only for permission checks at the * point where you will deliver the permission protected data to clients. * * <p>For example, if an app registers a location listener it should have the location * permission but no data is actually sent to the app at the moment of registration * and you should use {@link #checkPermissionForPreflight(Context, String, int, int, String)} * to determine if the app has or may have location permission (if app has only foreground * location the grant state depends on the app's fg/gb state) and this check will not * leave a trace that permission protected data was delivered. When you are about to * deliver the location data to a registered listener you should use this method which * will evaluate the permission access based on the current fg/bg state of the app and * leave a record that the data was accessed. * * @param context Context for accessing resources. * @param permission The permission to check. * @param pid The process id for which to check. * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID * is not known. * @param uid The uid for which to check. * @param packageName The package name for which to check. If null the * the first package for the calling UID will be used. * @return The permission check result which is either {@link #PERMISSION_GRANTED} * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. * * @see #checkPermissionForPreflight(Context, String, int, int, String) */ @PermissionResult public static int checkPermission(@NonNull Context context, @NonNull String permission, int pid, int uid, @Nullable String packageName) { if (context.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_DENIED) { return PERMISSION_DENIED; } AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); String op = appOpsManager.permissionToOp(permission); if (op == null) { return PERMISSION_GRANTED; } if (packageName == null) { String[] packageNames = context.getPackageManager().getPackagesForUid(uid); if (packageNames == null || packageNames.length <= 0) { return PERMISSION_DENIED; } packageName = packageNames[0]; public static int checkPermissionForDataDelivery(@NonNull Context context, @NonNull String permission, int pid, int uid, @Nullable String packageName) { return checkPermissionCommon(context, permission, pid, uid, packageName, true /*forDataDelivery*/); } if (appOpsManager.noteProxyOpNoThrow(op, packageName, uid) != AppOpsManager.MODE_ALLOWED) { return PERMISSION_DENIED_APP_OP; /** * Checks whether a given package in a UID and PID has a given permission * and whether the app op that corresponds to this permission is allowed. * * <strong>NOTE:</strong> Use this method only for permission checks at the * preflight point where you will not deliver the permission protected data * to clients but schedule permission data delivery, apps register listeners, * etc. * * <p>For example, if an app registers a location listener it should have the location * permission but no data is actually sent to the app at the moment of registration * and you should use this method to determine if the app has or may have location * permission (if app has only foreground location the grant state depends on the app's * fg/gb state) and this check will not leave a trace that permission protected data * was delivered. When you are about to deliver the location data to a registered * listener you should use {@link #checkPermissionForDataDelivery(Context, String, * int, int, String)} which will evaluate the permission access based on the current * fg/bg state of the app and leave a record that the data was accessed. * * @param context Context for accessing resources. * @param permission The permission to check. * @param pid The process id for which to check. * @param uid The uid for which to check. * @param packageName The package name for which to check. If null the * the first package for the calling UID will be used. * @return The permission check result which is either {@link #PERMISSION_GRANTED} * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. * * @see #checkPermissionForDataDelivery(Context, String, int, int, String) */ @PermissionResult public static int checkPermissionForPreflight(@NonNull Context context, @NonNull String permission, int pid, int uid, @Nullable String packageName) { return checkPermissionCommon(context, permission, pid, uid, packageName, false /*forDataDelivery*/); } return PERMISSION_GRANTED; /** * Checks whether your app has a given permission and whether the app op * that corresponds to this permission is allowed. * * <strong>NOTE:</strong> Use this method only for permission checks at the * point where you will deliver the permission protected data to clients. * * <p>For example, if an app registers a location listener it should have the location * permission but no data is actually sent to the app at the moment of registration * and you should use {@link #checkSelfPermissionForPreflight(Context, String)} * to determine if the app has or may have location permission (if app has only foreground * location the grant state depends on the app's fg/gb state) and this check will not * leave a trace that permission protected data was delivered. When you are about to * deliver the location data to a registered listener you should use this method * which will evaluate the permission access based on the current fg/bg state of the * app and leave a record that the data was accessed. * * <p>This API assumes the the {@link Binder#getCallingUid()} is the same as * {@link Process#myUid()}. * * @param context Context for accessing resources. * @param permission The permission to check. * @return The permission check result which is either {@link #PERMISSION_GRANTED} * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. * * @see #checkSelfPermissionForPreflight(Context, String) */ @PermissionResult public static int checkSelfPermissionForDataDelivery(@NonNull Context context, @NonNull String permission) { return checkPermissionForDataDelivery(context, permission, Process.myPid(), Process.myUid(), context.getPackageName()); } /** * Checks whether your app has a given permission and whether the app op * that corresponds to this permission is allowed. * * <strong>NOTE:</strong> Use this method only for permission checks at the * preflight point where you will not deliver the permission protected data * to clients but schedule permission data delivery, apps register listeners, * etc. * * <p>For example, if an app registers a location listener it should have the location * permission but no data is actually sent to the app at the moment of registration * and you should use this method to determine if the app has or may have location * permission (if app has only foreground location the grant state depends on the * app's fg/gb state) and this check will not leave a trace that permission protected * data was delivered. When you are about to deliver the location data to a registered * listener you should use this method which will evaluate the permission access based * on the current fg/bg state of the app and leave a record that the data was accessed. * * <p>This API assumes the the {@link Binder#getCallingUid()} is the same as * {@link Process#myUid()}. * Loading @@ -126,11 +222,13 @@ public final class PermissionChecker { * @param permission The permission to check. * @return The permission check result which is either {@link #PERMISSION_GRANTED} * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. * * @see #checkSelfPermissionForDataDelivery(Context, String) */ @PermissionResult public static int checkSelfPermission(@NonNull Context context, public static int checkSelfPermissionForPreflight(@NonNull Context context, @NonNull String permission) { return checkPermission(context, permission, Process.myPid(), return checkPermissionForPreflight(context, permission, Process.myPid(), Process.myUid(), context.getPackageName()); } Loading @@ -138,20 +236,106 @@ public final class PermissionChecker { * Checks whether the IPC you are handling has a given permission and whether * the app op that corresponds to this permission is allowed. * * <strong>NOTE:</strong> Use this method only for permission checks at the * point where you will deliver the permission protected data to clients. * * <p>For example, if an app registers a location listener it should have the location * permission but no data is actually sent to the app at the moment of registration * and you should use {@link #checkCallingPermissionForPreflight(Context, String, String)} * to determine if the app has or may have location permission (if app has only foreground * location the grant state depends on the app's fg/gb state) and this check will not * leave a trace that permission protected data was delivered. When you are about to * deliver the location data to a registered listener you should use this method which * will evaluate the permission access based on the current fg/bg state of the app and * leave a record that the data was accessed. * * @param context Context for accessing resources. * @param permission The permission to check. * @param packageName The package name making the IPC. If null the * the first package for the calling UID will be used. * @return The permission check result which is either {@link #PERMISSION_GRANTED} * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. * * @see #checkCallingPermissionForPreflight(Context, String, String) */ @PermissionResult public static int checkCallingPermissionForDataDelivery(@NonNull Context context, @NonNull String permission, @Nullable String packageName) { if (Binder.getCallingPid() == Process.myPid()) { return PERMISSION_DENIED; } return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(), Binder.getCallingUid(), packageName); } /** * Checks whether the IPC you are handling has a given permission and whether * the app op that corresponds to this permission is allowed. * * <strong>NOTE:</strong> Use this method only for permission checks at the * preflight point where you will not deliver the permission protected data * to clients but schedule permission data delivery, apps register listeners, * etc. * * <p>For example, if an app registers a location listener it should have the location * permission but no data is actually sent to the app at the moment of registration * and you should use this method to determine if the app has or may have location * permission (if app has only foreground location the grant state depends on the app's * fg/gb state) and this check will not leave a trace that permission protected data * was delivered. When you are about to deliver the location data to a registered * listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context, * String)} which will evaluate the permission access based on the current fg/bg state * of the app and leave a record that the data was accessed. * * @param context Context for accessing resources. * @param permission The permission to check. * @param packageName The package name making the IPC. If null the * the first package for the calling UID will be used. * @return The permission check result which is either {@link #PERMISSION_GRANTED} * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. * * @see #checkCallingPermissionForDataDelivery(Context, String, String) */ @PermissionResult public static int checkCallingPermission(@NonNull Context context, public static int checkCallingPermissionForPreflight(@NonNull Context context, @NonNull String permission, @Nullable String packageName) { if (Binder.getCallingPid() == Process.myPid()) { return PERMISSION_DENIED; } return checkPermission(context, permission, Binder.getCallingPid(), return checkPermissionForPreflight(context, permission, Binder.getCallingPid(), Binder.getCallingUid(), packageName); } /** * Checks whether the IPC you are handling or your app has a given permission * and whether the app op that corresponds to this permission is allowed. * * <strong>NOTE:</strong> Use this method only for permission checks at the * point where you will deliver the permission protected data to clients. * * <p>For example, if an app registers a location listener it should have the location * permission but no data is actually sent to the app at the moment of registration * and you should use {@link #checkCallingOrSelfPermissionForPreflight(Context, String)} * to determine if the app has or may have location permission (if app has only foreground * location the grant state depends on the app's fg/gb state) and this check will not * leave a trace that permission protected data was delivered. When you are about to * deliver the location data to a registered listener you should use this method which * will evaluate the permission access based on the current fg/bg state of the app and * leave a record that the data was accessed. * * @param context Context for accessing resources. * @param permission The permission to check. * @return The permission check result which is either {@link #PERMISSION_GRANTED} * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. * * @see #checkCallingOrSelfPermissionForPreflight(Context, String) */ @PermissionResult public static int checkCallingOrSelfPermissionForDataDelivery(@NonNull Context context, @NonNull String permission) { String packageName = (Binder.getCallingPid() == Process.myPid()) ? context.getPackageName() : null; return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(), Binder.getCallingUid(), packageName); } Loading @@ -159,17 +343,69 @@ public final class PermissionChecker { * Checks whether the IPC you are handling or your app has a given permission * and whether the app op that corresponds to this permission is allowed. * * <strong>NOTE:</strong> Use this method only for permission checks at the * preflight point where you will not deliver the permission protected data * to clients but schedule permission data delivery, apps register listeners, * etc. * * <p>For example, if an app registers a location listener it should have the location * permission but no data is actually sent to the app at the moment of registration * and you should use this method to determine if the app has or may have location * permission (if app has only foreground location the grant state depends on the * app's fg/gb state) and this check will not leave a trace that permission protected * data was delivered. When you are about to deliver the location data to a registered * listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context, * String)} which will evaluate the permission access based on the current fg/bg state * of the app and leave a record that the data was accessed. * * @param context Context for accessing resources. * @param permission The permission to check. * @return The permission check result which is either {@link #PERMISSION_GRANTED} * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. * * @see #checkCallingOrSelfPermissionForDataDelivery(Context, String) */ @PermissionResult public static int checkCallingOrSelfPermission(@NonNull Context context, public static int checkCallingOrSelfPermissionForPreflight(@NonNull Context context, @NonNull String permission) { String packageName = (Binder.getCallingPid() == Process.myPid()) ? context.getPackageName() : null; return checkPermission(context, permission, Binder.getCallingPid(), return checkPermissionForPreflight(context, permission, Binder.getCallingPid(), Binder.getCallingUid(), packageName); } private static int checkPermissionCommon(@NonNull Context context, @NonNull String permission, int pid, int uid, @Nullable String packageName, boolean forDataDelivery) { if (context.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_DENIED) { return PERMISSION_DENIED; } AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); String op = appOpsManager.permissionToOp(permission); if (op == null) { return PERMISSION_GRANTED; } if (packageName == null) { String[] packageNames = context.getPackageManager().getPackagesForUid(uid); if (packageNames == null || packageNames.length <= 0) { return PERMISSION_DENIED; } packageName = packageNames[0]; } if (forDataDelivery) { if (appOpsManager.noteProxyOpNoThrow(op, packageName, uid) != AppOpsManager.MODE_ALLOWED) { return PERMISSION_DENIED_APP_OP; } } else { final int mode = appOpsManager.unsafeCheckOpRawNoThrow(op, uid, packageName); if (mode != AppOpsManager.MODE_ALLOWED && mode != AppOpsManager.MODE_FOREGROUND) { return PERMISSION_DENIED_APP_OP; } } return PERMISSION_GRANTED; } } core/java/android/speech/RecognitionService.java +17 −7 Original line number Diff line number Diff line Loading @@ -170,14 +170,24 @@ public abstract class RecognitionService extends Service { * Checks whether the caller has sufficient permissions * * @param listener to send the error message to in case of error * @param forDataDelivery If the permission check is for delivering the sensitive data. * @return {@code true} if the caller has enough permissions, {@code false} otherwise */ private boolean checkPermissions(IRecognitionListener listener) { private boolean checkPermissions(IRecognitionListener listener, boolean forDataDelivery) { if (DBG) Log.d(TAG, "checkPermissions"); if (PermissionChecker.checkCallingOrSelfPermission(this, android.Manifest.permission.RECORD_AUDIO) == PermissionChecker.PERMISSION_GRANTED) { if (forDataDelivery) { if (PermissionChecker.checkCallingOrSelfPermissionForDataDelivery(this, android.Manifest.permission.RECORD_AUDIO) == PermissionChecker.PERMISSION_GRANTED) { return true; } } else { if (PermissionChecker.checkCallingOrSelfPermissionForPreflight(this, android.Manifest.permission.RECORD_AUDIO) == PermissionChecker.PERMISSION_GRANTED) { return true; } } try { Log.e(TAG, "call for recognition service without RECORD_AUDIO permissions"); listener.onError(SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS); Loading Loading @@ -342,7 +352,7 @@ public abstract class RecognitionService extends Service { public void startListening(Intent recognizerIntent, IRecognitionListener listener) { if (DBG) Log.d(TAG, "startListening called by:" + listener.asBinder()); final RecognitionService service = mServiceRef.get(); if (service != null && service.checkPermissions(listener)) { if (service != null && service.checkPermissions(listener, true /*forDataDelivery*/)) { service.mHandler.sendMessage(Message.obtain(service.mHandler, MSG_START_LISTENING, service.new StartListeningArgs( recognizerIntent, listener, Binder.getCallingUid()))); Loading @@ -353,7 +363,7 @@ public abstract class RecognitionService extends Service { public void stopListening(IRecognitionListener listener) { if (DBG) Log.d(TAG, "stopListening called by:" + listener.asBinder()); final RecognitionService service = mServiceRef.get(); if (service != null && service.checkPermissions(listener)) { if (service != null && service.checkPermissions(listener, false /*forDataDelivery*/)) { service.mHandler.sendMessage(Message.obtain(service.mHandler, MSG_STOP_LISTENING, listener)); } Loading @@ -363,7 +373,7 @@ public abstract class RecognitionService extends Service { public void cancel(IRecognitionListener listener) { if (DBG) Log.d(TAG, "cancel called by:" + listener.asBinder()); final RecognitionService service = mServiceRef.get(); if (service != null && service.checkPermissions(listener)) { if (service != null && service.checkPermissions(listener, false /*forDataDelivery*/)) { service.mHandler.sendMessage(Message.obtain(service.mHandler, MSG_CANCEL, listener)); } Loading packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java +3 −2 Original line number Diff line number Diff line Loading @@ -111,7 +111,8 @@ public class RecentLocationAccesses { for (int op : LOCATION_OPS) { final String permission = AppOpsManager.opToPermission(op); final int permissionFlags = pm.getPermissionFlags(permission, packageName, user); if (PermissionChecker.checkPermission(mContext, permission, -1, uid, packageName) if (PermissionChecker.checkPermissionForPreflight(mContext, permission, PermissionChecker.PID_UNKNOWN, uid, packageName) == PermissionChecker.PERMISSION_GRANTED) { if ((permissionFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) == 0) { Loading packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java +3 −3 Original line number Diff line number Diff line Loading @@ -106,8 +106,8 @@ public class RecentLocationApps { final String permission = AppOpsManager.opToPermission(op); final int permissionFlags = pm.getPermissionFlags(permission, packageName, user); if (PermissionChecker.checkPermission(mContext, permission, -1, uid, packageName) if (PermissionChecker.checkPermissionForPreflight(mContext, permission, PermissionChecker.PID_UNKNOWN, uid, packageName) == PermissionChecker.PERMISSION_GRANTED) { if ((permissionFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) Loading services/core/java/com/android/server/role/RoleManagerService.java +1 −2 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/android/content/PermissionChecker.java +266 −30 Original line number Diff line number Diff line Loading @@ -50,6 +50,19 @@ import java.lang.annotation.RetentionPolicy; * permission model for which the user had disabled the "permission" * which is achieved by disallowing the corresponding app op. * </p> * <p> * This class has two types of methods and you should be careful which * type to call based on whether permission protected data is being * passed to the app or you are just checking whether the app holds a * permission. The reason is that a permission check requires checking * the runtime permission and if it is granted checking the corresponding * app op as for apps not supporting the runtime mode we never revoke * permissions but disable app ops. Since there are two types of app op * checks, one that does not leave a record an action was performed and * another the does, one needs to call the preflight flavor of the checks * named xxxForPreflight only if no private data is being delivered but * a permission check is what is needed and the xxxForDataDelivery where * the permission check is right before private data delivery. * * @hide */ Loading @@ -63,6 +76,9 @@ public final class PermissionChecker { /** Permission result: The permission is denied because the app op is not allowed. */ public static final int PERMISSION_DENIED_APP_OP = PackageManager.PERMISSION_DENIED - 1; /** Constant when the PID for which we check permissions is unknown. */ public static final int PID_UNKNOWN = -1; /** @hide */ @IntDef({PERMISSION_GRANTED, PERMISSION_DENIED, Loading @@ -78,47 +94,127 @@ public final class PermissionChecker { * Checks whether a given package in a UID and PID has a given permission * and whether the app op that corresponds to this permission is allowed. * * <strong>NOTE:</strong> Use this method only for permission checks at the * point where you will deliver the permission protected data to clients. * * <p>For example, if an app registers a location listener it should have the location * permission but no data is actually sent to the app at the moment of registration * and you should use {@link #checkPermissionForPreflight(Context, String, int, int, String)} * to determine if the app has or may have location permission (if app has only foreground * location the grant state depends on the app's fg/gb state) and this check will not * leave a trace that permission protected data was delivered. When you are about to * deliver the location data to a registered listener you should use this method which * will evaluate the permission access based on the current fg/bg state of the app and * leave a record that the data was accessed. * * @param context Context for accessing resources. * @param permission The permission to check. * @param pid The process id for which to check. * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID * is not known. * @param uid The uid for which to check. * @param packageName The package name for which to check. If null the * the first package for the calling UID will be used. * @return The permission check result which is either {@link #PERMISSION_GRANTED} * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. * * @see #checkPermissionForPreflight(Context, String, int, int, String) */ @PermissionResult public static int checkPermission(@NonNull Context context, @NonNull String permission, int pid, int uid, @Nullable String packageName) { if (context.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_DENIED) { return PERMISSION_DENIED; } AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); String op = appOpsManager.permissionToOp(permission); if (op == null) { return PERMISSION_GRANTED; } if (packageName == null) { String[] packageNames = context.getPackageManager().getPackagesForUid(uid); if (packageNames == null || packageNames.length <= 0) { return PERMISSION_DENIED; } packageName = packageNames[0]; public static int checkPermissionForDataDelivery(@NonNull Context context, @NonNull String permission, int pid, int uid, @Nullable String packageName) { return checkPermissionCommon(context, permission, pid, uid, packageName, true /*forDataDelivery*/); } if (appOpsManager.noteProxyOpNoThrow(op, packageName, uid) != AppOpsManager.MODE_ALLOWED) { return PERMISSION_DENIED_APP_OP; /** * Checks whether a given package in a UID and PID has a given permission * and whether the app op that corresponds to this permission is allowed. * * <strong>NOTE:</strong> Use this method only for permission checks at the * preflight point where you will not deliver the permission protected data * to clients but schedule permission data delivery, apps register listeners, * etc. * * <p>For example, if an app registers a location listener it should have the location * permission but no data is actually sent to the app at the moment of registration * and you should use this method to determine if the app has or may have location * permission (if app has only foreground location the grant state depends on the app's * fg/gb state) and this check will not leave a trace that permission protected data * was delivered. When you are about to deliver the location data to a registered * listener you should use {@link #checkPermissionForDataDelivery(Context, String, * int, int, String)} which will evaluate the permission access based on the current * fg/bg state of the app and leave a record that the data was accessed. * * @param context Context for accessing resources. * @param permission The permission to check. * @param pid The process id for which to check. * @param uid The uid for which to check. * @param packageName The package name for which to check. If null the * the first package for the calling UID will be used. * @return The permission check result which is either {@link #PERMISSION_GRANTED} * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. * * @see #checkPermissionForDataDelivery(Context, String, int, int, String) */ @PermissionResult public static int checkPermissionForPreflight(@NonNull Context context, @NonNull String permission, int pid, int uid, @Nullable String packageName) { return checkPermissionCommon(context, permission, pid, uid, packageName, false /*forDataDelivery*/); } return PERMISSION_GRANTED; /** * Checks whether your app has a given permission and whether the app op * that corresponds to this permission is allowed. * * <strong>NOTE:</strong> Use this method only for permission checks at the * point where you will deliver the permission protected data to clients. * * <p>For example, if an app registers a location listener it should have the location * permission but no data is actually sent to the app at the moment of registration * and you should use {@link #checkSelfPermissionForPreflight(Context, String)} * to determine if the app has or may have location permission (if app has only foreground * location the grant state depends on the app's fg/gb state) and this check will not * leave a trace that permission protected data was delivered. When you are about to * deliver the location data to a registered listener you should use this method * which will evaluate the permission access based on the current fg/bg state of the * app and leave a record that the data was accessed. * * <p>This API assumes the the {@link Binder#getCallingUid()} is the same as * {@link Process#myUid()}. * * @param context Context for accessing resources. * @param permission The permission to check. * @return The permission check result which is either {@link #PERMISSION_GRANTED} * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. * * @see #checkSelfPermissionForPreflight(Context, String) */ @PermissionResult public static int checkSelfPermissionForDataDelivery(@NonNull Context context, @NonNull String permission) { return checkPermissionForDataDelivery(context, permission, Process.myPid(), Process.myUid(), context.getPackageName()); } /** * Checks whether your app has a given permission and whether the app op * that corresponds to this permission is allowed. * * <strong>NOTE:</strong> Use this method only for permission checks at the * preflight point where you will not deliver the permission protected data * to clients but schedule permission data delivery, apps register listeners, * etc. * * <p>For example, if an app registers a location listener it should have the location * permission but no data is actually sent to the app at the moment of registration * and you should use this method to determine if the app has or may have location * permission (if app has only foreground location the grant state depends on the * app's fg/gb state) and this check will not leave a trace that permission protected * data was delivered. When you are about to deliver the location data to a registered * listener you should use this method which will evaluate the permission access based * on the current fg/bg state of the app and leave a record that the data was accessed. * * <p>This API assumes the the {@link Binder#getCallingUid()} is the same as * {@link Process#myUid()}. * Loading @@ -126,11 +222,13 @@ public final class PermissionChecker { * @param permission The permission to check. * @return The permission check result which is either {@link #PERMISSION_GRANTED} * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. * * @see #checkSelfPermissionForDataDelivery(Context, String) */ @PermissionResult public static int checkSelfPermission(@NonNull Context context, public static int checkSelfPermissionForPreflight(@NonNull Context context, @NonNull String permission) { return checkPermission(context, permission, Process.myPid(), return checkPermissionForPreflight(context, permission, Process.myPid(), Process.myUid(), context.getPackageName()); } Loading @@ -138,20 +236,106 @@ public final class PermissionChecker { * Checks whether the IPC you are handling has a given permission and whether * the app op that corresponds to this permission is allowed. * * <strong>NOTE:</strong> Use this method only for permission checks at the * point where you will deliver the permission protected data to clients. * * <p>For example, if an app registers a location listener it should have the location * permission but no data is actually sent to the app at the moment of registration * and you should use {@link #checkCallingPermissionForPreflight(Context, String, String)} * to determine if the app has or may have location permission (if app has only foreground * location the grant state depends on the app's fg/gb state) and this check will not * leave a trace that permission protected data was delivered. When you are about to * deliver the location data to a registered listener you should use this method which * will evaluate the permission access based on the current fg/bg state of the app and * leave a record that the data was accessed. * * @param context Context for accessing resources. * @param permission The permission to check. * @param packageName The package name making the IPC. If null the * the first package for the calling UID will be used. * @return The permission check result which is either {@link #PERMISSION_GRANTED} * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. * * @see #checkCallingPermissionForPreflight(Context, String, String) */ @PermissionResult public static int checkCallingPermissionForDataDelivery(@NonNull Context context, @NonNull String permission, @Nullable String packageName) { if (Binder.getCallingPid() == Process.myPid()) { return PERMISSION_DENIED; } return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(), Binder.getCallingUid(), packageName); } /** * Checks whether the IPC you are handling has a given permission and whether * the app op that corresponds to this permission is allowed. * * <strong>NOTE:</strong> Use this method only for permission checks at the * preflight point where you will not deliver the permission protected data * to clients but schedule permission data delivery, apps register listeners, * etc. * * <p>For example, if an app registers a location listener it should have the location * permission but no data is actually sent to the app at the moment of registration * and you should use this method to determine if the app has or may have location * permission (if app has only foreground location the grant state depends on the app's * fg/gb state) and this check will not leave a trace that permission protected data * was delivered. When you are about to deliver the location data to a registered * listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context, * String)} which will evaluate the permission access based on the current fg/bg state * of the app and leave a record that the data was accessed. * * @param context Context for accessing resources. * @param permission The permission to check. * @param packageName The package name making the IPC. If null the * the first package for the calling UID will be used. * @return The permission check result which is either {@link #PERMISSION_GRANTED} * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. * * @see #checkCallingPermissionForDataDelivery(Context, String, String) */ @PermissionResult public static int checkCallingPermission(@NonNull Context context, public static int checkCallingPermissionForPreflight(@NonNull Context context, @NonNull String permission, @Nullable String packageName) { if (Binder.getCallingPid() == Process.myPid()) { return PERMISSION_DENIED; } return checkPermission(context, permission, Binder.getCallingPid(), return checkPermissionForPreflight(context, permission, Binder.getCallingPid(), Binder.getCallingUid(), packageName); } /** * Checks whether the IPC you are handling or your app has a given permission * and whether the app op that corresponds to this permission is allowed. * * <strong>NOTE:</strong> Use this method only for permission checks at the * point where you will deliver the permission protected data to clients. * * <p>For example, if an app registers a location listener it should have the location * permission but no data is actually sent to the app at the moment of registration * and you should use {@link #checkCallingOrSelfPermissionForPreflight(Context, String)} * to determine if the app has or may have location permission (if app has only foreground * location the grant state depends on the app's fg/gb state) and this check will not * leave a trace that permission protected data was delivered. When you are about to * deliver the location data to a registered listener you should use this method which * will evaluate the permission access based on the current fg/bg state of the app and * leave a record that the data was accessed. * * @param context Context for accessing resources. * @param permission The permission to check. * @return The permission check result which is either {@link #PERMISSION_GRANTED} * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. * * @see #checkCallingOrSelfPermissionForPreflight(Context, String) */ @PermissionResult public static int checkCallingOrSelfPermissionForDataDelivery(@NonNull Context context, @NonNull String permission) { String packageName = (Binder.getCallingPid() == Process.myPid()) ? context.getPackageName() : null; return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(), Binder.getCallingUid(), packageName); } Loading @@ -159,17 +343,69 @@ public final class PermissionChecker { * Checks whether the IPC you are handling or your app has a given permission * and whether the app op that corresponds to this permission is allowed. * * <strong>NOTE:</strong> Use this method only for permission checks at the * preflight point where you will not deliver the permission protected data * to clients but schedule permission data delivery, apps register listeners, * etc. * * <p>For example, if an app registers a location listener it should have the location * permission but no data is actually sent to the app at the moment of registration * and you should use this method to determine if the app has or may have location * permission (if app has only foreground location the grant state depends on the * app's fg/gb state) and this check will not leave a trace that permission protected * data was delivered. When you are about to deliver the location data to a registered * listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context, * String)} which will evaluate the permission access based on the current fg/bg state * of the app and leave a record that the data was accessed. * * @param context Context for accessing resources. * @param permission The permission to check. * @return The permission check result which is either {@link #PERMISSION_GRANTED} * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. * * @see #checkCallingOrSelfPermissionForDataDelivery(Context, String) */ @PermissionResult public static int checkCallingOrSelfPermission(@NonNull Context context, public static int checkCallingOrSelfPermissionForPreflight(@NonNull Context context, @NonNull String permission) { String packageName = (Binder.getCallingPid() == Process.myPid()) ? context.getPackageName() : null; return checkPermission(context, permission, Binder.getCallingPid(), return checkPermissionForPreflight(context, permission, Binder.getCallingPid(), Binder.getCallingUid(), packageName); } private static int checkPermissionCommon(@NonNull Context context, @NonNull String permission, int pid, int uid, @Nullable String packageName, boolean forDataDelivery) { if (context.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_DENIED) { return PERMISSION_DENIED; } AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); String op = appOpsManager.permissionToOp(permission); if (op == null) { return PERMISSION_GRANTED; } if (packageName == null) { String[] packageNames = context.getPackageManager().getPackagesForUid(uid); if (packageNames == null || packageNames.length <= 0) { return PERMISSION_DENIED; } packageName = packageNames[0]; } if (forDataDelivery) { if (appOpsManager.noteProxyOpNoThrow(op, packageName, uid) != AppOpsManager.MODE_ALLOWED) { return PERMISSION_DENIED_APP_OP; } } else { final int mode = appOpsManager.unsafeCheckOpRawNoThrow(op, uid, packageName); if (mode != AppOpsManager.MODE_ALLOWED && mode != AppOpsManager.MODE_FOREGROUND) { return PERMISSION_DENIED_APP_OP; } } return PERMISSION_GRANTED; } }
core/java/android/speech/RecognitionService.java +17 −7 Original line number Diff line number Diff line Loading @@ -170,14 +170,24 @@ public abstract class RecognitionService extends Service { * Checks whether the caller has sufficient permissions * * @param listener to send the error message to in case of error * @param forDataDelivery If the permission check is for delivering the sensitive data. * @return {@code true} if the caller has enough permissions, {@code false} otherwise */ private boolean checkPermissions(IRecognitionListener listener) { private boolean checkPermissions(IRecognitionListener listener, boolean forDataDelivery) { if (DBG) Log.d(TAG, "checkPermissions"); if (PermissionChecker.checkCallingOrSelfPermission(this, android.Manifest.permission.RECORD_AUDIO) == PermissionChecker.PERMISSION_GRANTED) { if (forDataDelivery) { if (PermissionChecker.checkCallingOrSelfPermissionForDataDelivery(this, android.Manifest.permission.RECORD_AUDIO) == PermissionChecker.PERMISSION_GRANTED) { return true; } } else { if (PermissionChecker.checkCallingOrSelfPermissionForPreflight(this, android.Manifest.permission.RECORD_AUDIO) == PermissionChecker.PERMISSION_GRANTED) { return true; } } try { Log.e(TAG, "call for recognition service without RECORD_AUDIO permissions"); listener.onError(SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS); Loading Loading @@ -342,7 +352,7 @@ public abstract class RecognitionService extends Service { public void startListening(Intent recognizerIntent, IRecognitionListener listener) { if (DBG) Log.d(TAG, "startListening called by:" + listener.asBinder()); final RecognitionService service = mServiceRef.get(); if (service != null && service.checkPermissions(listener)) { if (service != null && service.checkPermissions(listener, true /*forDataDelivery*/)) { service.mHandler.sendMessage(Message.obtain(service.mHandler, MSG_START_LISTENING, service.new StartListeningArgs( recognizerIntent, listener, Binder.getCallingUid()))); Loading @@ -353,7 +363,7 @@ public abstract class RecognitionService extends Service { public void stopListening(IRecognitionListener listener) { if (DBG) Log.d(TAG, "stopListening called by:" + listener.asBinder()); final RecognitionService service = mServiceRef.get(); if (service != null && service.checkPermissions(listener)) { if (service != null && service.checkPermissions(listener, false /*forDataDelivery*/)) { service.mHandler.sendMessage(Message.obtain(service.mHandler, MSG_STOP_LISTENING, listener)); } Loading @@ -363,7 +373,7 @@ public abstract class RecognitionService extends Service { public void cancel(IRecognitionListener listener) { if (DBG) Log.d(TAG, "cancel called by:" + listener.asBinder()); final RecognitionService service = mServiceRef.get(); if (service != null && service.checkPermissions(listener)) { if (service != null && service.checkPermissions(listener, false /*forDataDelivery*/)) { service.mHandler.sendMessage(Message.obtain(service.mHandler, MSG_CANCEL, listener)); } Loading
packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java +3 −2 Original line number Diff line number Diff line Loading @@ -111,7 +111,8 @@ public class RecentLocationAccesses { for (int op : LOCATION_OPS) { final String permission = AppOpsManager.opToPermission(op); final int permissionFlags = pm.getPermissionFlags(permission, packageName, user); if (PermissionChecker.checkPermission(mContext, permission, -1, uid, packageName) if (PermissionChecker.checkPermissionForPreflight(mContext, permission, PermissionChecker.PID_UNKNOWN, uid, packageName) == PermissionChecker.PERMISSION_GRANTED) { if ((permissionFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) == 0) { Loading
packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java +3 −3 Original line number Diff line number Diff line Loading @@ -106,8 +106,8 @@ public class RecentLocationApps { final String permission = AppOpsManager.opToPermission(op); final int permissionFlags = pm.getPermissionFlags(permission, packageName, user); if (PermissionChecker.checkPermission(mContext, permission, -1, uid, packageName) if (PermissionChecker.checkPermissionForPreflight(mContext, permission, PermissionChecker.PID_UNKNOWN, uid, packageName) == PermissionChecker.PERMISSION_GRANTED) { if ((permissionFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) Loading
services/core/java/com/android/server/role/RoleManagerService.java +1 −2 File changed.Preview size limit exceeded, changes collapsed. Show changes