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