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