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