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