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