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