1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.content; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.app.AppOpsManager; 22 import android.os.Binder; 23 import android.os.Process; 24 import android.permission.IPermissionChecker; 25 import android.permission.PermissionCheckerManager; 26 import android.permission.PermissionCheckerManager.PermissionResult; 27 28 /** 29 * This class provides permission check APIs that verify both the 30 * permission and the associated app op for this permission if 31 * such is defined. 32 * <p> 33 * In the new permission model permissions with protection level 34 * dangerous are runtime permissions. For apps targeting {@link android.os.Build.VERSION_CODES#M} 35 * and above the user may not grant such permissions or revoke 36 * them at any time. For apps targeting API lower than {@link android.os.Build.VERSION_CODES#M} 37 * these permissions are always granted as such apps do not expect 38 * permission revocations and would crash. Therefore, when the 39 * user disables a permission for a legacy app in the UI the 40 * platform disables the APIs guarded by this permission making 41 * them a no-op which is doing nothing or returning an empty 42 * result or default error. 43 * </p> 44 * <p> 45 * It is important that when you perform an operation on behalf of 46 * another app you use these APIs to check for permissions as the 47 * app may be a legacy app that does not participate in the new 48 * permission model for which the user had disabled the "permission" 49 * which is achieved by disallowing the corresponding app op. 50 * </p> 51 * <p> 52 * This class has two types of methods and you should be careful which 53 * type to call based on whether permission protected data is being 54 * passed to the app or you are just checking whether the app holds a 55 * permission. The reason is that a permission check requires checking 56 * the runtime permission and if it is granted checking the corresponding 57 * app op as for apps not supporting the runtime mode we never revoke 58 * permissions but disable app ops. Since there are two types of app op 59 * checks, one that does not leave a record an action was performed and 60 * another the does, one needs to call the preflight flavor of the checks 61 * named xxxForPreflight only if no private data is being delivered but 62 * a permission check is what is needed and the xxxForDataDelivery where 63 * the permission check is right before private data delivery. 64 * 65 * @hide 66 */ 67 public final class PermissionChecker { 68 /** 69 * The permission is granted. 70 * 71 * @hide 72 */ 73 public static final int PERMISSION_GRANTED = PermissionCheckerManager.PERMISSION_GRANTED; 74 75 /** 76 * The permission is denied. Applicable only to runtime permissions. 77 * 78 * <p>Returned when: 79 * <ul> 80 * <li>the runtime permission is granted, but the corresponding app op is denied 81 * for runtime permissions.</li> 82 * </ul> 83 * 84 * @hide 85 */ 86 public static final int PERMISSION_SOFT_DENIED = 87 PermissionCheckerManager.PERMISSION_SOFT_DENIED; 88 89 /** 90 * The permission is denied. 91 * 92 * <p>Returned when: 93 * <ul> 94 * <li>the permission is denied for non app op permissions.</li> 95 * <li>the app op is denied or app op is {@link AppOpsManager#MODE_DEFAULT} 96 * and permission is denied.</li> 97 * </ul> 98 * 99 * @hide 100 */ 101 public static final int PERMISSION_HARD_DENIED = 102 PermissionCheckerManager.PERMISSION_HARD_DENIED; 103 104 /** Constant when the PID for which we check permissions is unknown. */ 105 public static final int PID_UNKNOWN = -1; 106 107 private static volatile IPermissionChecker sService; 108 PermissionChecker()109 private PermissionChecker() { 110 /* do nothing */ 111 } 112 113 /** 114 * Checks whether a given package in a UID and PID has a given permission 115 * and whether the app op that corresponds to this permission is allowed. 116 * 117 * <strong>NOTE:</strong> Use this method only for permission checks at the 118 * point where you will deliver the permission protected data to clients. 119 * 120 * <p>For example, if an app registers a location listener it should have the location 121 * permission but no data is actually sent to the app at the moment of registration 122 * and you should use {@link #checkPermissionForPreflight(Context, String, int, int, String)} 123 * to determine if the app has or may have location permission (if app has only foreground 124 * location the grant state depends on the app's fg/gb state) and this check will not 125 * leave a trace that permission protected data was delivered. When you are about to 126 * deliver the location data to a registered listener you should use this method which 127 * will evaluate the permission access based on the current fg/bg state of the app and 128 * leave a record that the data was accessed. 129 * 130 * <p>For more details how to determine the {@code packageName}, {@code attributionTag}, and 131 * {@code message}, please check the description in 132 * {@link AppOpsManager#noteOp(String, int, String, String, String)} 133 * 134 * @param context Context for accessing resources. 135 * @param permission The permission to check. 136 * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID 137 * is not known. 138 * @param uid The uid for which to check. 139 * @param packageName The package name for which to check. If null the 140 * the first package for the calling UID will be used. 141 * @param attributionTag attribution tag 142 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 143 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 144 * @param message A message describing the reason the permission was checked 145 * @param startDataDelivery Whether this is the start of data delivery. 146 * 147 * @see #checkPermissionForPreflight(Context, String, int, int, String) 148 */ 149 @PermissionCheckerManager.PermissionResult checkPermissionForDataDelivery(@onNull Context context, @NonNull String permission, int pid, int uid, @Nullable String packageName, @Nullable String attributionTag, @Nullable String message, boolean startDataDelivery)150 public static int checkPermissionForDataDelivery(@NonNull Context context, 151 @NonNull String permission, int pid, int uid, @Nullable String packageName, 152 @Nullable String attributionTag, @Nullable String message, boolean startDataDelivery) { 153 return checkPermissionForDataDelivery(context, permission, pid, new AttributionSource(uid, 154 pid, packageName, attributionTag), message, startDataDelivery); 155 } 156 157 /** 158 * Checks whether a given package in a UID and PID has a given permission 159 * and whether the app op that corresponds to this permission is allowed. 160 * 161 * <strong>NOTE:</strong> Use this method only for permission checks at the 162 * point where you will deliver the permission protected data to clients. 163 * 164 * <p>For example, if an app registers a location listener it should have the location 165 * permission but no data is actually sent to the app at the moment of registration 166 * and you should use {@link #checkPermissionForPreflight(Context, String, int, int, String)} 167 * to determine if the app has or may have location permission (if app has only foreground 168 * location the grant state depends on the app's fg/gb state) and this check will not 169 * leave a trace that permission protected data was delivered. When you are about to 170 * deliver the location data to a registered listener you should use this method which 171 * will evaluate the permission access based on the current fg/bg state of the app and 172 * leave a record that the data was accessed. 173 * 174 * <p>For more details how to determine the {@code packageName}, {@code attributionTag}, and 175 * {@code message}, please check the description in 176 * {@link AppOpsManager#noteOp(String, int, String, String, String)} 177 * 178 * @param context Context for accessing resources. 179 * @param permission The permission to check. 180 * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID 181 * is not known. 182 * @param uid The uid for which to check. 183 * @param packageName The package name for which to check. If null the 184 * the first package for the calling UID will be used. 185 * @param attributionTag attribution tag 186 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 187 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 188 * @param message A message describing the reason the permission was checked 189 * 190 * @see #checkPermissionForPreflight(Context, String, int, int, String) 191 */ 192 @PermissionResult checkPermissionForDataDelivery(@onNull Context context, @NonNull String permission, int pid, int uid, @Nullable String packageName, @Nullable String attributionTag, @Nullable String message)193 public static int checkPermissionForDataDelivery(@NonNull Context context, 194 @NonNull String permission, int pid, int uid, @Nullable String packageName, 195 @Nullable String attributionTag, @Nullable String message) { 196 return checkPermissionForDataDelivery(context, permission, pid, uid, 197 packageName, attributionTag, message, false /*startDataDelivery*/); 198 } 199 200 /** 201 * Checks whether a given data access chain described by the given {@link AttributionSource} 202 * has a given permission and whether the app op that corresponds to this permission 203 * is allowed. Call this method if you are the datasource which would not blame you for 204 * access to the data since you are the data. 205 * 206 * <strong>NOTE:</strong> Use this method only for permission checks at the 207 * point where you will deliver the permission protected data to clients. 208 * 209 * <p>For example, if an app registers a location listener it should have the location 210 * permission but no data is actually sent to the app at the moment of registration 211 * and you should use {@link #checkPermissionForPreflight(Context, String, int, int, String)} 212 * to determine if the app has or may have location permission (if app has only foreground 213 * location the grant state depends on the app's fg/gb state) and this check will not 214 * leave a trace that permission protected data was delivered. When you are about to 215 * deliver the location data to a registered listener you should use this method which 216 * will evaluate the permission access based on the current fg/bg state of the app and 217 * leave a record that the data was accessed. 218 * 219 * @param context Context for accessing resources. 220 * @param permission The permission to check. 221 * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID 222 * is not known. 223 * @param attributionSource the permission identity 224 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 225 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 226 * @param message A message describing the reason the permission was checked 227 * 228 * @see #checkPermissionForPreflight(Context, String, AttributionSource) 229 */ 230 @PermissionResult checkPermissionForDataDeliveryFromDataSource(@onNull Context context, @NonNull String permission, int pid, @NonNull AttributionSource attributionSource, @Nullable String message)231 public static int checkPermissionForDataDeliveryFromDataSource(@NonNull Context context, 232 @NonNull String permission, int pid, @NonNull AttributionSource attributionSource, 233 @Nullable String message) { 234 return checkPermissionForDataDeliveryCommon(context, permission, attributionSource, 235 message, false /*startDataDelivery*/, /*fromDatasource*/ true); 236 } 237 238 /** 239 * Checks whether a given data access chain described by the given {@link AttributionSource} 240 * has a given permission and whether the app op that corresponds to this permission 241 * is allowed. 242 * 243 * <strong>NOTE:</strong> Use this method only for permission checks at the 244 * point where you will deliver the permission protected data to clients. 245 * 246 * <p>For example, if an app registers a location listener it should have the location 247 * permission but no data is actually sent to the app at the moment of registration 248 * and you should use {@link #checkPermissionForPreflight(Context, String, AttributionSource)} 249 * to determine if the app has or may have location permission (if app has only foreground 250 * location the grant state depends on the app's fg/gb state) and this check will not 251 * leave a trace that permission protected data was delivered. When you are about to 252 * deliver the location data to a registered listener you should use this method which 253 * will evaluate the permission access based on the current fg/bg state of the app and 254 * leave a record that the data was accessed. 255 * 256 * @param context Context for accessing resources. 257 * @param permission The permission to check. 258 * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID 259 * is not known. 260 * @param attributionSource the permission identity 261 * @param message A message describing the reason the permission was checked 262 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 263 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 264 * 265 * @see #checkPermissionForPreflight(Context, String, AttributionSource) 266 */ 267 @PermissionResult checkPermissionForDataDelivery(@onNull Context context, @NonNull String permission, int pid, @NonNull AttributionSource attributionSource, @Nullable String message)268 public static int checkPermissionForDataDelivery(@NonNull Context context, 269 @NonNull String permission, int pid, @NonNull AttributionSource attributionSource, 270 @Nullable String message) { 271 return checkPermissionForDataDelivery(context, permission, pid, attributionSource, 272 message, false /*startDataDelivery*/); 273 } 274 275 /** 276 * Checks whether a given data access chain described by the given {@link AttributionSource} 277 * has a given permission and whether the app op that corresponds to this permission 278 * is allowed. 279 * 280 * <strong>NOTE:</strong> Use this method only for permission checks at the 281 * point where you will deliver the permission protected data to clients. 282 * 283 * <p>For example, if an app registers a data listener it should have the required 284 * permission but no data is actually sent to the app at the moment of registration 285 * and you should use {@link #checkPermissionForPreflight(Context, String, 286 * AttributionSource)} 287 * to determine if the app has or may have permission and this check will not 288 * leave a trace that permission protected data was delivered. When you are about to 289 * deliver the data to a registered listener you should use this method which 290 * will evaluate the permission access based on the current fg/bg state of the app and 291 * leave a record that the data was accessed. 292 * 293 * @param context Context for accessing resources. 294 * @param permission The permission to check. 295 * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID 296 * is not known. 297 * @param attributionSource The identity for which to check the permission. 298 * @param message A message describing the reason the permission was checked 299 * @param startDataDelivery Whether this is the start of data delivery. 300 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 301 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 302 * 303 * @see #checkPermissionForPreflight(Context, String, AttributionSource) 304 */ 305 @PermissionResult checkPermissionForDataDelivery(@onNull Context context, @NonNull String permission, int pid, @NonNull AttributionSource attributionSource, @Nullable String message, boolean startDataDelivery)306 public static int checkPermissionForDataDelivery(@NonNull Context context, 307 @NonNull String permission, int pid, @NonNull AttributionSource attributionSource, 308 @Nullable String message, boolean startDataDelivery) { 309 return checkPermissionForDataDeliveryCommon(context, permission, attributionSource, 310 message, startDataDelivery, /*fromDatasource*/ false); 311 } 312 313 @SuppressWarnings("ConstantConditions") checkPermissionForDataDeliveryCommon(@onNull Context context, @NonNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message, boolean startDataDelivery, boolean fromDatasource)314 private static int checkPermissionForDataDeliveryCommon(@NonNull Context context, 315 @NonNull String permission, @NonNull AttributionSource attributionSource, 316 @Nullable String message, boolean startDataDelivery, boolean fromDatasource) { 317 return context.getSystemService(PermissionCheckerManager.class).checkPermission(permission, 318 attributionSource.asState(), message, true /*forDataDelivery*/, startDataDelivery, 319 fromDatasource, AppOpsManager.OP_NONE); 320 } 321 322 /** 323 * Checks whether a given data access chain described by the given {@link AttributionSource} 324 * has a given permission and whether the app op that corresponds to this permission 325 * is allowed. The app ops area also marked as started. This is useful for long running 326 * permissions like camera. 327 * 328 * <strong>NOTE:</strong> Use this method only for permission checks at the 329 * point where you will deliver the permission protected data to clients. 330 * 331 * <p>For example, if an app registers a data listener it should have the required 332 * permission but no data is actually sent to the app at the moment of registration 333 * and you should use {@link #checkPermissionForPreflight(Context, String, 334 * AttributionSource)} 335 * to determine if the app has or may have permission and this check will not 336 * leave a trace that permission protected data was delivered. When you are about to 337 * deliver the data to a registered listener you should use this method which 338 * will evaluate the permission access based on the current fg/bg state of the app and 339 * leave a record that the data was accessed. 340 * 341 * @param context Context for accessing resources. 342 * @param permission The permission to check. 343 * @param attributionSource The identity for which to check the permission. 344 * @param message A message describing the reason the permission was checked 345 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 346 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 347 * 348 * @see #checkPermissionForPreflight(Context, String, AttributionSource) 349 */ 350 @PermissionResult 351 @SuppressWarnings("ConstantConditions") checkPermissionAndStartDataDelivery(@onNull Context context, @NonNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message)352 public static int checkPermissionAndStartDataDelivery(@NonNull Context context, 353 @NonNull String permission, @NonNull AttributionSource attributionSource, 354 @Nullable String message) { 355 return context.getSystemService(PermissionCheckerManager.class).checkPermission( 356 permission, attributionSource.asState(), message, true /*forDataDelivery*/, 357 /*startDataDelivery*/ true, /*fromDatasource*/ false, AppOpsManager.OP_NONE); 358 } 359 360 /** 361 * Checks whether a given data access chain described by the given {@link 362 * AttributionSource} has a given app op allowed and marks the op as started. 363 * 364 * <strong>NOTE:</strong> Use this method only for app op checks at the 365 * point where you will deliver the protected data to clients. 366 * 367 * <p>For example, if an app registers a data listener it should have the data 368 * op but no data is actually sent to the app at the moment of registration 369 * and you should use {@link #checkOpForPreflight(Context, String, AttributionSource, String)} 370 * to determine if the app has or may have op access and this check will not 371 * leave a trace that op protected data was delivered. When you are about to 372 * deliver the data to a registered listener you should use this method which 373 * will evaluate the op access based on the current fg/bg state of the app and 374 * leave a record that the data was accessed. 375 * 376 * @param context Context for accessing resources. 377 * @param opName THe op to start. 378 * @param attributionSource The identity for which to check the permission. 379 * @param message A message describing the reason the permission was checked 380 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 381 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 382 * 383 * @see #finishDataDelivery(Context, String, AttributionSource) 384 */ 385 @PermissionResult 386 @SuppressWarnings("ConstantConditions") startOpForDataDelivery(@onNull Context context, @NonNull String opName, @NonNull AttributionSource attributionSource, @Nullable String message)387 public static int startOpForDataDelivery(@NonNull Context context, 388 @NonNull String opName, @NonNull AttributionSource attributionSource, 389 @Nullable String message) { 390 return context.getSystemService(PermissionCheckerManager.class).checkOp( 391 AppOpsManager.strOpToOp(opName), attributionSource.asState(), message, 392 true /*forDataDelivery*/, true /*startDataDelivery*/); 393 } 394 395 /** 396 * Finishes an ongoing op for data access chain described by the given {@link 397 * AttributionSource}. 398 * 399 * @param context Context for accessing resources. 400 * @param op The op to finish. 401 * @param attributionSource The identity for which finish op. 402 * 403 * @see #startOpForDataDelivery(Context, String, AttributionSource, String) 404 * @see #checkPermissionAndStartDataDelivery(Context, String, AttributionSource, String) 405 */ 406 @SuppressWarnings("ConstantConditions") finishDataDelivery(@onNull Context context, @NonNull String op, @NonNull AttributionSource attributionSource)407 public static void finishDataDelivery(@NonNull Context context, @NonNull String op, 408 @NonNull AttributionSource attributionSource) { 409 context.getSystemService(PermissionCheckerManager.class).finishDataDelivery( 410 AppOpsManager.strOpToOp(op), attributionSource.asState(), 411 /*fromDatasource*/ false); 412 } 413 414 /** 415 * Finishes an ongoing op for data access chain described by the given {@link 416 * AttributionSource}. Call this method if you are the datasource which would 417 * not finish an op for your attribution source as it was not started. 418 * 419 * @param context Context for accessing resources. 420 * @param op The op to finish. 421 * @param attributionSource The identity for which finish op. 422 * 423 * @see #startOpForDataDelivery(Context, String, AttributionSource, String) 424 * @see #checkPermissionAndStartDataDelivery(Context, String, AttributionSource, String) 425 */ 426 @SuppressWarnings("ConstantConditions") finishDataDeliveryFromDatasource(@onNull Context context, @NonNull String op, @NonNull AttributionSource attributionSource)427 public static void finishDataDeliveryFromDatasource(@NonNull Context context, 428 @NonNull String op, @NonNull AttributionSource attributionSource) { 429 context.getSystemService(PermissionCheckerManager.class).finishDataDelivery( 430 AppOpsManager.strOpToOp(op), attributionSource.asState(), 431 /*fromDatasource*/ true); 432 } 433 434 /** 435 * Checks whether a given data access chain described by the given {@link 436 * AttributionSource} has a given app op allowed. 437 * 438 * <strong>NOTE:</strong> Use this method only for op checks at the 439 * preflight point where you will not deliver the protected data 440 * to clients but schedule a data delivery, apps register listeners, 441 * etc. 442 * 443 * <p>For example, if an app registers a data listener it should have the op 444 * but no data is actually sent to the app at the moment of registration 445 * and you should use this method to determine if the app has or may have data 446 * access and this check will not leave a trace that protected data 447 * was delivered. When you are about to deliver the data to a registered 448 * listener you should use {@link #checkOpForDataDelivery(Context, String, 449 * AttributionSource, String)} which will evaluate the op access based 450 * on the current fg/bg state of the app and leave a record that the data was 451 * accessed. 452 * 453 * @param context Context for accessing resources. 454 * @param opName The op to check. 455 * @param attributionSource The identity for which to check the permission. 456 * @param message A message describing the reason the permission was checked 457 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 458 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 459 * 460 * @see #checkOpForDataDelivery(Context, String, AttributionSource, String) 461 */ 462 @PermissionResult 463 @SuppressWarnings("ConstantConditions") checkOpForPreflight(@onNull Context context, @NonNull String opName, @NonNull AttributionSource attributionSource, @Nullable String message)464 public static int checkOpForPreflight(@NonNull Context context, 465 @NonNull String opName, @NonNull AttributionSource attributionSource, 466 @Nullable String message) { 467 return context.getSystemService(PermissionCheckerManager.class).checkOp( 468 AppOpsManager.strOpToOp(opName), attributionSource.asState(), message, 469 false /*forDataDelivery*/, false /*startDataDelivery*/); 470 } 471 472 /** 473 * Checks whether a given data access chain described by the given {@link AttributionSource} 474 * has an allowed app op. 475 * 476 * <strong>NOTE:</strong> Use this method only for op checks at the 477 * point where you will deliver the permission protected data to clients. 478 * 479 * <p>For example, if an app registers a data listener it should have the data 480 * permission but no data is actually sent to the app at the moment of registration 481 * and you should use {@link #checkOpForPreflight(Context, String, AttributionSource, String)} 482 * to determine if the app has or may have data access and this check will not 483 * leave a trace that op protected data was delivered. When you are about to 484 * deliver the data to a registered listener you should use this method which 485 * will evaluate the op access based on the current fg/bg state of the app and 486 * leave a record that the data was accessed. 487 * 488 * @param context Context for accessing resources. 489 * @param opName The op to check. 490 * @param attributionSource The identity for which to check the op. 491 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 492 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 493 * @param message A message describing the reason the permission was checked 494 * 495 * @see #checkOpForPreflight(Context, String, AttributionSource, String) 496 */ 497 @PermissionResult 498 @SuppressWarnings("ConstantConditions") checkOpForDataDelivery(@onNull Context context, @NonNull String opName, @NonNull AttributionSource attributionSource, @Nullable String message)499 public static int checkOpForDataDelivery(@NonNull Context context, 500 @NonNull String opName, @NonNull AttributionSource attributionSource, 501 @Nullable String message) { 502 return context.getSystemService(PermissionCheckerManager.class).checkOp( 503 AppOpsManager.strOpToOp(opName), attributionSource.asState(), message, 504 true /*forDataDelivery*/, false /*startDataDelivery*/); 505 } 506 507 /** 508 * Checks whether a given package in a UID and PID has a given permission 509 * and whether the app op that corresponds to this permission is allowed. 510 * 511 * <strong>NOTE:</strong> Use this method only for permission checks at the 512 * preflight point where you will not deliver the permission protected data 513 * to clients but schedule permission data delivery, apps register listeners, 514 * etc. 515 * 516 * <p>For example, if an app registers a location listener it should have the location 517 * permission but no data is actually sent to the app at the moment of registration 518 * and you should use this method to determine if the app has or may have location 519 * permission (if app has only foreground location the grant state depends on the app's 520 * fg/gb state) and this check will not leave a trace that permission protected data 521 * was delivered. When you are about to deliver the location data to a registered 522 * listener you should use {@link #checkPermissionForDataDelivery(Context, String, 523 * int, int, String, String, String)} which will evaluate the permission access based 524 * on the currentfg/bg state of the app and leave a record that the data was accessed. 525 * 526 * @param context Context for accessing resources. 527 * @param permission The permission to check. 528 * @param pid The process id for which to check. 529 * @param uid The uid for which to check. 530 * @param packageName The package name for which to check. If null the 531 * the first package for the calling UID will be used. 532 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 533 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 534 * 535 * @see #checkPermissionForDataDelivery(Context, String, int, int, String, String, String) 536 */ 537 @PermissionResult checkPermissionForPreflight(@onNull Context context, @NonNull String permission, int pid, int uid, @Nullable String packageName)538 public static int checkPermissionForPreflight(@NonNull Context context, 539 @NonNull String permission, int pid, int uid, @Nullable String packageName) { 540 return checkPermissionForPreflight(context, permission, new AttributionSource( 541 uid, packageName, null /*attributionTag*/)); 542 } 543 544 /** 545 * Checks whether a given data access chain described by the given {@link AttributionSource} 546 * has a given permission and whether the app op that corresponds to this permission 547 * is allowed. 548 * 549 * <strong>NOTE:</strong> Use this method only for permission checks at the 550 * preflight point where you will not deliver the permission protected data 551 * to clients but schedule permission data delivery, apps register listeners, 552 * etc. 553 * 554 * <p>For example, if an app registers a data listener it should have the required 555 * permission but no data is actually sent to the app at the moment of registration 556 * and you should use this method to determine if the app has or may have the 557 * permission and this check will not leave a trace that permission protected data 558 * was delivered. When you are about to deliver the protected data to a registered 559 * listener you should use {@link #checkPermissionForDataDelivery(Context, String, 560 * int, AttributionSource, String, boolean)} which will evaluate the permission access based 561 * on the current fg/bg state of the app and leave a record that the data was accessed. 562 * 563 * @param context Context for accessing resources. 564 * @param permission The permission to check. 565 * @param attributionSource The identity for which to check the permission. 566 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 567 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 568 * 569 * @see #checkPermissionForDataDelivery(Context, String, int, AttributionSource, 570 * String, boolean) 571 */ 572 @PermissionResult 573 @SuppressWarnings("ConstantConditions") checkPermissionForPreflight(@onNull Context context, @NonNull String permission, @NonNull AttributionSource attributionSource)574 public static int checkPermissionForPreflight(@NonNull Context context, 575 @NonNull String permission, @NonNull AttributionSource attributionSource) { 576 return context.getSystemService(PermissionCheckerManager.class) 577 .checkPermission(permission, attributionSource.asState(), null /*message*/, 578 false /*forDataDelivery*/, /*startDataDelivery*/ false, /*fromDatasource*/ false, 579 AppOpsManager.OP_NONE); 580 } 581 582 /** 583 * Checks whether your app has a given permission and whether the app op 584 * that corresponds to this permission is allowed. 585 * 586 * <strong>NOTE:</strong> Use this method only for permission checks at the 587 * point where you will deliver the permission protected data to clients. 588 * 589 * <p>For example, if an app registers a location listener it should have the location 590 * permission but no data is actually sent to the app at the moment of registration 591 * and you should use {@link #checkSelfPermissionForPreflight(Context, String)} 592 * to determine if the app has or may have location permission (if app has only foreground 593 * location the grant state depends on the app's fg/gb state) and this check will not 594 * leave a trace that permission protected data was delivered. When you are about to 595 * deliver the location data to a registered listener you should use this method 596 * which will evaluate the permission access based on the current fg/bg state of the 597 * app and leave a record that the data was accessed. 598 * 599 * <p>This API assumes the {@link Binder#getCallingUid()} is the same as 600 * {@link Process#myUid()}. 601 * 602 * @param context Context for accessing resources. 603 * @param permission The permission to check. 604 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 605 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 606 * @param message A message describing the reason the permission was checked 607 * 608 * @see #checkSelfPermissionForPreflight(Context, String) 609 */ 610 @PermissionResult checkSelfPermissionForDataDelivery(@onNull Context context, @NonNull String permission, @Nullable String message)611 public static int checkSelfPermissionForDataDelivery(@NonNull Context context, 612 @NonNull String permission, @Nullable String message) { 613 return checkPermissionForDataDelivery(context, permission, Process.myPid(), 614 Process.myUid(), context.getPackageName(), context.getAttributionTag(), message, 615 /*startDataDelivery*/ false); 616 } 617 618 /** 619 * Checks whether your app has a given permission and whether the app op 620 * that corresponds to this permission is allowed. 621 * 622 * <strong>NOTE:</strong> Use this method only for permission checks at the 623 * preflight point where you will not deliver the permission protected data 624 * to clients but schedule permission data delivery, apps register listeners, 625 * etc. 626 * 627 * <p>For example, if an app registers a location listener it should have the location 628 * permission but no data is actually sent to the app at the moment of registration 629 * and you should use this method to determine if the app has or may have location 630 * permission (if app has only foreground location the grant state depends on the 631 * app's fg/gb state) and this check will not leave a trace that permission protected 632 * data was delivered. When you are about to deliver the location data to a registered 633 * listener you should use this method which will evaluate the permission access based 634 * on the current fg/bg state of the app and leave a record that the data was accessed. 635 * 636 * <p>This API assumes the {@link Binder#getCallingUid()} is the same as 637 * {@link Process#myUid()}. 638 * 639 * @param context Context for accessing resources. 640 * @param permission The permission to check. 641 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 642 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 643 * 644 * @see #checkSelfPermissionForDataDelivery(Context, String, String) 645 */ 646 @PermissionResult checkSelfPermissionForPreflight(@onNull Context context, @NonNull String permission)647 public static int checkSelfPermissionForPreflight(@NonNull Context context, 648 @NonNull String permission) { 649 return checkPermissionForPreflight(context, permission, Process.myPid(), 650 Process.myUid(), context.getPackageName()); 651 } 652 653 /** 654 * Checks whether the IPC you are handling has a given permission and whether 655 * the app op that corresponds to this permission is allowed. 656 * 657 * <strong>NOTE:</strong> Use this method only for permission checks at the 658 * point where you will deliver the permission protected data to clients. 659 * 660 * <p>For example, if an app registers a location listener it should have the location 661 * permission but no data is actually sent to the app at the moment of registration 662 * and you should use {@link #checkCallingPermissionForPreflight(Context, String, String)} 663 * to determine if the app has or may have location permission (if app has only foreground 664 * location the grant state depends on the app's fg/gb state) and this check will not 665 * leave a trace that permission protected data was delivered. When you are about to 666 * deliver the location data to a registered listener you should use this method which 667 * will evaluate the permission access based on the current fg/bg state of the app and 668 * leave a record that the data was accessed. 669 * 670 * <p>For more details how to determine the {@code callingPackageName}, 671 * {@code callingAttributionTag}, and {@code message}, please check the description in 672 * {@link AppOpsManager#noteOp(String, int, String, String, String)} 673 * 674 * @param context Context for accessing resources. 675 * @param permission The permission to check. 676 * @param callingPackageName The package name making the IPC. If null the 677 * the first package for the calling UID will be used. 678 * @param callingAttributionTag attribution tag 679 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 680 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 681 * @param message A message describing the reason the permission was checked 682 * 683 * @see #checkCallingPermissionForPreflight(Context, String, String) 684 */ 685 @PermissionResult checkCallingPermissionForDataDelivery(@onNull Context context, @NonNull String permission, @Nullable String callingPackageName, @Nullable String callingAttributionTag, @Nullable String message)686 public static int checkCallingPermissionForDataDelivery(@NonNull Context context, 687 @NonNull String permission, @Nullable String callingPackageName, 688 @Nullable String callingAttributionTag, @Nullable String message) { 689 if (Binder.getCallingPid() == Process.myPid()) { 690 return PERMISSION_HARD_DENIED; 691 } 692 return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(), 693 Binder.getCallingUid(), callingPackageName, callingAttributionTag, message, 694 /*startDataDelivery*/ false); 695 } 696 697 /** 698 * Checks whether the IPC you are handling has a given permission and whether 699 * the app op that corresponds to this permission is allowed. 700 * 701 * <strong>NOTE:</strong> Use this method only for permission checks at the 702 * preflight point where you will not deliver the permission protected data 703 * to clients but schedule permission data delivery, apps register listeners, 704 * etc. 705 * 706 * <p>For example, if an app registers a location listener it should have the location 707 * permission but no data is actually sent to the app at the moment of registration 708 * and you should use this method to determine if the app has or may have location 709 * permission (if app has only foreground location the grant state depends on the app's 710 * fg/gb state) and this check will not leave a trace that permission protected data 711 * was delivered. When you are about to deliver the location data to a registered 712 * listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context, 713 * String, String, String, String)} which will evaluate the permission access based on the 714 * current fg/bg stateof the app and leave a record that the data was accessed. 715 * 716 * @param context Context for accessing resources. 717 * @param permission The permission to check. 718 * @param packageName The package name making the IPC. If null the 719 * the first package for the calling UID will be used. 720 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 721 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 722 * 723 * @see #checkCallingPermissionForDataDelivery(Context, String, String, String, String) 724 */ 725 @PermissionResult checkCallingPermissionForPreflight(@onNull Context context, @NonNull String permission, @Nullable String packageName)726 public static int checkCallingPermissionForPreflight(@NonNull Context context, 727 @NonNull String permission, @Nullable String packageName) { 728 if (Binder.getCallingPid() == Process.myPid()) { 729 return PERMISSION_HARD_DENIED; 730 } 731 return checkPermissionForPreflight(context, permission, Binder.getCallingPid(), 732 Binder.getCallingUid(), packageName); 733 } 734 735 /** 736 * Checks whether the IPC you are handling or your app has a given permission 737 * and whether the app op that corresponds to this permission is allowed. 738 * 739 * <strong>NOTE:</strong> Use this method only for permission checks at the 740 * point where you will deliver the permission protected data to clients. 741 * 742 * <p>For example, if an app registers a location listener it should have the location 743 * permission but no data is actually sent to the app at the moment of registration 744 * and you should use {@link #checkCallingOrSelfPermissionForPreflight(Context, String)} 745 * to determine if the app has or may have location permission (if app has only foreground 746 * location the grant state depends on the app's fg/gb state) and this check will not 747 * leave a trace that permission protected data was delivered. When you are about to 748 * deliver the location data to a registered listener you should use this method which 749 * will evaluate the permission access based on the current fg/bg state of the app and 750 * leave a record that the data was accessed. 751 * 752 * <p>For more details how to determine the {@code callingPackageName}, 753 * {@code callingAttributionTag}, and {@code message}, please check the description in 754 * {@link AppOpsManager#noteOp(String, int, String, String, String)} 755 * 756 * @param context Context for accessing resources. 757 * @param permission The permission to check. 758 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 759 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 760 * @param callingPackageName package name tag of caller (if not self) 761 * @param callingAttributionTag attribution tag of caller (if not self) 762 * @param message A message describing the reason the permission was checked 763 * 764 * @see #checkCallingOrSelfPermissionForPreflight(Context, String) 765 */ 766 @PermissionResult checkCallingOrSelfPermissionForDataDelivery(@onNull Context context, @NonNull String permission, @Nullable String callingPackageName, @Nullable String callingAttributionTag, @Nullable String message)767 public static int checkCallingOrSelfPermissionForDataDelivery(@NonNull Context context, 768 @NonNull String permission, @Nullable String callingPackageName, 769 @Nullable String callingAttributionTag, @Nullable String message) { 770 callingPackageName = (Binder.getCallingPid() == Process.myPid()) 771 ? context.getPackageName() : callingPackageName; 772 callingAttributionTag = (Binder.getCallingPid() == Process.myPid()) 773 ? context.getAttributionTag() : callingAttributionTag; 774 return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(), 775 Binder.getCallingUid(), callingPackageName, callingAttributionTag, message, 776 /*startDataDelivery*/ false); 777 } 778 779 /** 780 * Checks whether the IPC you are handling or your app has a given permission 781 * and whether the app op that corresponds to this permission is allowed. 782 * 783 * <strong>NOTE:</strong> Use this method only for permission checks at the 784 * preflight point where you will not deliver the permission protected data 785 * to clients but schedule permission data delivery, apps register listeners, 786 * etc. 787 * 788 * <p>For example, if an app registers a location listener it should have the location 789 * permission but no data is actually sent to the app at the moment of registration 790 * and you should use this method to determine if the app has or may have location 791 * permission (if app has only foreground location the grant state depends on the 792 * app's fg/gb state) and this check will not leave a trace that permission protected 793 * data was delivered. When you are about to deliver the location data to a registered 794 * listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context, 795 * String, String, String, String)} which will evaluate the permission access based on the 796 * current fg/bg state of the app and leave a record that the data was accessed. 797 * 798 * @param context Context for accessing resources. 799 * @param permission The permission to check. 800 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 801 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 802 * 803 * @see #checkCallingOrSelfPermissionForDataDelivery(Context, String, String, String, String) 804 */ 805 @PermissionResult checkCallingOrSelfPermissionForPreflight(@onNull Context context, @NonNull String permission)806 public static int checkCallingOrSelfPermissionForPreflight(@NonNull Context context, 807 @NonNull String permission) { 808 String packageName = (Binder.getCallingPid() == Process.myPid()) 809 ? context.getPackageName() : null; 810 return checkPermissionForPreflight(context, permission, Binder.getCallingPid(), 811 Binder.getCallingUid(), packageName); 812 } 813 } 814