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.SystemApi;
21 import android.annotation.TestApi;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.text.TextUtils;
25 
26 import java.lang.annotation.Retention;
27 import java.lang.annotation.RetentionPolicy;
28 
29 /**
30  * Information you can retrieve about a particular security permission
31  * known to the system.  This corresponds to information collected from the
32  * AndroidManifest.xml's <permission> tags.
33  */
34 public class PermissionInfo extends PackageItemInfo implements Parcelable {
35     /**
36      * A normal application value for {@link #protectionLevel}, corresponding
37      * to the <code>normal</code> value of
38      * {@link android.R.attr#protectionLevel}.
39      */
40     public static final int PROTECTION_NORMAL = 0;
41 
42     /**
43      * Dangerous value for {@link #protectionLevel}, corresponding
44      * to the <code>dangerous</code> value of
45      * {@link android.R.attr#protectionLevel}.
46      */
47     public static final int PROTECTION_DANGEROUS = 1;
48 
49     /**
50      * System-level value for {@link #protectionLevel}, corresponding
51      * to the <code>signature</code> value of
52      * {@link android.R.attr#protectionLevel}.
53      */
54     public static final int PROTECTION_SIGNATURE = 2;
55 
56     /**
57      * @deprecated Use {@link #PROTECTION_SIGNATURE}|{@link #PROTECTION_FLAG_PRIVILEGED}
58      * instead.
59      */
60     @Deprecated
61     public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3;
62 
63     /** @hide */
64     @IntDef(flag = false, prefix = { "PROTECTION_" }, value = {
65             PROTECTION_NORMAL,
66             PROTECTION_DANGEROUS,
67             PROTECTION_SIGNATURE,
68             PROTECTION_SIGNATURE_OR_SYSTEM,
69     })
70     @Retention(RetentionPolicy.SOURCE)
71     public @interface Protection {}
72 
73     /**
74      * Additional flag for {@link #protectionLevel}, corresponding
75      * to the <code>privileged</code> value of
76      * {@link android.R.attr#protectionLevel}.
77      */
78     public static final int PROTECTION_FLAG_PRIVILEGED = 0x10;
79 
80     /**
81      * @deprecated Old name for {@link #PROTECTION_FLAG_PRIVILEGED}, which
82      * is now very confusing because it only applies to privileged apps, not all
83      * apps on the system image.
84      */
85     @Deprecated
86     public static final int PROTECTION_FLAG_SYSTEM = 0x10;
87 
88     /**
89      * Additional flag for {@link #protectionLevel}, corresponding
90      * to the <code>development</code> value of
91      * {@link android.R.attr#protectionLevel}.
92      */
93     public static final int PROTECTION_FLAG_DEVELOPMENT = 0x20;
94 
95     /**
96      * Additional flag for {@link #protectionLevel}, corresponding
97      * to the <code>appop</code> value of
98      * {@link android.R.attr#protectionLevel}.
99      */
100     public static final int PROTECTION_FLAG_APPOP = 0x40;
101 
102     /**
103      * Additional flag for {@link #protectionLevel}, corresponding
104      * to the <code>pre23</code> value of
105      * {@link android.R.attr#protectionLevel}.
106      */
107     public static final int PROTECTION_FLAG_PRE23 = 0x80;
108 
109     /**
110      * Additional flag for {@link #protectionLevel}, corresponding
111      * to the <code>installer</code> value of
112      * {@link android.R.attr#protectionLevel}.
113      */
114     public static final int PROTECTION_FLAG_INSTALLER = 0x100;
115 
116     /**
117      * Additional flag for {@link #protectionLevel}, corresponding
118      * to the <code>verifier</code> value of
119      * {@link android.R.attr#protectionLevel}.
120      */
121     public static final int PROTECTION_FLAG_VERIFIER = 0x200;
122 
123     /**
124      * Additional flag for {@link #protectionLevel}, corresponding
125      * to the <code>preinstalled</code> value of
126      * {@link android.R.attr#protectionLevel}.
127      */
128     public static final int PROTECTION_FLAG_PREINSTALLED = 0x400;
129 
130     /**
131      * Additional flag for {@link #protectionLevel}, corresponding
132      * to the <code>setup</code> value of
133      * {@link android.R.attr#protectionLevel}.
134      */
135     public static final int PROTECTION_FLAG_SETUP = 0x800;
136 
137     /**
138      * Additional flag for {@link #protectionLevel}, corresponding
139      * to the <code>instant</code> value of
140      * {@link android.R.attr#protectionLevel}.
141      */
142     public static final int PROTECTION_FLAG_INSTANT = 0x1000;
143 
144     /**
145      * Additional flag for {@link #protectionLevel}, corresponding
146      * to the <code>runtime</code> value of
147      * {@link android.R.attr#protectionLevel}.
148      */
149     public static final int PROTECTION_FLAG_RUNTIME_ONLY = 0x2000;
150 
151     /**
152      * Additional flag for {@link #protectionLevel}, corresponding
153      * to the <code>oem</code> value of
154      * {@link android.R.attr#protectionLevel}.
155      *
156      * @hide
157      */
158     @SystemApi
159     public static final int PROTECTION_FLAG_OEM = 0x4000;
160 
161     /**
162      * Additional flag for {${link #protectionLevel}, corresponding
163      * to the <code>vendorPrivileged</code> value of
164      * {@link android.R.attr#protectionLevel}.
165      *
166      * @hide
167      */
168     @TestApi
169     public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 0x8000;
170 
171     /**
172      * Additional flag for {@link #protectionLevel}, corresponding
173      * to the <code>text_classifier</code> value of
174      * {@link android.R.attr#protectionLevel}.
175      *
176      * @hide
177      */
178     @SystemApi
179     @TestApi
180     public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 0x10000;
181 
182     /** @hide */
183     @IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = {
184             PROTECTION_FLAG_PRIVILEGED,
185             PROTECTION_FLAG_SYSTEM,
186             PROTECTION_FLAG_DEVELOPMENT,
187             PROTECTION_FLAG_APPOP,
188             PROTECTION_FLAG_PRE23,
189             PROTECTION_FLAG_INSTALLER,
190             PROTECTION_FLAG_VERIFIER,
191             PROTECTION_FLAG_PREINSTALLED,
192             PROTECTION_FLAG_SETUP,
193             PROTECTION_FLAG_INSTANT,
194             PROTECTION_FLAG_RUNTIME_ONLY,
195             PROTECTION_FLAG_OEM,
196             PROTECTION_FLAG_VENDOR_PRIVILEGED,
197             PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER,
198     })
199     @Retention(RetentionPolicy.SOURCE)
200     public @interface ProtectionFlags {}
201 
202     /**
203      * Mask for {@link #protectionLevel}: the basic protection type.
204      *
205      * @deprecated Use #getProtection() instead.
206      */
207     @Deprecated
208     public static final int PROTECTION_MASK_BASE = 0xf;
209 
210     /**
211      * Mask for {@link #protectionLevel}: additional flag bits.
212      *
213      * @deprecated Use #getProtectionFlags() instead.
214      */
215     @Deprecated
216     public static final int PROTECTION_MASK_FLAGS = 0xfff0;
217 
218     /**
219      * The level of access this permission is protecting, as per
220      * {@link android.R.attr#protectionLevel}. Consists of
221      * a base permission type and zero or more flags. Use the following functions
222      * to extract them.
223      *
224      * <pre>
225      * int basePermissionType = permissionInfo.getProtection();
226      * int permissionFlags = permissionInfo.getProtectionFlags();
227      * </pre>
228      *
229      * <p></p>Base permission types are {@link #PROTECTION_NORMAL},
230      * {@link #PROTECTION_DANGEROUS}, {@link #PROTECTION_SIGNATURE}
231      * and the deprecated {@link #PROTECTION_SIGNATURE_OR_SYSTEM}.
232      * Flags are listed under {@link android.R.attr#protectionLevel}.
233      *
234      * @deprecated Use #getProtection() and #getProtectionFlags() instead.
235      */
236     @Deprecated
237     public int protectionLevel;
238 
239     /**
240      * The group this permission is a part of, as per
241      * {@link android.R.attr#permissionGroup}.
242      */
243     public String group;
244 
245     /**
246      * Flag for {@link #flags}, corresponding to <code>costsMoney</code>
247      * value of {@link android.R.attr#permissionFlags}.
248      */
249     public static final int FLAG_COSTS_MONEY = 1<<0;
250 
251     /**
252      * Flag for {@link #flags}, corresponding to <code>removed</code>
253      * value of {@link android.R.attr#permissionFlags}.
254      * @hide
255      */
256     @SystemApi
257     public static final int FLAG_REMOVED = 1<<1;
258 
259     /**
260      * Flag for {@link #flags}, indicating that this permission has been
261      * installed into the system's globally defined permissions.
262      */
263     public static final int FLAG_INSTALLED = 1<<30;
264 
265     /**
266      * Additional flags about this permission as given by
267      * {@link android.R.attr#permissionFlags}.
268      */
269     public int flags;
270 
271     /**
272      * A string resource identifier (in the package's resources) of this
273      * permission's description.  From the "description" attribute or,
274      * if not set, 0.
275      */
276     public int descriptionRes;
277 
278     /**
279      * A string resource identifier (in the package's resources) used to request the permissions.
280      * From the "request" attribute or, if not set, 0.
281      *
282      * @hide
283      */
284     @SystemApi
285     public int requestRes;
286 
287     /**
288      * The description string provided in the AndroidManifest file, if any.  You
289      * probably don't want to use this, since it will be null if the description
290      * is in a resource.  You probably want
291      * {@link PermissionInfo#loadDescription} instead.
292      */
293     public CharSequence nonLocalizedDescription;
294 
295     /** @hide */
fixProtectionLevel(int level)296     public static int fixProtectionLevel(int level) {
297         if (level == PROTECTION_SIGNATURE_OR_SYSTEM) {
298             level = PROTECTION_SIGNATURE | PROTECTION_FLAG_PRIVILEGED;
299         }
300         if ((level & PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0
301                 && (level & PROTECTION_FLAG_PRIVILEGED) == 0) {
302             // 'vendorPrivileged' must be 'privileged'. If not,
303             // drop the vendorPrivileged.
304             level = level & ~PROTECTION_FLAG_VENDOR_PRIVILEGED;
305         }
306         return level;
307     }
308 
309     /** @hide */
protectionToString(int level)310     public static String protectionToString(int level) {
311         String protLevel = "????";
312         switch (level & PROTECTION_MASK_BASE) {
313             case PermissionInfo.PROTECTION_DANGEROUS:
314                 protLevel = "dangerous";
315                 break;
316             case PermissionInfo.PROTECTION_NORMAL:
317                 protLevel = "normal";
318                 break;
319             case PermissionInfo.PROTECTION_SIGNATURE:
320                 protLevel = "signature";
321                 break;
322             case PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM:
323                 protLevel = "signatureOrSystem";
324                 break;
325         }
326         if ((level & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0) {
327             protLevel += "|privileged";
328         }
329         if ((level & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
330             protLevel += "|development";
331         }
332         if ((level & PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
333             protLevel += "|appop";
334         }
335         if ((level & PermissionInfo.PROTECTION_FLAG_PRE23) != 0) {
336             protLevel += "|pre23";
337         }
338         if ((level & PermissionInfo.PROTECTION_FLAG_INSTALLER) != 0) {
339             protLevel += "|installer";
340         }
341         if ((level & PermissionInfo.PROTECTION_FLAG_VERIFIER) != 0) {
342             protLevel += "|verifier";
343         }
344         if ((level & PermissionInfo.PROTECTION_FLAG_PREINSTALLED) != 0) {
345             protLevel += "|preinstalled";
346         }
347         if ((level & PermissionInfo.PROTECTION_FLAG_SETUP) != 0) {
348             protLevel += "|setup";
349         }
350         if ((level & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0) {
351             protLevel += "|instant";
352         }
353         if ((level & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) != 0) {
354             protLevel += "|runtime";
355         }
356         if ((level & PermissionInfo.PROTECTION_FLAG_OEM) != 0) {
357             protLevel += "|oem";
358         }
359         if ((level & PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0) {
360             protLevel += "|vendorPrivileged";
361         }
362         if ((level & PermissionInfo.PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER) != 0) {
363             protLevel += "|textClassifier";
364         }
365         return protLevel;
366     }
367 
PermissionInfo()368     public PermissionInfo() {
369     }
370 
PermissionInfo(PermissionInfo orig)371     public PermissionInfo(PermissionInfo orig) {
372         super(orig);
373         protectionLevel = orig.protectionLevel;
374         flags = orig.flags;
375         group = orig.group;
376         descriptionRes = orig.descriptionRes;
377         requestRes = orig.requestRes;
378         nonLocalizedDescription = orig.nonLocalizedDescription;
379     }
380 
381     /**
382      * Retrieve the textual description of this permission.  This
383      * will call back on the given PackageManager to load the description from
384      * the application.
385      *
386      * @param pm A PackageManager from which the label can be loaded; usually
387      * the PackageManager from which you originally retrieved this item.
388      *
389      * @return Returns a CharSequence containing the permission's description.
390      * If there is no description, null is returned.
391      */
loadDescription(PackageManager pm)392     public CharSequence loadDescription(PackageManager pm) {
393         if (nonLocalizedDescription != null) {
394             return nonLocalizedDescription;
395         }
396         if (descriptionRes != 0) {
397             CharSequence label = pm.getText(packageName, descriptionRes, null);
398             if (label != null) {
399                 return label;
400             }
401         }
402         return null;
403     }
404 
405     /**
406      * Return the base permission type.
407      */
408     @Protection
getProtection()409     public int getProtection() {
410         return protectionLevel & PROTECTION_MASK_BASE;
411     }
412 
413     /**
414      * Return the additional flags in {@link #protectionLevel}.
415      */
416     @ProtectionFlags
getProtectionFlags()417     public int getProtectionFlags() {
418         return protectionLevel & ~PROTECTION_MASK_BASE;
419     }
420 
421     @Override
toString()422     public String toString() {
423         return "PermissionInfo{"
424             + Integer.toHexString(System.identityHashCode(this))
425             + " " + name + "}";
426     }
427 
428     @Override
describeContents()429     public int describeContents() {
430         return 0;
431     }
432 
433     @Override
writeToParcel(Parcel dest, int parcelableFlags)434     public void writeToParcel(Parcel dest, int parcelableFlags) {
435         super.writeToParcel(dest, parcelableFlags);
436         dest.writeInt(protectionLevel);
437         dest.writeInt(flags);
438         dest.writeString(group);
439         dest.writeInt(descriptionRes);
440         dest.writeInt(requestRes);
441         TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags);
442     }
443 
444     /** @hide */
calculateFootprint()445     public int calculateFootprint() {
446         int size = name.length();
447         if (nonLocalizedLabel != null) {
448             size += nonLocalizedLabel.length();
449         }
450         if (nonLocalizedDescription != null) {
451             size += nonLocalizedDescription.length();
452         }
453         return size;
454     }
455 
456     /** @hide */
isAppOp()457     public boolean isAppOp() {
458         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0;
459     }
460 
461     public static final Creator<PermissionInfo> CREATOR =
462         new Creator<PermissionInfo>() {
463         @Override
464         public PermissionInfo createFromParcel(Parcel source) {
465             return new PermissionInfo(source);
466         }
467         @Override
468         public PermissionInfo[] newArray(int size) {
469             return new PermissionInfo[size];
470         }
471     };
472 
PermissionInfo(Parcel source)473     private PermissionInfo(Parcel source) {
474         super(source);
475         protectionLevel = source.readInt();
476         flags = source.readInt();
477         group = source.readString();
478         descriptionRes = source.readInt();
479         requestRes = source.readInt();
480         nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
481     }
482 }
483