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