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