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.Build; 26 import android.os.Environment; 27 import android.os.Process; 28 import android.os.storage.StorageManager; 29 import android.text.TextUtils; 30 import android.util.ArrayMap; 31 import android.util.ArraySet; 32 import android.util.Slog; 33 import android.util.SparseArray; 34 import android.util.Xml; 35 36 import com.android.internal.util.XmlUtils; 37 38 import libcore.io.IoUtils; 39 40 import org.xmlpull.v1.XmlPullParser; 41 import org.xmlpull.v1.XmlPullParserException; 42 43 import java.io.File; 44 import java.io.FileNotFoundException; 45 import java.io.FileReader; 46 import java.io.IOException; 47 import java.util.ArrayList; 48 import java.util.Collections; 49 import java.util.List; 50 import java.util.Map; 51 52 /** 53 * Loads global system configuration info. 54 */ 55 public class SystemConfig { 56 static final String TAG = "SystemConfig"; 57 58 static SystemConfig sInstance; 59 60 // permission flag, determines which types of configuration are allowed to be read 61 private static final int ALLOW_FEATURES = 0x01; 62 private static final int ALLOW_LIBS = 0x02; 63 private static final int ALLOW_PERMISSIONS = 0x04; 64 private static final int ALLOW_APP_CONFIGS = 0x08; 65 private static final int ALLOW_PRIVAPP_PERMISSIONS = 0x10; 66 private static final int ALLOW_OEM_PERMISSIONS = 0x20; 67 private static final int ALLOW_HIDDENAPI_WHITELISTING = 0x40; 68 private static final int ALLOW_ALL = ~0; 69 70 // Group-ids that are given to all packages as read from etc/permissions/*.xml. 71 int[] mGlobalGids; 72 73 // These are the built-in uid -> permission mappings that were read from the 74 // system configuration files. 75 final SparseArray<ArraySet<String>> mSystemPermissions = new SparseArray<>(); 76 77 // These are the built-in shared libraries that were read from the 78 // system configuration files. Keys are the library names; strings are the 79 // paths to the libraries. 80 final ArrayMap<String, String> mSharedLibraries = new ArrayMap<>(); 81 82 // These are the features this devices supports that were read from the 83 // system configuration files. 84 final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>(); 85 86 // These are the features which this device doesn't support; the OEM 87 // partition uses these to opt-out of features from the system image. 88 final ArraySet<String> mUnavailableFeatures = new ArraySet<>(); 89 90 public static final class PermissionEntry { 91 public final String name; 92 public int[] gids; 93 public boolean perUser; 94 PermissionEntry(String name, boolean perUser)95 PermissionEntry(String name, boolean perUser) { 96 this.name = name; 97 this.perUser = perUser; 98 } 99 } 100 101 // These are the permission -> gid mappings that were read from the 102 // system configuration files. 103 final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>(); 104 105 // These are the packages that are white-listed to be able to run in the 106 // background while in power save mode (but not whitelisted from device idle modes), 107 // as read from the configuration files. 108 final ArraySet<String> mAllowInPowerSaveExceptIdle = new ArraySet<>(); 109 110 // These are the packages that are white-listed to be able to run in the 111 // background while in power save mode, as read from the configuration files. 112 final ArraySet<String> mAllowInPowerSave = new ArraySet<>(); 113 114 // These are the packages that are white-listed to be able to run in the 115 // background while in data-usage save mode, as read from the configuration files. 116 final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>(); 117 118 // These are the packages that are white-listed to be able to run background location 119 // without throttling, as read from the configuration files. 120 final ArraySet<String> mAllowUnthrottledLocation = new ArraySet<>(); 121 122 // These are the action strings of broadcasts which are whitelisted to 123 // be delivered anonymously even to apps which target O+. 124 final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>(); 125 126 // These are the package names of apps which should be in the 'always' 127 // URL-handling state upon factory reset. 128 final ArraySet<String> mLinkedApps = new ArraySet<>(); 129 130 // These are the packages that are whitelisted to be able to run as system user 131 final ArraySet<String> mSystemUserWhitelistedApps = new ArraySet<>(); 132 133 // These are the packages that should not run under system user 134 final ArraySet<String> mSystemUserBlacklistedApps = new ArraySet<>(); 135 136 // These are the components that are enabled by default as VR mode listener services. 137 final ArraySet<ComponentName> mDefaultVrComponents = new ArraySet<>(); 138 139 // These are the permitted backup transport service components 140 final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>(); 141 142 // Package names that are exempted from private API blacklisting 143 final ArraySet<String> mHiddenApiPackageWhitelist = new ArraySet<>(); 144 145 // The list of carrier applications which should be disabled until used. 146 // This function suppresses update notifications for these pre-installed apps. 147 // In SubscriptionInfoUpdater, the listed applications are disabled until used when all of the 148 // following conditions are met. 149 // 1. Not currently carrier-privileged according to the inserted SIM 150 // 2. Pre-installed 151 // 3. In the default state (enabled but not explicitly) 152 // And SubscriptionInfoUpdater undoes this and marks the app enabled when a SIM is inserted 153 // that marks the app as carrier privileged. It also grants the app default permissions 154 // for Phone and Location. As such, apps MUST only ever be added to this list if they 155 // obtain user consent to access their location through other means. 156 final ArraySet<String> mDisabledUntilUsedPreinstalledCarrierApps = new ArraySet<>(); 157 158 // These are the packages of carrier-associated apps which should be disabled until used until 159 // a SIM is inserted which grants carrier privileges to that carrier app. 160 final ArrayMap<String, List<String>> mDisabledUntilUsedPreinstalledCarrierAssociatedApps = 161 new ArrayMap<>(); 162 163 final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>(); 164 final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>(); 165 166 final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>(); 167 final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>(); 168 169 final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>(); 170 final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>(); 171 172 final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>(); 173 getInstance()174 public static SystemConfig getInstance() { 175 synchronized (SystemConfig.class) { 176 if (sInstance == null) { 177 sInstance = new SystemConfig(); 178 } 179 return sInstance; 180 } 181 } 182 getGlobalGids()183 public int[] getGlobalGids() { 184 return mGlobalGids; 185 } 186 getSystemPermissions()187 public SparseArray<ArraySet<String>> getSystemPermissions() { 188 return mSystemPermissions; 189 } 190 getSharedLibraries()191 public ArrayMap<String, String> getSharedLibraries() { 192 return mSharedLibraries; 193 } 194 getAvailableFeatures()195 public ArrayMap<String, FeatureInfo> getAvailableFeatures() { 196 return mAvailableFeatures; 197 } 198 getPermissions()199 public ArrayMap<String, PermissionEntry> getPermissions() { 200 return mPermissions; 201 } 202 getAllowImplicitBroadcasts()203 public ArraySet<String> getAllowImplicitBroadcasts() { 204 return mAllowImplicitBroadcasts; 205 } 206 getAllowInPowerSaveExceptIdle()207 public ArraySet<String> getAllowInPowerSaveExceptIdle() { 208 return mAllowInPowerSaveExceptIdle; 209 } 210 getAllowInPowerSave()211 public ArraySet<String> getAllowInPowerSave() { 212 return mAllowInPowerSave; 213 } 214 getAllowInDataUsageSave()215 public ArraySet<String> getAllowInDataUsageSave() { 216 return mAllowInDataUsageSave; 217 } 218 getAllowUnthrottledLocation()219 public ArraySet<String> getAllowUnthrottledLocation() { 220 return mAllowUnthrottledLocation; 221 } 222 getLinkedApps()223 public ArraySet<String> getLinkedApps() { 224 return mLinkedApps; 225 } 226 getSystemUserWhitelistedApps()227 public ArraySet<String> getSystemUserWhitelistedApps() { 228 return mSystemUserWhitelistedApps; 229 } 230 getSystemUserBlacklistedApps()231 public ArraySet<String> getSystemUserBlacklistedApps() { 232 return mSystemUserBlacklistedApps; 233 } 234 getHiddenApiWhitelistedApps()235 public ArraySet<String> getHiddenApiWhitelistedApps() { 236 return mHiddenApiPackageWhitelist; 237 } 238 getDefaultVrComponents()239 public ArraySet<ComponentName> getDefaultVrComponents() { 240 return mDefaultVrComponents; 241 } 242 getBackupTransportWhitelist()243 public ArraySet<ComponentName> getBackupTransportWhitelist() { 244 return mBackupTransportWhitelist; 245 } 246 getDisabledUntilUsedPreinstalledCarrierApps()247 public ArraySet<String> getDisabledUntilUsedPreinstalledCarrierApps() { 248 return mDisabledUntilUsedPreinstalledCarrierApps; 249 } 250 getDisabledUntilUsedPreinstalledCarrierAssociatedApps()251 public ArrayMap<String, List<String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps() { 252 return mDisabledUntilUsedPreinstalledCarrierAssociatedApps; 253 } 254 getPrivAppPermissions(String packageName)255 public ArraySet<String> getPrivAppPermissions(String packageName) { 256 return mPrivAppPermissions.get(packageName); 257 } 258 getPrivAppDenyPermissions(String packageName)259 public ArraySet<String> getPrivAppDenyPermissions(String packageName) { 260 return mPrivAppDenyPermissions.get(packageName); 261 } 262 getVendorPrivAppPermissions(String packageName)263 public ArraySet<String> getVendorPrivAppPermissions(String packageName) { 264 return mVendorPrivAppPermissions.get(packageName); 265 } 266 getVendorPrivAppDenyPermissions(String packageName)267 public ArraySet<String> getVendorPrivAppDenyPermissions(String packageName) { 268 return mVendorPrivAppDenyPermissions.get(packageName); 269 } 270 getProductPrivAppPermissions(String packageName)271 public ArraySet<String> getProductPrivAppPermissions(String packageName) { 272 return mProductPrivAppPermissions.get(packageName); 273 } 274 getProductPrivAppDenyPermissions(String packageName)275 public ArraySet<String> getProductPrivAppDenyPermissions(String packageName) { 276 return mProductPrivAppDenyPermissions.get(packageName); 277 } 278 getOemPermissions(String packageName)279 public Map<String, Boolean> getOemPermissions(String packageName) { 280 final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName); 281 if (oemPermissions != null) { 282 return oemPermissions; 283 } 284 return Collections.emptyMap(); 285 } 286 SystemConfig()287 SystemConfig() { 288 // Read configuration from system 289 readPermissions(Environment.buildPath( 290 Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL); 291 292 // Read configuration from the old permissions dir 293 readPermissions(Environment.buildPath( 294 Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL); 295 296 // Vendors are only allowed to customze libs, features and privapp permissions 297 int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS; 298 if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) { 299 // For backward compatibility 300 vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS); 301 } 302 readPermissions(Environment.buildPath( 303 Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag); 304 readPermissions(Environment.buildPath( 305 Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag); 306 307 // Allow ODM to customize system configs as much as Vendor, because /odm is another 308 // vendor partition other than /vendor. 309 int odmPermissionFlag = vendorPermissionFlag; 310 readPermissions(Environment.buildPath( 311 Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag); 312 readPermissions(Environment.buildPath( 313 Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag); 314 315 // Allow OEM to customize features and OEM permissions 316 int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS; 317 readPermissions(Environment.buildPath( 318 Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag); 319 readPermissions(Environment.buildPath( 320 Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag); 321 322 // Allow Product to customize system configs around libs, features, permissions and apps 323 int productPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS | 324 ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS; 325 readPermissions(Environment.buildPath( 326 Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag); 327 readPermissions(Environment.buildPath( 328 Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag); 329 } 330 readPermissions(File libraryDir, int permissionFlag)331 void readPermissions(File libraryDir, int permissionFlag) { 332 // Read permissions from given directory. 333 if (!libraryDir.exists() || !libraryDir.isDirectory()) { 334 if (permissionFlag == ALLOW_ALL) { 335 Slog.w(TAG, "No directory " + libraryDir + ", skipping"); 336 } 337 return; 338 } 339 if (!libraryDir.canRead()) { 340 Slog.w(TAG, "Directory " + libraryDir + " cannot be read"); 341 return; 342 } 343 344 // Iterate over the files in the directory and scan .xml files 345 File platformFile = null; 346 for (File f : libraryDir.listFiles()) { 347 // We'll read platform.xml last 348 if (f.getPath().endsWith("etc/permissions/platform.xml")) { 349 platformFile = f; 350 continue; 351 } 352 353 if (!f.getPath().endsWith(".xml")) { 354 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring"); 355 continue; 356 } 357 if (!f.canRead()) { 358 Slog.w(TAG, "Permissions library file " + f + " cannot be read"); 359 continue; 360 } 361 362 readPermissionsFromXml(f, permissionFlag); 363 } 364 365 // Read platform permissions last so it will take precedence 366 if (platformFile != null) { 367 readPermissionsFromXml(platformFile, permissionFlag); 368 } 369 } 370 readPermissionsFromXml(File permFile, int permissionFlag)371 private void readPermissionsFromXml(File permFile, int permissionFlag) { 372 FileReader permReader = null; 373 try { 374 permReader = new FileReader(permFile); 375 } catch (FileNotFoundException e) { 376 Slog.w(TAG, "Couldn't find or open permissions file " + permFile); 377 return; 378 } 379 380 final boolean lowRam = ActivityManager.isLowRamDeviceStatic(); 381 382 try { 383 XmlPullParser parser = Xml.newPullParser(); 384 parser.setInput(permReader); 385 386 int type; 387 while ((type=parser.next()) != parser.START_TAG 388 && type != parser.END_DOCUMENT) { 389 ; 390 } 391 392 if (type != parser.START_TAG) { 393 throw new XmlPullParserException("No start tag found"); 394 } 395 396 if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) { 397 throw new XmlPullParserException("Unexpected start tag in " + permFile 398 + ": found " + parser.getName() + ", expected 'permissions' or 'config'"); 399 } 400 401 boolean allowAll = permissionFlag == ALLOW_ALL; 402 boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0; 403 boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0; 404 boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0; 405 boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0; 406 boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS) != 0; 407 boolean allowOemPermissions = (permissionFlag & ALLOW_OEM_PERMISSIONS) != 0; 408 boolean allowApiWhitelisting = (permissionFlag & ALLOW_HIDDENAPI_WHITELISTING) != 0; 409 while (true) { 410 XmlUtils.nextElement(parser); 411 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) { 412 break; 413 } 414 415 String name = parser.getName(); 416 if ("group".equals(name) && allowAll) { 417 String gidStr = parser.getAttributeValue(null, "gid"); 418 if (gidStr != null) { 419 int gid = android.os.Process.getGidForName(gidStr); 420 mGlobalGids = appendInt(mGlobalGids, gid); 421 } else { 422 Slog.w(TAG, "<group> without gid in " + permFile + " at " 423 + parser.getPositionDescription()); 424 } 425 426 XmlUtils.skipCurrentTag(parser); 427 continue; 428 } else if ("permission".equals(name) && allowPermissions) { 429 String perm = parser.getAttributeValue(null, "name"); 430 if (perm == null) { 431 Slog.w(TAG, "<permission> without name in " + permFile + " at " 432 + parser.getPositionDescription()); 433 XmlUtils.skipCurrentTag(parser); 434 continue; 435 } 436 perm = perm.intern(); 437 readPermission(parser, perm); 438 439 } else if ("assign-permission".equals(name) && allowPermissions) { 440 String perm = parser.getAttributeValue(null, "name"); 441 if (perm == null) { 442 Slog.w(TAG, "<assign-permission> without name in " + permFile + " at " 443 + parser.getPositionDescription()); 444 XmlUtils.skipCurrentTag(parser); 445 continue; 446 } 447 String uidStr = parser.getAttributeValue(null, "uid"); 448 if (uidStr == null) { 449 Slog.w(TAG, "<assign-permission> without uid in " + permFile + " at " 450 + parser.getPositionDescription()); 451 XmlUtils.skipCurrentTag(parser); 452 continue; 453 } 454 int uid = Process.getUidForName(uidStr); 455 if (uid < 0) { 456 Slog.w(TAG, "<assign-permission> with unknown uid \"" 457 + uidStr + " in " + permFile + " at " 458 + parser.getPositionDescription()); 459 XmlUtils.skipCurrentTag(parser); 460 continue; 461 } 462 perm = perm.intern(); 463 ArraySet<String> perms = mSystemPermissions.get(uid); 464 if (perms == null) { 465 perms = new ArraySet<String>(); 466 mSystemPermissions.put(uid, perms); 467 } 468 perms.add(perm); 469 XmlUtils.skipCurrentTag(parser); 470 471 } else if ("library".equals(name) && allowLibs) { 472 String lname = parser.getAttributeValue(null, "name"); 473 String lfile = parser.getAttributeValue(null, "file"); 474 if (lname == null) { 475 Slog.w(TAG, "<library> without name in " + permFile + " at " 476 + parser.getPositionDescription()); 477 } else if (lfile == null) { 478 Slog.w(TAG, "<library> without file in " + permFile + " at " 479 + parser.getPositionDescription()); 480 } else { 481 //Log.i(TAG, "Got library " + lname + " in " + lfile); 482 mSharedLibraries.put(lname, lfile); 483 } 484 XmlUtils.skipCurrentTag(parser); 485 continue; 486 487 } else if ("feature".equals(name) && allowFeatures) { 488 String fname = parser.getAttributeValue(null, "name"); 489 int fversion = XmlUtils.readIntAttribute(parser, "version", 0); 490 boolean allowed; 491 if (!lowRam) { 492 allowed = true; 493 } else { 494 String notLowRam = parser.getAttributeValue(null, "notLowRam"); 495 allowed = !"true".equals(notLowRam); 496 } 497 if (fname == null) { 498 Slog.w(TAG, "<feature> without name in " + permFile + " at " 499 + parser.getPositionDescription()); 500 } else if (allowed) { 501 addFeature(fname, fversion); 502 } 503 XmlUtils.skipCurrentTag(parser); 504 continue; 505 506 } else if ("unavailable-feature".equals(name) && allowFeatures) { 507 String fname = parser.getAttributeValue(null, "name"); 508 if (fname == null) { 509 Slog.w(TAG, "<unavailable-feature> without name in " + permFile + " at " 510 + parser.getPositionDescription()); 511 } else { 512 mUnavailableFeatures.add(fname); 513 } 514 XmlUtils.skipCurrentTag(parser); 515 continue; 516 517 } else if ("allow-in-power-save-except-idle".equals(name) && allowAll) { 518 String pkgname = parser.getAttributeValue(null, "package"); 519 if (pkgname == null) { 520 Slog.w(TAG, "<allow-in-power-save-except-idle> without package in " 521 + permFile + " at " + parser.getPositionDescription()); 522 } else { 523 mAllowInPowerSaveExceptIdle.add(pkgname); 524 } 525 XmlUtils.skipCurrentTag(parser); 526 continue; 527 528 } else if ("allow-in-power-save".equals(name) && allowAll) { 529 String pkgname = parser.getAttributeValue(null, "package"); 530 if (pkgname == null) { 531 Slog.w(TAG, "<allow-in-power-save> without package in " + permFile + " at " 532 + parser.getPositionDescription()); 533 } else { 534 mAllowInPowerSave.add(pkgname); 535 } 536 XmlUtils.skipCurrentTag(parser); 537 continue; 538 539 } else if ("allow-in-data-usage-save".equals(name) && allowAll) { 540 String pkgname = parser.getAttributeValue(null, "package"); 541 if (pkgname == null) { 542 Slog.w(TAG, "<allow-in-data-usage-save> without package in " + permFile 543 + " at " + parser.getPositionDescription()); 544 } else { 545 mAllowInDataUsageSave.add(pkgname); 546 } 547 XmlUtils.skipCurrentTag(parser); 548 continue; 549 550 } else if ("allow-unthrottled-location".equals(name) && allowAll) { 551 String pkgname = parser.getAttributeValue(null, "package"); 552 if (pkgname == null) { 553 Slog.w(TAG, "<allow-unthrottled-location> without package in " 554 + permFile + " at " + parser.getPositionDescription()); 555 } else { 556 mAllowUnthrottledLocation.add(pkgname); 557 } 558 XmlUtils.skipCurrentTag(parser); 559 continue; 560 561 } else if ("allow-implicit-broadcast".equals(name) && allowAll) { 562 String action = parser.getAttributeValue(null, "action"); 563 if (action == null) { 564 Slog.w(TAG, "<allow-implicit-broadcast> without action in " + permFile 565 + " at " + parser.getPositionDescription()); 566 } else { 567 mAllowImplicitBroadcasts.add(action); 568 } 569 XmlUtils.skipCurrentTag(parser); 570 continue; 571 572 } else if ("app-link".equals(name) && allowAppConfigs) { 573 String pkgname = parser.getAttributeValue(null, "package"); 574 if (pkgname == null) { 575 Slog.w(TAG, "<app-link> without package in " + permFile + " at " 576 + parser.getPositionDescription()); 577 } else { 578 mLinkedApps.add(pkgname); 579 } 580 XmlUtils.skipCurrentTag(parser); 581 } else if ("system-user-whitelisted-app".equals(name) && allowAppConfigs) { 582 String pkgname = parser.getAttributeValue(null, "package"); 583 if (pkgname == null) { 584 Slog.w(TAG, "<system-user-whitelisted-app> without package in " + permFile 585 + " at " + parser.getPositionDescription()); 586 } else { 587 mSystemUserWhitelistedApps.add(pkgname); 588 } 589 XmlUtils.skipCurrentTag(parser); 590 } else if ("system-user-blacklisted-app".equals(name) && allowAppConfigs) { 591 String pkgname = parser.getAttributeValue(null, "package"); 592 if (pkgname == null) { 593 Slog.w(TAG, "<system-user-blacklisted-app without package in " + permFile 594 + " at " + parser.getPositionDescription()); 595 } else { 596 mSystemUserBlacklistedApps.add(pkgname); 597 } 598 XmlUtils.skipCurrentTag(parser); 599 } else if ("default-enabled-vr-app".equals(name) && allowAppConfigs) { 600 String pkgname = parser.getAttributeValue(null, "package"); 601 String clsname = parser.getAttributeValue(null, "class"); 602 if (pkgname == null) { 603 Slog.w(TAG, "<default-enabled-vr-app without package in " + permFile 604 + " at " + parser.getPositionDescription()); 605 } else if (clsname == null) { 606 Slog.w(TAG, "<default-enabled-vr-app without class in " + permFile 607 + " at " + parser.getPositionDescription()); 608 } else { 609 mDefaultVrComponents.add(new ComponentName(pkgname, clsname)); 610 } 611 XmlUtils.skipCurrentTag(parser); 612 } else if ("backup-transport-whitelisted-service".equals(name) && allowFeatures) { 613 String serviceName = parser.getAttributeValue(null, "service"); 614 if (serviceName == null) { 615 Slog.w(TAG, "<backup-transport-whitelisted-service> without service in " 616 + permFile + " at " + parser.getPositionDescription()); 617 } else { 618 ComponentName cn = ComponentName.unflattenFromString(serviceName); 619 if (cn == null) { 620 Slog.w(TAG, 621 "<backup-transport-whitelisted-service> with invalid service name " 622 + serviceName + " in "+ permFile 623 + " at " + parser.getPositionDescription()); 624 } else { 625 mBackupTransportWhitelist.add(cn); 626 } 627 } 628 XmlUtils.skipCurrentTag(parser); 629 } else if ("disabled-until-used-preinstalled-carrier-associated-app".equals(name) 630 && allowAppConfigs) { 631 String pkgname = parser.getAttributeValue(null, "package"); 632 String carrierPkgname = parser.getAttributeValue(null, "carrierAppPackage"); 633 if (pkgname == null || carrierPkgname == null) { 634 Slog.w(TAG, "<disabled-until-used-preinstalled-carrier-associated-app" 635 + " without package or carrierAppPackage in " + permFile + " at " 636 + parser.getPositionDescription()); 637 } else { 638 List<String> associatedPkgs = 639 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get( 640 carrierPkgname); 641 if (associatedPkgs == null) { 642 associatedPkgs = new ArrayList<>(); 643 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put( 644 carrierPkgname, associatedPkgs); 645 } 646 associatedPkgs.add(pkgname); 647 } 648 XmlUtils.skipCurrentTag(parser); 649 } else if ("disabled-until-used-preinstalled-carrier-app".equals(name) 650 && allowAppConfigs) { 651 String pkgname = parser.getAttributeValue(null, "package"); 652 if (pkgname == null) { 653 Slog.w(TAG, 654 "<disabled-until-used-preinstalled-carrier-app> without " 655 + "package in " + permFile + " at " 656 + parser.getPositionDescription()); 657 } else { 658 mDisabledUntilUsedPreinstalledCarrierApps.add(pkgname); 659 } 660 XmlUtils.skipCurrentTag(parser); 661 } else if ("privapp-permissions".equals(name) && allowPrivappPermissions) { 662 // privapp permissions from system, vendor and product partitions are stored 663 // separately. This is to prevent xml files in the vendor partition from 664 // granting permissions to priv apps in the system partition and vice 665 // versa. 666 boolean vendor = permFile.toPath().startsWith( 667 Environment.getVendorDirectory().toPath()) 668 || permFile.toPath().startsWith( 669 Environment.getOdmDirectory().toPath()); 670 boolean product = permFile.toPath().startsWith( 671 Environment.getProductDirectory().toPath()); 672 if (vendor) { 673 readPrivAppPermissions(parser, mVendorPrivAppPermissions, 674 mVendorPrivAppDenyPermissions); 675 } else if (product) { 676 readPrivAppPermissions(parser, mProductPrivAppPermissions, 677 mProductPrivAppDenyPermissions); 678 } else { 679 readPrivAppPermissions(parser, mPrivAppPermissions, 680 mPrivAppDenyPermissions); 681 } 682 } else if ("oem-permissions".equals(name) && allowOemPermissions) { 683 readOemPermissions(parser); 684 } else if ("hidden-api-whitelisted-app".equals(name) && allowApiWhitelisting) { 685 String pkgname = parser.getAttributeValue(null, "package"); 686 if (pkgname == null) { 687 Slog.w(TAG, "<hidden-api-whitelisted-app> without package in " + permFile 688 + " at " + parser.getPositionDescription()); 689 } else { 690 mHiddenApiPackageWhitelist.add(pkgname); 691 } 692 XmlUtils.skipCurrentTag(parser); 693 } else { 694 Slog.w(TAG, "Tag " + name + " is unknown or not allowed in " 695 + permFile.getParent()); 696 XmlUtils.skipCurrentTag(parser); 697 continue; 698 } 699 } 700 } catch (XmlPullParserException e) { 701 Slog.w(TAG, "Got exception parsing permissions.", e); 702 } catch (IOException e) { 703 Slog.w(TAG, "Got exception parsing permissions.", e); 704 } finally { 705 IoUtils.closeQuietly(permReader); 706 } 707 708 // Some devices can be field-converted to FBE, so offer to splice in 709 // those features if not already defined by the static config 710 if (StorageManager.isFileEncryptedNativeOnly()) { 711 addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0); 712 addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0); 713 } 714 715 // Help legacy devices that may not have updated their static config 716 if (StorageManager.hasAdoptable()) { 717 addFeature(PackageManager.FEATURE_ADOPTABLE_STORAGE, 0); 718 } 719 720 if (ActivityManager.isLowRamDeviceStatic()) { 721 addFeature(PackageManager.FEATURE_RAM_LOW, 0); 722 } else { 723 addFeature(PackageManager.FEATURE_RAM_NORMAL, 0); 724 } 725 726 for (String featureName : mUnavailableFeatures) { 727 removeFeature(featureName); 728 } 729 } 730 addFeature(String name, int version)731 private void addFeature(String name, int version) { 732 FeatureInfo fi = mAvailableFeatures.get(name); 733 if (fi == null) { 734 fi = new FeatureInfo(); 735 fi.name = name; 736 fi.version = version; 737 mAvailableFeatures.put(name, fi); 738 } else { 739 fi.version = Math.max(fi.version, version); 740 } 741 } 742 removeFeature(String name)743 private void removeFeature(String name) { 744 if (mAvailableFeatures.remove(name) != null) { 745 Slog.d(TAG, "Removed unavailable feature " + name); 746 } 747 } 748 readPermission(XmlPullParser parser, String name)749 void readPermission(XmlPullParser parser, String name) 750 throws IOException, XmlPullParserException { 751 if (mPermissions.containsKey(name)) { 752 throw new IllegalStateException("Duplicate permission definition for " + name); 753 } 754 755 final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false); 756 final PermissionEntry perm = new PermissionEntry(name, perUser); 757 mPermissions.put(name, perm); 758 759 int outerDepth = parser.getDepth(); 760 int type; 761 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 762 && (type != XmlPullParser.END_TAG 763 || parser.getDepth() > outerDepth)) { 764 if (type == XmlPullParser.END_TAG 765 || type == XmlPullParser.TEXT) { 766 continue; 767 } 768 769 String tagName = parser.getName(); 770 if ("group".equals(tagName)) { 771 String gidStr = parser.getAttributeValue(null, "gid"); 772 if (gidStr != null) { 773 int gid = Process.getGidForName(gidStr); 774 perm.gids = appendInt(perm.gids, gid); 775 } else { 776 Slog.w(TAG, "<group> without gid at " 777 + parser.getPositionDescription()); 778 } 779 } 780 XmlUtils.skipCurrentTag(parser); 781 } 782 } 783 readPrivAppPermissions(XmlPullParser parser, ArrayMap<String, ArraySet<String>> grantMap, ArrayMap<String, ArraySet<String>> denyMap)784 private void readPrivAppPermissions(XmlPullParser parser, 785 ArrayMap<String, ArraySet<String>> grantMap, 786 ArrayMap<String, ArraySet<String>> denyMap) 787 throws IOException, XmlPullParserException { 788 String packageName = parser.getAttributeValue(null, "package"); 789 if (TextUtils.isEmpty(packageName)) { 790 Slog.w(TAG, "package is required for <privapp-permissions> in " 791 + parser.getPositionDescription()); 792 return; 793 } 794 795 ArraySet<String> permissions = grantMap.get(packageName); 796 if (permissions == null) { 797 permissions = new ArraySet<>(); 798 } 799 ArraySet<String> denyPermissions = denyMap.get(packageName); 800 int depth = parser.getDepth(); 801 while (XmlUtils.nextElementWithin(parser, depth)) { 802 String name = parser.getName(); 803 if ("permission".equals(name)) { 804 String permName = parser.getAttributeValue(null, "name"); 805 if (TextUtils.isEmpty(permName)) { 806 Slog.w(TAG, "name is required for <permission> in " 807 + parser.getPositionDescription()); 808 continue; 809 } 810 permissions.add(permName); 811 } else if ("deny-permission".equals(name)) { 812 String permName = parser.getAttributeValue(null, "name"); 813 if (TextUtils.isEmpty(permName)) { 814 Slog.w(TAG, "name is required for <deny-permission> in " 815 + parser.getPositionDescription()); 816 continue; 817 } 818 if (denyPermissions == null) { 819 denyPermissions = new ArraySet<>(); 820 } 821 denyPermissions.add(permName); 822 } 823 } 824 grantMap.put(packageName, permissions); 825 if (denyPermissions != null) { 826 denyMap.put(packageName, denyPermissions); 827 } 828 } 829 readOemPermissions(XmlPullParser parser)830 void readOemPermissions(XmlPullParser parser) throws IOException, XmlPullParserException { 831 final String packageName = parser.getAttributeValue(null, "package"); 832 if (TextUtils.isEmpty(packageName)) { 833 Slog.w(TAG, "package is required for <oem-permissions> in " 834 + parser.getPositionDescription()); 835 return; 836 } 837 838 ArrayMap<String, Boolean> permissions = mOemPermissions.get(packageName); 839 if (permissions == null) { 840 permissions = new ArrayMap<>(); 841 } 842 final int depth = parser.getDepth(); 843 while (XmlUtils.nextElementWithin(parser, depth)) { 844 final String name = parser.getName(); 845 if ("permission".equals(name)) { 846 final String permName = parser.getAttributeValue(null, "name"); 847 if (TextUtils.isEmpty(permName)) { 848 Slog.w(TAG, "name is required for <permission> in " 849 + parser.getPositionDescription()); 850 continue; 851 } 852 permissions.put(permName, Boolean.TRUE); 853 } else if ("deny-permission".equals(name)) { 854 String permName = parser.getAttributeValue(null, "name"); 855 if (TextUtils.isEmpty(permName)) { 856 Slog.w(TAG, "name is required for <deny-permission> in " 857 + parser.getPositionDescription()); 858 continue; 859 } 860 permissions.put(permName, Boolean.FALSE); 861 } 862 } 863 mOemPermissions.put(packageName, permissions); 864 } 865 } 866