• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 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 com.android.server.pm.permission;
18 
19 import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
20 import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
21 import static android.content.pm.PermissionInfo.PROTECTION_NORMAL;
22 import static android.content.pm.PermissionInfo.PROTECTION_SIGNATURE;
23 import static android.content.pm.PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM;
24 
25 import static com.android.server.pm.Settings.ATTR_NAME;
26 import static com.android.server.pm.Settings.ATTR_PACKAGE;
27 import static com.android.server.pm.Settings.TAG_ITEM;
28 
29 import android.annotation.IntDef;
30 import android.annotation.NonNull;
31 import android.annotation.Nullable;
32 import android.content.pm.PackageParser;
33 import android.content.pm.PackageParser.Permission;
34 import android.content.pm.PermissionInfo;
35 import android.content.pm.Signature;
36 import android.os.UserHandle;
37 import android.util.Log;
38 import android.util.Slog;
39 
40 import com.android.server.pm.DumpState;
41 import com.android.server.pm.PackageManagerService;
42 import com.android.server.pm.PackageSetting;
43 import com.android.server.pm.PackageSettingBase;
44 
45 import org.xmlpull.v1.XmlPullParser;
46 import org.xmlpull.v1.XmlSerializer;
47 
48 import java.io.IOException;
49 import java.io.PrintWriter;
50 import java.lang.annotation.Retention;
51 import java.lang.annotation.RetentionPolicy;
52 import java.util.Arrays;
53 import java.util.Collection;
54 import java.util.Map;
55 import java.util.Objects;
56 import java.util.Set;
57 
58 public final class BasePermission {
59     static final String TAG = "PackageManager";
60 
61     public static final int TYPE_NORMAL = 0;
62     public static final int TYPE_BUILTIN = 1;
63     public static final int TYPE_DYNAMIC = 2;
64     @IntDef(value = {
65         TYPE_NORMAL,
66         TYPE_BUILTIN,
67         TYPE_DYNAMIC,
68     })
69     @Retention(RetentionPolicy.SOURCE)
70     public @interface PermissionType {}
71 
72     @IntDef(value = {
73         PROTECTION_DANGEROUS,
74         PROTECTION_NORMAL,
75         PROTECTION_SIGNATURE,
76         PROTECTION_SIGNATURE_OR_SYSTEM,
77     })
78     @Retention(RetentionPolicy.SOURCE)
79     public @interface ProtectionLevel {}
80 
81     final String name;
82 
83     final @PermissionType int type;
84 
85     String sourcePackageName;
86 
87     // TODO: Can we get rid of this? Seems we only use some signature info from the setting
88     PackageSettingBase sourcePackageSetting;
89 
90     int protectionLevel;
91 
92     PackageParser.Permission perm;
93 
94     PermissionInfo pendingPermissionInfo;
95 
96     /** UID that owns the definition of this permission */
97     int uid;
98 
99     /** Additional GIDs given to apps granted this permission */
100     private int[] gids;
101 
102     /**
103      * Flag indicating that {@link #gids} should be adjusted based on the
104      * {@link UserHandle} the granted app is running as.
105      */
106     private boolean perUser;
107 
BasePermission(String _name, String _sourcePackageName, @PermissionType int _type)108     public BasePermission(String _name, String _sourcePackageName, @PermissionType int _type) {
109         name = _name;
110         sourcePackageName = _sourcePackageName;
111         type = _type;
112         // Default to most conservative protection level.
113         protectionLevel = PermissionInfo.PROTECTION_SIGNATURE;
114     }
115 
116     @Override
toString()117     public String toString() {
118         return "BasePermission{" + Integer.toHexString(System.identityHashCode(this)) + " " + name
119                 + "}";
120     }
121 
getName()122     public String getName() {
123         return name;
124     }
getProtectionLevel()125     public int getProtectionLevel() {
126         return protectionLevel;
127     }
getSourcePackageName()128     public String getSourcePackageName() {
129         return sourcePackageName;
130     }
getSourcePackageSetting()131     public PackageSettingBase getSourcePackageSetting() {
132         return sourcePackageSetting;
133     }
getSourceSignatures()134     public Signature[] getSourceSignatures() {
135         return sourcePackageSetting.getSignatures();
136     }
getType()137     public int getType() {
138         return type;
139     }
getUid()140     public int getUid() {
141         return uid;
142     }
setGids(int[] gids, boolean perUser)143     public void setGids(int[] gids, boolean perUser) {
144         this.gids = gids;
145         this.perUser = perUser;
146     }
setPermission(@ullable Permission perm)147     public void setPermission(@Nullable Permission perm) {
148         this.perm = perm;
149     }
setSourcePackageSetting(PackageSettingBase sourcePackageSetting)150     public void setSourcePackageSetting(PackageSettingBase sourcePackageSetting) {
151         this.sourcePackageSetting = sourcePackageSetting;
152     }
153 
computeGids(int userId)154     public int[] computeGids(int userId) {
155         if (perUser) {
156             final int[] userGids = new int[gids.length];
157             for (int i = 0; i < gids.length; i++) {
158                 userGids[i] = UserHandle.getUid(userId, gids[i]);
159             }
160             return userGids;
161         } else {
162             return gids;
163         }
164     }
165 
calculateFootprint(BasePermission perm)166     public int calculateFootprint(BasePermission perm) {
167         if (uid == perm.uid) {
168             return perm.name.length() + perm.perm.info.calculateFootprint();
169         }
170         return 0;
171     }
172 
isPermission(Permission perm)173     public boolean isPermission(Permission perm) {
174         return this.perm == perm;
175     }
176 
isDynamic()177     public boolean isDynamic() {
178         return type == TYPE_DYNAMIC;
179     }
180 
181 
isNormal()182     public boolean isNormal() {
183         return (protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
184                 == PermissionInfo.PROTECTION_NORMAL;
185     }
isRuntime()186     public boolean isRuntime() {
187         return (protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
188                 == PermissionInfo.PROTECTION_DANGEROUS;
189     }
190 
isRemoved()191     public boolean isRemoved() {
192         return perm != null && perm.info != null
193                 && (perm.info.flags & PermissionInfo.FLAG_REMOVED) != 0;
194     }
195 
isSoftRestricted()196     public boolean isSoftRestricted() {
197         return perm != null && perm.info != null
198                 && (perm.info.flags & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0;
199     }
200 
isHardRestricted()201     public boolean isHardRestricted() {
202         return perm != null && perm.info != null
203                 && (perm.info.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0;
204     }
205 
isHardOrSoftRestricted()206     public boolean isHardOrSoftRestricted() {
207         return perm != null && perm.info != null
208                 && (perm.info.flags & (PermissionInfo.FLAG_HARD_RESTRICTED
209                 | PermissionInfo.FLAG_SOFT_RESTRICTED)) != 0;
210     }
211 
isImmutablyRestricted()212     public boolean isImmutablyRestricted() {
213         return perm != null && perm.info != null
214                 && (perm.info.flags & PermissionInfo.FLAG_IMMUTABLY_RESTRICTED) != 0;
215     }
216 
isSignature()217     public boolean isSignature() {
218         return (protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) ==
219                 PermissionInfo.PROTECTION_SIGNATURE;
220     }
221 
isAppOp()222     public boolean isAppOp() {
223         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0;
224     }
isDevelopment()225     public boolean isDevelopment() {
226         return isSignature()
227                 && (protectionLevel & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0;
228     }
isInstaller()229     public boolean isInstaller() {
230         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTALLER) != 0;
231     }
isInstant()232     public boolean isInstant() {
233         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0;
234     }
isOEM()235     public boolean isOEM() {
236         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_OEM) != 0;
237     }
isPre23()238     public boolean isPre23() {
239         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_PRE23) != 0;
240     }
isPreInstalled()241     public boolean isPreInstalled() {
242         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_PREINSTALLED) != 0;
243     }
isPrivileged()244     public boolean isPrivileged() {
245         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0;
246     }
isRuntimeOnly()247     public boolean isRuntimeOnly() {
248         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) != 0;
249     }
isSetup()250     public boolean isSetup() {
251         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_SETUP) != 0;
252     }
isVerifier()253     public boolean isVerifier() {
254         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_VERIFIER) != 0;
255     }
isVendorPrivileged()256     public boolean isVendorPrivileged() {
257         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0;
258     }
isSystemTextClassifier()259     public boolean isSystemTextClassifier() {
260         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER)
261                 != 0;
262     }
isWellbeing()263     public boolean isWellbeing() {
264         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_WELLBEING) != 0;
265     }
isDocumenter()266     public boolean isDocumenter() {
267         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_DOCUMENTER) != 0;
268     }
isConfigurator()269     public boolean isConfigurator() {
270         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_CONFIGURATOR)
271             != 0;
272     }
isIncidentReportApprover()273     public boolean isIncidentReportApprover() {
274         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_INCIDENT_REPORT_APPROVER) != 0;
275     }
isAppPredictor()276     public boolean isAppPredictor() {
277         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) != 0;
278     }
279 
transfer(@onNull String origPackageName, @NonNull String newPackageName)280     public void transfer(@NonNull String origPackageName, @NonNull String newPackageName) {
281         if (!origPackageName.equals(sourcePackageName)) {
282             return;
283         }
284         sourcePackageName = newPackageName;
285         sourcePackageSetting = null;
286         perm = null;
287         if (pendingPermissionInfo != null) {
288             pendingPermissionInfo.packageName = newPackageName;
289         }
290         uid = 0;
291         setGids(null, false);
292     }
293 
addToTree(@rotectionLevel int protectionLevel, @NonNull PermissionInfo info, @NonNull BasePermission tree)294     public boolean addToTree(@ProtectionLevel int protectionLevel,
295             @NonNull PermissionInfo info, @NonNull BasePermission tree) {
296         final boolean changed =
297                 (this.protectionLevel != protectionLevel
298                     || perm == null
299                     || uid != tree.uid
300                     || !perm.owner.equals(tree.perm.owner)
301                     || !comparePermissionInfos(perm.info, info));
302         this.protectionLevel = protectionLevel;
303         info = new PermissionInfo(info);
304         info.protectionLevel = protectionLevel;
305         perm = new PackageParser.Permission(tree.perm.owner, info);
306         perm.info.packageName = tree.perm.info.packageName;
307         uid = tree.uid;
308         return changed;
309     }
310 
updateDynamicPermission(Collection<BasePermission> permissionTrees)311     public void updateDynamicPermission(Collection<BasePermission> permissionTrees) {
312         if (PackageManagerService.DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
313                 + getName() + " pkg=" + getSourcePackageName()
314                 + " info=" + pendingPermissionInfo);
315         if (sourcePackageSetting == null && pendingPermissionInfo != null) {
316             final BasePermission tree = findPermissionTree(permissionTrees, name);
317             if (tree != null && tree.perm != null) {
318                 sourcePackageSetting = tree.sourcePackageSetting;
319                 perm = new PackageParser.Permission(tree.perm.owner,
320                         new PermissionInfo(pendingPermissionInfo));
321                 perm.info.packageName = tree.perm.info.packageName;
322                 perm.info.name = name;
323                 uid = tree.uid;
324             }
325         }
326     }
327 
createOrUpdate(@ullable BasePermission bp, @NonNull Permission p, @NonNull PackageParser.Package pkg, Collection<BasePermission> permissionTrees, boolean chatty)328     static BasePermission createOrUpdate(@Nullable BasePermission bp, @NonNull Permission p,
329             @NonNull PackageParser.Package pkg, Collection<BasePermission> permissionTrees,
330             boolean chatty) {
331         final PackageSettingBase pkgSetting = (PackageSettingBase) pkg.mExtras;
332         // Allow system apps to redefine non-system permissions
333         if (bp != null && !Objects.equals(bp.sourcePackageName, p.info.packageName)) {
334             final boolean currentOwnerIsSystem = (bp.perm != null
335                     && bp.perm.owner.isSystem());
336             if (p.owner.isSystem()) {
337                 if (bp.type == BasePermission.TYPE_BUILTIN && bp.perm == null) {
338                     // It's a built-in permission and no owner, take ownership now
339                     bp.sourcePackageSetting = pkgSetting;
340                     bp.perm = p;
341                     bp.uid = pkg.applicationInfo.uid;
342                     bp.sourcePackageName = p.info.packageName;
343                     p.info.flags |= PermissionInfo.FLAG_INSTALLED;
344                 } else if (!currentOwnerIsSystem) {
345                     String msg = "New decl " + p.owner + " of permission  "
346                             + p.info.name + " is system; overriding " + bp.sourcePackageName;
347                     PackageManagerService.reportSettingsProblem(Log.WARN, msg);
348                     bp = null;
349                 }
350             }
351         }
352         if (bp == null) {
353             bp = new BasePermission(p.info.name, p.info.packageName, TYPE_NORMAL);
354         }
355         StringBuilder r = null;
356         if (bp.perm == null) {
357             if (bp.sourcePackageName == null
358                     || bp.sourcePackageName.equals(p.info.packageName)) {
359                 final BasePermission tree = findPermissionTree(permissionTrees, p.info.name);
360                 if (tree == null
361                         || tree.sourcePackageName.equals(p.info.packageName)) {
362                     bp.sourcePackageSetting = pkgSetting;
363                     bp.perm = p;
364                     bp.uid = pkg.applicationInfo.uid;
365                     bp.sourcePackageName = p.info.packageName;
366                     p.info.flags |= PermissionInfo.FLAG_INSTALLED;
367                     if (chatty) {
368                         if (r == null) {
369                             r = new StringBuilder(256);
370                         } else {
371                             r.append(' ');
372                         }
373                         r.append(p.info.name);
374                     }
375                 } else {
376                     Slog.w(TAG, "Permission " + p.info.name + " from package "
377                             + p.info.packageName + " ignored: base tree "
378                             + tree.name + " is from package "
379                             + tree.sourcePackageName);
380                 }
381             } else {
382                 Slog.w(TAG, "Permission " + p.info.name + " from package "
383                         + p.info.packageName + " ignored: original from "
384                         + bp.sourcePackageName);
385             }
386         } else if (chatty) {
387             if (r == null) {
388                 r = new StringBuilder(256);
389             } else {
390                 r.append(' ');
391             }
392             r.append("DUP:");
393             r.append(p.info.name);
394         }
395         if (bp.perm == p) {
396             bp.protectionLevel = p.info.protectionLevel;
397         }
398         if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) {
399             Log.d(TAG, "  Permissions: " + r);
400         }
401         return bp;
402     }
403 
enforcePermissionTree( Collection<BasePermission> permissionTrees, String permName, int callingUid)404     static BasePermission enforcePermissionTree(
405             Collection<BasePermission> permissionTrees, String permName, int callingUid) {
406         if (permName != null) {
407             BasePermission bp = findPermissionTree(permissionTrees, permName);
408             if (bp != null) {
409                 if (bp.uid == UserHandle.getAppId(callingUid)) {
410                     return bp;
411                 }
412                 throw new SecurityException("Calling uid " + callingUid
413                         + " is not allowed to add to permission tree "
414                         + bp.name + " owned by uid " + bp.uid);
415             }
416         }
417         throw new SecurityException("No permission tree found for " + permName);
418     }
419 
enforceDeclaredUsedAndRuntimeOrDevelopment(PackageParser.Package pkg)420     public void enforceDeclaredUsedAndRuntimeOrDevelopment(PackageParser.Package pkg) {
421         final PackageSetting pkgSetting = (PackageSetting) pkg.mExtras;
422         final PermissionsState permsState = pkgSetting.getPermissionsState();
423         int index = pkg.requestedPermissions.indexOf(name);
424         if (!permsState.hasRequestedPermission(name) && index == -1) {
425             throw new SecurityException("Package " + pkg.packageName
426                     + " has not requested permission " + name);
427         }
428         if (!isRuntime() && !isDevelopment()) {
429             throw new SecurityException("Permission " + name
430                     + " requested by " + pkg.packageName + " is not a changeable permission type");
431         }
432     }
433 
findPermissionTree( Collection<BasePermission> permissionTrees, String permName)434     private static BasePermission findPermissionTree(
435             Collection<BasePermission> permissionTrees, String permName) {
436         for (BasePermission bp : permissionTrees) {
437             if (permName.startsWith(bp.name) &&
438                     permName.length() > bp.name.length() &&
439                     permName.charAt(bp.name.length()) == '.') {
440                 return bp;
441             }
442         }
443         return null;
444     }
445 
generatePermissionInfo(@onNull String groupName, int flags)446     public @Nullable PermissionInfo generatePermissionInfo(@NonNull String groupName, int flags) {
447         if (groupName == null) {
448             if (perm == null || perm.info.group == null) {
449                 return generatePermissionInfo(protectionLevel, flags);
450             }
451         } else {
452             if (perm != null && groupName.equals(perm.info.group)) {
453                 return PackageParser.generatePermissionInfo(perm, flags);
454             }
455         }
456         return null;
457     }
458 
generatePermissionInfo(int adjustedProtectionLevel, int flags)459     public @NonNull PermissionInfo generatePermissionInfo(int adjustedProtectionLevel, int flags) {
460         PermissionInfo permissionInfo;
461         if (perm != null) {
462             final boolean protectionLevelChanged = protectionLevel != adjustedProtectionLevel;
463             permissionInfo = PackageParser.generatePermissionInfo(perm, flags);
464             if (protectionLevelChanged && permissionInfo == perm.info) {
465                 // if we return different protection level, don't use the cached info
466                 permissionInfo = new PermissionInfo(permissionInfo);
467                 permissionInfo.protectionLevel = adjustedProtectionLevel;
468             }
469             return permissionInfo;
470         }
471         permissionInfo = new PermissionInfo();
472         permissionInfo.name = name;
473         permissionInfo.packageName = sourcePackageName;
474         permissionInfo.nonLocalizedLabel = name;
475         permissionInfo.protectionLevel = protectionLevel;
476         return permissionInfo;
477     }
478 
readLPw(@onNull Map<String, BasePermission> out, @NonNull XmlPullParser parser)479     public static boolean readLPw(@NonNull Map<String, BasePermission> out,
480             @NonNull XmlPullParser parser) {
481         final String tagName = parser.getName();
482         if (!tagName.equals(TAG_ITEM)) {
483             return false;
484         }
485         final String name = parser.getAttributeValue(null, ATTR_NAME);
486         final String sourcePackage = parser.getAttributeValue(null, ATTR_PACKAGE);
487         final String ptype = parser.getAttributeValue(null, "type");
488         if (name == null || sourcePackage == null) {
489             PackageManagerService.reportSettingsProblem(Log.WARN,
490                     "Error in package manager settings: permissions has" + " no name at "
491                             + parser.getPositionDescription());
492             return false;
493         }
494         final boolean dynamic = "dynamic".equals(ptype);
495         BasePermission bp = out.get(name);
496         // If the permission is builtin, do not clobber it.
497         if (bp == null || bp.type != TYPE_BUILTIN) {
498             bp = new BasePermission(name.intern(), sourcePackage,
499                     dynamic ? TYPE_DYNAMIC : TYPE_NORMAL);
500         }
501         bp.protectionLevel = readInt(parser, null, "protection",
502                 PermissionInfo.PROTECTION_NORMAL);
503         bp.protectionLevel = PermissionInfo.fixProtectionLevel(bp.protectionLevel);
504         if (dynamic) {
505             final PermissionInfo pi = new PermissionInfo();
506             pi.packageName = sourcePackage.intern();
507             pi.name = name.intern();
508             pi.icon = readInt(parser, null, "icon", 0);
509             pi.nonLocalizedLabel = parser.getAttributeValue(null, "label");
510             pi.protectionLevel = bp.protectionLevel;
511             bp.pendingPermissionInfo = pi;
512         }
513         out.put(bp.name, bp);
514         return true;
515     }
516 
readInt(XmlPullParser parser, String ns, String name, int defValue)517     private static int readInt(XmlPullParser parser, String ns, String name, int defValue) {
518         String v = parser.getAttributeValue(ns, name);
519         try {
520             if (v == null) {
521                 return defValue;
522             }
523             return Integer.parseInt(v);
524         } catch (NumberFormatException e) {
525             PackageManagerService.reportSettingsProblem(Log.WARN,
526                     "Error in package manager settings: attribute " + name
527                             + " has bad integer value " + v + " at "
528                             + parser.getPositionDescription());
529         }
530         return defValue;
531     }
532 
writeLPr(@onNull XmlSerializer serializer)533     public void writeLPr(@NonNull XmlSerializer serializer) throws IOException {
534         if (sourcePackageName == null) {
535             return;
536         }
537         serializer.startTag(null, TAG_ITEM);
538         serializer.attribute(null, ATTR_NAME, name);
539         serializer.attribute(null, ATTR_PACKAGE, sourcePackageName);
540         if (protectionLevel != PermissionInfo.PROTECTION_NORMAL) {
541             serializer.attribute(null, "protection", Integer.toString(protectionLevel));
542         }
543         if (type == BasePermission.TYPE_DYNAMIC) {
544             final PermissionInfo pi = perm != null ? perm.info : pendingPermissionInfo;
545             if (pi != null) {
546                 serializer.attribute(null, "type", "dynamic");
547                 if (pi.icon != 0) {
548                     serializer.attribute(null, "icon", Integer.toString(pi.icon));
549                 }
550                 if (pi.nonLocalizedLabel != null) {
551                     serializer.attribute(null, "label", pi.nonLocalizedLabel.toString());
552                 }
553             }
554         }
555         serializer.endTag(null, TAG_ITEM);
556     }
557 
compareStrings(CharSequence s1, CharSequence s2)558     private static boolean compareStrings(CharSequence s1, CharSequence s2) {
559         if (s1 == null) {
560             return s2 == null;
561         }
562         if (s2 == null) {
563             return false;
564         }
565         if (s1.getClass() != s2.getClass()) {
566             return false;
567         }
568         return s1.equals(s2);
569     }
570 
comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2)571     private static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) {
572         if (pi1.icon != pi2.icon) return false;
573         if (pi1.logo != pi2.logo) return false;
574         if (pi1.protectionLevel != pi2.protectionLevel) return false;
575         if (!compareStrings(pi1.name, pi2.name)) return false;
576         if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false;
577         // We'll take care of setting this one.
578         if (!compareStrings(pi1.packageName, pi2.packageName)) return false;
579         // These are not currently stored in settings.
580         //if (!compareStrings(pi1.group, pi2.group)) return false;
581         //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false;
582         //if (pi1.labelRes != pi2.labelRes) return false;
583         //if (pi1.descriptionRes != pi2.descriptionRes) return false;
584         return true;
585     }
586 
dumpPermissionsLPr(@onNull PrintWriter pw, @NonNull String packageName, @NonNull Set<String> permissionNames, boolean readEnforced, boolean printedSomething, @NonNull DumpState dumpState)587     public boolean dumpPermissionsLPr(@NonNull PrintWriter pw, @NonNull String packageName,
588             @NonNull Set<String> permissionNames, boolean readEnforced,
589             boolean printedSomething, @NonNull DumpState dumpState) {
590         if (packageName != null && !packageName.equals(sourcePackageName)) {
591             return false;
592         }
593         if (permissionNames != null && !permissionNames.contains(name)) {
594             return false;
595         }
596         if (!printedSomething) {
597             if (dumpState.onTitlePrinted())
598                 pw.println();
599             pw.println("Permissions:");
600             printedSomething = true;
601         }
602         pw.print("  Permission ["); pw.print(name); pw.print("] (");
603                 pw.print(Integer.toHexString(System.identityHashCode(this)));
604                 pw.println("):");
605         pw.print("    sourcePackage="); pw.println(sourcePackageName);
606         pw.print("    uid="); pw.print(uid);
607                 pw.print(" gids="); pw.print(Arrays.toString(
608                         computeGids(UserHandle.USER_SYSTEM)));
609                 pw.print(" type="); pw.print(type);
610                 pw.print(" prot=");
611                 pw.println(PermissionInfo.protectionToString(protectionLevel));
612         if (perm != null) {
613             pw.print("    perm="); pw.println(perm);
614             if ((perm.info.flags & PermissionInfo.FLAG_INSTALLED) == 0
615                     || (perm.info.flags & PermissionInfo.FLAG_REMOVED) != 0) {
616                 pw.print("    flags=0x"); pw.println(Integer.toHexString(perm.info.flags));
617             }
618         }
619         if (sourcePackageSetting != null) {
620             pw.print("    packageSetting="); pw.println(sourcePackageSetting);
621         }
622         if (READ_EXTERNAL_STORAGE.equals(name)) {
623             pw.print("    enforced=");
624             pw.println(readEnforced);
625         }
626         return true;
627     }
628 }
629