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 com.android.role.controller.model; 18 19 import android.app.AppOpsManager; 20 import android.content.Context; 21 import android.content.pm.ApplicationInfo; 22 import android.content.pm.PackageInfo; 23 import android.content.pm.PackageManager; 24 import android.content.pm.PermissionGroupInfo; 25 import android.content.pm.PermissionInfo; 26 import android.os.Build; 27 import android.os.Process; 28 import android.os.UserHandle; 29 import android.permission.PermissionManager; 30 import android.util.ArrayMap; 31 import android.util.ArraySet; 32 import android.util.Log; 33 34 import androidx.annotation.NonNull; 35 import androidx.annotation.Nullable; 36 37 import com.android.role.controller.util.ArrayUtils; 38 import com.android.role.controller.util.CollectionUtils; 39 import com.android.role.controller.util.PackageUtils; 40 41 import java.util.ArrayList; 42 import java.util.List; 43 import java.util.Set; 44 45 /** 46 * Runtime permissions to be granted or revoke by a {@link Role}. 47 */ 48 public class Permissions { 49 50 private static final String LOG_TAG = Permissions.class.getSimpleName(); 51 52 private static final boolean DEBUG = false; 53 54 private static ArrayMap<String, String> sForegroundToBackgroundPermission; 55 private static ArrayMap<String, List<String>> sBackgroundToForegroundPermissions; 56 private static final Object sForegroundBackgroundPermissionMappingsLock = new Object(); 57 58 private static final ArrayMap<String, Boolean> sRestrictedPermissions = new ArrayMap<>(); 59 60 /** 61 * Filter a list of permissions based on their SDK versions. 62 * 63 * @param permissions the list of permissions 64 * 65 * @return the filtered list of permission names. 66 */ 67 @NonNull filterBySdkVersion(@onNull List<Permission> permissions)68 public static List<String> filterBySdkVersion(@NonNull List<Permission> permissions) { 69 List<String> permissionNames = new ArrayList<>(); 70 int permissionsSize = permissions.size(); 71 for (int i = 0; i < permissionsSize; i++) { 72 Permission permission = permissions.get(i); 73 if (!permission.isAvailable()) { 74 continue; 75 } 76 permissionNames.add(permission.getName()); 77 } 78 return permissionNames; 79 } 80 81 /** 82 * Grant permissions and associated app ops to an application. 83 * 84 * @param packageName the package name of the application to be granted permissions to 85 * @param permissions the list of permissions to be granted 86 * @param overrideDisabledSystemPackage whether to ignore the permissions of a disabled system 87 * package (if this package is an updated system package) 88 * @param overrideUserSetAndFixed whether to override user set and fixed flags on the permission 89 * @param setGrantedByRole whether the permissions will be granted as granted-by-role 90 * @param setGrantedByDefault whether the permissions will be granted as granted-by-default 91 * @param setSystemFixed whether the permissions will be granted as system-fixed 92 * @param context the {@code Context} to retrieve system services 93 * 94 * @return whether any permission or app op changed 95 * 96 * @see com.android.server.pm.permission.DefaultPermissionGrantPolicy#grantRuntimePermissions( 97 * PackageInfo, java.util.Set, boolean, boolean, int) 98 */ grant(@onNull String packageName, @NonNull List<String> permissions, boolean overrideDisabledSystemPackage, boolean overrideUserSetAndFixed, boolean setGrantedByRole, boolean setGrantedByDefault, boolean setSystemFixed, @NonNull Context context)99 public static boolean grant(@NonNull String packageName, @NonNull List<String> permissions, 100 boolean overrideDisabledSystemPackage, boolean overrideUserSetAndFixed, 101 boolean setGrantedByRole, boolean setGrantedByDefault, boolean setSystemFixed, 102 @NonNull Context context) { 103 if (setGrantedByRole == setGrantedByDefault) { 104 throw new IllegalArgumentException("Permission must be either granted by role, or" 105 + " granted by default, but not both"); 106 } 107 108 PackageInfo packageInfo = getPackageInfo(packageName, context); 109 if (packageInfo == null) { 110 return false; 111 } 112 113 if (ArrayUtils.isEmpty(packageInfo.requestedPermissions)) { 114 return false; 115 } 116 117 // Automatically attempt to grant split permissions to older APKs 118 PermissionManager permissionManager = context.getSystemService(PermissionManager.class); 119 List<PermissionManager.SplitPermissionInfo> splitPermissions = 120 permissionManager.getSplitPermissions(); 121 ArraySet<String> permissionsWithoutSplits = new ArraySet<>(permissions); 122 ArraySet<String> permissionsToGrant = new ArraySet<>(permissionsWithoutSplits); 123 int splitPermissionsSize = splitPermissions.size(); 124 for (int i = 0; i < splitPermissionsSize; i++) { 125 PermissionManager.SplitPermissionInfo splitPermission = splitPermissions.get(i); 126 127 if (packageInfo.applicationInfo.targetSdkVersion < splitPermission.getTargetSdk() 128 && permissionsWithoutSplits.contains(splitPermission.getSplitPermission())) { 129 permissionsToGrant.addAll(splitPermission.getNewPermissions()); 130 } 131 } 132 133 CollectionUtils.retainAll(permissionsToGrant, packageInfo.requestedPermissions); 134 if (permissionsToGrant.isEmpty()) { 135 return false; 136 } 137 138 // In some cases, like for the Phone or SMS app, we grant permissions regardless 139 // of if the version on the system image declares the permission as used since 140 // selecting the app as the default for that function the user makes a deliberate 141 // choice to grant this app the permissions needed to function. For all other 142 // apps, (default grants on first boot and user creation) we don't grant default 143 // permissions if the version on the system image does not declare them. 144 if (!overrideDisabledSystemPackage && isUpdatedSystemApp(packageInfo)) { 145 PackageInfo disabledSystemPackageInfo = getFactoryPackageInfo(packageName, context); 146 if (disabledSystemPackageInfo != null) { 147 if (ArrayUtils.isEmpty(disabledSystemPackageInfo.requestedPermissions)) { 148 return false; 149 } 150 CollectionUtils.retainAll(permissionsToGrant, 151 disabledSystemPackageInfo.requestedPermissions); 152 if (permissionsToGrant.isEmpty()) { 153 return false; 154 } 155 } 156 } 157 158 // Sort foreground permissions first so that we can grant a background permission based on 159 // whether any of its foreground permissions are granted. 160 int permissionsToGrantSize = permissionsToGrant.size(); 161 String[] sortedPermissionsToGrant = new String[permissionsToGrantSize]; 162 int foregroundPermissionCount = 0; 163 int nonForegroundPermissionCount = 0; 164 for (int i = 0; i < permissionsToGrantSize; i++) { 165 String permission = permissionsToGrant.valueAt(i); 166 167 if (isForegroundPermission(permission, context)) { 168 sortedPermissionsToGrant[foregroundPermissionCount] = permission; 169 foregroundPermissionCount++; 170 } else { 171 int index = permissionsToGrantSize - 1 - nonForegroundPermissionCount; 172 sortedPermissionsToGrant[index] = permission; 173 nonForegroundPermissionCount++; 174 } 175 } 176 177 boolean permissionOrAppOpChanged = false; 178 179 PackageManager packageManager = context.getPackageManager(); 180 Set<String> whitelistedRestrictedPermissions = new ArraySet<>( 181 packageManager.getWhitelistedRestrictedPermissions(packageName, 182 PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM)); 183 184 int sortedPermissionsToGrantLength = sortedPermissionsToGrant.length; 185 for (int i = 0; i < sortedPermissionsToGrantLength; i++) { 186 String permission = sortedPermissionsToGrant[i]; 187 188 if (isRestrictedPermission(permission, context) 189 && whitelistedRestrictedPermissions.add(permission)) { 190 packageManager.addWhitelistedRestrictedPermission(packageName, permission, 191 PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM); 192 } 193 194 permissionOrAppOpChanged |= grantSingle(packageName, permission, 195 overrideUserSetAndFixed, setGrantedByRole, setGrantedByDefault, setSystemFixed, 196 context); 197 } 198 199 return permissionOrAppOpChanged; 200 } 201 grantSingle(@onNull String packageName, @NonNull String permission, boolean overrideUserSetAndFixed, boolean setGrantedByRole, boolean setGrantedByDefault, boolean setSystemFixed, @NonNull Context context)202 private static boolean grantSingle(@NonNull String packageName, @NonNull String permission, 203 boolean overrideUserSetAndFixed, boolean setGrantedByRole, boolean setGrantedByDefault, 204 boolean setSystemFixed, @NonNull Context context) { 205 boolean wasPermissionOrAppOpGranted = isPermissionAndAppOpGranted(packageName, permission, 206 context); 207 if (isPermissionFixed(packageName, permission, false, overrideUserSetAndFixed, context) 208 && !wasPermissionOrAppOpGranted) { 209 // Stop granting if this permission is fixed to revoked. 210 return false; 211 } 212 213 if (isBackgroundPermission(permission, context)) { 214 List<String> foregroundPermissions = getForegroundPermissions(permission, context); 215 boolean isAnyForegroundPermissionGranted = false; 216 int foregroundPermissionsSize = foregroundPermissions.size(); 217 for (int i = 0; i < foregroundPermissionsSize; i++) { 218 String foregroundPermission = foregroundPermissions.get(i); 219 220 if (isPermissionAndAppOpGranted(packageName, foregroundPermission, context)) { 221 isAnyForegroundPermissionGranted = true; 222 break; 223 } 224 } 225 226 if (!isAnyForegroundPermissionGranted) { 227 // Stop granting if this background permission doesn't have a granted foreground 228 // permission. 229 return false; 230 } 231 } 232 233 boolean permissionOrAppOpChanged = grantPermissionAndAppOp(packageName, permission, 234 context); 235 236 // Update permission flags. 237 int newFlags = 0; 238 if (!wasPermissionOrAppOpGranted && setGrantedByRole) { 239 newFlags |= PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE; 240 } 241 if (setGrantedByDefault) { 242 newFlags |= PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT; 243 } 244 if (setSystemFixed) { 245 newFlags |= PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; 246 } 247 int newMask = newFlags; 248 newMask |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; 249 if (!wasPermissionOrAppOpGranted) { 250 // If we've granted a permission which wasn't granted, it's no longer user set or fixed. 251 newMask |= PackageManager.FLAG_PERMISSION_USER_FIXED 252 | PackageManager.FLAG_PERMISSION_USER_SET; 253 } 254 // If a component gets a permission for being the default handler A and also default handler 255 // B, we grant the weaker grant form. This only applies to default permission grant. 256 if (setGrantedByDefault && !setSystemFixed) { 257 int oldFlags = getPermissionFlags(packageName, permission, context); 258 if ((oldFlags & PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0 259 && (oldFlags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) { 260 if (DEBUG) { 261 Log.i(LOG_TAG, "Granted not fixed " + permission + " to default handler " 262 + packageName); 263 } 264 newMask |= PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; 265 } 266 } 267 268 setPermissionFlags(packageName, permission, newFlags, newMask, context); 269 270 return permissionOrAppOpChanged; 271 } 272 isPermissionAndAppOpGranted(@onNull String packageName, @NonNull String permission, @NonNull Context context)273 private static boolean isPermissionAndAppOpGranted(@NonNull String packageName, 274 @NonNull String permission, @NonNull Context context) { 275 // Check this permission. 276 if (!isPermissionGrantedWithoutCheckingAppOp(packageName, permission, context)) { 277 return false; 278 } 279 280 // Check if the permission is review required. 281 if (isPermissionReviewRequired(packageName, permission, context)) { 282 return false; 283 } 284 285 if (!isBackgroundPermission(permission, context)) { 286 // This permission is not a background permission, check its app op. 287 String appOp = getPermissionAppOp(permission); 288 if (appOp == null) { 289 return true; 290 } 291 Integer appOpMode = getAppOpMode(packageName, appOp, context); 292 if (appOpMode == null) { 293 return false; 294 } 295 if (!isForegroundPermission(permission, context)) { 296 // This permission is an ordinary permission, return true if its app op mode is 297 // MODE_ALLOWED. 298 return appOpMode == AppOpsManager.MODE_ALLOWED; 299 } else { 300 // This permission is a foreground permission, return true if its app op mode is 301 // MODE_FOREGROUND or MODE_ALLOWED. 302 return appOpMode == AppOpsManager.MODE_FOREGROUND 303 || appOpMode == AppOpsManager.MODE_ALLOWED; 304 } 305 } else { 306 // This permission is a background permission, return true if any of its foreground 307 // permissions' app op modes are MODE_ALLOWED. 308 List<String> foregroundPermissions = getForegroundPermissions(permission, context); 309 int foregroundPermissionsSize = foregroundPermissions.size(); 310 for (int i = 0; i < foregroundPermissionsSize; i++) { 311 String foregroundPermission = foregroundPermissions.get(i); 312 313 String foregroundAppOp = getPermissionAppOp(foregroundPermission); 314 if (foregroundAppOp == null) { 315 continue; 316 } 317 Integer foregroundAppOpMode = getAppOpMode(packageName, foregroundAppOp, context); 318 if (foregroundAppOpMode == null) { 319 continue; 320 } 321 if (foregroundAppOpMode == AppOpsManager.MODE_ALLOWED) { 322 return true; 323 } 324 } 325 return false; 326 } 327 } 328 grantPermissionAndAppOp(@onNull String packageName, @NonNull String permission, @NonNull Context context)329 private static boolean grantPermissionAndAppOp(@NonNull String packageName, 330 @NonNull String permission, @NonNull Context context) { 331 // Grant the permission. 332 boolean permissionOrAppOpChanged = grantPermissionWithoutAppOp(packageName, permission, 333 context); 334 335 // Grant the app op. 336 if (!isBackgroundPermission(permission, context)) { 337 String appOp = getPermissionAppOp(permission); 338 if (appOp != null) { 339 int appOpMode; 340 if (!isForegroundPermission(permission, context)) { 341 // This permission is an ordinary permission, set its app op mode to 342 // MODE_ALLOWED. 343 appOpMode = AppOpsManager.MODE_ALLOWED; 344 } else { 345 // This permission is a foreground permission, set its app op mode according to 346 // whether its background permission is granted. 347 String backgroundPermission = getBackgroundPermission(permission, context); 348 if (!isPermissionAndAppOpGranted(packageName, backgroundPermission, context)) { 349 appOpMode = AppOpsManager.MODE_FOREGROUND; 350 } else { 351 appOpMode = AppOpsManager.MODE_ALLOWED; 352 } 353 } 354 permissionOrAppOpChanged |= setAppOpUidMode(packageName, appOp, appOpMode, context); 355 } 356 } else { 357 // This permission is a background permission, set all its foreground permissions' app 358 // op modes to MODE_ALLOWED. 359 List<String> foregroundPermissions = getForegroundPermissions(permission, context); 360 int foregroundPermissionsSize = foregroundPermissions.size(); 361 for (int i = 0; i < foregroundPermissionsSize; i++) { 362 String foregroundPermission = foregroundPermissions.get(i); 363 364 String foregroundAppOp = getPermissionAppOp(foregroundPermission); 365 if (foregroundAppOp == null) { 366 continue; 367 } 368 permissionOrAppOpChanged |= setAppOpUidMode(packageName, foregroundAppOp, 369 AppOpsManager.MODE_ALLOWED, context); 370 } 371 } 372 373 return permissionOrAppOpChanged; 374 } 375 376 /** 377 * Revoke permissions and associated app ops from an application. 378 * 379 * @param packageName the package name of the application to be revoke permissions from 380 * @param permissions the list of permissions to be revoked 381 * @param onlyIfGrantedByRole revoke the permission only if it is granted by role 382 * @param onlyIfGrantedByDefault revoke the permission only if it is granted by default 383 * @param overrideSystemFixed whether system-fixed permissions can be revoked 384 * @param context the {@code Context} to retrieve system services 385 * 386 * @return whether any permission or app op changed 387 * 388 * @see com.android.server.pm.permission.DefaultPermissionGrantPolicy#revokeRuntimePermissions( 389 * String, java.util.Set, boolean, int) 390 */ revoke(@onNull String packageName, @NonNull List<String> permissions, boolean onlyIfGrantedByRole, boolean onlyIfGrantedByDefault, boolean overrideSystemFixed, @NonNull Context context)391 public static boolean revoke(@NonNull String packageName, @NonNull List<String> permissions, 392 boolean onlyIfGrantedByRole, boolean onlyIfGrantedByDefault, 393 boolean overrideSystemFixed, @NonNull Context context) { 394 PackageInfo packageInfo = getPackageInfo(packageName, context); 395 if (packageInfo == null) { 396 return false; 397 } 398 399 if (ArrayUtils.isEmpty(packageInfo.requestedPermissions)) { 400 return false; 401 } 402 403 ArraySet<String> permissionsToRevoke = new ArraySet<>(permissions); 404 CollectionUtils.retainAll(permissionsToRevoke, packageInfo.requestedPermissions); 405 if (permissionsToRevoke.isEmpty()) { 406 return false; 407 } 408 409 // Sort background permissions first so that we can revoke a foreground permission based on 410 // whether its background permission is revoked. 411 int permissionsToRevokeSize = permissionsToRevoke.size(); 412 String[] sortedPermissionsToRevoke = new String[permissionsToRevokeSize]; 413 int backgroundPermissionCount = 0; 414 int nonBackgroundPermissionCount = 0; 415 for (int i = 0; i < permissionsToRevokeSize; i++) { 416 String permission = permissionsToRevoke.valueAt(i); 417 418 if (isBackgroundPermission(permission, context)) { 419 sortedPermissionsToRevoke[backgroundPermissionCount] = permission; 420 backgroundPermissionCount++; 421 } else { 422 int index = permissionsToRevokeSize - 1 - nonBackgroundPermissionCount; 423 sortedPermissionsToRevoke[index] = permission; 424 nonBackgroundPermissionCount++; 425 } 426 } 427 428 PackageManager packageManager = context.getPackageManager(); 429 Set<String> whitelistedRestrictedPermissions = 430 packageManager.getWhitelistedRestrictedPermissions(packageName, 431 PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM 432 | PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE 433 | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER); 434 435 boolean permissionOrAppOpChanged = false; 436 437 int sortedPermissionsToRevokeLength = sortedPermissionsToRevoke.length; 438 for (int i = 0; i < sortedPermissionsToRevokeLength; i++) { 439 String permission = sortedPermissionsToRevoke[i]; 440 441 permissionOrAppOpChanged |= revokeSingle(packageName, permission, onlyIfGrantedByRole, 442 onlyIfGrantedByDefault, overrideSystemFixed, context); 443 444 // Remove from the system whitelist only if not granted by default. 445 if (!isPermissionGrantedByDefault(packageName, permission, context) 446 && whitelistedRestrictedPermissions.remove(permission)) { 447 packageManager.removeWhitelistedRestrictedPermission(packageName, permission, 448 PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM); 449 } 450 } 451 452 return permissionOrAppOpChanged; 453 } 454 revokeSingle(@onNull String packageName, @NonNull String permission, boolean onlyIfGrantedByRole, boolean onlyIfGrantedByDefault, boolean overrideSystemFixed, @NonNull Context context)455 private static boolean revokeSingle(@NonNull String packageName, @NonNull String permission, 456 boolean onlyIfGrantedByRole, boolean onlyIfGrantedByDefault, 457 boolean overrideSystemFixed, @NonNull Context context) { 458 if (onlyIfGrantedByRole == onlyIfGrantedByDefault) { 459 throw new IllegalArgumentException("Permission can be revoked only if either granted by" 460 + " role, or granted by default, but not both"); 461 } 462 463 if (onlyIfGrantedByRole) { 464 if (!isPermissionGrantedByRole(packageName, permission, context)) { 465 return false; 466 } 467 setPermissionFlags(packageName, permission, 0, 468 PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE, context); 469 } 470 471 if (onlyIfGrantedByDefault) { 472 if (!isPermissionGrantedByDefault(packageName, permission, context)) { 473 return false; 474 } 475 // Remove the granted-by-default permission flag. 476 setPermissionFlags(packageName, permission, 0, 477 PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, context); 478 // Note that we do not revoke FLAG_PERMISSION_SYSTEM_FIXED. That bit remains sticky once 479 // set. 480 } 481 482 if (isPermissionFixed(packageName, permission, overrideSystemFixed, false, context) 483 && isPermissionAndAppOpGranted(packageName, permission, context)) { 484 // Stop revoking if this permission is fixed to granted. 485 return false; 486 } 487 488 if (isForegroundPermission(permission, context)) { 489 String backgroundPermission = getBackgroundPermission(permission, context); 490 if (isPermissionAndAppOpGranted(packageName, backgroundPermission, context)) { 491 // Stop revoking if this foreground permission has a granted background permission. 492 return false; 493 } 494 } 495 496 return revokePermissionAndAppOp(packageName, permission, context); 497 } 498 revokePermissionAndAppOp(@onNull String packageName, @NonNull String permission, @NonNull Context context)499 private static boolean revokePermissionAndAppOp(@NonNull String packageName, 500 @NonNull String permission, @NonNull Context context) { 501 boolean permissionOrAppOpChanged = false; 502 503 boolean isRuntimePermissionsSupported = isRuntimePermissionsSupported(packageName, context); 504 if (isRuntimePermissionsSupported) { 505 // Revoke the permission. 506 permissionOrAppOpChanged |= revokePermissionWithoutAppOp(packageName, permission, 507 context); 508 } 509 510 // Revoke the app op. 511 if (!isBackgroundPermission(permission, context)) { 512 String appOp = getPermissionAppOp(permission); 513 if (appOp != null) { 514 // This permission is an ordinary or foreground permission, reset its app op mode to 515 // default. 516 int appOpMode = getDefaultAppOpMode(appOp); 517 boolean appOpModeChanged = setAppOpUidMode(packageName, appOp, appOpMode, context); 518 permissionOrAppOpChanged |= appOpModeChanged; 519 520 if (appOpModeChanged) { 521 if (!isRuntimePermissionsSupported 522 && (appOpMode == AppOpsManager.MODE_FOREGROUND 523 || appOpMode == AppOpsManager.MODE_ALLOWED)) { 524 // We've reset this permission's app op mode to be permissive, so we'll need 525 // the user to review it again. 526 setPermissionFlags(packageName, permission, 527 PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED, 528 PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED, context); 529 } 530 } 531 } 532 } else { 533 // This permission is a background permission, set all its granted foreground 534 // permissions' app op modes to MODE_FOREGROUND. 535 List<String> foregroundPermissions = getForegroundPermissions(permission, context); 536 int foregroundPermissionsSize = foregroundPermissions.size(); 537 for (int i = 0; i < foregroundPermissionsSize; i++) { 538 String foregroundPermission = foregroundPermissions.get(i); 539 540 if (!isPermissionAndAppOpGranted(packageName, foregroundPermission, context)) { 541 continue; 542 } 543 544 String foregroundAppOp = getPermissionAppOp(foregroundPermission); 545 if (foregroundAppOp == null) { 546 continue; 547 } 548 permissionOrAppOpChanged |= setAppOpUidMode(packageName, foregroundAppOp, 549 AppOpsManager.MODE_FOREGROUND, context); 550 } 551 } 552 553 return permissionOrAppOpChanged; 554 } 555 556 @Nullable getPackageInfo(@onNull String packageName, @NonNull Context context)557 private static PackageInfo getPackageInfo(@NonNull String packageName, 558 @NonNull Context context) { 559 return getPackageInfo(packageName, 0, context); 560 } 561 562 @Nullable getFactoryPackageInfo(@onNull String packageName, @NonNull Context context)563 private static PackageInfo getFactoryPackageInfo(@NonNull String packageName, 564 @NonNull Context context) { 565 return getPackageInfo(packageName, PackageManager.MATCH_FACTORY_ONLY, context); 566 } 567 568 @Nullable getPackageInfo(@onNull String packageName, int extraFlags, @NonNull Context context)569 private static PackageInfo getPackageInfo(@NonNull String packageName, int extraFlags, 570 @NonNull Context context) { 571 return PackageUtils.getPackageInfo(packageName, extraFlags 572 // TODO: Why MATCH_UNINSTALLED_PACKAGES? 573 | PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.GET_PERMISSIONS, 574 context); 575 } 576 isUpdatedSystemApp(@onNull PackageInfo packageInfo)577 private static boolean isUpdatedSystemApp(@NonNull PackageInfo packageInfo) { 578 return packageInfo.applicationInfo != null && (packageInfo.applicationInfo.flags 579 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0; 580 } 581 isRuntimePermissionsSupported(@onNull String packageName, @NonNull Context context)582 static boolean isRuntimePermissionsSupported(@NonNull String packageName, 583 @NonNull Context context) { 584 ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName, 585 Process.myUserHandle(), context); 586 if (applicationInfo == null) { 587 return false; 588 } 589 return applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M; 590 } 591 getPermissionFlags(@onNull String packageName, @NonNull String permission, @NonNull Context context)592 private static int getPermissionFlags(@NonNull String packageName, @NonNull String permission, 593 @NonNull Context context) { 594 PackageManager packageManager = context.getPackageManager(); 595 UserHandle user = Process.myUserHandle(); 596 return packageManager.getPermissionFlags(permission, packageName, user); 597 } 598 isPermissionFixed(@onNull String packageName, @NonNull String permission, boolean overrideSystemFixed, boolean overrideUserSetAndFixed, @NonNull Context context)599 private static boolean isPermissionFixed(@NonNull String packageName, 600 @NonNull String permission, boolean overrideSystemFixed, 601 boolean overrideUserSetAndFixed, @NonNull Context context) { 602 int flags = getPermissionFlags(packageName, permission, context); 603 int fixedFlags = PackageManager.FLAG_PERMISSION_POLICY_FIXED; 604 if (!overrideSystemFixed) { 605 fixedFlags |= PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; 606 } 607 if (!overrideUserSetAndFixed) { 608 fixedFlags |= PackageManager.FLAG_PERMISSION_USER_FIXED 609 | PackageManager.FLAG_PERMISSION_USER_SET; 610 } 611 return (flags & fixedFlags) != 0; 612 } 613 isPermissionGrantedByDefault(@onNull String packageName, @NonNull String permission, @NonNull Context context)614 private static boolean isPermissionGrantedByDefault(@NonNull String packageName, 615 @NonNull String permission, @NonNull Context context) { 616 int flags = getPermissionFlags(packageName, permission, context); 617 return (flags & PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0; 618 } 619 isPermissionGrantedByRole(@onNull String packageName, @NonNull String permission, @NonNull Context context)620 static boolean isPermissionGrantedByRole(@NonNull String packageName, 621 @NonNull String permission, @NonNull Context context) { 622 int flags = getPermissionFlags(packageName, permission, context); 623 return (flags & PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE) != 0; 624 } 625 isPermissionReviewRequired(@onNull String packageName, @NonNull String permission, @NonNull Context context)626 private static boolean isPermissionReviewRequired(@NonNull String packageName, 627 @NonNull String permission, @NonNull Context context) { 628 int flags = getPermissionFlags(packageName, permission, context); 629 return (flags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0; 630 } 631 setPermissionFlags(@onNull String packageName, @NonNull String permission, int flags, int mask, @NonNull Context context)632 private static void setPermissionFlags(@NonNull String packageName, @NonNull String permission, 633 int flags, int mask, @NonNull Context context) { 634 PackageManager packageManager = context.getPackageManager(); 635 UserHandle user = Process.myUserHandle(); 636 packageManager.updatePermissionFlags(permission, packageName, mask, flags, user); 637 } 638 setPermissionGrantedByRole(@onNull String packageName, @NonNull String permission, boolean grantedByRole, @NonNull Context context)639 static void setPermissionGrantedByRole(@NonNull String packageName, 640 @NonNull String permission, boolean grantedByRole, @NonNull Context context) { 641 setPermissionFlags(packageName, permission, 642 grantedByRole ? PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE : 0, 643 PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE, context); 644 } 645 646 /** 647 * Most of the time {@link #isPermissionAndAppOpGranted(String, String, Context)} should be used 648 * instead. 649 */ isPermissionGrantedWithoutCheckingAppOp(@onNull String packageName, @NonNull String permission, @NonNull Context context)650 private static boolean isPermissionGrantedWithoutCheckingAppOp(@NonNull String packageName, 651 @NonNull String permission, @NonNull Context context) { 652 PackageManager packageManager = context.getPackageManager(); 653 return packageManager.checkPermission(permission, packageName) 654 == PackageManager.PERMISSION_GRANTED; 655 } 656 grantPermissionWithoutAppOp(@onNull String packageName, @NonNull String permission, @NonNull Context context)657 private static boolean grantPermissionWithoutAppOp(@NonNull String packageName, 658 @NonNull String permission, @NonNull Context context) { 659 if (isPermissionGrantedWithoutCheckingAppOp(packageName, permission, context)) { 660 return false; 661 } 662 PackageManager packageManager = context.getPackageManager(); 663 UserHandle user = Process.myUserHandle(); 664 packageManager.grantRuntimePermission(packageName, permission, user); 665 return true; 666 } 667 revokePermissionWithoutAppOp(@onNull String packageName, @NonNull String permission, @NonNull Context context)668 private static boolean revokePermissionWithoutAppOp(@NonNull String packageName, 669 @NonNull String permission, @NonNull Context context) { 670 if (!isPermissionGrantedWithoutCheckingAppOp(packageName, permission, context)) { 671 return false; 672 } 673 PackageManager packageManager = context.getPackageManager(); 674 UserHandle user = Process.myUserHandle(); 675 packageManager.revokeRuntimePermission(packageName, permission, user); 676 return true; 677 } 678 isForegroundPermission(@onNull String permission, @NonNull Context context)679 private static boolean isForegroundPermission(@NonNull String permission, 680 @NonNull Context context) { 681 ensureForegroundBackgroundPermissionMappings(context); 682 return sForegroundToBackgroundPermission.containsKey(permission); 683 } 684 685 @Nullable getBackgroundPermission(@onNull String foregroundPermission, @NonNull Context context)686 private static String getBackgroundPermission(@NonNull String foregroundPermission, 687 @NonNull Context context) { 688 ensureForegroundBackgroundPermissionMappings(context); 689 return sForegroundToBackgroundPermission.get(foregroundPermission); 690 } 691 isBackgroundPermission(@onNull String permission, @NonNull Context context)692 private static boolean isBackgroundPermission(@NonNull String permission, 693 @NonNull Context context) { 694 ensureForegroundBackgroundPermissionMappings(context); 695 return sBackgroundToForegroundPermissions.containsKey(permission); 696 } 697 698 @Nullable getForegroundPermissions(@onNull String backgroundPermission, @NonNull Context context)699 private static List<String> getForegroundPermissions(@NonNull String backgroundPermission, 700 @NonNull Context context) { 701 ensureForegroundBackgroundPermissionMappings(context); 702 return sBackgroundToForegroundPermissions.get(backgroundPermission); 703 } 704 ensureForegroundBackgroundPermissionMappings(@onNull Context context)705 private static void ensureForegroundBackgroundPermissionMappings(@NonNull Context context) { 706 synchronized (sForegroundBackgroundPermissionMappingsLock) { 707 if (sForegroundToBackgroundPermission == null 708 && sBackgroundToForegroundPermissions == null) { 709 createForegroundBackgroundPermissionMappings(context); 710 } 711 } 712 } 713 isRestrictedPermission(@onNull String permission, @NonNull Context context)714 private static boolean isRestrictedPermission(@NonNull String permission, 715 @NonNull Context context) { 716 synchronized (sRestrictedPermissions) { 717 if (sRestrictedPermissions.containsKey(permission)) { 718 return sRestrictedPermissions.get(permission); 719 } 720 } 721 722 PackageManager packageManager = context.getPackageManager(); 723 PermissionInfo permissionInfo = null; 724 try { 725 permissionInfo = packageManager.getPermissionInfo(permission, 0); 726 } catch (PackageManager.NameNotFoundException e) { 727 Log.e(LOG_TAG, "Cannot get PermissionInfo for permission: " + permission); 728 } 729 730 // Don't expect that to be a transient error, so we can still cache the failed information. 731 boolean isRestrictedPermission = permissionInfo != null 732 && (permissionInfo.flags & (PermissionInfo.FLAG_SOFT_RESTRICTED 733 | PermissionInfo.FLAG_HARD_RESTRICTED)) != 0; 734 735 synchronized (sRestrictedPermissions) { 736 sRestrictedPermissions.put(permission, isRestrictedPermission); 737 } 738 739 return isRestrictedPermission; 740 } 741 createForegroundBackgroundPermissionMappings(@onNull Context context)742 private static void createForegroundBackgroundPermissionMappings(@NonNull Context context) { 743 List<String> permissions = new ArrayList<>(); 744 sBackgroundToForegroundPermissions = new ArrayMap<>(); 745 746 PackageManager packageManager = context.getPackageManager(); 747 List<PermissionGroupInfo> permissionGroupInfos = packageManager.getAllPermissionGroups(0); 748 749 int permissionGroupInfosSize = permissionGroupInfos.size(); 750 for (int permissionGroupInfosIndex = 0; 751 permissionGroupInfosIndex < permissionGroupInfosSize; permissionGroupInfosIndex++) { 752 PermissionGroupInfo permissionGroupInfo = permissionGroupInfos.get( 753 permissionGroupInfosIndex); 754 755 List<PermissionInfo> permissionInfos; 756 try { 757 permissionInfos = packageManager.queryPermissionsByGroup( 758 permissionGroupInfo.name, 0); 759 } catch (PackageManager.NameNotFoundException e) { 760 Log.e(LOG_TAG, "Cannot get permissions for group: " + permissionGroupInfo.name); 761 continue; 762 } 763 764 int permissionInfosSize = permissionInfos.size(); 765 for (int permissionInfosIndex = 0; permissionInfosIndex < permissionInfosSize; 766 permissionInfosIndex++) { 767 PermissionInfo permissionInfo = permissionInfos.get(permissionInfosIndex); 768 769 String permission = permissionInfo.name; 770 permissions.add(permission); 771 772 String backgroundPermission = permissionInfo.backgroundPermission; 773 if (backgroundPermission != null) { 774 List<String> foregroundPermissions = sBackgroundToForegroundPermissions.get( 775 backgroundPermission); 776 if (foregroundPermissions == null) { 777 foregroundPermissions = new ArrayList<>(); 778 sBackgroundToForegroundPermissions.put(backgroundPermission, 779 foregroundPermissions); 780 } 781 foregroundPermissions.add(permission); 782 } 783 } 784 } 785 786 // Remove background permissions declared by foreground permissions but don't actually 787 // exist. 788 sBackgroundToForegroundPermissions.retainAll(permissions); 789 790 // Collect foreground permissions that have existent background permissions. 791 sForegroundToBackgroundPermission = new ArrayMap<>(); 792 793 int backgroundToForegroundPermissionsSize = sBackgroundToForegroundPermissions.size(); 794 for (int backgroundToForegroundPermissionsIndex = 0; 795 backgroundToForegroundPermissionsIndex < backgroundToForegroundPermissionsSize; 796 backgroundToForegroundPermissionsIndex++) { 797 String backgroundPerimssion = sBackgroundToForegroundPermissions.keyAt( 798 backgroundToForegroundPermissionsIndex); 799 List<String> foregroundPermissions = sBackgroundToForegroundPermissions.valueAt( 800 backgroundToForegroundPermissionsIndex); 801 802 int foregroundPermissionsSize = foregroundPermissions.size(); 803 for (int foregroundPermissionsIndex = 0; 804 foregroundPermissionsIndex < foregroundPermissionsSize; 805 foregroundPermissionsIndex++) { 806 String foregroundPermission = foregroundPermissions.get(foregroundPermissionsIndex); 807 808 sForegroundToBackgroundPermission.put(foregroundPermission, backgroundPerimssion); 809 } 810 } 811 } 812 813 @Nullable getPermissionAppOp(@onNull String permission)814 private static String getPermissionAppOp(@NonNull String permission) { 815 return AppOpsManager.permissionToOp(permission); 816 } 817 818 @Nullable getAppOpMode(@onNull String packageName, @NonNull String appOp, @NonNull Context context)819 static Integer getAppOpMode(@NonNull String packageName, @NonNull String appOp, 820 @NonNull Context context) { 821 ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName, 822 Process.myUserHandle(), context); 823 if (applicationInfo == null) { 824 return null; 825 } 826 AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); 827 return appOpsManager.unsafeCheckOpRaw(appOp, applicationInfo.uid, packageName); 828 } 829 getDefaultAppOpMode(@onNull String appOp)830 static int getDefaultAppOpMode(@NonNull String appOp) { 831 return AppOpsManager.opToDefaultMode(appOp); 832 } 833 setAppOpUidMode(@onNull String packageName, @NonNull String appOp, int mode, @NonNull Context context)834 static boolean setAppOpUidMode(@NonNull String packageName, @NonNull String appOp, int mode, 835 @NonNull Context context) { 836 return setAppOpMode(packageName, appOp, mode, true, context); 837 } 838 setAppOpPackageMode(@onNull String packageName, @NonNull String appOp, int mode, @NonNull Context context)839 static boolean setAppOpPackageMode(@NonNull String packageName, @NonNull String appOp, int mode, 840 @NonNull Context context) { 841 return setAppOpMode(packageName, appOp, mode, false, context); 842 } 843 setAppOpMode(@onNull String packageName, @NonNull String appOp, int mode, boolean setUidMode, @NonNull Context context)844 private static boolean setAppOpMode(@NonNull String packageName, @NonNull String appOp, 845 int mode, boolean setUidMode, @NonNull Context context) { 846 Integer currentMode = getAppOpMode(packageName, appOp, context); 847 if (currentMode != null && currentMode == mode) { 848 return false; 849 } 850 ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName, 851 Process.myUserHandle(), context); 852 if (applicationInfo == null) { 853 Log.e(LOG_TAG, "Cannot get ApplicationInfo for package to set app op mode: " 854 + packageName); 855 return false; 856 } 857 AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); 858 if (setUidMode) { 859 appOpsManager.setUidMode(appOp, applicationInfo.uid, mode); 860 } else { 861 appOpsManager.setMode(appOp, applicationInfo.uid, packageName, mode); 862 } 863 return true; 864 } 865 } 866