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.os.Build.VERSION_CODES.S; 20 21 import android.Manifest; 22 import android.annotation.CheckResult; 23 import android.annotation.IntRange; 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 import android.annotation.RequiresPermission; 27 import android.annotation.SystemApi; 28 import android.annotation.SystemService; 29 import android.annotation.TestApi; 30 import android.annotation.UserIdInt; 31 import android.app.ActivityManager; 32 import android.app.ActivityThread; 33 import android.app.AppGlobals; 34 import android.app.IActivityManager; 35 import android.app.PropertyInvalidatedCache; 36 import android.compat.annotation.ChangeId; 37 import android.compat.annotation.EnabledAfter; 38 import android.content.AttributionSource; 39 import android.content.Context; 40 import android.content.pm.IPackageManager; 41 import android.content.pm.PackageManager; 42 import android.content.pm.ParceledListSlice; 43 import android.content.pm.PermissionGroupInfo; 44 import android.content.pm.PermissionInfo; 45 import android.content.pm.permission.SplitPermissionInfoParcelable; 46 import android.media.AudioManager; 47 import android.os.Binder; 48 import android.os.Build; 49 import android.os.Handler; 50 import android.os.Looper; 51 import android.os.Message; 52 import android.os.Process; 53 import android.os.RemoteException; 54 import android.os.ServiceManager; 55 import android.os.SystemClock; 56 import android.os.UserHandle; 57 import android.util.ArrayMap; 58 import android.util.ArraySet; 59 import android.util.DebugUtils; 60 import android.util.Log; 61 import android.util.Slog; 62 63 import com.android.internal.R; 64 import com.android.internal.annotations.Immutable; 65 import com.android.internal.util.CollectionUtils; 66 67 import java.util.ArrayList; 68 import java.util.Collections; 69 import java.util.List; 70 import java.util.Objects; 71 import java.util.Set; 72 73 /** 74 * System level service for accessing the permission capabilities of the platform. 75 * 76 * @hide 77 */ 78 @SystemApi 79 @SystemService(Context.PERMISSION_SERVICE) 80 public final class PermissionManager { 81 private static final String LOG_TAG = PermissionManager.class.getName(); 82 83 /** @hide */ 84 public static final String LOG_TAG_TRACE_GRANTS = "PermissionGrantTrace"; 85 86 /** @hide */ 87 public static final String KILL_APP_REASON_PERMISSIONS_REVOKED = 88 "permissions revoked"; 89 /** @hide */ 90 public static final String KILL_APP_REASON_GIDS_CHANGED = 91 "permission grant or revoke changed gids"; 92 93 private static final String SYSTEM_PKG = "android"; 94 95 /** 96 * Refuse to install package if groups of permissions are bad 97 * - Permission groups should only be shared between apps sharing a certificate 98 * - If a permission belongs to a group that group should be defined 99 * 100 * @hide 101 */ 102 @ChangeId 103 @EnabledAfter(targetSdkVersion = S) 104 public static final long CANNOT_INSTALL_WITH_BAD_PERMISSION_GROUPS = 146211400; 105 106 /** 107 * The time to wait in between refreshing the exempted indicator role packages 108 */ 109 private static final long EXEMPTED_INDICATOR_ROLE_UPDATE_FREQUENCY_MS = 15000; 110 111 private static long sLastIndicatorUpdateTime = -1; 112 113 private static final int[] EXEMPTED_ROLES = {R.string.config_systemAmbientAudioIntelligence, 114 R.string.config_systemUiIntelligence, R.string.config_systemAudioIntelligence, 115 R.string.config_systemNotificationIntelligence, R.string.config_systemTextIntelligence, 116 R.string.config_systemVisualIntelligence}; 117 118 private static final String[] INDICATOR_EXEMPTED_PACKAGES = new String[EXEMPTED_ROLES.length]; 119 120 /** 121 * Note: Changing this won't do anything on its own - you should also change the filtering in 122 * {@link #shouldTraceGrant}. 123 * 124 * See log output for tag {@link #LOG_TAG_TRACE_GRANTS} 125 * 126 * @hide 127 */ 128 public static final boolean DEBUG_TRACE_GRANTS = false; 129 /** 130 * @hide 131 */ 132 public static final boolean DEBUG_TRACE_PERMISSION_UPDATES = false; 133 134 private final @NonNull Context mContext; 135 136 private final IPackageManager mPackageManager; 137 138 private final IPermissionManager mPermissionManager; 139 140 private final LegacyPermissionManager mLegacyPermissionManager; 141 142 private final ArrayMap<PackageManager.OnPermissionsChangedListener, 143 IOnPermissionsChangeListener> mPermissionListeners = new ArrayMap<>(); 144 private PermissionUsageHelper mUsageHelper; 145 146 private List<SplitPermissionInfo> mSplitPermissionInfos; 147 148 /** 149 * Creates a new instance. 150 * 151 * @param context The current context in which to operate 152 * 153 * @hide 154 */ PermissionManager(@onNull Context context)155 public PermissionManager(@NonNull Context context) 156 throws ServiceManager.ServiceNotFoundException { 157 mContext = context; 158 mPackageManager = AppGlobals.getPackageManager(); 159 mPermissionManager = IPermissionManager.Stub.asInterface(ServiceManager.getServiceOrThrow( 160 "permissionmgr")); 161 mLegacyPermissionManager = context.getSystemService(LegacyPermissionManager.class); 162 } 163 164 /** 165 * Retrieve all of the information we know about a particular permission. 166 * 167 * @param permissionName the fully qualified name (e.g. com.android.permission.LOGIN) of the 168 * permission you are interested in 169 * @param flags additional option flags to modify the data returned 170 * @return a {@link PermissionInfo} containing information about the permission, or {@code null} 171 * if not found 172 * 173 * @hide Pending API 174 */ 175 @Nullable getPermissionInfo(@onNull String permissionName, @PackageManager.PermissionInfoFlags int flags)176 public PermissionInfo getPermissionInfo(@NonNull String permissionName, 177 @PackageManager.PermissionInfoFlags int flags) { 178 try { 179 final String packageName = mContext.getOpPackageName(); 180 return mPermissionManager.getPermissionInfo(permissionName, packageName, flags); 181 } catch (RemoteException e) { 182 throw e.rethrowFromSystemServer(); 183 } 184 } 185 186 /** 187 * Query for all of the permissions associated with a particular group. 188 * 189 * @param groupName the fully qualified name (e.g. com.android.permission.LOGIN) of the 190 * permission group you are interested in. Use {@code null} to find all of the 191 * permissions not associated with a group 192 * @param flags additional option flags to modify the data returned 193 * @return a list of {@link PermissionInfo} containing information about all of the permissions 194 * in the given group, or {@code null} if the group is not found 195 * 196 * @hide Pending API 197 */ 198 @Nullable queryPermissionsByGroup(@ullable String groupName, @PackageManager.PermissionInfoFlags int flags)199 public List<PermissionInfo> queryPermissionsByGroup(@Nullable String groupName, 200 @PackageManager.PermissionInfoFlags int flags) { 201 try { 202 final ParceledListSlice<PermissionInfo> parceledList = 203 mPermissionManager.queryPermissionsByGroup(groupName, flags); 204 if (parceledList == null) { 205 return null; 206 } 207 return parceledList.getList(); 208 } catch (RemoteException e) { 209 throw e.rethrowFromSystemServer(); 210 } 211 } 212 213 /** 214 * Add a new dynamic permission to the system. For this to work, your package must have defined 215 * a permission tree through the 216 * {@link android.R.styleable#AndroidManifestPermissionTree <permission-tree>} tag in its 217 * manifest. A package can only add permissions to trees that were defined by either its own 218 * package or another with the same user id; a permission is in a tree if it matches the name of 219 * the permission tree + ".": for example, "com.foo.bar" is a member of the permission tree 220 * "com.foo". 221 * <p> 222 * It is good to make your permission tree name descriptive, because you are taking possession 223 * of that entire set of permission names. Thus, it must be under a domain you control, with a 224 * suffix that will not match any normal permissions that may be declared in any applications 225 * that are part of that domain. 226 * <p> 227 * New permissions must be added before any .apks are installed that use those permissions. 228 * Permissions you add through this method are remembered across reboots of the device. If the 229 * given permission already exists, the info you supply here will be used to update it. 230 * 231 * @param permissionInfo description of the permission to be added 232 * @param async whether the persistence of the permission should be asynchronous, allowing it to 233 * return quicker and batch a series of adds, at the expense of no guarantee the 234 * added permission will be retained if the device is rebooted before it is 235 * written. 236 * @return {@code true} if a new permission was created, {@code false} if an existing one was 237 * updated 238 * @throws SecurityException if you are not allowed to add the given permission name 239 * 240 * @see #removePermission(String) 241 * 242 * @hide Pending API 243 */ addPermission(@onNull PermissionInfo permissionInfo, boolean async)244 public boolean addPermission(@NonNull PermissionInfo permissionInfo, boolean async) { 245 try { 246 return mPermissionManager.addPermission(permissionInfo, async); 247 } catch (RemoteException e) { 248 throw e.rethrowFromSystemServer(); 249 } 250 } 251 252 /** 253 * Removes a permission that was previously added with 254 * {@link #addPermission(PermissionInfo, boolean)}. The same ownership rules apply -- you are 255 * only allowed to remove permissions that you are allowed to add. 256 * 257 * @param permissionName the name of the permission to remove 258 * @throws SecurityException if you are not allowed to remove the given permission name 259 * 260 * @see #addPermission(PermissionInfo, boolean) 261 * 262 * @hide Pending API 263 */ removePermission(@onNull String permissionName)264 public void removePermission(@NonNull String permissionName) { 265 try { 266 mPermissionManager.removePermission(permissionName); 267 } catch (RemoteException e) { 268 throw e.rethrowFromSystemServer(); 269 } 270 } 271 272 /** 273 * Retrieve all of the information we know about a particular group of permissions. 274 * 275 * @param groupName the fully qualified name (e.g. com.android.permission_group.APPS) of the 276 * permission you are interested in 277 * @param flags additional option flags to modify the data returned 278 * @return a {@link PermissionGroupInfo} containing information about the permission, or 279 * {@code null} if not found 280 * 281 * @hide Pending API 282 */ 283 @Nullable getPermissionGroupInfo(@onNull String groupName, @PackageManager.PermissionGroupInfoFlags int flags)284 public PermissionGroupInfo getPermissionGroupInfo(@NonNull String groupName, 285 @PackageManager.PermissionGroupInfoFlags int flags) { 286 try { 287 return mPermissionManager.getPermissionGroupInfo(groupName, flags); 288 } catch (RemoteException e) { 289 throw e.rethrowFromSystemServer(); 290 } 291 } 292 293 /** 294 * Retrieve all of the known permission groups in the system. 295 * 296 * @param flags additional option flags to modify the data returned 297 * @return a list of {@link PermissionGroupInfo} containing information about all of the known 298 * permission groups 299 * 300 * @hide Pending API 301 */ 302 @NonNull getAllPermissionGroups( @ackageManager.PermissionGroupInfoFlags int flags)303 public List<PermissionGroupInfo> getAllPermissionGroups( 304 @PackageManager.PermissionGroupInfoFlags int flags) { 305 try { 306 final ParceledListSlice<PermissionGroupInfo> parceledList = 307 mPermissionManager.getAllPermissionGroups(flags); 308 if (parceledList == null) { 309 return Collections.emptyList(); 310 } 311 return parceledList.getList(); 312 } catch (RemoteException e) { 313 throw e.rethrowFromSystemServer(); 314 } 315 } 316 317 /** 318 * Checks whether a particular permissions has been revoked for a package by policy. Typically 319 * the device owner or the profile owner may apply such a policy. The user cannot grant policy 320 * revoked permissions, hence the only way for an app to get such a permission is by a policy 321 * change. 322 * 323 * @param packageName the name of the package you are checking against 324 * @param permissionName the name of the permission you are checking for 325 * 326 * @return whether the permission is restricted by policy 327 * 328 * @hide Pending API 329 */ 330 @CheckResult isPermissionRevokedByPolicy(@onNull String packageName, @NonNull String permissionName)331 public boolean isPermissionRevokedByPolicy(@NonNull String packageName, 332 @NonNull String permissionName) { 333 try { 334 return mPermissionManager.isPermissionRevokedByPolicy(packageName, permissionName, 335 mContext.getUserId()); 336 } catch (RemoteException e) { 337 throw e.rethrowFromSystemServer(); 338 } 339 } 340 341 /** @hide */ shouldTraceGrant( @onNull String packageName, @NonNull String permissionName, int userId)342 public static boolean shouldTraceGrant( 343 @NonNull String packageName, @NonNull String permissionName, int userId) { 344 // To be modified when debugging 345 // template: if ("".equals(packageName) && "".equals(permissionName)) return true; 346 return false; 347 } 348 349 /** 350 * Grant a runtime permission to an application which the application does not already have. The 351 * permission must have been requested by the application. If the application is not allowed to 352 * hold the permission, a {@link java.lang.SecurityException} is thrown. If the package or 353 * permission is invalid, a {@link java.lang.IllegalArgumentException} is thrown. 354 * <p> 355 * <strong>Note: </strong>Using this API requires holding 356 * {@code android.permission.GRANT_RUNTIME_PERMISSIONS} and if the user ID is not the current 357 * user {@code android.permission.INTERACT_ACROSS_USERS_FULL}. 358 * 359 * @param packageName the package to which to grant the permission 360 * @param permissionName the permission name to grant 361 * @param user the user for which to grant the permission 362 * 363 * @see #revokeRuntimePermission(String, String, android.os.UserHandle, String) 364 * 365 * @hide 366 */ 367 @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) 368 //@SystemApi grantRuntimePermission(@onNull String packageName, @NonNull String permissionName, @NonNull UserHandle user)369 public void grantRuntimePermission(@NonNull String packageName, 370 @NonNull String permissionName, @NonNull UserHandle user) { 371 if (DEBUG_TRACE_GRANTS 372 && shouldTraceGrant(packageName, permissionName, user.getIdentifier())) { 373 Log.i(LOG_TAG_TRACE_GRANTS, "App " + mContext.getPackageName() + " is granting " 374 + packageName + " " 375 + permissionName + " for user " + user.getIdentifier(), new RuntimeException()); 376 } 377 try { 378 mPermissionManager.grantRuntimePermission(packageName, permissionName, 379 user.getIdentifier()); 380 } catch (RemoteException e) { 381 throw e.rethrowFromSystemServer(); 382 } 383 } 384 385 /** 386 * Revoke a runtime permission that was previously granted by 387 * {@link #grantRuntimePermission(String, String, android.os.UserHandle)}. The permission must 388 * have been requested by and granted to the application. If the application is not allowed to 389 * hold the permission, a {@link java.lang.SecurityException} is thrown. If the package or 390 * permission is invalid, a {@link java.lang.IllegalArgumentException} is thrown. 391 * <p> 392 * <strong>Note: </strong>Using this API requires holding 393 * {@code android.permission.REVOKE_RUNTIME_PERMISSIONS} and if the user ID is not the current 394 * user {@code android.permission.INTERACT_ACROSS_USERS_FULL}. 395 * 396 * @param packageName the package from which to revoke the permission 397 * @param permName the permission name to revoke 398 * @param user the user for which to revoke the permission 399 * @param reason the reason for the revoke, or {@code null} for unspecified 400 * 401 * @see #grantRuntimePermission(String, String, android.os.UserHandle) 402 * 403 * @hide 404 */ 405 @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) 406 //@SystemApi revokeRuntimePermission(@onNull String packageName, @NonNull String permName, @NonNull UserHandle user, @Nullable String reason)407 public void revokeRuntimePermission(@NonNull String packageName, 408 @NonNull String permName, @NonNull UserHandle user, @Nullable String reason) { 409 if (DEBUG_TRACE_PERMISSION_UPDATES 410 && shouldTraceGrant(packageName, permName, user.getIdentifier())) { 411 Log.i(LOG_TAG, "App " + mContext.getPackageName() + " is revoking " + packageName + " " 412 + permName + " for user " + user.getIdentifier() + " with reason " 413 + reason, new RuntimeException()); 414 } 415 try { 416 mPermissionManager 417 .revokeRuntimePermission(packageName, permName, user.getIdentifier(), reason); 418 } catch (RemoteException e) { 419 throw e.rethrowFromSystemServer(); 420 } 421 } 422 423 /** 424 * Gets the state flags associated with a permission. 425 * 426 * @param packageName the package name for which to get the flags 427 * @param permissionName the permission for which to get the flags 428 * @param user the user for which to get permission flags 429 * @return the permission flags 430 * 431 * @hide 432 */ 433 @PackageManager.PermissionFlags 434 @RequiresPermission(anyOf = { 435 android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, 436 android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, 437 android.Manifest.permission.GET_RUNTIME_PERMISSIONS 438 }) 439 //@SystemApi getPermissionFlags(@onNull String packageName, @NonNull String permissionName, @NonNull UserHandle user)440 public int getPermissionFlags(@NonNull String packageName, @NonNull String permissionName, 441 @NonNull UserHandle user) { 442 try { 443 return mPermissionManager.getPermissionFlags(packageName, permissionName, 444 user.getIdentifier()); 445 } catch (RemoteException e) { 446 throw e.rethrowFromSystemServer(); 447 } 448 } 449 450 /** 451 * Updates the flags associated with a permission by replacing the flags in the specified mask 452 * with the provided flag values. 453 * 454 * @param packageName The package name for which to update the flags 455 * @param permissionName The permission for which to update the flags 456 * @param flagMask The flags which to replace 457 * @param flagValues The flags with which to replace 458 * @param user The user for which to update the permission flags 459 * 460 * @hide 461 */ 462 @RequiresPermission(anyOf = { 463 android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, 464 android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS 465 }) 466 //@SystemApi updatePermissionFlags(@onNull String packageName, @NonNull String permissionName, @PackageManager.PermissionFlags int flagMask, @PackageManager.PermissionFlags int flagValues, @NonNull UserHandle user)467 public void updatePermissionFlags(@NonNull String packageName, @NonNull String permissionName, 468 @PackageManager.PermissionFlags int flagMask, 469 @PackageManager.PermissionFlags int flagValues, @NonNull UserHandle user) { 470 if (DEBUG_TRACE_PERMISSION_UPDATES && shouldTraceGrant(packageName, permissionName, 471 user.getIdentifier())) { 472 Log.i(LOG_TAG, "App " + mContext.getPackageName() + " is updating flags for " 473 + packageName + " " + permissionName + " for user " 474 + user.getIdentifier() + ": " + DebugUtils.flagsToString( 475 PackageManager.class, "FLAG_PERMISSION_", flagMask) + " := " 476 + DebugUtils.flagsToString(PackageManager.class, "FLAG_PERMISSION_", 477 flagValues), new RuntimeException()); 478 } 479 try { 480 final boolean checkAdjustPolicyFlagPermission = 481 mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q; 482 mPermissionManager.updatePermissionFlags(packageName, permissionName, flagMask, 483 flagValues, checkAdjustPolicyFlagPermission, user.getIdentifier()); 484 } catch (RemoteException e) { 485 throw e.rethrowFromSystemServer(); 486 } 487 } 488 489 /** 490 * Gets the restricted permissions that have been allowlisted and the app is allowed to have 491 * them granted in their full form. 492 * <p> 493 * Permissions can be hard restricted which means that the app cannot hold them or soft 494 * restricted where the app can hold the permission but in a weaker form. Whether a permission 495 * is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or 496 * {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission 497 * declaration. Allowlisting a hard restricted permission allows for the to hold that permission 498 * and allowlisting a soft restricted permission allows the app to hold the permission in its 499 * full, unrestricted form. 500 * <p> 501 * There are four allowlists: 502 * <ol> 503 * <li> 504 * One for cases where the system permission policy allowlists a permission. This list 505 * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be 506 * accessed by pre-installed holders of a dedicated permission. 507 * <li> 508 * One for cases where the system allowlists the permission when upgrading from an OS version in 509 * which the permission was not restricted to an OS version in which the permission is 510 * restricted. This list corresponds to the 511 * {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by 512 * pre-installed holders of a dedicated permission or the installer on record. 513 * <li> 514 * One for cases where the installer of the package allowlists a permission. This list 515 * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be 516 * accessed by pre-installed holders of a dedicated permission or the installer on record. 517 * </ol> 518 * 519 * @param packageName the app for which to get allowlisted permissions 520 * @param allowlistFlag the flag to determine which allowlist to query. Only one flag can be 521 * passed. 522 * @return the allowlisted permissions that are on any of the allowlists you query for 523 * @throws SecurityException if you try to access a allowlist that you have no access to 524 * 525 * @see #addAllowlistedRestrictedPermission(String, String, int) 526 * @see #removeAllowlistedRestrictedPermission(String, String, int) 527 * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM 528 * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE 529 * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER 530 * 531 * @hide Pending API 532 */ 533 @NonNull 534 @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS, 535 conditional = true) getAllowlistedRestrictedPermissions(@onNull String packageName, @PackageManager.PermissionWhitelistFlags int allowlistFlag)536 public Set<String> getAllowlistedRestrictedPermissions(@NonNull String packageName, 537 @PackageManager.PermissionWhitelistFlags int allowlistFlag) { 538 try { 539 final List<String> allowlist = mPermissionManager.getAllowlistedRestrictedPermissions( 540 packageName, allowlistFlag, mContext.getUserId()); 541 if (allowlist == null) { 542 return Collections.emptySet(); 543 } 544 return new ArraySet<>(allowlist); 545 } catch (RemoteException e) { 546 throw e.rethrowFromSystemServer(); 547 } 548 } 549 550 /** 551 * Adds a allowlisted restricted permission for an app. 552 * <p> 553 * Permissions can be hard restricted which means that the app cannot hold them or soft 554 * restricted where the app can hold the permission but in a weaker form. Whether a permission 555 * is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or 556 * {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission 557 * declaration. Allowlisting a hard restricted permission allows for the to hold that permission 558 * and allowlisting a soft restricted permission allows the app to hold the permission in its 559 * full, unrestricted form. 560 * <p>There are four allowlists: 561 * <ol> 562 * <li> 563 * One for cases where the system permission policy allowlists a permission. This list 564 * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be 565 * accessed by pre-installed holders of a dedicated permission. 566 * <li> 567 * One for cases where the system allowlists the permission when upgrading from an OS version in 568 * which the permission was not restricted to an OS version in which the permission is 569 * restricted. This list corresponds to the 570 * {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by 571 * pre-installed holders of a dedicated permission or the installer on record. 572 * <li> 573 * One for cases where the installer of the package allowlists a permission. This list 574 * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be 575 * accessed by pre-installed holders of a dedicated permission or the installer on record. 576 * </ol> 577 * <p> 578 * You need to specify the allowlists for which to set the allowlisted permissions which will 579 * clear the previous allowlisted permissions and replace them with the provided ones. 580 * 581 * @param packageName the app for which to get allowlisted permissions 582 * @param permissionName the allowlisted permission to add 583 * @param allowlistFlags the allowlists to which to add. Passing multiple flags updates all 584 * specified allowlists. 585 * @return whether the permission was added to the allowlist 586 * @throws SecurityException if you try to modify a allowlist that you have no access to. 587 * 588 * @see #getAllowlistedRestrictedPermissions(String, int) 589 * @see #removeAllowlistedRestrictedPermission(String, String, int) 590 * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM 591 * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE 592 * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER 593 * 594 * @hide Pending API 595 */ 596 @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS, 597 conditional = true) addAllowlistedRestrictedPermission(@onNull String packageName, @NonNull String permissionName, @PackageManager.PermissionWhitelistFlags int allowlistFlags)598 public boolean addAllowlistedRestrictedPermission(@NonNull String packageName, 599 @NonNull String permissionName, 600 @PackageManager.PermissionWhitelistFlags int allowlistFlags) { 601 try { 602 return mPermissionManager.addAllowlistedRestrictedPermission(packageName, 603 permissionName, allowlistFlags, mContext.getUserId()); 604 } catch (RemoteException e) { 605 throw e.rethrowFromSystemServer(); 606 } 607 } 608 609 /** 610 * Removes a allowlisted restricted permission for an app. 611 * <p> 612 * Permissions can be hard restricted which means that the app cannot hold them or soft 613 * restricted where the app can hold the permission but in a weaker form. Whether a permission 614 * is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or 615 * {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission 616 * declaration. Allowlisting a hard restricted permission allows for the to hold that permission 617 * and allowlisting a soft restricted permission allows the app to hold the permission in its 618 * full, unrestricted form. 619 * <p>There are four allowlists: 620 * <ol> 621 * <li> 622 * One for cases where the system permission policy allowlists a permission. This list 623 * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be 624 * accessed by pre-installed holders of a dedicated permission. 625 * <li> 626 * One for cases where the system allowlists the permission when upgrading from an OS version in 627 * which the permission was not restricted to an OS version in which the permission is 628 * restricted. This list corresponds to the 629 * {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by 630 * pre-installed holders of a dedicated permission or the installer on record. 631 * <li> 632 * One for cases where the installer of the package allowlists a permission. This list 633 * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be 634 * accessed by pre-installed holders of a dedicated permission or the installer on record. 635 * </ol> 636 * <p> 637 * You need to specify the allowlists for which to set the allowlisted permissions which will 638 * clear the previous allowlisted permissions and replace them with the provided ones. 639 * 640 * @param packageName the app for which to get allowlisted permissions 641 * @param permissionName the allowlisted permission to remove 642 * @param allowlistFlags the allowlists from which to remove. Passing multiple flags updates all 643 * specified allowlists. 644 * @return whether the permission was removed from the allowlist 645 * @throws SecurityException if you try to modify a allowlist that you have no access to. 646 * 647 * @see #getAllowlistedRestrictedPermissions(String, int) 648 * @see #addAllowlistedRestrictedPermission(String, String, int) 649 * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM 650 * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE 651 * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER 652 * 653 * @hide Pending API 654 */ 655 @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS, 656 conditional = true) removeAllowlistedRestrictedPermission(@onNull String packageName, @NonNull String permissionName, @PackageManager.PermissionWhitelistFlags int allowlistFlags)657 public boolean removeAllowlistedRestrictedPermission(@NonNull String packageName, 658 @NonNull String permissionName, 659 @PackageManager.PermissionWhitelistFlags int allowlistFlags) { 660 try { 661 return mPermissionManager.removeAllowlistedRestrictedPermission(packageName, 662 permissionName, allowlistFlags, mContext.getUserId()); 663 } catch (RemoteException e) { 664 throw e.rethrowFromSystemServer(); 665 } 666 } 667 668 /** 669 * Checks whether an application is exempted from having its permissions be automatically 670 * revoked when the app is unused for an extended period of time. 671 * <p> 672 * Only the installer on record that installed the given package, or a holder of 673 * {@code WHITELIST_AUTO_REVOKE_PERMISSIONS} is allowed to call this. 674 * 675 * @param packageName the app for which to set exemption 676 * @return whether the app is exempted 677 * @throws SecurityException if you you have no access to this 678 * 679 * @see #setAutoRevokeExempted 680 * 681 * @hide Pending API 682 */ 683 @RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS, 684 conditional = true) isAutoRevokeExempted(@onNull String packageName)685 public boolean isAutoRevokeExempted(@NonNull String packageName) { 686 try { 687 return mPermissionManager.isAutoRevokeExempted(packageName, mContext.getUserId()); 688 } catch (RemoteException e) { 689 throw e.rethrowFromSystemServer(); 690 } 691 } 692 693 /** 694 * Marks an application exempted from having its permissions be automatically revoked when the 695 * app is unused for an extended period of time. 696 * <p> 697 * Only the installer on record that installed the given package is allowed to call this. 698 * <p> 699 * Packages start in exempted state, and it is the installer's responsibility to un-exempt the 700 * packages it installs, unless auto-revoking permissions from that package would cause 701 * breakages beyond having to re-request the permission(s). 702 * 703 * @param packageName the app for which to set exemption 704 * @param exempted whether the app should be exempted 705 * @return whether any change took effect 706 * @throws SecurityException if you you have no access to modify this 707 * 708 * @see #isAutoRevokeExempted 709 * 710 * @hide Pending API 711 */ 712 @RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS, 713 conditional = true) setAutoRevokeExempted(@onNull String packageName, boolean exempted)714 public boolean setAutoRevokeExempted(@NonNull String packageName, boolean exempted) { 715 try { 716 return mPermissionManager.setAutoRevokeExempted(packageName, exempted, 717 mContext.getUserId()); 718 } catch (RemoteException e) { 719 throw e.rethrowFromSystemServer(); 720 } 721 } 722 723 /** 724 * Get whether you should show UI with rationale for requesting a permission. You should do this 725 * only if you do not have the permission and the context in which the permission is requested 726 * does not clearly communicate to the user what would be the benefit from grating this 727 * permission. 728 * 729 * @param permissionName a permission your app wants to request 730 * @return whether you can show permission rationale UI 731 * 732 * @hide 733 */ 734 //@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) shouldShowRequestPermissionRationale(@onNull String permissionName)735 public boolean shouldShowRequestPermissionRationale(@NonNull String permissionName) { 736 try { 737 final String packageName = mContext.getPackageName(); 738 return mPermissionManager.shouldShowRequestPermissionRationale(packageName, 739 permissionName, mContext.getUserId()); 740 } catch (RemoteException e) { 741 throw e.rethrowFromSystemServer(); 742 } 743 } 744 745 /** 746 * Add a listener for permission changes for installed packages. 747 * 748 * @param listener the listener to add 749 * 750 * @hide 751 */ 752 //@SystemApi 753 @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS) addOnPermissionsChangeListener( @onNull PackageManager.OnPermissionsChangedListener listener)754 public void addOnPermissionsChangeListener( 755 @NonNull PackageManager.OnPermissionsChangedListener listener) { 756 synchronized (mPermissionListeners) { 757 if (mPermissionListeners.get(listener) != null) { 758 return; 759 } 760 final OnPermissionsChangeListenerDelegate delegate = 761 new OnPermissionsChangeListenerDelegate(listener, Looper.getMainLooper()); 762 try { 763 mPermissionManager.addOnPermissionsChangeListener(delegate); 764 mPermissionListeners.put(listener, delegate); 765 } catch (RemoteException e) { 766 throw e.rethrowFromSystemServer(); 767 } 768 } 769 } 770 771 /** 772 * Remove a listener for permission changes for installed packages. 773 * 774 * @param listener the listener to remove 775 * 776 * @hide 777 */ 778 //@SystemApi 779 @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS) removeOnPermissionsChangeListener( @onNull PackageManager.OnPermissionsChangedListener listener)780 public void removeOnPermissionsChangeListener( 781 @NonNull PackageManager.OnPermissionsChangedListener listener) { 782 synchronized (mPermissionListeners) { 783 final IOnPermissionsChangeListener delegate = mPermissionListeners.get(listener); 784 if (delegate != null) { 785 try { 786 mPermissionManager.removeOnPermissionsChangeListener(delegate); 787 mPermissionListeners.remove(listener); 788 } catch (RemoteException e) { 789 throw e.rethrowFromSystemServer(); 790 } 791 } 792 } 793 } 794 795 /** 796 * Gets the version of the runtime permission database. 797 * 798 * @return The database version, -1 when this is an upgrade from pre-Q, 0 when this is a fresh 799 * install. 800 * 801 * @hide 802 */ 803 @SystemApi 804 @RequiresPermission(anyOf = { 805 Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, 806 Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS 807 }) getRuntimePermissionsVersion()808 public @IntRange(from = 0) int getRuntimePermissionsVersion() { 809 try { 810 return mPackageManager.getRuntimePermissionsVersion(mContext.getUserId()); 811 } catch (RemoteException e) { 812 throw e.rethrowFromSystemServer(); 813 } 814 } 815 816 /** 817 * Sets the version of the runtime permission database. 818 * 819 * @param version The new version. 820 * 821 * @hide 822 */ 823 @SystemApi 824 @RequiresPermission(anyOf = { 825 Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, 826 Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS 827 }) setRuntimePermissionsVersion(@ntRangefrom = 0) int version)828 public void setRuntimePermissionsVersion(@IntRange(from = 0) int version) { 829 try { 830 mPackageManager.setRuntimePermissionsVersion(version, mContext.getUserId()); 831 } catch (RemoteException e) { 832 throw e.rethrowFromSystemServer(); 833 } 834 } 835 836 /** 837 * Get set of permissions that have been split into more granular or dependent permissions. 838 * 839 * <p>E.g. before {@link android.os.Build.VERSION_CODES#Q} an app that was granted 840 * {@link Manifest.permission#ACCESS_COARSE_LOCATION} could access the location while it was in 841 * foreground and background. On platforms after {@link android.os.Build.VERSION_CODES#Q} 842 * the location permission only grants location access while the app is in foreground. This 843 * would break apps that target before {@link android.os.Build.VERSION_CODES#Q}. Hence whenever 844 * such an old app asks for a location permission (i.e. the 845 * {@link SplitPermissionInfo#getSplitPermission()}), then the 846 * {@link Manifest.permission#ACCESS_BACKGROUND_LOCATION} permission (inside 847 * {@link SplitPermissionInfo#getNewPermissions}) is added. 848 * 849 * <p>Note: Regular apps do not have to worry about this. The platform and permission controller 850 * automatically add the new permissions where needed. 851 * 852 * @return All permissions that are split. 853 */ getSplitPermissions()854 public @NonNull List<SplitPermissionInfo> getSplitPermissions() { 855 if (mSplitPermissionInfos != null) { 856 return mSplitPermissionInfos; 857 } 858 859 List<SplitPermissionInfoParcelable> parcelableList; 860 try { 861 parcelableList = ActivityThread.getPermissionManager().getSplitPermissions(); 862 } catch (RemoteException e) { 863 Slog.e(LOG_TAG, "Error getting split permissions", e); 864 return Collections.emptyList(); 865 } 866 867 mSplitPermissionInfos = splitPermissionInfoListToNonParcelableList(parcelableList); 868 869 return mSplitPermissionInfos; 870 } 871 872 /** 873 * Initialize the PermissionUsageHelper, which will register active app op listeners 874 * 875 * @hide 876 */ initializeUsageHelper()877 public void initializeUsageHelper() { 878 if (mUsageHelper == null) { 879 mUsageHelper = new PermissionUsageHelper(mContext); 880 } 881 } 882 883 /** 884 * Teardown the PermissionUsageHelper, removing listeners 885 * 886 * @hide 887 */ tearDownUsageHelper()888 public void tearDownUsageHelper() { 889 if (mUsageHelper != null) { 890 mUsageHelper.tearDown(); 891 mUsageHelper = null; 892 } 893 } 894 895 /** 896 * @return A list of permission groups currently or recently used by all apps by all users in 897 * the current profile group. 898 * 899 * @hide 900 */ 901 @TestApi 902 @NonNull 903 @RequiresPermission(Manifest.permission.GET_APP_OPS_STATS) getIndicatorAppOpUsageData()904 public List<PermGroupUsage> getIndicatorAppOpUsageData() { 905 return getIndicatorAppOpUsageData(new AudioManager().isMicrophoneMute()); 906 } 907 908 /** 909 * @param micMuted whether to consider the microphone muted when retrieving audio ops 910 * @return A list of permission groups currently or recently used by all apps by all users in 911 * the current profile group. 912 * 913 * @hide 914 */ 915 @TestApi 916 @NonNull 917 @RequiresPermission(Manifest.permission.GET_APP_OPS_STATS) getIndicatorAppOpUsageData(boolean micMuted)918 public List<PermGroupUsage> getIndicatorAppOpUsageData(boolean micMuted) { 919 // Lazily initialize the usage helper 920 initializeUsageHelper(); 921 return mUsageHelper.getOpUsageData(micMuted); 922 } 923 924 /** 925 * Determine if a package should be shown in indicators. Only a select few roles, and the 926 * system app itself, are hidden. These values are updated at most every 15 seconds. 927 * @hide 928 */ shouldShowPackageForIndicatorCached(@onNull Context context, @NonNull String packageName)929 public static boolean shouldShowPackageForIndicatorCached(@NonNull Context context, 930 @NonNull String packageName) { 931 return !getIndicatorExemptedPackages(context).contains(packageName); 932 } 933 934 /** 935 * Get the list of packages that are not shown by the indicators. Only a select few roles, and 936 * the system app itself, are hidden. These values are updated at most every 15 seconds. 937 * @hide 938 */ getIndicatorExemptedPackages(@onNull Context context)939 public static Set<String> getIndicatorExemptedPackages(@NonNull Context context) { 940 updateIndicatorExemptedPackages(context); 941 ArraySet<String> pkgNames = new ArraySet<>(); 942 pkgNames.add(SYSTEM_PKG); 943 for (int i = 0; i < INDICATOR_EXEMPTED_PACKAGES.length; i++) { 944 String exemptedPackage = INDICATOR_EXEMPTED_PACKAGES[i]; 945 if (exemptedPackage != null) { 946 pkgNames.add(exemptedPackage); 947 } 948 } 949 return pkgNames; 950 } 951 952 /** 953 * Update the cached indicator exempted packages 954 * @hide 955 */ updateIndicatorExemptedPackages(@onNull Context context)956 public static void updateIndicatorExemptedPackages(@NonNull Context context) { 957 long now = SystemClock.elapsedRealtime(); 958 if (sLastIndicatorUpdateTime == -1 959 || (now - sLastIndicatorUpdateTime) > EXEMPTED_INDICATOR_ROLE_UPDATE_FREQUENCY_MS) { 960 sLastIndicatorUpdateTime = now; 961 for (int i = 0; i < EXEMPTED_ROLES.length; i++) { 962 INDICATOR_EXEMPTED_PACKAGES[i] = context.getString(EXEMPTED_ROLES[i]); 963 } 964 } 965 } 966 /** 967 * Gets the list of packages that have permissions that specified 968 * {@code requestDontAutoRevokePermissions=true} in their 969 * {@code application} manifest declaration. 970 * 971 * @return the list of packages for current user 972 * @hide 973 */ 974 @SystemApi 975 @NonNull 976 @RequiresPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY) getAutoRevokeExemptionRequestedPackages()977 public Set<String> getAutoRevokeExemptionRequestedPackages() { 978 try { 979 return CollectionUtils.toSet(mPermissionManager.getAutoRevokeExemptionRequestedPackages( 980 mContext.getUser().getIdentifier())); 981 } catch (RemoteException e) { 982 throw e.rethrowFromSystemServer(); 983 } 984 } 985 986 /** 987 * Gets the list of packages that have permissions that specified 988 * {@code autoRevokePermissions=disallowed} in their 989 * {@code application} manifest declaration. 990 * 991 * @return the list of packages for current user 992 * @hide 993 */ 994 @SystemApi 995 @NonNull 996 @RequiresPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY) getAutoRevokeExemptionGrantedPackages()997 public Set<String> getAutoRevokeExemptionGrantedPackages() { 998 try { 999 return CollectionUtils.toSet(mPermissionManager.getAutoRevokeExemptionGrantedPackages( 1000 mContext.getUser().getIdentifier())); 1001 } catch (RemoteException e) { 1002 throw e.rethrowFromSystemServer(); 1003 } 1004 } 1005 splitPermissionInfoListToNonParcelableList( List<SplitPermissionInfoParcelable> parcelableList)1006 private List<SplitPermissionInfo> splitPermissionInfoListToNonParcelableList( 1007 List<SplitPermissionInfoParcelable> parcelableList) { 1008 final int size = parcelableList.size(); 1009 List<SplitPermissionInfo> list = new ArrayList<>(size); 1010 for (int i = 0; i < size; i++) { 1011 list.add(new SplitPermissionInfo(parcelableList.get(i))); 1012 } 1013 return list; 1014 } 1015 1016 /** 1017 * Converts a {@link List} of {@link SplitPermissionInfo} into a List of 1018 * {@link SplitPermissionInfoParcelable} and returns it. 1019 * @hide 1020 */ splitPermissionInfoListToParcelableList( List<SplitPermissionInfo> splitPermissionsList)1021 public static List<SplitPermissionInfoParcelable> splitPermissionInfoListToParcelableList( 1022 List<SplitPermissionInfo> splitPermissionsList) { 1023 final int size = splitPermissionsList.size(); 1024 List<SplitPermissionInfoParcelable> outList = new ArrayList<>(size); 1025 for (int i = 0; i < size; i++) { 1026 SplitPermissionInfo info = splitPermissionsList.get(i); 1027 outList.add(new SplitPermissionInfoParcelable( 1028 info.getSplitPermission(), info.getNewPermissions(), info.getTargetSdk())); 1029 } 1030 return outList; 1031 } 1032 1033 /** 1034 * A permission that was added in a previous API level might have split into several 1035 * permissions. This object describes one such split. 1036 */ 1037 @Immutable 1038 public static final class SplitPermissionInfo { 1039 private @NonNull final SplitPermissionInfoParcelable mSplitPermissionInfoParcelable; 1040 1041 @Override equals(@ullable Object o)1042 public boolean equals(@Nullable Object o) { 1043 if (this == o) return true; 1044 if (o == null || getClass() != o.getClass()) return false; 1045 SplitPermissionInfo that = (SplitPermissionInfo) o; 1046 return mSplitPermissionInfoParcelable.equals(that.mSplitPermissionInfoParcelable); 1047 } 1048 1049 @Override hashCode()1050 public int hashCode() { 1051 return mSplitPermissionInfoParcelable.hashCode(); 1052 } 1053 1054 /** 1055 * Get the permission that is split. 1056 */ getSplitPermission()1057 public @NonNull String getSplitPermission() { 1058 return mSplitPermissionInfoParcelable.getSplitPermission(); 1059 } 1060 1061 /** 1062 * Get the permissions that are added. 1063 */ getNewPermissions()1064 public @NonNull List<String> getNewPermissions() { 1065 return mSplitPermissionInfoParcelable.getNewPermissions(); 1066 } 1067 1068 /** 1069 * Get the target API level when the permission was split. 1070 */ getTargetSdk()1071 public int getTargetSdk() { 1072 return mSplitPermissionInfoParcelable.getTargetSdk(); 1073 } 1074 1075 /** 1076 * Constructs a split permission. 1077 * 1078 * @param splitPerm old permission that will be split 1079 * @param newPerms list of new permissions that {@code rootPerm} will be split into 1080 * @param targetSdk apps targetting SDK versions below this will have {@code rootPerm} 1081 * split into {@code newPerms} 1082 * @hide 1083 */ SplitPermissionInfo(@onNull String splitPerm, @NonNull List<String> newPerms, int targetSdk)1084 public SplitPermissionInfo(@NonNull String splitPerm, @NonNull List<String> newPerms, 1085 int targetSdk) { 1086 this(new SplitPermissionInfoParcelable(splitPerm, newPerms, targetSdk)); 1087 } 1088 SplitPermissionInfo(@onNull SplitPermissionInfoParcelable parcelable)1089 private SplitPermissionInfo(@NonNull SplitPermissionInfoParcelable parcelable) { 1090 mSplitPermissionInfoParcelable = parcelable; 1091 } 1092 } 1093 1094 /** 1095 * Starts a one-time permission session for a given package. A one-time permission session is 1096 * ended if app becomes inactive. Inactivity is defined as the package's uid importance level 1097 * staying > importanceToResetTimer for timeoutMillis milliseconds. If the package's uid 1098 * importance level goes <= importanceToResetTimer then the timer is reset and doesn't start 1099 * until going > importanceToResetTimer. 1100 * <p> 1101 * When this timeoutMillis is reached if the importance level is <= importanceToKeepSessionAlive 1102 * then the session is extended until either the importance goes above 1103 * importanceToKeepSessionAlive which will end the session or <= importanceToResetTimer which 1104 * will continue the session and reset the timer. 1105 * </p> 1106 * <p> 1107 * Importance levels are defined in {@link android.app.ActivityManager.RunningAppProcessInfo}. 1108 * </p> 1109 * <p> 1110 * Once the session ends 1111 * {@link PermissionControllerService#onOneTimePermissionSessionTimeout(String)} is invoked. 1112 * </p> 1113 * <p> 1114 * Note that if there is currently an active session for a package a new one isn't created and 1115 * the existing one isn't changed. 1116 * </p> 1117 * @param packageName The package to start a one-time permission session for 1118 * @param timeoutMillis Number of milliseconds for an app to be in an inactive state 1119 * @param importanceToResetTimer The least important level to uid must be to reset the timer 1120 * @param importanceToKeepSessionAlive The least important level the uid must be to keep the 1121 * session alive 1122 * 1123 * @hide 1124 */ 1125 @SystemApi 1126 @RequiresPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS) startOneTimePermissionSession(@onNull String packageName, long timeoutMillis, @ActivityManager.RunningAppProcessInfo.Importance int importanceToResetTimer, @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive)1127 public void startOneTimePermissionSession(@NonNull String packageName, long timeoutMillis, 1128 @ActivityManager.RunningAppProcessInfo.Importance int importanceToResetTimer, 1129 @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive) { 1130 try { 1131 mPermissionManager.startOneTimePermissionSession(packageName, mContext.getUserId(), 1132 timeoutMillis, importanceToResetTimer, importanceToKeepSessionAlive); 1133 } catch (RemoteException e) { 1134 e.rethrowFromSystemServer(); 1135 } 1136 } 1137 1138 /** 1139 * Stops the one-time permission session for the package. The callback to the end of session is 1140 * not invoked. If there is no one-time session for the package then nothing happens. 1141 * 1142 * @param packageName Package to stop the one-time permission session for 1143 * 1144 * @hide 1145 */ 1146 @SystemApi 1147 @RequiresPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS) stopOneTimePermissionSession(@onNull String packageName)1148 public void stopOneTimePermissionSession(@NonNull String packageName) { 1149 try { 1150 mPermissionManager.stopOneTimePermissionSession(packageName, 1151 mContext.getUserId()); 1152 } catch (RemoteException e) { 1153 e.rethrowFromSystemServer(); 1154 } 1155 } 1156 1157 /** 1158 * Checks whether the package with the given pid/uid can read device identifiers. 1159 * 1160 * @param packageName the name of the package to be checked for identifier access 1161 * @param message the message to be used for logging during identifier access 1162 * verification 1163 * @param callingFeatureId the feature in the package 1164 * @param pid the process id of the package to be checked 1165 * @param uid the uid of the package to be checked 1166 * @return {@link PackageManager#PERMISSION_GRANTED} if the package is allowed identifier 1167 * access, {@link PackageManager#PERMISSION_DENIED} otherwise 1168 * @hide 1169 */ 1170 @SystemApi checkDeviceIdentifierAccess(@ullable String packageName, @Nullable String message, @Nullable String callingFeatureId, int pid, int uid)1171 public int checkDeviceIdentifierAccess(@Nullable String packageName, @Nullable String message, 1172 @Nullable String callingFeatureId, int pid, int uid) { 1173 return mLegacyPermissionManager.checkDeviceIdentifierAccess(packageName, message, 1174 callingFeatureId, pid, uid); 1175 } 1176 1177 /** 1178 * Registers an attribution source with the OS. An app can only register an attribution 1179 * source for itself. Once an attribution source has been registered another app can 1180 * check whether this registration exists and thus trust the payload in the source 1181 * object. This is important for permission checking and specifically for app op blaming 1182 * since a malicious app should not be able to force the OS to blame another app 1183 * that doesn't participate in an attribution chain. 1184 * 1185 * @param source The attribution source to register. 1186 * @return The registered new attribution source. 1187 * 1188 * @see #isRegisteredAttributionSource(AttributionSource) 1189 * 1190 * @hide 1191 */ 1192 @TestApi registerAttributionSource(@onNull AttributionSource source)1193 public @NonNull AttributionSource registerAttributionSource(@NonNull AttributionSource source) { 1194 // We use a shared static token for sources that are not registered since the token's 1195 // only used for process death detection. If we are about to use the source for security 1196 // enforcement we need to replace the binder with a unique one. 1197 final AttributionSource registeredSource = source.withToken(new Binder()); 1198 try { 1199 mPermissionManager.registerAttributionSource(registeredSource.asState()); 1200 } catch (RemoteException e) { 1201 e.rethrowFromSystemServer(); 1202 } 1203 return registeredSource; 1204 } 1205 1206 /** 1207 * Checks whether an attribution source is registered. 1208 * 1209 * @param source The attribution source to check. 1210 * @return Whether this is a registered source. 1211 * 1212 * @see #registerAttributionSource(AttributionSource) 1213 * 1214 * @hide 1215 */ isRegisteredAttributionSource(@onNull AttributionSource source)1216 public boolean isRegisteredAttributionSource(@NonNull AttributionSource source) { 1217 try { 1218 return mPermissionManager.isRegisteredAttributionSource(source.asState()); 1219 } catch (RemoteException e) { 1220 e.rethrowFromSystemServer(); 1221 } 1222 return false; 1223 } 1224 1225 /* @hide */ checkPermissionUncached(@ullable String permission, int pid, int uid)1226 private static int checkPermissionUncached(@Nullable String permission, int pid, int uid) { 1227 final IActivityManager am = ActivityManager.getService(); 1228 if (am == null) { 1229 // Well this is super awkward; we somehow don't have an active ActivityManager 1230 // instance. If we're testing a root or system UID, then they totally have whatever 1231 // permission this is. 1232 final int appId = UserHandle.getAppId(uid); 1233 if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) { 1234 Slog.w(LOG_TAG, "Missing ActivityManager; assuming " + uid + " holds " 1235 + permission); 1236 return PackageManager.PERMISSION_GRANTED; 1237 } 1238 Slog.w(LOG_TAG, "Missing ActivityManager; assuming " + uid + " does not hold " 1239 + permission); 1240 return PackageManager.PERMISSION_DENIED; 1241 } 1242 try { 1243 return am.checkPermission(permission, pid, uid); 1244 } catch (RemoteException e) { 1245 throw e.rethrowFromSystemServer(); 1246 } 1247 } 1248 1249 /** 1250 * Identifies a permission query. 1251 * 1252 * N.B. we include the checking pid for tracking purposes but don't include it in the equality 1253 * comparison: we use only uid for the actual security check, so comparing pid would result 1254 * in spurious misses. 1255 * 1256 * @hide 1257 */ 1258 @Immutable 1259 private static final class PermissionQuery { 1260 final String permission; 1261 final int pid; 1262 final int uid; 1263 PermissionQuery(@ullable String permission, int pid, int uid)1264 PermissionQuery(@Nullable String permission, int pid, int uid) { 1265 this.permission = permission; 1266 this.pid = pid; 1267 this.uid = uid; 1268 } 1269 1270 @Override toString()1271 public String toString() { 1272 return String.format("PermissionQuery(permission=\"%s\", pid=%s, uid=%s)", 1273 permission, pid, uid); 1274 } 1275 1276 @Override hashCode()1277 public int hashCode() { 1278 // N.B. pid doesn't count toward equality and therefore shouldn't count for 1279 // hashing either. 1280 int hash = Objects.hashCode(permission); 1281 hash = hash * 13 + Objects.hashCode(uid); 1282 return hash; 1283 } 1284 1285 @Override equals(@ullable Object rval)1286 public boolean equals(@Nullable Object rval) { 1287 // N.B. pid doesn't count toward equality! 1288 if (rval == null) { 1289 return false; 1290 } 1291 PermissionQuery other; 1292 try { 1293 other = (PermissionQuery) rval; 1294 } catch (ClassCastException ex) { 1295 return false; 1296 } 1297 return uid == other.uid 1298 && Objects.equals(permission, other.permission); 1299 } 1300 } 1301 1302 /** @hide */ 1303 public static final String CACHE_KEY_PACKAGE_INFO = "cache_key.package_info"; 1304 1305 /** @hide */ 1306 private static final PropertyInvalidatedCache<PermissionQuery, Integer> sPermissionCache = 1307 new PropertyInvalidatedCache<PermissionQuery, Integer>( 1308 2048, CACHE_KEY_PACKAGE_INFO, "checkPermission") { 1309 @Override 1310 protected Integer recompute(PermissionQuery query) { 1311 return checkPermissionUncached(query.permission, query.pid, query.uid); 1312 } 1313 }; 1314 1315 /** @hide */ checkPermission(@ullable String permission, int pid, int uid)1316 public static int checkPermission(@Nullable String permission, int pid, int uid) { 1317 return sPermissionCache.query(new PermissionQuery(permission, pid, uid)); 1318 } 1319 1320 /** 1321 * Make checkPermission() above bypass the permission cache in this process. 1322 * 1323 * @hide 1324 */ disablePermissionCache()1325 public static void disablePermissionCache() { 1326 sPermissionCache.disableLocal(); 1327 } 1328 1329 /** 1330 * Like PermissionQuery, but for permission checks based on a package name instead of 1331 * a UID. 1332 */ 1333 @Immutable 1334 private static final class PackageNamePermissionQuery { 1335 final String permName; 1336 final String pkgName; 1337 final int userId; 1338 PackageNamePermissionQuery(@ullable String permName, @Nullable String pkgName, @UserIdInt int userId)1339 PackageNamePermissionQuery(@Nullable String permName, @Nullable String pkgName, 1340 @UserIdInt int userId) { 1341 this.permName = permName; 1342 this.pkgName = pkgName; 1343 this.userId = userId; 1344 } 1345 1346 @Override toString()1347 public String toString() { 1348 return String.format( 1349 "PackageNamePermissionQuery(pkgName=\"%s\", permName=\"%s, userId=%s\")", 1350 pkgName, permName, userId); 1351 } 1352 1353 @Override hashCode()1354 public int hashCode() { 1355 return Objects.hash(permName, pkgName, userId); 1356 } 1357 1358 @Override equals(@ullable Object rval)1359 public boolean equals(@Nullable Object rval) { 1360 if (rval == null) { 1361 return false; 1362 } 1363 PackageNamePermissionQuery other; 1364 try { 1365 other = (PackageNamePermissionQuery) rval; 1366 } catch (ClassCastException ex) { 1367 return false; 1368 } 1369 return Objects.equals(permName, other.permName) 1370 && Objects.equals(pkgName, other.pkgName) 1371 && userId == other.userId; 1372 } 1373 } 1374 1375 /* @hide */ checkPackageNamePermissionUncached( String permName, String pkgName, @UserIdInt int userId)1376 private static int checkPackageNamePermissionUncached( 1377 String permName, String pkgName, @UserIdInt int userId) { 1378 try { 1379 return ActivityThread.getPackageManager().checkPermission( 1380 permName, pkgName, userId); 1381 } catch (RemoteException e) { 1382 throw e.rethrowFromSystemServer(); 1383 } 1384 } 1385 1386 /* @hide */ 1387 private static PropertyInvalidatedCache<PackageNamePermissionQuery, Integer> 1388 sPackageNamePermissionCache = 1389 new PropertyInvalidatedCache<PackageNamePermissionQuery, Integer>( 1390 16, CACHE_KEY_PACKAGE_INFO, "checkPackageNamePermission") { 1391 @Override 1392 protected Integer recompute(PackageNamePermissionQuery query) { 1393 return checkPackageNamePermissionUncached( 1394 query.permName, query.pkgName, query.userId); 1395 } 1396 }; 1397 1398 /** 1399 * Check whether a package has a permission. 1400 * 1401 * @hide 1402 */ checkPackageNamePermission(String permName, String pkgName, @UserIdInt int userId)1403 public static int checkPackageNamePermission(String permName, String pkgName, 1404 @UserIdInt int userId) { 1405 return sPackageNamePermissionCache.query( 1406 new PackageNamePermissionQuery(permName, pkgName, userId)); 1407 } 1408 1409 /** 1410 * Make checkPackageNamePermission() bypass the cache in this process. 1411 * 1412 * @hide 1413 */ disablePackageNamePermissionCache()1414 public static void disablePackageNamePermissionCache() { 1415 sPackageNamePermissionCache.disableLocal(); 1416 } 1417 1418 private final class OnPermissionsChangeListenerDelegate 1419 extends IOnPermissionsChangeListener.Stub implements Handler.Callback{ 1420 private static final int MSG_PERMISSIONS_CHANGED = 1; 1421 1422 private final PackageManager.OnPermissionsChangedListener mListener; 1423 private final Handler mHandler; 1424 OnPermissionsChangeListenerDelegate( PackageManager.OnPermissionsChangedListener listener, Looper looper)1425 public OnPermissionsChangeListenerDelegate( 1426 PackageManager.OnPermissionsChangedListener listener, Looper looper) { 1427 mListener = listener; 1428 mHandler = new Handler(looper, this); 1429 } 1430 1431 @Override onPermissionsChanged(int uid)1432 public void onPermissionsChanged(int uid) { 1433 mHandler.obtainMessage(MSG_PERMISSIONS_CHANGED, uid, 0).sendToTarget(); 1434 } 1435 1436 @Override handleMessage(Message msg)1437 public boolean handleMessage(Message msg) { 1438 switch (msg.what) { 1439 case MSG_PERMISSIONS_CHANGED: { 1440 final int uid = msg.arg1; 1441 mListener.onPermissionsChanged(uid); 1442 return true; 1443 } 1444 default: 1445 return false; 1446 } 1447 } 1448 } 1449 } 1450