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