1 /* 2 * Copyright (C) 2014 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; 18 19 import static com.android.internal.util.ArrayUtils.appendInt; 20 21 import android.app.ActivityManager; 22 import android.content.ComponentName; 23 import android.content.pm.FeatureInfo; 24 import android.content.pm.PackageManager; 25 import android.os.Environment; 26 import android.os.Process; 27 import android.os.storage.StorageManager; 28 import android.text.TextUtils; 29 import android.util.ArrayMap; 30 import android.util.ArraySet; 31 import android.util.Slog; 32 import android.util.SparseArray; 33 import android.util.Xml; 34 35 import com.android.internal.util.XmlUtils; 36 37 import libcore.io.IoUtils; 38 39 import org.xmlpull.v1.XmlPullParser; 40 import org.xmlpull.v1.XmlPullParserException; 41 42 import java.io.File; 43 import java.io.FileNotFoundException; 44 import java.io.FileReader; 45 import java.io.IOException; 46 import java.util.ArrayList; 47 import java.util.List; 48 49 /** 50 * Loads global system configuration info. 51 */ 52 public class SystemConfig { 53 static final String TAG = "SystemConfig"; 54 55 static SystemConfig sInstance; 56 57 // permission flag, determines which types of configuration are allowed to be read 58 private static final int ALLOW_FEATURES = 0x01; 59 private static final int ALLOW_LIBS = 0x02; 60 private static final int ALLOW_PERMISSIONS = 0x04; 61 private static final int ALLOW_APP_CONFIGS = 0x08; 62 private static final int ALLOW_PRIVAPP_PERMISSIONS = 0x10; 63 private static final int ALLOW_ALL = ~0; 64 65 // Group-ids that are given to all packages as read from etc/permissions/*.xml. 66 int[] mGlobalGids; 67 68 // These are the built-in uid -> permission mappings that were read from the 69 // system configuration files. 70 final SparseArray<ArraySet<String>> mSystemPermissions = new SparseArray<>(); 71 72 // These are the built-in shared libraries that were read from the 73 // system configuration files. Keys are the library names; strings are the 74 // paths to the libraries. 75 final ArrayMap<String, String> mSharedLibraries = new ArrayMap<>(); 76 77 // These are the features this devices supports that were read from the 78 // system configuration files. 79 final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>(); 80 81 // These are the features which this device doesn't support; the OEM 82 // partition uses these to opt-out of features from the system image. 83 final ArraySet<String> mUnavailableFeatures = new ArraySet<>(); 84 85 public static final class PermissionEntry { 86 public final String name; 87 public int[] gids; 88 public boolean perUser; 89 90 PermissionEntry(String name, boolean perUser) { 91 this.name = name; 92 this.perUser = perUser; 93 } 94 } 95 96 // These are the permission -> gid mappings that were read from the 97 // system configuration files. 98 final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>(); 99 100 // These are the packages that are white-listed to be able to run in the 101 // background while in power save mode (but not whitelisted from device idle modes), 102 // as read from the configuration files. 103 final ArraySet<String> mAllowInPowerSaveExceptIdle = new ArraySet<>(); 104 105 // These are the packages that are white-listed to be able to run in the 106 // background while in power save mode, as read from the configuration files. 107 final ArraySet<String> mAllowInPowerSave = new ArraySet<>(); 108 109 // These are the packages that are white-listed to be able to run in the 110 // background while in data-usage save mode, as read from the configuration files. 111 final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>(); 112 113 // These are the packages that are white-listed to be able to run background location 114 // without throttling, as read from the configuration files. 115 final ArraySet<String> mAllowUnthrottledLocation = new ArraySet<>(); 116 117 // These are the action strings of broadcasts which are whitelisted to 118 // be delivered anonymously even to apps which target O+. 119 final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>(); 120 121 // These are the package names of apps which should be in the 'always' 122 // URL-handling state upon factory reset. 123 final ArraySet<String> mLinkedApps = new ArraySet<>(); 124 125 // These are the packages that are whitelisted to be able to run as system user 126 final ArraySet<String> mSystemUserWhitelistedApps = new ArraySet<>(); 127 128 // These are the packages that should not run under system user 129 final ArraySet<String> mSystemUserBlacklistedApps = new ArraySet<>(); 130 131 // These are the components that are enabled by default as VR mode listener services. 132 final ArraySet<ComponentName> mDefaultVrComponents = new ArraySet<>(); 133 134 // These are the permitted backup transport service components 135 final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>(); 136 137 // These are the packages of carrier-associated apps which should be disabled until used until 138 // a SIM is inserted which grants carrier privileges to that carrier app. 139 final ArrayMap<String, List<String>> mDisabledUntilUsedPreinstalledCarrierAssociatedApps = 140 new ArrayMap<>(); 141 142 143 final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>(); 144 145 public static SystemConfig getInstance() { 146 synchronized (SystemConfig.class) { 147 if (sInstance == null) { 148 sInstance = new SystemConfig(); 149 } 150 return sInstance; 151 } 152 } 153 154 public int[] getGlobalGids() { 155 return mGlobalGids; 156 } 157 158 public SparseArray<ArraySet<String>> getSystemPermissions() { 159 return mSystemPermissions; 160 } 161 162 public ArrayMap<String, String> getSharedLibraries() { 163 return mSharedLibraries; 164 } 165 166 public ArrayMap<String, FeatureInfo> getAvailableFeatures() { 167 return mAvailableFeatures; 168 } 169 170 public ArrayMap<String, PermissionEntry> getPermissions() { 171 return mPermissions; 172 } 173 174 public ArraySet<String> getAllowImplicitBroadcasts() { 175 return mAllowImplicitBroadcasts; 176 } 177 178 public ArraySet<String> getAllowInPowerSaveExceptIdle() { 179 return mAllowInPowerSaveExceptIdle; 180 } 181 182 public ArraySet<String> getAllowInPowerSave() { 183 return mAllowInPowerSave; 184 } 185 186 public ArraySet<String> getAllowInDataUsageSave() { 187 return mAllowInDataUsageSave; 188 } 189 190 public ArraySet<String> getAllowUnthrottledLocation() { 191 return mAllowUnthrottledLocation; 192 } 193 194 public ArraySet<String> getLinkedApps() { 195 return mLinkedApps; 196 } 197 198 public ArraySet<String> getSystemUserWhitelistedApps() { 199 return mSystemUserWhitelistedApps; 200 } 201 202 public ArraySet<String> getSystemUserBlacklistedApps() { 203 return mSystemUserBlacklistedApps; 204 } 205 206 public ArraySet<ComponentName> getDefaultVrComponents() { 207 return mDefaultVrComponents; 208 } 209 210 public ArraySet<ComponentName> getBackupTransportWhitelist() { 211 return mBackupTransportWhitelist; 212 } 213 214 public ArrayMap<String, List<String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps() { 215 return mDisabledUntilUsedPreinstalledCarrierAssociatedApps; 216 } 217 218 public ArraySet<String> getPrivAppPermissions(String packageName) { 219 return mPrivAppPermissions.get(packageName); 220 } 221 222 SystemConfig() { 223 // Read configuration from system 224 readPermissions(Environment.buildPath( 225 Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL); 226 // Read configuration from the old permissions dir 227 readPermissions(Environment.buildPath( 228 Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL); 229 // Allow Vendor to customize system configs around libs, features, permissions and apps 230 int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS | 231 ALLOW_APP_CONFIGS; 232 readPermissions(Environment.buildPath( 233 Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag); 234 readPermissions(Environment.buildPath( 235 Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag); 236 // Allow ODM to customize system configs around libs, features and apps 237 int odmPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_APP_CONFIGS; 238 readPermissions(Environment.buildPath( 239 Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag); 240 readPermissions(Environment.buildPath( 241 Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag); 242 // Only allow OEM to customize features 243 readPermissions(Environment.buildPath( 244 Environment.getOemDirectory(), "etc", "sysconfig"), ALLOW_FEATURES); 245 readPermissions(Environment.buildPath( 246 Environment.getOemDirectory(), "etc", "permissions"), ALLOW_FEATURES); 247 } 248 249 void readPermissions(File libraryDir, int permissionFlag) { 250 // Read permissions from given directory. 251 if (!libraryDir.exists() || !libraryDir.isDirectory()) { 252 if (permissionFlag == ALLOW_ALL) { 253 Slog.w(TAG, "No directory " + libraryDir + ", skipping"); 254 } 255 return; 256 } 257 if (!libraryDir.canRead()) { 258 Slog.w(TAG, "Directory " + libraryDir + " cannot be read"); 259 return; 260 } 261 262 // Iterate over the files in the directory and scan .xml files 263 File platformFile = null; 264 for (File f : libraryDir.listFiles()) { 265 // We'll read platform.xml last 266 if (f.getPath().endsWith("etc/permissions/platform.xml")) { 267 platformFile = f; 268 continue; 269 } 270 271 if (!f.getPath().endsWith(".xml")) { 272 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring"); 273 continue; 274 } 275 if (!f.canRead()) { 276 Slog.w(TAG, "Permissions library file " + f + " cannot be read"); 277 continue; 278 } 279 280 readPermissionsFromXml(f, permissionFlag); 281 } 282 283 // Read platform permissions last so it will take precedence 284 if (platformFile != null) { 285 readPermissionsFromXml(platformFile, permissionFlag); 286 } 287 } 288 289 private void readPermissionsFromXml(File permFile, int permissionFlag) { 290 FileReader permReader = null; 291 try { 292 permReader = new FileReader(permFile); 293 } catch (FileNotFoundException e) { 294 Slog.w(TAG, "Couldn't find or open permissions file " + permFile); 295 return; 296 } 297 298 final boolean lowRam = ActivityManager.isLowRamDeviceStatic(); 299 300 try { 301 XmlPullParser parser = Xml.newPullParser(); 302 parser.setInput(permReader); 303 304 int type; 305 while ((type=parser.next()) != parser.START_TAG 306 && type != parser.END_DOCUMENT) { 307 ; 308 } 309 310 if (type != parser.START_TAG) { 311 throw new XmlPullParserException("No start tag found"); 312 } 313 314 if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) { 315 throw new XmlPullParserException("Unexpected start tag in " + permFile 316 + ": found " + parser.getName() + ", expected 'permissions' or 'config'"); 317 } 318 319 boolean allowAll = permissionFlag == ALLOW_ALL; 320 boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0; 321 boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0; 322 boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0; 323 boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0; 324 boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS) != 0; 325 while (true) { 326 XmlUtils.nextElement(parser); 327 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) { 328 break; 329 } 330 331 String name = parser.getName(); 332 if ("group".equals(name) && allowAll) { 333 String gidStr = parser.getAttributeValue(null, "gid"); 334 if (gidStr != null) { 335 int gid = android.os.Process.getGidForName(gidStr); 336 mGlobalGids = appendInt(mGlobalGids, gid); 337 } else { 338 Slog.w(TAG, "<group> without gid in " + permFile + " at " 339 + parser.getPositionDescription()); 340 } 341 342 XmlUtils.skipCurrentTag(parser); 343 continue; 344 } else if ("permission".equals(name) && allowPermissions) { 345 String perm = parser.getAttributeValue(null, "name"); 346 if (perm == null) { 347 Slog.w(TAG, "<permission> without name in " + permFile + " at " 348 + parser.getPositionDescription()); 349 XmlUtils.skipCurrentTag(parser); 350 continue; 351 } 352 perm = perm.intern(); 353 readPermission(parser, perm); 354 355 } else if ("assign-permission".equals(name) && allowPermissions) { 356 String perm = parser.getAttributeValue(null, "name"); 357 if (perm == null) { 358 Slog.w(TAG, "<assign-permission> without name in " + permFile + " at " 359 + parser.getPositionDescription()); 360 XmlUtils.skipCurrentTag(parser); 361 continue; 362 } 363 String uidStr = parser.getAttributeValue(null, "uid"); 364 if (uidStr == null) { 365 Slog.w(TAG, "<assign-permission> without uid in " + permFile + " at " 366 + parser.getPositionDescription()); 367 XmlUtils.skipCurrentTag(parser); 368 continue; 369 } 370 int uid = Process.getUidForName(uidStr); 371 if (uid < 0) { 372 Slog.w(TAG, "<assign-permission> with unknown uid \"" 373 + uidStr + " in " + permFile + " at " 374 + parser.getPositionDescription()); 375 XmlUtils.skipCurrentTag(parser); 376 continue; 377 } 378 perm = perm.intern(); 379 ArraySet<String> perms = mSystemPermissions.get(uid); 380 if (perms == null) { 381 perms = new ArraySet<String>(); 382 mSystemPermissions.put(uid, perms); 383 } 384 perms.add(perm); 385 XmlUtils.skipCurrentTag(parser); 386 387 } else if ("library".equals(name) && allowLibs) { 388 String lname = parser.getAttributeValue(null, "name"); 389 String lfile = parser.getAttributeValue(null, "file"); 390 if (lname == null) { 391 Slog.w(TAG, "<library> without name in " + permFile + " at " 392 + parser.getPositionDescription()); 393 } else if (lfile == null) { 394 Slog.w(TAG, "<library> without file in " + permFile + " at " 395 + parser.getPositionDescription()); 396 } else { 397 //Log.i(TAG, "Got library " + lname + " in " + lfile); 398 mSharedLibraries.put(lname, lfile); 399 } 400 XmlUtils.skipCurrentTag(parser); 401 continue; 402 403 } else if ("feature".equals(name) && allowFeatures) { 404 String fname = parser.getAttributeValue(null, "name"); 405 int fversion = XmlUtils.readIntAttribute(parser, "version", 0); 406 boolean allowed; 407 if (!lowRam) { 408 allowed = true; 409 } else { 410 String notLowRam = parser.getAttributeValue(null, "notLowRam"); 411 allowed = !"true".equals(notLowRam); 412 } 413 if (fname == null) { 414 Slog.w(TAG, "<feature> without name in " + permFile + " at " 415 + parser.getPositionDescription()); 416 } else if (allowed) { 417 addFeature(fname, fversion); 418 } 419 XmlUtils.skipCurrentTag(parser); 420 continue; 421 422 } else if ("unavailable-feature".equals(name) && allowFeatures) { 423 String fname = parser.getAttributeValue(null, "name"); 424 if (fname == null) { 425 Slog.w(TAG, "<unavailable-feature> without name in " + permFile + " at " 426 + parser.getPositionDescription()); 427 } else { 428 mUnavailableFeatures.add(fname); 429 } 430 XmlUtils.skipCurrentTag(parser); 431 continue; 432 433 } else if ("allow-in-power-save-except-idle".equals(name) && allowAll) { 434 String pkgname = parser.getAttributeValue(null, "package"); 435 if (pkgname == null) { 436 Slog.w(TAG, "<allow-in-power-save-except-idle> without package in " 437 + permFile + " at " + parser.getPositionDescription()); 438 } else { 439 mAllowInPowerSaveExceptIdle.add(pkgname); 440 } 441 XmlUtils.skipCurrentTag(parser); 442 continue; 443 444 } else if ("allow-in-power-save".equals(name) && allowAll) { 445 String pkgname = parser.getAttributeValue(null, "package"); 446 if (pkgname == null) { 447 Slog.w(TAG, "<allow-in-power-save> without package in " + permFile + " at " 448 + parser.getPositionDescription()); 449 } else { 450 mAllowInPowerSave.add(pkgname); 451 } 452 XmlUtils.skipCurrentTag(parser); 453 continue; 454 455 } else if ("allow-in-data-usage-save".equals(name) && allowAll) { 456 String pkgname = parser.getAttributeValue(null, "package"); 457 if (pkgname == null) { 458 Slog.w(TAG, "<allow-in-data-usage-save> without package in " + permFile 459 + " at " + parser.getPositionDescription()); 460 } else { 461 mAllowInDataUsageSave.add(pkgname); 462 } 463 XmlUtils.skipCurrentTag(parser); 464 continue; 465 466 } else if ("allow-unthrottled-location".equals(name) && allowAll) { 467 String pkgname = parser.getAttributeValue(null, "package"); 468 if (pkgname == null) { 469 Slog.w(TAG, "<allow-unthrottled-location> without package in " 470 + permFile + " at " + parser.getPositionDescription()); 471 } else { 472 mAllowUnthrottledLocation.add(pkgname); 473 } 474 XmlUtils.skipCurrentTag(parser); 475 continue; 476 477 } else if ("allow-implicit-broadcast".equals(name) && allowAll) { 478 String action = parser.getAttributeValue(null, "action"); 479 if (action == null) { 480 Slog.w(TAG, "<allow-implicit-broadcast> without action in " + permFile 481 + " at " + parser.getPositionDescription()); 482 } else { 483 mAllowImplicitBroadcasts.add(action); 484 } 485 XmlUtils.skipCurrentTag(parser); 486 continue; 487 488 } else if ("app-link".equals(name) && allowAppConfigs) { 489 String pkgname = parser.getAttributeValue(null, "package"); 490 if (pkgname == null) { 491 Slog.w(TAG, "<app-link> without package in " + permFile + " at " 492 + parser.getPositionDescription()); 493 } else { 494 mLinkedApps.add(pkgname); 495 } 496 XmlUtils.skipCurrentTag(parser); 497 } else if ("system-user-whitelisted-app".equals(name) && allowAppConfigs) { 498 String pkgname = parser.getAttributeValue(null, "package"); 499 if (pkgname == null) { 500 Slog.w(TAG, "<system-user-whitelisted-app> without package in " + permFile 501 + " at " + parser.getPositionDescription()); 502 } else { 503 mSystemUserWhitelistedApps.add(pkgname); 504 } 505 XmlUtils.skipCurrentTag(parser); 506 } else if ("system-user-blacklisted-app".equals(name) && allowAppConfigs) { 507 String pkgname = parser.getAttributeValue(null, "package"); 508 if (pkgname == null) { 509 Slog.w(TAG, "<system-user-blacklisted-app without package in " + permFile 510 + " at " + parser.getPositionDescription()); 511 } else { 512 mSystemUserBlacklistedApps.add(pkgname); 513 } 514 XmlUtils.skipCurrentTag(parser); 515 } else if ("default-enabled-vr-app".equals(name) && allowAppConfigs) { 516 String pkgname = parser.getAttributeValue(null, "package"); 517 String clsname = parser.getAttributeValue(null, "class"); 518 if (pkgname == null) { 519 Slog.w(TAG, "<default-enabled-vr-app without package in " + permFile 520 + " at " + parser.getPositionDescription()); 521 } else if (clsname == null) { 522 Slog.w(TAG, "<default-enabled-vr-app without class in " + permFile 523 + " at " + parser.getPositionDescription()); 524 } else { 525 mDefaultVrComponents.add(new ComponentName(pkgname, clsname)); 526 } 527 XmlUtils.skipCurrentTag(parser); 528 } else if ("backup-transport-whitelisted-service".equals(name) && allowFeatures) { 529 String serviceName = parser.getAttributeValue(null, "service"); 530 if (serviceName == null) { 531 Slog.w(TAG, "<backup-transport-whitelisted-service> without service in " 532 + permFile + " at " + parser.getPositionDescription()); 533 } else { 534 ComponentName cn = ComponentName.unflattenFromString(serviceName); 535 if (cn == null) { 536 Slog.w(TAG, 537 "<backup-transport-whitelisted-service> with invalid service name " 538 + serviceName + " in "+ permFile 539 + " at " + parser.getPositionDescription()); 540 } else { 541 mBackupTransportWhitelist.add(cn); 542 } 543 } 544 XmlUtils.skipCurrentTag(parser); 545 } else if ("disabled-until-used-preinstalled-carrier-associated-app".equals(name) 546 && allowAppConfigs) { 547 String pkgname = parser.getAttributeValue(null, "package"); 548 String carrierPkgname = parser.getAttributeValue(null, "carrierAppPackage"); 549 if (pkgname == null || carrierPkgname == null) { 550 Slog.w(TAG, "<disabled-until-used-preinstalled-carrier-associated-app" 551 + " without package or carrierAppPackage in " + permFile + " at " 552 + parser.getPositionDescription()); 553 } else { 554 List<String> associatedPkgs = 555 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get( 556 carrierPkgname); 557 if (associatedPkgs == null) { 558 associatedPkgs = new ArrayList<>(); 559 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put( 560 carrierPkgname, associatedPkgs); 561 } 562 associatedPkgs.add(pkgname); 563 } 564 XmlUtils.skipCurrentTag(parser); 565 } else if ("privapp-permissions".equals(name) && allowPrivappPermissions) { 566 readPrivAppPermissions(parser); 567 } else { 568 XmlUtils.skipCurrentTag(parser); 569 continue; 570 } 571 } 572 } catch (XmlPullParserException e) { 573 Slog.w(TAG, "Got exception parsing permissions.", e); 574 } catch (IOException e) { 575 Slog.w(TAG, "Got exception parsing permissions.", e); 576 } finally { 577 IoUtils.closeQuietly(permReader); 578 } 579 580 // Some devices can be field-converted to FBE, so offer to splice in 581 // those features if not already defined by the static config 582 if (StorageManager.isFileEncryptedNativeOnly()) { 583 addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0); 584 addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0); 585 } 586 587 for (String featureName : mUnavailableFeatures) { 588 removeFeature(featureName); 589 } 590 } 591 592 private void addFeature(String name, int version) { 593 FeatureInfo fi = mAvailableFeatures.get(name); 594 if (fi == null) { 595 fi = new FeatureInfo(); 596 fi.name = name; 597 fi.version = version; 598 mAvailableFeatures.put(name, fi); 599 } else { 600 fi.version = Math.max(fi.version, version); 601 } 602 } 603 604 private void removeFeature(String name) { 605 if (mAvailableFeatures.remove(name) != null) { 606 Slog.d(TAG, "Removed unavailable feature " + name); 607 } 608 } 609 610 void readPermission(XmlPullParser parser, String name) 611 throws IOException, XmlPullParserException { 612 if (mPermissions.containsKey(name)) { 613 throw new IllegalStateException("Duplicate permission definition for " + name); 614 } 615 616 final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false); 617 final PermissionEntry perm = new PermissionEntry(name, perUser); 618 mPermissions.put(name, perm); 619 620 int outerDepth = parser.getDepth(); 621 int type; 622 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 623 && (type != XmlPullParser.END_TAG 624 || parser.getDepth() > outerDepth)) { 625 if (type == XmlPullParser.END_TAG 626 || type == XmlPullParser.TEXT) { 627 continue; 628 } 629 630 String tagName = parser.getName(); 631 if ("group".equals(tagName)) { 632 String gidStr = parser.getAttributeValue(null, "gid"); 633 if (gidStr != null) { 634 int gid = Process.getGidForName(gidStr); 635 perm.gids = appendInt(perm.gids, gid); 636 } else { 637 Slog.w(TAG, "<group> without gid at " 638 + parser.getPositionDescription()); 639 } 640 } 641 XmlUtils.skipCurrentTag(parser); 642 } 643 } 644 645 void readPrivAppPermissions(XmlPullParser parser) throws IOException, XmlPullParserException { 646 String packageName = parser.getAttributeValue(null, "package"); 647 if (TextUtils.isEmpty(packageName)) { 648 Slog.w(TAG, "package is required for <privapp-permissions> in " 649 + parser.getPositionDescription()); 650 return; 651 } 652 653 ArraySet<String> permissions = mPrivAppPermissions.get(packageName); 654 if (permissions == null) { 655 permissions = new ArraySet<>(); 656 } 657 int depth = parser.getDepth(); 658 while (XmlUtils.nextElementWithin(parser, depth)) { 659 String name = parser.getName(); 660 if ("permission".equals(name)) { 661 String permName = parser.getAttributeValue(null, "name"); 662 if (TextUtils.isEmpty(permName)) { 663 Slog.w(TAG, "name is required for <permission> in " 664 + parser.getPositionDescription()); 665 continue; 666 } 667 permissions.add(permName); 668 } 669 } 670 mPrivAppPermissions.put(packageName, permissions); 671 } 672 } 673