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