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.permission; 18 19 import static android.companion.virtual.VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT; 20 import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT; 21 import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE; 22 import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED; 23 import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; 24 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED; 25 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET; 26 import static android.os.Build.VERSION_CODES.S; 27 import static android.permission.flags.Flags.FLAG_SHOULD_REGISTER_ATTRIBUTION_SOURCE; 28 import static android.permission.flags.Flags.serverSideAttributionRegistration; 29 30 import android.Manifest; 31 import android.annotation.CheckResult; 32 import android.annotation.DurationMillisLong; 33 import android.annotation.FlaggedApi; 34 import android.annotation.IntDef; 35 import android.annotation.IntRange; 36 import android.annotation.NonNull; 37 import android.annotation.Nullable; 38 import android.annotation.RequiresPermission; 39 import android.annotation.SdkConstant; 40 import android.annotation.SdkConstant.SdkConstantType; 41 import android.annotation.SystemApi; 42 import android.annotation.SystemService; 43 import android.annotation.TestApi; 44 import android.annotation.UserIdInt; 45 import android.app.ActivityManager; 46 import android.app.ActivityThread; 47 import android.app.AppGlobals; 48 import android.app.AppOpsManager; 49 import android.app.IActivityManager; 50 import android.app.PropertyInvalidatedCache; 51 import android.companion.virtual.VirtualDevice; 52 import android.companion.virtual.VirtualDeviceManager; 53 import android.compat.annotation.ChangeId; 54 import android.compat.annotation.EnabledAfter; 55 import android.content.AttributionSource; 56 import android.content.Context; 57 import android.content.PermissionChecker; 58 import android.content.pm.IPackageManager; 59 import android.content.pm.PackageManager; 60 import android.content.pm.ParceledListSlice; 61 import android.content.pm.PermissionGroupInfo; 62 import android.content.pm.PermissionInfo; 63 import android.content.pm.permission.SplitPermissionInfoParcelable; 64 import android.media.AudioManager; 65 import android.os.Binder; 66 import android.os.Build; 67 import android.os.Handler; 68 import android.os.IBinder; 69 import android.os.Looper; 70 import android.os.Message; 71 import android.os.Parcel; 72 import android.os.Parcelable; 73 import android.os.Process; 74 import android.os.RemoteException; 75 import android.os.ServiceManager; 76 import android.os.SystemClock; 77 import android.os.UserHandle; 78 import android.permission.flags.Flags; 79 import android.text.TextUtils; 80 import android.util.ArrayMap; 81 import android.util.ArraySet; 82 import android.util.DebugUtils; 83 import android.util.Log; 84 import android.util.Slog; 85 86 import com.android.internal.R; 87 import com.android.internal.annotations.Immutable; 88 import com.android.internal.util.CollectionUtils; 89 import com.android.modules.utils.build.SdkLevel; 90 91 import java.lang.annotation.Retention; 92 import java.lang.annotation.RetentionPolicy; 93 import java.util.ArrayList; 94 import java.util.Collections; 95 import java.util.List; 96 import java.util.Map; 97 import java.util.Objects; 98 import java.util.Set; 99 100 /** 101 * System level service for accessing the permission capabilities of the platform. 102 * 103 * @hide 104 */ 105 @SystemApi 106 @SystemService(Context.PERMISSION_SERVICE) 107 public final class PermissionManager { 108 private static final String LOG_TAG = PermissionManager.class.getName(); 109 110 /** 111 * The permission is granted. 112 */ 113 public static final int PERMISSION_GRANTED = 0; 114 115 /** 116 * The permission is denied. Applicable only to runtime permissions. 117 * <p> 118 * The app isn't expecting the permission to be denied so that a "no-op" action should be taken, 119 * such as returning an empty result. 120 */ 121 public static final int PERMISSION_SOFT_DENIED = 1; 122 123 /** 124 * The permission is denied. 125 * <p> 126 * The app should receive a {@code SecurityException}, or an error through a relevant callback. 127 */ 128 public static final int PERMISSION_HARD_DENIED = 2; 129 130 /** @hide */ 131 @IntDef(prefix = { "PERMISSION_" }, value = { 132 PERMISSION_GRANTED, 133 PERMISSION_SOFT_DENIED, 134 PERMISSION_HARD_DENIED 135 }) 136 @Retention(RetentionPolicy.SOURCE) 137 public @interface PermissionResult {} 138 139 /** 140 * The set of flags that indicate that a permission state has been explicitly set 141 * 142 * @hide 143 */ 144 public static final int EXPLICIT_SET_FLAGS = FLAG_PERMISSION_USER_SET 145 | FLAG_PERMISSION_USER_FIXED | FLAG_PERMISSION_POLICY_FIXED 146 | FLAG_PERMISSION_SYSTEM_FIXED | FLAG_PERMISSION_GRANTED_BY_DEFAULT 147 | FLAG_PERMISSION_GRANTED_BY_ROLE; 148 149 /** 150 * Activity action: Launch UI to review permission decisions. 151 * <p> 152 * <strong>Important:</strong>You must protect the activity that handles this action with the 153 * {@link android.Manifest.permission#START_REVIEW_PERMISSION_DECISIONS} permission to ensure 154 * that only the system can launch this activity. The system will not launch activities that are 155 * not properly protected. 156 * <p> 157 * Input: Nothing. 158 * </p> 159 * <p> 160 * Output: Nothing. 161 * </p> 162 */ 163 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 164 @RequiresPermission(android.Manifest.permission.START_REVIEW_PERMISSION_DECISIONS) 165 public static final String ACTION_REVIEW_PERMISSION_DECISIONS = 166 "android.permission.action.REVIEW_PERMISSION_DECISIONS"; 167 168 169 /** @hide */ 170 public static final String LOG_TAG_TRACE_GRANTS = "PermissionGrantTrace"; 171 172 /** @hide */ 173 public static final String KILL_APP_REASON_PERMISSIONS_REVOKED = 174 "permissions revoked"; 175 /** @hide */ 176 public static final String KILL_APP_REASON_GIDS_CHANGED = 177 "permission grant or revoke changed gids"; 178 179 private static final String SYSTEM_PKG = "android"; 180 181 /** 182 * Refuse to install package if groups of permissions are bad 183 * - Permission groups should only be shared between apps sharing a certificate 184 * - If a permission belongs to a group that group should be defined 185 * 186 * @hide 187 */ 188 @ChangeId 189 @EnabledAfter(targetSdkVersion = S) 190 public static final long CANNOT_INSTALL_WITH_BAD_PERMISSION_GROUPS = 146211400; 191 192 /** 193 * Whether to use the new {@link com.android.server.permission.access.AccessCheckingService}. 194 * 195 * @hide 196 */ 197 public static final boolean USE_ACCESS_CHECKING_SERVICE = SdkLevel.isAtLeastV(); 198 199 /** 200 * The time to wait in between refreshing the exempted indicator role packages 201 */ 202 private static final long EXEMPTED_INDICATOR_ROLE_UPDATE_FREQUENCY_MS = 15000; 203 204 private static long sLastIndicatorUpdateTime = -1; 205 206 private static final int[] EXEMPTED_ROLES = {R.string.config_systemAmbientAudioIntelligence, 207 R.string.config_systemUiIntelligence, R.string.config_systemAudioIntelligence, 208 R.string.config_systemNotificationIntelligence, R.string.config_systemTextIntelligence, 209 R.string.config_systemVisualIntelligence}; 210 211 private static final String[] INDICATOR_EXEMPTED_PACKAGES = new String[EXEMPTED_ROLES.length]; 212 213 /** 214 * Note: Changing this won't do anything on its own - you should also change the filtering in 215 * {@link #shouldTraceGrant}. 216 * 217 * See log output for tag {@link #LOG_TAG_TRACE_GRANTS} 218 * 219 * @hide 220 */ 221 public static final boolean DEBUG_TRACE_GRANTS = false; 222 /** 223 * @hide 224 */ 225 public static final boolean DEBUG_TRACE_PERMISSION_UPDATES = false; 226 227 /** 228 * Additional debug log for virtual device permissions. 229 * @hide 230 */ 231 public static final boolean DEBUG_DEVICE_PERMISSIONS = false; 232 233 /** 234 * Intent extra: List of PermissionGroupUsages 235 * <p> 236 * Type: {@code List<PermissionGroupUsage>} 237 * </p> 238 * @hide 239 */ 240 @SystemApi 241 public static final String EXTRA_PERMISSION_USAGES = 242 "android.permission.extra.PERMISSION_USAGES"; 243 244 /** 245 * Specify what permissions are device aware. Only device aware permissions can be granted to 246 * a remote device. 247 * @hide 248 */ 249 public static final Set<String> DEVICE_AWARE_PERMISSIONS = 250 Flags.deviceAwarePermissionsEnabled() 251 ? Set.of(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO) 252 : Collections.emptySet(); 253 254 private final @NonNull Context mContext; 255 256 private final IPackageManager mPackageManager; 257 258 private final IPermissionManager mPermissionManager; 259 260 private final LegacyPermissionManager mLegacyPermissionManager; 261 262 private final ArrayMap<PackageManager.OnPermissionsChangedListener, 263 IOnPermissionsChangeListener> mPermissionListeners = new ArrayMap<>(); 264 private PermissionUsageHelper mUsageHelper; 265 266 private List<SplitPermissionInfo> mSplitPermissionInfos; 267 268 /** 269 * Creates a new instance. 270 * 271 * @param context The current context in which to operate 272 * 273 * @hide 274 */ PermissionManager(@onNull Context context)275 public PermissionManager(@NonNull Context context) 276 throws ServiceManager.ServiceNotFoundException { 277 mContext = context; 278 mPackageManager = AppGlobals.getPackageManager(); 279 mPermissionManager = IPermissionManager.Stub.asInterface(ServiceManager.getServiceOrThrow( 280 "permissionmgr")); 281 mLegacyPermissionManager = context.getSystemService(LegacyPermissionManager.class); 282 } 283 284 /** 285 * Checks whether a given data access chain described by the given {@link AttributionSource} 286 * has a given permission. 287 * 288 * <strong>NOTE:</strong> Use this method only for permission checks at the 289 * point where you will deliver the permission protected data to clients. 290 * 291 * <p>For example, if an app registers a location listener it should have the location 292 * permission but no data is actually sent to the app at the moment of registration 293 * and you should use {@link #checkPermissionForPreflight(String, AttributionSource)} 294 * to determine if the app has or may have location permission (if app has only foreground 295 * location the grant state depends on the app's fg/gb state) and this check will not 296 * leave a trace that permission protected data was delivered. When you are about to 297 * deliver the location data to a registered listener you should use this method which 298 * will evaluate the permission access based on the current fg/bg state of the app and 299 * leave a record that the data was accessed. 300 * 301 * <p>Requires the start of the AttributionSource chain to have the UPDATE_APP_OPS_STATS 302 * permission for the app op accesses to be given the TRUSTED_PROXY/PROXIED flags, otherwise the 303 * accesses will have the UNTRUSTED flags. 304 * 305 * @param permission The permission to check. 306 * @param attributionSource the permission identity 307 * @param message A message describing the reason the permission was checked 308 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 309 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 310 * 311 * @see #checkPermissionForPreflight(String, AttributionSource) 312 */ 313 @PermissionResult 314 @RequiresPermission(value = Manifest.permission.UPDATE_APP_OPS_STATS, conditional = true) checkPermissionForDataDelivery(@onNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message)315 public int checkPermissionForDataDelivery(@NonNull String permission, 316 @NonNull AttributionSource attributionSource, @Nullable String message) { 317 return PermissionChecker.checkPermissionForDataDelivery(mContext, permission, 318 // FIXME(b/199526514): PID should be passed inside AttributionSource. 319 PermissionChecker.PID_UNKNOWN, attributionSource, message); 320 } 321 322 /** 323 * 324 * Similar to checkPermissionForDataDelivery, except it results in an app op start, rather than 325 * a note. If this method is used, then {@link #finishDataDelivery(String, AttributionSource)} 326 * must be used when access is finished. 327 * 328 * @param permission The permission to check. 329 * @param attributionSource the permission identity 330 * @param message A message describing the reason the permission was checked 331 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 332 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 333 * 334 * <p>Requires the start of the AttributionSource chain to have the UPDATE_APP_OPS_STATS 335 * permission for the app op accesses to be given the TRUSTED_PROXY/PROXIED flags, otherwise the 336 * accesses will have the UNTRUSTED flags. 337 * 338 * @see #checkPermissionForDataDelivery(String, AttributionSource, String) 339 */ 340 @PermissionResult 341 @RequiresPermission(value = Manifest.permission.UPDATE_APP_OPS_STATS, conditional = true) checkPermissionForStartDataDelivery(@onNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message)342 public int checkPermissionForStartDataDelivery(@NonNull String permission, 343 @NonNull AttributionSource attributionSource, @Nullable String message) { 344 return PermissionChecker.checkPermissionForDataDelivery(mContext, permission, 345 // FIXME(b/199526514): PID should be passed inside AttributionSource. 346 PermissionChecker.PID_UNKNOWN, attributionSource, message, true); 347 } 348 349 /** 350 * Indicate that usage has finished for an {@link AttributionSource} started with 351 * {@link #checkPermissionForStartDataDelivery(String, AttributionSource, String)} 352 * 353 * @param permission The permission to check. 354 * @param attributionSource the permission identity to finish 355 */ finishDataDelivery(@onNull String permission, @NonNull AttributionSource attributionSource)356 public void finishDataDelivery(@NonNull String permission, 357 @NonNull AttributionSource attributionSource) { 358 PermissionChecker.finishDataDelivery(mContext, AppOpsManager.permissionToOp(permission), 359 attributionSource); 360 } 361 362 /** 363 * Checks whether a given data access chain described by the given {@link AttributionSource} 364 * has a given permission. Call this method if you are the datasource which would not blame you 365 * for access to the data since you are the data. Use this API if you are the datasource of the 366 * protected state. 367 * 368 * <strong>NOTE:</strong> Use this method only for permission checks at the 369 * point where you will deliver the permission protected data to clients. 370 * 371 * <p>For example, if an app registers a location listener it should have the location 372 * permission but no data is actually sent to the app at the moment of registration 373 * and you should use {@link #checkPermissionForPreflight(String, AttributionSource)} 374 * to determine if the app has or may have location permission (if app has only foreground 375 * location the grant state depends on the app's fg/gb state) and this check will not 376 * leave a trace that permission protected data was delivered. When you are about to 377 * deliver the location data to a registered listener you should use this method which 378 * will evaluate the permission access based on the current fg/bg state of the app and 379 * leave a record that the data was accessed. 380 * 381 * <p>Requires the start of the AttributionSource chain to have the UPDATE_APP_OPS_STATS 382 * permission for the app op accesses to be given the TRUSTED_PROXY/PROXIED flags, otherwise the 383 * accesses will have the UNTRUSTED flags. 384 * 385 * @param permission The permission to check. 386 * @param attributionSource the permission identity 387 * @param message A message describing the reason the permission was checked 388 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 389 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 390 * 391 * @see #checkPermissionForPreflight(String, AttributionSource) 392 */ 393 @PermissionResult 394 @RequiresPermission(value = Manifest.permission.UPDATE_APP_OPS_STATS, conditional = true) checkPermissionForDataDeliveryFromDataSource(@onNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message)395 public int checkPermissionForDataDeliveryFromDataSource(@NonNull String permission, 396 @NonNull AttributionSource attributionSource, @Nullable String message) { 397 return PermissionChecker.checkPermissionForDataDeliveryFromDataSource(mContext, permission, 398 PermissionChecker.PID_UNKNOWN, attributionSource, message); 399 } 400 401 /** 402 * Checks whether a given data access chain described by the given {@link AttributionSource} 403 * has a given permission. 404 * 405 * <strong>NOTE:</strong> Use this method only for permission checks at the 406 * preflight point where you will not deliver the permission protected data 407 * to clients but schedule permission data delivery, apps register listeners, 408 * etc. 409 * 410 * <p>For example, if an app registers a data listener it should have the required 411 * permission but no data is actually sent to the app at the moment of registration 412 * and you should use this method to determine if the app has or may have the 413 * permission and this check will not leave a trace that permission protected data 414 * was delivered. When you are about to deliver the protected data to a registered 415 * listener you should use {@link #checkPermissionForDataDelivery(String, 416 * AttributionSource, String)} which will evaluate the permission access based 417 * on the current fg/bg state of the app and leave a record that the data was accessed. 418 * 419 * @param permission The permission to check. 420 * @param attributionSource The identity for which to check the permission. 421 * @return The permission check result which is either {@link #PERMISSION_GRANTED} 422 * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. 423 */ 424 @PermissionResult checkPermissionForPreflight(@onNull String permission, @NonNull AttributionSource attributionSource)425 public int checkPermissionForPreflight(@NonNull String permission, 426 @NonNull AttributionSource attributionSource) { 427 return PermissionChecker.checkPermissionForPreflight(mContext, permission, 428 attributionSource); 429 } 430 431 /** 432 * Retrieve all of the information we know about a particular permission. 433 * 434 * @param permissionName the fully qualified name (e.g. com.android.permission.LOGIN) of the 435 * permission you are interested in 436 * @param flags additional option flags to modify the data returned 437 * @return a {@link PermissionInfo} containing information about the permission, or {@code null} 438 * if not found 439 * 440 * @hide Pending API 441 */ 442 @Nullable getPermissionInfo(@onNull String permissionName, @PackageManager.PermissionInfoFlags int flags)443 public PermissionInfo getPermissionInfo(@NonNull String permissionName, 444 @PackageManager.PermissionInfoFlags int flags) { 445 try { 446 final String packageName = mContext.getOpPackageName(); 447 return mPermissionManager.getPermissionInfo(permissionName, packageName, flags); 448 } catch (RemoteException e) { 449 throw e.rethrowFromSystemServer(); 450 } 451 } 452 453 /** 454 * Query for all of the permissions associated with a particular group. 455 * 456 * @param groupName the fully qualified name (e.g. com.android.permission.LOGIN) of the 457 * permission group you are interested in. Use {@code null} to find all of the 458 * permissions not associated with a group 459 * @param flags additional option flags to modify the data returned 460 * @return a list of {@link PermissionInfo} containing information about all of the permissions 461 * in the given group, or {@code null} if the group is not found 462 * 463 * @hide Pending API 464 */ 465 @Nullable queryPermissionsByGroup(@ullable String groupName, @PackageManager.PermissionInfoFlags int flags)466 public List<PermissionInfo> queryPermissionsByGroup(@Nullable String groupName, 467 @PackageManager.PermissionInfoFlags int flags) { 468 try { 469 final ParceledListSlice<PermissionInfo> parceledList = 470 mPermissionManager.queryPermissionsByGroup(groupName, flags); 471 if (parceledList == null) { 472 return null; 473 } 474 return parceledList.getList(); 475 } catch (RemoteException e) { 476 throw e.rethrowFromSystemServer(); 477 } 478 } 479 480 /** 481 * Add a new dynamic permission to the system. For this to work, your package must have defined 482 * a permission tree through the 483 * {@link android.R.styleable#AndroidManifestPermissionTree <permission-tree>} tag in its 484 * manifest. A package can only add permissions to trees that were defined by either its own 485 * package or another with the same user id; a permission is in a tree if it matches the name of 486 * the permission tree + ".": for example, "com.foo.bar" is a member of the permission tree 487 * "com.foo". 488 * <p> 489 * It is good to make your permission tree name descriptive, because you are taking possession 490 * of that entire set of permission names. Thus, it must be under a domain you control, with a 491 * suffix that will not match any normal permissions that may be declared in any applications 492 * that are part of that domain. 493 * <p> 494 * New permissions must be added before any .apks are installed that use those permissions. 495 * Permissions you add through this method are remembered across reboots of the device. If the 496 * given permission already exists, the info you supply here will be used to update it. 497 * 498 * @param permissionInfo description of the permission to be added 499 * @param async whether the persistence of the permission should be asynchronous, allowing it to 500 * return quicker and batch a series of adds, at the expense of no guarantee the 501 * added permission will be retained if the device is rebooted before it is 502 * written. 503 * @return {@code true} if a new permission was created, {@code false} if an existing one was 504 * updated 505 * @throws SecurityException if you are not allowed to add the given permission name 506 * 507 * @see #removePermission(String) 508 * 509 * @hide Pending API 510 */ addPermission(@onNull PermissionInfo permissionInfo, boolean async)511 public boolean addPermission(@NonNull PermissionInfo permissionInfo, boolean async) { 512 try { 513 return mPermissionManager.addPermission(permissionInfo, async); 514 } catch (RemoteException e) { 515 throw e.rethrowFromSystemServer(); 516 } 517 } 518 519 /** 520 * Removes a permission that was previously added with 521 * {@link #addPermission(PermissionInfo, boolean)}. The same ownership rules apply -- you are 522 * only allowed to remove permissions that you are allowed to add. 523 * 524 * @param permissionName the name of the permission to remove 525 * @throws SecurityException if you are not allowed to remove the given permission name 526 * 527 * @see #addPermission(PermissionInfo, boolean) 528 * 529 * @hide Pending API 530 */ removePermission(@onNull String permissionName)531 public void removePermission(@NonNull String permissionName) { 532 try { 533 mPermissionManager.removePermission(permissionName); 534 } catch (RemoteException e) { 535 throw e.rethrowFromSystemServer(); 536 } 537 } 538 539 /** 540 * Retrieve all of the information we know about a particular group of permissions. 541 * 542 * @param groupName the fully qualified name (e.g. com.android.permission_group.APPS) of the 543 * permission you are interested in 544 * @param flags additional option flags to modify the data returned 545 * @return a {@link PermissionGroupInfo} containing information about the permission, or 546 * {@code null} if not found 547 * 548 * @hide Pending API 549 */ 550 @Nullable getPermissionGroupInfo(@onNull String groupName, @PackageManager.PermissionGroupInfoFlags int flags)551 public PermissionGroupInfo getPermissionGroupInfo(@NonNull String groupName, 552 @PackageManager.PermissionGroupInfoFlags int flags) { 553 try { 554 return mPermissionManager.getPermissionGroupInfo(groupName, flags); 555 } catch (RemoteException e) { 556 throw e.rethrowFromSystemServer(); 557 } 558 } 559 560 /** 561 * Retrieve all of the known permission groups in the system. 562 * 563 * @param flags additional option flags to modify the data returned 564 * @return a list of {@link PermissionGroupInfo} containing information about all of the known 565 * permission groups 566 * 567 * @hide Pending API 568 */ 569 @NonNull getAllPermissionGroups( @ackageManager.PermissionGroupInfoFlags int flags)570 public List<PermissionGroupInfo> getAllPermissionGroups( 571 @PackageManager.PermissionGroupInfoFlags int flags) { 572 try { 573 final ParceledListSlice<PermissionGroupInfo> parceledList = 574 mPermissionManager.getAllPermissionGroups(flags); 575 if (parceledList == null) { 576 return Collections.emptyList(); 577 } 578 return parceledList.getList(); 579 } catch (RemoteException e) { 580 throw e.rethrowFromSystemServer(); 581 } 582 } 583 584 /** 585 * Checks whether a particular permissions has been revoked for a package by policy. Typically 586 * the device owner or the profile owner may apply such a policy. The user cannot grant policy 587 * revoked permissions, hence the only way for an app to get such a permission is by a policy 588 * change. 589 * 590 * @param packageName the name of the package you are checking against 591 * @param permissionName the name of the permission you are checking for 592 * 593 * @return whether the permission is restricted by policy 594 * 595 * @hide Pending API 596 */ 597 @CheckResult isPermissionRevokedByPolicy(@onNull String packageName, @NonNull String permissionName)598 public boolean isPermissionRevokedByPolicy(@NonNull String packageName, 599 @NonNull String permissionName) { 600 try { 601 return mPermissionManager.isPermissionRevokedByPolicy(packageName, permissionName, 602 mContext.getDeviceId(), mContext.getUserId()); 603 } catch (RemoteException e) { 604 throw e.rethrowFromSystemServer(); 605 } 606 } 607 608 /** @hide */ shouldTraceGrant( @onNull String packageName, @NonNull String permissionName, int userId)609 public static boolean shouldTraceGrant( 610 @NonNull String packageName, @NonNull String permissionName, int userId) { 611 // To be modified when debugging 612 // template: if ("".equals(packageName) && "".equals(permissionName)) return true; 613 return false; 614 } 615 616 /** 617 * Grant a runtime permission to an application which the application does not already have. The 618 * permission must have been requested by the application. If the application is not allowed to 619 * hold the permission, a {@link java.lang.SecurityException} is thrown. If the package or 620 * permission is invalid, a {@link java.lang.IllegalArgumentException} is thrown. 621 * <p> 622 * <strong>Note: </strong>Using this API requires holding 623 * {@code android.permission.GRANT_RUNTIME_PERMISSIONS} and if the user ID is not the current 624 * user {@code android.permission.INTERACT_ACROSS_USERS_FULL}. 625 * 626 * @param packageName the package to which to grant the permission 627 * @param permissionName the permission name to grant 628 * @param user the user for which to grant the permission 629 * 630 * @see #revokeRuntimePermission(String, String, android.os.UserHandle, String) 631 * 632 * @hide 633 */ 634 @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) 635 //@SystemApi grantRuntimePermission(@onNull String packageName, @NonNull String permissionName, @NonNull UserHandle user)636 public void grantRuntimePermission(@NonNull String packageName, 637 @NonNull String permissionName, @NonNull UserHandle user) { 638 String persistentDeviceId = getPersistentDeviceId(mContext.getDeviceId()); 639 if (persistentDeviceId == null) { 640 return; 641 } 642 643 grantRuntimePermissionInternal(packageName, permissionName, persistentDeviceId, user); 644 } 645 646 /** 647 * Grant a runtime permission to an application which the application does not already have. The 648 * permission must have been requested by the application. If the application is not allowed to 649 * hold the permission, a {@link java.lang.SecurityException} is thrown. If the package or 650 * permission is invalid, a {@link java.lang.IllegalArgumentException} is thrown. 651 * 652 * @param packageName the package to which to grant the permission 653 * @param permissionName the permission name to grant 654 * @param persistentDeviceId the device Id to which to grant the permission 655 * 656 * @see #revokeRuntimePermission(String, String, String, String) 657 * 658 * @hide 659 */ 660 @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) 661 @SystemApi 662 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) grantRuntimePermission(@onNull String packageName, @NonNull String permissionName, @NonNull String persistentDeviceId)663 public void grantRuntimePermission(@NonNull String packageName, 664 @NonNull String permissionName, @NonNull String persistentDeviceId) { 665 grantRuntimePermissionInternal(packageName, permissionName, persistentDeviceId, 666 mContext.getUser()); 667 } 668 grantRuntimePermissionInternal(@onNull String packageName, @NonNull String permissionName, @NonNull String persistentDeviceId, @NonNull UserHandle user)669 private void grantRuntimePermissionInternal(@NonNull String packageName, 670 @NonNull String permissionName, @NonNull String persistentDeviceId, 671 @NonNull UserHandle user) { 672 if (DEBUG_TRACE_GRANTS 673 && shouldTraceGrant(packageName, permissionName, user.getIdentifier())) { 674 Log.i(LOG_TAG_TRACE_GRANTS, "App " + mContext.getPackageName() + " is granting " 675 + packageName + " " 676 + permissionName + " for user " + user.getIdentifier() 677 + " for persistent device " + persistentDeviceId, new RuntimeException()); 678 } 679 try { 680 mPermissionManager.grantRuntimePermission(packageName, permissionName, 681 persistentDeviceId, user.getIdentifier()); 682 } catch (RemoteException e) { 683 throw e.rethrowFromSystemServer(); 684 } 685 } 686 687 /** 688 * Revoke a runtime permission that was previously granted by 689 * {@link #grantRuntimePermission(String, String, android.os.UserHandle)}. The permission must 690 * have been requested by and granted to the application. If the application is not allowed to 691 * hold the permission, a {@link java.lang.SecurityException} is thrown. If the package or 692 * permission is invalid, a {@link java.lang.IllegalArgumentException} is thrown. 693 * <p> 694 * <strong>Note: </strong>Using this API requires holding 695 * {@code android.permission.REVOKE_RUNTIME_PERMISSIONS} and if the user ID is not the current 696 * user {@code android.permission.INTERACT_ACROSS_USERS_FULL}. 697 * 698 * @param packageName the package from which to revoke the permission 699 * @param permissionName the permission name to revoke 700 * @param user the user for which to revoke the permission 701 * @param reason the reason for the revoke, or {@code null} for unspecified 702 * 703 * @see #grantRuntimePermission(String, String, android.os.UserHandle) 704 * 705 * @hide 706 */ 707 @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) 708 //@SystemApi revokeRuntimePermission(@onNull String packageName, @NonNull String permissionName, @NonNull UserHandle user, @Nullable String reason)709 public void revokeRuntimePermission(@NonNull String packageName, 710 @NonNull String permissionName, @NonNull UserHandle user, @Nullable String reason) { 711 String persistentDeviceId = getPersistentDeviceId(mContext.getDeviceId()); 712 if (persistentDeviceId == null) { 713 return; 714 } 715 716 revokeRuntimePermissionInternal(packageName, permissionName, persistentDeviceId, user, 717 reason); 718 } 719 720 /** 721 * Revoke a runtime permission that was previously granted by 722 * {@link #grantRuntimePermission(String, String, String)}. The permission must 723 * have been requested by and granted to the application. If the application is not allowed to 724 * hold the permission, a {@link java.lang.SecurityException} is thrown. If the package or 725 * permission is invalid, a {@link java.lang.IllegalArgumentException} is thrown. 726 * 727 * @param packageName the package from which to revoke the permission 728 * @param permissionName the permission name to revoke 729 * @param persistentDeviceId the persistent device id for which to revoke the permission 730 * @param reason the reason for the revoke, or {@code null} for unspecified 731 * 732 * @see #grantRuntimePermission(String, String, String) 733 * 734 * @hide 735 */ 736 @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) 737 @SystemApi 738 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) revokeRuntimePermission(@onNull String packageName, @NonNull String permissionName, @NonNull String persistentDeviceId, @Nullable String reason)739 public void revokeRuntimePermission(@NonNull String packageName, 740 @NonNull String permissionName, @NonNull String persistentDeviceId, 741 @Nullable String reason) { 742 revokeRuntimePermissionInternal(packageName, permissionName, persistentDeviceId, 743 mContext.getUser(), reason); 744 } 745 revokeRuntimePermissionInternal(@onNull String packageName, @NonNull String permissionName, @NonNull String persistentDeviceId, @NonNull UserHandle user, @Nullable String reason)746 private void revokeRuntimePermissionInternal(@NonNull String packageName, 747 @NonNull String permissionName, @NonNull String persistentDeviceId, 748 @NonNull UserHandle user, @Nullable String reason) { 749 if (DEBUG_TRACE_PERMISSION_UPDATES 750 && shouldTraceGrant(packageName, permissionName, user.getIdentifier())) { 751 Log.i(LOG_TAG, "App " + mContext.getPackageName() + " is revoking " + packageName + " " 752 + permissionName + " for user " + user.getIdentifier() 753 + " for persistent device " 754 + persistentDeviceId + " with reason " 755 + reason, new RuntimeException()); 756 } 757 try { 758 mPermissionManager.revokeRuntimePermission(packageName, permissionName, 759 persistentDeviceId, user.getIdentifier(), reason); 760 } catch (RemoteException e) { 761 throw e.rethrowFromSystemServer(); 762 } 763 } 764 765 /** 766 * Gets the state flags associated with a permission. 767 * 768 * @param packageName the package name for which to get the flags 769 * @param permissionName the permission for which to get the flags 770 * @param user the user for which to get permission flags 771 * @return the permission flags 772 * 773 * @hide 774 */ 775 @PackageManager.PermissionFlags 776 @RequiresPermission(anyOf = { 777 android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, 778 android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, 779 android.Manifest.permission.GET_RUNTIME_PERMISSIONS 780 }) 781 //@SystemApi getPermissionFlags(@onNull String packageName, @NonNull String permissionName, @NonNull UserHandle user)782 public int getPermissionFlags(@NonNull String packageName, @NonNull String permissionName, 783 @NonNull UserHandle user) { 784 String persistentDeviceId = getPersistentDeviceId(mContext.getDeviceId()); 785 if (persistentDeviceId == null) { 786 return 0; 787 } 788 789 return getPermissionFlagsInternal(packageName, permissionName, persistentDeviceId, user); 790 } 791 792 /** 793 * Gets the state flags associated with a permission. 794 * 795 * @param packageName the package name for which to get the flags 796 * @param permissionName the permission for which to get the flags 797 * @param persistentDeviceId the persistent device Id for which to get permission flags 798 * @return the permission flags 799 * 800 * @hide 801 */ 802 @PackageManager.PermissionFlags 803 @RequiresPermission(anyOf = { 804 android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, 805 android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, 806 android.Manifest.permission.GET_RUNTIME_PERMISSIONS 807 }) 808 @SystemApi 809 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) getPermissionFlags(@onNull String packageName, @NonNull String permissionName, @NonNull String persistentDeviceId)810 public int getPermissionFlags(@NonNull String packageName, @NonNull String permissionName, 811 @NonNull String persistentDeviceId) { 812 return getPermissionFlagsInternal(packageName, permissionName, persistentDeviceId, 813 mContext.getUser()); 814 } 815 getPermissionFlagsInternal(@onNull String packageName, @NonNull String permissionName, @NonNull String persistentDeviceId, @NonNull UserHandle user)816 private int getPermissionFlagsInternal(@NonNull String packageName, 817 @NonNull String permissionName, @NonNull String persistentDeviceId, 818 @NonNull UserHandle user) { 819 try { 820 return mPermissionManager.getPermissionFlags(packageName, permissionName, 821 persistentDeviceId, user.getIdentifier()); 822 } catch (RemoteException e) { 823 throw e.rethrowFromSystemServer(); 824 } 825 } 826 827 /** 828 * Updates the flags associated with a permission by replacing the flags in the specified mask 829 * with the provided flag values. 830 * 831 * @param packageName The package name for which to update the flags 832 * @param permissionName The permission for which to update the flags 833 * @param flagMask The flags which to replace 834 * @param flagValues The flags with which to replace 835 * @param user The user for which to update the permission flags 836 * 837 * @hide 838 */ 839 @RequiresPermission(anyOf = { 840 android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, 841 android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS 842 }) 843 //@SystemApi updatePermissionFlags(@onNull String packageName, @NonNull String permissionName, @PackageManager.PermissionFlags int flagMask, @PackageManager.PermissionFlags int flagValues, @NonNull UserHandle user)844 public void updatePermissionFlags(@NonNull String packageName, @NonNull String permissionName, 845 @PackageManager.PermissionFlags int flagMask, 846 @PackageManager.PermissionFlags int flagValues, @NonNull UserHandle user) { 847 String persistentDeviceId = getPersistentDeviceId(mContext.getDeviceId()); 848 if (persistentDeviceId == null) { 849 return; 850 } 851 852 updatePermissionFlagsInternal(packageName, permissionName, flagMask, flagValues, 853 persistentDeviceId, user); 854 } 855 856 /** 857 * Updates the flags associated with a permission by replacing the flags in the specified mask 858 * with the provided flag values. 859 * 860 * @param packageName The package name for which to update the flags 861 * @param permissionName The permission for which to update the flags 862 * @param persistentDeviceId The persistent device for which to update the permission flags 863 * @param flagMask The flags which to replace 864 * @param flagValues The flags with which to replace 865 * 866 * @hide 867 */ 868 @RequiresPermission(anyOf = { 869 android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, 870 android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS 871 }) 872 @SystemApi 873 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) updatePermissionFlags(@onNull String packageName, @NonNull String permissionName, @NonNull String persistentDeviceId, @PackageManager.PermissionFlags int flagMask, @PackageManager.PermissionFlags int flagValues )874 public void updatePermissionFlags(@NonNull String packageName, @NonNull String permissionName, 875 @NonNull String persistentDeviceId, 876 @PackageManager.PermissionFlags int flagMask, 877 @PackageManager.PermissionFlags int flagValues 878 ) { 879 updatePermissionFlagsInternal(packageName, permissionName, flagMask, flagValues, 880 persistentDeviceId, mContext.getUser()); 881 } 882 updatePermissionFlagsInternal(@onNull String packageName, @NonNull String permissionName, @PackageManager.PermissionFlags int flagMask, @PackageManager.PermissionFlags int flagValues, @NonNull String persistentDeviceId, @NonNull UserHandle user )883 private void updatePermissionFlagsInternal(@NonNull String packageName, 884 @NonNull String permissionName, 885 @PackageManager.PermissionFlags int flagMask, 886 @PackageManager.PermissionFlags int flagValues, @NonNull String persistentDeviceId, 887 @NonNull UserHandle user 888 ) { 889 if (DEBUG_TRACE_PERMISSION_UPDATES && shouldTraceGrant(packageName, permissionName, 890 user.getIdentifier())) { 891 Log.i(LOG_TAG, "App " + mContext.getPackageName() + " is updating flags for " 892 + packageName + " " + permissionName + " for user " 893 + user.getIdentifier() + " for persistentDeviceId " + persistentDeviceId + ": " 894 + DebugUtils.flagsToString(PackageManager.class, "FLAG_PERMISSION_", flagMask) 895 + " := " + DebugUtils.flagsToString(PackageManager.class, "FLAG_PERMISSION_", 896 flagValues), new RuntimeException()); 897 } 898 try { 899 final boolean checkAdjustPolicyFlagPermission = 900 mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q; 901 mPermissionManager.updatePermissionFlags(packageName, permissionName, flagMask, 902 flagValues, checkAdjustPolicyFlagPermission, 903 persistentDeviceId, user.getIdentifier()); 904 } catch (RemoteException e) { 905 throw e.rethrowFromSystemServer(); 906 } 907 } 908 909 /** 910 * Gets the restricted permissions that have been allowlisted and the app is allowed to have 911 * them granted in their full form. 912 * <p> 913 * Permissions can be hard restricted which means that the app cannot hold them or soft 914 * restricted where the app can hold the permission but in a weaker form. Whether a permission 915 * is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or 916 * {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission 917 * declaration. Allowlisting a hard restricted permission allows for the to hold that permission 918 * and allowlisting a soft restricted permission allows the app to hold the permission in its 919 * full, unrestricted form. 920 * <p> 921 * There are four allowlists: 922 * <ol> 923 * <li> 924 * One for cases where the system permission policy allowlists a permission. This list 925 * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be 926 * accessed by pre-installed holders of a dedicated permission. 927 * <li> 928 * One for cases where the system allowlists the permission when upgrading from an OS version in 929 * which the permission was not restricted to an OS version in which the permission is 930 * restricted. This list corresponds to the 931 * {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by 932 * pre-installed holders of a dedicated permission or the installer on record. 933 * <li> 934 * One for cases where the installer of the package allowlists a permission. This list 935 * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be 936 * accessed by pre-installed holders of a dedicated permission or the installer on record. 937 * </ol> 938 * 939 * @param packageName the app for which to get allowlisted permissions 940 * @param allowlistFlag the flag to determine which allowlist to query. Only one flag can be 941 * passed. 942 * @return the allowlisted permissions that are on any of the allowlists you query for 943 * @throws SecurityException if you try to access a allowlist that you have no access to 944 * 945 * @see #addAllowlistedRestrictedPermission(String, String, int) 946 * @see #removeAllowlistedRestrictedPermission(String, String, int) 947 * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM 948 * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE 949 * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER 950 * 951 * @hide Pending API 952 */ 953 @NonNull 954 @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS, 955 conditional = true) getAllowlistedRestrictedPermissions(@onNull String packageName, @PackageManager.PermissionWhitelistFlags int allowlistFlag)956 public Set<String> getAllowlistedRestrictedPermissions(@NonNull String packageName, 957 @PackageManager.PermissionWhitelistFlags int allowlistFlag) { 958 try { 959 final List<String> allowlist = mPermissionManager.getAllowlistedRestrictedPermissions( 960 packageName, allowlistFlag, mContext.getUserId()); 961 if (allowlist == null) { 962 return Collections.emptySet(); 963 } 964 return new ArraySet<>(allowlist); 965 } catch (RemoteException e) { 966 throw e.rethrowFromSystemServer(); 967 } 968 } 969 970 /** 971 * Adds a allowlisted restricted permission for an app. 972 * <p> 973 * Permissions can be hard restricted which means that the app cannot hold them or soft 974 * restricted where the app can hold the permission but in a weaker form. Whether a permission 975 * is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or 976 * {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission 977 * declaration. Allowlisting a hard restricted permission allows for the to hold that permission 978 * and allowlisting a soft restricted permission allows the app to hold the permission in its 979 * full, unrestricted form. 980 * <p>There are four allowlists: 981 * <ol> 982 * <li> 983 * One for cases where the system permission policy allowlists a permission. This list 984 * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be 985 * accessed by pre-installed holders of a dedicated permission. 986 * <li> 987 * One for cases where the system allowlists the permission when upgrading from an OS version in 988 * which the permission was not restricted to an OS version in which the permission is 989 * restricted. This list corresponds to the 990 * {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by 991 * pre-installed holders of a dedicated permission or the installer on record. 992 * <li> 993 * One for cases where the installer of the package allowlists a permission. This list 994 * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be 995 * accessed by pre-installed holders of a dedicated permission or the installer on record. 996 * </ol> 997 * <p> 998 * You need to specify the allowlists for which to set the allowlisted permissions which will 999 * clear the previous allowlisted permissions and replace them with the provided ones. 1000 * 1001 * @param packageName the app for which to get allowlisted permissions 1002 * @param permissionName the allowlisted permission to add 1003 * @param allowlistFlags the allowlists to which to add. Passing multiple flags updates all 1004 * specified allowlists. 1005 * @return whether the permission was added to the allowlist 1006 * @throws SecurityException if you try to modify a allowlist that you have no access to. 1007 * 1008 * @see #getAllowlistedRestrictedPermissions(String, int) 1009 * @see #removeAllowlistedRestrictedPermission(String, String, int) 1010 * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM 1011 * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE 1012 * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER 1013 * 1014 * @hide Pending API 1015 */ 1016 @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS, 1017 conditional = true) addAllowlistedRestrictedPermission(@onNull String packageName, @NonNull String permissionName, @PackageManager.PermissionWhitelistFlags int allowlistFlags)1018 public boolean addAllowlistedRestrictedPermission(@NonNull String packageName, 1019 @NonNull String permissionName, 1020 @PackageManager.PermissionWhitelistFlags int allowlistFlags) { 1021 try { 1022 return mPermissionManager.addAllowlistedRestrictedPermission(packageName, 1023 permissionName, allowlistFlags, mContext.getUserId()); 1024 } catch (RemoteException e) { 1025 throw e.rethrowFromSystemServer(); 1026 } 1027 } 1028 1029 /** 1030 * Removes a allowlisted restricted permission for an app. 1031 * <p> 1032 * Permissions can be hard restricted which means that the app cannot hold them or soft 1033 * restricted where the app can hold the permission but in a weaker form. Whether a permission 1034 * is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or 1035 * {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission 1036 * declaration. Allowlisting a hard restricted permission allows for the to hold that permission 1037 * and allowlisting a soft restricted permission allows the app to hold the permission in its 1038 * full, unrestricted form. 1039 * <p>There are four allowlists: 1040 * <ol> 1041 * <li> 1042 * One for cases where the system permission policy allowlists a permission. This list 1043 * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be 1044 * accessed by pre-installed holders of a dedicated permission. 1045 * <li> 1046 * One for cases where the system allowlists the permission when upgrading from an OS version in 1047 * which the permission was not restricted to an OS version in which the permission is 1048 * restricted. This list corresponds to the 1049 * {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by 1050 * pre-installed holders of a dedicated permission or the installer on record. 1051 * <li> 1052 * One for cases where the installer of the package allowlists a permission. This list 1053 * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be 1054 * accessed by pre-installed holders of a dedicated permission or the installer on record. 1055 * </ol> 1056 * <p> 1057 * You need to specify the allowlists for which to set the allowlisted permissions which will 1058 * clear the previous allowlisted permissions and replace them with the provided ones. 1059 * 1060 * @param packageName the app for which to get allowlisted permissions 1061 * @param permissionName the allowlisted permission to remove 1062 * @param allowlistFlags the allowlists from which to remove. Passing multiple flags updates all 1063 * specified allowlists. 1064 * @return whether the permission was removed from the allowlist 1065 * @throws SecurityException if you try to modify a allowlist that you have no access to. 1066 * 1067 * @see #getAllowlistedRestrictedPermissions(String, int) 1068 * @see #addAllowlistedRestrictedPermission(String, String, int) 1069 * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM 1070 * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE 1071 * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER 1072 * 1073 * @hide Pending API 1074 */ 1075 @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS, 1076 conditional = true) removeAllowlistedRestrictedPermission(@onNull String packageName, @NonNull String permissionName, @PackageManager.PermissionWhitelistFlags int allowlistFlags)1077 public boolean removeAllowlistedRestrictedPermission(@NonNull String packageName, 1078 @NonNull String permissionName, 1079 @PackageManager.PermissionWhitelistFlags int allowlistFlags) { 1080 try { 1081 return mPermissionManager.removeAllowlistedRestrictedPermission(packageName, 1082 permissionName, allowlistFlags, mContext.getUserId()); 1083 } catch (RemoteException e) { 1084 throw e.rethrowFromSystemServer(); 1085 } 1086 } 1087 1088 /** 1089 * Checks whether an application is exempted from having its permissions be automatically 1090 * revoked when the app is unused for an extended period of time. 1091 * <p> 1092 * Only the installer on record that installed the given package, or a holder of 1093 * {@code WHITELIST_AUTO_REVOKE_PERMISSIONS} is allowed to call this. 1094 * 1095 * @param packageName the app for which to set exemption 1096 * @return whether the app is exempted 1097 * @throws SecurityException if you you have no access to this 1098 * 1099 * @see #setAutoRevokeExempted 1100 * 1101 * @hide Pending API 1102 */ 1103 @RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS, 1104 conditional = true) isAutoRevokeExempted(@onNull String packageName)1105 public boolean isAutoRevokeExempted(@NonNull String packageName) { 1106 try { 1107 return mPermissionManager.isAutoRevokeExempted(packageName, mContext.getUserId()); 1108 } catch (RemoteException e) { 1109 throw e.rethrowFromSystemServer(); 1110 } 1111 } 1112 1113 /** 1114 * Marks an application exempted from having its permissions be automatically revoked when the 1115 * app is unused for an extended period of time. 1116 * <p> 1117 * Only the installer on record that installed the given package is allowed to call this. 1118 * <p> 1119 * Packages start in exempted state, and it is the installer's responsibility to un-exempt the 1120 * packages it installs, unless auto-revoking permissions from that package would cause 1121 * breakages beyond having to re-request the permission(s). 1122 * 1123 * @param packageName the app for which to set exemption 1124 * @param exempted whether the app should be exempted 1125 * @return whether any change took effect 1126 * @throws SecurityException if you you have no access to modify this 1127 * 1128 * @see #isAutoRevokeExempted 1129 * 1130 * @hide Pending API 1131 */ 1132 @RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS, 1133 conditional = true) setAutoRevokeExempted(@onNull String packageName, boolean exempted)1134 public boolean setAutoRevokeExempted(@NonNull String packageName, boolean exempted) { 1135 try { 1136 return mPermissionManager.setAutoRevokeExempted(packageName, exempted, 1137 mContext.getUserId()); 1138 } catch (RemoteException e) { 1139 throw e.rethrowFromSystemServer(); 1140 } 1141 } 1142 1143 /** 1144 * Get whether you should show UI with rationale for requesting a permission. You should do this 1145 * only if you do not have the permission and the context in which the permission is requested 1146 * does not clearly communicate to the user what would be the benefit from grating this 1147 * permission. 1148 * 1149 * @param permissionName a permission your app wants to request 1150 * @return whether you can show permission rationale UI 1151 * 1152 * @hide 1153 */ 1154 //@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) shouldShowRequestPermissionRationale(@onNull String permissionName)1155 public boolean shouldShowRequestPermissionRationale(@NonNull String permissionName) { 1156 try { 1157 final String packageName = mContext.getPackageName(); 1158 return mPermissionManager.shouldShowRequestPermissionRationale(packageName, 1159 permissionName, mContext.getDeviceId(), mContext.getUserId()); 1160 } catch (RemoteException e) { 1161 throw e.rethrowFromSystemServer(); 1162 } 1163 } 1164 1165 /** 1166 * Add a listener for permission changes for installed packages. 1167 * 1168 * @param listener the listener to add 1169 * 1170 * @hide 1171 */ 1172 //@SystemApi 1173 @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS) addOnPermissionsChangeListener( @onNull PackageManager.OnPermissionsChangedListener listener)1174 public void addOnPermissionsChangeListener( 1175 @NonNull PackageManager.OnPermissionsChangedListener listener) { 1176 synchronized (mPermissionListeners) { 1177 if (mPermissionListeners.get(listener) != null) { 1178 return; 1179 } 1180 final OnPermissionsChangeListenerDelegate delegate = 1181 new OnPermissionsChangeListenerDelegate(listener, Looper.getMainLooper()); 1182 try { 1183 mPermissionManager.addOnPermissionsChangeListener(delegate); 1184 mPermissionListeners.put(listener, delegate); 1185 } catch (RemoteException e) { 1186 throw e.rethrowFromSystemServer(); 1187 } 1188 } 1189 } 1190 1191 /** 1192 * Remove a listener for permission changes for installed packages. 1193 * 1194 * @param listener the listener to remove 1195 * 1196 * @hide 1197 */ 1198 //@SystemApi 1199 @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS) removeOnPermissionsChangeListener( @onNull PackageManager.OnPermissionsChangedListener listener)1200 public void removeOnPermissionsChangeListener( 1201 @NonNull PackageManager.OnPermissionsChangedListener listener) { 1202 synchronized (mPermissionListeners) { 1203 final IOnPermissionsChangeListener delegate = mPermissionListeners.get(listener); 1204 if (delegate != null) { 1205 try { 1206 mPermissionManager.removeOnPermissionsChangeListener(delegate); 1207 mPermissionListeners.remove(listener); 1208 } catch (RemoteException e) { 1209 throw e.rethrowFromSystemServer(); 1210 } 1211 } 1212 } 1213 } 1214 1215 /** 1216 * Gets the version of the runtime permission database. 1217 * 1218 * @return The database version, -1 when this is an upgrade from pre-Q, 0 when this is a fresh 1219 * install. 1220 * 1221 * @hide 1222 */ 1223 @SystemApi 1224 @RequiresPermission(anyOf = { 1225 Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, 1226 Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS 1227 }) getRuntimePermissionsVersion()1228 public @IntRange(from = 0) int getRuntimePermissionsVersion() { 1229 try { 1230 return mPackageManager.getRuntimePermissionsVersion(mContext.getUserId()); 1231 } catch (RemoteException e) { 1232 throw e.rethrowFromSystemServer(); 1233 } 1234 } 1235 1236 /** 1237 * Sets the version of the runtime permission database. 1238 * 1239 * @param version The new version. 1240 * 1241 * @hide 1242 */ 1243 @SystemApi 1244 @RequiresPermission(anyOf = { 1245 Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, 1246 Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS 1247 }) setRuntimePermissionsVersion(@ntRangefrom = 0) int version)1248 public void setRuntimePermissionsVersion(@IntRange(from = 0) int version) { 1249 try { 1250 mPackageManager.setRuntimePermissionsVersion(version, mContext.getUserId()); 1251 } catch (RemoteException e) { 1252 throw e.rethrowFromSystemServer(); 1253 } 1254 } 1255 1256 /** 1257 * Get set of permissions that have been split into more granular or dependent permissions. 1258 * 1259 * <p>E.g. before {@link android.os.Build.VERSION_CODES#Q} an app that was granted 1260 * {@link Manifest.permission#ACCESS_COARSE_LOCATION} could access the location while it was in 1261 * foreground and background. On platforms after {@link android.os.Build.VERSION_CODES#Q} 1262 * the location permission only grants location access while the app is in foreground. This 1263 * would break apps that target before {@link android.os.Build.VERSION_CODES#Q}. Hence whenever 1264 * such an old app asks for a location permission (i.e. the 1265 * {@link SplitPermissionInfo#getSplitPermission()}), then the 1266 * {@link Manifest.permission#ACCESS_BACKGROUND_LOCATION} permission (inside 1267 * {@link SplitPermissionInfo#getNewPermissions}) is added. 1268 * 1269 * <p>Note: Regular apps do not have to worry about this. The platform and permission controller 1270 * automatically add the new permissions where needed. 1271 * 1272 * @return All permissions that are split. 1273 */ getSplitPermissions()1274 public @NonNull List<SplitPermissionInfo> getSplitPermissions() { 1275 if (mSplitPermissionInfos != null) { 1276 return mSplitPermissionInfos; 1277 } 1278 1279 List<SplitPermissionInfoParcelable> parcelableList; 1280 try { 1281 parcelableList = ActivityThread.getPermissionManager().getSplitPermissions(); 1282 } catch (RemoteException e) { 1283 Slog.e(LOG_TAG, "Error getting split permissions", e); 1284 return Collections.emptyList(); 1285 } 1286 1287 mSplitPermissionInfos = splitPermissionInfoListToNonParcelableList(parcelableList); 1288 1289 return mSplitPermissionInfos; 1290 } 1291 1292 /** 1293 * Initialize the PermissionUsageHelper, which will register active app op listeners 1294 * 1295 * @hide 1296 */ initializeUsageHelper()1297 public void initializeUsageHelper() { 1298 if (mUsageHelper == null) { 1299 mUsageHelper = new PermissionUsageHelper(mContext); 1300 } 1301 } 1302 1303 /** 1304 * Teardown the PermissionUsageHelper, removing listeners 1305 * 1306 * @hide 1307 */ tearDownUsageHelper()1308 public void tearDownUsageHelper() { 1309 if (mUsageHelper != null) { 1310 mUsageHelper.tearDown(); 1311 mUsageHelper = null; 1312 } 1313 } 1314 1315 /** 1316 * @return A list of permission groups currently or recently used by all apps by all users in 1317 * the current profile group. 1318 * 1319 * @hide 1320 */ 1321 @TestApi 1322 @NonNull 1323 @RequiresPermission(Manifest.permission.GET_APP_OPS_STATS) getIndicatorAppOpUsageData()1324 public List<PermissionGroupUsage> getIndicatorAppOpUsageData() { 1325 return getIndicatorAppOpUsageData(new AudioManager().isMicrophoneMute()); 1326 } 1327 1328 /** 1329 * @param micMuted whether to consider the microphone muted when retrieving audio ops 1330 * @return A list of permission groups currently or recently used by all apps by all users in 1331 * the current profile group. 1332 * 1333 * @hide 1334 */ 1335 @TestApi 1336 @NonNull 1337 @RequiresPermission(Manifest.permission.GET_APP_OPS_STATS) getIndicatorAppOpUsageData(boolean micMuted)1338 public List<PermissionGroupUsage> getIndicatorAppOpUsageData(boolean micMuted) { 1339 // Lazily initialize the usage helper 1340 initializeUsageHelper(); 1341 boolean includeMicrophoneUsage = !micMuted; 1342 return mUsageHelper.getOpUsageDataByDevice(includeMicrophoneUsage, 1343 VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT); 1344 } 1345 1346 /** 1347 * Determine if a package should be shown in indicators. Only a select few roles, and the 1348 * system app itself, are hidden. These values are updated at most every 15 seconds. 1349 * @hide 1350 */ shouldShowPackageForIndicatorCached(@onNull Context context, @NonNull String packageName)1351 public static boolean shouldShowPackageForIndicatorCached(@NonNull Context context, 1352 @NonNull String packageName) { 1353 return !getIndicatorExemptedPackages(context).contains(packageName); 1354 } 1355 1356 /** 1357 * Get the list of packages that are not shown by the indicators. Only a select few roles, and 1358 * the system app itself, are hidden. These values are updated at most every 15 seconds. 1359 * @hide 1360 */ getIndicatorExemptedPackages(@onNull Context context)1361 public static Set<String> getIndicatorExemptedPackages(@NonNull Context context) { 1362 updateIndicatorExemptedPackages(context); 1363 ArraySet<String> pkgNames = new ArraySet<>(); 1364 pkgNames.add(SYSTEM_PKG); 1365 for (int i = 0; i < INDICATOR_EXEMPTED_PACKAGES.length; i++) { 1366 String exemptedPackage = INDICATOR_EXEMPTED_PACKAGES[i]; 1367 if (exemptedPackage != null) { 1368 pkgNames.add(exemptedPackage); 1369 } 1370 } 1371 return pkgNames; 1372 } 1373 1374 /** 1375 * Update the cached indicator exempted packages 1376 * @hide 1377 */ updateIndicatorExemptedPackages(@onNull Context context)1378 public static void updateIndicatorExemptedPackages(@NonNull Context context) { 1379 long now = SystemClock.elapsedRealtime(); 1380 if (sLastIndicatorUpdateTime == -1 1381 || (now - sLastIndicatorUpdateTime) > EXEMPTED_INDICATOR_ROLE_UPDATE_FREQUENCY_MS) { 1382 sLastIndicatorUpdateTime = now; 1383 for (int i = 0; i < EXEMPTED_ROLES.length; i++) { 1384 INDICATOR_EXEMPTED_PACKAGES[i] = context.getString(EXEMPTED_ROLES[i]); 1385 } 1386 } 1387 } 1388 /** 1389 * Gets the list of packages that have permissions that specified 1390 * {@code requestDontAutoRevokePermissions=true} in their 1391 * {@code application} manifest declaration. 1392 * 1393 * @return the list of packages for current user 1394 * @hide 1395 */ 1396 @SystemApi 1397 @NonNull 1398 @RequiresPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY) getAutoRevokeExemptionRequestedPackages()1399 public Set<String> getAutoRevokeExemptionRequestedPackages() { 1400 try { 1401 return CollectionUtils.toSet(mPermissionManager.getAutoRevokeExemptionRequestedPackages( 1402 mContext.getUser().getIdentifier())); 1403 } catch (RemoteException e) { 1404 throw e.rethrowFromSystemServer(); 1405 } 1406 } 1407 1408 /** 1409 * Gets the list of packages that have permissions that specified 1410 * {@code autoRevokePermissions=disallowed} in their 1411 * {@code application} manifest declaration. 1412 * 1413 * @return the list of packages for current user 1414 * @hide 1415 */ 1416 @SystemApi 1417 @NonNull 1418 @RequiresPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY) getAutoRevokeExemptionGrantedPackages()1419 public Set<String> getAutoRevokeExemptionGrantedPackages() { 1420 try { 1421 return CollectionUtils.toSet(mPermissionManager.getAutoRevokeExemptionGrantedPackages( 1422 mContext.getUser().getIdentifier())); 1423 } catch (RemoteException e) { 1424 throw e.rethrowFromSystemServer(); 1425 } 1426 } 1427 splitPermissionInfoListToNonParcelableList( List<SplitPermissionInfoParcelable> parcelableList)1428 private List<SplitPermissionInfo> splitPermissionInfoListToNonParcelableList( 1429 List<SplitPermissionInfoParcelable> parcelableList) { 1430 final int size = parcelableList.size(); 1431 List<SplitPermissionInfo> list = new ArrayList<>(size); 1432 for (int i = 0; i < size; i++) { 1433 list.add(new SplitPermissionInfo(parcelableList.get(i))); 1434 } 1435 return list; 1436 } 1437 1438 /** 1439 * Converts a {@link List} of {@link SplitPermissionInfo} into a List of 1440 * {@link SplitPermissionInfoParcelable} and returns it. 1441 * @hide 1442 */ splitPermissionInfoListToParcelableList( List<SplitPermissionInfo> splitPermissionsList)1443 public static List<SplitPermissionInfoParcelable> splitPermissionInfoListToParcelableList( 1444 List<SplitPermissionInfo> splitPermissionsList) { 1445 final int size = splitPermissionsList.size(); 1446 List<SplitPermissionInfoParcelable> outList = new ArrayList<>(size); 1447 for (int i = 0; i < size; i++) { 1448 SplitPermissionInfo info = splitPermissionsList.get(i); 1449 outList.add(new SplitPermissionInfoParcelable( 1450 info.getSplitPermission(), info.getNewPermissions(), info.getTargetSdk())); 1451 } 1452 return outList; 1453 } 1454 1455 /** 1456 * A permission that was added in a previous API level might have split into several 1457 * permissions. This object describes one such split. 1458 */ 1459 @Immutable 1460 public static final class SplitPermissionInfo { 1461 private @NonNull final SplitPermissionInfoParcelable mSplitPermissionInfoParcelable; 1462 1463 @Override equals(@ullable Object o)1464 public boolean equals(@Nullable Object o) { 1465 if (this == o) return true; 1466 if (o == null || getClass() != o.getClass()) return false; 1467 SplitPermissionInfo that = (SplitPermissionInfo) o; 1468 return mSplitPermissionInfoParcelable.equals(that.mSplitPermissionInfoParcelable); 1469 } 1470 1471 @Override hashCode()1472 public int hashCode() { 1473 return mSplitPermissionInfoParcelable.hashCode(); 1474 } 1475 1476 /** 1477 * Get the permission that is split. 1478 */ getSplitPermission()1479 public @NonNull String getSplitPermission() { 1480 return mSplitPermissionInfoParcelable.getSplitPermission(); 1481 } 1482 1483 /** 1484 * Get the permissions that are added. 1485 */ getNewPermissions()1486 public @NonNull List<String> getNewPermissions() { 1487 return mSplitPermissionInfoParcelable.getNewPermissions(); 1488 } 1489 1490 /** 1491 * Get the target API level when the permission was split. 1492 */ getTargetSdk()1493 public int getTargetSdk() { 1494 return mSplitPermissionInfoParcelable.getTargetSdk(); 1495 } 1496 1497 /** 1498 * Constructs a split permission. 1499 * 1500 * @param splitPerm old permission that will be split 1501 * @param newPerms list of new permissions that {@code rootPerm} will be split into 1502 * @param targetSdk apps targetting SDK versions below this will have {@code rootPerm} 1503 * split into {@code newPerms} 1504 * @hide 1505 */ SplitPermissionInfo(@onNull String splitPerm, @NonNull List<String> newPerms, int targetSdk)1506 public SplitPermissionInfo(@NonNull String splitPerm, @NonNull List<String> newPerms, 1507 int targetSdk) { 1508 this(new SplitPermissionInfoParcelable(splitPerm, newPerms, targetSdk)); 1509 } 1510 SplitPermissionInfo(@onNull SplitPermissionInfoParcelable parcelable)1511 private SplitPermissionInfo(@NonNull SplitPermissionInfoParcelable parcelable) { 1512 mSplitPermissionInfoParcelable = parcelable; 1513 } 1514 } 1515 1516 /** 1517 * Starts a one-time permission session for a given package. 1518 * @see #startOneTimePermissionSession(String, long, long, int, int) 1519 * @hide 1520 * @deprecated Use {@link #startOneTimePermissionSession(String, long, long, int, int)} instead 1521 */ 1522 @Deprecated 1523 @SystemApi 1524 @RequiresPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS) startOneTimePermissionSession(@onNull String packageName, long timeoutMillis, @ActivityManager.RunningAppProcessInfo.Importance int importanceToResetTimer, @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive)1525 public void startOneTimePermissionSession(@NonNull String packageName, long timeoutMillis, 1526 @ActivityManager.RunningAppProcessInfo.Importance int importanceToResetTimer, 1527 @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive) { 1528 startOneTimePermissionSession(packageName, timeoutMillis, -1, 1529 importanceToResetTimer, importanceToKeepSessionAlive); 1530 } 1531 1532 /** 1533 * Starts a one-time permission session for a given package. A one-time permission session is 1534 * ended if app becomes inactive. Inactivity is defined as the package's uid importance level 1535 * staying > importanceToResetTimer for timeoutMillis milliseconds. If the package's uid 1536 * importance level goes <= importanceToResetTimer then the timer is reset and doesn't start 1537 * until going > importanceToResetTimer. 1538 * <p> 1539 * When this timeoutMillis is reached if the importance level is <= importanceToKeepSessionAlive 1540 * then the session is extended until either the importance goes above 1541 * importanceToKeepSessionAlive which will end the session or <= importanceToResetTimer which 1542 * will continue the session and reset the timer. 1543 * </p> 1544 * <p> 1545 * Importance levels are defined in {@link android.app.ActivityManager.RunningAppProcessInfo}. 1546 * </p> 1547 * <p> 1548 * Once the session ends 1549 * {@link PermissionControllerService#onOneTimePermissionSessionTimeout(String)} is invoked. 1550 * </p> 1551 * <p> 1552 * Note that if there is currently an active session for a package a new one isn't created but 1553 * each parameter of the existing one will be updated to the more aggressive of both sessions. 1554 * This means that durations will be set to the shortest parameter and importances will be set 1555 * to the lowest one. 1556 * </p> 1557 * @param packageName The package to start a one-time permission session for 1558 * @param timeoutMillis Number of milliseconds for an app to be in an inactive state 1559 * @param revokeAfterKilledDelayMillis Number of milliseconds to wait before revoking on the 1560 * event an app is terminated. Set to -1 to use default 1561 * value for the device. 1562 * @param importanceToResetTimer The least important level to uid must be to reset the timer 1563 * @param importanceToKeepSessionAlive The least important level the uid must be to keep the 1564 * session alive 1565 * 1566 * @hide 1567 */ 1568 @SystemApi 1569 @RequiresPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS) startOneTimePermissionSession(@onNull String packageName, @DurationMillisLong long timeoutMillis, @DurationMillisLong long revokeAfterKilledDelayMillis, @ActivityManager.RunningAppProcessInfo.Importance int importanceToResetTimer, @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive)1570 public void startOneTimePermissionSession(@NonNull String packageName, 1571 @DurationMillisLong long timeoutMillis, 1572 @DurationMillisLong long revokeAfterKilledDelayMillis, 1573 @ActivityManager.RunningAppProcessInfo.Importance int importanceToResetTimer, 1574 @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive) { 1575 try { 1576 mPermissionManager.startOneTimePermissionSession(packageName, mContext.getDeviceId(), 1577 mContext.getUserId(), timeoutMillis, revokeAfterKilledDelayMillis); 1578 } catch (RemoteException e) { 1579 e.rethrowFromSystemServer(); 1580 } 1581 } 1582 1583 /** 1584 * Stops the one-time permission session for the package. The callback to the end of session is 1585 * not invoked. If there is no one-time session for the package then nothing happens. 1586 * 1587 * @param packageName Package to stop the one-time permission session for 1588 * 1589 * @hide 1590 */ 1591 @SystemApi 1592 @RequiresPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS) stopOneTimePermissionSession(@onNull String packageName)1593 public void stopOneTimePermissionSession(@NonNull String packageName) { 1594 try { 1595 mPermissionManager.stopOneTimePermissionSession(packageName, 1596 mContext.getUserId()); 1597 } catch (RemoteException e) { 1598 e.rethrowFromSystemServer(); 1599 } 1600 } 1601 1602 /** 1603 * Checks whether the package with the given pid/uid can read device identifiers. 1604 * 1605 * @param packageName the name of the package to be checked for identifier access 1606 * @param message the message to be used for logging during identifier access 1607 * verification 1608 * @param callingFeatureId the feature in the package 1609 * @param pid the process id of the package to be checked 1610 * @param uid the uid of the package to be checked 1611 * @return {@link PackageManager#PERMISSION_GRANTED} if the package is allowed identifier 1612 * access, {@link PackageManager#PERMISSION_DENIED} otherwise 1613 * @hide 1614 */ 1615 @SystemApi checkDeviceIdentifierAccess(@ullable String packageName, @Nullable String message, @Nullable String callingFeatureId, int pid, int uid)1616 public int checkDeviceIdentifierAccess(@Nullable String packageName, @Nullable String message, 1617 @Nullable String callingFeatureId, int pid, int uid) { 1618 return mLegacyPermissionManager.checkDeviceIdentifierAccess(packageName, message, 1619 callingFeatureId, pid, uid); 1620 } 1621 1622 /** 1623 * Registers an attribution source with the OS. An app can only register an attribution 1624 * source for itself. Once an attribution source has been registered another app can 1625 * check whether this registration exists and thus trust the payload in the source 1626 * object. This is important for permission checking and specifically for app op blaming 1627 * since a malicious app should not be able to force the OS to blame another app 1628 * that doesn't participate in an attribution chain. 1629 * 1630 * @param source The attribution source to register. 1631 * @return The registered new attribution source. 1632 * 1633 * @see #isRegisteredAttributionSource(AttributionSource) 1634 * 1635 * @hide 1636 */ 1637 @TestApi registerAttributionSource(@onNull AttributionSource source)1638 public @NonNull AttributionSource registerAttributionSource(@NonNull AttributionSource source) { 1639 // We use a shared static token for sources that are not registered since the token's 1640 // only used for process death detection. If we are about to use the source for security 1641 // enforcement we need to replace the binder with a unique one. 1642 try { 1643 if (serverSideAttributionRegistration()) { 1644 IBinder newToken = mPermissionManager.registerAttributionSource(source.asState()); 1645 return source.withToken(newToken); 1646 } else { 1647 AttributionSource registeredSource = source.withToken(new Binder()); 1648 mPermissionManager.registerAttributionSource(registeredSource.asState()); 1649 return registeredSource; 1650 } 1651 } catch (RemoteException e) { 1652 e.rethrowFromSystemServer(); 1653 } 1654 return source; 1655 } 1656 1657 /** 1658 * Checks whether an attribution source is registered. 1659 * 1660 * @param source The attribution source to check. 1661 * @return Whether this is a registered source. 1662 * 1663 * @see #registerAttributionSource(AttributionSource) 1664 * 1665 * @hide 1666 */ 1667 @TestApi 1668 @FlaggedApi(FLAG_SHOULD_REGISTER_ATTRIBUTION_SOURCE) isRegisteredAttributionSource(@onNull AttributionSource source)1669 public boolean isRegisteredAttributionSource(@NonNull AttributionSource source) { 1670 try { 1671 return mPermissionManager.isRegisteredAttributionSource(source.asState()); 1672 } catch (RemoteException e) { 1673 e.rethrowFromSystemServer(); 1674 } 1675 return false; 1676 } 1677 1678 /** 1679 * Gets the number of currently registered attribution sources for a particular UID. This should 1680 * only be used for testing purposes. 1681 * @hide 1682 */ 1683 @RequiresPermission(Manifest.permission.UPDATE_APP_OPS_STATS) getRegisteredAttributionSourceCountForTest(int uid)1684 public int getRegisteredAttributionSourceCountForTest(int uid) { 1685 try { 1686 return mPermissionManager.getRegisteredAttributionSourceCount(uid); 1687 } catch (RemoteException e) { 1688 e.rethrowFromSystemServer(); 1689 } 1690 return -1; 1691 } 1692 1693 /** 1694 * Revoke the POST_NOTIFICATIONS permission, without killing the app. This method must ONLY BE 1695 * USED in CTS or local tests. 1696 * 1697 * @param packageName The package to be revoked 1698 * @param userId The user for which to revoke 1699 * 1700 * @hide 1701 */ 1702 @TestApi 1703 @RequiresPermission(Manifest.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL) revokePostNotificationPermissionWithoutKillForTest(@onNull String packageName, int userId)1704 public void revokePostNotificationPermissionWithoutKillForTest(@NonNull String packageName, 1705 int userId) { 1706 try { 1707 mPermissionManager.revokePostNotificationPermissionWithoutKillForTest(packageName, 1708 userId); 1709 } catch (RemoteException e) { 1710 e.rethrowFromSystemServer(); 1711 } 1712 } 1713 1714 // Only warn once for assuming that root or system UID has a permission 1715 // to reduce duplicate logcat output. 1716 private static volatile boolean sShouldWarnMissingActivityManager = true; 1717 checkPermissionUncached(@ullable String permission, int pid, int uid, int deviceId)1718 private static int checkPermissionUncached(@Nullable String permission, int pid, int uid, 1719 int deviceId) { 1720 final int appId = UserHandle.getAppId(uid); 1721 if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) { 1722 return PackageManager.PERMISSION_GRANTED; 1723 } 1724 final IActivityManager am = ActivityManager.getService(); 1725 if (am == null) { 1726 // We don't have an active ActivityManager instance and the calling UID is not root or 1727 // system, so we don't grant this permission. 1728 Slog.w(LOG_TAG, "Missing ActivityManager; assuming " + uid + " does not hold " 1729 + permission); 1730 return PackageManager.PERMISSION_DENIED; 1731 } 1732 try { 1733 sShouldWarnMissingActivityManager = true; 1734 return am.checkPermissionForDevice(permission, pid, uid, deviceId); 1735 } catch (RemoteException e) { 1736 throw e.rethrowFromSystemServer(); 1737 } 1738 } 1739 getPermissionRequestStateUncached(String packageName, String permission, int deviceId)1740 private static int getPermissionRequestStateUncached(String packageName, String permission, 1741 int deviceId) { 1742 try { 1743 return AppGlobals.getPermissionManager().getPermissionRequestState( 1744 packageName, permission, deviceId); 1745 } catch (RemoteException e) { 1746 throw e.rethrowFromSystemServer(); 1747 } 1748 } 1749 1750 /** 1751 * Identifies a permission query. 1752 * 1753 * N.B. we include the checking pid for tracking purposes but don't include it in the equality 1754 * comparison: we use only uid for the actual security check, so comparing pid would result 1755 * in spurious misses. 1756 * 1757 * @hide 1758 */ 1759 @Immutable 1760 private static final class PermissionQuery { 1761 final String permission; 1762 final int pid; 1763 final int uid; 1764 final int deviceId; 1765 PermissionQuery(@ullable String permission, int pid, int uid, int deviceId)1766 PermissionQuery(@Nullable String permission, int pid, int uid, int deviceId) { 1767 this.permission = permission; 1768 this.pid = pid; 1769 this.uid = uid; 1770 this.deviceId = deviceId; 1771 } 1772 1773 @Override toString()1774 public String toString() { 1775 return TextUtils.formatSimple("PermissionQuery(permission=\"%s\", pid=%d, uid=%d, " 1776 + "deviceId=%d)", permission, pid, uid, deviceId); 1777 } 1778 1779 @Override hashCode()1780 public int hashCode() { 1781 // N.B. pid doesn't count toward equality and therefore shouldn't count for 1782 // hashing either. 1783 return Objects.hash(permission, uid, deviceId); 1784 } 1785 1786 @Override equals(@ullable Object rval)1787 public boolean equals(@Nullable Object rval) { 1788 // N.B. pid doesn't count toward equality! 1789 if (rval == null) { 1790 return false; 1791 } 1792 PermissionQuery other; 1793 try { 1794 other = (PermissionQuery) rval; 1795 } catch (ClassCastException ex) { 1796 return false; 1797 } 1798 return uid == other.uid && deviceId == other.deviceId 1799 && Objects.equals(permission, other.permission); 1800 } 1801 } 1802 1803 private static final class PermissionRequestStateQuery { 1804 final String mPackageName; 1805 final String mPermission; 1806 final int mDeviceId; 1807 PermissionRequestStateQuery(@onNull String packageName, @NonNull String permission, int deviceId)1808 PermissionRequestStateQuery(@NonNull String packageName, @NonNull String permission, 1809 int deviceId) { 1810 mPackageName = packageName; 1811 mPermission = permission; 1812 mDeviceId = deviceId; 1813 } 1814 1815 @Override toString()1816 public String toString() { 1817 return TextUtils.formatSimple("PermissionRequestStateQuery(package=\"%s\"," 1818 + " permission=\"%s\", " + "deviceId=%d)", 1819 mPackageName, mPermission, mDeviceId); 1820 } 1821 1822 @Override hashCode()1823 public int hashCode() { 1824 return Objects.hash(mPackageName, mPermission, mDeviceId); 1825 } 1826 1827 @Override equals(@ullable Object rval)1828 public boolean equals(@Nullable Object rval) { 1829 if (rval == null) { 1830 return false; 1831 } 1832 PermissionRequestStateQuery other; 1833 try { 1834 other = (PermissionRequestStateQuery) rval; 1835 } catch (ClassCastException ex) { 1836 return false; 1837 } 1838 return mDeviceId == other.mDeviceId && Objects.equals(mPackageName, other.mPackageName) 1839 && Objects.equals(mPermission, other.mPermission); 1840 } 1841 } 1842 1843 // The legacy system property "package_info" had two purposes: to invalidate PIC caches and to 1844 // signal that package information, and therefore permissions, might have changed. 1845 // AudioSystem is the only client of the signaling behavior. The "separate permissions 1846 // notification" feature splits the two behaviors into two system property names. 1847 // 1848 // If the feature is disabled (legacy behavior) then the two system property names have the 1849 // same value. This means there is only one system property in use. 1850 // 1851 // If the feature is enabled, then the two system property names have different values, which 1852 // means there is a system property used by PIC and a system property used for signaling. The 1853 // legacy value is hard-coded in native code that relies on the signaling behavior, so the 1854 // system property name for signaling is the legacy property name, and the system property 1855 // name for PIC is new. getPackageInfoCacheKey()1856 private static String getPackageInfoCacheKey() { 1857 if (PropertyInvalidatedCache.separatePermissionNotificationsEnabled()) { 1858 return PropertyInvalidatedCache.createSystemCacheKey("package_info_cache"); 1859 } else { 1860 return CACHE_KEY_PACKAGE_INFO_NOTIFY; 1861 } 1862 } 1863 1864 /** 1865 * The system property that is used to notify clients that package information, and therefore 1866 * permissions, may have changed. 1867 * @hide 1868 */ 1869 public static final String CACHE_KEY_PACKAGE_INFO_NOTIFY = 1870 PropertyInvalidatedCache.createSystemCacheKey("package_info"); 1871 1872 /** 1873 * The system property that is used to invalidate PIC caches. 1874 * @hide 1875 */ 1876 public static final String CACHE_KEY_PACKAGE_INFO_CACHE = getPackageInfoCacheKey(); 1877 1878 /** @hide */ 1879 private static final PropertyInvalidatedCache<PermissionQuery, Integer> sPermissionCache = 1880 new PropertyInvalidatedCache<PermissionQuery, Integer>( 1881 2048, CACHE_KEY_PACKAGE_INFO_CACHE, "checkPermission") { 1882 @Override 1883 public Integer recompute(PermissionQuery query) { 1884 return checkPermissionUncached(query.permission, query.pid, query.uid, 1885 query.deviceId); 1886 } 1887 }; 1888 1889 /** @hide */ 1890 private static final PropertyInvalidatedCache<PermissionRequestStateQuery, Integer> 1891 sPermissionRequestStateCache = 1892 new PropertyInvalidatedCache<>( 1893 512, CACHE_KEY_PACKAGE_INFO_CACHE, "getPermissionRequestState") { 1894 @Override 1895 public Integer recompute(PermissionRequestStateQuery query) { 1896 return getPermissionRequestStateUncached(query.mPackageName, query.mPermission, 1897 query.mDeviceId); 1898 } 1899 }; 1900 1901 /** @hide */ checkPermission(@ullable String permission, int pid, int uid, int deviceId)1902 public static int checkPermission(@Nullable String permission, int pid, int uid, int deviceId) { 1903 return sPermissionCache.query(new PermissionQuery(permission, pid, uid, deviceId)); 1904 } 1905 1906 /** @hide */ 1907 @Context.PermissionRequestState getPermissionRequestState(@onNull String packageName, @NonNull String permission, int deviceId)1908 public int getPermissionRequestState(@NonNull String packageName, @NonNull String permission, 1909 int deviceId) { 1910 int resolvedDeviceId = resolveDeviceIdForPermissionCheck(mContext, deviceId, permission); 1911 return sPermissionRequestStateCache.query( 1912 new PermissionRequestStateQuery(packageName, permission, resolvedDeviceId)); 1913 } 1914 1915 /** 1916 * Gets the permission states for requested package and persistent device. 1917 * <p> 1918 * <strong>Note: </strong>Default device permissions are not inherited in this API. Returns the 1919 * exact permission states for the requested device. 1920 * 1921 * @param packageName name of the package you are checking against 1922 * @param persistentDeviceId id of the persistent device you are checking against 1923 * @return mapping of all permission states keyed by their permission names 1924 * 1925 * @hide 1926 */ 1927 @SystemApi 1928 @NonNull 1929 @RequiresPermission(anyOf = { 1930 android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, 1931 android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, 1932 android.Manifest.permission.GET_RUNTIME_PERMISSIONS 1933 }) 1934 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) getAllPermissionStates(@onNull String packageName, @NonNull String persistentDeviceId)1935 public Map<String, PermissionState> getAllPermissionStates(@NonNull String packageName, 1936 @NonNull String persistentDeviceId) { 1937 try { 1938 return mPermissionManager.getAllPermissionStates(packageName, persistentDeviceId, 1939 mContext.getUserId()); 1940 } catch (RemoteException e) { 1941 throw e.rethrowFromSystemServer(); 1942 } 1943 } 1944 1945 /** 1946 * Make checkPermission() above bypass the permission cache in this process. 1947 * 1948 * @hide 1949 */ disablePermissionCache()1950 public static void disablePermissionCache() { 1951 sPermissionCache.disableLocal(); 1952 } 1953 1954 /** 1955 * Like PermissionQuery, but for permission checks based on a package name instead of 1956 * a UID. 1957 */ 1958 @Immutable 1959 private static final class PackageNamePermissionQuery { 1960 final String permName; 1961 final String pkgName; 1962 final String persistentDeviceId; 1963 @UserIdInt 1964 final int userId; 1965 PackageNamePermissionQuery(@ullable String permName, @Nullable String pkgName, @Nullable String persistentDeviceId, @UserIdInt int userId)1966 PackageNamePermissionQuery(@Nullable String permName, @Nullable String pkgName, 1967 @Nullable String persistentDeviceId, @UserIdInt int userId) { 1968 this.permName = permName; 1969 this.pkgName = pkgName; 1970 this.persistentDeviceId = persistentDeviceId; 1971 this.userId = userId; 1972 } 1973 1974 @Override toString()1975 public String toString() { 1976 return TextUtils.formatSimple( 1977 "PackageNamePermissionQuery(pkgName=\"%s\", permName=\"%s\", " 1978 + "persistentDeviceId=%s, userId=%s\")", 1979 pkgName, permName, persistentDeviceId, userId); 1980 } 1981 1982 @Override hashCode()1983 public int hashCode() { 1984 return Objects.hash(permName, pkgName, persistentDeviceId, userId); 1985 } 1986 1987 @Override equals(@ullable Object rval)1988 public boolean equals(@Nullable Object rval) { 1989 if (rval == null) { 1990 return false; 1991 } 1992 PackageNamePermissionQuery other; 1993 try { 1994 other = (PackageNamePermissionQuery) rval; 1995 } catch (ClassCastException ex) { 1996 return false; 1997 } 1998 return Objects.equals(permName, other.permName) 1999 && Objects.equals(pkgName, other.pkgName) 2000 && Objects.equals(persistentDeviceId, other.persistentDeviceId) 2001 && userId == other.userId; 2002 } 2003 } 2004 2005 /* @hide */ checkPackageNamePermissionUncached( String permName, String pkgName, String persistentDeviceId, @UserIdInt int userId)2006 private static int checkPackageNamePermissionUncached( 2007 String permName, String pkgName, String persistentDeviceId, @UserIdInt int userId) { 2008 try { 2009 return ActivityThread.getPermissionManager().checkPermission( 2010 pkgName, permName, persistentDeviceId, userId); 2011 } catch (RemoteException e) { 2012 throw e.rethrowFromSystemServer(); 2013 } 2014 } 2015 2016 /* @hide */ 2017 private static PropertyInvalidatedCache<PackageNamePermissionQuery, Integer> 2018 sPackageNamePermissionCache = 2019 new PropertyInvalidatedCache<PackageNamePermissionQuery, Integer>( 2020 16, CACHE_KEY_PACKAGE_INFO_CACHE, "checkPackageNamePermission") { 2021 @Override 2022 public Integer recompute(PackageNamePermissionQuery query) { 2023 return checkPackageNamePermissionUncached( 2024 query.permName, query.pkgName, query.persistentDeviceId, query.userId); 2025 } 2026 @Override 2027 public boolean bypass(PackageNamePermissionQuery query) { 2028 return query.userId < 0; 2029 } 2030 }; 2031 2032 /** 2033 * Check whether a package has a permission for given device. 2034 * 2035 * @hide 2036 */ checkPackageNamePermission(String permName, String pkgName, int deviceId, @UserIdInt int userId)2037 public int checkPackageNamePermission(String permName, String pkgName, 2038 int deviceId, @UserIdInt int userId) { 2039 int resolvedDeviceId = resolveDeviceIdForPermissionCheck(mContext, deviceId, permName); 2040 String persistentDeviceId = getPersistentDeviceId(resolvedDeviceId); 2041 return sPackageNamePermissionCache.query( 2042 new PackageNamePermissionQuery(permName, pkgName, persistentDeviceId, userId)); 2043 } 2044 2045 /** 2046 * When checking a device-aware permission on a remote device, if the permission is CAMERA 2047 * or RECORD_AUDIO we need to check remote device's corresponding capability. If the remote 2048 * device doesn't have capability fall back to checking permission on the default device. 2049 * 2050 * @hide 2051 */ resolveDeviceIdForPermissionCheck(@onNull Context context, int deviceId, @Nullable String permission)2052 public static int resolveDeviceIdForPermissionCheck(@NonNull Context context, int deviceId, 2053 @Nullable String permission) { 2054 if (deviceId == Context.DEVICE_ID_DEFAULT || !DEVICE_AWARE_PERMISSIONS.contains( 2055 permission)) { 2056 return Context.DEVICE_ID_DEFAULT; 2057 } 2058 2059 VirtualDeviceManager virtualDeviceManager = 2060 context.getSystemService(VirtualDeviceManager.class); 2061 if (virtualDeviceManager == null) { 2062 Slog.e(LOG_TAG, "VDM is not enabled when device id is not default. deviceId = " 2063 + deviceId); 2064 } else { 2065 VirtualDevice virtualDevice = virtualDeviceManager.getVirtualDevice(deviceId); 2066 if (virtualDevice != null) { 2067 if ((Objects.equals(permission, Manifest.permission.RECORD_AUDIO) 2068 && !virtualDevice.hasCustomAudioInputSupport()) 2069 || (Objects.equals(permission, Manifest.permission.CAMERA) 2070 && !virtualDevice.hasCustomCameraSupport())) { 2071 deviceId = Context.DEVICE_ID_DEFAULT; 2072 } 2073 } else { 2074 Slog.e(LOG_TAG, 2075 "virtualDevice is not found when device id is not default. deviceId = " 2076 + deviceId); 2077 } 2078 } 2079 return deviceId; 2080 } 2081 2082 @Nullable getPersistentDeviceId(int deviceId)2083 private String getPersistentDeviceId(int deviceId) { 2084 String persistentDeviceId = null; 2085 2086 if (deviceId == Context.DEVICE_ID_DEFAULT) { 2087 persistentDeviceId = PERSISTENT_DEVICE_ID_DEFAULT; 2088 } else { 2089 VirtualDeviceManager virtualDeviceManager = mContext.getSystemService( 2090 VirtualDeviceManager.class); 2091 if (virtualDeviceManager != null) { 2092 VirtualDevice virtualDevice = virtualDeviceManager.getVirtualDevice(deviceId); 2093 if (virtualDevice == null) { 2094 Slog.e(LOG_TAG, "Virtual device is not found with device Id " + deviceId); 2095 return null; 2096 } 2097 persistentDeviceId = virtualDevice.getPersistentDeviceId(); 2098 if (persistentDeviceId == null) { 2099 Slog.e(LOG_TAG, "Cannot find persistent device Id for " + deviceId); 2100 } 2101 } 2102 } 2103 return persistentDeviceId; 2104 } 2105 2106 /** 2107 * Check whether a package has been granted a permission on a given device. 2108 * <p> 2109 * <strong>Note: </strong>This API returns the underlying permission state 2110 * as-is and is mostly intended for permission managing system apps. To 2111 * perform an access check for a certain app, please use the 2112 * {@link Context#checkPermission} APIs instead. 2113 * 2114 * @param permissionName The name of the permission you are checking for. 2115 * @param packageName The name of the package you are checking against. 2116 * @param persistentDeviceId The id of the physical device that you are checking permission 2117 * against. 2118 * 2119 * @return If the package has the permission on the device, PERMISSION_GRANTED is 2120 * returned. If it does not have the permission on the device, PERMISSION_DENIED 2121 * is returned. 2122 * 2123 * @see VirtualDevice#getPersistentDeviceId() 2124 * @see PackageManager#PERMISSION_GRANTED 2125 * @see PackageManager#PERMISSION_DENIED 2126 * 2127 * @hide 2128 */ 2129 @SystemApi 2130 @PermissionResult 2131 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) checkPermission(@onNull String permissionName, @NonNull String packageName, @NonNull String persistentDeviceId)2132 public int checkPermission(@NonNull String permissionName, @NonNull String packageName, 2133 @NonNull String persistentDeviceId) { 2134 return sPackageNamePermissionCache.query( 2135 new PackageNamePermissionQuery(permissionName, packageName, persistentDeviceId, 2136 mContext.getUserId())); 2137 } 2138 2139 /** 2140 * Make checkPackageNamePermission() bypass the cache in this process. 2141 * 2142 * @hide 2143 */ disablePackageNamePermissionCache()2144 public static void disablePackageNamePermissionCache() { 2145 sPackageNamePermissionCache.disableLocal(); 2146 } 2147 2148 private final class OnPermissionsChangeListenerDelegate 2149 extends IOnPermissionsChangeListener.Stub implements Handler.Callback { 2150 private static final int MSG_PERMISSIONS_CHANGED = 1; 2151 2152 private final PackageManager.OnPermissionsChangedListener mListener; 2153 private final Handler mHandler; 2154 OnPermissionsChangeListenerDelegate( PackageManager.OnPermissionsChangedListener listener, Looper looper)2155 public OnPermissionsChangeListenerDelegate( 2156 PackageManager.OnPermissionsChangedListener listener, Looper looper) { 2157 mListener = listener; 2158 mHandler = new Handler(looper, this); 2159 } 2160 2161 @Override onPermissionsChanged(int uid, String persistentDeviceId)2162 public void onPermissionsChanged(int uid, String persistentDeviceId) { 2163 mHandler.obtainMessage(MSG_PERMISSIONS_CHANGED, uid, 0, persistentDeviceId) 2164 .sendToTarget(); 2165 } 2166 2167 @Override handleMessage(Message msg)2168 public boolean handleMessage(Message msg) { 2169 switch (msg.what) { 2170 case MSG_PERMISSIONS_CHANGED: { 2171 final int uid = msg.arg1; 2172 final String persistentDeviceId = msg.obj.toString(); 2173 mListener.onPermissionsChanged(uid, persistentDeviceId); 2174 return true; 2175 } 2176 default: 2177 return false; 2178 } 2179 } 2180 } 2181 2182 /** 2183 * Data class for the state of a permission requested by a package 2184 * 2185 * @hide 2186 */ 2187 @SystemApi 2188 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) 2189 public static final class PermissionState implements Parcelable { 2190 private final boolean mGranted; 2191 private final int mFlags; 2192 2193 /** @hide */ 2194 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) PermissionState(boolean granted, int flags)2195 public PermissionState(boolean granted, int flags) { 2196 mGranted = granted; 2197 mFlags = flags; 2198 } 2199 2200 /** 2201 * Returns whether this permission is granted 2202 */ 2203 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) isGranted()2204 public boolean isGranted() { 2205 return mGranted; 2206 } 2207 2208 /** 2209 * Returns the flags associated with this permission state 2210 * @see PackageManager#getPermissionFlags 2211 */ 2212 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) getFlags()2213 public int getFlags() { 2214 return mFlags; 2215 } 2216 2217 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) 2218 @Override describeContents()2219 public int describeContents() { 2220 return 0; 2221 } 2222 2223 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) 2224 @Override writeToParcel(@onNull Parcel parcel, int flags)2225 public void writeToParcel(@NonNull Parcel parcel, int flags) { 2226 parcel.writeBoolean(mGranted); 2227 parcel.writeInt(mFlags); 2228 } 2229 PermissionState(Parcel parcel)2230 private PermissionState(Parcel parcel) { 2231 this(parcel.readBoolean(), parcel.readInt()); 2232 } 2233 2234 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) 2235 public static final @NonNull Creator<PermissionState> CREATOR = new Creator<>() { 2236 public PermissionState createFromParcel(Parcel source) { 2237 return new PermissionState(source); 2238 } 2239 2240 public PermissionState[] newArray(int size) { 2241 return new PermissionState[size]; 2242 } 2243 }; 2244 2245 /** @hide */ 2246 @Override equals(Object o)2247 public boolean equals(Object o) { 2248 if (this == o) return true; 2249 if (o == null || getClass() != o.getClass()) return false; 2250 PermissionState that = (PermissionState) o; 2251 return mGranted == that.mGranted && mFlags == that.mFlags; 2252 } 2253 2254 /** @hide */ 2255 @Override hashCode()2256 public int hashCode() { 2257 return Objects.hash(mGranted, mFlags); 2258 } 2259 2260 /** @hide */ 2261 @Override toString()2262 public String toString() { 2263 return "PermissionState{" 2264 + "mGranted=" + mGranted 2265 + ", mFlags=" + mFlags 2266 + '}'; 2267 } 2268 } 2269 } 2270