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.annotation.NonNull; 22 import android.app.ActivityManager; 23 import android.content.ComponentName; 24 import android.content.pm.FeatureInfo; 25 import android.content.pm.PackageManager; 26 import android.os.Build; 27 import android.os.CarrierAssociatedAppEntry; 28 import android.os.Environment; 29 import android.os.FileUtils; 30 import android.os.Process; 31 import android.os.SystemProperties; 32 import android.os.Trace; 33 import android.os.incremental.IncrementalManager; 34 import android.os.storage.StorageManager; 35 import android.permission.PermissionManager.SplitPermissionInfo; 36 import android.text.TextUtils; 37 import android.util.ArrayMap; 38 import android.util.ArraySet; 39 import android.util.Slog; 40 import android.util.SparseArray; 41 import android.util.TimingsTraceLog; 42 import android.util.Xml; 43 44 import com.android.internal.annotations.VisibleForTesting; 45 import com.android.internal.util.XmlUtils; 46 47 import libcore.io.IoUtils; 48 49 import org.xmlpull.v1.XmlPullParser; 50 import org.xmlpull.v1.XmlPullParserException; 51 52 import java.io.File; 53 import java.io.FileNotFoundException; 54 import java.io.FileReader; 55 import java.io.IOException; 56 import java.util.ArrayList; 57 import java.util.Collections; 58 import java.util.List; 59 import java.util.Map; 60 import java.util.Set; 61 62 /** 63 * Loads global system configuration info. 64 * Note: Initializing this class hits the disk and is slow. This class should generally only be 65 * accessed by the system_server process. 66 */ 67 public class SystemConfig { 68 static final String TAG = "SystemConfig"; 69 70 static SystemConfig sInstance; 71 72 // permission flag, determines which types of configuration are allowed to be read 73 private static final int ALLOW_FEATURES = 0x01; 74 private static final int ALLOW_LIBS = 0x02; 75 private static final int ALLOW_PERMISSIONS = 0x04; 76 private static final int ALLOW_APP_CONFIGS = 0x08; 77 private static final int ALLOW_PRIVAPP_PERMISSIONS = 0x10; 78 private static final int ALLOW_OEM_PERMISSIONS = 0x20; 79 private static final int ALLOW_HIDDENAPI_WHITELISTING = 0x40; 80 private static final int ALLOW_ASSOCIATIONS = 0x80; 81 private static final int ALLOW_ALL = ~0; 82 83 // property for runtime configuration differentiation 84 private static final String SKU_PROPERTY = "ro.boot.product.hardware.sku"; 85 86 // property for runtime configuration differentiation in vendor 87 private static final String VENDOR_SKU_PROPERTY = "ro.boot.product.vendor.sku"; 88 89 // Group-ids that are given to all packages as read from etc/permissions/*.xml. 90 int[] mGlobalGids; 91 92 // These are the built-in uid -> permission mappings that were read from the 93 // system configuration files. 94 final SparseArray<ArraySet<String>> mSystemPermissions = new SparseArray<>(); 95 96 final ArrayList<SplitPermissionInfo> mSplitPermissions = new ArrayList<>(); 97 98 public static final class SharedLibraryEntry { 99 public final String name; 100 public final String filename; 101 public final String[] dependencies; 102 SharedLibraryEntry(String name, String filename, String[] dependencies)103 SharedLibraryEntry(String name, String filename, String[] dependencies) { 104 this.name = name; 105 this.filename = filename; 106 this.dependencies = dependencies; 107 } 108 } 109 110 // These are the built-in shared libraries that were read from the 111 // system configuration files. Keys are the library names; values are 112 // the individual entries that contain information such as filename 113 // and dependencies. 114 final ArrayMap<String, SharedLibraryEntry> mSharedLibraries = new ArrayMap<>(); 115 116 // These are the features this devices supports that were read from the 117 // system configuration files. 118 final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>(); 119 120 // These are the features which this device doesn't support; the OEM 121 // partition uses these to opt-out of features from the system image. 122 final ArraySet<String> mUnavailableFeatures = new ArraySet<>(); 123 124 public static final class PermissionEntry { 125 public final String name; 126 public int[] gids; 127 public boolean perUser; 128 PermissionEntry(String name, boolean perUser)129 PermissionEntry(String name, boolean perUser) { 130 this.name = name; 131 this.perUser = perUser; 132 } 133 } 134 135 // These are the permission -> gid mappings that were read from the 136 // system configuration files. 137 final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>(); 138 139 // These are the packages that are white-listed to be able to run in the 140 // background while in power save mode (but not whitelisted from device idle modes), 141 // as read from the configuration files. 142 final ArraySet<String> mAllowInPowerSaveExceptIdle = new ArraySet<>(); 143 144 // These are the packages that are white-listed to be able to run in the 145 // background while in power save mode, as read from the configuration files. 146 final ArraySet<String> mAllowInPowerSave = new ArraySet<>(); 147 148 // These are the packages that are white-listed to be able to run in the 149 // background while in data-usage save mode, as read from the configuration files. 150 final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>(); 151 152 // These are the packages that are white-listed to be able to run background location 153 // without throttling, as read from the configuration files. 154 final ArraySet<String> mAllowUnthrottledLocation = new ArraySet<>(); 155 156 // These are the packages that are white-listed to be able to retrieve location even when user 157 // location settings are off, for emergency purposes, as read from the configuration files. 158 final ArraySet<String> mAllowIgnoreLocationSettings = new ArraySet<>(); 159 160 // These are the action strings of broadcasts which are whitelisted to 161 // be delivered anonymously even to apps which target O+. 162 final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>(); 163 164 // These are the package names of apps which should be in the 'always' 165 // URL-handling state upon factory reset. 166 final ArraySet<String> mLinkedApps = new ArraySet<>(); 167 168 // These are the packages that are whitelisted to be able to run as system user 169 final ArraySet<String> mSystemUserWhitelistedApps = new ArraySet<>(); 170 171 // These are the packages that should not run under system user 172 final ArraySet<String> mSystemUserBlacklistedApps = new ArraySet<>(); 173 174 // These are the components that are enabled by default as VR mode listener services. 175 final ArraySet<ComponentName> mDefaultVrComponents = new ArraySet<>(); 176 177 // These are the permitted backup transport service components 178 final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>(); 179 180 // These are packages mapped to maps of component class name to default enabled state. 181 final ArrayMap<String, ArrayMap<String, Boolean>> mPackageComponentEnabledState = 182 new ArrayMap<>(); 183 184 // Package names that are exempted from private API blacklisting 185 final ArraySet<String> mHiddenApiPackageWhitelist = new ArraySet<>(); 186 187 // The list of carrier applications which should be disabled until used. 188 // This function suppresses update notifications for these pre-installed apps. 189 // In SubscriptionInfoUpdater, the listed applications are disabled until used when all of the 190 // following conditions are met. 191 // 1. Not currently carrier-privileged according to the inserted SIM 192 // 2. Pre-installed 193 // 3. In the default state (enabled but not explicitly) 194 // And SubscriptionInfoUpdater undoes this and marks the app enabled when a SIM is inserted 195 // that marks the app as carrier privileged. It also grants the app default permissions 196 // for Phone and Location. As such, apps MUST only ever be added to this list if they 197 // obtain user consent to access their location through other means. 198 final ArraySet<String> mDisabledUntilUsedPreinstalledCarrierApps = new ArraySet<>(); 199 200 // These are the packages of carrier-associated apps which should be disabled until used until 201 // a SIM is inserted which grants carrier privileges to that carrier app. 202 final ArrayMap<String, List<CarrierAssociatedAppEntry>> 203 mDisabledUntilUsedPreinstalledCarrierAssociatedApps = new ArrayMap<>(); 204 205 final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>(); 206 final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>(); 207 208 final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>(); 209 final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>(); 210 211 final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>(); 212 final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>(); 213 214 final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppPermissions = new ArrayMap<>(); 215 final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppDenyPermissions = new ArrayMap<>(); 216 217 final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>(); 218 219 // Allowed associations between applications. If there are any entries 220 // for an app, those are the only associations allowed; otherwise, all associations 221 // are allowed. Allowing an association from app A to app B means app A can not 222 // associate with any other apps, but does not limit what apps B can associate with. 223 final ArrayMap<String, ArraySet<String>> mAllowedAssociations = new ArrayMap<>(); 224 225 private final ArraySet<String> mBugreportWhitelistedPackages = new ArraySet<>(); 226 private final ArraySet<String> mAppDataIsolationWhitelistedApps = new ArraySet<>(); 227 228 // Map of packagesNames to userTypes. Stored temporarily until cleared by UserManagerService(). 229 private ArrayMap<String, Set<String>> mPackageToUserTypeWhitelist = new ArrayMap<>(); 230 private ArrayMap<String, Set<String>> mPackageToUserTypeBlacklist = new ArrayMap<>(); 231 232 private final ArraySet<String> mRollbackWhitelistedPackages = new ArraySet<>(); 233 private final ArraySet<String> mWhitelistedStagedInstallers = new ArraySet<>(); 234 235 /** 236 * Map of system pre-defined, uniquely named actors; keys are namespace, 237 * value maps actor name to package name. 238 */ 239 private Map<String, Map<String, String>> mNamedActors = null; 240 getInstance()241 public static SystemConfig getInstance() { 242 if (!isSystemProcess()) { 243 Slog.wtf(TAG, "SystemConfig is being accessed by a process other than " 244 + "system_server."); 245 } 246 247 synchronized (SystemConfig.class) { 248 if (sInstance == null) { 249 sInstance = new SystemConfig(); 250 } 251 return sInstance; 252 } 253 } 254 getGlobalGids()255 public int[] getGlobalGids() { 256 return mGlobalGids; 257 } 258 getSystemPermissions()259 public SparseArray<ArraySet<String>> getSystemPermissions() { 260 return mSystemPermissions; 261 } 262 getSplitPermissions()263 public ArrayList<SplitPermissionInfo> getSplitPermissions() { 264 return mSplitPermissions; 265 } 266 getSharedLibraries()267 public ArrayMap<String, SharedLibraryEntry> getSharedLibraries() { 268 return mSharedLibraries; 269 } 270 getAvailableFeatures()271 public ArrayMap<String, FeatureInfo> getAvailableFeatures() { 272 return mAvailableFeatures; 273 } 274 getPermissions()275 public ArrayMap<String, PermissionEntry> getPermissions() { 276 return mPermissions; 277 } 278 getAllowImplicitBroadcasts()279 public ArraySet<String> getAllowImplicitBroadcasts() { 280 return mAllowImplicitBroadcasts; 281 } 282 getAllowInPowerSaveExceptIdle()283 public ArraySet<String> getAllowInPowerSaveExceptIdle() { 284 return mAllowInPowerSaveExceptIdle; 285 } 286 getAllowInPowerSave()287 public ArraySet<String> getAllowInPowerSave() { 288 return mAllowInPowerSave; 289 } 290 getAllowInDataUsageSave()291 public ArraySet<String> getAllowInDataUsageSave() { 292 return mAllowInDataUsageSave; 293 } 294 getAllowUnthrottledLocation()295 public ArraySet<String> getAllowUnthrottledLocation() { 296 return mAllowUnthrottledLocation; 297 } 298 getAllowIgnoreLocationSettings()299 public ArraySet<String> getAllowIgnoreLocationSettings() { 300 return mAllowIgnoreLocationSettings; 301 } 302 getLinkedApps()303 public ArraySet<String> getLinkedApps() { 304 return mLinkedApps; 305 } 306 getSystemUserWhitelistedApps()307 public ArraySet<String> getSystemUserWhitelistedApps() { 308 return mSystemUserWhitelistedApps; 309 } 310 getSystemUserBlacklistedApps()311 public ArraySet<String> getSystemUserBlacklistedApps() { 312 return mSystemUserBlacklistedApps; 313 } 314 getHiddenApiWhitelistedApps()315 public ArraySet<String> getHiddenApiWhitelistedApps() { 316 return mHiddenApiPackageWhitelist; 317 } 318 getDefaultVrComponents()319 public ArraySet<ComponentName> getDefaultVrComponents() { 320 return mDefaultVrComponents; 321 } 322 getBackupTransportWhitelist()323 public ArraySet<ComponentName> getBackupTransportWhitelist() { 324 return mBackupTransportWhitelist; 325 } 326 getComponentsEnabledStates(String packageName)327 public ArrayMap<String, Boolean> getComponentsEnabledStates(String packageName) { 328 return mPackageComponentEnabledState.get(packageName); 329 } 330 getDisabledUntilUsedPreinstalledCarrierApps()331 public ArraySet<String> getDisabledUntilUsedPreinstalledCarrierApps() { 332 return mDisabledUntilUsedPreinstalledCarrierApps; 333 } 334 335 public ArrayMap<String, List<CarrierAssociatedAppEntry>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps()336 getDisabledUntilUsedPreinstalledCarrierAssociatedApps() { 337 return mDisabledUntilUsedPreinstalledCarrierAssociatedApps; 338 } 339 getPrivAppPermissions(String packageName)340 public ArraySet<String> getPrivAppPermissions(String packageName) { 341 return mPrivAppPermissions.get(packageName); 342 } 343 getPrivAppDenyPermissions(String packageName)344 public ArraySet<String> getPrivAppDenyPermissions(String packageName) { 345 return mPrivAppDenyPermissions.get(packageName); 346 } 347 getVendorPrivAppPermissions(String packageName)348 public ArraySet<String> getVendorPrivAppPermissions(String packageName) { 349 return mVendorPrivAppPermissions.get(packageName); 350 } 351 getVendorPrivAppDenyPermissions(String packageName)352 public ArraySet<String> getVendorPrivAppDenyPermissions(String packageName) { 353 return mVendorPrivAppDenyPermissions.get(packageName); 354 } 355 getProductPrivAppPermissions(String packageName)356 public ArraySet<String> getProductPrivAppPermissions(String packageName) { 357 return mProductPrivAppPermissions.get(packageName); 358 } 359 getProductPrivAppDenyPermissions(String packageName)360 public ArraySet<String> getProductPrivAppDenyPermissions(String packageName) { 361 return mProductPrivAppDenyPermissions.get(packageName); 362 } 363 364 /** 365 * Read from "permission" tags in /system_ext/etc/permissions/*.xml 366 * @return Set of privileged permissions that are explicitly granted. 367 */ getSystemExtPrivAppPermissions(String packageName)368 public ArraySet<String> getSystemExtPrivAppPermissions(String packageName) { 369 return mSystemExtPrivAppPermissions.get(packageName); 370 } 371 372 /** 373 * Read from "deny-permission" tags in /system_ext/etc/permissions/*.xml 374 * @return Set of privileged permissions that are explicitly denied. 375 */ getSystemExtPrivAppDenyPermissions(String packageName)376 public ArraySet<String> getSystemExtPrivAppDenyPermissions(String packageName) { 377 return mSystemExtPrivAppDenyPermissions.get(packageName); 378 } 379 getOemPermissions(String packageName)380 public Map<String, Boolean> getOemPermissions(String packageName) { 381 final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName); 382 if (oemPermissions != null) { 383 return oemPermissions; 384 } 385 return Collections.emptyMap(); 386 } 387 getAllowedAssociations()388 public ArrayMap<String, ArraySet<String>> getAllowedAssociations() { 389 return mAllowedAssociations; 390 } 391 getBugreportWhitelistedPackages()392 public ArraySet<String> getBugreportWhitelistedPackages() { 393 return mBugreportWhitelistedPackages; 394 } 395 getRollbackWhitelistedPackages()396 public Set<String> getRollbackWhitelistedPackages() { 397 return mRollbackWhitelistedPackages; 398 } 399 getWhitelistedStagedInstallers()400 public Set<String> getWhitelistedStagedInstallers() { 401 return mWhitelistedStagedInstallers; 402 } 403 getAppDataIsolationWhitelistedApps()404 public ArraySet<String> getAppDataIsolationWhitelistedApps() { 405 return mAppDataIsolationWhitelistedApps; 406 } 407 408 /** 409 * Gets map of packagesNames to userTypes, dictating on which user types each package should be 410 * initially installed, and then removes this map from SystemConfig. 411 * Called by UserManagerService when it is constructed. 412 */ getAndClearPackageToUserTypeWhitelist()413 public ArrayMap<String, Set<String>> getAndClearPackageToUserTypeWhitelist() { 414 ArrayMap<String, Set<String>> r = mPackageToUserTypeWhitelist; 415 mPackageToUserTypeWhitelist = new ArrayMap<>(0); 416 return r; 417 } 418 419 /** 420 * Gets map of packagesNames to userTypes, dictating on which user types each package should NOT 421 * be initially installed, even if they are whitelisted, and then removes this map from 422 * SystemConfig. 423 * Called by UserManagerService when it is constructed. 424 */ getAndClearPackageToUserTypeBlacklist()425 public ArrayMap<String, Set<String>> getAndClearPackageToUserTypeBlacklist() { 426 ArrayMap<String, Set<String>> r = mPackageToUserTypeBlacklist; 427 mPackageToUserTypeBlacklist = new ArrayMap<>(0); 428 return r; 429 } 430 431 @NonNull getNamedActors()432 public Map<String, Map<String, String>> getNamedActors() { 433 return mNamedActors != null ? mNamedActors : Collections.emptyMap(); 434 } 435 436 /** 437 * Only use for testing. Do NOT use in production code. 438 * @param readPermissions false to create an empty SystemConfig; true to read the permissions. 439 */ 440 @VisibleForTesting SystemConfig(boolean readPermissions)441 public SystemConfig(boolean readPermissions) { 442 if (readPermissions) { 443 Slog.w(TAG, "Constructing a test SystemConfig"); 444 readAllPermissions(); 445 } else { 446 Slog.w(TAG, "Constructing an empty test SystemConfig"); 447 } 448 } 449 SystemConfig()450 SystemConfig() { 451 TimingsTraceLog log = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER); 452 log.traceBegin("readAllPermissions"); 453 try { 454 readAllPermissions(); 455 } finally { 456 log.traceEnd(); 457 } 458 } 459 readAllPermissions()460 private void readAllPermissions() { 461 // Read configuration from system 462 readPermissions(Environment.buildPath( 463 Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL); 464 465 // Read configuration from the old permissions dir 466 readPermissions(Environment.buildPath( 467 Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL); 468 469 // Vendors are only allowed to customize these 470 int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS 471 | ALLOW_ASSOCIATIONS; 472 if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) { 473 // For backward compatibility 474 vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS); 475 } 476 readPermissions(Environment.buildPath( 477 Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag); 478 readPermissions(Environment.buildPath( 479 Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag); 480 481 String vendorSkuProperty = SystemProperties.get(VENDOR_SKU_PROPERTY, ""); 482 if (!vendorSkuProperty.isEmpty()) { 483 String vendorSkuDir = "sku_" + vendorSkuProperty; 484 readPermissions(Environment.buildPath( 485 Environment.getVendorDirectory(), "etc", "sysconfig", vendorSkuDir), 486 vendorPermissionFlag); 487 readPermissions(Environment.buildPath( 488 Environment.getVendorDirectory(), "etc", "permissions", vendorSkuDir), 489 vendorPermissionFlag); 490 } 491 492 // Allow ODM to customize system configs as much as Vendor, because /odm is another 493 // vendor partition other than /vendor. 494 int odmPermissionFlag = vendorPermissionFlag; 495 readPermissions(Environment.buildPath( 496 Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag); 497 readPermissions(Environment.buildPath( 498 Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag); 499 500 String skuProperty = SystemProperties.get(SKU_PROPERTY, ""); 501 if (!skuProperty.isEmpty()) { 502 String skuDir = "sku_" + skuProperty; 503 504 readPermissions(Environment.buildPath( 505 Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag); 506 readPermissions(Environment.buildPath( 507 Environment.getOdmDirectory(), "etc", "permissions", skuDir), 508 odmPermissionFlag); 509 } 510 511 // Allow OEM to customize these 512 int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS | ALLOW_ASSOCIATIONS; 513 readPermissions(Environment.buildPath( 514 Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag); 515 readPermissions(Environment.buildPath( 516 Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag); 517 518 // Allow Product to customize all system configs 519 readPermissions(Environment.buildPath( 520 Environment.getProductDirectory(), "etc", "sysconfig"), ALLOW_ALL); 521 readPermissions(Environment.buildPath( 522 Environment.getProductDirectory(), "etc", "permissions"), ALLOW_ALL); 523 524 // Allow /system_ext to customize all system configs 525 readPermissions(Environment.buildPath( 526 Environment.getSystemExtDirectory(), "etc", "sysconfig"), ALLOW_ALL); 527 readPermissions(Environment.buildPath( 528 Environment.getSystemExtDirectory(), "etc", "permissions"), ALLOW_ALL); 529 530 // Skip loading configuration from apex if it is not a system process. 531 if (!isSystemProcess()) { 532 return; 533 } 534 // Read configuration of libs from apex module. 535 // TODO: Use a solid way to filter apex module folders? 536 for (File f: FileUtils.listFilesOrEmpty(Environment.getApexDirectory())) { 537 if (f.isFile() || f.getPath().contains("@")) { 538 continue; 539 } 540 readPermissions(Environment.buildPath(f, "etc", "permissions"), ALLOW_LIBS); 541 } 542 } 543 544 @VisibleForTesting readPermissions(File libraryDir, int permissionFlag)545 public void readPermissions(File libraryDir, int permissionFlag) { 546 // Read permissions from given directory. 547 if (!libraryDir.exists() || !libraryDir.isDirectory()) { 548 if (permissionFlag == ALLOW_ALL) { 549 Slog.w(TAG, "No directory " + libraryDir + ", skipping"); 550 } 551 return; 552 } 553 if (!libraryDir.canRead()) { 554 Slog.w(TAG, "Directory " + libraryDir + " cannot be read"); 555 return; 556 } 557 558 // Iterate over the files in the directory and scan .xml files 559 File platformFile = null; 560 for (File f : libraryDir.listFiles()) { 561 if (!f.isFile()) { 562 continue; 563 } 564 565 // We'll read platform.xml last 566 if (f.getPath().endsWith("etc/permissions/platform.xml")) { 567 platformFile = f; 568 continue; 569 } 570 571 if (!f.getPath().endsWith(".xml")) { 572 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring"); 573 continue; 574 } 575 if (!f.canRead()) { 576 Slog.w(TAG, "Permissions library file " + f + " cannot be read"); 577 continue; 578 } 579 580 readPermissionsFromXml(f, permissionFlag); 581 } 582 583 // Read platform permissions last so it will take precedence 584 if (platformFile != null) { 585 readPermissionsFromXml(platformFile, permissionFlag); 586 } 587 } 588 logNotAllowedInPartition(String name, File permFile, XmlPullParser parser)589 private void logNotAllowedInPartition(String name, File permFile, XmlPullParser parser) { 590 Slog.w(TAG, "<" + name + "> not allowed in partition of " 591 + permFile + " at " + parser.getPositionDescription()); 592 } 593 readPermissionsFromXml(File permFile, int permissionFlag)594 private void readPermissionsFromXml(File permFile, int permissionFlag) { 595 FileReader permReader = null; 596 try { 597 permReader = new FileReader(permFile); 598 } catch (FileNotFoundException e) { 599 Slog.w(TAG, "Couldn't find or open permissions file " + permFile); 600 return; 601 } 602 Slog.i(TAG, "Reading permissions from " + permFile); 603 604 final boolean lowRam = ActivityManager.isLowRamDeviceStatic(); 605 606 try { 607 XmlPullParser parser = Xml.newPullParser(); 608 parser.setInput(permReader); 609 610 int type; 611 while ((type=parser.next()) != parser.START_TAG 612 && type != parser.END_DOCUMENT) { 613 ; 614 } 615 616 if (type != parser.START_TAG) { 617 throw new XmlPullParserException("No start tag found"); 618 } 619 620 if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) { 621 throw new XmlPullParserException("Unexpected start tag in " + permFile 622 + ": found " + parser.getName() + ", expected 'permissions' or 'config'"); 623 } 624 625 final boolean allowAll = permissionFlag == ALLOW_ALL; 626 final boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0; 627 final boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0; 628 final boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0; 629 final boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0; 630 final boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS) 631 != 0; 632 final boolean allowOemPermissions = (permissionFlag & ALLOW_OEM_PERMISSIONS) != 0; 633 final boolean allowApiWhitelisting = (permissionFlag & ALLOW_HIDDENAPI_WHITELISTING) 634 != 0; 635 final boolean allowAssociations = (permissionFlag & ALLOW_ASSOCIATIONS) != 0; 636 while (true) { 637 XmlUtils.nextElement(parser); 638 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) { 639 break; 640 } 641 642 String name = parser.getName(); 643 if (name == null) { 644 XmlUtils.skipCurrentTag(parser); 645 continue; 646 } 647 switch (name) { 648 case "group": { 649 if (allowAll) { 650 String gidStr = parser.getAttributeValue(null, "gid"); 651 if (gidStr != null) { 652 int gid = android.os.Process.getGidForName(gidStr); 653 mGlobalGids = appendInt(mGlobalGids, gid); 654 } else { 655 Slog.w(TAG, "<" + name + "> without gid in " + permFile + " at " 656 + parser.getPositionDescription()); 657 } 658 } else { 659 logNotAllowedInPartition(name, permFile, parser); 660 } 661 XmlUtils.skipCurrentTag(parser); 662 } break; 663 case "permission": { 664 if (allowPermissions) { 665 String perm = parser.getAttributeValue(null, "name"); 666 if (perm == null) { 667 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at " 668 + parser.getPositionDescription()); 669 XmlUtils.skipCurrentTag(parser); 670 break; 671 } 672 perm = perm.intern(); 673 readPermission(parser, perm); 674 } else { 675 logNotAllowedInPartition(name, permFile, parser); 676 XmlUtils.skipCurrentTag(parser); 677 } 678 } break; 679 case "assign-permission": { 680 if (allowPermissions) { 681 String perm = parser.getAttributeValue(null, "name"); 682 if (perm == null) { 683 Slog.w(TAG, "<" + name + "> without name in " + permFile 684 + " at " + parser.getPositionDescription()); 685 XmlUtils.skipCurrentTag(parser); 686 break; 687 } 688 String uidStr = parser.getAttributeValue(null, "uid"); 689 if (uidStr == null) { 690 Slog.w(TAG, "<" + name + "> without uid in " + permFile 691 + " at " + parser.getPositionDescription()); 692 XmlUtils.skipCurrentTag(parser); 693 break; 694 } 695 int uid = Process.getUidForName(uidStr); 696 if (uid < 0) { 697 Slog.w(TAG, "<" + name + "> with unknown uid \"" 698 + uidStr + " in " + permFile + " at " 699 + parser.getPositionDescription()); 700 XmlUtils.skipCurrentTag(parser); 701 break; 702 } 703 perm = perm.intern(); 704 ArraySet<String> perms = mSystemPermissions.get(uid); 705 if (perms == null) { 706 perms = new ArraySet<String>(); 707 mSystemPermissions.put(uid, perms); 708 } 709 perms.add(perm); 710 } else { 711 logNotAllowedInPartition(name, permFile, parser); 712 } 713 XmlUtils.skipCurrentTag(parser); 714 } break; 715 case "split-permission": { 716 if (allowPermissions) { 717 readSplitPermission(parser, permFile); 718 } else { 719 logNotAllowedInPartition(name, permFile, parser); 720 XmlUtils.skipCurrentTag(parser); 721 } 722 } break; 723 case "library": { 724 if (allowLibs) { 725 String lname = parser.getAttributeValue(null, "name"); 726 String lfile = parser.getAttributeValue(null, "file"); 727 String ldependency = parser.getAttributeValue(null, "dependency"); 728 if (lname == null) { 729 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at " 730 + parser.getPositionDescription()); 731 } else if (lfile == null) { 732 Slog.w(TAG, "<" + name + "> without file in " + permFile + " at " 733 + parser.getPositionDescription()); 734 } else { 735 //Log.i(TAG, "Got library " + lname + " in " + lfile); 736 SharedLibraryEntry entry = new SharedLibraryEntry(lname, lfile, 737 ldependency == null ? new String[0] : ldependency.split(":")); 738 mSharedLibraries.put(lname, entry); 739 } 740 } else { 741 logNotAllowedInPartition(name, permFile, parser); 742 } 743 XmlUtils.skipCurrentTag(parser); 744 } break; 745 case "feature": { 746 if (allowFeatures) { 747 String fname = parser.getAttributeValue(null, "name"); 748 int fversion = XmlUtils.readIntAttribute(parser, "version", 0); 749 boolean allowed; 750 if (!lowRam) { 751 allowed = true; 752 } else { 753 String notLowRam = parser.getAttributeValue(null, "notLowRam"); 754 allowed = !"true".equals(notLowRam); 755 } 756 if (fname == null) { 757 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at " 758 + parser.getPositionDescription()); 759 } else if (allowed) { 760 addFeature(fname, fversion); 761 } 762 } else { 763 logNotAllowedInPartition(name, permFile, parser); 764 } 765 XmlUtils.skipCurrentTag(parser); 766 } break; 767 case "unavailable-feature": { 768 if (allowFeatures) { 769 String fname = parser.getAttributeValue(null, "name"); 770 if (fname == null) { 771 Slog.w(TAG, "<" + name + "> without name in " + permFile 772 + " at " + parser.getPositionDescription()); 773 } else { 774 mUnavailableFeatures.add(fname); 775 } 776 } else { 777 logNotAllowedInPartition(name, permFile, parser); 778 } 779 XmlUtils.skipCurrentTag(parser); 780 } break; 781 case "allow-in-power-save-except-idle": { 782 if (allowAll) { 783 String pkgname = parser.getAttributeValue(null, "package"); 784 if (pkgname == null) { 785 Slog.w(TAG, "<" + name + "> without package in " 786 + permFile + " at " + parser.getPositionDescription()); 787 } else { 788 mAllowInPowerSaveExceptIdle.add(pkgname); 789 } 790 } else { 791 logNotAllowedInPartition(name, permFile, parser); 792 } 793 XmlUtils.skipCurrentTag(parser); 794 } break; 795 case "allow-in-power-save": { 796 if (allowAll) { 797 String pkgname = parser.getAttributeValue(null, "package"); 798 if (pkgname == null) { 799 Slog.w(TAG, "<" + name + "> without package in " 800 + permFile + " at " + parser.getPositionDescription()); 801 } else { 802 mAllowInPowerSave.add(pkgname); 803 } 804 } else { 805 logNotAllowedInPartition(name, permFile, parser); 806 } 807 XmlUtils.skipCurrentTag(parser); 808 } break; 809 case "allow-in-data-usage-save": { 810 if (allowAll) { 811 String pkgname = parser.getAttributeValue(null, "package"); 812 if (pkgname == null) { 813 Slog.w(TAG, "<" + name + "> without package in " 814 + permFile + " at " + parser.getPositionDescription()); 815 } else { 816 mAllowInDataUsageSave.add(pkgname); 817 } 818 } else { 819 logNotAllowedInPartition(name, permFile, parser); 820 } 821 XmlUtils.skipCurrentTag(parser); 822 } break; 823 case "allow-unthrottled-location": { 824 if (allowAll) { 825 String pkgname = parser.getAttributeValue(null, "package"); 826 if (pkgname == null) { 827 Slog.w(TAG, "<" + name + "> without package in " 828 + permFile + " at " + parser.getPositionDescription()); 829 } else { 830 mAllowUnthrottledLocation.add(pkgname); 831 } 832 } else { 833 logNotAllowedInPartition(name, permFile, parser); 834 } 835 XmlUtils.skipCurrentTag(parser); 836 } break; 837 case "allow-ignore-location-settings": { 838 if (allowAll) { 839 String pkgname = parser.getAttributeValue(null, "package"); 840 if (pkgname == null) { 841 Slog.w(TAG, "<" + name + "> without package in " 842 + permFile + " at " + parser.getPositionDescription()); 843 } else { 844 mAllowIgnoreLocationSettings.add(pkgname); 845 } 846 } else { 847 logNotAllowedInPartition(name, permFile, parser); 848 } 849 XmlUtils.skipCurrentTag(parser); 850 } break; 851 case "allow-implicit-broadcast": { 852 if (allowAll) { 853 String action = parser.getAttributeValue(null, "action"); 854 if (action == null) { 855 Slog.w(TAG, "<" + name + "> without action in " 856 + permFile + " at " + parser.getPositionDescription()); 857 } else { 858 mAllowImplicitBroadcasts.add(action); 859 } 860 } else { 861 logNotAllowedInPartition(name, permFile, parser); 862 } 863 XmlUtils.skipCurrentTag(parser); 864 } break; 865 case "app-link": { 866 if (allowAppConfigs) { 867 String pkgname = parser.getAttributeValue(null, "package"); 868 if (pkgname == null) { 869 Slog.w(TAG, "<" + name + "> without package in " + permFile 870 + " at " + parser.getPositionDescription()); 871 } else { 872 mLinkedApps.add(pkgname); 873 } 874 } else { 875 logNotAllowedInPartition(name, permFile, parser); 876 } 877 XmlUtils.skipCurrentTag(parser); 878 } break; 879 case "system-user-whitelisted-app": { 880 if (allowAppConfigs) { 881 String pkgname = parser.getAttributeValue(null, "package"); 882 if (pkgname == null) { 883 Slog.w(TAG, "<" + name + "> without package in " 884 + permFile + " at " + parser.getPositionDescription()); 885 } else { 886 mSystemUserWhitelistedApps.add(pkgname); 887 } 888 } else { 889 logNotAllowedInPartition(name, permFile, parser); 890 } 891 XmlUtils.skipCurrentTag(parser); 892 } break; 893 case "system-user-blacklisted-app": { 894 if (allowAppConfigs) { 895 String pkgname = parser.getAttributeValue(null, "package"); 896 if (pkgname == null) { 897 Slog.w(TAG, "<" + name + "> without package in " 898 + permFile + " at " + parser.getPositionDescription()); 899 } else { 900 mSystemUserBlacklistedApps.add(pkgname); 901 } 902 } else { 903 logNotAllowedInPartition(name, permFile, parser); 904 } 905 XmlUtils.skipCurrentTag(parser); 906 } break; 907 case "default-enabled-vr-app": { 908 if (allowAppConfigs) { 909 String pkgname = parser.getAttributeValue(null, "package"); 910 String clsname = parser.getAttributeValue(null, "class"); 911 if (pkgname == null) { 912 Slog.w(TAG, "<" + name + "> without package in " 913 + permFile + " at " + parser.getPositionDescription()); 914 } else if (clsname == null) { 915 Slog.w(TAG, "<" + name + "> without class in " 916 + permFile + " at " + parser.getPositionDescription()); 917 } else { 918 mDefaultVrComponents.add(new ComponentName(pkgname, clsname)); 919 } 920 } else { 921 logNotAllowedInPartition(name, permFile, parser); 922 } 923 XmlUtils.skipCurrentTag(parser); 924 } break; 925 case "component-override": { 926 readComponentOverrides(parser, permFile); 927 } break; 928 case "backup-transport-whitelisted-service": { 929 if (allowFeatures) { 930 String serviceName = parser.getAttributeValue(null, "service"); 931 if (serviceName == null) { 932 Slog.w(TAG, "<" + name + "> without service in " 933 + permFile + " at " + parser.getPositionDescription()); 934 } else { 935 ComponentName cn = ComponentName.unflattenFromString(serviceName); 936 if (cn == null) { 937 Slog.w(TAG, "<" + name + "> with invalid service name " 938 + serviceName + " in " + permFile 939 + " at " + parser.getPositionDescription()); 940 } else { 941 mBackupTransportWhitelist.add(cn); 942 } 943 } 944 } else { 945 logNotAllowedInPartition(name, permFile, parser); 946 } 947 XmlUtils.skipCurrentTag(parser); 948 } break; 949 case "disabled-until-used-preinstalled-carrier-associated-app": { 950 if (allowAppConfigs) { 951 String pkgname = parser.getAttributeValue(null, "package"); 952 String carrierPkgname = parser.getAttributeValue(null, 953 "carrierAppPackage"); 954 if (pkgname == null || carrierPkgname == null) { 955 Slog.w(TAG, "<" + name 956 + "> without package or carrierAppPackage in " + permFile 957 + " at " + parser.getPositionDescription()); 958 } else { 959 // APKs added to system images via OTA should specify the addedInSdk 960 // attribute, otherwise they may be enabled-by-default in too many 961 // cases. See CarrierAppUtils for more info. 962 int addedInSdk = CarrierAssociatedAppEntry.SDK_UNSPECIFIED; 963 String addedInSdkStr = parser.getAttributeValue(null, "addedInSdk"); 964 if (!TextUtils.isEmpty(addedInSdkStr)) { 965 try { 966 addedInSdk = Integer.parseInt(addedInSdkStr); 967 } catch (NumberFormatException e) { 968 Slog.w(TAG, "<" + name + "> addedInSdk not an integer in " 969 + permFile + " at " 970 + parser.getPositionDescription()); 971 XmlUtils.skipCurrentTag(parser); 972 break; 973 } 974 } 975 List<CarrierAssociatedAppEntry> associatedPkgs = 976 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get( 977 carrierPkgname); 978 if (associatedPkgs == null) { 979 associatedPkgs = new ArrayList<>(); 980 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put( 981 carrierPkgname, associatedPkgs); 982 } 983 associatedPkgs.add( 984 new CarrierAssociatedAppEntry(pkgname, addedInSdk)); 985 } 986 } else { 987 logNotAllowedInPartition(name, permFile, parser); 988 } 989 XmlUtils.skipCurrentTag(parser); 990 } break; 991 case "disabled-until-used-preinstalled-carrier-app": { 992 if (allowAppConfigs) { 993 String pkgname = parser.getAttributeValue(null, "package"); 994 if (pkgname == null) { 995 Slog.w(TAG, 996 "<" + name + "> without " 997 + "package in " + permFile + " at " 998 + parser.getPositionDescription()); 999 } else { 1000 mDisabledUntilUsedPreinstalledCarrierApps.add(pkgname); 1001 } 1002 } else { 1003 logNotAllowedInPartition(name, permFile, parser); 1004 } 1005 XmlUtils.skipCurrentTag(parser); 1006 } break; 1007 case "privapp-permissions": { 1008 if (allowPrivappPermissions) { 1009 // privapp permissions from system, vendor, product and system_ext 1010 // partitions are stored separately. This is to prevent xml files in 1011 // the vendor partition from granting permissions to priv apps in the 1012 // system partition and vice versa. 1013 boolean vendor = permFile.toPath().startsWith( 1014 Environment.getVendorDirectory().toPath() + "/") 1015 || permFile.toPath().startsWith( 1016 Environment.getOdmDirectory().toPath() + "/"); 1017 boolean product = permFile.toPath().startsWith( 1018 Environment.getProductDirectory().toPath() + "/"); 1019 boolean systemExt = permFile.toPath().startsWith( 1020 Environment.getSystemExtDirectory().toPath() + "/"); 1021 if (vendor) { 1022 readPrivAppPermissions(parser, mVendorPrivAppPermissions, 1023 mVendorPrivAppDenyPermissions); 1024 } else if (product) { 1025 readPrivAppPermissions(parser, mProductPrivAppPermissions, 1026 mProductPrivAppDenyPermissions); 1027 } else if (systemExt) { 1028 readPrivAppPermissions(parser, mSystemExtPrivAppPermissions, 1029 mSystemExtPrivAppDenyPermissions); 1030 } else { 1031 readPrivAppPermissions(parser, mPrivAppPermissions, 1032 mPrivAppDenyPermissions); 1033 } 1034 } else { 1035 logNotAllowedInPartition(name, permFile, parser); 1036 XmlUtils.skipCurrentTag(parser); 1037 } 1038 } break; 1039 case "oem-permissions": { 1040 if (allowOemPermissions) { 1041 readOemPermissions(parser); 1042 } else { 1043 logNotAllowedInPartition(name, permFile, parser); 1044 XmlUtils.skipCurrentTag(parser); 1045 } 1046 } break; 1047 case "hidden-api-whitelisted-app": { 1048 if (allowApiWhitelisting) { 1049 String pkgname = parser.getAttributeValue(null, "package"); 1050 if (pkgname == null) { 1051 Slog.w(TAG, "<" + name + "> without package in " 1052 + permFile + " at " + parser.getPositionDescription()); 1053 } else { 1054 mHiddenApiPackageWhitelist.add(pkgname); 1055 } 1056 } else { 1057 logNotAllowedInPartition(name, permFile, parser); 1058 } 1059 XmlUtils.skipCurrentTag(parser); 1060 } break; 1061 case "allow-association": { 1062 if (allowAssociations) { 1063 String target = parser.getAttributeValue(null, "target"); 1064 if (target == null) { 1065 Slog.w(TAG, "<" + name + "> without target in " + permFile 1066 + " at " + parser.getPositionDescription()); 1067 XmlUtils.skipCurrentTag(parser); 1068 break; 1069 } 1070 String allowed = parser.getAttributeValue(null, "allowed"); 1071 if (allowed == null) { 1072 Slog.w(TAG, "<" + name + "> without allowed in " + permFile 1073 + " at " + parser.getPositionDescription()); 1074 XmlUtils.skipCurrentTag(parser); 1075 break; 1076 } 1077 target = target.intern(); 1078 allowed = allowed.intern(); 1079 ArraySet<String> associations = mAllowedAssociations.get(target); 1080 if (associations == null) { 1081 associations = new ArraySet<>(); 1082 mAllowedAssociations.put(target, associations); 1083 } 1084 Slog.i(TAG, "Adding association: " + target + " <- " + allowed); 1085 associations.add(allowed); 1086 } else { 1087 logNotAllowedInPartition(name, permFile, parser); 1088 } 1089 XmlUtils.skipCurrentTag(parser); 1090 } break; 1091 case "app-data-isolation-whitelisted-app": { 1092 String pkgname = parser.getAttributeValue(null, "package"); 1093 if (pkgname == null) { 1094 Slog.w(TAG, "<" + name + "> without package in " + permFile 1095 + " at " + parser.getPositionDescription()); 1096 } else { 1097 mAppDataIsolationWhitelistedApps.add(pkgname); 1098 } 1099 XmlUtils.skipCurrentTag(parser); 1100 } break; 1101 case "bugreport-whitelisted": { 1102 String pkgname = parser.getAttributeValue(null, "package"); 1103 if (pkgname == null) { 1104 Slog.w(TAG, "<" + name + "> without package in " + permFile 1105 + " at " + parser.getPositionDescription()); 1106 } else { 1107 mBugreportWhitelistedPackages.add(pkgname); 1108 } 1109 XmlUtils.skipCurrentTag(parser); 1110 } break; 1111 case "install-in-user-type": { 1112 // NB: We allow any directory permission to declare install-in-user-type. 1113 readInstallInUserType(parser, 1114 mPackageToUserTypeWhitelist, mPackageToUserTypeBlacklist); 1115 } break; 1116 case "named-actor": { 1117 String namespace = TextUtils.safeIntern( 1118 parser.getAttributeValue(null, "namespace")); 1119 String actorName = parser.getAttributeValue(null, "name"); 1120 String pkgName = TextUtils.safeIntern( 1121 parser.getAttributeValue(null, "package")); 1122 if (TextUtils.isEmpty(namespace)) { 1123 Slog.wtf(TAG, "<" + name + "> without namespace in " + permFile 1124 + " at " + parser.getPositionDescription()); 1125 } else if (TextUtils.isEmpty(actorName)) { 1126 Slog.wtf(TAG, "<" + name + "> without actor name in " + permFile 1127 + " at " + parser.getPositionDescription()); 1128 } else if (TextUtils.isEmpty(pkgName)) { 1129 Slog.wtf(TAG, "<" + name + "> without package name in " + permFile 1130 + " at " + parser.getPositionDescription()); 1131 } else if ("android".equalsIgnoreCase(namespace)) { 1132 throw new IllegalStateException("Defining " + actorName + " as " 1133 + pkgName + " for the android namespace is not allowed"); 1134 } else { 1135 if (mNamedActors == null) { 1136 mNamedActors = new ArrayMap<>(); 1137 } 1138 1139 Map<String, String> nameToPkgMap = mNamedActors.get(namespace); 1140 if (nameToPkgMap == null) { 1141 nameToPkgMap = new ArrayMap<>(); 1142 mNamedActors.put(namespace, nameToPkgMap); 1143 } else if (nameToPkgMap.containsKey(actorName)) { 1144 String existing = nameToPkgMap.get(actorName); 1145 throw new IllegalStateException("Duplicate actor definition for " 1146 + namespace + "/" + actorName 1147 + "; defined as both " + existing + " and " + pkgName); 1148 } 1149 1150 nameToPkgMap.put(actorName, pkgName); 1151 } 1152 XmlUtils.skipCurrentTag(parser); 1153 } break; 1154 case "rollback-whitelisted-app": { 1155 String pkgname = parser.getAttributeValue(null, "package"); 1156 if (pkgname == null) { 1157 Slog.w(TAG, "<" + name + "> without package in " + permFile 1158 + " at " + parser.getPositionDescription()); 1159 } else { 1160 mRollbackWhitelistedPackages.add(pkgname); 1161 } 1162 XmlUtils.skipCurrentTag(parser); 1163 } break; 1164 case "whitelisted-staged-installer": { 1165 if (allowAppConfigs) { 1166 String pkgname = parser.getAttributeValue(null, "package"); 1167 if (pkgname == null) { 1168 Slog.w(TAG, "<" + name + "> without package in " + permFile 1169 + " at " + parser.getPositionDescription()); 1170 } else { 1171 mWhitelistedStagedInstallers.add(pkgname); 1172 } 1173 } else { 1174 logNotAllowedInPartition(name, permFile, parser); 1175 } 1176 XmlUtils.skipCurrentTag(parser); 1177 } break; 1178 default: { 1179 Slog.w(TAG, "Tag " + name + " is unknown in " 1180 + permFile + " at " + parser.getPositionDescription()); 1181 XmlUtils.skipCurrentTag(parser); 1182 } break; 1183 } 1184 } 1185 } catch (XmlPullParserException e) { 1186 Slog.w(TAG, "Got exception parsing permissions.", e); 1187 } catch (IOException e) { 1188 Slog.w(TAG, "Got exception parsing permissions.", e); 1189 } finally { 1190 IoUtils.closeQuietly(permReader); 1191 } 1192 1193 // Some devices can be field-converted to FBE, so offer to splice in 1194 // those features if not already defined by the static config 1195 if (StorageManager.isFileEncryptedNativeOnly()) { 1196 addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0); 1197 addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0); 1198 } 1199 1200 // Help legacy devices that may not have updated their static config 1201 if (StorageManager.hasAdoptable()) { 1202 addFeature(PackageManager.FEATURE_ADOPTABLE_STORAGE, 0); 1203 } 1204 1205 if (ActivityManager.isLowRamDeviceStatic()) { 1206 addFeature(PackageManager.FEATURE_RAM_LOW, 0); 1207 } else { 1208 addFeature(PackageManager.FEATURE_RAM_NORMAL, 0); 1209 } 1210 1211 if (IncrementalManager.isFeatureEnabled()) { 1212 addFeature(PackageManager.FEATURE_INCREMENTAL_DELIVERY, 0); 1213 } 1214 1215 if (PackageManager.APP_ENUMERATION_ENABLED_BY_DEFAULT) { 1216 addFeature(PackageManager.FEATURE_APP_ENUMERATION, 0); 1217 } 1218 1219 if (Build.VERSION.FIRST_SDK_INT >= Build.VERSION_CODES.Q) { 1220 addFeature(PackageManager.FEATURE_IPSEC_TUNNELS, 0); 1221 } 1222 1223 for (String featureName : mUnavailableFeatures) { 1224 removeFeature(featureName); 1225 } 1226 } 1227 addFeature(String name, int version)1228 private void addFeature(String name, int version) { 1229 FeatureInfo fi = mAvailableFeatures.get(name); 1230 if (fi == null) { 1231 fi = new FeatureInfo(); 1232 fi.name = name; 1233 fi.version = version; 1234 mAvailableFeatures.put(name, fi); 1235 } else { 1236 fi.version = Math.max(fi.version, version); 1237 } 1238 } 1239 removeFeature(String name)1240 private void removeFeature(String name) { 1241 if (mAvailableFeatures.remove(name) != null) { 1242 Slog.d(TAG, "Removed unavailable feature " + name); 1243 } 1244 } 1245 readPermission(XmlPullParser parser, String name)1246 void readPermission(XmlPullParser parser, String name) 1247 throws IOException, XmlPullParserException { 1248 if (mPermissions.containsKey(name)) { 1249 throw new IllegalStateException("Duplicate permission definition for " + name); 1250 } 1251 1252 final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false); 1253 final PermissionEntry perm = new PermissionEntry(name, perUser); 1254 mPermissions.put(name, perm); 1255 1256 int outerDepth = parser.getDepth(); 1257 int type; 1258 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 1259 && (type != XmlPullParser.END_TAG 1260 || parser.getDepth() > outerDepth)) { 1261 if (type == XmlPullParser.END_TAG 1262 || type == XmlPullParser.TEXT) { 1263 continue; 1264 } 1265 1266 String tagName = parser.getName(); 1267 if ("group".equals(tagName)) { 1268 String gidStr = parser.getAttributeValue(null, "gid"); 1269 if (gidStr != null) { 1270 int gid = Process.getGidForName(gidStr); 1271 perm.gids = appendInt(perm.gids, gid); 1272 } else { 1273 Slog.w(TAG, "<group> without gid at " 1274 + parser.getPositionDescription()); 1275 } 1276 } 1277 XmlUtils.skipCurrentTag(parser); 1278 } 1279 } 1280 readPrivAppPermissions(XmlPullParser parser, ArrayMap<String, ArraySet<String>> grantMap, ArrayMap<String, ArraySet<String>> denyMap)1281 private void readPrivAppPermissions(XmlPullParser parser, 1282 ArrayMap<String, ArraySet<String>> grantMap, 1283 ArrayMap<String, ArraySet<String>> denyMap) 1284 throws IOException, XmlPullParserException { 1285 String packageName = parser.getAttributeValue(null, "package"); 1286 if (TextUtils.isEmpty(packageName)) { 1287 Slog.w(TAG, "package is required for <privapp-permissions> in " 1288 + parser.getPositionDescription()); 1289 return; 1290 } 1291 1292 ArraySet<String> permissions = grantMap.get(packageName); 1293 if (permissions == null) { 1294 permissions = new ArraySet<>(); 1295 } 1296 ArraySet<String> denyPermissions = denyMap.get(packageName); 1297 int depth = parser.getDepth(); 1298 while (XmlUtils.nextElementWithin(parser, depth)) { 1299 String name = parser.getName(); 1300 if ("permission".equals(name)) { 1301 String permName = parser.getAttributeValue(null, "name"); 1302 if (TextUtils.isEmpty(permName)) { 1303 Slog.w(TAG, "name is required for <permission> in " 1304 + parser.getPositionDescription()); 1305 continue; 1306 } 1307 permissions.add(permName); 1308 } else if ("deny-permission".equals(name)) { 1309 String permName = parser.getAttributeValue(null, "name"); 1310 if (TextUtils.isEmpty(permName)) { 1311 Slog.w(TAG, "name is required for <deny-permission> in " 1312 + parser.getPositionDescription()); 1313 continue; 1314 } 1315 if (denyPermissions == null) { 1316 denyPermissions = new ArraySet<>(); 1317 } 1318 denyPermissions.add(permName); 1319 } 1320 } 1321 grantMap.put(packageName, permissions); 1322 if (denyPermissions != null) { 1323 denyMap.put(packageName, denyPermissions); 1324 } 1325 } 1326 readInstallInUserType(XmlPullParser parser, Map<String, Set<String>> doInstallMap, Map<String, Set<String>> nonInstallMap)1327 private void readInstallInUserType(XmlPullParser parser, 1328 Map<String, Set<String>> doInstallMap, 1329 Map<String, Set<String>> nonInstallMap) 1330 throws IOException, XmlPullParserException { 1331 final String packageName = parser.getAttributeValue(null, "package"); 1332 if (TextUtils.isEmpty(packageName)) { 1333 Slog.w(TAG, "package is required for <install-in-user-type> in " 1334 + parser.getPositionDescription()); 1335 return; 1336 } 1337 1338 Set<String> userTypesYes = doInstallMap.get(packageName); 1339 Set<String> userTypesNo = nonInstallMap.get(packageName); 1340 final int depth = parser.getDepth(); 1341 while (XmlUtils.nextElementWithin(parser, depth)) { 1342 final String name = parser.getName(); 1343 if ("install-in".equals(name)) { 1344 final String userType = parser.getAttributeValue(null, "user-type"); 1345 if (TextUtils.isEmpty(userType)) { 1346 Slog.w(TAG, "user-type is required for <install-in-user-type> in " 1347 + parser.getPositionDescription()); 1348 continue; 1349 } 1350 if (userTypesYes == null) { 1351 userTypesYes = new ArraySet<>(); 1352 doInstallMap.put(packageName, userTypesYes); 1353 } 1354 userTypesYes.add(userType); 1355 } else if ("do-not-install-in".equals(name)) { 1356 final String userType = parser.getAttributeValue(null, "user-type"); 1357 if (TextUtils.isEmpty(userType)) { 1358 Slog.w(TAG, "user-type is required for <install-in-user-type> in " 1359 + parser.getPositionDescription()); 1360 continue; 1361 } 1362 if (userTypesNo == null) { 1363 userTypesNo = new ArraySet<>(); 1364 nonInstallMap.put(packageName, userTypesNo); 1365 } 1366 userTypesNo.add(userType); 1367 } else { 1368 Slog.w(TAG, "unrecognized tag in <install-in-user-type> in " 1369 + parser.getPositionDescription()); 1370 } 1371 } 1372 } 1373 readOemPermissions(XmlPullParser parser)1374 void readOemPermissions(XmlPullParser parser) throws IOException, XmlPullParserException { 1375 final String packageName = parser.getAttributeValue(null, "package"); 1376 if (TextUtils.isEmpty(packageName)) { 1377 Slog.w(TAG, "package is required for <oem-permissions> in " 1378 + parser.getPositionDescription()); 1379 return; 1380 } 1381 1382 ArrayMap<String, Boolean> permissions = mOemPermissions.get(packageName); 1383 if (permissions == null) { 1384 permissions = new ArrayMap<>(); 1385 } 1386 final int depth = parser.getDepth(); 1387 while (XmlUtils.nextElementWithin(parser, depth)) { 1388 final String name = parser.getName(); 1389 if ("permission".equals(name)) { 1390 final String permName = parser.getAttributeValue(null, "name"); 1391 if (TextUtils.isEmpty(permName)) { 1392 Slog.w(TAG, "name is required for <permission> in " 1393 + parser.getPositionDescription()); 1394 continue; 1395 } 1396 permissions.put(permName, Boolean.TRUE); 1397 } else if ("deny-permission".equals(name)) { 1398 String permName = parser.getAttributeValue(null, "name"); 1399 if (TextUtils.isEmpty(permName)) { 1400 Slog.w(TAG, "name is required for <deny-permission> in " 1401 + parser.getPositionDescription()); 1402 continue; 1403 } 1404 permissions.put(permName, Boolean.FALSE); 1405 } 1406 } 1407 mOemPermissions.put(packageName, permissions); 1408 } 1409 readSplitPermission(XmlPullParser parser, File permFile)1410 private void readSplitPermission(XmlPullParser parser, File permFile) 1411 throws IOException, XmlPullParserException { 1412 String splitPerm = parser.getAttributeValue(null, "name"); 1413 if (splitPerm == null) { 1414 Slog.w(TAG, "<split-permission> without name in " + permFile + " at " 1415 + parser.getPositionDescription()); 1416 XmlUtils.skipCurrentTag(parser); 1417 return; 1418 } 1419 String targetSdkStr = parser.getAttributeValue(null, "targetSdk"); 1420 int targetSdk = Build.VERSION_CODES.CUR_DEVELOPMENT + 1; 1421 if (!TextUtils.isEmpty(targetSdkStr)) { 1422 try { 1423 targetSdk = Integer.parseInt(targetSdkStr); 1424 } catch (NumberFormatException e) { 1425 Slog.w(TAG, "<split-permission> targetSdk not an integer in " + permFile + " at " 1426 + parser.getPositionDescription()); 1427 XmlUtils.skipCurrentTag(parser); 1428 return; 1429 } 1430 } 1431 final int depth = parser.getDepth(); 1432 List<String> newPermissions = new ArrayList<>(); 1433 while (XmlUtils.nextElementWithin(parser, depth)) { 1434 String name = parser.getName(); 1435 if ("new-permission".equals(name)) { 1436 final String newName = parser.getAttributeValue(null, "name"); 1437 if (TextUtils.isEmpty(newName)) { 1438 Slog.w(TAG, "name is required for <new-permission> in " 1439 + parser.getPositionDescription()); 1440 continue; 1441 } 1442 newPermissions.add(newName); 1443 } else { 1444 XmlUtils.skipCurrentTag(parser); 1445 } 1446 } 1447 if (!newPermissions.isEmpty()) { 1448 mSplitPermissions.add(new SplitPermissionInfo(splitPerm, newPermissions, targetSdk)); 1449 } 1450 } 1451 readComponentOverrides(XmlPullParser parser, File permFile)1452 private void readComponentOverrides(XmlPullParser parser, File permFile) 1453 throws IOException, XmlPullParserException { 1454 String pkgname = parser.getAttributeValue(null, "package"); 1455 if (pkgname == null) { 1456 Slog.w(TAG, "<component-override> without package in " 1457 + permFile + " at " + parser.getPositionDescription()); 1458 return; 1459 } 1460 1461 pkgname = pkgname.intern(); 1462 1463 final int depth = parser.getDepth(); 1464 while (XmlUtils.nextElementWithin(parser, depth)) { 1465 if ("component".equals(parser.getName())) { 1466 String clsname = parser.getAttributeValue(null, "class"); 1467 String enabled = parser.getAttributeValue(null, "enabled"); 1468 if (clsname == null) { 1469 Slog.w(TAG, "<component> without class in " 1470 + permFile + " at " + parser.getPositionDescription()); 1471 return; 1472 } else if (enabled == null) { 1473 Slog.w(TAG, "<component> without enabled in " 1474 + permFile + " at " + parser.getPositionDescription()); 1475 return; 1476 } 1477 1478 if (clsname.startsWith(".")) { 1479 clsname = pkgname + clsname; 1480 } 1481 1482 clsname = clsname.intern(); 1483 1484 ArrayMap<String, Boolean> componentEnabledStates = 1485 mPackageComponentEnabledState.get(pkgname); 1486 if (componentEnabledStates == null) { 1487 componentEnabledStates = new ArrayMap<>(); 1488 mPackageComponentEnabledState.put(pkgname, 1489 componentEnabledStates); 1490 } 1491 1492 componentEnabledStates.put(clsname, !"false".equals(enabled)); 1493 } 1494 } 1495 } 1496 isSystemProcess()1497 private static boolean isSystemProcess() { 1498 return Process.myUid() == Process.SYSTEM_UID; 1499 } 1500 } 1501