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 } isTelephony()279 public boolean isTelephony() { 280 return (protectionLevel & PermissionInfo.PROTECTION_FLAG_TELEPHONY) != 0; 281 } 282 transfer(@onNull String origPackageName, @NonNull String newPackageName)283 public void transfer(@NonNull String origPackageName, @NonNull String newPackageName) { 284 if (!origPackageName.equals(sourcePackageName)) { 285 return; 286 } 287 sourcePackageName = newPackageName; 288 sourcePackageSetting = null; 289 perm = null; 290 if (pendingPermissionInfo != null) { 291 pendingPermissionInfo.packageName = newPackageName; 292 } 293 uid = 0; 294 setGids(null, false); 295 } 296 addToTree(@rotectionLevel int protectionLevel, @NonNull PermissionInfo info, @NonNull BasePermission tree)297 public boolean addToTree(@ProtectionLevel int protectionLevel, 298 @NonNull PermissionInfo info, @NonNull BasePermission tree) { 299 final boolean changed = 300 (this.protectionLevel != protectionLevel 301 || perm == null 302 || uid != tree.uid 303 || !perm.owner.equals(tree.perm.owner) 304 || !comparePermissionInfos(perm.info, info)); 305 this.protectionLevel = protectionLevel; 306 info = new PermissionInfo(info); 307 info.protectionLevel = protectionLevel; 308 perm = new PackageParser.Permission(tree.perm.owner, info); 309 perm.info.packageName = tree.perm.info.packageName; 310 uid = tree.uid; 311 return changed; 312 } 313 updateDynamicPermission(Collection<BasePermission> permissionTrees)314 public void updateDynamicPermission(Collection<BasePermission> permissionTrees) { 315 if (PackageManagerService.DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name=" 316 + getName() + " pkg=" + getSourcePackageName() 317 + " info=" + pendingPermissionInfo); 318 if (sourcePackageSetting == null && pendingPermissionInfo != null) { 319 final BasePermission tree = findPermissionTree(permissionTrees, name); 320 if (tree != null && tree.perm != null) { 321 sourcePackageSetting = tree.sourcePackageSetting; 322 perm = new PackageParser.Permission(tree.perm.owner, 323 new PermissionInfo(pendingPermissionInfo)); 324 perm.info.packageName = tree.perm.info.packageName; 325 perm.info.name = name; 326 uid = tree.uid; 327 } 328 } 329 } 330 createOrUpdate(@ullable BasePermission bp, @NonNull Permission p, @NonNull PackageParser.Package pkg, Collection<BasePermission> permissionTrees, boolean chatty)331 static BasePermission createOrUpdate(@Nullable BasePermission bp, @NonNull Permission p, 332 @NonNull PackageParser.Package pkg, Collection<BasePermission> permissionTrees, 333 boolean chatty) { 334 final PackageSettingBase pkgSetting = (PackageSettingBase) pkg.mExtras; 335 // Allow system apps to redefine non-system permissions 336 if (bp != null && !Objects.equals(bp.sourcePackageName, p.info.packageName)) { 337 final boolean currentOwnerIsSystem = (bp.perm != null 338 && bp.perm.owner.isSystem()); 339 if (p.owner.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 bp.sourcePackageSetting = pkgSetting; 343 bp.perm = p; 344 bp.uid = pkg.applicationInfo.uid; 345 bp.sourcePackageName = p.info.packageName; 346 p.info.flags |= PermissionInfo.FLAG_INSTALLED; 347 } else if (!currentOwnerIsSystem) { 348 String msg = "New decl " + p.owner + " of permission " 349 + p.info.name + " is system; overriding " + bp.sourcePackageName; 350 PackageManagerService.reportSettingsProblem(Log.WARN, msg); 351 bp = null; 352 } 353 } 354 } 355 if (bp == null) { 356 bp = new BasePermission(p.info.name, p.info.packageName, TYPE_NORMAL); 357 } 358 StringBuilder r = null; 359 if (bp.perm == null) { 360 if (bp.sourcePackageName == null 361 || bp.sourcePackageName.equals(p.info.packageName)) { 362 final BasePermission tree = findPermissionTree(permissionTrees, p.info.name); 363 if (tree == null 364 || tree.sourcePackageName.equals(p.info.packageName)) { 365 bp.sourcePackageSetting = pkgSetting; 366 bp.perm = p; 367 bp.uid = pkg.applicationInfo.uid; 368 bp.sourcePackageName = p.info.packageName; 369 p.info.flags |= PermissionInfo.FLAG_INSTALLED; 370 if (chatty) { 371 if (r == null) { 372 r = new StringBuilder(256); 373 } else { 374 r.append(' '); 375 } 376 r.append(p.info.name); 377 } 378 } else { 379 Slog.w(TAG, "Permission " + p.info.name + " from package " 380 + p.info.packageName + " ignored: base tree " 381 + tree.name + " is from package " 382 + tree.sourcePackageName); 383 } 384 } else { 385 Slog.w(TAG, "Permission " + p.info.name + " from package " 386 + p.info.packageName + " ignored: original from " 387 + bp.sourcePackageName); 388 } 389 } else if (chatty) { 390 if (r == null) { 391 r = new StringBuilder(256); 392 } else { 393 r.append(' '); 394 } 395 r.append("DUP:"); 396 r.append(p.info.name); 397 } 398 if (bp.perm == p) { 399 bp.protectionLevel = p.info.protectionLevel; 400 } 401 if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) { 402 Log.d(TAG, " Permissions: " + r); 403 } 404 return bp; 405 } 406 enforcePermissionTree( Collection<BasePermission> permissionTrees, String permName, int callingUid)407 static BasePermission enforcePermissionTree( 408 Collection<BasePermission> permissionTrees, String permName, int callingUid) { 409 if (permName != null) { 410 BasePermission bp = findPermissionTree(permissionTrees, permName); 411 if (bp != null) { 412 if (bp.uid == UserHandle.getAppId(callingUid)) { 413 return bp; 414 } 415 throw new SecurityException("Calling uid " + callingUid 416 + " is not allowed to add to permission tree " 417 + bp.name + " owned by uid " + bp.uid); 418 } 419 } 420 throw new SecurityException("No permission tree found for " + permName); 421 } 422 enforceDeclaredUsedAndRuntimeOrDevelopment(PackageParser.Package pkg)423 public void enforceDeclaredUsedAndRuntimeOrDevelopment(PackageParser.Package pkg) { 424 final PackageSetting pkgSetting = (PackageSetting) pkg.mExtras; 425 final PermissionsState permsState = pkgSetting.getPermissionsState(); 426 int index = pkg.requestedPermissions.indexOf(name); 427 if (!permsState.hasRequestedPermission(name) && index == -1) { 428 throw new SecurityException("Package " + pkg.packageName 429 + " has not requested permission " + name); 430 } 431 if (!isRuntime() && !isDevelopment()) { 432 throw new SecurityException("Permission " + name 433 + " requested by " + pkg.packageName + " is not a changeable permission type"); 434 } 435 } 436 findPermissionTree( Collection<BasePermission> permissionTrees, String permName)437 private static BasePermission findPermissionTree( 438 Collection<BasePermission> permissionTrees, String permName) { 439 for (BasePermission bp : permissionTrees) { 440 if (permName.startsWith(bp.name) && 441 permName.length() > bp.name.length() && 442 permName.charAt(bp.name.length()) == '.') { 443 return bp; 444 } 445 } 446 return null; 447 } 448 generatePermissionInfo(@onNull String groupName, int flags)449 public @Nullable PermissionInfo generatePermissionInfo(@NonNull String groupName, int flags) { 450 if (groupName == null) { 451 if (perm == null || perm.info.group == null) { 452 return generatePermissionInfo(protectionLevel, flags); 453 } 454 } else { 455 if (perm != null && groupName.equals(perm.info.group)) { 456 return PackageParser.generatePermissionInfo(perm, flags); 457 } 458 } 459 return null; 460 } 461 generatePermissionInfo(int adjustedProtectionLevel, int flags)462 public @NonNull PermissionInfo generatePermissionInfo(int adjustedProtectionLevel, int flags) { 463 PermissionInfo permissionInfo; 464 if (perm != null) { 465 final boolean protectionLevelChanged = protectionLevel != adjustedProtectionLevel; 466 permissionInfo = PackageParser.generatePermissionInfo(perm, flags); 467 if (protectionLevelChanged && permissionInfo == perm.info) { 468 // if we return different protection level, don't use the cached info 469 permissionInfo = new PermissionInfo(permissionInfo); 470 permissionInfo.protectionLevel = adjustedProtectionLevel; 471 } 472 return permissionInfo; 473 } 474 permissionInfo = new PermissionInfo(); 475 permissionInfo.name = name; 476 permissionInfo.packageName = sourcePackageName; 477 permissionInfo.nonLocalizedLabel = name; 478 permissionInfo.protectionLevel = protectionLevel; 479 return permissionInfo; 480 } 481 readLPw(@onNull Map<String, BasePermission> out, @NonNull XmlPullParser parser)482 public static boolean readLPw(@NonNull Map<String, BasePermission> out, 483 @NonNull XmlPullParser parser) { 484 final String tagName = parser.getName(); 485 if (!tagName.equals(TAG_ITEM)) { 486 return false; 487 } 488 final String name = parser.getAttributeValue(null, ATTR_NAME); 489 final String sourcePackage = parser.getAttributeValue(null, ATTR_PACKAGE); 490 final String ptype = parser.getAttributeValue(null, "type"); 491 if (name == null || sourcePackage == null) { 492 PackageManagerService.reportSettingsProblem(Log.WARN, 493 "Error in package manager settings: permissions has" + " no name at " 494 + parser.getPositionDescription()); 495 return false; 496 } 497 final boolean dynamic = "dynamic".equals(ptype); 498 BasePermission bp = out.get(name); 499 // If the permission is builtin, do not clobber it. 500 if (bp == null || bp.type != TYPE_BUILTIN) { 501 bp = new BasePermission(name.intern(), sourcePackage, 502 dynamic ? TYPE_DYNAMIC : TYPE_NORMAL); 503 } 504 bp.protectionLevel = readInt(parser, null, "protection", 505 PermissionInfo.PROTECTION_NORMAL); 506 bp.protectionLevel = PermissionInfo.fixProtectionLevel(bp.protectionLevel); 507 if (dynamic) { 508 final PermissionInfo pi = new PermissionInfo(); 509 pi.packageName = sourcePackage.intern(); 510 pi.name = name.intern(); 511 pi.icon = readInt(parser, null, "icon", 0); 512 pi.nonLocalizedLabel = parser.getAttributeValue(null, "label"); 513 pi.protectionLevel = bp.protectionLevel; 514 bp.pendingPermissionInfo = pi; 515 } 516 out.put(bp.name, bp); 517 return true; 518 } 519 readInt(XmlPullParser parser, String ns, String name, int defValue)520 private static int readInt(XmlPullParser parser, String ns, String name, int defValue) { 521 String v = parser.getAttributeValue(ns, name); 522 try { 523 if (v == null) { 524 return defValue; 525 } 526 return Integer.parseInt(v); 527 } catch (NumberFormatException e) { 528 PackageManagerService.reportSettingsProblem(Log.WARN, 529 "Error in package manager settings: attribute " + name 530 + " has bad integer value " + v + " at " 531 + parser.getPositionDescription()); 532 } 533 return defValue; 534 } 535 writeLPr(@onNull XmlSerializer serializer)536 public void writeLPr(@NonNull XmlSerializer serializer) throws IOException { 537 if (sourcePackageName == null) { 538 return; 539 } 540 serializer.startTag(null, TAG_ITEM); 541 serializer.attribute(null, ATTR_NAME, name); 542 serializer.attribute(null, ATTR_PACKAGE, sourcePackageName); 543 if (protectionLevel != PermissionInfo.PROTECTION_NORMAL) { 544 serializer.attribute(null, "protection", Integer.toString(protectionLevel)); 545 } 546 if (type == BasePermission.TYPE_DYNAMIC) { 547 final PermissionInfo pi = perm != null ? perm.info : pendingPermissionInfo; 548 if (pi != null) { 549 serializer.attribute(null, "type", "dynamic"); 550 if (pi.icon != 0) { 551 serializer.attribute(null, "icon", Integer.toString(pi.icon)); 552 } 553 if (pi.nonLocalizedLabel != null) { 554 serializer.attribute(null, "label", pi.nonLocalizedLabel.toString()); 555 } 556 } 557 } 558 serializer.endTag(null, TAG_ITEM); 559 } 560 compareStrings(CharSequence s1, CharSequence s2)561 private static boolean compareStrings(CharSequence s1, CharSequence s2) { 562 if (s1 == null) { 563 return s2 == null; 564 } 565 if (s2 == null) { 566 return false; 567 } 568 if (s1.getClass() != s2.getClass()) { 569 return false; 570 } 571 return s1.equals(s2); 572 } 573 comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2)574 private static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) { 575 if (pi1.icon != pi2.icon) return false; 576 if (pi1.logo != pi2.logo) return false; 577 if (pi1.protectionLevel != pi2.protectionLevel) return false; 578 if (!compareStrings(pi1.name, pi2.name)) return false; 579 if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false; 580 // We'll take care of setting this one. 581 if (!compareStrings(pi1.packageName, pi2.packageName)) return false; 582 // These are not currently stored in settings. 583 //if (!compareStrings(pi1.group, pi2.group)) return false; 584 //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false; 585 //if (pi1.labelRes != pi2.labelRes) return false; 586 //if (pi1.descriptionRes != pi2.descriptionRes) return false; 587 return true; 588 } 589 dumpPermissionsLPr(@onNull PrintWriter pw, @NonNull String packageName, @NonNull Set<String> permissionNames, boolean readEnforced, boolean printedSomething, @NonNull DumpState dumpState)590 public boolean dumpPermissionsLPr(@NonNull PrintWriter pw, @NonNull String packageName, 591 @NonNull Set<String> permissionNames, boolean readEnforced, 592 boolean printedSomething, @NonNull DumpState dumpState) { 593 if (packageName != null && !packageName.equals(sourcePackageName)) { 594 return false; 595 } 596 if (permissionNames != null && !permissionNames.contains(name)) { 597 return false; 598 } 599 if (!printedSomething) { 600 if (dumpState.onTitlePrinted()) 601 pw.println(); 602 pw.println("Permissions:"); 603 printedSomething = true; 604 } 605 pw.print(" Permission ["); pw.print(name); pw.print("] ("); 606 pw.print(Integer.toHexString(System.identityHashCode(this))); 607 pw.println("):"); 608 pw.print(" sourcePackage="); pw.println(sourcePackageName); 609 pw.print(" uid="); pw.print(uid); 610 pw.print(" gids="); pw.print(Arrays.toString( 611 computeGids(UserHandle.USER_SYSTEM))); 612 pw.print(" type="); pw.print(type); 613 pw.print(" prot="); 614 pw.println(PermissionInfo.protectionToString(protectionLevel)); 615 if (perm != null) { 616 pw.print(" perm="); pw.println(perm); 617 if ((perm.info.flags & PermissionInfo.FLAG_INSTALLED) == 0 618 || (perm.info.flags & PermissionInfo.FLAG_REMOVED) != 0) { 619 pw.print(" flags=0x"); pw.println(Integer.toHexString(perm.info.flags)); 620 } 621 } 622 if (sourcePackageSetting != null) { 623 pw.print(" packageSetting="); pw.println(sourcePackageSetting); 624 } 625 if (READ_EXTERNAL_STORAGE.equals(name)) { 626 pw.print(" enforced="); 627 pw.println(readEnforced); 628 } 629 return true; 630 } 631 } 632