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