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