1 /* 2 * Copyright (C) 2022 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.annotation.Nullable; 23 import android.app.ActivityManager; 24 import android.content.ComponentName; 25 import android.content.pm.FeatureInfo; 26 import android.content.pm.PackageManager; 27 import android.content.pm.Signature; 28 import android.content.pm.SignedPackage; 29 import android.os.Build; 30 import android.os.CarrierAssociatedAppEntry; 31 import android.os.Environment; 32 import android.os.FileUtils; 33 import android.os.Process; 34 import android.os.SystemProperties; 35 import android.os.Trace; 36 import android.os.VintfRuntimeInfo; 37 import android.os.incremental.IncrementalManager; 38 import android.os.storage.StorageManager; 39 import android.permission.PermissionManager.SplitPermissionInfo; 40 import android.text.TextUtils; 41 import android.util.ArrayMap; 42 import android.util.ArraySet; 43 import android.util.Slog; 44 import android.util.SparseArray; 45 import android.util.TimingsTraceLog; 46 import android.util.Xml; 47 48 import com.android.internal.annotations.VisibleForTesting; 49 import com.android.internal.util.XmlUtils; 50 import com.android.modules.utils.build.UnboundedSdkLevel; 51 import com.android.server.pm.permission.PermissionAllowlist; 52 53 import libcore.io.IoUtils; 54 import libcore.util.EmptyArray; 55 56 import org.xmlpull.v1.XmlPullParser; 57 import org.xmlpull.v1.XmlPullParserException; 58 59 import java.io.BufferedReader; 60 import java.io.File; 61 import java.io.FileNotFoundException; 62 import java.io.FileReader; 63 import java.io.IOException; 64 import java.nio.file.Files; 65 import java.nio.file.Path; 66 import java.nio.file.Paths; 67 import java.util.ArrayList; 68 import java.util.Collections; 69 import java.util.List; 70 import java.util.Map; 71 import java.util.Set; 72 73 /** 74 * Loads global system configuration info. 75 * Note: Initializing this class hits the disk and is slow. This class should generally only be 76 * accessed by the system_server process. 77 * 78 * @hide 79 */ 80 public class SystemConfig { 81 static final String TAG = "SystemConfig"; 82 83 static SystemConfig sInstance; 84 85 // permission flag, determines which types of configuration are allowed to be read 86 private static final int ALLOW_FEATURES = 0x001; 87 private static final int ALLOW_LIBS = 0x002; 88 private static final int ALLOW_PERMISSIONS = 0x004; 89 private static final int ALLOW_APP_CONFIGS = 0x008; 90 private static final int ALLOW_PRIVAPP_PERMISSIONS = 0x010; 91 private static final int ALLOW_OEM_PERMISSIONS = 0x020; 92 private static final int ALLOW_HIDDENAPI_WHITELISTING = 0x040; 93 private static final int ALLOW_ASSOCIATIONS = 0x080; 94 // ALLOW_OVERRIDE_APP_RESTRICTIONS allows to use "allow-in-power-save-except-idle", 95 // "allow-in-power-save", "allow-in-data-usage-save","allow-unthrottled-location", 96 // "allow-ignore-location-settings" and "allow-adas-location-settings". 97 private static final int ALLOW_OVERRIDE_APP_RESTRICTIONS = 0x100; 98 private static final int ALLOW_IMPLICIT_BROADCASTS = 0x200; 99 private static final int ALLOW_VENDOR_APEX = 0x400; 100 private static final int ALLOW_SIGNATURE_PERMISSIONS = 0x800; 101 private static final int ALLOW_ALL = ~0; 102 103 // property for runtime configuration differentiation 104 private static final String SKU_PROPERTY = "ro.boot.product.hardware.sku"; 105 106 // property for runtime configuration differentiation in vendor 107 private static final String VENDOR_SKU_PROPERTY = "ro.boot.product.vendor.sku"; 108 109 // property for runtime configuration differentation in product 110 private static final String PRODUCT_SKU_PROPERTY = "ro.boot.hardware.sku"; 111 112 private static final ArrayMap<String, ArraySet<String>> EMPTY_PERMISSIONS = 113 new ArrayMap<>(); 114 115 // Group-ids that are given to all packages as read from etc/permissions/*.xml. 116 int[] mGlobalGids = EmptyArray.INT; 117 118 // These are the built-in uid -> permission mappings that were read from the 119 // system configuration files. 120 final SparseArray<ArraySet<String>> mSystemPermissions = new SparseArray<>(); 121 122 final ArrayList<SplitPermissionInfo> mSplitPermissions = new ArrayList<>(); 123 isAtLeastSdkLevel(String version)124 private static boolean isAtLeastSdkLevel(String version) { 125 try { 126 return UnboundedSdkLevel.isAtLeast(version); 127 } catch (IllegalArgumentException e) { 128 // UnboundedSdkLevel throws when it sees a known old codename 129 return false; 130 } 131 } 132 isAtMostSdkLevel(String version)133 private static boolean isAtMostSdkLevel(String version) { 134 try { 135 return UnboundedSdkLevel.isAtMost(version); 136 } catch (IllegalArgumentException e) { 137 // UnboundedSdkLevel throws when it sees a known old codename 138 return true; 139 } 140 } 141 142 public static final class SharedLibraryEntry { 143 public final String name; 144 public final String filename; 145 public final String[] dependencies; 146 147 /** 148 * SDK version this library was added to the BOOTCLASSPATH. 149 * 150 * <p>At the SDK level specified in this field and higher, the apps' uses-library tags for 151 * this library will be ignored, since the library is always available on BOOTCLASSPATH. 152 * 153 * <p>0 means not specified. 154 */ 155 public final String onBootclasspathSince; 156 157 /** 158 * SDK version this library was removed from the BOOTCLASSPATH. 159 * 160 * <p>At the SDK level specified in this field and higher, this library needs to be 161 * explicitly added by apps. For compatibility reasons, when an app 162 * targets an SDK less than the value of this attribute, this library is automatically 163 * added. 164 * 165 * <p>0 means not specified. 166 */ 167 public final String onBootclasspathBefore; 168 169 /** 170 * Declares whether this library can be safely ignored from <uses-library> tags. 171 * 172 * <p> This can happen if the library initially had to be explicitly depended-on using that 173 * tag but has since been moved to the BOOTCLASSPATH which means now is always available 174 * and the tag is no longer required. 175 */ 176 public final boolean canBeSafelyIgnored; 177 178 public final boolean isNative; 179 180 181 @VisibleForTesting SharedLibraryEntry(String name, String filename, String[] dependencies, boolean isNative)182 public SharedLibraryEntry(String name, String filename, String[] dependencies, 183 boolean isNative) { 184 this(name, filename, dependencies, null /* onBootclasspathSince */, 185 null /* onBootclasspathBefore */, isNative); 186 } 187 188 @VisibleForTesting SharedLibraryEntry(String name, String filename, String[] dependencies, String onBootclasspathSince, String onBootclasspathBefore)189 public SharedLibraryEntry(String name, String filename, String[] dependencies, 190 String onBootclasspathSince, String onBootclasspathBefore) { 191 this(name, filename, dependencies, onBootclasspathSince, onBootclasspathBefore, 192 false /* isNative */); 193 } 194 SharedLibraryEntry(String name, String filename, String[] dependencies, String onBootclasspathSince, String onBootclasspathBefore, boolean isNative)195 SharedLibraryEntry(String name, String filename, String[] dependencies, 196 String onBootclasspathSince, String onBootclasspathBefore, boolean isNative) { 197 this.name = name; 198 this.filename = filename; 199 this.dependencies = dependencies; 200 this.onBootclasspathSince = onBootclasspathSince; 201 this.onBootclasspathBefore = onBootclasspathBefore; 202 this.isNative = isNative; 203 204 // this entry can be ignored if either: 205 // - onBootclasspathSince is set and we are at or past that SDK 206 // - onBootclasspathBefore is set and we are before that SDK 207 canBeSafelyIgnored = 208 (this.onBootclasspathSince != null 209 && isAtLeastSdkLevel(this.onBootclasspathSince)) 210 || (this.onBootclasspathBefore != null 211 && !isAtLeastSdkLevel(this.onBootclasspathBefore)); 212 } 213 } 214 215 // These are the built-in shared libraries that were read from the 216 // system configuration files. Keys are the library names; values are 217 // the individual entries that contain information such as filename 218 // and dependencies. 219 final ArrayMap<String, SharedLibraryEntry> mSharedLibraries = new ArrayMap<>(); 220 221 // These are the features this devices supports that were read from the 222 // system configuration files. 223 final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>(); 224 225 // These are the features which this device doesn't support; the OEM 226 // partition uses these to opt-out of features from the system image. 227 final ArraySet<String> mUnavailableFeatures = new ArraySet<>(); 228 229 public static final class PermissionEntry { 230 public final String name; 231 public int[] gids; 232 public boolean perUser; 233 PermissionEntry(String name, boolean perUser)234 PermissionEntry(String name, boolean perUser) { 235 this.name = name; 236 this.perUser = perUser; 237 } 238 } 239 240 // These are the permission -> gid mappings that were read from the 241 // system configuration files. 242 final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>(); 243 244 // These are the packages that are white-listed to be able to run in the 245 // background while in power save mode (but not whitelisted from device idle modes), 246 // as read from the configuration files. 247 final ArraySet<String> mAllowInPowerSaveExceptIdle = new ArraySet<>(); 248 249 // These are the packages that are white-listed to be able to run in the 250 // background while in power save mode, as read from the configuration files. 251 final ArraySet<String> mAllowInPowerSave = new ArraySet<>(); 252 253 // These are the packages that are white-listed to be able to run in the 254 // background while in data-usage save mode, as read from the configuration files. 255 final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>(); 256 257 // These are the packages that are white-listed to be able to run background location 258 // without throttling, as read from the configuration files. 259 final ArraySet<String> mAllowUnthrottledLocation = new ArraySet<>(); 260 261 // These are the packages that are allow-listed to be able to retrieve location when 262 // the location state is driver assistance only. 263 final ArrayMap<String, ArraySet<String>> mAllowAdasSettings = new ArrayMap<>(); 264 265 // These are the packages that are white-listed to be able to retrieve location even when user 266 // location settings are off, for emergency purposes, as read from the configuration files. 267 final ArrayMap<String, ArraySet<String>> mAllowIgnoreLocationSettings = new ArrayMap<>(); 268 269 // These are the packages that are allow-listed to be able to access camera when 270 // the camera privacy state is enabled. 271 final ArraySet<String> mAllowlistCameraPrivacy = new ArraySet<>(); 272 273 // These are the action strings of broadcasts which are whitelisted to 274 // be delivered anonymously even to apps which target O+. 275 final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>(); 276 277 // These are the packages that are exempted from the background restriction applied 278 // by the system automatically, i.e., due to high background current drain. 279 final ArraySet<String> mBgRestrictionExemption = new ArraySet<>(); 280 281 // These are the package names of apps which should be automatically granted domain verification 282 // for all of their domains. The only way these apps can be overridden by the user is by 283 // explicitly disabling overall link handling support in app info. 284 final ArraySet<String> mLinkedApps = new ArraySet<>(); 285 286 // These are the components that are enabled by default as VR mode listener services. 287 final ArraySet<ComponentName> mDefaultVrComponents = new ArraySet<>(); 288 289 // These are the permitted backup transport service components 290 final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>(); 291 292 // These are packages mapped to maps of component class name to default enabled state. 293 final ArrayMap<String, ArrayMap<String, Boolean>> mPackageComponentEnabledState = 294 new ArrayMap<>(); 295 296 // Package names that are exempted from private API blacklisting 297 final ArraySet<String> mHiddenApiPackageWhitelist = new ArraySet<>(); 298 299 // The list of carrier applications which should be disabled until used. 300 // This function suppresses update notifications for these pre-installed apps. 301 // In SubscriptionInfoUpdater, the listed applications are disabled until used when all of the 302 // following conditions are met. 303 // 1. Not currently carrier-privileged according to the inserted SIM 304 // 2. Pre-installed 305 // 3. In the default state (enabled but not explicitly) 306 // And SubscriptionInfoUpdater undoes this and marks the app enabled when a SIM is inserted 307 // that marks the app as carrier privileged. It also grants the app default permissions 308 // for Phone and Location. As such, apps MUST only ever be added to this list if they 309 // obtain user consent to access their location through other means. 310 final ArraySet<String> mDisabledUntilUsedPreinstalledCarrierApps = new ArraySet<>(); 311 312 // These are the packages of carrier-associated apps which should be disabled until used until 313 // a SIM is inserted which grants carrier privileges to that carrier app. 314 final ArrayMap<String, List<CarrierAssociatedAppEntry>> 315 mDisabledUntilUsedPreinstalledCarrierAssociatedApps = new ArrayMap<>(); 316 317 private final PermissionAllowlist mPermissionAllowlist = new PermissionAllowlist(); 318 319 // Allowed associations between applications. If there are any entries 320 // for an app, those are the only associations allowed; otherwise, all associations 321 // are allowed. Allowing an association from app A to app B means app A can not 322 // associate with any other apps, but does not limit what apps B can associate with. 323 final ArrayMap<String, ArraySet<String>> mAllowedAssociations = new ArrayMap<>(); 324 325 private final ArraySet<String> mBugreportWhitelistedPackages = new ArraySet<>(); 326 private final ArraySet<String> mAppDataIsolationWhitelistedApps = new ArraySet<>(); 327 328 // These packages will be set as 'prevent disable', where they are no longer possible 329 // for the end user to disable via settings. This flag should only be used for packages 330 // which meet the 'force or keep enabled apps' policy. 331 private final ArrayList<String> mPreventUserDisablePackages = new ArrayList<>(); 332 333 // Map of packagesNames to userTypes. Stored temporarily until cleared by UserManagerService(). 334 private ArrayMap<String, Set<String>> mPackageToUserTypeWhitelist = new ArrayMap<>(); 335 private ArrayMap<String, Set<String>> mPackageToUserTypeBlacklist = new ArrayMap<>(); 336 337 private final ArraySet<String> mRollbackWhitelistedPackages = new ArraySet<>(); 338 private final ArraySet<String> mWhitelistedStagedInstallers = new ArraySet<>(); 339 // A map from package name of vendor APEXes that can be updated to an installer package name 340 // allowed to install updates for it. 341 private final ArrayMap<String, String> mAllowedVendorApexes = new ArrayMap<>(); 342 // A set of package names that are allowed to use <install-constraints> manifest tag. 343 private final Set<String> mInstallConstraintsAllowlist = new ArraySet<>(); 344 345 private String mModulesInstallerPackageName; 346 // Update ownership for system applications and the installers eligible to update them. 347 private final ArrayMap<String, String> mUpdateOwnersForSystemApps = new ArrayMap<>(); 348 349 // Set of package names that should not be marked as "stopped" during initial device boot 350 // or when adding a new user. A new package not contained in this set will be 351 // marked as stopped by the system 352 @NonNull private final Set<String> mInitialNonStoppedSystemPackages = new ArraySet<>(); 353 354 // Which packages (key) are allowed to join particular SharedUid (value). 355 @NonNull private final ArrayMap<String, String> mPackageToSharedUidAllowList = new ArrayMap<>(); 356 357 // A map of preloaded package names and the path to its app metadata file path. 358 private final ArrayMap<String, String> mAppMetadataFilePaths = new ArrayMap<>(); 359 360 // A set of pre-installed package names that requires strict signature verification once 361 // updated to avoid cached/potentially tampered results. 362 private final Set<String> mPreinstallPackagesWithStrictSignatureCheck = new ArraySet<>(); 363 364 // A set of packages that should be considered "trusted packages" by ECM (Enhanced 365 // Confirmation Mode). "Trusted packages" are exempt from ECM (i.e., they will never be 366 // considered "restricted"). 367 private final ArraySet<SignedPackage> mEnhancedConfirmationTrustedPackages = new ArraySet<>(); 368 369 // A set of packages that should be considered "trusted installers" by ECM (Enhanced 370 // Confirmation Mode). "Trusted installers", and all apps installed by a trusted installer, are 371 // exempt from ECM (i.e., they will never be considered "restricted"). 372 private final ArraySet<SignedPackage> mEnhancedConfirmationTrustedInstallers = new ArraySet<>(); 373 374 /** 375 * Map of system pre-defined, uniquely named actors; keys are namespace, 376 * value maps actor name to package name. 377 */ 378 private Map<String, Map<String, String>> mNamedActors = null; 379 380 // Package name of the package pre-installed on a read-only 381 // partition that is used to verify if an overlay package fulfills 382 // the 'config_signature' policy by comparing their signatures: 383 // if the overlay package is signed with the same certificate as 384 // the package declared in 'overlay-config-signature' tag, then the 385 // overlay package fulfills the 'config_signature' policy. 386 private String mOverlayConfigSignaturePackage; 387 getInstance()388 public static SystemConfig getInstance() { 389 if (!isSystemProcess()) { 390 Slog.wtf(TAG, "SystemConfig is being accessed by a process other than " 391 + "system_server."); 392 } 393 394 synchronized (SystemConfig.class) { 395 if (sInstance == null) { 396 sInstance = new SystemConfig(); 397 } 398 return sInstance; 399 } 400 } 401 getGlobalGids()402 public int[] getGlobalGids() { 403 return mGlobalGids; 404 } 405 getSystemPermissions()406 public SparseArray<ArraySet<String>> getSystemPermissions() { 407 return mSystemPermissions; 408 } 409 getSplitPermissions()410 public ArrayList<SplitPermissionInfo> getSplitPermissions() { 411 return mSplitPermissions; 412 } 413 getSharedLibraries()414 public ArrayMap<String, SharedLibraryEntry> getSharedLibraries() { 415 return mSharedLibraries; 416 } 417 getAvailableFeatures()418 public ArrayMap<String, FeatureInfo> getAvailableFeatures() { 419 return mAvailableFeatures; 420 } 421 getPermissions()422 public ArrayMap<String, PermissionEntry> getPermissions() { 423 return mPermissions; 424 } 425 getAllowImplicitBroadcasts()426 public ArraySet<String> getAllowImplicitBroadcasts() { 427 return mAllowImplicitBroadcasts; 428 } 429 getAllowInPowerSaveExceptIdle()430 public ArraySet<String> getAllowInPowerSaveExceptIdle() { 431 return mAllowInPowerSaveExceptIdle; 432 } 433 getAllowInPowerSave()434 public ArraySet<String> getAllowInPowerSave() { 435 return mAllowInPowerSave; 436 } 437 getAllowInDataUsageSave()438 public ArraySet<String> getAllowInDataUsageSave() { 439 return mAllowInDataUsageSave; 440 } 441 getAllowUnthrottledLocation()442 public ArraySet<String> getAllowUnthrottledLocation() { 443 return mAllowUnthrottledLocation; 444 } 445 getAllowAdasLocationSettings()446 public ArrayMap<String, ArraySet<String>> getAllowAdasLocationSettings() { 447 return mAllowAdasSettings; 448 } 449 getAllowIgnoreLocationSettings()450 public ArrayMap<String, ArraySet<String>> getAllowIgnoreLocationSettings() { 451 return mAllowIgnoreLocationSettings; 452 } 453 getBgRestrictionExemption()454 public ArraySet<String> getBgRestrictionExemption() { 455 return mBgRestrictionExemption; 456 } 457 getLinkedApps()458 public ArraySet<String> getLinkedApps() { 459 return mLinkedApps; 460 } 461 getHiddenApiWhitelistedApps()462 public ArraySet<String> getHiddenApiWhitelistedApps() { 463 return mHiddenApiPackageWhitelist; 464 } 465 getDefaultVrComponents()466 public ArraySet<ComponentName> getDefaultVrComponents() { 467 return mDefaultVrComponents; 468 } 469 getBackupTransportWhitelist()470 public ArraySet<ComponentName> getBackupTransportWhitelist() { 471 return mBackupTransportWhitelist; 472 } 473 getComponentsEnabledStates(String packageName)474 public ArrayMap<String, Boolean> getComponentsEnabledStates(String packageName) { 475 return mPackageComponentEnabledState.get(packageName); 476 } 477 getDisabledUntilUsedPreinstalledCarrierApps()478 public ArraySet<String> getDisabledUntilUsedPreinstalledCarrierApps() { 479 return mDisabledUntilUsedPreinstalledCarrierApps; 480 } 481 482 public ArrayMap<String, List<CarrierAssociatedAppEntry>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps()483 getDisabledUntilUsedPreinstalledCarrierAssociatedApps() { 484 return mDisabledUntilUsedPreinstalledCarrierAssociatedApps; 485 } 486 getPermissionAllowlist()487 public PermissionAllowlist getPermissionAllowlist() { 488 return mPermissionAllowlist; 489 } 490 getAllowedAssociations()491 public ArrayMap<String, ArraySet<String>> getAllowedAssociations() { 492 return mAllowedAssociations; 493 } 494 getCameraPrivacyAllowlist()495 public ArraySet<String> getCameraPrivacyAllowlist() { 496 return mAllowlistCameraPrivacy; 497 } 498 getBugreportWhitelistedPackages()499 public ArraySet<String> getBugreportWhitelistedPackages() { 500 return mBugreportWhitelistedPackages; 501 } 502 getRollbackWhitelistedPackages()503 public Set<String> getRollbackWhitelistedPackages() { 504 return mRollbackWhitelistedPackages; 505 } 506 getWhitelistedStagedInstallers()507 public Set<String> getWhitelistedStagedInstallers() { 508 return mWhitelistedStagedInstallers; 509 } 510 getAllowedVendorApexes()511 public Map<String, String> getAllowedVendorApexes() { 512 return mAllowedVendorApexes; 513 } 514 getInstallConstraintsAllowlist()515 public Set<String> getInstallConstraintsAllowlist() { 516 return mInstallConstraintsAllowlist; 517 } 518 getModulesInstallerPackageName()519 public String getModulesInstallerPackageName() { 520 return mModulesInstallerPackageName; 521 } 522 523 /** 524 * Gets the update owner of the given package from "update-ownership" tags in sysconfig. 525 */ getSystemAppUpdateOwnerPackageName(@onNull String packageName)526 public @Nullable String getSystemAppUpdateOwnerPackageName(@NonNull String packageName) { 527 return mUpdateOwnersForSystemApps.get(packageName); 528 } 529 getAppDataIsolationWhitelistedApps()530 public ArraySet<String> getAppDataIsolationWhitelistedApps() { 531 return mAppDataIsolationWhitelistedApps; 532 } 533 getPreventUserDisablePackages()534 public @NonNull ArrayList<String> getPreventUserDisablePackages() { 535 return mPreventUserDisablePackages; 536 } 537 538 /** 539 * Gets map of packagesNames to userTypes, dictating on which user types each package should be 540 * initially installed, and then removes this map from SystemConfig. 541 * Called by UserManagerService when it is constructed. 542 */ getAndClearPackageToUserTypeWhitelist()543 public ArrayMap<String, Set<String>> getAndClearPackageToUserTypeWhitelist() { 544 ArrayMap<String, Set<String>> r = mPackageToUserTypeWhitelist; 545 mPackageToUserTypeWhitelist = new ArrayMap<>(0); 546 return r; 547 } 548 549 /** 550 * Gets map of packagesNames to userTypes, dictating on which user types each package should NOT 551 * be initially installed, even if they are whitelisted, and then removes this map from 552 * SystemConfig. 553 * Called by UserManagerService when it is constructed. 554 */ getAndClearPackageToUserTypeBlacklist()555 public ArrayMap<String, Set<String>> getAndClearPackageToUserTypeBlacklist() { 556 ArrayMap<String, Set<String>> r = mPackageToUserTypeBlacklist; 557 mPackageToUserTypeBlacklist = new ArrayMap<>(0); 558 return r; 559 } 560 561 @NonNull getNamedActors()562 public Map<String, Map<String, String>> getNamedActors() { 563 return mNamedActors != null ? mNamedActors : Collections.emptyMap(); 564 } 565 566 @Nullable getOverlayConfigSignaturePackage()567 public String getOverlayConfigSignaturePackage() { 568 return TextUtils.isEmpty(mOverlayConfigSignaturePackage) 569 ? null : mOverlayConfigSignaturePackage; 570 } 571 getInitialNonStoppedSystemPackages()572 public Set<String> getInitialNonStoppedSystemPackages() { 573 return mInitialNonStoppedSystemPackages; 574 } 575 576 @NonNull getPackageToSharedUidAllowList()577 public ArrayMap<String, String> getPackageToSharedUidAllowList() { 578 return mPackageToSharedUidAllowList; 579 } 580 getAppMetadataFilePaths()581 public ArrayMap<String, String> getAppMetadataFilePaths() { 582 return mAppMetadataFilePaths; 583 } 584 getPreinstallPackagesWithStrictSignatureCheck()585 public Set<String> getPreinstallPackagesWithStrictSignatureCheck() { 586 return mPreinstallPackagesWithStrictSignatureCheck; 587 } 588 getEnhancedConfirmationTrustedPackages()589 public ArraySet<SignedPackage> getEnhancedConfirmationTrustedPackages() { 590 return mEnhancedConfirmationTrustedPackages; 591 } 592 getEnhancedConfirmationTrustedInstallers()593 public ArraySet<SignedPackage> getEnhancedConfirmationTrustedInstallers() { 594 return mEnhancedConfirmationTrustedInstallers; 595 } 596 597 /** 598 * Only use for testing. Do NOT use in production code. 599 * @param readPermissions false to create an empty SystemConfig; true to read the permissions. 600 */ 601 @VisibleForTesting SystemConfig(boolean readPermissions)602 public SystemConfig(boolean readPermissions) { 603 if (readPermissions) { 604 Slog.w(TAG, "Constructing a test SystemConfig"); 605 readAllPermissions(); 606 } else { 607 Slog.w(TAG, "Constructing an empty test SystemConfig"); 608 } 609 } 610 SystemConfig()611 SystemConfig() { 612 TimingsTraceLog log = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER); 613 log.traceBegin("readAllPermissions"); 614 try { 615 readAllPermissions(); 616 readPublicNativeLibrariesList(); 617 } finally { 618 log.traceEnd(); 619 } 620 } 621 readAllPermissions()622 private void readAllPermissions() { 623 final XmlPullParser parser = Xml.newPullParser(); 624 625 // Read configuration from system 626 readPermissions(parser, Environment.buildPath( 627 Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL); 628 629 // Read configuration from the old permissions dir 630 readPermissions(parser, Environment.buildPath( 631 Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL); 632 633 // Vendors are only allowed to customize these 634 int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS 635 | ALLOW_SIGNATURE_PERMISSIONS | ALLOW_ASSOCIATIONS | ALLOW_VENDOR_APEX; 636 if (Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.O_MR1) { 637 // For backward compatibility 638 vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS); 639 } 640 readPermissions(parser, Environment.buildPath( 641 Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag); 642 readPermissions(parser, Environment.buildPath( 643 Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag); 644 645 String vendorSkuProperty = SystemProperties.get(VENDOR_SKU_PROPERTY, ""); 646 if (!vendorSkuProperty.isEmpty()) { 647 String vendorSkuDir = "sku_" + vendorSkuProperty; 648 readPermissions(parser, Environment.buildPath( 649 Environment.getVendorDirectory(), "etc", "sysconfig", vendorSkuDir), 650 vendorPermissionFlag); 651 readPermissions(parser, Environment.buildPath( 652 Environment.getVendorDirectory(), "etc", "permissions", vendorSkuDir), 653 vendorPermissionFlag); 654 } 655 656 // Allow ODM to customize system configs as much as Vendor, because /odm is another 657 // vendor partition other than /vendor. 658 int odmPermissionFlag = vendorPermissionFlag; 659 readPermissions(parser, Environment.buildPath( 660 Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag); 661 readPermissions(parser, Environment.buildPath( 662 Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag); 663 664 String skuProperty = SystemProperties.get(SKU_PROPERTY, ""); 665 if (!skuProperty.isEmpty()) { 666 String skuDir = "sku_" + skuProperty; 667 668 readPermissions(parser, Environment.buildPath( 669 Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag); 670 readPermissions(parser, Environment.buildPath( 671 Environment.getOdmDirectory(), "etc", "permissions", skuDir), 672 odmPermissionFlag); 673 } 674 675 // Allow OEM to customize these 676 int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS | ALLOW_ASSOCIATIONS 677 | ALLOW_VENDOR_APEX; 678 readPermissions(parser, Environment.buildPath( 679 Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag); 680 readPermissions(parser, Environment.buildPath( 681 Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag); 682 683 // Allow Product to customize these configs 684 // TODO(b/157203468): ALLOW_HIDDENAPI_WHITELISTING must be removed because we prohibited 685 // the use of hidden APIs from the product partition. 686 int productPermissionFlag = ALLOW_FEATURES | ALLOW_LIBS | ALLOW_PERMISSIONS 687 | ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS | ALLOW_SIGNATURE_PERMISSIONS 688 | ALLOW_HIDDENAPI_WHITELISTING | ALLOW_ASSOCIATIONS 689 | ALLOW_OVERRIDE_APP_RESTRICTIONS | ALLOW_IMPLICIT_BROADCASTS | ALLOW_VENDOR_APEX; 690 if (Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.R) { 691 // TODO(b/157393157): This must check product interface enforcement instead of 692 // DEVICE_INITIAL_SDK_INT for the devices without product interface enforcement. 693 productPermissionFlag = ALLOW_ALL; 694 } 695 readPermissions(parser, Environment.buildPath( 696 Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag); 697 readPermissions(parser, Environment.buildPath( 698 Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag); 699 700 String productSkuProperty = SystemProperties.get(PRODUCT_SKU_PROPERTY, ""); 701 if (!productSkuProperty.isEmpty()) { 702 String productSkuDir = "sku_" + productSkuProperty; 703 readPermissions(parser, Environment.buildPath( 704 Environment.getProductDirectory(), "etc", "sysconfig", productSkuDir), 705 productPermissionFlag); 706 readPermissions(parser, Environment.buildPath( 707 Environment.getProductDirectory(), "etc", "permissions", productSkuDir), 708 productPermissionFlag); 709 } 710 711 // Allow /system_ext to customize all system configs 712 readPermissions(parser, Environment.buildPath( 713 Environment.getSystemExtDirectory(), "etc", "sysconfig"), ALLOW_ALL); 714 readPermissions(parser, Environment.buildPath( 715 Environment.getSystemExtDirectory(), "etc", "permissions"), ALLOW_ALL); 716 717 // Skip loading configuration from apex if it is not a system process. 718 if (!isSystemProcess()) { 719 return; 720 } 721 // Read configuration of features, libs and priv-app permissions from apex module. 722 int apexPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS; 723 if (android.permission.flags.Flags.apexSignaturePermissionAllowlistEnabled()) { 724 apexPermissionFlag |= ALLOW_SIGNATURE_PERMISSIONS; 725 } 726 // TODO: Use a solid way to filter apex module folders? 727 for (File f: FileUtils.listFilesOrEmpty(Environment.getApexDirectory())) { 728 if (f.isFile() || f.getPath().contains("@")) { 729 continue; 730 } 731 readPermissions(parser, Environment.buildPath(f, "etc", "permissions"), 732 apexPermissionFlag); 733 } 734 } 735 736 @VisibleForTesting readPermissions(final XmlPullParser parser, File libraryDir, int permissionFlag)737 public void readPermissions(final XmlPullParser parser, File libraryDir, int permissionFlag) { 738 // Read permissions from given directory. 739 if (!libraryDir.exists() || !libraryDir.isDirectory()) { 740 if (permissionFlag == ALLOW_ALL) { 741 Slog.w(TAG, "No directory " + libraryDir + ", skipping"); 742 } 743 return; 744 } 745 if (!libraryDir.canRead()) { 746 Slog.w(TAG, "Directory " + libraryDir + " cannot be read"); 747 return; 748 } 749 750 // Iterate over the files in the directory and scan .xml files 751 File platformFile = null; 752 for (File f : libraryDir.listFiles()) { 753 if (!f.isFile()) { 754 continue; 755 } 756 757 // We'll read platform.xml last 758 if (f.getPath().endsWith("etc/permissions/platform.xml")) { 759 platformFile = f; 760 continue; 761 } 762 763 if (!f.getPath().endsWith(".xml")) { 764 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring"); 765 continue; 766 } 767 if (!f.canRead()) { 768 Slog.w(TAG, "Permissions library file " + f + " cannot be read"); 769 continue; 770 } 771 772 readPermissionsFromXml(parser, f, permissionFlag); 773 } 774 775 // Read platform permissions last so it will take precedence 776 if (platformFile != null) { 777 readPermissionsFromXml(parser, platformFile, permissionFlag); 778 } 779 } 780 logNotAllowedInPartition(String name, File permFile, XmlPullParser parser)781 private void logNotAllowedInPartition(String name, File permFile, XmlPullParser parser) { 782 Slog.w(TAG, "<" + name + "> not allowed in partition of " 783 + permFile + " at " + parser.getPositionDescription()); 784 } 785 readPermissionsFromXml(final XmlPullParser parser, File permFile, int permissionFlag)786 private void readPermissionsFromXml(final XmlPullParser parser, File permFile, 787 int permissionFlag) { 788 final FileReader permReader; 789 try { 790 permReader = new FileReader(permFile); 791 } catch (FileNotFoundException e) { 792 Slog.w(TAG, "Couldn't find or open permissions file " + permFile); 793 return; 794 } 795 Slog.i(TAG, "Reading permissions from " + permFile); 796 797 final boolean lowRam = ActivityManager.isLowRamDeviceStatic(); 798 799 try { 800 parser.setInput(permReader); 801 802 int type; 803 while ((type=parser.next()) != parser.START_TAG 804 && type != parser.END_DOCUMENT) { 805 ; 806 } 807 808 if (type != parser.START_TAG) { 809 throw new XmlPullParserException("No start tag found"); 810 } 811 812 if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) { 813 throw new XmlPullParserException("Unexpected start tag in " + permFile 814 + ": found " + parser.getName() + ", expected 'permissions' or 'config'"); 815 } 816 817 final boolean allowAll = permissionFlag == ALLOW_ALL; 818 final boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0; 819 final boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0; 820 final boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0; 821 final boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0; 822 final boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS) 823 != 0; 824 final boolean allowSignaturePermissions = (permissionFlag & ALLOW_SIGNATURE_PERMISSIONS) 825 != 0; 826 final boolean allowOemPermissions = (permissionFlag & ALLOW_OEM_PERMISSIONS) != 0; 827 final boolean allowApiWhitelisting = (permissionFlag & ALLOW_HIDDENAPI_WHITELISTING) 828 != 0; 829 final boolean allowAssociations = (permissionFlag & ALLOW_ASSOCIATIONS) != 0; 830 final boolean allowOverrideAppRestrictions = 831 (permissionFlag & ALLOW_OVERRIDE_APP_RESTRICTIONS) != 0; 832 final boolean allowImplicitBroadcasts = (permissionFlag & ALLOW_IMPLICIT_BROADCASTS) 833 != 0; 834 final boolean allowVendorApex = (permissionFlag & ALLOW_VENDOR_APEX) != 0; 835 while (true) { 836 XmlUtils.nextElement(parser); 837 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) { 838 break; 839 } 840 841 String name = parser.getName(); 842 if (name == null) { 843 XmlUtils.skipCurrentTag(parser); 844 continue; 845 } 846 switch (name) { 847 case "group": { 848 if (allowAll) { 849 String gidStr = parser.getAttributeValue(null, "gid"); 850 if (gidStr != null) { 851 int gid = android.os.Process.getGidForName(gidStr); 852 mGlobalGids = appendInt(mGlobalGids, gid); 853 } else { 854 Slog.w(TAG, "<" + name + "> without gid in " + permFile + " at " 855 + parser.getPositionDescription()); 856 } 857 } else { 858 logNotAllowedInPartition(name, permFile, parser); 859 } 860 XmlUtils.skipCurrentTag(parser); 861 } break; 862 case "permission": { 863 if (allowPermissions) { 864 String perm = parser.getAttributeValue(null, "name"); 865 if (perm == null) { 866 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at " 867 + parser.getPositionDescription()); 868 XmlUtils.skipCurrentTag(parser); 869 break; 870 } 871 perm = perm.intern(); 872 readPermission(parser, perm); 873 } else { 874 logNotAllowedInPartition(name, permFile, parser); 875 XmlUtils.skipCurrentTag(parser); 876 } 877 } break; 878 case "assign-permission": { 879 if (allowPermissions) { 880 String perm = parser.getAttributeValue(null, "name"); 881 if (perm == null) { 882 Slog.w(TAG, "<" + name + "> without name in " + permFile 883 + " at " + parser.getPositionDescription()); 884 XmlUtils.skipCurrentTag(parser); 885 break; 886 } 887 String uidStr = parser.getAttributeValue(null, "uid"); 888 if (uidStr == null) { 889 Slog.w(TAG, "<" + name + "> without uid in " + permFile 890 + " at " + parser.getPositionDescription()); 891 XmlUtils.skipCurrentTag(parser); 892 break; 893 } 894 int uid = Process.getUidForName(uidStr); 895 if (uid < 0) { 896 Slog.w(TAG, "<" + name + "> with unknown uid \"" 897 + uidStr + " in " + permFile + " at " 898 + parser.getPositionDescription()); 899 XmlUtils.skipCurrentTag(parser); 900 break; 901 } 902 perm = perm.intern(); 903 ArraySet<String> perms = mSystemPermissions.get(uid); 904 if (perms == null) { 905 perms = new ArraySet<String>(); 906 mSystemPermissions.put(uid, perms); 907 } 908 perms.add(perm); 909 } else { 910 logNotAllowedInPartition(name, permFile, parser); 911 } 912 XmlUtils.skipCurrentTag(parser); 913 } break; 914 case "split-permission": { 915 if (allowPermissions) { 916 readSplitPermission(parser, permFile); 917 } else { 918 logNotAllowedInPartition(name, permFile, parser); 919 XmlUtils.skipCurrentTag(parser); 920 } 921 } break; 922 case "apex-library": 923 // "apex-library" is meant to behave exactly like "library" 924 case "library": { 925 if (allowLibs) { 926 String lname = parser.getAttributeValue(null, "name"); 927 String lfile = parser.getAttributeValue(null, "file"); 928 String ldependency = parser.getAttributeValue(null, "dependency"); 929 String minDeviceSdk = parser.getAttributeValue(null, "min-device-sdk"); 930 String maxDeviceSdk = parser.getAttributeValue(null, "max-device-sdk"); 931 if (lname == null) { 932 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at " 933 + parser.getPositionDescription()); 934 } else if (lfile == null) { 935 Slog.w(TAG, "<" + name + "> without file in " + permFile + " at " 936 + parser.getPositionDescription()); 937 } else { 938 boolean allowedMinSdk = 939 minDeviceSdk == null || isAtLeastSdkLevel(minDeviceSdk); 940 boolean allowedMaxSdk = 941 maxDeviceSdk == null || isAtMostSdkLevel(maxDeviceSdk); 942 final boolean exists = new File(lfile).exists(); 943 if (allowedMinSdk && allowedMaxSdk && exists) { 944 String bcpSince = parser.getAttributeValue(null, 945 "on-bootclasspath-since"); 946 String bcpBefore = parser.getAttributeValue(null, 947 "on-bootclasspath-before"); 948 SharedLibraryEntry entry = new SharedLibraryEntry(lname, lfile, 949 ldependency == null 950 ? new String[0] : ldependency.split(":"), 951 bcpSince, bcpBefore); 952 mSharedLibraries.put(lname, entry); 953 } else { 954 final StringBuilder msg = new StringBuilder( 955 "Ignore shared library ").append(lname).append(":"); 956 if (!allowedMinSdk) { 957 msg.append(" min-device-sdk=").append(minDeviceSdk); 958 } 959 if (!allowedMaxSdk) { 960 msg.append(" max-device-sdk=").append(maxDeviceSdk); 961 } 962 if (!exists) { 963 msg.append(" ").append(lfile).append(" does not exist"); 964 } 965 Slog.i(TAG, msg.toString()); 966 } 967 } 968 } else { 969 logNotAllowedInPartition(name, permFile, parser); 970 } 971 XmlUtils.skipCurrentTag(parser); 972 } break; 973 case "feature": { 974 if (allowFeatures) { 975 String fname = parser.getAttributeValue(null, "name"); 976 int fversion = XmlUtils.readIntAttribute(parser, "version", 0); 977 boolean allowed; 978 if (!lowRam) { 979 allowed = true; 980 } else { 981 String notLowRam = parser.getAttributeValue(null, "notLowRam"); 982 allowed = !"true".equals(notLowRam); 983 } 984 if (fname == null) { 985 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at " 986 + parser.getPositionDescription()); 987 } else if (allowed) { 988 addFeature(fname, fversion); 989 } 990 } else { 991 logNotAllowedInPartition(name, permFile, parser); 992 } 993 XmlUtils.skipCurrentTag(parser); 994 } break; 995 case "unavailable-feature": { 996 if (allowFeatures) { 997 String fname = parser.getAttributeValue(null, "name"); 998 if (fname == null) { 999 Slog.w(TAG, "<" + name + "> without name in " + permFile 1000 + " at " + parser.getPositionDescription()); 1001 } else { 1002 mUnavailableFeatures.add(fname); 1003 } 1004 } else { 1005 logNotAllowedInPartition(name, permFile, parser); 1006 } 1007 XmlUtils.skipCurrentTag(parser); 1008 } break; 1009 case "allow-in-power-save-except-idle": { 1010 if (allowOverrideAppRestrictions) { 1011 String pkgname = parser.getAttributeValue(null, "package"); 1012 if (pkgname == null) { 1013 Slog.w(TAG, "<" + name + "> without package in " 1014 + permFile + " at " + parser.getPositionDescription()); 1015 } else { 1016 mAllowInPowerSaveExceptIdle.add(pkgname); 1017 } 1018 } else { 1019 logNotAllowedInPartition(name, permFile, parser); 1020 } 1021 XmlUtils.skipCurrentTag(parser); 1022 } break; 1023 case "allow-in-power-save": { 1024 if (allowOverrideAppRestrictions) { 1025 String pkgname = parser.getAttributeValue(null, "package"); 1026 if (pkgname == null) { 1027 Slog.w(TAG, "<" + name + "> without package in " 1028 + permFile + " at " + parser.getPositionDescription()); 1029 } else { 1030 mAllowInPowerSave.add(pkgname); 1031 } 1032 } else { 1033 logNotAllowedInPartition(name, permFile, parser); 1034 } 1035 XmlUtils.skipCurrentTag(parser); 1036 } break; 1037 case "allow-in-data-usage-save": { 1038 if (allowOverrideAppRestrictions) { 1039 String pkgname = parser.getAttributeValue(null, "package"); 1040 if (pkgname == null) { 1041 Slog.w(TAG, "<" + name + "> without package in " 1042 + permFile + " at " + parser.getPositionDescription()); 1043 } else { 1044 mAllowInDataUsageSave.add(pkgname); 1045 } 1046 } else { 1047 logNotAllowedInPartition(name, permFile, parser); 1048 } 1049 XmlUtils.skipCurrentTag(parser); 1050 } break; 1051 case "allow-unthrottled-location": { 1052 if (allowOverrideAppRestrictions) { 1053 String pkgname = parser.getAttributeValue(null, "package"); 1054 if (pkgname == null) { 1055 Slog.w(TAG, "<" + name + "> without package in " 1056 + permFile + " at " + parser.getPositionDescription()); 1057 } else { 1058 mAllowUnthrottledLocation.add(pkgname); 1059 } 1060 } else { 1061 logNotAllowedInPartition(name, permFile, parser); 1062 } 1063 XmlUtils.skipCurrentTag(parser); 1064 } break; 1065 case "allow-adas-location-settings" : { 1066 if (allowOverrideAppRestrictions) { 1067 String pkgname = parser.getAttributeValue(null, "package"); 1068 String attributionTag = parser.getAttributeValue(null, 1069 "attributionTag"); 1070 if (pkgname == null) { 1071 Slog.w(TAG, "<" + name + "> without package in " 1072 + permFile + " at " + parser.getPositionDescription()); 1073 } else { 1074 ArraySet<String> tags = mAllowAdasSettings.get(pkgname); 1075 if (tags == null || !tags.isEmpty()) { 1076 if (tags == null) { 1077 tags = new ArraySet<>(1); 1078 mAllowAdasSettings.put(pkgname, tags); 1079 } 1080 if (!"*".equals(attributionTag)) { 1081 if ("null".equals(attributionTag)) { 1082 attributionTag = null; 1083 } 1084 tags.add(attributionTag); 1085 } 1086 } 1087 } 1088 } else { 1089 logNotAllowedInPartition(name, permFile, parser); 1090 } 1091 XmlUtils.skipCurrentTag(parser); 1092 } break; 1093 case "camera-privacy-allowlisted-app" : { 1094 if (allowOverrideAppRestrictions) { 1095 String pkgname = parser.getAttributeValue(null, "package"); 1096 if (pkgname == null) { 1097 Slog.w(TAG, "<" + name + "> without package in " 1098 + permFile + " at " + parser.getPositionDescription()); 1099 } else { 1100 mAllowlistCameraPrivacy.add(pkgname); 1101 } 1102 } else { 1103 logNotAllowedInPartition(name, permFile, parser); 1104 } 1105 XmlUtils.skipCurrentTag(parser); 1106 } break; 1107 case "allow-ignore-location-settings": { 1108 if (allowOverrideAppRestrictions) { 1109 String pkgname = parser.getAttributeValue(null, "package"); 1110 String attributionTag = parser.getAttributeValue(null, 1111 "attributionTag"); 1112 if (pkgname == null) { 1113 Slog.w(TAG, "<" + name + "> without package in " 1114 + permFile + " at " + parser.getPositionDescription()); 1115 } else { 1116 ArraySet<String> tags = mAllowIgnoreLocationSettings.get(pkgname); 1117 if (tags == null || !tags.isEmpty()) { 1118 if (tags == null) { 1119 tags = new ArraySet<>(1); 1120 mAllowIgnoreLocationSettings.put(pkgname, tags); 1121 } 1122 if (!"*".equals(attributionTag)) { 1123 if ("null".equals(attributionTag)) { 1124 attributionTag = null; 1125 } 1126 tags.add(attributionTag); 1127 } 1128 } 1129 } 1130 } else { 1131 logNotAllowedInPartition(name, permFile, parser); 1132 } 1133 XmlUtils.skipCurrentTag(parser); 1134 } break; 1135 case "allow-implicit-broadcast": { 1136 if (allowImplicitBroadcasts) { 1137 String action = parser.getAttributeValue(null, "action"); 1138 if (action == null) { 1139 Slog.w(TAG, "<" + name + "> without action in " 1140 + permFile + " at " + parser.getPositionDescription()); 1141 } else { 1142 mAllowImplicitBroadcasts.add(action); 1143 } 1144 } else { 1145 logNotAllowedInPartition(name, permFile, parser); 1146 } 1147 XmlUtils.skipCurrentTag(parser); 1148 } break; 1149 case "app-link": { 1150 if (allowAppConfigs) { 1151 String pkgname = parser.getAttributeValue(null, "package"); 1152 if (pkgname == null) { 1153 Slog.w(TAG, "<" + name + "> without package in " + permFile 1154 + " at " + parser.getPositionDescription()); 1155 } else { 1156 mLinkedApps.add(pkgname); 1157 } 1158 } else { 1159 logNotAllowedInPartition(name, permFile, parser); 1160 } 1161 XmlUtils.skipCurrentTag(parser); 1162 } break; 1163 case "bg-restriction-exemption": { 1164 if (allowOverrideAppRestrictions) { 1165 String pkgname = parser.getAttributeValue(null, "package"); 1166 if (pkgname == null) { 1167 Slog.w(TAG, "<" + name + "> without package in " 1168 + permFile + " at " + parser.getPositionDescription()); 1169 } else { 1170 mBgRestrictionExemption.add(pkgname); 1171 } 1172 } else { 1173 logNotAllowedInPartition(name, permFile, parser); 1174 } 1175 XmlUtils.skipCurrentTag(parser); 1176 } break; 1177 case "default-enabled-vr-app": { 1178 if (allowAppConfigs) { 1179 String pkgname = parser.getAttributeValue(null, "package"); 1180 String clsname = parser.getAttributeValue(null, "class"); 1181 if (pkgname == null) { 1182 Slog.w(TAG, "<" + name + "> without package in " 1183 + permFile + " at " + parser.getPositionDescription()); 1184 } else if (clsname == null) { 1185 Slog.w(TAG, "<" + name + "> without class in " 1186 + permFile + " at " + parser.getPositionDescription()); 1187 } else { 1188 mDefaultVrComponents.add(new ComponentName(pkgname, clsname)); 1189 } 1190 } else { 1191 logNotAllowedInPartition(name, permFile, parser); 1192 } 1193 XmlUtils.skipCurrentTag(parser); 1194 } break; 1195 case "component-override": { 1196 readComponentOverrides(parser, permFile); 1197 } break; 1198 case "backup-transport-whitelisted-service": { 1199 if (allowFeatures) { 1200 String serviceName = parser.getAttributeValue(null, "service"); 1201 if (serviceName == null) { 1202 Slog.w(TAG, "<" + name + "> without service in " 1203 + permFile + " at " + parser.getPositionDescription()); 1204 } else { 1205 ComponentName cn = ComponentName.unflattenFromString(serviceName); 1206 if (cn == null) { 1207 Slog.w(TAG, "<" + name + "> with invalid service name " 1208 + serviceName + " in " + permFile 1209 + " at " + parser.getPositionDescription()); 1210 } else { 1211 mBackupTransportWhitelist.add(cn); 1212 } 1213 } 1214 } else { 1215 logNotAllowedInPartition(name, permFile, parser); 1216 } 1217 XmlUtils.skipCurrentTag(parser); 1218 } break; 1219 case "disabled-until-used-preinstalled-carrier-associated-app": { 1220 if (allowAppConfigs) { 1221 String pkgname = parser.getAttributeValue(null, "package"); 1222 String carrierPkgname = parser.getAttributeValue(null, 1223 "carrierAppPackage"); 1224 if (pkgname == null || carrierPkgname == null) { 1225 Slog.w(TAG, "<" + name 1226 + "> without package or carrierAppPackage in " + permFile 1227 + " at " + parser.getPositionDescription()); 1228 } else { 1229 // APKs added to system images via OTA should specify the addedInSdk 1230 // attribute, otherwise they may be enabled-by-default in too many 1231 // cases. See CarrierAppUtils for more info. 1232 int addedInSdk = CarrierAssociatedAppEntry.SDK_UNSPECIFIED; 1233 String addedInSdkStr = parser.getAttributeValue(null, "addedInSdk"); 1234 if (!TextUtils.isEmpty(addedInSdkStr)) { 1235 try { 1236 addedInSdk = Integer.parseInt(addedInSdkStr); 1237 } catch (NumberFormatException e) { 1238 Slog.w(TAG, "<" + name + "> addedInSdk not an integer in " 1239 + permFile + " at " 1240 + parser.getPositionDescription()); 1241 XmlUtils.skipCurrentTag(parser); 1242 break; 1243 } 1244 } 1245 List<CarrierAssociatedAppEntry> associatedPkgs = 1246 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get( 1247 carrierPkgname); 1248 if (associatedPkgs == null) { 1249 associatedPkgs = new ArrayList<>(); 1250 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put( 1251 carrierPkgname, associatedPkgs); 1252 } 1253 associatedPkgs.add( 1254 new CarrierAssociatedAppEntry(pkgname, addedInSdk)); 1255 } 1256 } else { 1257 logNotAllowedInPartition(name, permFile, parser); 1258 } 1259 XmlUtils.skipCurrentTag(parser); 1260 } break; 1261 case "disabled-until-used-preinstalled-carrier-app": { 1262 if (allowAppConfigs) { 1263 String pkgname = parser.getAttributeValue(null, "package"); 1264 if (pkgname == null) { 1265 Slog.w(TAG, 1266 "<" + name + "> without " 1267 + "package in " + permFile + " at " 1268 + parser.getPositionDescription()); 1269 } else { 1270 mDisabledUntilUsedPreinstalledCarrierApps.add(pkgname); 1271 } 1272 } else { 1273 logNotAllowedInPartition(name, permFile, parser); 1274 } 1275 XmlUtils.skipCurrentTag(parser); 1276 } break; 1277 case "privapp-permissions": { 1278 if (allowPrivappPermissions) { 1279 // privapp permissions from system, apex, vendor, product and 1280 // system_ext partitions are stored separately. This is to 1281 // prevent xml files in the vendor partition from granting 1282 // permissions to priv apps in the system partition and vice versa. 1283 boolean vendor = permFile.toPath().startsWith( 1284 Environment.getVendorDirectory().toPath() + "/") 1285 || permFile.toPath().startsWith( 1286 Environment.getOdmDirectory().toPath() + "/"); 1287 boolean product = permFile.toPath().startsWith( 1288 Environment.getProductDirectory().toPath() + "/"); 1289 boolean systemExt = permFile.toPath().startsWith( 1290 Environment.getSystemExtDirectory().toPath() + "/"); 1291 boolean apex = permFile.toPath().startsWith( 1292 Environment.getApexDirectory().toPath() + "/"); 1293 if (vendor) { 1294 readPrivAppPermissions(parser, 1295 mPermissionAllowlist.getVendorPrivilegedAppAllowlist()); 1296 } else if (product) { 1297 readPrivAppPermissions(parser, 1298 mPermissionAllowlist.getProductPrivilegedAppAllowlist()); 1299 } else if (systemExt) { 1300 readPrivAppPermissions(parser, 1301 mPermissionAllowlist.getSystemExtPrivilegedAppAllowlist()); 1302 } else if (apex) { 1303 readApexPrivAppPermissions(parser, permFile, 1304 Environment.getApexDirectory().toPath()); 1305 } else { 1306 readPrivAppPermissions(parser, 1307 mPermissionAllowlist.getPrivilegedAppAllowlist()); 1308 } 1309 } else { 1310 logNotAllowedInPartition(name, permFile, parser); 1311 XmlUtils.skipCurrentTag(parser); 1312 } 1313 } break; 1314 case "signature-permissions": { 1315 if (allowSignaturePermissions) { 1316 // signature permissions from system, apex, vendor, product and 1317 // system_ext partitions are stored separately. This is to 1318 // prevent xml files in the vendor partition from granting 1319 // permissions to signature apps in the system partition and vice versa. 1320 boolean vendor = permFile.toPath().startsWith( 1321 Environment.getVendorDirectory().toPath() + "/") 1322 || permFile.toPath().startsWith( 1323 Environment.getOdmDirectory().toPath() + "/"); 1324 boolean product = permFile.toPath().startsWith( 1325 Environment.getProductDirectory().toPath() + "/"); 1326 boolean systemExt = permFile.toPath().startsWith( 1327 Environment.getSystemExtDirectory().toPath() + "/"); 1328 boolean apex = permFile.toPath().startsWith( 1329 Environment.getApexDirectory().toPath() + "/"); 1330 if (vendor) { 1331 readSignatureAppPermissions(parser, 1332 mPermissionAllowlist.getVendorSignatureAppAllowlist()); 1333 } else if (product) { 1334 readSignatureAppPermissions(parser, 1335 mPermissionAllowlist.getProductSignatureAppAllowlist()); 1336 } else if (systemExt) { 1337 readSignatureAppPermissions(parser, 1338 mPermissionAllowlist.getSystemExtSignatureAppAllowlist()); 1339 } else if (apex) { 1340 readSignatureAppPermissions(parser, 1341 mPermissionAllowlist.getApexSignatureAppAllowlist()); 1342 } else { 1343 readSignatureAppPermissions(parser, 1344 mPermissionAllowlist.getSignatureAppAllowlist()); 1345 } 1346 } else { 1347 logNotAllowedInPartition(name, permFile, parser); 1348 XmlUtils.skipCurrentTag(parser); 1349 } 1350 } break; 1351 case "oem-permissions": { 1352 if (allowOemPermissions) { 1353 readOemPermissions(parser); 1354 } else { 1355 logNotAllowedInPartition(name, permFile, parser); 1356 XmlUtils.skipCurrentTag(parser); 1357 } 1358 } break; 1359 case "hidden-api-whitelisted-app": { 1360 if (allowApiWhitelisting) { 1361 String pkgname = parser.getAttributeValue(null, "package"); 1362 if (pkgname == null) { 1363 Slog.w(TAG, "<" + name + "> without package in " 1364 + permFile + " at " + parser.getPositionDescription()); 1365 } else { 1366 mHiddenApiPackageWhitelist.add(pkgname); 1367 } 1368 } else { 1369 logNotAllowedInPartition(name, permFile, parser); 1370 } 1371 XmlUtils.skipCurrentTag(parser); 1372 } break; 1373 case "allow-association": { 1374 if (allowAssociations) { 1375 String target = parser.getAttributeValue(null, "target"); 1376 if (target == null) { 1377 Slog.w(TAG, "<" + name + "> without target in " + permFile 1378 + " at " + parser.getPositionDescription()); 1379 XmlUtils.skipCurrentTag(parser); 1380 break; 1381 } 1382 String allowed = parser.getAttributeValue(null, "allowed"); 1383 if (allowed == null) { 1384 Slog.w(TAG, "<" + name + "> without allowed in " + permFile 1385 + " at " + parser.getPositionDescription()); 1386 XmlUtils.skipCurrentTag(parser); 1387 break; 1388 } 1389 target = target.intern(); 1390 allowed = allowed.intern(); 1391 ArraySet<String> associations = mAllowedAssociations.get(target); 1392 if (associations == null) { 1393 associations = new ArraySet<>(); 1394 mAllowedAssociations.put(target, associations); 1395 } 1396 Slog.i(TAG, "Adding association: " + target + " <- " + allowed); 1397 associations.add(allowed); 1398 } else { 1399 logNotAllowedInPartition(name, permFile, parser); 1400 } 1401 XmlUtils.skipCurrentTag(parser); 1402 } break; 1403 case "app-data-isolation-whitelisted-app": { 1404 String pkgname = parser.getAttributeValue(null, "package"); 1405 if (pkgname == null) { 1406 Slog.w(TAG, "<" + name + "> without package in " + permFile 1407 + " at " + parser.getPositionDescription()); 1408 } else { 1409 mAppDataIsolationWhitelistedApps.add(pkgname); 1410 } 1411 XmlUtils.skipCurrentTag(parser); 1412 } break; 1413 case "bugreport-whitelisted": { 1414 String pkgname = parser.getAttributeValue(null, "package"); 1415 if (pkgname == null) { 1416 Slog.w(TAG, "<" + name + "> without package in " + permFile 1417 + " at " + parser.getPositionDescription()); 1418 } else { 1419 mBugreportWhitelistedPackages.add(pkgname); 1420 } 1421 XmlUtils.skipCurrentTag(parser); 1422 } break; 1423 case "prevent-disable": { 1424 String pkgname = parser.getAttributeValue(null, "package"); 1425 if (pkgname == null) { 1426 Slog.w(TAG, "<" + name + "> without package in " + permFile 1427 + " at " + parser.getPositionDescription()); 1428 } else { 1429 mPreventUserDisablePackages.add(pkgname); 1430 } 1431 XmlUtils.skipCurrentTag(parser); 1432 } break; 1433 case "install-in-user-type": { 1434 // NB: We allow any directory permission to declare install-in-user-type. 1435 readInstallInUserType(parser, 1436 mPackageToUserTypeWhitelist, mPackageToUserTypeBlacklist); 1437 } break; 1438 case "named-actor": { 1439 String namespace = TextUtils.safeIntern( 1440 parser.getAttributeValue(null, "namespace")); 1441 String actorName = parser.getAttributeValue(null, "name"); 1442 String pkgName = TextUtils.safeIntern( 1443 parser.getAttributeValue(null, "package")); 1444 if (TextUtils.isEmpty(namespace)) { 1445 Slog.wtf(TAG, "<" + name + "> without namespace in " + permFile 1446 + " at " + parser.getPositionDescription()); 1447 } else if (TextUtils.isEmpty(actorName)) { 1448 Slog.wtf(TAG, "<" + name + "> without actor name in " + permFile 1449 + " at " + parser.getPositionDescription()); 1450 } else if (TextUtils.isEmpty(pkgName)) { 1451 Slog.wtf(TAG, "<" + name + "> without package name in " + permFile 1452 + " at " + parser.getPositionDescription()); 1453 } else if ("android".equalsIgnoreCase(namespace)) { 1454 throw new IllegalStateException("Defining " + actorName + " as " 1455 + pkgName + " for the android namespace is not allowed"); 1456 } else { 1457 if (mNamedActors == null) { 1458 mNamedActors = new ArrayMap<>(); 1459 } 1460 1461 Map<String, String> nameToPkgMap = mNamedActors.get(namespace); 1462 if (nameToPkgMap == null) { 1463 nameToPkgMap = new ArrayMap<>(); 1464 mNamedActors.put(namespace, nameToPkgMap); 1465 } else if (nameToPkgMap.containsKey(actorName)) { 1466 String existing = nameToPkgMap.get(actorName); 1467 throw new IllegalStateException("Duplicate actor definition for " 1468 + namespace + "/" + actorName 1469 + "; defined as both " + existing + " and " + pkgName); 1470 } 1471 1472 nameToPkgMap.put(actorName, pkgName); 1473 } 1474 XmlUtils.skipCurrentTag(parser); 1475 } break; 1476 case "overlay-config-signature": { 1477 if (allowAll) { 1478 String pkgName = parser.getAttributeValue(null, "package"); 1479 if (pkgName == null) { 1480 Slog.w(TAG, "<" + name + "> without package in " + permFile 1481 + " at " + parser.getPositionDescription()); 1482 } else { 1483 if (TextUtils.isEmpty(mOverlayConfigSignaturePackage)) { 1484 mOverlayConfigSignaturePackage = pkgName.intern(); 1485 } else { 1486 throw new IllegalStateException("Reference signature package " 1487 + "defined as both " 1488 + mOverlayConfigSignaturePackage 1489 + " and " + pkgName); 1490 } 1491 } 1492 } else { 1493 logNotAllowedInPartition(name, permFile, parser); 1494 } 1495 XmlUtils.skipCurrentTag(parser); 1496 } break; 1497 case "rollback-whitelisted-app": { 1498 String pkgname = parser.getAttributeValue(null, "package"); 1499 if (pkgname == null) { 1500 Slog.w(TAG, "<" + name + "> without package in " + permFile 1501 + " at " + parser.getPositionDescription()); 1502 } else { 1503 mRollbackWhitelistedPackages.add(pkgname); 1504 } 1505 XmlUtils.skipCurrentTag(parser); 1506 } break; 1507 case "whitelisted-staged-installer": { 1508 if (allowAppConfigs) { 1509 String pkgname = parser.getAttributeValue(null, "package"); 1510 boolean isModulesInstaller = XmlUtils.readBooleanAttribute( 1511 parser, "isModulesInstaller", false); 1512 if (pkgname == null) { 1513 Slog.w(TAG, "<" + name + "> without package in " + permFile 1514 + " at " + parser.getPositionDescription()); 1515 } else { 1516 mWhitelistedStagedInstallers.add(pkgname); 1517 } 1518 if (isModulesInstaller) { 1519 if (mModulesInstallerPackageName != null) { 1520 throw new IllegalStateException( 1521 "Multiple modules installers"); 1522 } 1523 mModulesInstallerPackageName = pkgname; 1524 } 1525 } else { 1526 logNotAllowedInPartition(name, permFile, parser); 1527 } 1528 XmlUtils.skipCurrentTag(parser); 1529 } break; 1530 case "allowed-vendor-apex": { 1531 if (allowVendorApex) { 1532 String pkgName = parser.getAttributeValue(null, "package"); 1533 String installerPkgName = parser.getAttributeValue( 1534 null, "installerPackage"); 1535 if (pkgName == null) { 1536 Slog.w(TAG, "<" + name + "> without package in " + permFile 1537 + " at " + parser.getPositionDescription()); 1538 } 1539 if (installerPkgName == null) { 1540 Slog.w(TAG, "<" + name + "> without installerPackage in " + permFile 1541 + " at " + parser.getPositionDescription()); 1542 } 1543 if (pkgName != null && installerPkgName != null) { 1544 mAllowedVendorApexes.put(pkgName, installerPkgName); 1545 } 1546 } else { 1547 logNotAllowedInPartition(name, permFile, parser); 1548 } 1549 XmlUtils.skipCurrentTag(parser); 1550 } break; 1551 case "install-constraints-allowed": { 1552 if (allowAppConfigs) { 1553 String packageName = parser.getAttributeValue(null, "package"); 1554 if (packageName == null) { 1555 Slog.w(TAG, "<" + name + "> without package in " + permFile 1556 + " at " + parser.getPositionDescription()); 1557 } else { 1558 mInstallConstraintsAllowlist.add(packageName); 1559 } 1560 } else { 1561 logNotAllowedInPartition(name, permFile, parser); 1562 } 1563 XmlUtils.skipCurrentTag(parser); 1564 } break; 1565 case "update-ownership": { 1566 final String packageName = parser.getAttributeValue(null /* namespace */, 1567 "package"); 1568 final String installerName = parser.getAttributeValue(null /* namespace */, 1569 "installer"); 1570 if (TextUtils.isEmpty(packageName)) { 1571 Slog.w(TAG, "<" + name + "> without valid package in " + permFile 1572 + " at " + parser.getPositionDescription()); 1573 } else if (TextUtils.isEmpty(installerName)) { 1574 Slog.w(TAG, "<" + name + "> without valid installer in " + permFile 1575 + " at " + parser.getPositionDescription()); 1576 } else { 1577 mUpdateOwnersForSystemApps.put(packageName, installerName); 1578 } 1579 XmlUtils.skipCurrentTag(parser); 1580 } break; 1581 case "initial-package-state": { 1582 String pkgName = parser.getAttributeValue(null, "package"); 1583 String stopped = parser.getAttributeValue(null, "stopped"); 1584 if (TextUtils.isEmpty(pkgName)) { 1585 Slog.w(TAG, "<" + name + "> without package in " + permFile 1586 + " at " + parser.getPositionDescription()); 1587 } else if (TextUtils.isEmpty(stopped)) { 1588 Slog.w(TAG, "<" + name + "> without stopped in " + permFile 1589 + " at " + parser.getPositionDescription()); 1590 } else if (!Boolean.parseBoolean(stopped)) { 1591 mInitialNonStoppedSystemPackages.add(pkgName); 1592 } 1593 } break; 1594 case "allow-package-shareduid": { 1595 String pkgName = parser.getAttributeValue(null, "package"); 1596 String sharedUid = parser.getAttributeValue(null, "shareduid"); 1597 if (TextUtils.isEmpty(pkgName)) { 1598 Slog.w(TAG, "<" + name + "> without package in " + permFile 1599 + " at " + parser.getPositionDescription()); 1600 } else if (TextUtils.isEmpty(sharedUid)) { 1601 Slog.w(TAG, "<" + name + "> without shareduid in " + permFile 1602 + " at " + parser.getPositionDescription()); 1603 } else { 1604 mPackageToSharedUidAllowList.put(pkgName, sharedUid); 1605 } 1606 } break; 1607 case "asl-file": { 1608 String packageName = parser.getAttributeValue(null, "package"); 1609 String path = parser.getAttributeValue(null, "path"); 1610 if (TextUtils.isEmpty(packageName)) { 1611 Slog.w(TAG, "<" + name + "> without valid package in " + permFile 1612 + " at " + parser.getPositionDescription()); 1613 } else if (TextUtils.isEmpty(path)) { 1614 Slog.w(TAG, "<" + name + "> without valid path in " + permFile 1615 + " at " + parser.getPositionDescription()); 1616 } else { 1617 mAppMetadataFilePaths.put(packageName, path); 1618 } 1619 } break; 1620 case "require-strict-signature": { 1621 if (android.security.Flags.extendVbChainToUpdatedApk()) { 1622 String packageName = parser.getAttributeValue(null, "package"); 1623 if (TextUtils.isEmpty(packageName)) { 1624 Slog.w(TAG, "<" + name + "> without valid package in " + permFile 1625 + " at " + parser.getPositionDescription()); 1626 } else { 1627 mPreinstallPackagesWithStrictSignatureCheck.add(packageName); 1628 } 1629 } 1630 } break; 1631 case "enhanced-confirmation-trusted-package": { 1632 if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()) { 1633 SignedPackage signedPackage = parseEnhancedConfirmationTrustedPackage( 1634 parser, permFile, name); 1635 if (signedPackage != null) { 1636 mEnhancedConfirmationTrustedPackages.add(signedPackage); 1637 } 1638 break; 1639 } 1640 } // fall through if flag is not enabled 1641 case "enhanced-confirmation-trusted-installer": { 1642 if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()) { 1643 SignedPackage signedPackage = parseEnhancedConfirmationTrustedPackage( 1644 parser, permFile, name); 1645 if (signedPackage != null) { 1646 mEnhancedConfirmationTrustedInstallers.add(signedPackage); 1647 } 1648 break; 1649 } 1650 } // fall through if flag is not enabled 1651 default: { 1652 Slog.w(TAG, "Tag " + name + " is unknown in " 1653 + permFile + " at " + parser.getPositionDescription()); 1654 XmlUtils.skipCurrentTag(parser); 1655 } break; 1656 } 1657 } 1658 } catch (XmlPullParserException e) { 1659 Slog.w(TAG, "Got exception parsing permissions.", e); 1660 } catch (IOException e) { 1661 Slog.w(TAG, "Got exception parsing permissions.", e); 1662 } finally { 1663 IoUtils.closeQuietly(permReader); 1664 } 1665 1666 // Some devices can be field-converted to FBE, so offer to splice in 1667 // those features if not already defined by the static config 1668 if (StorageManager.isFileEncrypted()) { 1669 addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0); 1670 addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0); 1671 } 1672 1673 // Help legacy devices that may not have updated their static config 1674 if (StorageManager.hasAdoptable()) { 1675 addFeature(PackageManager.FEATURE_ADOPTABLE_STORAGE, 0); 1676 } 1677 1678 if (ActivityManager.isLowRamDeviceStatic()) { 1679 addFeature(PackageManager.FEATURE_RAM_LOW, 0); 1680 } else { 1681 addFeature(PackageManager.FEATURE_RAM_NORMAL, 0); 1682 } 1683 1684 final int incrementalVersion = IncrementalManager.getVersion(); 1685 if (incrementalVersion > 0) { 1686 addFeature(PackageManager.FEATURE_INCREMENTAL_DELIVERY, incrementalVersion); 1687 } 1688 1689 if (PackageManager.APP_ENUMERATION_ENABLED_BY_DEFAULT) { 1690 addFeature(PackageManager.FEATURE_APP_ENUMERATION, 0); 1691 } 1692 1693 if (Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.Q) { 1694 addFeature(PackageManager.FEATURE_IPSEC_TUNNELS, 0); 1695 } 1696 1697 enableIpSecTunnelMigrationOnVsrUAndAbove(); 1698 1699 if (isErofsSupported()) { 1700 if (isKernelVersionAtLeast(5, 10)) { 1701 addFeature(PackageManager.FEATURE_EROFS, 0); 1702 } else if (isKernelVersionAtLeast(4, 19)) { 1703 addFeature(PackageManager.FEATURE_EROFS_LEGACY, 0); 1704 } 1705 } 1706 1707 for (String featureName : mUnavailableFeatures) { 1708 removeFeature(featureName); 1709 } 1710 } 1711 parseEnhancedConfirmationTrustedPackage(XmlPullParser parser, File permFile, String elementName)1712 private @Nullable SignedPackage parseEnhancedConfirmationTrustedPackage(XmlPullParser parser, 1713 File permFile, String elementName) { 1714 String pkgName = parser.getAttributeValue(null, "package"); 1715 if (TextUtils.isEmpty(pkgName)) { 1716 Slog.w(TAG, "<" + elementName + "> without package " + permFile + " at " 1717 + parser.getPositionDescription()); 1718 return null; 1719 } 1720 1721 String certificateDigestStr = parser.getAttributeValue(null, "sha256-cert-digest"); 1722 if (TextUtils.isEmpty(certificateDigestStr)) { 1723 Slog.w(TAG, "<" + elementName + "> without sha256-cert-digest in " + permFile 1724 + " at " + parser.getPositionDescription()); 1725 return null; 1726 } 1727 byte[] certificateDigest = null; 1728 try { 1729 certificateDigest = new Signature(certificateDigestStr.replace(":", "")).toByteArray(); 1730 } catch (IllegalArgumentException e) { 1731 Slog.w(TAG, "<" + elementName + "> with invalid sha256-cert-digest in " 1732 + permFile + " at " + parser.getPositionDescription()); 1733 return null; 1734 } 1735 1736 return new SignedPackage(pkgName, certificateDigest); 1737 } 1738 1739 // This method only enables a new Android feature added in U and will not have impact on app 1740 // compatibility 1741 @SuppressWarnings("AndroidFrameworkCompatChange") enableIpSecTunnelMigrationOnVsrUAndAbove()1742 private void enableIpSecTunnelMigrationOnVsrUAndAbove() { 1743 final int vsrApi = 1744 SystemProperties.getInt( 1745 "ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT); 1746 if (vsrApi > Build.VERSION_CODES.TIRAMISU) { 1747 addFeature(PackageManager.FEATURE_IPSEC_TUNNEL_MIGRATION, 0); 1748 } 1749 } 1750 addFeature(String name, int version)1751 private void addFeature(String name, int version) { 1752 FeatureInfo fi = mAvailableFeatures.get(name); 1753 if (fi == null) { 1754 fi = new FeatureInfo(); 1755 fi.name = name; 1756 fi.version = version; 1757 mAvailableFeatures.put(name, fi); 1758 } else { 1759 fi.version = Math.max(fi.version, version); 1760 } 1761 } 1762 removeFeature(String name)1763 private void removeFeature(String name) { 1764 if (mAvailableFeatures.remove(name) != null) { 1765 Slog.d(TAG, "Removed unavailable feature " + name); 1766 } 1767 } 1768 readPermission(XmlPullParser parser, String name)1769 void readPermission(XmlPullParser parser, String name) 1770 throws IOException, XmlPullParserException { 1771 if (mPermissions.containsKey(name)) { 1772 throw new IllegalStateException("Duplicate permission definition for " + name); 1773 } 1774 1775 final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false); 1776 final PermissionEntry perm = new PermissionEntry(name, perUser); 1777 mPermissions.put(name, perm); 1778 1779 int outerDepth = parser.getDepth(); 1780 int type; 1781 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 1782 && (type != XmlPullParser.END_TAG 1783 || parser.getDepth() > outerDepth)) { 1784 if (type == XmlPullParser.END_TAG 1785 || type == XmlPullParser.TEXT) { 1786 continue; 1787 } 1788 1789 String tagName = parser.getName(); 1790 if ("group".equals(tagName)) { 1791 String gidStr = parser.getAttributeValue(null, "gid"); 1792 if (gidStr != null) { 1793 int gid = Process.getGidForName(gidStr); 1794 if (gid != -1) { 1795 perm.gids = appendInt(perm.gids, gid); 1796 } else { 1797 Slog.w(TAG, "<group> with unknown gid \"" 1798 + gidStr + " for permission " + name + " in " 1799 + parser.getPositionDescription()); 1800 } 1801 } else { 1802 Slog.w(TAG, "<group> without gid at " 1803 + parser.getPositionDescription()); 1804 } 1805 } 1806 XmlUtils.skipCurrentTag(parser); 1807 } 1808 } 1809 readPrivAppPermissions(@onNull XmlPullParser parser, @NonNull ArrayMap<String, ArrayMap<String, Boolean>> allowlist)1810 private void readPrivAppPermissions(@NonNull XmlPullParser parser, 1811 @NonNull ArrayMap<String, ArrayMap<String, Boolean>> allowlist) 1812 throws IOException, XmlPullParserException { 1813 readPermissionAllowlist(parser, allowlist, "privapp-permissions"); 1814 } 1815 readSignatureAppPermissions(@onNull XmlPullParser parser, @NonNull ArrayMap<String, ArrayMap<String, Boolean>> allowlist)1816 private void readSignatureAppPermissions(@NonNull XmlPullParser parser, 1817 @NonNull ArrayMap<String, ArrayMap<String, Boolean>> allowlist) 1818 throws IOException, XmlPullParserException { 1819 readPermissionAllowlist(parser, allowlist, "signature-permissions"); 1820 } 1821 readInstallInUserType(XmlPullParser parser, Map<String, Set<String>> doInstallMap, Map<String, Set<String>> nonInstallMap)1822 private void readInstallInUserType(XmlPullParser parser, 1823 Map<String, Set<String>> doInstallMap, 1824 Map<String, Set<String>> nonInstallMap) 1825 throws IOException, XmlPullParserException { 1826 final String packageName = parser.getAttributeValue(null, "package"); 1827 if (TextUtils.isEmpty(packageName)) { 1828 Slog.w(TAG, "package is required for <install-in-user-type> in " 1829 + parser.getPositionDescription()); 1830 return; 1831 } 1832 1833 Set<String> userTypesYes = doInstallMap.get(packageName); 1834 Set<String> userTypesNo = nonInstallMap.get(packageName); 1835 final int depth = parser.getDepth(); 1836 while (XmlUtils.nextElementWithin(parser, depth)) { 1837 final String name = parser.getName(); 1838 if ("install-in".equals(name)) { 1839 final String userType = parser.getAttributeValue(null, "user-type"); 1840 if (TextUtils.isEmpty(userType)) { 1841 Slog.w(TAG, "user-type is required for <install-in-user-type> in " 1842 + parser.getPositionDescription()); 1843 continue; 1844 } 1845 if (userTypesYes == null) { 1846 userTypesYes = new ArraySet<>(); 1847 doInstallMap.put(packageName, userTypesYes); 1848 } 1849 userTypesYes.add(userType); 1850 } else if ("do-not-install-in".equals(name)) { 1851 final String userType = parser.getAttributeValue(null, "user-type"); 1852 if (TextUtils.isEmpty(userType)) { 1853 Slog.w(TAG, "user-type is required for <install-in-user-type> in " 1854 + parser.getPositionDescription()); 1855 continue; 1856 } 1857 if (userTypesNo == null) { 1858 userTypesNo = new ArraySet<>(); 1859 nonInstallMap.put(packageName, userTypesNo); 1860 } 1861 userTypesNo.add(userType); 1862 } else { 1863 Slog.w(TAG, "unrecognized tag in <install-in-user-type> in " 1864 + parser.getPositionDescription()); 1865 } 1866 } 1867 } 1868 readOemPermissions(XmlPullParser parser)1869 void readOemPermissions(XmlPullParser parser) throws IOException, XmlPullParserException { 1870 readPermissionAllowlist(parser, mPermissionAllowlist.getOemAppAllowlist(), 1871 "oem-permissions"); 1872 } 1873 readPermissionAllowlist(@onNull XmlPullParser parser, @NonNull ArrayMap<String, ArrayMap<String, Boolean>> allowlist, @NonNull String tagName)1874 private static void readPermissionAllowlist(@NonNull XmlPullParser parser, 1875 @NonNull ArrayMap<String, ArrayMap<String, Boolean>> allowlist, @NonNull String tagName) 1876 throws IOException, XmlPullParserException { 1877 final String packageName = parser.getAttributeValue(null, "package"); 1878 if (TextUtils.isEmpty(packageName)) { 1879 Slog.w(TAG, "package is required for <" + tagName + "> in " 1880 + parser.getPositionDescription()); 1881 return; 1882 } 1883 1884 ArrayMap<String, Boolean> permissions = allowlist.get(packageName); 1885 if (permissions == null) { 1886 permissions = new ArrayMap<>(); 1887 } 1888 final int depth = parser.getDepth(); 1889 while (XmlUtils.nextElementWithin(parser, depth)) { 1890 final String name = parser.getName(); 1891 if ("permission".equals(name)) { 1892 final String permissionName = parser.getAttributeValue(null, "name"); 1893 if (TextUtils.isEmpty(permissionName)) { 1894 Slog.w(TAG, "name is required for <permission> in " 1895 + parser.getPositionDescription()); 1896 continue; 1897 } 1898 permissions.put(permissionName, Boolean.TRUE); 1899 } else if ("deny-permission".equals(name)) { 1900 String permissionName = parser.getAttributeValue(null, "name"); 1901 if (TextUtils.isEmpty(permissionName)) { 1902 Slog.w(TAG, "name is required for <deny-permission> in " 1903 + parser.getPositionDescription()); 1904 continue; 1905 } 1906 permissions.put(permissionName, Boolean.FALSE); 1907 } 1908 } 1909 allowlist.put(packageName, permissions); 1910 } 1911 readSplitPermission(XmlPullParser parser, File permFile)1912 private void readSplitPermission(XmlPullParser parser, File permFile) 1913 throws IOException, XmlPullParserException { 1914 String splitPerm = parser.getAttributeValue(null, "name"); 1915 if (splitPerm == null) { 1916 Slog.w(TAG, "<split-permission> without name in " + permFile + " at " 1917 + parser.getPositionDescription()); 1918 XmlUtils.skipCurrentTag(parser); 1919 return; 1920 } 1921 String targetSdkStr = parser.getAttributeValue(null, "targetSdk"); 1922 int targetSdk = Build.VERSION_CODES.CUR_DEVELOPMENT + 1; 1923 if (!TextUtils.isEmpty(targetSdkStr)) { 1924 try { 1925 targetSdk = Integer.parseInt(targetSdkStr); 1926 } catch (NumberFormatException e) { 1927 Slog.w(TAG, "<split-permission> targetSdk not an integer in " + permFile + " at " 1928 + parser.getPositionDescription()); 1929 XmlUtils.skipCurrentTag(parser); 1930 return; 1931 } 1932 } 1933 final int depth = parser.getDepth(); 1934 List<String> newPermissions = new ArrayList<>(); 1935 while (XmlUtils.nextElementWithin(parser, depth)) { 1936 String name = parser.getName(); 1937 if ("new-permission".equals(name)) { 1938 final String newName = parser.getAttributeValue(null, "name"); 1939 if (TextUtils.isEmpty(newName)) { 1940 Slog.w(TAG, "name is required for <new-permission> in " 1941 + parser.getPositionDescription()); 1942 continue; 1943 } 1944 newPermissions.add(newName); 1945 } else { 1946 XmlUtils.skipCurrentTag(parser); 1947 } 1948 } 1949 if (!newPermissions.isEmpty()) { 1950 mSplitPermissions.add(new SplitPermissionInfo(splitPerm, newPermissions, targetSdk)); 1951 } 1952 } 1953 readComponentOverrides(XmlPullParser parser, File permFile)1954 private void readComponentOverrides(XmlPullParser parser, File permFile) 1955 throws IOException, XmlPullParserException { 1956 String pkgname = parser.getAttributeValue(null, "package"); 1957 if (pkgname == null) { 1958 Slog.w(TAG, "<component-override> without package in " 1959 + permFile + " at " + parser.getPositionDescription()); 1960 return; 1961 } 1962 1963 pkgname = pkgname.intern(); 1964 1965 final int depth = parser.getDepth(); 1966 while (XmlUtils.nextElementWithin(parser, depth)) { 1967 if ("component".equals(parser.getName())) { 1968 String clsname = parser.getAttributeValue(null, "class"); 1969 String enabled = parser.getAttributeValue(null, "enabled"); 1970 if (clsname == null) { 1971 Slog.w(TAG, "<component> without class in " 1972 + permFile + " at " + parser.getPositionDescription()); 1973 return; 1974 } else if (enabled == null) { 1975 Slog.w(TAG, "<component> without enabled in " 1976 + permFile + " at " + parser.getPositionDescription()); 1977 return; 1978 } 1979 1980 if (clsname.startsWith(".")) { 1981 clsname = pkgname + clsname; 1982 } 1983 1984 clsname = clsname.intern(); 1985 1986 ArrayMap<String, Boolean> componentEnabledStates = 1987 mPackageComponentEnabledState.get(pkgname); 1988 if (componentEnabledStates == null) { 1989 componentEnabledStates = new ArrayMap<>(); 1990 mPackageComponentEnabledState.put(pkgname, 1991 componentEnabledStates); 1992 } 1993 1994 componentEnabledStates.put(clsname, !"false".equals(enabled)); 1995 } 1996 } 1997 } 1998 readPublicNativeLibrariesList()1999 private void readPublicNativeLibrariesList() { 2000 readPublicLibrariesListFile(new File("/vendor/etc/public.libraries.txt")); 2001 String[] dirs = {"/system/etc", "/system_ext/etc", "/product/etc"}; 2002 for (String dir : dirs) { 2003 File[] files = new File(dir).listFiles(); 2004 if (files == null) { 2005 Slog.w(TAG, "Public libraries file folder missing: " + dir); 2006 continue; 2007 } 2008 for (File f : files) { 2009 String name = f.getName(); 2010 if (name.startsWith("public.libraries-") && name.endsWith(".txt")) { 2011 readPublicLibrariesListFile(f); 2012 } 2013 } 2014 } 2015 } 2016 readPublicLibrariesListFile(File listFile)2017 private void readPublicLibrariesListFile(File listFile) { 2018 try (BufferedReader br = new BufferedReader(new FileReader(listFile))) { 2019 String line; 2020 while ((line = br.readLine()) != null) { 2021 if (line.isEmpty() || line.startsWith("#")) { 2022 continue; 2023 } 2024 // Line format is <soname> [abi]. We take the soname part. 2025 String soname = line.trim().split(" ")[0]; 2026 SharedLibraryEntry entry = new SharedLibraryEntry( 2027 soname, soname, new String[0], true); 2028 mSharedLibraries.put(entry.name, entry); 2029 } 2030 } catch (FileNotFoundException e) { 2031 // Expected for /vendor/etc/public.libraries.txt on some devices 2032 Slog.d(TAG, listFile + " does not exist"); 2033 } catch (IOException e) { 2034 Slog.w(TAG, "Failed to read public libraries file " + listFile, e); 2035 } 2036 } 2037 2038 2039 /** 2040 * Returns the module name for a file in the apex module's partition. 2041 */ getApexModuleNameFromFilePath(Path path, Path apexDirectoryPath)2042 private String getApexModuleNameFromFilePath(Path path, Path apexDirectoryPath) { 2043 if (!path.startsWith(apexDirectoryPath)) { 2044 throw new IllegalArgumentException("File " + path + " is not part of an APEX."); 2045 } 2046 // File must be in <apex_directory>/<module_name>/[extra_paths/]<xml_file> 2047 if (path.getNameCount() <= (apexDirectoryPath.getNameCount() + 1)) { 2048 throw new IllegalArgumentException("File " + path + " is in the APEX partition," 2049 + " but not inside a module."); 2050 } 2051 return path.getName(apexDirectoryPath.getNameCount()).toString(); 2052 } 2053 2054 /** 2055 * Reads the contents of the privileged permission allowlist stored inside an APEX. 2056 */ 2057 @VisibleForTesting readApexPrivAppPermissions(XmlPullParser parser, File permFile, Path apexDirectoryPath)2058 public void readApexPrivAppPermissions(XmlPullParser parser, File permFile, 2059 Path apexDirectoryPath) throws IOException, XmlPullParserException { 2060 final String moduleName = 2061 getApexModuleNameFromFilePath(permFile.toPath(), apexDirectoryPath); 2062 final ArrayMap<String, ArrayMap<String, ArrayMap<String, Boolean>>> allowlists = 2063 mPermissionAllowlist.getApexPrivilegedAppAllowlists(); 2064 ArrayMap<String, ArrayMap<String, Boolean>> allowlist = allowlists.get(moduleName); 2065 if (allowlist == null) { 2066 allowlist = new ArrayMap<>(); 2067 allowlists.put(moduleName, allowlist); 2068 } 2069 readPrivAppPermissions(parser, allowlist); 2070 } 2071 isSystemProcess()2072 private static boolean isSystemProcess() { 2073 return Process.myUid() == Process.SYSTEM_UID; 2074 } 2075 isErofsSupported()2076 private static boolean isErofsSupported() { 2077 try { 2078 final Path path = Paths.get("/sys/fs/erofs"); 2079 return Files.exists(path); 2080 } catch (Exception e) { 2081 return false; 2082 } 2083 } 2084 isKernelVersionAtLeast(int major, int minor)2085 private static boolean isKernelVersionAtLeast(int major, int minor) { 2086 final String kernelVersion = VintfRuntimeInfo.getKernelVersion(); 2087 final String[] parts = kernelVersion.split("\\."); 2088 if (parts.length < 2) { 2089 return false; 2090 } 2091 try { 2092 final int majorVersion = Integer.parseInt(parts[0]); 2093 final int minorVersion = Integer.parseInt(parts[1]); 2094 return majorVersion > major || (majorVersion == major && minorVersion >= minor); 2095 } catch (NumberFormatException e) { 2096 return false; 2097 } 2098 } 2099 } 2100