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