1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.content.pm; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.StringRes; 23 import android.annotation.SystemApi; 24 import android.annotation.TestApi; 25 import android.compat.annotation.UnsupportedAppUsage; 26 import android.os.Parcel; 27 import android.os.Parcelable; 28 import android.text.TextUtils; 29 30 import java.lang.annotation.Retention; 31 import java.lang.annotation.RetentionPolicy; 32 33 /** 34 * Information you can retrieve about a particular security permission 35 * known to the system. This corresponds to information collected from the 36 * AndroidManifest.xml's <permission> tags. 37 */ 38 public class PermissionInfo extends PackageItemInfo implements Parcelable { 39 /** 40 * A normal application value for {@link #protectionLevel}, corresponding 41 * to the <code>normal</code> value of 42 * {@link android.R.attr#protectionLevel}. 43 */ 44 public static final int PROTECTION_NORMAL = 0; 45 46 /** 47 * Dangerous value for {@link #protectionLevel}, corresponding 48 * to the <code>dangerous</code> value of 49 * {@link android.R.attr#protectionLevel}. 50 */ 51 public static final int PROTECTION_DANGEROUS = 1; 52 53 /** 54 * System-level value for {@link #protectionLevel}, corresponding 55 * to the <code>signature</code> value of 56 * {@link android.R.attr#protectionLevel}. 57 */ 58 public static final int PROTECTION_SIGNATURE = 2; 59 60 /** 61 * @deprecated Use {@link #PROTECTION_SIGNATURE}|{@link #PROTECTION_FLAG_PRIVILEGED} 62 * instead. 63 */ 64 @Deprecated 65 public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3; 66 67 /** @hide */ 68 @IntDef(flag = false, prefix = { "PROTECTION_" }, value = { 69 PROTECTION_NORMAL, 70 PROTECTION_DANGEROUS, 71 PROTECTION_SIGNATURE, 72 PROTECTION_SIGNATURE_OR_SYSTEM, 73 }) 74 @Retention(RetentionPolicy.SOURCE) 75 public @interface Protection {} 76 77 /** 78 * Additional flag for {@link #protectionLevel}, corresponding 79 * to the <code>privileged</code> value of 80 * {@link android.R.attr#protectionLevel}. 81 */ 82 public static final int PROTECTION_FLAG_PRIVILEGED = 0x10; 83 84 /** 85 * @deprecated Old name for {@link #PROTECTION_FLAG_PRIVILEGED}, which 86 * is now very confusing because it only applies to privileged apps, not all 87 * apps on the system image. 88 */ 89 @Deprecated 90 public static final int PROTECTION_FLAG_SYSTEM = 0x10; 91 92 /** 93 * Additional flag for {@link #protectionLevel}, corresponding 94 * to the <code>development</code> value of 95 * {@link android.R.attr#protectionLevel}. 96 */ 97 public static final int PROTECTION_FLAG_DEVELOPMENT = 0x20; 98 99 /** 100 * Additional flag for {@link #protectionLevel}, corresponding 101 * to the <code>appop</code> value of 102 * {@link android.R.attr#protectionLevel}. 103 */ 104 public static final int PROTECTION_FLAG_APPOP = 0x40; 105 106 /** 107 * Additional flag for {@link #protectionLevel}, corresponding 108 * to the <code>pre23</code> value of 109 * {@link android.R.attr#protectionLevel}. 110 */ 111 public static final int PROTECTION_FLAG_PRE23 = 0x80; 112 113 /** 114 * Additional flag for {@link #protectionLevel}, corresponding 115 * to the <code>installer</code> value of 116 * {@link android.R.attr#protectionLevel}. 117 */ 118 public static final int PROTECTION_FLAG_INSTALLER = 0x100; 119 120 /** 121 * Additional flag for {@link #protectionLevel}, corresponding 122 * to the <code>verifier</code> value of 123 * {@link android.R.attr#protectionLevel}. 124 */ 125 public static final int PROTECTION_FLAG_VERIFIER = 0x200; 126 127 /** 128 * Additional flag for {@link #protectionLevel}, corresponding 129 * to the <code>preinstalled</code> value of 130 * {@link android.R.attr#protectionLevel}. 131 */ 132 public static final int PROTECTION_FLAG_PREINSTALLED = 0x400; 133 134 /** 135 * Additional flag for {@link #protectionLevel}, corresponding 136 * to the <code>setup</code> value of 137 * {@link android.R.attr#protectionLevel}. 138 */ 139 public static final int PROTECTION_FLAG_SETUP = 0x800; 140 141 /** 142 * Additional flag for {@link #protectionLevel}, corresponding 143 * to the <code>instant</code> value of 144 * {@link android.R.attr#protectionLevel}. 145 */ 146 public static final int PROTECTION_FLAG_INSTANT = 0x1000; 147 148 /** 149 * Additional flag for {@link #protectionLevel}, corresponding 150 * to the <code>runtime</code> value of 151 * {@link android.R.attr#protectionLevel}. 152 */ 153 public static final int PROTECTION_FLAG_RUNTIME_ONLY = 0x2000; 154 155 /** 156 * Additional flag for {@link #protectionLevel}, corresponding 157 * to the <code>oem</code> value of 158 * {@link android.R.attr#protectionLevel}. 159 * 160 * @hide 161 */ 162 @SystemApi 163 @TestApi 164 public static final int PROTECTION_FLAG_OEM = 0x4000; 165 166 /** 167 * Additional flag for {${link #protectionLevel}, corresponding 168 * to the <code>vendorPrivileged</code> value of 169 * {@link android.R.attr#protectionLevel}. 170 * 171 * @hide 172 */ 173 @TestApi 174 public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 0x8000; 175 176 /** 177 * Additional flag for {@link #protectionLevel}, corresponding 178 * to the <code>text_classifier</code> value of 179 * {@link android.R.attr#protectionLevel}. 180 * 181 * @hide 182 */ 183 @SystemApi 184 @TestApi 185 public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 0x10000; 186 187 /** 188 * Additional flag for {${link #protectionLevel}, corresponding 189 * to the <code>wellbeing</code> value of 190 * {@link android.R.attr#protectionLevel}. 191 * 192 * @hide 193 */ 194 @SystemApi 195 @TestApi 196 public static final int PROTECTION_FLAG_WELLBEING = 0x20000; 197 198 /** 199 * Additional flag for {@link #protectionLevel}, corresponding to the 200 * {@code documenter} value of {@link android.R.attr#protectionLevel}. 201 * 202 * @hide 203 */ 204 @SystemApi 205 @TestApi 206 public static final int PROTECTION_FLAG_DOCUMENTER = 0x40000; 207 208 /** 209 * Additional flag for {@link #protectionLevel}, corresponding to the 210 * {@code configurator} value of {@link android.R.attr#protectionLevel}. 211 * 212 * @hide 213 */ 214 @SystemApi 215 @TestApi 216 public static final int PROTECTION_FLAG_CONFIGURATOR = 0x80000; 217 218 /** 219 * Additional flag for {${link #protectionLevel}, corresponding 220 * to the <code>incident_report_approver</code> value of 221 * {@link android.R.attr#protectionLevel}. 222 * 223 * @hide 224 */ 225 @SystemApi 226 @TestApi 227 public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 0x100000; 228 229 /** 230 * Additional flag for {@link #protectionLevel}, corresponding 231 * to the <code>app_predictor</code> value of 232 * {@link android.R.attr#protectionLevel}. 233 * 234 * @hide 235 */ 236 @SystemApi 237 @TestApi 238 public static final int PROTECTION_FLAG_APP_PREDICTOR = 0x200000; 239 240 /** 241 * Additional flag for {@link #protectionLevel}, corresponding 242 * to the <code>telephony</code> value of 243 * {@link android.R.attr#protectionLevel}. 244 * 245 * @hide 246 */ 247 @SystemApi 248 @TestApi 249 public static final int PROTECTION_FLAG_TELEPHONY = 0x400000; 250 251 /** @hide */ 252 @IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = { 253 PROTECTION_FLAG_PRIVILEGED, 254 PROTECTION_FLAG_SYSTEM, 255 PROTECTION_FLAG_DEVELOPMENT, 256 PROTECTION_FLAG_APPOP, 257 PROTECTION_FLAG_PRE23, 258 PROTECTION_FLAG_INSTALLER, 259 PROTECTION_FLAG_VERIFIER, 260 PROTECTION_FLAG_PREINSTALLED, 261 PROTECTION_FLAG_SETUP, 262 PROTECTION_FLAG_INSTANT, 263 PROTECTION_FLAG_RUNTIME_ONLY, 264 PROTECTION_FLAG_OEM, 265 PROTECTION_FLAG_VENDOR_PRIVILEGED, 266 PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER, 267 PROTECTION_FLAG_WELLBEING, 268 PROTECTION_FLAG_DOCUMENTER, 269 PROTECTION_FLAG_CONFIGURATOR, 270 PROTECTION_FLAG_INCIDENT_REPORT_APPROVER, 271 PROTECTION_FLAG_APP_PREDICTOR, 272 PROTECTION_FLAG_TELEPHONY, 273 }) 274 @Retention(RetentionPolicy.SOURCE) 275 public @interface ProtectionFlags {} 276 277 /** 278 * Mask for {@link #protectionLevel}: the basic protection type. 279 * 280 * @deprecated Use #getProtection() instead. 281 */ 282 @Deprecated 283 public static final int PROTECTION_MASK_BASE = 0xf; 284 285 /** 286 * Mask for {@link #protectionLevel}: additional flag bits. 287 * 288 * @deprecated Use #getProtectionFlags() instead. 289 */ 290 @Deprecated 291 public static final int PROTECTION_MASK_FLAGS = 0xfff0; 292 293 /** 294 * The level of access this permission is protecting, as per 295 * {@link android.R.attr#protectionLevel}. Consists of 296 * a base permission type and zero or more flags. Use the following functions 297 * to extract them. 298 * 299 * <pre> 300 * int basePermissionType = permissionInfo.getProtection(); 301 * int permissionFlags = permissionInfo.getProtectionFlags(); 302 * </pre> 303 * 304 * <p></p>Base permission types are {@link #PROTECTION_NORMAL}, 305 * {@link #PROTECTION_DANGEROUS}, {@link #PROTECTION_SIGNATURE} 306 * and the deprecated {@link #PROTECTION_SIGNATURE_OR_SYSTEM}. 307 * Flags are listed under {@link android.R.attr#protectionLevel}. 308 * 309 * @deprecated Use #getProtection() and #getProtectionFlags() instead. 310 */ 311 @Deprecated 312 public int protectionLevel; 313 314 /** 315 * The group this permission is a part of, as per 316 * {@link android.R.attr#permissionGroup}. 317 */ 318 public @Nullable String group; 319 320 /** 321 * Flag for {@link #flags}, corresponding to <code>costsMoney</code> 322 * value of {@link android.R.attr#permissionFlags}. 323 */ 324 public static final int FLAG_COSTS_MONEY = 1<<0; 325 326 /** 327 * Flag for {@link #flags}, corresponding to <code>removed</code> 328 * value of {@link android.R.attr#permissionFlags}. 329 * @hide 330 */ 331 @TestApi 332 @SystemApi 333 public static final int FLAG_REMOVED = 1<<1; 334 335 /** 336 * Flag for {@link #flags}, corresponding to <code>hardRestricted</code> 337 * value of {@link android.R.attr#permissionFlags}. 338 * 339 * <p> This permission is restricted by the platform and it would be 340 * grantable only to apps that meet special criteria per platform 341 * policy. 342 */ 343 public static final int FLAG_HARD_RESTRICTED = 1<<2; 344 345 /** 346 * Flag for {@link #flags}, corresponding to <code>softRestricted</code> 347 * value of {@link android.R.attr#permissionFlags}. 348 * 349 * <p>This permission is restricted by the platform and it would be 350 * grantable in its full form to apps that meet special criteria 351 * per platform policy. Otherwise, a weaker form of the permission 352 * would be granted. The weak grant depends on the permission. 353 */ 354 public static final int FLAG_SOFT_RESTRICTED = 1<<3; 355 356 /** 357 * Flag for {@link #flags}, corresponding to <code>immutablyRestricted</code> 358 * value of {@link android.R.attr#permissionFlags}. 359 * 360 * <p>This permission is restricted immutably which means that its 361 * restriction state may be specified only on the first install of 362 * the app and will stay in this initial whitelist state until 363 * the app is uninstalled. 364 */ 365 public static final int FLAG_IMMUTABLY_RESTRICTED = 1<<4; 366 367 /** 368 * Flag for {@link #flags}, indicating that this permission has been 369 * installed into the system's globally defined permissions. 370 */ 371 public static final int FLAG_INSTALLED = 1<<30; 372 373 /** @hide */ 374 @IntDef(flag = true, prefix = { "FLAG_" }, value = { 375 FLAG_COSTS_MONEY, 376 FLAG_REMOVED, 377 FLAG_HARD_RESTRICTED, 378 FLAG_SOFT_RESTRICTED, 379 FLAG_IMMUTABLY_RESTRICTED, 380 FLAG_INSTALLED 381 }) 382 @Retention(RetentionPolicy.SOURCE) 383 public @interface Flags {} 384 385 /** 386 * Additional flags about this permission as given by 387 * {@link android.R.attr#permissionFlags}. 388 */ 389 public @Flags int flags; 390 391 /** 392 * A string resource identifier (in the package's resources) of this 393 * permission's description. From the "description" attribute or, 394 * if not set, 0. 395 */ 396 public @StringRes int descriptionRes; 397 398 /** 399 * A string resource identifier (in the package's resources) used to request the permissions. 400 * From the "request" attribute or, if not set, 0. 401 * 402 * @hide 403 */ 404 @SystemApi 405 public @StringRes int requestRes; 406 407 /** 408 * Some permissions only grant access while the app is in foreground. Some of these permissions 409 * allow to add background capabilities by adding another permission. 410 * 411 * If this is such a permission, this is the name of the permission adding the background 412 * access. 413 * 414 * From the "backgroundPermission" attribute or, if not set null 415 * 416 * @hide 417 */ 418 @SystemApi 419 @TestApi 420 public final @Nullable String backgroundPermission; 421 422 /** 423 * The description string provided in the AndroidManifest file, if any. You 424 * probably don't want to use this, since it will be null if the description 425 * is in a resource. You probably want 426 * {@link PermissionInfo#loadDescription} instead. 427 */ 428 public @Nullable CharSequence nonLocalizedDescription; 429 430 /** @hide */ fixProtectionLevel(int level)431 public static int fixProtectionLevel(int level) { 432 if (level == PROTECTION_SIGNATURE_OR_SYSTEM) { 433 level = PROTECTION_SIGNATURE | PROTECTION_FLAG_PRIVILEGED; 434 } 435 if ((level & PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0 436 && (level & PROTECTION_FLAG_PRIVILEGED) == 0) { 437 // 'vendorPrivileged' must be 'privileged'. If not, 438 // drop the vendorPrivileged. 439 level = level & ~PROTECTION_FLAG_VENDOR_PRIVILEGED; 440 } 441 return level; 442 } 443 444 /** @hide */ 445 @UnsupportedAppUsage protectionToString(int level)446 public static @NonNull String protectionToString(int level) { 447 String protLevel = "????"; 448 switch (level & PROTECTION_MASK_BASE) { 449 case PermissionInfo.PROTECTION_DANGEROUS: 450 protLevel = "dangerous"; 451 break; 452 case PermissionInfo.PROTECTION_NORMAL: 453 protLevel = "normal"; 454 break; 455 case PermissionInfo.PROTECTION_SIGNATURE: 456 protLevel = "signature"; 457 break; 458 case PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM: 459 protLevel = "signatureOrSystem"; 460 break; 461 } 462 if ((level & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0) { 463 protLevel += "|privileged"; 464 } 465 if ((level & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) { 466 protLevel += "|development"; 467 } 468 if ((level & PermissionInfo.PROTECTION_FLAG_APPOP) != 0) { 469 protLevel += "|appop"; 470 } 471 if ((level & PermissionInfo.PROTECTION_FLAG_PRE23) != 0) { 472 protLevel += "|pre23"; 473 } 474 if ((level & PermissionInfo.PROTECTION_FLAG_INSTALLER) != 0) { 475 protLevel += "|installer"; 476 } 477 if ((level & PermissionInfo.PROTECTION_FLAG_VERIFIER) != 0) { 478 protLevel += "|verifier"; 479 } 480 if ((level & PermissionInfo.PROTECTION_FLAG_PREINSTALLED) != 0) { 481 protLevel += "|preinstalled"; 482 } 483 if ((level & PermissionInfo.PROTECTION_FLAG_SETUP) != 0) { 484 protLevel += "|setup"; 485 } 486 if ((level & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0) { 487 protLevel += "|instant"; 488 } 489 if ((level & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) != 0) { 490 protLevel += "|runtime"; 491 } 492 if ((level & PermissionInfo.PROTECTION_FLAG_OEM) != 0) { 493 protLevel += "|oem"; 494 } 495 if ((level & PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0) { 496 protLevel += "|vendorPrivileged"; 497 } 498 if ((level & PermissionInfo.PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER) != 0) { 499 protLevel += "|textClassifier"; 500 } 501 if ((level & PermissionInfo.PROTECTION_FLAG_WELLBEING) != 0) { 502 protLevel += "|wellbeing"; 503 } 504 if ((level & PermissionInfo.PROTECTION_FLAG_DOCUMENTER) != 0) { 505 protLevel += "|documenter"; 506 } 507 if ((level & PROTECTION_FLAG_CONFIGURATOR) != 0) { 508 protLevel += "|configurator"; 509 } 510 if ((level & PermissionInfo.PROTECTION_FLAG_INCIDENT_REPORT_APPROVER) != 0) { 511 protLevel += "|incidentReportApprover"; 512 } 513 if ((level & PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) != 0) { 514 protLevel += "|appPredictor"; 515 } 516 if ((level & PermissionInfo.PROTECTION_FLAG_TELEPHONY) != 0) { 517 protLevel += "|telephony"; 518 } 519 return protLevel; 520 } 521 522 /** 523 * @hide 524 */ PermissionInfo(@ullable String backgroundPermission)525 public PermissionInfo(@Nullable String backgroundPermission) { 526 this.backgroundPermission = backgroundPermission; 527 } 528 529 /** 530 * @deprecated Should only be created by the system. 531 */ 532 @Deprecated PermissionInfo()533 public PermissionInfo() { 534 this((String) null); 535 } 536 537 /** 538 * @deprecated Should only be created by the system. 539 */ 540 @Deprecated PermissionInfo(@onNull PermissionInfo orig)541 public PermissionInfo(@NonNull PermissionInfo orig) { 542 super(orig); 543 protectionLevel = orig.protectionLevel; 544 flags = orig.flags; 545 group = orig.group; 546 backgroundPermission = orig.backgroundPermission; 547 descriptionRes = orig.descriptionRes; 548 requestRes = orig.requestRes; 549 nonLocalizedDescription = orig.nonLocalizedDescription; 550 } 551 552 /** 553 * Retrieve the textual description of this permission. This 554 * will call back on the given PackageManager to load the description from 555 * the application. 556 * 557 * @param pm A PackageManager from which the label can be loaded; usually 558 * the PackageManager from which you originally retrieved this item. 559 * 560 * @return Returns a CharSequence containing the permission's description. 561 * If there is no description, null is returned. 562 */ loadDescription(@onNull PackageManager pm)563 public @Nullable CharSequence loadDescription(@NonNull PackageManager pm) { 564 if (nonLocalizedDescription != null) { 565 return nonLocalizedDescription; 566 } 567 if (descriptionRes != 0) { 568 CharSequence label = pm.getText(packageName, descriptionRes, null); 569 if (label != null) { 570 return label; 571 } 572 } 573 return null; 574 } 575 576 /** 577 * Return the base permission type. 578 */ 579 @Protection getProtection()580 public int getProtection() { 581 return protectionLevel & PROTECTION_MASK_BASE; 582 } 583 584 /** 585 * Return the additional flags in {@link #protectionLevel}. 586 */ 587 @ProtectionFlags getProtectionFlags()588 public int getProtectionFlags() { 589 return protectionLevel & ~PROTECTION_MASK_BASE; 590 } 591 592 @Override toString()593 public String toString() { 594 return "PermissionInfo{" 595 + Integer.toHexString(System.identityHashCode(this)) 596 + " " + name + "}"; 597 } 598 599 @Override describeContents()600 public int describeContents() { 601 return 0; 602 } 603 604 @Override writeToParcel(Parcel dest, int parcelableFlags)605 public void writeToParcel(Parcel dest, int parcelableFlags) { 606 super.writeToParcel(dest, parcelableFlags); 607 dest.writeInt(protectionLevel); 608 dest.writeInt(flags); 609 dest.writeString(group); 610 dest.writeString(backgroundPermission); 611 dest.writeInt(descriptionRes); 612 dest.writeInt(requestRes); 613 TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags); 614 } 615 616 /** @hide */ calculateFootprint()617 public int calculateFootprint() { 618 int size = name.length(); 619 if (nonLocalizedLabel != null) { 620 size += nonLocalizedLabel.length(); 621 } 622 if (nonLocalizedDescription != null) { 623 size += nonLocalizedDescription.length(); 624 } 625 return size; 626 } 627 628 /** @hide */ isHardRestricted()629 public boolean isHardRestricted() { 630 return (flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0; 631 } 632 633 /** @hide */ isSoftRestricted()634 public boolean isSoftRestricted() { 635 return (flags & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0; 636 } 637 638 /** @hide */ isRestricted()639 public boolean isRestricted() { 640 return isHardRestricted() || isSoftRestricted(); 641 } 642 643 /** @hide */ isAppOp()644 public boolean isAppOp() { 645 return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0; 646 } 647 648 /** @hide */ isRuntime()649 public boolean isRuntime() { 650 return getProtection() == PROTECTION_DANGEROUS; 651 } 652 653 public static final @NonNull Creator<PermissionInfo> CREATOR = 654 new Creator<PermissionInfo>() { 655 @Override 656 public PermissionInfo createFromParcel(Parcel source) { 657 return new PermissionInfo(source); 658 } 659 @Override 660 public PermissionInfo[] newArray(int size) { 661 return new PermissionInfo[size]; 662 } 663 }; 664 PermissionInfo(Parcel source)665 private PermissionInfo(Parcel source) { 666 super(source); 667 protectionLevel = source.readInt(); 668 flags = source.readInt(); 669 group = source.readString(); 670 backgroundPermission = source.readString(); 671 descriptionRes = source.readInt(); 672 requestRes = source.readInt(); 673 nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); 674 } 675 } 676