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.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 /** @hide */ 241 @IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = { 242 PROTECTION_FLAG_PRIVILEGED, 243 PROTECTION_FLAG_SYSTEM, 244 PROTECTION_FLAG_DEVELOPMENT, 245 PROTECTION_FLAG_APPOP, 246 PROTECTION_FLAG_PRE23, 247 PROTECTION_FLAG_INSTALLER, 248 PROTECTION_FLAG_VERIFIER, 249 PROTECTION_FLAG_PREINSTALLED, 250 PROTECTION_FLAG_SETUP, 251 PROTECTION_FLAG_INSTANT, 252 PROTECTION_FLAG_RUNTIME_ONLY, 253 PROTECTION_FLAG_OEM, 254 PROTECTION_FLAG_VENDOR_PRIVILEGED, 255 PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER, 256 PROTECTION_FLAG_WELLBEING, 257 PROTECTION_FLAG_DOCUMENTER, 258 PROTECTION_FLAG_CONFIGURATOR, 259 PROTECTION_FLAG_INCIDENT_REPORT_APPROVER, 260 PROTECTION_FLAG_APP_PREDICTOR, 261 }) 262 @Retention(RetentionPolicy.SOURCE) 263 public @interface ProtectionFlags {} 264 265 /** 266 * Mask for {@link #protectionLevel}: the basic protection type. 267 * 268 * @deprecated Use #getProtection() instead. 269 */ 270 @Deprecated 271 public static final int PROTECTION_MASK_BASE = 0xf; 272 273 /** 274 * Mask for {@link #protectionLevel}: additional flag bits. 275 * 276 * @deprecated Use #getProtectionFlags() instead. 277 */ 278 @Deprecated 279 public static final int PROTECTION_MASK_FLAGS = 0xfff0; 280 281 /** 282 * The level of access this permission is protecting, as per 283 * {@link android.R.attr#protectionLevel}. Consists of 284 * a base permission type and zero or more flags. Use the following functions 285 * to extract them. 286 * 287 * <pre> 288 * int basePermissionType = permissionInfo.getProtection(); 289 * int permissionFlags = permissionInfo.getProtectionFlags(); 290 * </pre> 291 * 292 * <p></p>Base permission types are {@link #PROTECTION_NORMAL}, 293 * {@link #PROTECTION_DANGEROUS}, {@link #PROTECTION_SIGNATURE} 294 * and the deprecated {@link #PROTECTION_SIGNATURE_OR_SYSTEM}. 295 * Flags are listed under {@link android.R.attr#protectionLevel}. 296 * 297 * @deprecated Use #getProtection() and #getProtectionFlags() instead. 298 */ 299 @Deprecated 300 public int protectionLevel; 301 302 /** 303 * The group this permission is a part of, as per 304 * {@link android.R.attr#permissionGroup}. 305 */ 306 public @Nullable String group; 307 308 /** 309 * Flag for {@link #flags}, corresponding to <code>costsMoney</code> 310 * value of {@link android.R.attr#permissionFlags}. 311 */ 312 public static final int FLAG_COSTS_MONEY = 1<<0; 313 314 /** 315 * Flag for {@link #flags}, corresponding to <code>removed</code> 316 * value of {@link android.R.attr#permissionFlags}. 317 * @hide 318 */ 319 @TestApi 320 @SystemApi 321 public static final int FLAG_REMOVED = 1<<1; 322 323 /** 324 * Flag for {@link #flags}, corresponding to <code>hardRestricted</code> 325 * value of {@link android.R.attr#permissionFlags}. 326 * 327 * <p> This permission is restricted by the platform and it would be 328 * grantable only to apps that meet special criteria per platform 329 * policy. 330 */ 331 public static final int FLAG_HARD_RESTRICTED = 1<<2; 332 333 /** 334 * Flag for {@link #flags}, corresponding to <code>softRestricted</code> 335 * value of {@link android.R.attr#permissionFlags}. 336 * 337 * <p>This permission is restricted by the platform and it would be 338 * grantable in its full form to apps that meet special criteria 339 * per platform policy. Otherwise, a weaker form of the permission 340 * would be granted. The weak grant depends on the permission. 341 */ 342 public static final int FLAG_SOFT_RESTRICTED = 1<<3; 343 344 /** 345 * Flag for {@link #flags}, corresponding to <code>immutablyRestricted</code> 346 * value of {@link android.R.attr#permissionFlags}. 347 * 348 * <p>This permission is restricted immutably which means that its 349 * restriction state may be specified only on the first install of 350 * the app and will stay in this initial whitelist state until 351 * the app is uninstalled. 352 */ 353 public static final int FLAG_IMMUTABLY_RESTRICTED = 1<<4; 354 355 /** 356 * Flag for {@link #flags}, indicating that this permission has been 357 * installed into the system's globally defined permissions. 358 */ 359 public static final int FLAG_INSTALLED = 1<<30; 360 361 /** @hide */ 362 @IntDef(flag = true, prefix = { "FLAG_" }, value = { 363 FLAG_COSTS_MONEY, 364 FLAG_REMOVED, 365 FLAG_HARD_RESTRICTED, 366 FLAG_SOFT_RESTRICTED, 367 FLAG_IMMUTABLY_RESTRICTED, 368 FLAG_INSTALLED 369 }) 370 @Retention(RetentionPolicy.SOURCE) 371 public @interface Flags {} 372 373 /** 374 * Additional flags about this permission as given by 375 * {@link android.R.attr#permissionFlags}. 376 */ 377 public @Flags int flags; 378 379 /** 380 * A string resource identifier (in the package's resources) of this 381 * permission's description. From the "description" attribute or, 382 * if not set, 0. 383 */ 384 public @StringRes int descriptionRes; 385 386 /** 387 * A string resource identifier (in the package's resources) used to request the permissions. 388 * From the "request" attribute or, if not set, 0. 389 * 390 * @hide 391 */ 392 @SystemApi 393 public @StringRes int requestRes; 394 395 /** 396 * Some permissions only grant access while the app is in foreground. Some of these permissions 397 * allow to add background capabilities by adding another permission. 398 * 399 * If this is such a permission, this is the name of the permission adding the background 400 * access. 401 * 402 * From the "backgroundPermission" attribute or, if not set null 403 * 404 * @hide 405 */ 406 @SystemApi 407 @TestApi 408 public final @Nullable String backgroundPermission; 409 410 /** 411 * The description string provided in the AndroidManifest file, if any. You 412 * probably don't want to use this, since it will be null if the description 413 * is in a resource. You probably want 414 * {@link PermissionInfo#loadDescription} instead. 415 */ 416 public @Nullable CharSequence nonLocalizedDescription; 417 418 /** @hide */ fixProtectionLevel(int level)419 public static int fixProtectionLevel(int level) { 420 if (level == PROTECTION_SIGNATURE_OR_SYSTEM) { 421 level = PROTECTION_SIGNATURE | PROTECTION_FLAG_PRIVILEGED; 422 } 423 if ((level & PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0 424 && (level & PROTECTION_FLAG_PRIVILEGED) == 0) { 425 // 'vendorPrivileged' must be 'privileged'. If not, 426 // drop the vendorPrivileged. 427 level = level & ~PROTECTION_FLAG_VENDOR_PRIVILEGED; 428 } 429 return level; 430 } 431 432 /** @hide */ 433 @UnsupportedAppUsage protectionToString(int level)434 public static @NonNull String protectionToString(int level) { 435 String protLevel = "????"; 436 switch (level & PROTECTION_MASK_BASE) { 437 case PermissionInfo.PROTECTION_DANGEROUS: 438 protLevel = "dangerous"; 439 break; 440 case PermissionInfo.PROTECTION_NORMAL: 441 protLevel = "normal"; 442 break; 443 case PermissionInfo.PROTECTION_SIGNATURE: 444 protLevel = "signature"; 445 break; 446 case PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM: 447 protLevel = "signatureOrSystem"; 448 break; 449 } 450 if ((level & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0) { 451 protLevel += "|privileged"; 452 } 453 if ((level & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) { 454 protLevel += "|development"; 455 } 456 if ((level & PermissionInfo.PROTECTION_FLAG_APPOP) != 0) { 457 protLevel += "|appop"; 458 } 459 if ((level & PermissionInfo.PROTECTION_FLAG_PRE23) != 0) { 460 protLevel += "|pre23"; 461 } 462 if ((level & PermissionInfo.PROTECTION_FLAG_INSTALLER) != 0) { 463 protLevel += "|installer"; 464 } 465 if ((level & PermissionInfo.PROTECTION_FLAG_VERIFIER) != 0) { 466 protLevel += "|verifier"; 467 } 468 if ((level & PermissionInfo.PROTECTION_FLAG_PREINSTALLED) != 0) { 469 protLevel += "|preinstalled"; 470 } 471 if ((level & PermissionInfo.PROTECTION_FLAG_SETUP) != 0) { 472 protLevel += "|setup"; 473 } 474 if ((level & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0) { 475 protLevel += "|instant"; 476 } 477 if ((level & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) != 0) { 478 protLevel += "|runtime"; 479 } 480 if ((level & PermissionInfo.PROTECTION_FLAG_OEM) != 0) { 481 protLevel += "|oem"; 482 } 483 if ((level & PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0) { 484 protLevel += "|vendorPrivileged"; 485 } 486 if ((level & PermissionInfo.PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER) != 0) { 487 protLevel += "|textClassifier"; 488 } 489 if ((level & PermissionInfo.PROTECTION_FLAG_WELLBEING) != 0) { 490 protLevel += "|wellbeing"; 491 } 492 if ((level & PermissionInfo.PROTECTION_FLAG_DOCUMENTER) != 0) { 493 protLevel += "|documenter"; 494 } 495 if ((level & PROTECTION_FLAG_CONFIGURATOR) != 0) { 496 protLevel += "|configurator"; 497 } 498 if ((level & PermissionInfo.PROTECTION_FLAG_INCIDENT_REPORT_APPROVER) != 0) { 499 protLevel += "|incidentReportApprover"; 500 } 501 if ((level & PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) != 0) { 502 protLevel += "|appPredictor"; 503 } 504 return protLevel; 505 } 506 507 /** 508 * @hide 509 */ PermissionInfo(@ullable String backgroundPermission)510 public PermissionInfo(@Nullable String backgroundPermission) { 511 this.backgroundPermission = backgroundPermission; 512 } 513 514 /** 515 * @deprecated Should only be created by the system. 516 */ 517 @Deprecated PermissionInfo()518 public PermissionInfo() { 519 this((String) null); 520 } 521 522 /** 523 * @deprecated Should only be created by the system. 524 */ 525 @Deprecated PermissionInfo(@onNull PermissionInfo orig)526 public PermissionInfo(@NonNull PermissionInfo orig) { 527 super(orig); 528 protectionLevel = orig.protectionLevel; 529 flags = orig.flags; 530 group = orig.group; 531 backgroundPermission = orig.backgroundPermission; 532 descriptionRes = orig.descriptionRes; 533 requestRes = orig.requestRes; 534 nonLocalizedDescription = orig.nonLocalizedDescription; 535 } 536 537 /** 538 * Retrieve the textual description of this permission. This 539 * will call back on the given PackageManager to load the description from 540 * the application. 541 * 542 * @param pm A PackageManager from which the label can be loaded; usually 543 * the PackageManager from which you originally retrieved this item. 544 * 545 * @return Returns a CharSequence containing the permission's description. 546 * If there is no description, null is returned. 547 */ loadDescription(@onNull PackageManager pm)548 public @Nullable CharSequence loadDescription(@NonNull PackageManager pm) { 549 if (nonLocalizedDescription != null) { 550 return nonLocalizedDescription; 551 } 552 if (descriptionRes != 0) { 553 CharSequence label = pm.getText(packageName, descriptionRes, null); 554 if (label != null) { 555 return label; 556 } 557 } 558 return null; 559 } 560 561 /** 562 * Return the base permission type. 563 */ 564 @Protection getProtection()565 public int getProtection() { 566 return protectionLevel & PROTECTION_MASK_BASE; 567 } 568 569 /** 570 * Return the additional flags in {@link #protectionLevel}. 571 */ 572 @ProtectionFlags getProtectionFlags()573 public int getProtectionFlags() { 574 return protectionLevel & ~PROTECTION_MASK_BASE; 575 } 576 577 @Override toString()578 public String toString() { 579 return "PermissionInfo{" 580 + Integer.toHexString(System.identityHashCode(this)) 581 + " " + name + "}"; 582 } 583 584 @Override describeContents()585 public int describeContents() { 586 return 0; 587 } 588 589 @Override writeToParcel(Parcel dest, int parcelableFlags)590 public void writeToParcel(Parcel dest, int parcelableFlags) { 591 super.writeToParcel(dest, parcelableFlags); 592 dest.writeInt(protectionLevel); 593 dest.writeInt(flags); 594 dest.writeString(group); 595 dest.writeString(backgroundPermission); 596 dest.writeInt(descriptionRes); 597 dest.writeInt(requestRes); 598 TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags); 599 } 600 601 /** @hide */ calculateFootprint()602 public int calculateFootprint() { 603 int size = name.length(); 604 if (nonLocalizedLabel != null) { 605 size += nonLocalizedLabel.length(); 606 } 607 if (nonLocalizedDescription != null) { 608 size += nonLocalizedDescription.length(); 609 } 610 return size; 611 } 612 613 /** @hide */ isHardRestricted()614 public boolean isHardRestricted() { 615 return (flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0; 616 } 617 618 /** @hide */ isSoftRestricted()619 public boolean isSoftRestricted() { 620 return (flags & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0; 621 } 622 623 /** @hide */ isRestricted()624 public boolean isRestricted() { 625 return isHardRestricted() || isSoftRestricted(); 626 } 627 628 /** @hide */ isAppOp()629 public boolean isAppOp() { 630 return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0; 631 } 632 633 /** @hide */ isRuntime()634 public boolean isRuntime() { 635 return getProtection() == PROTECTION_DANGEROUS; 636 } 637 638 public static final @NonNull Creator<PermissionInfo> CREATOR = 639 new Creator<PermissionInfo>() { 640 @Override 641 public PermissionInfo createFromParcel(Parcel source) { 642 return new PermissionInfo(source); 643 } 644 @Override 645 public PermissionInfo[] newArray(int size) { 646 return new PermissionInfo[size]; 647 } 648 }; 649 PermissionInfo(Parcel source)650 private PermissionInfo(Parcel source) { 651 super(source); 652 protectionLevel = source.readInt(); 653 flags = source.readInt(); 654 group = source.readString(); 655 backgroundPermission = source.readString(); 656 descriptionRes = source.readInt(); 657 requestRes = source.readInt(); 658 nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); 659 } 660 } 661