1 /* 2 * Copyright (C) 2007 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 android.content.pm; 18 19 import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE; 20 import static android.content.pm.ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE; 21 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY; 22 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY; 23 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION; 24 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE; 25 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE; 26 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION; 27 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; 28 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 29 import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED; 30 import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE; 31 import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION; 32 import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE; 33 import static android.content.pm.PackageManager.FEATURE_WATCH; 34 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST; 35 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME; 36 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; 37 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 38 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK; 39 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; 40 import static android.os.Build.VERSION_CODES.O; 41 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; 42 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED; 43 44 import android.annotation.IntDef; 45 import android.annotation.IntRange; 46 import android.annotation.NonNull; 47 import android.annotation.Nullable; 48 import android.annotation.StringRes; 49 import android.apex.ApexInfo; 50 import android.app.ActivityTaskManager; 51 import android.app.ActivityThread; 52 import android.app.ResourcesManager; 53 import android.compat.annotation.UnsupportedAppUsage; 54 import android.content.ComponentName; 55 import android.content.Intent; 56 import android.content.IntentFilter; 57 import android.content.pm.PackageParserCacheHelper.ReadHelper; 58 import android.content.pm.PackageParserCacheHelper.WriteHelper; 59 import android.content.pm.permission.SplitPermissionInfoParcelable; 60 import android.content.pm.split.DefaultSplitAssetLoader; 61 import android.content.pm.split.SplitAssetDependencyLoader; 62 import android.content.pm.split.SplitAssetLoader; 63 import android.content.res.ApkAssets; 64 import android.content.res.AssetManager; 65 import android.content.res.Configuration; 66 import android.content.res.Resources; 67 import android.content.res.TypedArray; 68 import android.content.res.XmlResourceParser; 69 import android.os.Build; 70 import android.os.Bundle; 71 import android.os.FileUtils; 72 import android.os.Parcel; 73 import android.os.Parcelable; 74 import android.os.PatternMatcher; 75 import android.os.RemoteException; 76 import android.os.SystemClock; 77 import android.os.SystemProperties; 78 import android.os.Trace; 79 import android.os.UserHandle; 80 import android.os.storage.StorageManager; 81 import android.permission.PermissionManager; 82 import android.system.ErrnoException; 83 import android.system.OsConstants; 84 import android.system.StructStat; 85 import android.text.TextUtils; 86 import android.util.ArrayMap; 87 import android.util.ArraySet; 88 import android.util.AttributeSet; 89 import android.util.Base64; 90 import android.util.DisplayMetrics; 91 import android.util.Log; 92 import android.util.PackageUtils; 93 import android.util.Pair; 94 import android.util.Slog; 95 import android.util.SparseArray; 96 import android.util.TypedValue; 97 import android.util.apk.ApkSignatureVerifier; 98 import android.view.Display; 99 import android.view.Gravity; 100 101 import com.android.internal.R; 102 import com.android.internal.annotations.VisibleForTesting; 103 import com.android.internal.os.ClassLoaderFactory; 104 import com.android.internal.util.ArrayUtils; 105 import com.android.internal.util.XmlUtils; 106 import com.android.server.SystemConfig; 107 108 import libcore.io.IoUtils; 109 import libcore.util.EmptyArray; 110 import libcore.util.HexEncoding; 111 112 import org.xmlpull.v1.XmlPullParser; 113 import org.xmlpull.v1.XmlPullParserException; 114 115 import java.io.File; 116 import java.io.FileDescriptor; 117 import java.io.FileOutputStream; 118 import java.io.IOException; 119 import java.io.PrintWriter; 120 import java.lang.annotation.Retention; 121 import java.lang.annotation.RetentionPolicy; 122 import java.lang.reflect.Constructor; 123 import java.security.KeyFactory; 124 import java.security.NoSuchAlgorithmException; 125 import java.security.PublicKey; 126 import java.security.cert.CertificateException; 127 import java.security.spec.EncodedKeySpec; 128 import java.security.spec.InvalidKeySpecException; 129 import java.security.spec.X509EncodedKeySpec; 130 import java.util.ArrayList; 131 import java.util.Arrays; 132 import java.util.Collections; 133 import java.util.Comparator; 134 import java.util.Iterator; 135 import java.util.List; 136 import java.util.Set; 137 import java.util.UUID; 138 import java.util.concurrent.atomic.AtomicInteger; 139 140 /** 141 * Parser for package files (APKs) on disk. This supports apps packaged either 142 * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple 143 * APKs in a single directory. 144 * <p> 145 * Apps packaged as multiple APKs always consist of a single "base" APK (with a 146 * {@code null} split name) and zero or more "split" APKs (with unique split 147 * names). Any subset of those split APKs are a valid install, as long as the 148 * following constraints are met: 149 * <ul> 150 * <li>All APKs must have the exact same package name, version code, and signing 151 * certificates. 152 * <li>All APKs must have unique split names. 153 * <li>All installations must contain a single base APK. 154 * </ul> 155 * 156 * @hide 157 */ 158 public class PackageParser { 159 private static final boolean DEBUG_JAR = false; 160 private static final boolean DEBUG_PARSER = false; 161 private static final boolean DEBUG_BACKUP = false; 162 private static final boolean LOG_PARSE_TIMINGS = Build.IS_DEBUGGABLE; 163 private static final int LOG_PARSE_TIMINGS_THRESHOLD_MS = 100; 164 165 private static final String PROPERTY_CHILD_PACKAGES_ENABLED = 166 "persist.sys.child_packages_enabled"; 167 168 private static final boolean MULTI_PACKAGE_APK_ENABLED = Build.IS_DEBUGGABLE && 169 SystemProperties.getBoolean(PROPERTY_CHILD_PACKAGES_ENABLED, false); 170 171 private static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f; 172 private static final float DEFAULT_PRE_Q_MIN_ASPECT_RATIO = 1.333f; 173 private static final float DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH = 1f; 174 175 private static final int DEFAULT_MIN_SDK_VERSION = 1; 176 private static final int DEFAULT_TARGET_SDK_VERSION = 0; 177 178 // TODO: switch outError users to PackageParserException 179 // TODO: refactor "codePath" to "apkPath" 180 181 /** File name in an APK for the Android manifest. */ 182 public static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml"; 183 184 /** Path prefix for apps on expanded storage */ 185 private static final String MNT_EXPAND = "/mnt/expand/"; 186 187 private static final String TAG_MANIFEST = "manifest"; 188 private static final String TAG_APPLICATION = "application"; 189 private static final String TAG_PACKAGE_VERIFIER = "package-verifier"; 190 private static final String TAG_OVERLAY = "overlay"; 191 private static final String TAG_KEY_SETS = "key-sets"; 192 private static final String TAG_PERMISSION_GROUP = "permission-group"; 193 private static final String TAG_PERMISSION = "permission"; 194 private static final String TAG_PERMISSION_TREE = "permission-tree"; 195 private static final String TAG_USES_PERMISSION = "uses-permission"; 196 private static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m"; 197 private static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23"; 198 private static final String TAG_USES_CONFIGURATION = "uses-configuration"; 199 private static final String TAG_USES_FEATURE = "uses-feature"; 200 private static final String TAG_FEATURE_GROUP = "feature-group"; 201 private static final String TAG_USES_SDK = "uses-sdk"; 202 private static final String TAG_SUPPORT_SCREENS = "supports-screens"; 203 private static final String TAG_PROTECTED_BROADCAST = "protected-broadcast"; 204 private static final String TAG_INSTRUMENTATION = "instrumentation"; 205 private static final String TAG_ORIGINAL_PACKAGE = "original-package"; 206 private static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions"; 207 private static final String TAG_USES_GL_TEXTURE = "uses-gl-texture"; 208 private static final String TAG_COMPATIBLE_SCREENS = "compatible-screens"; 209 private static final String TAG_SUPPORTS_INPUT = "supports-input"; 210 private static final String TAG_EAT_COMMENT = "eat-comment"; 211 private static final String TAG_PACKAGE = "package"; 212 private static final String TAG_RESTRICT_UPDATE = "restrict-update"; 213 private static final String TAG_USES_SPLIT = "uses-split"; 214 215 private static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect"; 216 217 /** 218 * Bit mask of all the valid bits that can be set in recreateOnConfigChanges. 219 * @hide 220 */ 221 private static final int RECREATE_ON_CONFIG_CHANGES_MASK = 222 ActivityInfo.CONFIG_MCC | ActivityInfo.CONFIG_MNC; 223 224 // These are the tags supported by child packages 225 private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>(); 226 static { 227 CHILD_PACKAGE_TAGS.add(TAG_APPLICATION); 228 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION); 229 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_M); 230 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_23); 231 CHILD_PACKAGE_TAGS.add(TAG_USES_CONFIGURATION); 232 CHILD_PACKAGE_TAGS.add(TAG_USES_FEATURE); 233 CHILD_PACKAGE_TAGS.add(TAG_FEATURE_GROUP); 234 CHILD_PACKAGE_TAGS.add(TAG_USES_SDK); 235 CHILD_PACKAGE_TAGS.add(TAG_SUPPORT_SCREENS); 236 CHILD_PACKAGE_TAGS.add(TAG_INSTRUMENTATION); 237 CHILD_PACKAGE_TAGS.add(TAG_USES_GL_TEXTURE); 238 CHILD_PACKAGE_TAGS.add(TAG_COMPATIBLE_SCREENS); 239 CHILD_PACKAGE_TAGS.add(TAG_SUPPORTS_INPUT); 240 CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT); 241 } 242 243 private static final boolean LOG_UNSAFE_BROADCASTS = false; 244 245 /** 246 * Total number of packages that were read from the cache. We use it only for logging. 247 */ 248 public static final AtomicInteger sCachedPackageReadCount = new AtomicInteger(); 249 250 // Set of broadcast actions that are safe for manifest receivers 251 private static final Set<String> SAFE_BROADCASTS = new ArraySet<>(); 252 static { 253 SAFE_BROADCASTS.add(Intent.ACTION_BOOT_COMPLETED); 254 } 255 256 /** @hide */ 257 public static final String APK_FILE_EXTENSION = ".apk"; 258 /** @hide */ 259 public static final String APEX_FILE_EXTENSION = ".apex"; 260 261 /** @hide */ 262 public static class NewPermissionInfo { 263 @UnsupportedAppUsage 264 public final String name; 265 @UnsupportedAppUsage 266 public final int sdkVersion; 267 public final int fileVersion; 268 NewPermissionInfo(String name, int sdkVersion, int fileVersion)269 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) { 270 this.name = name; 271 this.sdkVersion = sdkVersion; 272 this.fileVersion = fileVersion; 273 } 274 } 275 276 /** 277 * List of new permissions that have been added since 1.0. 278 * NOTE: These must be declared in SDK version order, with permissions 279 * added to older SDKs appearing before those added to newer SDKs. 280 * If sdkVersion is 0, then this is not a permission that we want to 281 * automatically add to older apps, but we do want to allow it to be 282 * granted during a platform update. 283 * @hide 284 */ 285 @UnsupportedAppUsage 286 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] = 287 new PackageParser.NewPermissionInfo[] { 288 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE, 289 android.os.Build.VERSION_CODES.DONUT, 0), 290 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE, 291 android.os.Build.VERSION_CODES.DONUT, 0) 292 }; 293 294 /** 295 * @deprecated callers should move to explicitly passing around source path. 296 */ 297 @Deprecated 298 private String mArchiveSourcePath; 299 300 private String[] mSeparateProcesses; 301 private boolean mOnlyCoreApps; 302 private DisplayMetrics mMetrics; 303 @UnsupportedAppUsage 304 private Callback mCallback; 305 private File mCacheDir; 306 307 private static final int SDK_VERSION = Build.VERSION.SDK_INT; 308 private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES; 309 310 private int mParseError = PackageManager.INSTALL_SUCCEEDED; 311 312 private static boolean sCompatibilityModeEnabled = true; 313 private static boolean sUseRoundIcon = false; 314 315 private static final int PARSE_DEFAULT_INSTALL_LOCATION = 316 PackageInfo.INSTALL_LOCATION_UNSPECIFIED; 317 private static final int PARSE_DEFAULT_TARGET_SANDBOX = 1; 318 319 static class ParsePackageItemArgs { 320 final Package owner; 321 final String[] outError; 322 final int nameRes; 323 final int labelRes; 324 final int iconRes; 325 final int roundIconRes; 326 final int logoRes; 327 final int bannerRes; 328 329 String tag; 330 TypedArray sa; 331 ParsePackageItemArgs(Package _owner, String[] _outError, int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes, int _bannerRes)332 ParsePackageItemArgs(Package _owner, String[] _outError, 333 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes, 334 int _bannerRes) { 335 owner = _owner; 336 outError = _outError; 337 nameRes = _nameRes; 338 labelRes = _labelRes; 339 iconRes = _iconRes; 340 logoRes = _logoRes; 341 bannerRes = _bannerRes; 342 roundIconRes = _roundIconRes; 343 } 344 } 345 346 /** @hide */ 347 @VisibleForTesting 348 public static class ParseComponentArgs extends ParsePackageItemArgs { 349 final String[] sepProcesses; 350 final int processRes; 351 final int descriptionRes; 352 final int enabledRes; 353 int flags; 354 ParseComponentArgs(Package _owner, String[] _outError, int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes, int _bannerRes, String[] _sepProcesses, int _processRes, int _descriptionRes, int _enabledRes)355 public ParseComponentArgs(Package _owner, String[] _outError, 356 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes, 357 int _bannerRes, 358 String[] _sepProcesses, int _processRes, 359 int _descriptionRes, int _enabledRes) { 360 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _roundIconRes, _logoRes, 361 _bannerRes); 362 sepProcesses = _sepProcesses; 363 processRes = _processRes; 364 descriptionRes = _descriptionRes; 365 enabledRes = _enabledRes; 366 } 367 } 368 369 /** 370 * Lightweight parsed details about a single package. 371 */ 372 public static class PackageLite { 373 @UnsupportedAppUsage 374 public final String packageName; 375 public final int versionCode; 376 public final int versionCodeMajor; 377 @UnsupportedAppUsage 378 public final int installLocation; 379 public final VerifierInfo[] verifiers; 380 381 /** Names of any split APKs, ordered by parsed splitName */ 382 public final String[] splitNames; 383 384 /** Names of any split APKs that are features. Ordered by splitName */ 385 public final boolean[] isFeatureSplits; 386 387 /** Dependencies of any split APKs, ordered by parsed splitName */ 388 public final String[] usesSplitNames; 389 public final String[] configForSplit; 390 391 /** 392 * Path where this package was found on disk. For monolithic packages 393 * this is path to single base APK file; for cluster packages this is 394 * path to the cluster directory. 395 */ 396 public final String codePath; 397 398 /** Path of base APK */ 399 public final String baseCodePath; 400 /** Paths of any split APKs, ordered by parsed splitName */ 401 public final String[] splitCodePaths; 402 403 /** Revision code of base APK */ 404 public final int baseRevisionCode; 405 /** Revision codes of any split APKs, ordered by parsed splitName */ 406 public final int[] splitRevisionCodes; 407 408 public final boolean coreApp; 409 public final boolean debuggable; 410 public final boolean multiArch; 411 public final boolean use32bitAbi; 412 public final boolean extractNativeLibs; 413 public final boolean isolatedSplits; 414 PackageLite(String codePath, ApkLite baseApk, String[] splitNames, boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit, String[] splitCodePaths, int[] splitRevisionCodes)415 public PackageLite(String codePath, ApkLite baseApk, String[] splitNames, 416 boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit, 417 String[] splitCodePaths, int[] splitRevisionCodes) { 418 this.packageName = baseApk.packageName; 419 this.versionCode = baseApk.versionCode; 420 this.versionCodeMajor = baseApk.versionCodeMajor; 421 this.installLocation = baseApk.installLocation; 422 this.verifiers = baseApk.verifiers; 423 this.splitNames = splitNames; 424 this.isFeatureSplits = isFeatureSplits; 425 this.usesSplitNames = usesSplitNames; 426 this.configForSplit = configForSplit; 427 this.codePath = codePath; 428 this.baseCodePath = baseApk.codePath; 429 this.splitCodePaths = splitCodePaths; 430 this.baseRevisionCode = baseApk.revisionCode; 431 this.splitRevisionCodes = splitRevisionCodes; 432 this.coreApp = baseApk.coreApp; 433 this.debuggable = baseApk.debuggable; 434 this.multiArch = baseApk.multiArch; 435 this.use32bitAbi = baseApk.use32bitAbi; 436 this.extractNativeLibs = baseApk.extractNativeLibs; 437 this.isolatedSplits = baseApk.isolatedSplits; 438 } 439 getAllCodePaths()440 public List<String> getAllCodePaths() { 441 ArrayList<String> paths = new ArrayList<>(); 442 paths.add(baseCodePath); 443 if (!ArrayUtils.isEmpty(splitCodePaths)) { 444 Collections.addAll(paths, splitCodePaths); 445 } 446 return paths; 447 } 448 } 449 450 /** 451 * Lightweight parsed details about a single APK file. 452 */ 453 public static class ApkLite { 454 public final String codePath; 455 public final String packageName; 456 public final String splitName; 457 public boolean isFeatureSplit; 458 public final String configForSplit; 459 public final String usesSplitName; 460 public final int versionCode; 461 public final int versionCodeMajor; 462 public final int revisionCode; 463 public final int installLocation; 464 public final int minSdkVersion; 465 public final int targetSdkVersion; 466 public final VerifierInfo[] verifiers; 467 public final SigningDetails signingDetails; 468 public final boolean coreApp; 469 public final boolean debuggable; 470 public final boolean multiArch; 471 public final boolean use32bitAbi; 472 public final boolean extractNativeLibs; 473 public final boolean isolatedSplits; 474 public final boolean isSplitRequired; 475 public final boolean useEmbeddedDex; 476 ApkLite(String codePath, String packageName, String splitName, boolean isFeatureSplit, String configForSplit, String usesSplitName, boolean isSplitRequired, int versionCode, int versionCodeMajor, int revisionCode, int installLocation, List<VerifierInfo> verifiers, SigningDetails signingDetails, boolean coreApp, boolean debuggable, boolean multiArch, boolean use32bitAbi, boolean useEmbeddedDex, boolean extractNativeLibs, boolean isolatedSplits, int minSdkVersion, int targetSdkVersion)477 public ApkLite(String codePath, String packageName, String splitName, 478 boolean isFeatureSplit, 479 String configForSplit, String usesSplitName, boolean isSplitRequired, 480 int versionCode, int versionCodeMajor, 481 int revisionCode, int installLocation, List<VerifierInfo> verifiers, 482 SigningDetails signingDetails, boolean coreApp, 483 boolean debuggable, boolean multiArch, boolean use32bitAbi, 484 boolean useEmbeddedDex, boolean extractNativeLibs, boolean isolatedSplits, 485 int minSdkVersion, int targetSdkVersion) { 486 this.codePath = codePath; 487 this.packageName = packageName; 488 this.splitName = splitName; 489 this.isFeatureSplit = isFeatureSplit; 490 this.configForSplit = configForSplit; 491 this.usesSplitName = usesSplitName; 492 this.versionCode = versionCode; 493 this.versionCodeMajor = versionCodeMajor; 494 this.revisionCode = revisionCode; 495 this.installLocation = installLocation; 496 this.signingDetails = signingDetails; 497 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]); 498 this.coreApp = coreApp; 499 this.debuggable = debuggable; 500 this.multiArch = multiArch; 501 this.use32bitAbi = use32bitAbi; 502 this.useEmbeddedDex = useEmbeddedDex; 503 this.extractNativeLibs = extractNativeLibs; 504 this.isolatedSplits = isolatedSplits; 505 this.isSplitRequired = isSplitRequired; 506 this.minSdkVersion = minSdkVersion; 507 this.targetSdkVersion = targetSdkVersion; 508 } 509 getLongVersionCode()510 public long getLongVersionCode() { 511 return PackageInfo.composeLongVersionCode(versionCodeMajor, versionCode); 512 } 513 } 514 515 /** 516 * Cached parse state for new components. 517 * 518 * Allows reuse of the same parse argument records to avoid GC pressure. Lifetime is carefully 519 * scoped to the parsing of a single application element. 520 */ 521 private static class CachedComponentArgs { 522 ParseComponentArgs mActivityArgs; 523 ParseComponentArgs mActivityAliasArgs; 524 ParseComponentArgs mServiceArgs; 525 ParseComponentArgs mProviderArgs; 526 } 527 528 /** 529 * Cached state for parsing instrumentation to avoid GC pressure. 530 * 531 * Must be manually reset to null for each new manifest. 532 */ 533 private ParsePackageItemArgs mParseInstrumentationArgs; 534 535 /** If set to true, we will only allow package files that exactly match 536 * the DTD. Otherwise, we try to get as much from the package as we 537 * can without failing. This should normally be set to false, to 538 * support extensions to the DTD in future versions. */ 539 private static final boolean RIGID_PARSER = false; 540 541 private static final String TAG = "PackageParser"; 542 543 @UnsupportedAppUsage PackageParser()544 public PackageParser() { 545 mMetrics = new DisplayMetrics(); 546 mMetrics.setToDefaults(); 547 } 548 549 @UnsupportedAppUsage setSeparateProcesses(String[] procs)550 public void setSeparateProcesses(String[] procs) { 551 mSeparateProcesses = procs; 552 } 553 554 /** 555 * Flag indicating this parser should only consider apps with 556 * {@code coreApp} manifest attribute to be valid apps. This is useful when 557 * creating a minimalist boot environment. 558 */ setOnlyCoreApps(boolean onlyCoreApps)559 public void setOnlyCoreApps(boolean onlyCoreApps) { 560 mOnlyCoreApps = onlyCoreApps; 561 } 562 setDisplayMetrics(DisplayMetrics metrics)563 public void setDisplayMetrics(DisplayMetrics metrics) { 564 mMetrics = metrics; 565 } 566 567 /** 568 * Sets the cache directory for this package parser. 569 */ setCacheDir(File cacheDir)570 public void setCacheDir(File cacheDir) { 571 mCacheDir = cacheDir; 572 } 573 574 /** 575 * Callback interface for retrieving information that may be needed while parsing 576 * a package. 577 */ 578 public interface Callback { hasFeature(String feature)579 boolean hasFeature(String feature); getOverlayPaths(String targetPackageName, String targetPath)580 String[] getOverlayPaths(String targetPackageName, String targetPath); getOverlayApks(String targetPackageName)581 String[] getOverlayApks(String targetPackageName); 582 } 583 584 /** 585 * Standard implementation of {@link Callback} on top of the public {@link PackageManager} 586 * class. 587 */ 588 public static final class CallbackImpl implements Callback { 589 private final PackageManager mPm; 590 CallbackImpl(PackageManager pm)591 public CallbackImpl(PackageManager pm) { 592 mPm = pm; 593 } 594 hasFeature(String feature)595 @Override public boolean hasFeature(String feature) { 596 return mPm.hasSystemFeature(feature); 597 } 598 getOverlayPaths(String targetPackageName, String targetPath)599 @Override public String[] getOverlayPaths(String targetPackageName, String targetPath) { 600 return null; 601 } 602 getOverlayApks(String targetPackageName)603 @Override public String[] getOverlayApks(String targetPackageName) { 604 return null; 605 } 606 } 607 608 /** 609 * Set the {@link Callback} that can be used while parsing. 610 */ setCallback(Callback cb)611 public void setCallback(Callback cb) { 612 mCallback = cb; 613 } 614 isApkFile(File file)615 public static final boolean isApkFile(File file) { 616 return isApkPath(file.getName()); 617 } 618 isApkPath(String path)619 public static boolean isApkPath(String path) { 620 return path.endsWith(APK_FILE_EXTENSION); 621 } 622 623 /** 624 * Returns true if the package is installed and not hidden, or if the caller 625 * explicitly wanted all uninstalled and hidden packages as well. 626 * @param appInfo The applicationInfo of the app being checked. 627 */ checkUseInstalledOrHidden(int flags, PackageUserState state, ApplicationInfo appInfo)628 private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state, 629 ApplicationInfo appInfo) { 630 // Returns false if the package is hidden system app until installed. 631 if ((flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) == 0 632 && !state.installed 633 && appInfo != null && appInfo.hiddenUntilInstalled) { 634 return false; 635 } 636 637 // If available for the target user, or trying to match uninstalled packages and it's 638 // a system app. 639 return state.isAvailable(flags) 640 || (appInfo != null && appInfo.isSystemApp() 641 && ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0 642 || (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0)); 643 } 644 isAvailable(PackageUserState state)645 public static boolean isAvailable(PackageUserState state) { 646 return checkUseInstalledOrHidden(0, state, null); 647 } 648 649 /** 650 * Generate and return the {@link PackageInfo} for a parsed package. 651 * 652 * @param p the parsed package. 653 * @param flags indicating which optional information is included. 654 */ 655 @UnsupportedAppUsage generatePackageInfo(PackageParser.Package p, int[] gids, int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state)656 public static PackageInfo generatePackageInfo(PackageParser.Package p, 657 int[] gids, int flags, long firstInstallTime, long lastUpdateTime, 658 Set<String> grantedPermissions, PackageUserState state) { 659 660 return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime, 661 grantedPermissions, state, UserHandle.getCallingUserId()); 662 } 663 664 @UnsupportedAppUsage generatePackageInfo(PackageParser.Package p, int[] gids, int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId)665 public static PackageInfo generatePackageInfo(PackageParser.Package p, 666 int[] gids, int flags, long firstInstallTime, long lastUpdateTime, 667 Set<String> grantedPermissions, PackageUserState state, int userId) { 668 669 return generatePackageInfo(p, null, gids, flags, firstInstallTime, lastUpdateTime, 670 grantedPermissions, state, userId); 671 } 672 673 /** 674 * PackageInfo generator specifically for apex files. 675 * 676 * @param pkg Package to generate info from. Should be derived from an apex. 677 * @param apexInfo Apex info relating to the package. 678 * @return PackageInfo 679 * @throws PackageParserException 680 */ generatePackageInfo( PackageParser.Package pkg, ApexInfo apexInfo, int flags)681 public static PackageInfo generatePackageInfo( 682 PackageParser.Package pkg, ApexInfo apexInfo, int flags) { 683 return generatePackageInfo(pkg, apexInfo, EmptyArray.INT, flags, 0, 0, 684 Collections.emptySet(), new PackageUserState(), UserHandle.getCallingUserId()); 685 } 686 generatePackageInfo(PackageParser.Package p, ApexInfo apexInfo, int gids[], int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId)687 private static PackageInfo generatePackageInfo(PackageParser.Package p, ApexInfo apexInfo, 688 int gids[], int flags, long firstInstallTime, long lastUpdateTime, 689 Set<String> grantedPermissions, PackageUserState state, int userId) { 690 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) { 691 return null; 692 } 693 PackageInfo pi = new PackageInfo(); 694 pi.packageName = p.packageName; 695 pi.splitNames = p.splitNames; 696 pi.versionCode = p.mVersionCode; 697 pi.versionCodeMajor = p.mVersionCodeMajor; 698 pi.baseRevisionCode = p.baseRevisionCode; 699 pi.splitRevisionCodes = p.splitRevisionCodes; 700 pi.versionName = p.mVersionName; 701 pi.sharedUserId = p.mSharedUserId; 702 pi.sharedUserLabel = p.mSharedUserLabel; 703 pi.applicationInfo = generateApplicationInfo(p, flags, state, userId); 704 pi.installLocation = p.installLocation; 705 pi.isStub = p.isStub; 706 pi.coreApp = p.coreApp; 707 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0 708 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) { 709 pi.requiredForAllUsers = p.mRequiredForAllUsers; 710 } 711 pi.restrictedAccountType = p.mRestrictedAccountType; 712 pi.requiredAccountType = p.mRequiredAccountType; 713 pi.overlayTarget = p.mOverlayTarget; 714 pi.targetOverlayableName = p.mOverlayTargetName; 715 pi.overlayCategory = p.mOverlayCategory; 716 pi.overlayPriority = p.mOverlayPriority; 717 pi.mOverlayIsStatic = p.mOverlayIsStatic; 718 pi.compileSdkVersion = p.mCompileSdkVersion; 719 pi.compileSdkVersionCodename = p.mCompileSdkVersionCodename; 720 pi.firstInstallTime = firstInstallTime; 721 pi.lastUpdateTime = lastUpdateTime; 722 if ((flags&PackageManager.GET_GIDS) != 0) { 723 pi.gids = gids; 724 } 725 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) { 726 int N = p.configPreferences != null ? p.configPreferences.size() : 0; 727 if (N > 0) { 728 pi.configPreferences = new ConfigurationInfo[N]; 729 p.configPreferences.toArray(pi.configPreferences); 730 } 731 N = p.reqFeatures != null ? p.reqFeatures.size() : 0; 732 if (N > 0) { 733 pi.reqFeatures = new FeatureInfo[N]; 734 p.reqFeatures.toArray(pi.reqFeatures); 735 } 736 N = p.featureGroups != null ? p.featureGroups.size() : 0; 737 if (N > 0) { 738 pi.featureGroups = new FeatureGroupInfo[N]; 739 p.featureGroups.toArray(pi.featureGroups); 740 } 741 } 742 if ((flags & PackageManager.GET_ACTIVITIES) != 0) { 743 final int N = p.activities.size(); 744 if (N > 0) { 745 int num = 0; 746 final ActivityInfo[] res = new ActivityInfo[N]; 747 for (int i = 0; i < N; i++) { 748 final Activity a = p.activities.get(i); 749 if (state.isMatch(a.info, flags)) { 750 if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(a.className)) { 751 continue; 752 } 753 res[num++] = generateActivityInfo(a, flags, state, userId); 754 } 755 } 756 pi.activities = ArrayUtils.trimToSize(res, num); 757 } 758 } 759 if ((flags & PackageManager.GET_RECEIVERS) != 0) { 760 final int N = p.receivers.size(); 761 if (N > 0) { 762 int num = 0; 763 final ActivityInfo[] res = new ActivityInfo[N]; 764 for (int i = 0; i < N; i++) { 765 final Activity a = p.receivers.get(i); 766 if (state.isMatch(a.info, flags)) { 767 res[num++] = generateActivityInfo(a, flags, state, userId); 768 } 769 } 770 pi.receivers = ArrayUtils.trimToSize(res, num); 771 } 772 } 773 if ((flags & PackageManager.GET_SERVICES) != 0) { 774 final int N = p.services.size(); 775 if (N > 0) { 776 int num = 0; 777 final ServiceInfo[] res = new ServiceInfo[N]; 778 for (int i = 0; i < N; i++) { 779 final Service s = p.services.get(i); 780 if (state.isMatch(s.info, flags)) { 781 res[num++] = generateServiceInfo(s, flags, state, userId); 782 } 783 } 784 pi.services = ArrayUtils.trimToSize(res, num); 785 } 786 } 787 if ((flags & PackageManager.GET_PROVIDERS) != 0) { 788 final int N = p.providers.size(); 789 if (N > 0) { 790 int num = 0; 791 final ProviderInfo[] res = new ProviderInfo[N]; 792 for (int i = 0; i < N; i++) { 793 final Provider pr = p.providers.get(i); 794 if (state.isMatch(pr.info, flags)) { 795 res[num++] = generateProviderInfo(pr, flags, state, userId); 796 } 797 } 798 pi.providers = ArrayUtils.trimToSize(res, num); 799 } 800 } 801 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) { 802 int N = p.instrumentation.size(); 803 if (N > 0) { 804 pi.instrumentation = new InstrumentationInfo[N]; 805 for (int i=0; i<N; i++) { 806 pi.instrumentation[i] = generateInstrumentationInfo( 807 p.instrumentation.get(i), flags); 808 } 809 } 810 } 811 if ((flags&PackageManager.GET_PERMISSIONS) != 0) { 812 int N = p.permissions.size(); 813 if (N > 0) { 814 pi.permissions = new PermissionInfo[N]; 815 for (int i=0; i<N; i++) { 816 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags); 817 } 818 } 819 N = p.requestedPermissions.size(); 820 if (N > 0) { 821 pi.requestedPermissions = new String[N]; 822 pi.requestedPermissionsFlags = new int[N]; 823 for (int i=0; i<N; i++) { 824 final String perm = p.requestedPermissions.get(i); 825 pi.requestedPermissions[i] = perm; 826 // The notion of required permissions is deprecated but for compatibility. 827 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED; 828 if (grantedPermissions != null && grantedPermissions.contains(perm)) { 829 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED; 830 } 831 } 832 } 833 } 834 835 if (apexInfo != null) { 836 File apexFile = new File(apexInfo.modulePath); 837 838 pi.applicationInfo.sourceDir = apexFile.getPath(); 839 pi.applicationInfo.publicSourceDir = apexFile.getPath(); 840 if (apexInfo.isFactory) { 841 pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; 842 } else { 843 pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM; 844 } 845 if (apexInfo.isActive) { 846 pi.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED; 847 } else { 848 pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED; 849 } 850 pi.isApex = true; 851 } 852 853 // deprecated method of getting signing certificates 854 if ((flags & PackageManager.GET_SIGNATURES) != 0) { 855 if (p.mSigningDetails.hasPastSigningCertificates()) { 856 // Package has included signing certificate rotation information. Return the oldest 857 // cert so that programmatic checks keep working even if unaware of key rotation. 858 pi.signatures = new Signature[1]; 859 pi.signatures[0] = p.mSigningDetails.pastSigningCertificates[0]; 860 } else if (p.mSigningDetails.hasSignatures()) { 861 // otherwise keep old behavior 862 int numberOfSigs = p.mSigningDetails.signatures.length; 863 pi.signatures = new Signature[numberOfSigs]; 864 System.arraycopy(p.mSigningDetails.signatures, 0, pi.signatures, 0, numberOfSigs); 865 } 866 } 867 868 // replacement for GET_SIGNATURES 869 if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) { 870 if (p.mSigningDetails != SigningDetails.UNKNOWN) { 871 // only return a valid SigningInfo if there is signing information to report 872 pi.signingInfo = new SigningInfo(p.mSigningDetails); 873 } else { 874 pi.signingInfo = null; 875 } 876 } 877 return pi; 878 } 879 880 public static final int PARSE_MUST_BE_APK = 1 << 0; 881 public static final int PARSE_IGNORE_PROCESSES = 1 << 1; 882 public static final int PARSE_EXTERNAL_STORAGE = 1 << 3; 883 public static final int PARSE_IS_SYSTEM_DIR = 1 << 4; 884 public static final int PARSE_COLLECT_CERTIFICATES = 1 << 5; 885 public static final int PARSE_ENFORCE_CODE = 1 << 6; 886 public static final int PARSE_CHATTY = 1 << 31; 887 888 @IntDef(flag = true, prefix = { "PARSE_" }, value = { 889 PARSE_CHATTY, 890 PARSE_COLLECT_CERTIFICATES, 891 PARSE_ENFORCE_CODE, 892 PARSE_EXTERNAL_STORAGE, 893 PARSE_IGNORE_PROCESSES, 894 PARSE_IS_SYSTEM_DIR, 895 PARSE_MUST_BE_APK, 896 }) 897 @Retention(RetentionPolicy.SOURCE) 898 public @interface ParseFlags {} 899 900 private static final Comparator<String> sSplitNameComparator = new SplitNameComparator(); 901 902 /** 903 * Used to sort a set of APKs based on their split names, always placing the 904 * base APK (with {@code null} split name) first. 905 */ 906 private static class SplitNameComparator implements Comparator<String> { 907 @Override compare(String lhs, String rhs)908 public int compare(String lhs, String rhs) { 909 if (lhs == null) { 910 return -1; 911 } else if (rhs == null) { 912 return 1; 913 } else { 914 return lhs.compareTo(rhs); 915 } 916 } 917 } 918 919 /** 920 * Parse only lightweight details about the package at the given location. 921 * Automatically detects if the package is a monolithic style (single APK 922 * file) or cluster style (directory of APKs). 923 * <p> 924 * This performs checking on cluster style packages, such as 925 * requiring identical package name and version codes, a single base APK, 926 * and unique split names. 927 * 928 * @see PackageParser#parsePackage(File, int) 929 */ 930 @UnsupportedAppUsage parsePackageLite(File packageFile, int flags)931 public static PackageLite parsePackageLite(File packageFile, int flags) 932 throws PackageParserException { 933 if (packageFile.isDirectory()) { 934 return parseClusterPackageLite(packageFile, flags); 935 } else { 936 return parseMonolithicPackageLite(packageFile, flags); 937 } 938 } 939 parseMonolithicPackageLite(File packageFile, int flags)940 private static PackageLite parseMonolithicPackageLite(File packageFile, int flags) 941 throws PackageParserException { 942 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite"); 943 final ApkLite baseApk = parseApkLite(packageFile, flags); 944 final String packagePath = packageFile.getAbsolutePath(); 945 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 946 return new PackageLite(packagePath, baseApk, null, null, null, null, null, null); 947 } 948 parseClusterPackageLite(File packageDir, int flags)949 static PackageLite parseClusterPackageLite(File packageDir, int flags) 950 throws PackageParserException { 951 final File[] files = packageDir.listFiles(); 952 if (ArrayUtils.isEmpty(files)) { 953 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, 954 "No packages found in split"); 955 } 956 957 String packageName = null; 958 int versionCode = 0; 959 960 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite"); 961 final ArrayMap<String, ApkLite> apks = new ArrayMap<>(); 962 for (File file : files) { 963 if (isApkFile(file)) { 964 final ApkLite lite = parseApkLite(file, flags); 965 966 // Assert that all package names and version codes are 967 // consistent with the first one we encounter. 968 if (packageName == null) { 969 packageName = lite.packageName; 970 versionCode = lite.versionCode; 971 } else { 972 if (!packageName.equals(lite.packageName)) { 973 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, 974 "Inconsistent package " + lite.packageName + " in " + file 975 + "; expected " + packageName); 976 } 977 if (versionCode != lite.versionCode) { 978 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, 979 "Inconsistent version " + lite.versionCode + " in " + file 980 + "; expected " + versionCode); 981 } 982 } 983 984 // Assert that each split is defined only once 985 if (apks.put(lite.splitName, lite) != null) { 986 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, 987 "Split name " + lite.splitName 988 + " defined more than once; most recent was " + file); 989 } 990 } 991 } 992 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 993 994 final ApkLite baseApk = apks.remove(null); 995 if (baseApk == null) { 996 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, 997 "Missing base APK in " + packageDir); 998 } 999 1000 // Always apply deterministic ordering based on splitName 1001 final int size = apks.size(); 1002 1003 String[] splitNames = null; 1004 boolean[] isFeatureSplits = null; 1005 String[] usesSplitNames = null; 1006 String[] configForSplits = null; 1007 String[] splitCodePaths = null; 1008 int[] splitRevisionCodes = null; 1009 String[] splitClassLoaderNames = null; 1010 if (size > 0) { 1011 splitNames = new String[size]; 1012 isFeatureSplits = new boolean[size]; 1013 usesSplitNames = new String[size]; 1014 configForSplits = new String[size]; 1015 splitCodePaths = new String[size]; 1016 splitRevisionCodes = new int[size]; 1017 1018 splitNames = apks.keySet().toArray(splitNames); 1019 Arrays.sort(splitNames, sSplitNameComparator); 1020 1021 for (int i = 0; i < size; i++) { 1022 final ApkLite apk = apks.get(splitNames[i]); 1023 usesSplitNames[i] = apk.usesSplitName; 1024 isFeatureSplits[i] = apk.isFeatureSplit; 1025 configForSplits[i] = apk.configForSplit; 1026 splitCodePaths[i] = apk.codePath; 1027 splitRevisionCodes[i] = apk.revisionCode; 1028 } 1029 } 1030 1031 final String codePath = packageDir.getAbsolutePath(); 1032 return new PackageLite(codePath, baseApk, splitNames, isFeatureSplits, usesSplitNames, 1033 configForSplits, splitCodePaths, splitRevisionCodes); 1034 } 1035 1036 /** 1037 * Parse the package at the given location. Automatically detects if the 1038 * package is a monolithic style (single APK file) or cluster style 1039 * (directory of APKs). 1040 * <p> 1041 * This performs checking on cluster style packages, such as 1042 * requiring identical package name and version codes, a single base APK, 1043 * and unique split names. 1044 * <p> 1045 * Note that this <em>does not</em> perform signature verification; that 1046 * must be done separately in {@link #collectCertificates(Package, int)}. 1047 * 1048 * If {@code useCaches} is true, the package parser might return a cached 1049 * result from a previous parse of the same {@code packageFile} with the same 1050 * {@code flags}. Note that this method does not check whether {@code packageFile} 1051 * has changed since the last parse, it's up to callers to do so. 1052 * 1053 * @see #parsePackageLite(File, int) 1054 */ 1055 @UnsupportedAppUsage parsePackage(File packageFile, int flags, boolean useCaches)1056 public Package parsePackage(File packageFile, int flags, boolean useCaches) 1057 throws PackageParserException { 1058 Package parsed = useCaches ? getCachedResult(packageFile, flags) : null; 1059 if (parsed != null) { 1060 return parsed; 1061 } 1062 1063 long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0; 1064 if (packageFile.isDirectory()) { 1065 parsed = parseClusterPackage(packageFile, flags); 1066 } else { 1067 parsed = parseMonolithicPackage(packageFile, flags); 1068 } 1069 1070 long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0; 1071 cacheResult(packageFile, flags, parsed); 1072 if (LOG_PARSE_TIMINGS) { 1073 parseTime = cacheTime - parseTime; 1074 cacheTime = SystemClock.uptimeMillis() - cacheTime; 1075 if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) { 1076 Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime 1077 + "ms, update_cache=" + cacheTime + " ms"); 1078 } 1079 } 1080 return parsed; 1081 } 1082 1083 /** 1084 * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}. 1085 */ 1086 @UnsupportedAppUsage parsePackage(File packageFile, int flags)1087 public Package parsePackage(File packageFile, int flags) throws PackageParserException { 1088 return parsePackage(packageFile, flags, false /* useCaches */); 1089 } 1090 1091 /** 1092 * Returns the cache key for a specificied {@code packageFile} and {@code flags}. 1093 */ getCacheKey(File packageFile, int flags)1094 private String getCacheKey(File packageFile, int flags) { 1095 StringBuilder sb = new StringBuilder(packageFile.getName()); 1096 sb.append('-'); 1097 sb.append(flags); 1098 1099 return sb.toString(); 1100 } 1101 1102 @VisibleForTesting fromCacheEntry(byte[] bytes)1103 protected Package fromCacheEntry(byte[] bytes) { 1104 return fromCacheEntryStatic(bytes); 1105 } 1106 1107 /** static version of {@link #fromCacheEntry} for unit tests. */ 1108 @VisibleForTesting fromCacheEntryStatic(byte[] bytes)1109 public static Package fromCacheEntryStatic(byte[] bytes) { 1110 final Parcel p = Parcel.obtain(); 1111 p.unmarshall(bytes, 0, bytes.length); 1112 p.setDataPosition(0); 1113 1114 final ReadHelper helper = new ReadHelper(p); 1115 helper.startAndInstall(); 1116 1117 PackageParser.Package pkg = new PackageParser.Package(p); 1118 1119 p.recycle(); 1120 1121 sCachedPackageReadCount.incrementAndGet(); 1122 1123 return pkg; 1124 } 1125 1126 @VisibleForTesting toCacheEntry(Package pkg)1127 protected byte[] toCacheEntry(Package pkg) { 1128 return toCacheEntryStatic(pkg); 1129 1130 } 1131 1132 /** static version of {@link #toCacheEntry} for unit tests. */ 1133 @VisibleForTesting toCacheEntryStatic(Package pkg)1134 public static byte[] toCacheEntryStatic(Package pkg) { 1135 final Parcel p = Parcel.obtain(); 1136 final WriteHelper helper = new WriteHelper(p); 1137 1138 pkg.writeToParcel(p, 0 /* flags */); 1139 1140 helper.finishAndUninstall(); 1141 1142 byte[] serialized = p.marshall(); 1143 p.recycle(); 1144 1145 return serialized; 1146 } 1147 1148 /** 1149 * Given a {@code packageFile} and a {@code cacheFile} returns whether the 1150 * cache file is up to date based on the mod-time of both files. 1151 */ isCacheUpToDate(File packageFile, File cacheFile)1152 private static boolean isCacheUpToDate(File packageFile, File cacheFile) { 1153 try { 1154 // NOTE: We don't use the File.lastModified API because it has the very 1155 // non-ideal failure mode of returning 0 with no excepions thrown. 1156 // The nio2 Files API is a little better but is considerably more expensive. 1157 final StructStat pkg = android.system.Os.stat(packageFile.getAbsolutePath()); 1158 final StructStat cache = android.system.Os.stat(cacheFile.getAbsolutePath()); 1159 return pkg.st_mtime < cache.st_mtime; 1160 } catch (ErrnoException ee) { 1161 // The most common reason why stat fails is that a given cache file doesn't 1162 // exist. We ignore that here. It's easy to reason that it's safe to say the 1163 // cache isn't up to date if we see any sort of exception here. 1164 // 1165 // (1) Exception while stating the package file : This should never happen, 1166 // and if it does, we do a full package parse (which is likely to throw the 1167 // same exception). 1168 // (2) Exception while stating the cache file : If the file doesn't exist, the 1169 // cache is obviously out of date. If the file *does* exist, we can't read it. 1170 // We will attempt to delete and recreate it after parsing the package. 1171 if (ee.errno != OsConstants.ENOENT) { 1172 Slog.w("Error while stating package cache : ", ee); 1173 } 1174 1175 return false; 1176 } 1177 } 1178 1179 /** 1180 * Returns the cached parse result for {@code packageFile} for parse flags {@code flags}, 1181 * or {@code null} if no cached result exists. 1182 */ getCachedResult(File packageFile, int flags)1183 private Package getCachedResult(File packageFile, int flags) { 1184 if (mCacheDir == null) { 1185 return null; 1186 } 1187 1188 final String cacheKey = getCacheKey(packageFile, flags); 1189 final File cacheFile = new File(mCacheDir, cacheKey); 1190 1191 try { 1192 // If the cache is not up to date, return null. 1193 if (!isCacheUpToDate(packageFile, cacheFile)) { 1194 return null; 1195 } 1196 1197 final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath()); 1198 Package p = fromCacheEntry(bytes); 1199 if (mCallback != null) { 1200 String[] overlayApks = mCallback.getOverlayApks(p.packageName); 1201 if (overlayApks != null && overlayApks.length > 0) { 1202 for (String overlayApk : overlayApks) { 1203 // If a static RRO is updated, return null. 1204 if (!isCacheUpToDate(new File(overlayApk), cacheFile)) { 1205 return null; 1206 } 1207 } 1208 } 1209 } 1210 return p; 1211 } catch (Throwable e) { 1212 Slog.w(TAG, "Error reading package cache: ", e); 1213 1214 // If something went wrong while reading the cache entry, delete the cache file 1215 // so that we regenerate it the next time. 1216 cacheFile.delete(); 1217 return null; 1218 } 1219 } 1220 1221 /** 1222 * Caches the parse result for {@code packageFile} with flags {@code flags}. 1223 */ cacheResult(File packageFile, int flags, Package parsed)1224 private void cacheResult(File packageFile, int flags, Package parsed) { 1225 if (mCacheDir == null) { 1226 return; 1227 } 1228 1229 try { 1230 final String cacheKey = getCacheKey(packageFile, flags); 1231 final File cacheFile = new File(mCacheDir, cacheKey); 1232 1233 if (cacheFile.exists()) { 1234 if (!cacheFile.delete()) { 1235 Slog.e(TAG, "Unable to delete cache file: " + cacheFile); 1236 } 1237 } 1238 1239 final byte[] cacheEntry = toCacheEntry(parsed); 1240 1241 if (cacheEntry == null) { 1242 return; 1243 } 1244 1245 try (FileOutputStream fos = new FileOutputStream(cacheFile)) { 1246 fos.write(cacheEntry); 1247 } catch (IOException ioe) { 1248 Slog.w(TAG, "Error writing cache entry.", ioe); 1249 cacheFile.delete(); 1250 } 1251 } catch (Throwable e) { 1252 Slog.w(TAG, "Error saving package cache.", e); 1253 } 1254 } 1255 1256 /** 1257 * Parse all APKs contained in the given directory, treating them as a 1258 * single package. This also performs checking, such as requiring 1259 * identical package name and version codes, a single base APK, and unique 1260 * split names. 1261 * <p> 1262 * Note that this <em>does not</em> perform signature verification; that 1263 * must be done separately in {@link #collectCertificates(Package, int)}. 1264 */ parseClusterPackage(File packageDir, int flags)1265 private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException { 1266 final PackageLite lite = parseClusterPackageLite(packageDir, 0); 1267 if (mOnlyCoreApps && !lite.coreApp) { 1268 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, 1269 "Not a coreApp: " + packageDir); 1270 } 1271 1272 // Build the split dependency tree. 1273 SparseArray<int[]> splitDependencies = null; 1274 final SplitAssetLoader assetLoader; 1275 if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) { 1276 try { 1277 splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite); 1278 assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags); 1279 } catch (SplitAssetDependencyLoader.IllegalDependencyException e) { 1280 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage()); 1281 } 1282 } else { 1283 assetLoader = new DefaultSplitAssetLoader(lite, flags); 1284 } 1285 1286 try { 1287 final AssetManager assets = assetLoader.getBaseAssetManager(); 1288 final File baseApk = new File(lite.baseCodePath); 1289 final Package pkg = parseBaseApk(baseApk, assets, flags); 1290 if (pkg == null) { 1291 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, 1292 "Failed to parse base APK: " + baseApk); 1293 } 1294 1295 if (!ArrayUtils.isEmpty(lite.splitNames)) { 1296 final int num = lite.splitNames.length; 1297 pkg.splitNames = lite.splitNames; 1298 pkg.splitCodePaths = lite.splitCodePaths; 1299 pkg.splitRevisionCodes = lite.splitRevisionCodes; 1300 pkg.splitFlags = new int[num]; 1301 pkg.splitPrivateFlags = new int[num]; 1302 pkg.applicationInfo.splitNames = pkg.splitNames; 1303 pkg.applicationInfo.splitDependencies = splitDependencies; 1304 pkg.applicationInfo.splitClassLoaderNames = new String[num]; 1305 1306 for (int i = 0; i < num; i++) { 1307 final AssetManager splitAssets = assetLoader.getSplitAssetManager(i); 1308 parseSplitApk(pkg, i, splitAssets, flags); 1309 } 1310 } 1311 1312 pkg.setCodePath(packageDir.getCanonicalPath()); 1313 pkg.setUse32bitAbi(lite.use32bitAbi); 1314 return pkg; 1315 } catch (IOException e) { 1316 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, 1317 "Failed to get path: " + lite.baseCodePath, e); 1318 } finally { 1319 IoUtils.closeQuietly(assetLoader); 1320 } 1321 } 1322 1323 /** 1324 * Parse the given APK file, treating it as as a single monolithic package. 1325 * <p> 1326 * Note that this <em>does not</em> perform signature verification; that 1327 * must be done separately in {@link #collectCertificates(Package, int)}. 1328 * 1329 * @deprecated external callers should move to 1330 * {@link #parsePackage(File, int)}. Eventually this method will 1331 * be marked private. 1332 */ 1333 @Deprecated 1334 @UnsupportedAppUsage parseMonolithicPackage(File apkFile, int flags)1335 public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException { 1336 final PackageLite lite = parseMonolithicPackageLite(apkFile, flags); 1337 if (mOnlyCoreApps) { 1338 if (!lite.coreApp) { 1339 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, 1340 "Not a coreApp: " + apkFile); 1341 } 1342 } 1343 1344 final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags); 1345 try { 1346 final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags); 1347 pkg.setCodePath(apkFile.getCanonicalPath()); 1348 pkg.setUse32bitAbi(lite.use32bitAbi); 1349 return pkg; 1350 } catch (IOException e) { 1351 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, 1352 "Failed to get path: " + apkFile, e); 1353 } finally { 1354 IoUtils.closeQuietly(assetLoader); 1355 } 1356 } 1357 parseBaseApk(File apkFile, AssetManager assets, int flags)1358 private Package parseBaseApk(File apkFile, AssetManager assets, int flags) 1359 throws PackageParserException { 1360 final String apkPath = apkFile.getAbsolutePath(); 1361 1362 String volumeUuid = null; 1363 if (apkPath.startsWith(MNT_EXPAND)) { 1364 final int end = apkPath.indexOf('/', MNT_EXPAND.length()); 1365 volumeUuid = apkPath.substring(MNT_EXPAND.length(), end); 1366 } 1367 1368 mParseError = PackageManager.INSTALL_SUCCEEDED; 1369 mArchiveSourcePath = apkFile.getAbsolutePath(); 1370 1371 if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath); 1372 1373 XmlResourceParser parser = null; 1374 try { 1375 final int cookie = assets.findCookieForPath(apkPath); 1376 if (cookie == 0) { 1377 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, 1378 "Failed adding asset path: " + apkPath); 1379 } 1380 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME); 1381 final Resources res = new Resources(assets, mMetrics, null); 1382 1383 final String[] outError = new String[1]; 1384 final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError); 1385 if (pkg == null) { 1386 throw new PackageParserException(mParseError, 1387 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]); 1388 } 1389 1390 pkg.setVolumeUuid(volumeUuid); 1391 pkg.setApplicationVolumeUuid(volumeUuid); 1392 pkg.setBaseCodePath(apkPath); 1393 pkg.setSigningDetails(SigningDetails.UNKNOWN); 1394 1395 return pkg; 1396 1397 } catch (PackageParserException e) { 1398 throw e; 1399 } catch (Exception e) { 1400 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, 1401 "Failed to read manifest from " + apkPath, e); 1402 } finally { 1403 IoUtils.closeQuietly(parser); 1404 } 1405 } 1406 parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)1407 private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags) 1408 throws PackageParserException { 1409 final String apkPath = pkg.splitCodePaths[splitIndex]; 1410 1411 mParseError = PackageManager.INSTALL_SUCCEEDED; 1412 mArchiveSourcePath = apkPath; 1413 1414 if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath); 1415 1416 final Resources res; 1417 XmlResourceParser parser = null; 1418 try { 1419 // This must always succeed, as the path has been added to the AssetManager before. 1420 final int cookie = assets.findCookieForPath(apkPath); 1421 if (cookie == 0) { 1422 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, 1423 "Failed adding asset path: " + apkPath); 1424 } 1425 1426 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME); 1427 res = new Resources(assets, mMetrics, null); 1428 1429 final String[] outError = new String[1]; 1430 pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError); 1431 if (pkg == null) { 1432 throw new PackageParserException(mParseError, 1433 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]); 1434 } 1435 1436 } catch (PackageParserException e) { 1437 throw e; 1438 } catch (Exception e) { 1439 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, 1440 "Failed to read manifest from " + apkPath, e); 1441 } finally { 1442 IoUtils.closeQuietly(parser); 1443 } 1444 } 1445 1446 /** 1447 * Parse the manifest of a <em>split APK</em>. 1448 * <p> 1449 * Note that split APKs have many more restrictions on what they're capable 1450 * of doing, so many valid features of a base APK have been carefully 1451 * omitted here. 1452 */ parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags, int splitIndex, String[] outError)1453 private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags, 1454 int splitIndex, String[] outError) throws XmlPullParserException, IOException, 1455 PackageParserException { 1456 AttributeSet attrs = parser; 1457 1458 // We parsed manifest tag earlier; just skip past it 1459 parsePackageSplitNames(parser, attrs); 1460 1461 mParseInstrumentationArgs = null; 1462 1463 int type; 1464 1465 boolean foundApp = false; 1466 1467 int outerDepth = parser.getDepth(); 1468 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 1469 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 1470 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 1471 continue; 1472 } 1473 1474 String tagName = parser.getName(); 1475 if (tagName.equals(TAG_APPLICATION)) { 1476 if (foundApp) { 1477 if (RIGID_PARSER) { 1478 outError[0] = "<manifest> has more than one <application>"; 1479 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1480 return null; 1481 } else { 1482 Slog.w(TAG, "<manifest> has more than one <application>"); 1483 XmlUtils.skipCurrentTag(parser); 1484 continue; 1485 } 1486 } 1487 1488 foundApp = true; 1489 if (!parseSplitApplication(pkg, res, parser, flags, splitIndex, outError)) { 1490 return null; 1491 } 1492 1493 } else if (RIGID_PARSER) { 1494 outError[0] = "Bad element under <manifest>: " 1495 + parser.getName(); 1496 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1497 return null; 1498 1499 } else { 1500 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName() 1501 + " at " + mArchiveSourcePath + " " 1502 + parser.getPositionDescription()); 1503 XmlUtils.skipCurrentTag(parser); 1504 continue; 1505 } 1506 } 1507 1508 if (!foundApp) { 1509 outError[0] = "<manifest> does not contain an <application>"; 1510 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY; 1511 } 1512 1513 return pkg; 1514 } 1515 1516 /** Parses the public keys from the set of signatures. */ toSigningKeys(Signature[] signatures)1517 public static ArraySet<PublicKey> toSigningKeys(Signature[] signatures) 1518 throws CertificateException { 1519 ArraySet<PublicKey> keys = new ArraySet<>(signatures.length); 1520 for (int i = 0; i < signatures.length; i++) { 1521 keys.add(signatures[i].getPublicKey()); 1522 } 1523 return keys; 1524 } 1525 1526 /** 1527 * Collect certificates from all the APKs described in the given package, 1528 * populating {@link Package#mSigningDetails}. Also asserts that all APK 1529 * contents are signed correctly and consistently. 1530 */ 1531 @UnsupportedAppUsage collectCertificates(Package pkg, boolean skipVerify)1532 public static void collectCertificates(Package pkg, boolean skipVerify) 1533 throws PackageParserException { 1534 collectCertificatesInternal(pkg, skipVerify); 1535 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; 1536 for (int i = 0; i < childCount; i++) { 1537 Package childPkg = pkg.childPackages.get(i); 1538 childPkg.mSigningDetails = pkg.mSigningDetails; 1539 } 1540 } 1541 collectCertificatesInternal(Package pkg, boolean skipVerify)1542 private static void collectCertificatesInternal(Package pkg, boolean skipVerify) 1543 throws PackageParserException { 1544 pkg.mSigningDetails = SigningDetails.UNKNOWN; 1545 1546 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates"); 1547 try { 1548 collectCertificates(pkg, new File(pkg.baseCodePath), skipVerify); 1549 1550 if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { 1551 for (int i = 0; i < pkg.splitCodePaths.length; i++) { 1552 collectCertificates(pkg, new File(pkg.splitCodePaths[i]), skipVerify); 1553 } 1554 } 1555 } finally { 1556 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 1557 } 1558 } 1559 1560 @UnsupportedAppUsage collectCertificates(Package pkg, File apkFile, boolean skipVerify)1561 private static void collectCertificates(Package pkg, File apkFile, boolean skipVerify) 1562 throws PackageParserException { 1563 final String apkPath = apkFile.getAbsolutePath(); 1564 1565 int minSignatureScheme = SigningDetails.SignatureSchemeVersion.JAR; 1566 if (pkg.applicationInfo.isStaticSharedLibrary()) { 1567 // must use v2 signing scheme 1568 minSignatureScheme = SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2; 1569 } 1570 SigningDetails verified; 1571 if (skipVerify) { 1572 // systemDir APKs are already trusted, save time by not verifying 1573 verified = ApkSignatureVerifier.unsafeGetCertsWithoutVerification( 1574 apkPath, minSignatureScheme); 1575 } else { 1576 verified = ApkSignatureVerifier.verify(apkPath, minSignatureScheme); 1577 } 1578 1579 // Verify that entries are signed consistently with the first pkg 1580 // we encountered. Note that for splits, certificates may have 1581 // already been populated during an earlier parse of a base APK. 1582 if (pkg.mSigningDetails == SigningDetails.UNKNOWN) { 1583 pkg.mSigningDetails = verified; 1584 } else { 1585 if (!Signature.areExactMatch(pkg.mSigningDetails.signatures, verified.signatures)) { 1586 throw new PackageParserException( 1587 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, 1588 apkPath + " has mismatched certificates"); 1589 } 1590 } 1591 } 1592 newConfiguredAssetManager()1593 private static AssetManager newConfiguredAssetManager() { 1594 AssetManager assetManager = new AssetManager(); 1595 assetManager.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1596 Build.VERSION.RESOURCES_SDK_INT); 1597 return assetManager; 1598 } 1599 1600 /** 1601 * Utility method that retrieves lightweight details about a single APK 1602 * file, including package name, split name, and install location. 1603 * 1604 * @param apkFile path to a single APK 1605 * @param flags optional parse flags, such as 1606 * {@link #PARSE_COLLECT_CERTIFICATES} 1607 */ parseApkLite(File apkFile, int flags)1608 public static ApkLite parseApkLite(File apkFile, int flags) 1609 throws PackageParserException { 1610 return parseApkLiteInner(apkFile, null, null, flags); 1611 } 1612 1613 /** 1614 * Utility method that retrieves lightweight details about a single APK 1615 * file, including package name, split name, and install location. 1616 * 1617 * @param fd already open file descriptor of an apk file 1618 * @param debugPathName arbitrary text name for this file, for debug output 1619 * @param flags optional parse flags, such as 1620 * {@link #PARSE_COLLECT_CERTIFICATES} 1621 */ parseApkLite(FileDescriptor fd, String debugPathName, int flags)1622 public static ApkLite parseApkLite(FileDescriptor fd, String debugPathName, int flags) 1623 throws PackageParserException { 1624 return parseApkLiteInner(null, fd, debugPathName, flags); 1625 } 1626 parseApkLiteInner(File apkFile, FileDescriptor fd, String debugPathName, int flags)1627 private static ApkLite parseApkLiteInner(File apkFile, FileDescriptor fd, String debugPathName, 1628 int flags) throws PackageParserException { 1629 final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath(); 1630 1631 XmlResourceParser parser = null; 1632 ApkAssets apkAssets = null; 1633 try { 1634 try { 1635 apkAssets = fd != null 1636 ? ApkAssets.loadFromFd(fd, debugPathName, false, false) 1637 : ApkAssets.loadFromPath(apkPath); 1638 } catch (IOException e) { 1639 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, 1640 "Failed to parse " + apkPath); 1641 } 1642 1643 parser = apkAssets.openXml(ANDROID_MANIFEST_FILENAME); 1644 1645 final SigningDetails signingDetails; 1646 if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) { 1647 // TODO: factor signature related items out of Package object 1648 final Package tempPkg = new Package((String) null); 1649 final boolean skipVerify = (flags & PARSE_IS_SYSTEM_DIR) != 0; 1650 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates"); 1651 try { 1652 collectCertificates(tempPkg, apkFile, skipVerify); 1653 } finally { 1654 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 1655 } 1656 signingDetails = tempPkg.mSigningDetails; 1657 } else { 1658 signingDetails = SigningDetails.UNKNOWN; 1659 } 1660 1661 final AttributeSet attrs = parser; 1662 return parseApkLite(apkPath, parser, attrs, signingDetails); 1663 1664 } catch (XmlPullParserException | IOException | RuntimeException e) { 1665 Slog.w(TAG, "Failed to parse " + apkPath, e); 1666 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, 1667 "Failed to parse " + apkPath, e); 1668 } finally { 1669 IoUtils.closeQuietly(parser); 1670 if (apkAssets != null) { 1671 try { 1672 apkAssets.close(); 1673 } catch (Throwable ignored) { 1674 } 1675 } 1676 // TODO(b/72056911): Implement AutoCloseable on ApkAssets. 1677 } 1678 } 1679 validateName(String name, boolean requireSeparator, boolean requireFilename)1680 private static String validateName(String name, boolean requireSeparator, 1681 boolean requireFilename) { 1682 final int N = name.length(); 1683 boolean hasSep = false; 1684 boolean front = true; 1685 for (int i=0; i<N; i++) { 1686 final char c = name.charAt(i); 1687 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { 1688 front = false; 1689 continue; 1690 } 1691 if (!front) { 1692 if ((c >= '0' && c <= '9') || c == '_') { 1693 continue; 1694 } 1695 } 1696 if (c == '.') { 1697 hasSep = true; 1698 front = true; 1699 continue; 1700 } 1701 return "bad character '" + c + "'"; 1702 } 1703 if (requireFilename && !FileUtils.isValidExtFilename(name)) { 1704 return "Invalid filename"; 1705 } 1706 return hasSep || !requireSeparator 1707 ? null : "must have at least one '.' separator"; 1708 } 1709 parsePackageSplitNames(XmlPullParser parser, AttributeSet attrs)1710 private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser, 1711 AttributeSet attrs) throws IOException, XmlPullParserException, 1712 PackageParserException { 1713 1714 int type; 1715 while ((type = parser.next()) != XmlPullParser.START_TAG 1716 && type != XmlPullParser.END_DOCUMENT) { 1717 } 1718 1719 if (type != XmlPullParser.START_TAG) { 1720 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, 1721 "No start tag found"); 1722 } 1723 if (!parser.getName().equals(TAG_MANIFEST)) { 1724 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, 1725 "No <manifest> tag"); 1726 } 1727 1728 final String packageName = attrs.getAttributeValue(null, "package"); 1729 if (!"android".equals(packageName)) { 1730 final String error = validateName(packageName, true, true); 1731 if (error != null) { 1732 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME, 1733 "Invalid manifest package: " + error); 1734 } 1735 } 1736 1737 String splitName = attrs.getAttributeValue(null, "split"); 1738 if (splitName != null) { 1739 if (splitName.length() == 0) { 1740 splitName = null; 1741 } else { 1742 final String error = validateName(splitName, false, false); 1743 if (error != null) { 1744 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME, 1745 "Invalid manifest split: " + error); 1746 } 1747 } 1748 } 1749 1750 return Pair.create(packageName.intern(), 1751 (splitName != null) ? splitName.intern() : splitName); 1752 } 1753 parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs, SigningDetails signingDetails)1754 private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs, 1755 SigningDetails signingDetails) 1756 throws IOException, XmlPullParserException, PackageParserException { 1757 final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs); 1758 1759 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION; 1760 int versionCode = 0; 1761 int versionCodeMajor = 0; 1762 int targetSdkVersion = DEFAULT_TARGET_SDK_VERSION; 1763 int minSdkVersion = DEFAULT_MIN_SDK_VERSION; 1764 int revisionCode = 0; 1765 boolean coreApp = false; 1766 boolean debuggable = false; 1767 boolean multiArch = false; 1768 boolean use32bitAbi = false; 1769 boolean extractNativeLibs = true; 1770 boolean isolatedSplits = false; 1771 boolean isFeatureSplit = false; 1772 boolean isSplitRequired = false; 1773 boolean useEmbeddedDex = false; 1774 String configForSplit = null; 1775 String usesSplitName = null; 1776 1777 for (int i = 0; i < attrs.getAttributeCount(); i++) { 1778 final String attr = attrs.getAttributeName(i); 1779 if (attr.equals("installLocation")) { 1780 installLocation = attrs.getAttributeIntValue(i, 1781 PARSE_DEFAULT_INSTALL_LOCATION); 1782 } else if (attr.equals("versionCode")) { 1783 versionCode = attrs.getAttributeIntValue(i, 0); 1784 } else if (attr.equals("versionCodeMajor")) { 1785 versionCodeMajor = attrs.getAttributeIntValue(i, 0); 1786 } else if (attr.equals("revisionCode")) { 1787 revisionCode = attrs.getAttributeIntValue(i, 0); 1788 } else if (attr.equals("coreApp")) { 1789 coreApp = attrs.getAttributeBooleanValue(i, false); 1790 } else if (attr.equals("isolatedSplits")) { 1791 isolatedSplits = attrs.getAttributeBooleanValue(i, false); 1792 } else if (attr.equals("configForSplit")) { 1793 configForSplit = attrs.getAttributeValue(i); 1794 } else if (attr.equals("isFeatureSplit")) { 1795 isFeatureSplit = attrs.getAttributeBooleanValue(i, false); 1796 } else if (attr.equals("isSplitRequired")) { 1797 isSplitRequired = attrs.getAttributeBooleanValue(i, false); 1798 } 1799 } 1800 1801 // Only search the tree when the tag is the direct child of <manifest> tag 1802 int type; 1803 final int searchDepth = parser.getDepth() + 1; 1804 1805 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>(); 1806 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 1807 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) { 1808 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 1809 continue; 1810 } 1811 1812 if (parser.getDepth() != searchDepth) { 1813 continue; 1814 } 1815 1816 if (TAG_PACKAGE_VERIFIER.equals(parser.getName())) { 1817 final VerifierInfo verifier = parseVerifier(attrs); 1818 if (verifier != null) { 1819 verifiers.add(verifier); 1820 } 1821 } else if (TAG_APPLICATION.equals(parser.getName())) { 1822 for (int i = 0; i < attrs.getAttributeCount(); ++i) { 1823 final String attr = attrs.getAttributeName(i); 1824 if ("debuggable".equals(attr)) { 1825 debuggable = attrs.getAttributeBooleanValue(i, false); 1826 } 1827 if ("multiArch".equals(attr)) { 1828 multiArch = attrs.getAttributeBooleanValue(i, false); 1829 } 1830 if ("use32bitAbi".equals(attr)) { 1831 use32bitAbi = attrs.getAttributeBooleanValue(i, false); 1832 } 1833 if ("extractNativeLibs".equals(attr)) { 1834 extractNativeLibs = attrs.getAttributeBooleanValue(i, true); 1835 } 1836 if ("useEmbeddedDex".equals(attr)) { 1837 useEmbeddedDex = attrs.getAttributeBooleanValue(i, false); 1838 } 1839 } 1840 } else if (TAG_USES_SPLIT.equals(parser.getName())) { 1841 if (usesSplitName != null) { 1842 Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others."); 1843 continue; 1844 } 1845 1846 usesSplitName = attrs.getAttributeValue(ANDROID_RESOURCES, "name"); 1847 if (usesSplitName == null) { 1848 throw new PackageParserException( 1849 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, 1850 "<uses-split> tag requires 'android:name' attribute"); 1851 } 1852 } else if (TAG_USES_SDK.equals(parser.getName())) { 1853 for (int i = 0; i < attrs.getAttributeCount(); ++i) { 1854 final String attr = attrs.getAttributeName(i); 1855 if ("targetSdkVersion".equals(attr)) { 1856 targetSdkVersion = attrs.getAttributeIntValue(i, 1857 DEFAULT_TARGET_SDK_VERSION); 1858 } 1859 if ("minSdkVersion".equals(attr)) { 1860 minSdkVersion = attrs.getAttributeIntValue(i, DEFAULT_MIN_SDK_VERSION); 1861 } 1862 } 1863 } 1864 } 1865 1866 return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit, 1867 configForSplit, usesSplitName, isSplitRequired, versionCode, versionCodeMajor, 1868 revisionCode, installLocation, verifiers, signingDetails, coreApp, debuggable, 1869 multiArch, use32bitAbi, useEmbeddedDex, extractNativeLibs, isolatedSplits, 1870 minSdkVersion, targetSdkVersion); 1871 } 1872 1873 /** 1874 * Parses a child package and adds it to the parent if successful. If you add 1875 * new tags that need to be supported by child packages make sure to add them 1876 * to {@link #CHILD_PACKAGE_TAGS}. 1877 * 1878 * @param parentPkg The parent that contains the child 1879 * @param res Resources against which to resolve values 1880 * @param parser Parser of the manifest 1881 * @param flags Flags about how to parse 1882 * @param outError Human readable error if parsing fails 1883 * @return True of parsing succeeded. 1884 * 1885 * @throws XmlPullParserException 1886 * @throws IOException 1887 */ parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser, int flags, String[] outError)1888 private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser, 1889 int flags, String[] outError) throws XmlPullParserException, IOException { 1890 // Make sure we have a valid child package name 1891 String childPackageName = parser.getAttributeValue(null, "package"); 1892 if (validateName(childPackageName, true, false) != null) { 1893 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME; 1894 return false; 1895 } 1896 1897 // Child packages must be unique 1898 if (childPackageName.equals(parentPkg.packageName)) { 1899 String message = "Child package name cannot be equal to parent package name: " 1900 + parentPkg.packageName; 1901 Slog.w(TAG, message); 1902 outError[0] = message; 1903 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1904 return false; 1905 } 1906 1907 // Child packages must be unique 1908 if (parentPkg.hasChildPackage(childPackageName)) { 1909 String message = "Duplicate child package:" + childPackageName; 1910 Slog.w(TAG, message); 1911 outError[0] = message; 1912 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1913 return false; 1914 } 1915 1916 // Go ahead and parse the child 1917 Package childPkg = new Package(childPackageName); 1918 1919 // Child package inherits parent version code/name/target SDK 1920 childPkg.mVersionCode = parentPkg.mVersionCode; 1921 childPkg.baseRevisionCode = parentPkg.baseRevisionCode; 1922 childPkg.mVersionName = parentPkg.mVersionName; 1923 childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion; 1924 childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion; 1925 1926 childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError); 1927 if (childPkg == null) { 1928 // If we got null then error was set during child parsing 1929 return false; 1930 } 1931 1932 // Set the parent-child relation 1933 if (parentPkg.childPackages == null) { 1934 parentPkg.childPackages = new ArrayList<>(); 1935 } 1936 parentPkg.childPackages.add(childPkg); 1937 childPkg.parentPackage = parentPkg; 1938 1939 return true; 1940 } 1941 1942 /** 1943 * Parse the manifest of a <em>base APK</em>. When adding new features you 1944 * need to consider whether they should be supported by split APKs and child 1945 * packages. 1946 * 1947 * @param apkPath The package apk file path 1948 * @param res The resources from which to resolve values 1949 * @param parser The manifest parser 1950 * @param flags Flags how to parse 1951 * @param outError Human readable error message 1952 * @return Parsed package or null on error. 1953 * 1954 * @throws XmlPullParserException 1955 * @throws IOException 1956 */ 1957 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags, String[] outError)1958 private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags, 1959 String[] outError) throws XmlPullParserException, IOException { 1960 final String splitName; 1961 final String pkgName; 1962 1963 try { 1964 Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser); 1965 pkgName = packageSplit.first; 1966 splitName = packageSplit.second; 1967 1968 if (!TextUtils.isEmpty(splitName)) { 1969 outError[0] = "Expected base APK, but found split " + splitName; 1970 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME; 1971 return null; 1972 } 1973 } catch (PackageParserException e) { 1974 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME; 1975 return null; 1976 } 1977 1978 if (mCallback != null) { 1979 String[] overlayPaths = mCallback.getOverlayPaths(pkgName, apkPath); 1980 if (overlayPaths != null && overlayPaths.length > 0) { 1981 for (String overlayPath : overlayPaths) { 1982 res.getAssets().addOverlayPath(overlayPath); 1983 } 1984 } 1985 } 1986 1987 final Package pkg = new Package(pkgName); 1988 1989 TypedArray sa = res.obtainAttributes(parser, 1990 com.android.internal.R.styleable.AndroidManifest); 1991 1992 pkg.mVersionCode = sa.getInteger( 1993 com.android.internal.R.styleable.AndroidManifest_versionCode, 0); 1994 pkg.mVersionCodeMajor = sa.getInteger( 1995 com.android.internal.R.styleable.AndroidManifest_versionCodeMajor, 0); 1996 pkg.applicationInfo.setVersionCode(pkg.getLongVersionCode()); 1997 pkg.baseRevisionCode = sa.getInteger( 1998 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0); 1999 pkg.mVersionName = sa.getNonConfigurationString( 2000 com.android.internal.R.styleable.AndroidManifest_versionName, 0); 2001 if (pkg.mVersionName != null) { 2002 pkg.mVersionName = pkg.mVersionName.intern(); 2003 } 2004 2005 pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false); 2006 2007 pkg.mCompileSdkVersion = sa.getInteger( 2008 com.android.internal.R.styleable.AndroidManifest_compileSdkVersion, 0); 2009 pkg.applicationInfo.compileSdkVersion = pkg.mCompileSdkVersion; 2010 pkg.mCompileSdkVersionCodename = sa.getNonConfigurationString( 2011 com.android.internal.R.styleable.AndroidManifest_compileSdkVersionCodename, 0); 2012 if (pkg.mCompileSdkVersionCodename != null) { 2013 pkg.mCompileSdkVersionCodename = pkg.mCompileSdkVersionCodename.intern(); 2014 } 2015 pkg.applicationInfo.compileSdkVersionCodename = pkg.mCompileSdkVersionCodename; 2016 2017 sa.recycle(); 2018 2019 return parseBaseApkCommon(pkg, null, res, parser, flags, outError); 2020 } 2021 2022 /** 2023 * This is the common parsing routing for handling parent and child 2024 * packages in a base APK. The difference between parent and child 2025 * parsing is that some tags are not supported by child packages as 2026 * well as some manifest attributes are ignored. The implementation 2027 * assumes the calling code has already handled the manifest tag if needed 2028 * (this applies to the parent only). 2029 * 2030 * @param pkg The package which to populate 2031 * @param acceptedTags Which tags to handle, null to handle all 2032 * @param res Resources against which to resolve values 2033 * @param parser Parser of the manifest 2034 * @param flags Flags about how to parse 2035 * @param outError Human readable error if parsing fails 2036 * @return The package if parsing succeeded or null. 2037 * 2038 * @throws XmlPullParserException 2039 * @throws IOException 2040 */ parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res, XmlResourceParser parser, int flags, String[] outError)2041 private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res, 2042 XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, 2043 IOException { 2044 mParseInstrumentationArgs = null; 2045 2046 int type; 2047 boolean foundApp = false; 2048 2049 TypedArray sa = res.obtainAttributes(parser, 2050 com.android.internal.R.styleable.AndroidManifest); 2051 2052 String str = sa.getNonConfigurationString( 2053 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0); 2054 if (str != null && str.length() > 0) { 2055 String nameError = validateName(str, true, true); 2056 if (nameError != null && !"android".equals(pkg.packageName)) { 2057 outError[0] = "<manifest> specifies bad sharedUserId name \"" 2058 + str + "\": " + nameError; 2059 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID; 2060 return null; 2061 } 2062 pkg.mSharedUserId = str.intern(); 2063 pkg.mSharedUserLabel = sa.getResourceId( 2064 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0); 2065 } 2066 2067 pkg.installLocation = sa.getInteger( 2068 com.android.internal.R.styleable.AndroidManifest_installLocation, 2069 PARSE_DEFAULT_INSTALL_LOCATION); 2070 pkg.applicationInfo.installLocation = pkg.installLocation; 2071 2072 final int targetSandboxVersion = sa.getInteger( 2073 com.android.internal.R.styleable.AndroidManifest_targetSandboxVersion, 2074 PARSE_DEFAULT_TARGET_SANDBOX); 2075 pkg.applicationInfo.targetSandboxVersion = targetSandboxVersion; 2076 2077 /* Set the global "on SD card" flag */ 2078 if ((flags & PARSE_EXTERNAL_STORAGE) != 0) { 2079 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE; 2080 } 2081 2082 if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) { 2083 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING; 2084 } 2085 2086 // Resource boolean are -1, so 1 means we don't know the value. 2087 int supportsSmallScreens = 1; 2088 int supportsNormalScreens = 1; 2089 int supportsLargeScreens = 1; 2090 int supportsXLargeScreens = 1; 2091 int resizeable = 1; 2092 int anyDensity = 1; 2093 2094 int outerDepth = parser.getDepth(); 2095 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 2096 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 2097 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2098 continue; 2099 } 2100 2101 String tagName = parser.getName(); 2102 2103 if (acceptedTags != null && !acceptedTags.contains(tagName)) { 2104 Slog.w(TAG, "Skipping unsupported element under <manifest>: " 2105 + tagName + " at " + mArchiveSourcePath + " " 2106 + parser.getPositionDescription()); 2107 XmlUtils.skipCurrentTag(parser); 2108 continue; 2109 } 2110 2111 if (tagName.equals(TAG_APPLICATION)) { 2112 if (foundApp) { 2113 if (RIGID_PARSER) { 2114 outError[0] = "<manifest> has more than one <application>"; 2115 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 2116 return null; 2117 } else { 2118 Slog.w(TAG, "<manifest> has more than one <application>"); 2119 XmlUtils.skipCurrentTag(parser); 2120 continue; 2121 } 2122 } 2123 2124 foundApp = true; 2125 if (!parseBaseApplication(pkg, res, parser, flags, outError)) { 2126 return null; 2127 } 2128 } else if (tagName.equals(TAG_OVERLAY)) { 2129 sa = res.obtainAttributes(parser, 2130 com.android.internal.R.styleable.AndroidManifestResourceOverlay); 2131 pkg.mOverlayTarget = sa.getString( 2132 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage); 2133 pkg.mOverlayTargetName = sa.getString( 2134 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetName); 2135 pkg.mOverlayCategory = sa.getString( 2136 com.android.internal.R.styleable.AndroidManifestResourceOverlay_category); 2137 pkg.mOverlayPriority = sa.getInt( 2138 com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority, 2139 0); 2140 pkg.mOverlayIsStatic = sa.getBoolean( 2141 com.android.internal.R.styleable.AndroidManifestResourceOverlay_isStatic, 2142 false); 2143 final String propName = sa.getString( 2144 com.android.internal.R.styleable 2145 .AndroidManifestResourceOverlay_requiredSystemPropertyName); 2146 final String propValue = sa.getString( 2147 com.android.internal.R.styleable 2148 .AndroidManifestResourceOverlay_requiredSystemPropertyValue); 2149 sa.recycle(); 2150 2151 if (pkg.mOverlayTarget == null) { 2152 outError[0] = "<overlay> does not specify a target package"; 2153 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 2154 return null; 2155 } 2156 2157 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) { 2158 outError[0] = "<overlay> priority must be between 0 and 9999"; 2159 mParseError = 2160 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 2161 return null; 2162 } 2163 2164 // check to see if overlay should be excluded based on system property condition 2165 if (!checkOverlayRequiredSystemProperty(propName, propValue)) { 2166 Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and " 2167 + pkg.baseCodePath+ ": overlay ignored due to required system property: " 2168 + propName + " with value: " + propValue); 2169 return null; 2170 } 2171 2172 pkg.applicationInfo.privateFlags |= 2173 ApplicationInfo.PRIVATE_FLAG_IS_RESOURCE_OVERLAY; 2174 2175 XmlUtils.skipCurrentTag(parser); 2176 2177 } else if (tagName.equals(TAG_KEY_SETS)) { 2178 if (!parseKeySets(pkg, res, parser, outError)) { 2179 return null; 2180 } 2181 } else if (tagName.equals(TAG_PERMISSION_GROUP)) { 2182 if (!parsePermissionGroup(pkg, flags, res, parser, outError)) { 2183 return null; 2184 } 2185 } else if (tagName.equals(TAG_PERMISSION)) { 2186 if (!parsePermission(pkg, res, parser, outError)) { 2187 return null; 2188 } 2189 } else if (tagName.equals(TAG_PERMISSION_TREE)) { 2190 if (!parsePermissionTree(pkg, res, parser, outError)) { 2191 return null; 2192 } 2193 } else if (tagName.equals(TAG_USES_PERMISSION)) { 2194 if (!parseUsesPermission(pkg, res, parser)) { 2195 return null; 2196 } 2197 } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M) 2198 || tagName.equals(TAG_USES_PERMISSION_SDK_23)) { 2199 if (!parseUsesPermission(pkg, res, parser)) { 2200 return null; 2201 } 2202 } else if (tagName.equals(TAG_USES_CONFIGURATION)) { 2203 ConfigurationInfo cPref = new ConfigurationInfo(); 2204 sa = res.obtainAttributes(parser, 2205 com.android.internal.R.styleable.AndroidManifestUsesConfiguration); 2206 cPref.reqTouchScreen = sa.getInt( 2207 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen, 2208 Configuration.TOUCHSCREEN_UNDEFINED); 2209 cPref.reqKeyboardType = sa.getInt( 2210 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType, 2211 Configuration.KEYBOARD_UNDEFINED); 2212 if (sa.getBoolean( 2213 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard, 2214 false)) { 2215 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD; 2216 } 2217 cPref.reqNavigation = sa.getInt( 2218 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation, 2219 Configuration.NAVIGATION_UNDEFINED); 2220 if (sa.getBoolean( 2221 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav, 2222 false)) { 2223 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV; 2224 } 2225 sa.recycle(); 2226 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref); 2227 2228 XmlUtils.skipCurrentTag(parser); 2229 2230 } else if (tagName.equals(TAG_USES_FEATURE)) { 2231 FeatureInfo fi = parseUsesFeature(res, parser); 2232 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi); 2233 2234 if (fi.name == null) { 2235 ConfigurationInfo cPref = new ConfigurationInfo(); 2236 cPref.reqGlEsVersion = fi.reqGlEsVersion; 2237 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref); 2238 } 2239 2240 XmlUtils.skipCurrentTag(parser); 2241 2242 } else if (tagName.equals(TAG_FEATURE_GROUP)) { 2243 FeatureGroupInfo group = new FeatureGroupInfo(); 2244 ArrayList<FeatureInfo> features = null; 2245 final int innerDepth = parser.getDepth(); 2246 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 2247 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) { 2248 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2249 continue; 2250 } 2251 2252 final String innerTagName = parser.getName(); 2253 if (innerTagName.equals("uses-feature")) { 2254 FeatureInfo featureInfo = parseUsesFeature(res, parser); 2255 // FeatureGroups are stricter and mandate that 2256 // any <uses-feature> declared are mandatory. 2257 featureInfo.flags |= FeatureInfo.FLAG_REQUIRED; 2258 features = ArrayUtils.add(features, featureInfo); 2259 } else { 2260 Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName + 2261 " at " + mArchiveSourcePath + " " + 2262 parser.getPositionDescription()); 2263 } 2264 XmlUtils.skipCurrentTag(parser); 2265 } 2266 2267 if (features != null) { 2268 group.features = new FeatureInfo[features.size()]; 2269 group.features = features.toArray(group.features); 2270 } 2271 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group); 2272 2273 } else if (tagName.equals(TAG_USES_SDK)) { 2274 if (SDK_VERSION > 0) { 2275 sa = res.obtainAttributes(parser, 2276 com.android.internal.R.styleable.AndroidManifestUsesSdk); 2277 2278 int minVers = 1; 2279 String minCode = null; 2280 int targetVers = 0; 2281 String targetCode = null; 2282 2283 TypedValue val = sa.peekValue( 2284 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion); 2285 if (val != null) { 2286 if (val.type == TypedValue.TYPE_STRING && val.string != null) { 2287 minCode = val.string.toString(); 2288 } else { 2289 // If it's not a string, it's an integer. 2290 minVers = val.data; 2291 } 2292 } 2293 2294 val = sa.peekValue( 2295 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion); 2296 if (val != null) { 2297 if (val.type == TypedValue.TYPE_STRING && val.string != null) { 2298 targetCode = val.string.toString(); 2299 if (minCode == null) { 2300 minCode = targetCode; 2301 } 2302 } else { 2303 // If it's not a string, it's an integer. 2304 targetVers = val.data; 2305 } 2306 } else { 2307 targetVers = minVers; 2308 targetCode = minCode; 2309 } 2310 2311 sa.recycle(); 2312 2313 final int minSdkVersion = PackageParser.computeMinSdkVersion(minVers, minCode, 2314 SDK_VERSION, SDK_CODENAMES, outError); 2315 if (minSdkVersion < 0) { 2316 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK; 2317 return null; 2318 } 2319 2320 final int targetSdkVersion = PackageParser.computeTargetSdkVersion(targetVers, 2321 targetCode, SDK_CODENAMES, outError); 2322 if (targetSdkVersion < 0) { 2323 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK; 2324 return null; 2325 } 2326 2327 pkg.applicationInfo.minSdkVersion = minSdkVersion; 2328 pkg.applicationInfo.targetSdkVersion = targetSdkVersion; 2329 } 2330 2331 XmlUtils.skipCurrentTag(parser); 2332 2333 } else if (tagName.equals(TAG_SUPPORT_SCREENS)) { 2334 sa = res.obtainAttributes(parser, 2335 com.android.internal.R.styleable.AndroidManifestSupportsScreens); 2336 2337 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger( 2338 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp, 2339 0); 2340 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger( 2341 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp, 2342 0); 2343 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger( 2344 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp, 2345 0); 2346 2347 // This is a trick to get a boolean and still able to detect 2348 // if a value was actually set. 2349 supportsSmallScreens = sa.getInteger( 2350 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens, 2351 supportsSmallScreens); 2352 supportsNormalScreens = sa.getInteger( 2353 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens, 2354 supportsNormalScreens); 2355 supportsLargeScreens = sa.getInteger( 2356 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens, 2357 supportsLargeScreens); 2358 supportsXLargeScreens = sa.getInteger( 2359 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens, 2360 supportsXLargeScreens); 2361 resizeable = sa.getInteger( 2362 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable, 2363 resizeable); 2364 anyDensity = sa.getInteger( 2365 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity, 2366 anyDensity); 2367 2368 sa.recycle(); 2369 2370 XmlUtils.skipCurrentTag(parser); 2371 2372 } else if (tagName.equals(TAG_PROTECTED_BROADCAST)) { 2373 sa = res.obtainAttributes(parser, 2374 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast); 2375 2376 // Note: don't allow this value to be a reference to a resource 2377 // that may change. 2378 String name = sa.getNonResourceString( 2379 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name); 2380 2381 sa.recycle(); 2382 2383 if (name != null) { 2384 if (pkg.protectedBroadcasts == null) { 2385 pkg.protectedBroadcasts = new ArrayList<String>(); 2386 } 2387 if (!pkg.protectedBroadcasts.contains(name)) { 2388 pkg.protectedBroadcasts.add(name.intern()); 2389 } 2390 } 2391 2392 XmlUtils.skipCurrentTag(parser); 2393 2394 } else if (tagName.equals(TAG_INSTRUMENTATION)) { 2395 if (parseInstrumentation(pkg, res, parser, outError) == null) { 2396 return null; 2397 } 2398 } else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) { 2399 sa = res.obtainAttributes(parser, 2400 com.android.internal.R.styleable.AndroidManifestOriginalPackage); 2401 2402 String orig =sa.getNonConfigurationString( 2403 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0); 2404 if (!pkg.packageName.equals(orig)) { 2405 if (pkg.mOriginalPackages == null) { 2406 pkg.mOriginalPackages = new ArrayList<String>(); 2407 pkg.mRealPackage = pkg.packageName; 2408 } 2409 pkg.mOriginalPackages.add(orig); 2410 } 2411 2412 sa.recycle(); 2413 2414 XmlUtils.skipCurrentTag(parser); 2415 2416 } else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) { 2417 sa = res.obtainAttributes(parser, 2418 com.android.internal.R.styleable.AndroidManifestOriginalPackage); 2419 2420 String name = sa.getNonConfigurationString( 2421 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0); 2422 2423 sa.recycle(); 2424 2425 if (name != null) { 2426 if (pkg.mAdoptPermissions == null) { 2427 pkg.mAdoptPermissions = new ArrayList<String>(); 2428 } 2429 pkg.mAdoptPermissions.add(name); 2430 } 2431 2432 XmlUtils.skipCurrentTag(parser); 2433 2434 } else if (tagName.equals(TAG_USES_GL_TEXTURE)) { 2435 // Just skip this tag 2436 XmlUtils.skipCurrentTag(parser); 2437 continue; 2438 2439 } else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) { 2440 // Just skip this tag 2441 XmlUtils.skipCurrentTag(parser); 2442 continue; 2443 } else if (tagName.equals(TAG_SUPPORTS_INPUT)) {// 2444 XmlUtils.skipCurrentTag(parser); 2445 continue; 2446 2447 } else if (tagName.equals(TAG_EAT_COMMENT)) { 2448 // Just skip this tag 2449 XmlUtils.skipCurrentTag(parser); 2450 continue; 2451 2452 } else if (tagName.equals(TAG_PACKAGE)) { 2453 if (!MULTI_PACKAGE_APK_ENABLED) { 2454 XmlUtils.skipCurrentTag(parser); 2455 continue; 2456 } 2457 if (!parseBaseApkChild(pkg, res, parser, flags, outError)) { 2458 // If parsing a child failed the error is already set 2459 return null; 2460 } 2461 2462 } else if (tagName.equals(TAG_RESTRICT_UPDATE)) { 2463 if ((flags & PARSE_IS_SYSTEM_DIR) != 0) { 2464 sa = res.obtainAttributes(parser, 2465 com.android.internal.R.styleable.AndroidManifestRestrictUpdate); 2466 final String hash = sa.getNonConfigurationString( 2467 com.android.internal.R.styleable.AndroidManifestRestrictUpdate_hash, 0); 2468 sa.recycle(); 2469 2470 pkg.restrictUpdateHash = null; 2471 if (hash != null) { 2472 final int hashLength = hash.length(); 2473 final byte[] hashBytes = new byte[hashLength / 2]; 2474 for (int i = 0; i < hashLength; i += 2){ 2475 hashBytes[i/2] = (byte) ((Character.digit(hash.charAt(i), 16) << 4) 2476 + Character.digit(hash.charAt(i + 1), 16)); 2477 } 2478 pkg.restrictUpdateHash = hashBytes; 2479 } 2480 } 2481 2482 XmlUtils.skipCurrentTag(parser); 2483 2484 } else if (RIGID_PARSER) { 2485 outError[0] = "Bad element under <manifest>: " 2486 + parser.getName(); 2487 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 2488 return null; 2489 2490 } else { 2491 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName() 2492 + " at " + mArchiveSourcePath + " " 2493 + parser.getPositionDescription()); 2494 XmlUtils.skipCurrentTag(parser); 2495 continue; 2496 } 2497 } 2498 2499 if (!foundApp && pkg.instrumentation.size() == 0) { 2500 outError[0] = "<manifest> does not contain an <application> or <instrumentation>"; 2501 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY; 2502 } 2503 2504 final int NP = PackageParser.NEW_PERMISSIONS.length; 2505 StringBuilder newPermsMsg = null; 2506 for (int ip=0; ip<NP; ip++) { 2507 final PackageParser.NewPermissionInfo npi 2508 = PackageParser.NEW_PERMISSIONS[ip]; 2509 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) { 2510 break; 2511 } 2512 if (!pkg.requestedPermissions.contains(npi.name)) { 2513 if (newPermsMsg == null) { 2514 newPermsMsg = new StringBuilder(128); 2515 newPermsMsg.append(pkg.packageName); 2516 newPermsMsg.append(": compat added "); 2517 } else { 2518 newPermsMsg.append(' '); 2519 } 2520 newPermsMsg.append(npi.name); 2521 pkg.requestedPermissions.add(npi.name); 2522 pkg.implicitPermissions.add(npi.name); 2523 } 2524 } 2525 if (newPermsMsg != null) { 2526 Slog.i(TAG, newPermsMsg.toString()); 2527 } 2528 2529 List<SplitPermissionInfoParcelable> splitPermissions = getSplitPermissions(); 2530 final int listSize = splitPermissions.size(); 2531 for (int is = 0; is < listSize; is++) { 2532 final SplitPermissionInfoParcelable spi = splitPermissions.get(is); 2533 if (pkg.applicationInfo.targetSdkVersion >= spi.getTargetSdk() 2534 || !pkg.requestedPermissions.contains(spi.getSplitPermission())) { 2535 continue; 2536 } 2537 final List<String> newPerms = spi.getNewPermissions(); 2538 for (int in = 0; in < newPerms.size(); in++) { 2539 final String perm = newPerms.get(in); 2540 if (!pkg.requestedPermissions.contains(perm)) { 2541 pkg.requestedPermissions.add(perm); 2542 pkg.implicitPermissions.add(perm); 2543 } 2544 } 2545 } 2546 2547 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0 2548 && pkg.applicationInfo.targetSdkVersion 2549 >= android.os.Build.VERSION_CODES.DONUT)) { 2550 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS; 2551 } 2552 if (supportsNormalScreens != 0) { 2553 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS; 2554 } 2555 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0 2556 && pkg.applicationInfo.targetSdkVersion 2557 >= android.os.Build.VERSION_CODES.DONUT)) { 2558 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS; 2559 } 2560 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0 2561 && pkg.applicationInfo.targetSdkVersion 2562 >= android.os.Build.VERSION_CODES.GINGERBREAD)) { 2563 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS; 2564 } 2565 if (resizeable < 0 || (resizeable > 0 2566 && pkg.applicationInfo.targetSdkVersion 2567 >= android.os.Build.VERSION_CODES.DONUT)) { 2568 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS; 2569 } 2570 if (anyDensity < 0 || (anyDensity > 0 2571 && pkg.applicationInfo.targetSdkVersion 2572 >= android.os.Build.VERSION_CODES.DONUT)) { 2573 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES; 2574 } 2575 2576 // At this point we can check if an application is not supporting densities and hence 2577 // cannot be windowed / resized. Note that an SDK version of 0 is common for 2578 // pre-Doughnut applications. 2579 if (pkg.applicationInfo.usesCompatibilityMode()) { 2580 adjustPackageToBeUnresizeableAndUnpipable(pkg); 2581 } 2582 2583 return pkg; 2584 } 2585 getSplitPermissions()2586 private List<SplitPermissionInfoParcelable> getSplitPermissions() { 2587 // PackageManager runs this code during initialization prior to registering with 2588 // ServiceManager, so we can't use the PackageManager API. Instead, just read from 2589 // SystemConfig directly when in any SystemProcess and only use PackageManager when not in 2590 // one. 2591 if (ActivityThread.isSystem()) { 2592 return PermissionManager.splitPermissionInfoListToParcelableList( 2593 SystemConfig.getInstance().getSplitPermissions()); 2594 } else { 2595 try { 2596 return ActivityThread.getPackageManager().getSplitPermissions(); 2597 } catch (RemoteException e) { 2598 throw e.rethrowFromSystemServer(); 2599 } 2600 } 2601 } 2602 checkOverlayRequiredSystemProperty(String propName, String propValue)2603 private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) { 2604 2605 if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) { 2606 if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) { 2607 // malformed condition - incomplete 2608 Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName 2609 + "=" + propValue + "' - require both requiredSystemPropertyName" 2610 + " AND requiredSystemPropertyValue to be specified."); 2611 return false; 2612 } 2613 // no valid condition set - so no exclusion criteria, overlay will be included. 2614 return true; 2615 } 2616 2617 // check property value - make sure it is both set and equal to expected value 2618 final String currValue = SystemProperties.get(propName); 2619 return (currValue != null && currValue.equals(propValue)); 2620 } 2621 2622 /** 2623 * This is a pre-density application which will get scaled - instead of being pixel perfect. 2624 * This type of application is not resizable. 2625 * 2626 * @param pkg The package which needs to be marked as unresizable. 2627 */ adjustPackageToBeUnresizeableAndUnpipable(Package pkg)2628 private void adjustPackageToBeUnresizeableAndUnpipable(Package pkg) { 2629 for (Activity a : pkg.activities) { 2630 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE; 2631 a.info.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE; 2632 } 2633 } 2634 2635 /** 2636 2637 /** 2638 * Matches a given {@code targetCode} against a set of release codeNames. Target codes can 2639 * either be of the form {@code [codename]}" (e.g {@code "Q"}) or of the form 2640 * {@code [codename].[fingerprint]} (e.g {@code "Q.cafebc561"}). 2641 */ matchTargetCode(@onNull String[] codeNames, @NonNull String targetCode)2642 private static boolean matchTargetCode(@NonNull String[] codeNames, 2643 @NonNull String targetCode) { 2644 final String targetCodeName; 2645 final int targetCodeIdx = targetCode.indexOf('.'); 2646 if (targetCodeIdx == -1) { 2647 targetCodeName = targetCode; 2648 } else { 2649 targetCodeName = targetCode.substring(0, targetCodeIdx); 2650 } 2651 return ArrayUtils.contains(codeNames, targetCodeName); 2652 } 2653 2654 /** 2655 * Computes the targetSdkVersion to use at runtime. If the package is not 2656 * compatible with this platform, populates {@code outError[0]} with an 2657 * error message. 2658 * <p> 2659 * If {@code targetCode} is not specified, e.g. the value is {@code null}, 2660 * then the {@code targetVers} will be returned unmodified. 2661 * <p> 2662 * Otherwise, the behavior varies based on whether the current platform 2663 * is a pre-release version, e.g. the {@code platformSdkCodenames} array 2664 * has length > 0: 2665 * <ul> 2666 * <li>If this is a pre-release platform and the value specified by 2667 * {@code targetCode} is contained within the array of allowed pre-release 2668 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}. 2669 * <li>If this is a released platform, this method will return -1 to 2670 * indicate that the package is not compatible with this platform. 2671 * </ul> 2672 * 2673 * @param targetVers targetSdkVersion number, if specified in the 2674 * application manifest, or 0 otherwise 2675 * @param targetCode targetSdkVersion code, if specified in the application 2676 * manifest, or {@code null} otherwise 2677 * @param platformSdkCodenames array of allowed pre-release SDK codenames 2678 * for this platform 2679 * @param outError output array to populate with error, if applicable 2680 * @return the targetSdkVersion to use at runtime, or -1 if the package is 2681 * not compatible with this platform 2682 * @hide Exposed for unit testing only. 2683 */ computeTargetSdkVersion(@ntRangefrom = 0) int targetVers, @Nullable String targetCode, @NonNull String[] platformSdkCodenames, @NonNull String[] outError)2684 public static int computeTargetSdkVersion(@IntRange(from = 0) int targetVers, 2685 @Nullable String targetCode, @NonNull String[] platformSdkCodenames, 2686 @NonNull String[] outError) { 2687 // If it's a release SDK, return the version number unmodified. 2688 if (targetCode == null) { 2689 return targetVers; 2690 } 2691 2692 // If it's a pre-release SDK and the codename matches this platform, it 2693 // definitely targets this SDK. 2694 if (matchTargetCode(platformSdkCodenames, targetCode)) { 2695 return Build.VERSION_CODES.CUR_DEVELOPMENT; 2696 } 2697 2698 // Otherwise, we're looking at an incompatible pre-release SDK. 2699 if (platformSdkCodenames.length > 0) { 2700 outError[0] = "Requires development platform " + targetCode 2701 + " (current platform is any of " 2702 + Arrays.toString(platformSdkCodenames) + ")"; 2703 } else { 2704 outError[0] = "Requires development platform " + targetCode 2705 + " but this is a release platform."; 2706 } 2707 return -1; 2708 } 2709 2710 /** 2711 * Computes the minSdkVersion to use at runtime. If the package is not 2712 * compatible with this platform, populates {@code outError[0]} with an 2713 * error message. 2714 * <p> 2715 * If {@code minCode} is not specified, e.g. the value is {@code null}, 2716 * then behavior varies based on the {@code platformSdkVersion}: 2717 * <ul> 2718 * <li>If the platform SDK version is greater than or equal to the 2719 * {@code minVers}, returns the {@code mniVers} unmodified. 2720 * <li>Otherwise, returns -1 to indicate that the package is not 2721 * compatible with this platform. 2722 * </ul> 2723 * <p> 2724 * Otherwise, the behavior varies based on whether the current platform 2725 * is a pre-release version, e.g. the {@code platformSdkCodenames} array 2726 * has length > 0: 2727 * <ul> 2728 * <li>If this is a pre-release platform and the value specified by 2729 * {@code targetCode} is contained within the array of allowed pre-release 2730 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}. 2731 * <li>If this is a released platform, this method will return -1 to 2732 * indicate that the package is not compatible with this platform. 2733 * </ul> 2734 * 2735 * @param minVers minSdkVersion number, if specified in the application 2736 * manifest, or 1 otherwise 2737 * @param minCode minSdkVersion code, if specified in the application 2738 * manifest, or {@code null} otherwise 2739 * @param platformSdkVersion platform SDK version number, typically 2740 * Build.VERSION.SDK_INT 2741 * @param platformSdkCodenames array of allowed prerelease SDK codenames 2742 * for this platform 2743 * @param outError output array to populate with error, if applicable 2744 * @return the minSdkVersion to use at runtime, or -1 if the package is not 2745 * compatible with this platform 2746 * @hide Exposed for unit testing only. 2747 */ computeMinSdkVersion(@ntRangefrom = 1) int minVers, @Nullable String minCode, @IntRange(from = 1) int platformSdkVersion, @NonNull String[] platformSdkCodenames, @NonNull String[] outError)2748 public static int computeMinSdkVersion(@IntRange(from = 1) int minVers, 2749 @Nullable String minCode, @IntRange(from = 1) int platformSdkVersion, 2750 @NonNull String[] platformSdkCodenames, @NonNull String[] outError) { 2751 // If it's a release SDK, make sure we meet the minimum SDK requirement. 2752 if (minCode == null) { 2753 if (minVers <= platformSdkVersion) { 2754 return minVers; 2755 } 2756 2757 // We don't meet the minimum SDK requirement. 2758 outError[0] = "Requires newer sdk version #" + minVers 2759 + " (current version is #" + platformSdkVersion + ")"; 2760 return -1; 2761 } 2762 2763 // If it's a pre-release SDK and the codename matches this platform, we 2764 // definitely meet the minimum SDK requirement. 2765 if (matchTargetCode(platformSdkCodenames, minCode)) { 2766 return Build.VERSION_CODES.CUR_DEVELOPMENT; 2767 } 2768 2769 // Otherwise, we're looking at an incompatible pre-release SDK. 2770 if (platformSdkCodenames.length > 0) { 2771 outError[0] = "Requires development platform " + minCode 2772 + " (current platform is any of " 2773 + Arrays.toString(platformSdkCodenames) + ")"; 2774 } else { 2775 outError[0] = "Requires development platform " + minCode 2776 + " but this is a release platform."; 2777 } 2778 return -1; 2779 } 2780 parseUsesFeature(Resources res, AttributeSet attrs)2781 private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs) { 2782 FeatureInfo fi = new FeatureInfo(); 2783 TypedArray sa = res.obtainAttributes(attrs, 2784 com.android.internal.R.styleable.AndroidManifestUsesFeature); 2785 // Note: don't allow this value to be a reference to a resource 2786 // that may change. 2787 fi.name = sa.getNonResourceString( 2788 com.android.internal.R.styleable.AndroidManifestUsesFeature_name); 2789 fi.version = sa.getInt( 2790 com.android.internal.R.styleable.AndroidManifestUsesFeature_version, 0); 2791 if (fi.name == null) { 2792 fi.reqGlEsVersion = sa.getInt( 2793 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion, 2794 FeatureInfo.GL_ES_VERSION_UNDEFINED); 2795 } 2796 if (sa.getBoolean( 2797 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, true)) { 2798 fi.flags |= FeatureInfo.FLAG_REQUIRED; 2799 } 2800 sa.recycle(); 2801 return fi; 2802 } 2803 parseUsesStaticLibrary(Package pkg, Resources res, XmlResourceParser parser, String[] outError)2804 private boolean parseUsesStaticLibrary(Package pkg, Resources res, XmlResourceParser parser, 2805 String[] outError) throws XmlPullParserException, IOException { 2806 TypedArray sa = res.obtainAttributes(parser, 2807 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary); 2808 2809 // Note: don't allow this value to be a reference to a resource that may change. 2810 String lname = sa.getNonResourceString( 2811 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name); 2812 final int version = sa.getInt( 2813 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary_version, -1); 2814 String certSha256Digest = sa.getNonResourceString(com.android.internal.R.styleable 2815 .AndroidManifestUsesStaticLibrary_certDigest); 2816 sa.recycle(); 2817 2818 // Since an APK providing a static shared lib can only provide the lib - fail if malformed 2819 if (lname == null || version < 0 || certSha256Digest == null) { 2820 outError[0] = "Bad uses-static-library declaration name: " + lname + " version: " 2821 + version + " certDigest" + certSha256Digest; 2822 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 2823 XmlUtils.skipCurrentTag(parser); 2824 return false; 2825 } 2826 2827 // Can depend only on one version of the same library 2828 if (pkg.usesStaticLibraries != null && pkg.usesStaticLibraries.contains(lname)) { 2829 outError[0] = "Depending on multiple versions of static library " + lname; 2830 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 2831 XmlUtils.skipCurrentTag(parser); 2832 return false; 2833 } 2834 2835 lname = lname.intern(); 2836 // We allow ":" delimiters in the SHA declaration as this is the format 2837 // emitted by the certtool making it easy for developers to copy/paste. 2838 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase(); 2839 2840 // Fot apps targeting O-MR1 we require explicit enumeration of all certs. 2841 String[] additionalCertSha256Digests = EmptyArray.STRING; 2842 if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O_MR1) { 2843 additionalCertSha256Digests = parseAdditionalCertificates(res, parser, outError); 2844 if (additionalCertSha256Digests == null) { 2845 return false; 2846 } 2847 } else { 2848 XmlUtils.skipCurrentTag(parser); 2849 } 2850 2851 final String[] certSha256Digests = new String[additionalCertSha256Digests.length + 1]; 2852 certSha256Digests[0] = certSha256Digest; 2853 System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests, 2854 1, additionalCertSha256Digests.length); 2855 2856 pkg.usesStaticLibraries = ArrayUtils.add(pkg.usesStaticLibraries, lname); 2857 pkg.usesStaticLibrariesVersions = ArrayUtils.appendLong( 2858 pkg.usesStaticLibrariesVersions, version, true); 2859 pkg.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String[].class, 2860 pkg.usesStaticLibrariesCertDigests, certSha256Digests, true); 2861 2862 return true; 2863 } 2864 parseAdditionalCertificates(Resources resources, XmlResourceParser parser, String[] outError)2865 private String[] parseAdditionalCertificates(Resources resources, XmlResourceParser parser, 2866 String[] outError) throws XmlPullParserException, IOException { 2867 String[] certSha256Digests = EmptyArray.STRING; 2868 2869 int outerDepth = parser.getDepth(); 2870 int type; 2871 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 2872 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 2873 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2874 continue; 2875 } 2876 2877 final String nodeName = parser.getName(); 2878 if (nodeName.equals("additional-certificate")) { 2879 final TypedArray sa = resources.obtainAttributes(parser, com.android.internal. 2880 R.styleable.AndroidManifestAdditionalCertificate); 2881 String certSha256Digest = sa.getNonResourceString(com.android.internal. 2882 R.styleable.AndroidManifestAdditionalCertificate_certDigest); 2883 sa.recycle(); 2884 2885 if (TextUtils.isEmpty(certSha256Digest)) { 2886 outError[0] = "Bad additional-certificate declaration with empty" 2887 + " certDigest:" + certSha256Digest; 2888 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 2889 XmlUtils.skipCurrentTag(parser); 2890 sa.recycle(); 2891 return null; 2892 } 2893 2894 // We allow ":" delimiters in the SHA declaration as this is the format 2895 // emitted by the certtool making it easy for developers to copy/paste. 2896 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase(); 2897 certSha256Digests = ArrayUtils.appendElement(String.class, 2898 certSha256Digests, certSha256Digest); 2899 } else { 2900 XmlUtils.skipCurrentTag(parser); 2901 } 2902 } 2903 2904 return certSha256Digests; 2905 } 2906 parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)2907 private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser) 2908 throws XmlPullParserException, IOException { 2909 TypedArray sa = res.obtainAttributes(parser, 2910 com.android.internal.R.styleable.AndroidManifestUsesPermission); 2911 2912 // Note: don't allow this value to be a reference to a resource 2913 // that may change. 2914 String name = sa.getNonResourceString( 2915 com.android.internal.R.styleable.AndroidManifestUsesPermission_name); 2916 2917 int maxSdkVersion = 0; 2918 TypedValue val = sa.peekValue( 2919 com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion); 2920 if (val != null) { 2921 if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) { 2922 maxSdkVersion = val.data; 2923 } 2924 } 2925 2926 final String requiredFeature = sa.getNonConfigurationString( 2927 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredFeature, 0); 2928 2929 final String requiredNotfeature = sa.getNonConfigurationString( 2930 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0); 2931 2932 sa.recycle(); 2933 2934 XmlUtils.skipCurrentTag(parser); 2935 2936 if (name == null) { 2937 return true; 2938 } 2939 2940 if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) { 2941 return true; 2942 } 2943 2944 // Only allow requesting this permission if the platform supports the given feature. 2945 if (requiredFeature != null && mCallback != null && !mCallback.hasFeature(requiredFeature)) { 2946 return true; 2947 } 2948 2949 // Only allow requesting this permission if the platform doesn't support the given feature. 2950 if (requiredNotfeature != null && mCallback != null 2951 && mCallback.hasFeature(requiredNotfeature)) { 2952 return true; 2953 } 2954 2955 int index = pkg.requestedPermissions.indexOf(name); 2956 if (index == -1) { 2957 pkg.requestedPermissions.add(name.intern()); 2958 } else { 2959 Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: " 2960 + name + " in package: " + pkg.packageName + " at: " 2961 + parser.getPositionDescription()); 2962 } 2963 2964 return true; 2965 } 2966 buildClassName(String pkg, CharSequence clsSeq, String[] outError)2967 private static String buildClassName(String pkg, CharSequence clsSeq, 2968 String[] outError) { 2969 if (clsSeq == null || clsSeq.length() <= 0) { 2970 outError[0] = "Empty class name in package " + pkg; 2971 return null; 2972 } 2973 String cls = clsSeq.toString(); 2974 char c = cls.charAt(0); 2975 if (c == '.') { 2976 return pkg + cls; 2977 } 2978 if (cls.indexOf('.') < 0) { 2979 StringBuilder b = new StringBuilder(pkg); 2980 b.append('.'); 2981 b.append(cls); 2982 return b.toString(); 2983 } 2984 return cls; 2985 } 2986 buildCompoundName(String pkg, CharSequence procSeq, String type, String[] outError)2987 private static String buildCompoundName(String pkg, 2988 CharSequence procSeq, String type, String[] outError) { 2989 String proc = procSeq.toString(); 2990 char c = proc.charAt(0); 2991 if (pkg != null && c == ':') { 2992 if (proc.length() < 2) { 2993 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg 2994 + ": must be at least two characters"; 2995 return null; 2996 } 2997 String subName = proc.substring(1); 2998 String nameError = validateName(subName, false, false); 2999 if (nameError != null) { 3000 outError[0] = "Invalid " + type + " name " + proc + " in package " 3001 + pkg + ": " + nameError; 3002 return null; 3003 } 3004 return pkg + proc; 3005 } 3006 String nameError = validateName(proc, true, false); 3007 if (nameError != null && !"system".equals(proc)) { 3008 outError[0] = "Invalid " + type + " name " + proc + " in package " 3009 + pkg + ": " + nameError; 3010 return null; 3011 } 3012 return proc; 3013 } 3014 buildProcessName(String pkg, String defProc, CharSequence procSeq, int flags, String[] separateProcesses, String[] outError)3015 private static String buildProcessName(String pkg, String defProc, 3016 CharSequence procSeq, int flags, String[] separateProcesses, 3017 String[] outError) { 3018 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) { 3019 return defProc != null ? defProc : pkg; 3020 } 3021 if (separateProcesses != null) { 3022 for (int i=separateProcesses.length-1; i>=0; i--) { 3023 String sp = separateProcesses[i]; 3024 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) { 3025 return pkg; 3026 } 3027 } 3028 } 3029 if (procSeq == null || procSeq.length() <= 0) { 3030 return defProc; 3031 } 3032 return TextUtils.safeIntern(buildCompoundName(pkg, procSeq, "process", outError)); 3033 } 3034 buildTaskAffinityName(String pkg, String defProc, CharSequence procSeq, String[] outError)3035 private static String buildTaskAffinityName(String pkg, String defProc, 3036 CharSequence procSeq, String[] outError) { 3037 if (procSeq == null) { 3038 return defProc; 3039 } 3040 if (procSeq.length() <= 0) { 3041 return null; 3042 } 3043 return buildCompoundName(pkg, procSeq, "taskAffinity", outError); 3044 } 3045 parseKeySets(Package owner, Resources res, XmlResourceParser parser, String[] outError)3046 private boolean parseKeySets(Package owner, Resources res, 3047 XmlResourceParser parser, String[] outError) 3048 throws XmlPullParserException, IOException { 3049 // we've encountered the 'key-sets' tag 3050 // all the keys and keysets that we want must be defined here 3051 // so we're going to iterate over the parser and pull out the things we want 3052 int outerDepth = parser.getDepth(); 3053 int currentKeySetDepth = -1; 3054 int type; 3055 String currentKeySet = null; 3056 ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>(); 3057 ArraySet<String> upgradeKeySets = new ArraySet<String>(); 3058 ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>(); 3059 ArraySet<String> improperKeySets = new ArraySet<String>(); 3060 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 3061 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 3062 if (type == XmlPullParser.END_TAG) { 3063 if (parser.getDepth() == currentKeySetDepth) { 3064 currentKeySet = null; 3065 currentKeySetDepth = -1; 3066 } 3067 continue; 3068 } 3069 String tagName = parser.getName(); 3070 if (tagName.equals("key-set")) { 3071 if (currentKeySet != null) { 3072 outError[0] = "Improperly nested 'key-set' tag at " 3073 + parser.getPositionDescription(); 3074 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3075 return false; 3076 } 3077 final TypedArray sa = res.obtainAttributes(parser, 3078 com.android.internal.R.styleable.AndroidManifestKeySet); 3079 final String keysetName = sa.getNonResourceString( 3080 com.android.internal.R.styleable.AndroidManifestKeySet_name); 3081 definedKeySets.put(keysetName, new ArraySet<String>()); 3082 currentKeySet = keysetName; 3083 currentKeySetDepth = parser.getDepth(); 3084 sa.recycle(); 3085 } else if (tagName.equals("public-key")) { 3086 if (currentKeySet == null) { 3087 outError[0] = "Improperly nested 'key-set' tag at " 3088 + parser.getPositionDescription(); 3089 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3090 return false; 3091 } 3092 final TypedArray sa = res.obtainAttributes(parser, 3093 com.android.internal.R.styleable.AndroidManifestPublicKey); 3094 final String publicKeyName = sa.getNonResourceString( 3095 com.android.internal.R.styleable.AndroidManifestPublicKey_name); 3096 final String encodedKey = sa.getNonResourceString( 3097 com.android.internal.R.styleable.AndroidManifestPublicKey_value); 3098 if (encodedKey == null && publicKeys.get(publicKeyName) == null) { 3099 outError[0] = "'public-key' " + publicKeyName + " must define a public-key value" 3100 + " on first use at " + parser.getPositionDescription(); 3101 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3102 sa.recycle(); 3103 return false; 3104 } else if (encodedKey != null) { 3105 PublicKey currentKey = parsePublicKey(encodedKey); 3106 if (currentKey == null) { 3107 Slog.w(TAG, "No recognized valid key in 'public-key' tag at " 3108 + parser.getPositionDescription() + " key-set " + currentKeySet 3109 + " will not be added to the package's defined key-sets."); 3110 sa.recycle(); 3111 improperKeySets.add(currentKeySet); 3112 XmlUtils.skipCurrentTag(parser); 3113 continue; 3114 } 3115 if (publicKeys.get(publicKeyName) == null 3116 || publicKeys.get(publicKeyName).equals(currentKey)) { 3117 3118 /* public-key first definition, or matches old definition */ 3119 publicKeys.put(publicKeyName, currentKey); 3120 } else { 3121 outError[0] = "Value of 'public-key' " + publicKeyName 3122 + " conflicts with previously defined value at " 3123 + parser.getPositionDescription(); 3124 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3125 sa.recycle(); 3126 return false; 3127 } 3128 } 3129 definedKeySets.get(currentKeySet).add(publicKeyName); 3130 sa.recycle(); 3131 XmlUtils.skipCurrentTag(parser); 3132 } else if (tagName.equals("upgrade-key-set")) { 3133 final TypedArray sa = res.obtainAttributes(parser, 3134 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet); 3135 String name = sa.getNonResourceString( 3136 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name); 3137 upgradeKeySets.add(name); 3138 sa.recycle(); 3139 XmlUtils.skipCurrentTag(parser); 3140 } else if (RIGID_PARSER) { 3141 outError[0] = "Bad element under <key-sets>: " + parser.getName() 3142 + " at " + mArchiveSourcePath + " " 3143 + parser.getPositionDescription(); 3144 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3145 return false; 3146 } else { 3147 Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName() 3148 + " at " + mArchiveSourcePath + " " 3149 + parser.getPositionDescription()); 3150 XmlUtils.skipCurrentTag(parser); 3151 continue; 3152 } 3153 } 3154 Set<String> publicKeyNames = publicKeys.keySet(); 3155 if (publicKeyNames.removeAll(definedKeySets.keySet())) { 3156 outError[0] = "Package" + owner.packageName + " AndroidManifext.xml " 3157 + "'key-set' and 'public-key' names must be distinct."; 3158 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3159 return false; 3160 } 3161 owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>(); 3162 for (ArrayMap.Entry<String, ArraySet<String>> e: definedKeySets.entrySet()) { 3163 final String keySetName = e.getKey(); 3164 if (e.getValue().size() == 0) { 3165 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml " 3166 + "'key-set' " + keySetName + " has no valid associated 'public-key'." 3167 + " Not including in package's defined key-sets."); 3168 continue; 3169 } else if (improperKeySets.contains(keySetName)) { 3170 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml " 3171 + "'key-set' " + keySetName + " contained improper 'public-key'" 3172 + " tags. Not including in package's defined key-sets."); 3173 continue; 3174 } 3175 owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>()); 3176 for (String s : e.getValue()) { 3177 owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s)); 3178 } 3179 } 3180 if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) { 3181 owner.mUpgradeKeySets = upgradeKeySets; 3182 } else { 3183 outError[0] ="Package" + owner.packageName + " AndroidManifext.xml " 3184 + "does not define all 'upgrade-key-set's ."; 3185 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3186 return false; 3187 } 3188 return true; 3189 } 3190 parsePermissionGroup(Package owner, int flags, Resources res, XmlResourceParser parser, String[] outError)3191 private boolean parsePermissionGroup(Package owner, int flags, Resources res, 3192 XmlResourceParser parser, String[] outError) 3193 throws XmlPullParserException, IOException { 3194 TypedArray sa = res.obtainAttributes(parser, 3195 com.android.internal.R.styleable.AndroidManifestPermissionGroup); 3196 3197 int requestDetailResourceId = sa.getResourceId( 3198 com.android.internal.R.styleable.AndroidManifestPermissionGroup_requestDetail, 0); 3199 int backgroundRequestResourceId = sa.getResourceId( 3200 com.android.internal.R.styleable.AndroidManifestPermissionGroup_backgroundRequest, 3201 0); 3202 int backgroundRequestDetailResourceId = sa.getResourceId( 3203 com.android.internal.R.styleable 3204 .AndroidManifestPermissionGroup_backgroundRequestDetail, 0); 3205 3206 PermissionGroup perm = new PermissionGroup(owner, requestDetailResourceId, 3207 backgroundRequestResourceId, backgroundRequestDetailResourceId); 3208 3209 if (!parsePackageItemInfo(owner, perm.info, outError, 3210 "<permission-group>", sa, true /*nameRequired*/, 3211 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name, 3212 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label, 3213 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon, 3214 com.android.internal.R.styleable.AndroidManifestPermissionGroup_roundIcon, 3215 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo, 3216 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) { 3217 sa.recycle(); 3218 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3219 return false; 3220 } 3221 3222 perm.info.descriptionRes = sa.getResourceId( 3223 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description, 3224 0); 3225 perm.info.requestRes = sa.getResourceId( 3226 com.android.internal.R.styleable.AndroidManifestPermissionGroup_request, 0); 3227 perm.info.flags = sa.getInt( 3228 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0); 3229 perm.info.priority = sa.getInt( 3230 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0); 3231 3232 sa.recycle(); 3233 3234 if (!parseAllMetaData(res, parser, "<permission-group>", perm, 3235 outError)) { 3236 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3237 return false; 3238 } 3239 3240 owner.permissionGroups.add(perm); 3241 3242 return true; 3243 } 3244 parsePermission(Package owner, Resources res, XmlResourceParser parser, String[] outError)3245 private boolean parsePermission(Package owner, Resources res, 3246 XmlResourceParser parser, String[] outError) 3247 throws XmlPullParserException, IOException { 3248 3249 TypedArray sa = res.obtainAttributes(parser, 3250 com.android.internal.R.styleable.AndroidManifestPermission); 3251 3252 String backgroundPermission = null; 3253 if (sa.hasValue( 3254 com.android.internal.R.styleable.AndroidManifestPermission_backgroundPermission)) { 3255 if ("android".equals(owner.packageName)) { 3256 backgroundPermission = sa.getNonResourceString( 3257 com.android.internal.R.styleable 3258 .AndroidManifestPermission_backgroundPermission); 3259 } else { 3260 Slog.w(TAG, owner.packageName + " defines a background permission. Only the " 3261 + "'android' package can do that."); 3262 } 3263 } 3264 3265 Permission perm = new Permission(owner, backgroundPermission); 3266 if (!parsePackageItemInfo(owner, perm.info, outError, 3267 "<permission>", sa, true /*nameRequired*/, 3268 com.android.internal.R.styleable.AndroidManifestPermission_name, 3269 com.android.internal.R.styleable.AndroidManifestPermission_label, 3270 com.android.internal.R.styleable.AndroidManifestPermission_icon, 3271 com.android.internal.R.styleable.AndroidManifestPermission_roundIcon, 3272 com.android.internal.R.styleable.AndroidManifestPermission_logo, 3273 com.android.internal.R.styleable.AndroidManifestPermission_banner)) { 3274 sa.recycle(); 3275 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3276 return false; 3277 } 3278 3279 // Note: don't allow this value to be a reference to a resource 3280 // that may change. 3281 perm.info.group = sa.getNonResourceString( 3282 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup); 3283 if (perm.info.group != null) { 3284 perm.info.group = perm.info.group.intern(); 3285 } 3286 3287 perm.info.descriptionRes = sa.getResourceId( 3288 com.android.internal.R.styleable.AndroidManifestPermission_description, 3289 0); 3290 3291 perm.info.requestRes = sa.getResourceId( 3292 com.android.internal.R.styleable.AndroidManifestPermission_request, 0); 3293 3294 perm.info.protectionLevel = sa.getInt( 3295 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel, 3296 PermissionInfo.PROTECTION_NORMAL); 3297 3298 perm.info.flags = sa.getInt( 3299 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0); 3300 3301 // For now only platform runtime permissions can be restricted 3302 if (!perm.info.isRuntime() || !"android".equals(perm.info.packageName)) { 3303 perm.info.flags &= ~PermissionInfo.FLAG_HARD_RESTRICTED; 3304 perm.info.flags &= ~PermissionInfo.FLAG_SOFT_RESTRICTED; 3305 } else { 3306 // The platform does not get to specify conflicting permissions 3307 if ((perm.info.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0 3308 && (perm.info.flags & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0) { 3309 throw new IllegalStateException("Permission cannot be both soft and hard" 3310 + " restricted: " + perm.info.name); 3311 } 3312 } 3313 3314 sa.recycle(); 3315 3316 if (perm.info.protectionLevel == -1) { 3317 outError[0] = "<permission> does not specify protectionLevel"; 3318 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3319 return false; 3320 } 3321 3322 perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel); 3323 3324 if (perm.info.getProtectionFlags() != 0) { 3325 if ( (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_INSTANT) == 0 3326 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) == 0 3327 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) != 3328 PermissionInfo.PROTECTION_SIGNATURE) { 3329 outError[0] = "<permission> protectionLevel specifies a non-instant flag but is " 3330 + "not based on signature type"; 3331 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3332 return false; 3333 } 3334 } 3335 3336 if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) { 3337 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3338 return false; 3339 } 3340 3341 owner.permissions.add(perm); 3342 3343 return true; 3344 } 3345 parsePermissionTree(Package owner, Resources res, XmlResourceParser parser, String[] outError)3346 private boolean parsePermissionTree(Package owner, Resources res, 3347 XmlResourceParser parser, String[] outError) 3348 throws XmlPullParserException, IOException { 3349 Permission perm = new Permission(owner, (String) null); 3350 3351 TypedArray sa = res.obtainAttributes(parser, 3352 com.android.internal.R.styleable.AndroidManifestPermissionTree); 3353 3354 if (!parsePackageItemInfo(owner, perm.info, outError, 3355 "<permission-tree>", sa, true /*nameRequired*/, 3356 com.android.internal.R.styleable.AndroidManifestPermissionTree_name, 3357 com.android.internal.R.styleable.AndroidManifestPermissionTree_label, 3358 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon, 3359 com.android.internal.R.styleable.AndroidManifestPermissionTree_roundIcon, 3360 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo, 3361 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) { 3362 sa.recycle(); 3363 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3364 return false; 3365 } 3366 3367 sa.recycle(); 3368 3369 int index = perm.info.name.indexOf('.'); 3370 if (index > 0) { 3371 index = perm.info.name.indexOf('.', index+1); 3372 } 3373 if (index < 0) { 3374 outError[0] = "<permission-tree> name has less than three segments: " 3375 + perm.info.name; 3376 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3377 return false; 3378 } 3379 3380 perm.info.descriptionRes = 0; 3381 perm.info.requestRes = 0; 3382 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL; 3383 perm.tree = true; 3384 3385 if (!parseAllMetaData(res, parser, "<permission-tree>", perm, 3386 outError)) { 3387 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3388 return false; 3389 } 3390 3391 owner.permissions.add(perm); 3392 3393 return true; 3394 } 3395 parseInstrumentation(Package owner, Resources res, XmlResourceParser parser, String[] outError)3396 private Instrumentation parseInstrumentation(Package owner, Resources res, 3397 XmlResourceParser parser, String[] outError) 3398 throws XmlPullParserException, IOException { 3399 TypedArray sa = res.obtainAttributes(parser, 3400 com.android.internal.R.styleable.AndroidManifestInstrumentation); 3401 3402 if (mParseInstrumentationArgs == null) { 3403 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError, 3404 com.android.internal.R.styleable.AndroidManifestInstrumentation_name, 3405 com.android.internal.R.styleable.AndroidManifestInstrumentation_label, 3406 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon, 3407 com.android.internal.R.styleable.AndroidManifestInstrumentation_roundIcon, 3408 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo, 3409 com.android.internal.R.styleable.AndroidManifestInstrumentation_banner); 3410 mParseInstrumentationArgs.tag = "<instrumentation>"; 3411 } 3412 3413 mParseInstrumentationArgs.sa = sa; 3414 3415 Instrumentation a = new Instrumentation(mParseInstrumentationArgs, 3416 new InstrumentationInfo()); 3417 if (outError[0] != null) { 3418 sa.recycle(); 3419 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3420 return null; 3421 } 3422 3423 String str; 3424 // Note: don't allow this value to be a reference to a resource 3425 // that may change. 3426 str = sa.getNonResourceString( 3427 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage); 3428 a.info.targetPackage = str != null ? str.intern() : null; 3429 3430 str = sa.getNonResourceString( 3431 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetProcesses); 3432 a.info.targetProcesses = str != null ? str.intern() : null; 3433 3434 a.info.handleProfiling = sa.getBoolean( 3435 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling, 3436 false); 3437 3438 a.info.functionalTest = sa.getBoolean( 3439 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest, 3440 false); 3441 3442 sa.recycle(); 3443 3444 if (a.info.targetPackage == null) { 3445 outError[0] = "<instrumentation> does not specify targetPackage"; 3446 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3447 return null; 3448 } 3449 3450 if (!parseAllMetaData(res, parser, "<instrumentation>", a, 3451 outError)) { 3452 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3453 return null; 3454 } 3455 3456 owner.instrumentation.add(a); 3457 3458 return a; 3459 } 3460 3461 /** 3462 * Parse the {@code application} XML tree at the current parse location in a 3463 * <em>base APK</em> manifest. 3464 * <p> 3465 * When adding new features, carefully consider if they should also be 3466 * supported by split APKs. 3467 */ 3468 @UnsupportedAppUsage parseBaseApplication(Package owner, Resources res, XmlResourceParser parser, int flags, String[] outError)3469 private boolean parseBaseApplication(Package owner, Resources res, 3470 XmlResourceParser parser, int flags, String[] outError) 3471 throws XmlPullParserException, IOException { 3472 final ApplicationInfo ai = owner.applicationInfo; 3473 final String pkgName = owner.applicationInfo.packageName; 3474 3475 TypedArray sa = res.obtainAttributes(parser, 3476 com.android.internal.R.styleable.AndroidManifestApplication); 3477 3478 ai.iconRes = sa.getResourceId( 3479 com.android.internal.R.styleable.AndroidManifestApplication_icon, 0); 3480 ai.roundIconRes = sa.getResourceId( 3481 com.android.internal.R.styleable.AndroidManifestApplication_roundIcon, 0); 3482 3483 if (!parsePackageItemInfo(owner, ai, outError, 3484 "<application>", sa, false /*nameRequired*/, 3485 com.android.internal.R.styleable.AndroidManifestApplication_name, 3486 com.android.internal.R.styleable.AndroidManifestApplication_label, 3487 com.android.internal.R.styleable.AndroidManifestApplication_icon, 3488 com.android.internal.R.styleable.AndroidManifestApplication_roundIcon, 3489 com.android.internal.R.styleable.AndroidManifestApplication_logo, 3490 com.android.internal.R.styleable.AndroidManifestApplication_banner)) { 3491 sa.recycle(); 3492 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3493 return false; 3494 } 3495 3496 if (ai.name != null) { 3497 ai.className = ai.name; 3498 } 3499 3500 String manageSpaceActivity = sa.getNonConfigurationString( 3501 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity, 3502 Configuration.NATIVE_CONFIG_VERSION); 3503 if (manageSpaceActivity != null) { 3504 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity, 3505 outError); 3506 } 3507 3508 boolean allowBackup = sa.getBoolean( 3509 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true); 3510 if (allowBackup) { 3511 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP; 3512 3513 // backupAgent, killAfterRestore, fullBackupContent, backupInForeground, 3514 // and restoreAnyVersion are only relevant if backup is possible for the 3515 // given application. 3516 String backupAgent = sa.getNonConfigurationString( 3517 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent, 3518 Configuration.NATIVE_CONFIG_VERSION); 3519 if (backupAgent != null) { 3520 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError); 3521 if (DEBUG_BACKUP) { 3522 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName 3523 + " from " + pkgName + "+" + backupAgent); 3524 } 3525 3526 if (sa.getBoolean( 3527 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore, 3528 true)) { 3529 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE; 3530 } 3531 if (sa.getBoolean( 3532 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion, 3533 false)) { 3534 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION; 3535 } 3536 if (sa.getBoolean( 3537 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly, 3538 false)) { 3539 ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY; 3540 } 3541 if (sa.getBoolean( 3542 com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground, 3543 false)) { 3544 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND; 3545 } 3546 } 3547 3548 TypedValue v = sa.peekValue( 3549 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent); 3550 if (v != null && (ai.fullBackupContent = v.resourceId) == 0) { 3551 if (DEBUG_BACKUP) { 3552 Slog.v(TAG, "fullBackupContent specified as boolean=" + 3553 (v.data == 0 ? "false" : "true")); 3554 } 3555 // "false" => -1, "true" => 0 3556 ai.fullBackupContent = (v.data == 0 ? -1 : 0); 3557 } 3558 if (DEBUG_BACKUP) { 3559 Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName); 3560 } 3561 } 3562 3563 ai.theme = sa.getResourceId( 3564 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0); 3565 ai.descriptionRes = sa.getResourceId( 3566 com.android.internal.R.styleable.AndroidManifestApplication_description, 0); 3567 3568 if (sa.getBoolean( 3569 com.android.internal.R.styleable.AndroidManifestApplication_persistent, 3570 false)) { 3571 // Check if persistence is based on a feature being present 3572 final String requiredFeature = sa.getNonResourceString(com.android.internal.R.styleable 3573 .AndroidManifestApplication_persistentWhenFeatureAvailable); 3574 if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) { 3575 ai.flags |= ApplicationInfo.FLAG_PERSISTENT; 3576 } 3577 } 3578 3579 if (sa.getBoolean( 3580 com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers, 3581 false)) { 3582 owner.mRequiredForAllUsers = true; 3583 } 3584 3585 String restrictedAccountType = sa.getString(com.android.internal.R.styleable 3586 .AndroidManifestApplication_restrictedAccountType); 3587 if (restrictedAccountType != null && restrictedAccountType.length() > 0) { 3588 owner.mRestrictedAccountType = restrictedAccountType; 3589 } 3590 3591 String requiredAccountType = sa.getString(com.android.internal.R.styleable 3592 .AndroidManifestApplication_requiredAccountType); 3593 if (requiredAccountType != null && requiredAccountType.length() > 0) { 3594 owner.mRequiredAccountType = requiredAccountType; 3595 } 3596 3597 if (sa.getBoolean( 3598 com.android.internal.R.styleable.AndroidManifestApplication_debuggable, 3599 false)) { 3600 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE; 3601 // Debuggable implies profileable 3602 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL; 3603 } 3604 3605 if (sa.getBoolean( 3606 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode, 3607 false)) { 3608 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE; 3609 } 3610 3611 owner.baseHardwareAccelerated = sa.getBoolean( 3612 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated, 3613 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH); 3614 if (owner.baseHardwareAccelerated) { 3615 ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED; 3616 } 3617 3618 if (sa.getBoolean( 3619 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, 3620 true)) { 3621 ai.flags |= ApplicationInfo.FLAG_HAS_CODE; 3622 } 3623 3624 if (sa.getBoolean( 3625 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting, 3626 false)) { 3627 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING; 3628 } 3629 3630 if (sa.getBoolean( 3631 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData, 3632 true)) { 3633 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA; 3634 } 3635 3636 // The parent package controls installation, hence specify test only installs. 3637 if (owner.parentPackage == null) { 3638 if (sa.getBoolean( 3639 com.android.internal.R.styleable.AndroidManifestApplication_testOnly, 3640 false)) { 3641 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY; 3642 } 3643 } 3644 3645 if (sa.getBoolean( 3646 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap, 3647 false)) { 3648 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP; 3649 } 3650 3651 if (sa.getBoolean( 3652 com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic, 3653 owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.P)) { 3654 ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC; 3655 } 3656 3657 if (sa.getBoolean( 3658 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl, 3659 false /* default is no RTL support*/)) { 3660 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL; 3661 } 3662 3663 if (sa.getBoolean( 3664 com.android.internal.R.styleable.AndroidManifestApplication_multiArch, 3665 false)) { 3666 ai.flags |= ApplicationInfo.FLAG_MULTIARCH; 3667 } 3668 3669 if (sa.getBoolean( 3670 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs, 3671 true)) { 3672 ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS; 3673 } 3674 3675 if (sa.getBoolean( 3676 R.styleable.AndroidManifestApplication_useEmbeddedDex, 3677 false)) { 3678 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_USE_EMBEDDED_DEX; 3679 } 3680 3681 if (sa.getBoolean( 3682 R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage, 3683 false)) { 3684 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE; 3685 } 3686 if (sa.getBoolean( 3687 R.styleable.AndroidManifestApplication_directBootAware, 3688 false)) { 3689 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE; 3690 } 3691 3692 if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) { 3693 if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity, true)) { 3694 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE; 3695 } else { 3696 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE; 3697 } 3698 } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) { 3699 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION; 3700 } 3701 3702 if (sa.getBoolean( 3703 com.android.internal.R.styleable 3704 .AndroidManifestApplication_allowClearUserDataOnFailedRestore, 3705 true)) { 3706 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE; 3707 } 3708 3709 if (sa.getBoolean( 3710 R.styleable.AndroidManifestApplication_allowAudioPlaybackCapture, 3711 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q)) { 3712 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE; 3713 } 3714 3715 if (sa.getBoolean( 3716 R.styleable.AndroidManifestApplication_requestLegacyExternalStorage, 3717 owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.Q)) { 3718 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE; 3719 } 3720 3721 ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0); 3722 ai.minAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_minAspectRatio, 0); 3723 3724 ai.networkSecurityConfigRes = sa.getResourceId( 3725 com.android.internal.R.styleable.AndroidManifestApplication_networkSecurityConfig, 3726 0); 3727 ai.category = sa.getInt( 3728 com.android.internal.R.styleable.AndroidManifestApplication_appCategory, 3729 ApplicationInfo.CATEGORY_UNDEFINED); 3730 3731 String str; 3732 str = sa.getNonConfigurationString( 3733 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0); 3734 ai.permission = (str != null && str.length() > 0) ? str.intern() : null; 3735 3736 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) { 3737 str = sa.getNonConfigurationString( 3738 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity, 3739 Configuration.NATIVE_CONFIG_VERSION); 3740 } else { 3741 // Some older apps have been seen to use a resource reference 3742 // here that on older builds was ignored (with a warning). We 3743 // need to continue to do this for them so they don't break. 3744 str = sa.getNonResourceString( 3745 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity); 3746 } 3747 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName, 3748 str, outError); 3749 String factory = sa.getNonResourceString( 3750 com.android.internal.R.styleable.AndroidManifestApplication_appComponentFactory); 3751 if (factory != null) { 3752 ai.appComponentFactory = buildClassName(ai.packageName, factory, outError); 3753 } 3754 3755 if (sa.getBoolean( 3756 com.android.internal.R.styleable.AndroidManifestApplication_usesNonSdkApi, false)) { 3757 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API; 3758 } 3759 3760 if (sa.getBoolean( 3761 com.android.internal.R.styleable.AndroidManifestApplication_hasFragileUserData, 3762 false)) { 3763 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_FRAGILE_USER_DATA; 3764 } 3765 3766 if (outError[0] == null) { 3767 CharSequence pname; 3768 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) { 3769 pname = sa.getNonConfigurationString( 3770 com.android.internal.R.styleable.AndroidManifestApplication_process, 3771 Configuration.NATIVE_CONFIG_VERSION); 3772 } else { 3773 // Some older apps have been seen to use a resource reference 3774 // here that on older builds was ignored (with a warning). We 3775 // need to continue to do this for them so they don't break. 3776 pname = sa.getNonResourceString( 3777 com.android.internal.R.styleable.AndroidManifestApplication_process); 3778 } 3779 ai.processName = buildProcessName(ai.packageName, null, pname, 3780 flags, mSeparateProcesses, outError); 3781 3782 ai.enabled = sa.getBoolean( 3783 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true); 3784 3785 if (sa.getBoolean( 3786 com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) { 3787 ai.flags |= ApplicationInfo.FLAG_IS_GAME; 3788 } 3789 3790 if (sa.getBoolean( 3791 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState, 3792 false)) { 3793 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE; 3794 3795 // A heavy-weight application can not be in a custom process. 3796 // We can do direct compare because we intern all strings. 3797 if (ai.processName != null && !ai.processName.equals(ai.packageName)) { 3798 outError[0] = "cantSaveState applications can not use custom processes"; 3799 } 3800 } 3801 } 3802 3803 ai.uiOptions = sa.getInt( 3804 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0); 3805 3806 ai.classLoaderName = sa.getString( 3807 com.android.internal.R.styleable.AndroidManifestApplication_classLoader); 3808 if (ai.classLoaderName != null 3809 && !ClassLoaderFactory.isValidClassLoaderName(ai.classLoaderName)) { 3810 outError[0] = "Invalid class loader name: " + ai.classLoaderName; 3811 } 3812 3813 ai.zygotePreloadName = sa.getString( 3814 com.android.internal.R.styleable.AndroidManifestApplication_zygotePreloadName); 3815 3816 sa.recycle(); 3817 3818 if (outError[0] != null) { 3819 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3820 return false; 3821 } 3822 3823 final int innerDepth = parser.getDepth(); 3824 // IMPORTANT: These must only be cached for a single <application> to avoid components 3825 // getting added to the wrong package. 3826 final CachedComponentArgs cachedArgs = new CachedComponentArgs(); 3827 int type; 3828 boolean hasActivityOrder = false; 3829 boolean hasReceiverOrder = false; 3830 boolean hasServiceOrder = false; 3831 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 3832 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) { 3833 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 3834 continue; 3835 } 3836 3837 String tagName = parser.getName(); 3838 if (tagName.equals("activity")) { 3839 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false, 3840 owner.baseHardwareAccelerated); 3841 if (a == null) { 3842 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3843 return false; 3844 } 3845 3846 hasActivityOrder |= (a.order != 0); 3847 owner.activities.add(a); 3848 3849 } else if (tagName.equals("receiver")) { 3850 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, 3851 true, false); 3852 if (a == null) { 3853 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3854 return false; 3855 } 3856 3857 hasReceiverOrder |= (a.order != 0); 3858 owner.receivers.add(a); 3859 3860 } else if (tagName.equals("service")) { 3861 Service s = parseService(owner, res, parser, flags, outError, cachedArgs); 3862 if (s == null) { 3863 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3864 return false; 3865 } 3866 3867 hasServiceOrder |= (s.order != 0); 3868 owner.services.add(s); 3869 3870 } else if (tagName.equals("provider")) { 3871 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs); 3872 if (p == null) { 3873 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3874 return false; 3875 } 3876 3877 owner.providers.add(p); 3878 3879 } else if (tagName.equals("activity-alias")) { 3880 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs); 3881 if (a == null) { 3882 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3883 return false; 3884 } 3885 3886 hasActivityOrder |= (a.order != 0); 3887 owner.activities.add(a); 3888 3889 } else if (parser.getName().equals("meta-data")) { 3890 // note: application meta-data is stored off to the side, so it can 3891 // remain null in the primary copy (we like to avoid extra copies because 3892 // it can be large) 3893 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData, 3894 outError)) == null) { 3895 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3896 return false; 3897 } 3898 } else if (tagName.equals("static-library")) { 3899 sa = res.obtainAttributes(parser, 3900 com.android.internal.R.styleable.AndroidManifestStaticLibrary); 3901 3902 // Note: don't allow this value to be a reference to a resource 3903 // that may change. 3904 final String lname = sa.getNonResourceString( 3905 com.android.internal.R.styleable.AndroidManifestStaticLibrary_name); 3906 final int version = sa.getInt( 3907 com.android.internal.R.styleable.AndroidManifestStaticLibrary_version, -1); 3908 final int versionMajor = sa.getInt( 3909 com.android.internal.R.styleable.AndroidManifestStaticLibrary_versionMajor, 3910 0); 3911 3912 sa.recycle(); 3913 3914 // Since the app canot run without a static lib - fail if malformed 3915 if (lname == null || version < 0) { 3916 outError[0] = "Bad static-library declaration name: " + lname 3917 + " version: " + version; 3918 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3919 XmlUtils.skipCurrentTag(parser); 3920 return false; 3921 } 3922 3923 if (owner.mSharedUserId != null) { 3924 outError[0] = "sharedUserId not allowed in static shared library"; 3925 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID; 3926 XmlUtils.skipCurrentTag(parser); 3927 return false; 3928 } 3929 3930 if (owner.staticSharedLibName != null) { 3931 outError[0] = "Multiple static-shared libs for package " + pkgName; 3932 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 3933 XmlUtils.skipCurrentTag(parser); 3934 return false; 3935 } 3936 3937 owner.staticSharedLibName = lname.intern(); 3938 if (version >= 0) { 3939 owner.staticSharedLibVersion = 3940 PackageInfo.composeLongVersionCode(versionMajor, version); 3941 } else { 3942 owner.staticSharedLibVersion = version; 3943 } 3944 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY; 3945 3946 XmlUtils.skipCurrentTag(parser); 3947 3948 } else if (tagName.equals("library")) { 3949 sa = res.obtainAttributes(parser, 3950 com.android.internal.R.styleable.AndroidManifestLibrary); 3951 3952 // Note: don't allow this value to be a reference to a resource 3953 // that may change. 3954 String lname = sa.getNonResourceString( 3955 com.android.internal.R.styleable.AndroidManifestLibrary_name); 3956 3957 sa.recycle(); 3958 3959 if (lname != null) { 3960 lname = lname.intern(); 3961 if (!ArrayUtils.contains(owner.libraryNames, lname)) { 3962 owner.libraryNames = ArrayUtils.add( 3963 owner.libraryNames, lname); 3964 } 3965 } 3966 3967 XmlUtils.skipCurrentTag(parser); 3968 3969 } else if (tagName.equals("uses-static-library")) { 3970 if (!parseUsesStaticLibrary(owner, res, parser, outError)) { 3971 return false; 3972 } 3973 3974 } else if (tagName.equals("uses-library")) { 3975 sa = res.obtainAttributes(parser, 3976 com.android.internal.R.styleable.AndroidManifestUsesLibrary); 3977 3978 // Note: don't allow this value to be a reference to a resource 3979 // that may change. 3980 String lname = sa.getNonResourceString( 3981 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name); 3982 boolean req = sa.getBoolean( 3983 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required, 3984 true); 3985 3986 sa.recycle(); 3987 3988 if (lname != null) { 3989 lname = lname.intern(); 3990 if (req) { 3991 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname); 3992 } else { 3993 owner.usesOptionalLibraries = ArrayUtils.add( 3994 owner.usesOptionalLibraries, lname); 3995 } 3996 } 3997 3998 XmlUtils.skipCurrentTag(parser); 3999 4000 } else if (tagName.equals("uses-package")) { 4001 // Dependencies for app installers; we don't currently try to 4002 // enforce this. 4003 XmlUtils.skipCurrentTag(parser); 4004 } else if (tagName.equals("profileable")) { 4005 sa = res.obtainAttributes(parser, 4006 com.android.internal.R.styleable.AndroidManifestProfileable); 4007 if (sa.getBoolean( 4008 com.android.internal.R.styleable.AndroidManifestProfileable_shell, false)) { 4009 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL; 4010 } 4011 XmlUtils.skipCurrentTag(parser); 4012 4013 } else { 4014 if (!RIGID_PARSER) { 4015 Slog.w(TAG, "Unknown element under <application>: " + tagName 4016 + " at " + mArchiveSourcePath + " " 4017 + parser.getPositionDescription()); 4018 XmlUtils.skipCurrentTag(parser); 4019 continue; 4020 } else { 4021 outError[0] = "Bad element under <application>: " + tagName; 4022 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 4023 return false; 4024 } 4025 } 4026 } 4027 4028 if (TextUtils.isEmpty(owner.staticSharedLibName)) { 4029 // Add a hidden app detail activity to normal apps which forwards user to App Details 4030 // page. 4031 Activity a = generateAppDetailsHiddenActivity(owner, flags, outError, 4032 owner.baseHardwareAccelerated); 4033 owner.activities.add(a); 4034 } 4035 4036 if (hasActivityOrder) { 4037 Collections.sort(owner.activities, (a1, a2) -> Integer.compare(a2.order, a1.order)); 4038 } 4039 if (hasReceiverOrder) { 4040 Collections.sort(owner.receivers, (r1, r2) -> Integer.compare(r2.order, r1.order)); 4041 } 4042 if (hasServiceOrder) { 4043 Collections.sort(owner.services, (s1, s2) -> Integer.compare(s2.order, s1.order)); 4044 } 4045 // Must be ran after the entire {@link ApplicationInfo} has been fully processed and after 4046 // every activity info has had a chance to set it from its attributes. 4047 setMaxAspectRatio(owner); 4048 setMinAspectRatio(owner); 4049 4050 if (hasDomainURLs(owner)) { 4051 owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS; 4052 } else { 4053 owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS; 4054 } 4055 4056 return true; 4057 } 4058 4059 /** 4060 * Check if one of the IntentFilter as both actions DEFAULT / VIEW and a HTTP/HTTPS data URI 4061 */ hasDomainURLs(Package pkg)4062 private static boolean hasDomainURLs(Package pkg) { 4063 if (pkg == null || pkg.activities == null) return false; 4064 final ArrayList<Activity> activities = pkg.activities; 4065 final int countActivities = activities.size(); 4066 for (int n=0; n<countActivities; n++) { 4067 Activity activity = activities.get(n); 4068 ArrayList<ActivityIntentInfo> filters = activity.intents; 4069 if (filters == null) continue; 4070 final int countFilters = filters.size(); 4071 for (int m=0; m<countFilters; m++) { 4072 ActivityIntentInfo aii = filters.get(m); 4073 if (!aii.hasAction(Intent.ACTION_VIEW)) continue; 4074 if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue; 4075 if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) || 4076 aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) { 4077 return true; 4078 } 4079 } 4080 } 4081 return false; 4082 } 4083 4084 /** 4085 * Parse the {@code application} XML tree at the current parse location in a 4086 * <em>split APK</em> manifest. 4087 * <p> 4088 * Note that split APKs have many more restrictions on what they're capable 4089 * of doing, so many valid features of a base APK have been carefully 4090 * omitted here. 4091 */ parseSplitApplication(Package owner, Resources res, XmlResourceParser parser, int flags, int splitIndex, String[] outError)4092 private boolean parseSplitApplication(Package owner, Resources res, XmlResourceParser parser, 4093 int flags, int splitIndex, String[] outError) 4094 throws XmlPullParserException, IOException { 4095 TypedArray sa = res.obtainAttributes(parser, 4096 com.android.internal.R.styleable.AndroidManifestApplication); 4097 4098 if (sa.getBoolean( 4099 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) { 4100 owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE; 4101 } 4102 4103 final String classLoaderName = sa.getString( 4104 com.android.internal.R.styleable.AndroidManifestApplication_classLoader); 4105 if (classLoaderName == null || ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) { 4106 owner.applicationInfo.splitClassLoaderNames[splitIndex] = classLoaderName; 4107 } else { 4108 outError[0] = "Invalid class loader name: " + classLoaderName; 4109 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 4110 return false; 4111 } 4112 4113 final int innerDepth = parser.getDepth(); 4114 int type; 4115 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 4116 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) { 4117 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 4118 continue; 4119 } 4120 4121 ComponentInfo parsedComponent = null; 4122 4123 // IMPORTANT: These must only be cached for a single <application> to avoid components 4124 // getting added to the wrong package. 4125 final CachedComponentArgs cachedArgs = new CachedComponentArgs(); 4126 String tagName = parser.getName(); 4127 if (tagName.equals("activity")) { 4128 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false, 4129 owner.baseHardwareAccelerated); 4130 if (a == null) { 4131 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 4132 return false; 4133 } 4134 4135 owner.activities.add(a); 4136 parsedComponent = a.info; 4137 4138 } else if (tagName.equals("receiver")) { 4139 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, 4140 true, false); 4141 if (a == null) { 4142 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 4143 return false; 4144 } 4145 4146 owner.receivers.add(a); 4147 parsedComponent = a.info; 4148 4149 } else if (tagName.equals("service")) { 4150 Service s = parseService(owner, res, parser, flags, outError, cachedArgs); 4151 if (s == null) { 4152 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 4153 return false; 4154 } 4155 4156 owner.services.add(s); 4157 parsedComponent = s.info; 4158 4159 } else if (tagName.equals("provider")) { 4160 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs); 4161 if (p == null) { 4162 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 4163 return false; 4164 } 4165 4166 owner.providers.add(p); 4167 parsedComponent = p.info; 4168 4169 } else if (tagName.equals("activity-alias")) { 4170 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs); 4171 if (a == null) { 4172 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 4173 return false; 4174 } 4175 4176 owner.activities.add(a); 4177 parsedComponent = a.info; 4178 4179 } else if (parser.getName().equals("meta-data")) { 4180 // note: application meta-data is stored off to the side, so it can 4181 // remain null in the primary copy (we like to avoid extra copies because 4182 // it can be large) 4183 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData, 4184 outError)) == null) { 4185 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 4186 return false; 4187 } 4188 4189 } else if (tagName.equals("uses-static-library")) { 4190 if (!parseUsesStaticLibrary(owner, res, parser, outError)) { 4191 return false; 4192 } 4193 4194 } else if (tagName.equals("uses-library")) { 4195 sa = res.obtainAttributes(parser, 4196 com.android.internal.R.styleable.AndroidManifestUsesLibrary); 4197 4198 // Note: don't allow this value to be a reference to a resource 4199 // that may change. 4200 String lname = sa.getNonResourceString( 4201 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name); 4202 boolean req = sa.getBoolean( 4203 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required, 4204 true); 4205 4206 sa.recycle(); 4207 4208 if (lname != null) { 4209 lname = lname.intern(); 4210 if (req) { 4211 // Upgrade to treat as stronger constraint 4212 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname); 4213 owner.usesOptionalLibraries = ArrayUtils.remove( 4214 owner.usesOptionalLibraries, lname); 4215 } else { 4216 // Ignore if someone already defined as required 4217 if (!ArrayUtils.contains(owner.usesLibraries, lname)) { 4218 owner.usesOptionalLibraries = ArrayUtils.add( 4219 owner.usesOptionalLibraries, lname); 4220 } 4221 } 4222 } 4223 4224 XmlUtils.skipCurrentTag(parser); 4225 4226 } else if (tagName.equals("uses-package")) { 4227 // Dependencies for app installers; we don't currently try to 4228 // enforce this. 4229 XmlUtils.skipCurrentTag(parser); 4230 4231 } else { 4232 if (!RIGID_PARSER) { 4233 Slog.w(TAG, "Unknown element under <application>: " + tagName 4234 + " at " + mArchiveSourcePath + " " 4235 + parser.getPositionDescription()); 4236 XmlUtils.skipCurrentTag(parser); 4237 continue; 4238 } else { 4239 outError[0] = "Bad element under <application>: " + tagName; 4240 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 4241 return false; 4242 } 4243 } 4244 4245 if (parsedComponent != null && parsedComponent.splitName == null) { 4246 // If the loaded component did not specify a split, inherit the split name 4247 // based on the split it is defined in. 4248 // This is used to later load the correct split when starting this 4249 // component. 4250 parsedComponent.splitName = owner.splitNames[splitIndex]; 4251 } 4252 } 4253 4254 return true; 4255 } 4256 parsePackageItemInfo(Package owner, PackageItemInfo outInfo, String[] outError, String tag, TypedArray sa, boolean nameRequired, int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes)4257 private static boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo, 4258 String[] outError, String tag, TypedArray sa, boolean nameRequired, 4259 int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) { 4260 // This case can only happen in unit tests where we sometimes need to create fakes 4261 // of various package parser data structures. 4262 if (sa == null) { 4263 outError[0] = tag + " does not contain any attributes"; 4264 return false; 4265 } 4266 4267 String name = sa.getNonConfigurationString(nameRes, 0); 4268 if (name == null) { 4269 if (nameRequired) { 4270 outError[0] = tag + " does not specify android:name"; 4271 return false; 4272 } 4273 } else { 4274 String outInfoName 4275 = buildClassName(owner.applicationInfo.packageName, name, outError); 4276 if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(outInfoName)) { 4277 outError[0] = tag + " invalid android:name"; 4278 return false; 4279 } 4280 outInfo.name = outInfoName; 4281 if (outInfoName == null) { 4282 return false; 4283 } 4284 } 4285 4286 int roundIconVal = sUseRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0; 4287 if (roundIconVal != 0) { 4288 outInfo.icon = roundIconVal; 4289 outInfo.nonLocalizedLabel = null; 4290 } else { 4291 int iconVal = sa.getResourceId(iconRes, 0); 4292 if (iconVal != 0) { 4293 outInfo.icon = iconVal; 4294 outInfo.nonLocalizedLabel = null; 4295 } 4296 } 4297 4298 int logoVal = sa.getResourceId(logoRes, 0); 4299 if (logoVal != 0) { 4300 outInfo.logo = logoVal; 4301 } 4302 4303 int bannerVal = sa.getResourceId(bannerRes, 0); 4304 if (bannerVal != 0) { 4305 outInfo.banner = bannerVal; 4306 } 4307 4308 TypedValue v = sa.peekValue(labelRes); 4309 if (v != null && (outInfo.labelRes=v.resourceId) == 0) { 4310 outInfo.nonLocalizedLabel = v.coerceToString(); 4311 } 4312 4313 outInfo.packageName = owner.packageName; 4314 4315 return true; 4316 } 4317 4318 /** 4319 * Generate activity object that forwards user to App Details page automatically. 4320 * This activity should be invisible to user and user should not know or see it. 4321 */ generateAppDetailsHiddenActivity( PackageParser.Package owner, int flags, String[] outError, boolean hardwareAccelerated)4322 private @NonNull PackageParser.Activity generateAppDetailsHiddenActivity( 4323 PackageParser.Package owner, int flags, String[] outError, 4324 boolean hardwareAccelerated) { 4325 4326 // Build custom App Details activity info instead of parsing it from xml 4327 Activity a = new Activity(owner, PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME, 4328 new ActivityInfo()); 4329 a.owner = owner; 4330 a.setPackageName(owner.packageName); 4331 4332 a.info.theme = android.R.style.Theme_NoDisplay; 4333 a.info.exported = true; 4334 a.info.name = PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME; 4335 a.info.processName = owner.applicationInfo.processName; 4336 a.info.uiOptions = a.info.applicationInfo.uiOptions; 4337 a.info.taskAffinity = buildTaskAffinityName(owner.packageName, owner.packageName, 4338 ":app_details", outError); 4339 a.info.enabled = true; 4340 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE; 4341 a.info.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NONE; 4342 a.info.maxRecents = ActivityTaskManager.getDefaultAppRecentsLimitStatic(); 4343 a.info.configChanges = getActivityConfigChanges(0, 0); 4344 a.info.softInputMode = 0; 4345 a.info.persistableMode = ActivityInfo.PERSIST_NEVER; 4346 a.info.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED; 4347 a.info.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE; 4348 a.info.lockTaskLaunchMode = 0; 4349 a.info.encryptionAware = a.info.directBootAware = false; 4350 a.info.rotationAnimation = ROTATION_ANIMATION_UNSPECIFIED; 4351 a.info.colorMode = ActivityInfo.COLOR_MODE_DEFAULT; 4352 if (hardwareAccelerated) { 4353 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED; 4354 } 4355 return a; 4356 } 4357 parseActivity(Package owner, Resources res, XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs, boolean receiver, boolean hardwareAccelerated)4358 private Activity parseActivity(Package owner, Resources res, 4359 XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs, 4360 boolean receiver, boolean hardwareAccelerated) 4361 throws XmlPullParserException, IOException { 4362 TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity); 4363 4364 if (cachedArgs.mActivityArgs == null) { 4365 cachedArgs.mActivityArgs = new ParseComponentArgs(owner, outError, 4366 R.styleable.AndroidManifestActivity_name, 4367 R.styleable.AndroidManifestActivity_label, 4368 R.styleable.AndroidManifestActivity_icon, 4369 R.styleable.AndroidManifestActivity_roundIcon, 4370 R.styleable.AndroidManifestActivity_logo, 4371 R.styleable.AndroidManifestActivity_banner, 4372 mSeparateProcesses, 4373 R.styleable.AndroidManifestActivity_process, 4374 R.styleable.AndroidManifestActivity_description, 4375 R.styleable.AndroidManifestActivity_enabled); 4376 } 4377 4378 cachedArgs.mActivityArgs.tag = receiver ? "<receiver>" : "<activity>"; 4379 cachedArgs.mActivityArgs.sa = sa; 4380 cachedArgs.mActivityArgs.flags = flags; 4381 4382 Activity a = new Activity(cachedArgs.mActivityArgs, new ActivityInfo()); 4383 if (outError[0] != null) { 4384 sa.recycle(); 4385 return null; 4386 } 4387 4388 boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported); 4389 if (setExported) { 4390 a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false); 4391 } 4392 4393 a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0); 4394 4395 a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions, 4396 a.info.applicationInfo.uiOptions); 4397 4398 String parentName = sa.getNonConfigurationString( 4399 R.styleable.AndroidManifestActivity_parentActivityName, 4400 Configuration.NATIVE_CONFIG_VERSION); 4401 if (parentName != null) { 4402 String parentClassName = buildClassName(a.info.packageName, parentName, outError); 4403 if (outError[0] == null) { 4404 a.info.parentActivityName = parentClassName; 4405 } else { 4406 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " + 4407 parentName); 4408 outError[0] = null; 4409 } 4410 } 4411 4412 String str; 4413 str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0); 4414 if (str == null) { 4415 a.info.permission = owner.applicationInfo.permission; 4416 } else { 4417 a.info.permission = str.length() > 0 ? str.toString().intern() : null; 4418 } 4419 4420 str = sa.getNonConfigurationString( 4421 R.styleable.AndroidManifestActivity_taskAffinity, 4422 Configuration.NATIVE_CONFIG_VERSION); 4423 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName, 4424 owner.applicationInfo.taskAffinity, str, outError); 4425 4426 a.info.splitName = 4427 sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_splitName, 0); 4428 4429 a.info.flags = 0; 4430 if (sa.getBoolean( 4431 R.styleable.AndroidManifestActivity_multiprocess, false)) { 4432 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS; 4433 } 4434 4435 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) { 4436 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH; 4437 } 4438 4439 if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) { 4440 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH; 4441 } 4442 4443 if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) { 4444 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY; 4445 } 4446 4447 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) { 4448 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE; 4449 } 4450 4451 if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) { 4452 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED; 4453 } 4454 4455 if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) { 4456 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS; 4457 } 4458 4459 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting, 4460 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) { 4461 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING; 4462 } 4463 4464 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) { 4465 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS; 4466 } 4467 4468 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false) 4469 || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) { 4470 a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS; 4471 } 4472 4473 if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) { 4474 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE; 4475 } 4476 4477 if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) { 4478 a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY; 4479 } 4480 4481 if (!receiver) { 4482 if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated, 4483 hardwareAccelerated)) { 4484 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED; 4485 } 4486 4487 a.info.launchMode = sa.getInt( 4488 R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE); 4489 a.info.documentLaunchMode = sa.getInt( 4490 R.styleable.AndroidManifestActivity_documentLaunchMode, 4491 ActivityInfo.DOCUMENT_LAUNCH_NONE); 4492 a.info.maxRecents = sa.getInt( 4493 R.styleable.AndroidManifestActivity_maxRecents, 4494 ActivityTaskManager.getDefaultAppRecentsLimitStatic()); 4495 a.info.configChanges = getActivityConfigChanges( 4496 sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0), 4497 sa.getInt(R.styleable.AndroidManifestActivity_recreateOnConfigChanges, 0)); 4498 a.info.softInputMode = sa.getInt( 4499 R.styleable.AndroidManifestActivity_windowSoftInputMode, 0); 4500 4501 a.info.persistableMode = sa.getInteger( 4502 R.styleable.AndroidManifestActivity_persistableMode, 4503 ActivityInfo.PERSIST_ROOT_ONLY); 4504 4505 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) { 4506 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED; 4507 } 4508 4509 if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) { 4510 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS; 4511 } 4512 4513 if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) { 4514 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY; 4515 } 4516 4517 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) { 4518 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING; 4519 } 4520 4521 a.info.screenOrientation = sa.getInt( 4522 R.styleable.AndroidManifestActivity_screenOrientation, 4523 SCREEN_ORIENTATION_UNSPECIFIED); 4524 4525 setActivityResizeMode(a.info, sa, owner); 4526 4527 if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture, 4528 false)) { 4529 a.info.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE; 4530 } 4531 4532 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) { 4533 a.info.flags |= FLAG_ALWAYS_FOCUSABLE; 4534 } 4535 4536 if (sa.hasValue(R.styleable.AndroidManifestActivity_maxAspectRatio) 4537 && sa.getType(R.styleable.AndroidManifestActivity_maxAspectRatio) 4538 == TypedValue.TYPE_FLOAT) { 4539 a.setMaxAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_maxAspectRatio, 4540 0 /*default*/)); 4541 } 4542 4543 if (sa.hasValue(R.styleable.AndroidManifestActivity_minAspectRatio) 4544 && sa.getType(R.styleable.AndroidManifestActivity_minAspectRatio) 4545 == TypedValue.TYPE_FLOAT) { 4546 a.setMinAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_minAspectRatio, 4547 0 /*default*/)); 4548 } 4549 4550 a.info.lockTaskLaunchMode = 4551 sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0); 4552 4553 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean( 4554 R.styleable.AndroidManifestActivity_directBootAware, 4555 false); 4556 4557 a.info.requestedVrComponent = 4558 sa.getString(R.styleable.AndroidManifestActivity_enableVrMode); 4559 4560 a.info.rotationAnimation = 4561 sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, ROTATION_ANIMATION_UNSPECIFIED); 4562 4563 a.info.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode, 4564 ActivityInfo.COLOR_MODE_DEFAULT); 4565 4566 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showWhenLocked, false)) { 4567 a.info.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED; 4568 } 4569 4570 if (sa.getBoolean(R.styleable.AndroidManifestActivity_turnScreenOn, false)) { 4571 a.info.flags |= ActivityInfo.FLAG_TURN_SCREEN_ON; 4572 } 4573 4574 if (sa.getBoolean(R.styleable.AndroidManifestActivity_inheritShowWhenLocked, false)) { 4575 a.info.privateFlags |= ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED; 4576 } 4577 } else { 4578 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE; 4579 a.info.configChanges = 0; 4580 4581 if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) { 4582 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER; 4583 } 4584 4585 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean( 4586 R.styleable.AndroidManifestActivity_directBootAware, 4587 false); 4588 } 4589 4590 if (a.info.directBootAware) { 4591 owner.applicationInfo.privateFlags |= 4592 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE; 4593 } 4594 4595 // can't make this final; we may set it later via meta-data 4596 boolean visibleToEphemeral = 4597 sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false); 4598 if (visibleToEphemeral) { 4599 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP; 4600 owner.visibleToInstantApps = true; 4601 } 4602 4603 sa.recycle(); 4604 4605 if (receiver && (owner.applicationInfo.privateFlags 4606 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) { 4607 // A heavy-weight application can not have receives in its main process 4608 // We can do direct compare because we intern all strings. 4609 if (a.info.processName == owner.packageName) { 4610 outError[0] = "Heavy-weight applications can not have receivers in main process"; 4611 } 4612 } 4613 4614 if (outError[0] != null) { 4615 return null; 4616 } 4617 4618 int outerDepth = parser.getDepth(); 4619 int type; 4620 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 4621 && (type != XmlPullParser.END_TAG 4622 || parser.getDepth() > outerDepth)) { 4623 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 4624 continue; 4625 } 4626 4627 if (parser.getName().equals("intent-filter")) { 4628 ActivityIntentInfo intent = new ActivityIntentInfo(a); 4629 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/, 4630 intent, outError)) { 4631 return null; 4632 } 4633 if (intent.countActions() == 0) { 4634 Slog.w(TAG, "No actions in intent filter at " 4635 + mArchiveSourcePath + " " 4636 + parser.getPositionDescription()); 4637 } else { 4638 a.order = Math.max(intent.getOrder(), a.order); 4639 a.intents.add(intent); 4640 } 4641 // adjust activity flags when we implicitly expose it via a browsable filter 4642 final int visibility = visibleToEphemeral 4643 ? IntentFilter.VISIBILITY_EXPLICIT 4644 : !receiver && isImplicitlyExposedIntent(intent) 4645 ? IntentFilter.VISIBILITY_IMPLICIT 4646 : IntentFilter.VISIBILITY_NONE; 4647 intent.setVisibilityToInstantApp(visibility); 4648 if (intent.isVisibleToInstantApp()) { 4649 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP; 4650 } 4651 if (intent.isImplicitlyVisibleToInstantApp()) { 4652 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP; 4653 } 4654 if (LOG_UNSAFE_BROADCASTS && receiver 4655 && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) { 4656 for (int i = 0; i < intent.countActions(); i++) { 4657 final String action = intent.getAction(i); 4658 if (action == null || !action.startsWith("android.")) continue; 4659 if (!SAFE_BROADCASTS.contains(action)) { 4660 Slog.w(TAG, "Broadcast " + action + " may never be delivered to " 4661 + owner.packageName + " as requested at: " 4662 + parser.getPositionDescription()); 4663 } 4664 } 4665 } 4666 } else if (!receiver && parser.getName().equals("preferred")) { 4667 ActivityIntentInfo intent = new ActivityIntentInfo(a); 4668 if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/, 4669 intent, outError)) { 4670 return null; 4671 } 4672 if (intent.countActions() == 0) { 4673 Slog.w(TAG, "No actions in preferred at " 4674 + mArchiveSourcePath + " " 4675 + parser.getPositionDescription()); 4676 } else { 4677 if (owner.preferredActivityFilters == null) { 4678 owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>(); 4679 } 4680 owner.preferredActivityFilters.add(intent); 4681 } 4682 // adjust activity flags when we implicitly expose it via a browsable filter 4683 final int visibility = visibleToEphemeral 4684 ? IntentFilter.VISIBILITY_EXPLICIT 4685 : !receiver && isImplicitlyExposedIntent(intent) 4686 ? IntentFilter.VISIBILITY_IMPLICIT 4687 : IntentFilter.VISIBILITY_NONE; 4688 intent.setVisibilityToInstantApp(visibility); 4689 if (intent.isVisibleToInstantApp()) { 4690 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP; 4691 } 4692 if (intent.isImplicitlyVisibleToInstantApp()) { 4693 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP; 4694 } 4695 } else if (parser.getName().equals("meta-data")) { 4696 if ((a.metaData = parseMetaData(res, parser, a.metaData, 4697 outError)) == null) { 4698 return null; 4699 } 4700 } else if (!receiver && parser.getName().equals("layout")) { 4701 parseLayout(res, parser, a); 4702 } else { 4703 if (!RIGID_PARSER) { 4704 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); 4705 if (receiver) { 4706 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName() 4707 + " at " + mArchiveSourcePath + " " 4708 + parser.getPositionDescription()); 4709 } else { 4710 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName() 4711 + " at " + mArchiveSourcePath + " " 4712 + parser.getPositionDescription()); 4713 } 4714 XmlUtils.skipCurrentTag(parser); 4715 continue; 4716 } else { 4717 if (receiver) { 4718 outError[0] = "Bad element under <receiver>: " + parser.getName(); 4719 } else { 4720 outError[0] = "Bad element under <activity>: " + parser.getName(); 4721 } 4722 return null; 4723 } 4724 } 4725 } 4726 4727 if (!setExported) { 4728 a.info.exported = a.intents.size() > 0; 4729 } 4730 4731 return a; 4732 } 4733 setActivityResizeMode(ActivityInfo aInfo, TypedArray sa, Package owner)4734 private void setActivityResizeMode(ActivityInfo aInfo, TypedArray sa, Package owner) { 4735 final boolean appExplicitDefault = (owner.applicationInfo.privateFlags 4736 & (PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE 4737 | PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE)) != 0; 4738 4739 if (sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity) 4740 || appExplicitDefault) { 4741 // Activity or app explicitly set if it is resizeable or not; 4742 final boolean appResizeable = (owner.applicationInfo.privateFlags 4743 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE) != 0; 4744 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity, 4745 appResizeable)) { 4746 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE; 4747 } else { 4748 aInfo.resizeMode = RESIZE_MODE_UNRESIZEABLE; 4749 } 4750 return; 4751 } 4752 4753 if ((owner.applicationInfo.privateFlags 4754 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) != 0) { 4755 // The activity or app didn't explicitly set the resizing option, however we want to 4756 // make it resize due to the sdk version it is targeting. 4757 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION; 4758 return; 4759 } 4760 4761 // resize preference isn't set and target sdk version doesn't support resizing apps by 4762 // default. For the app to be resizeable if it isn't fixed orientation or immersive. 4763 if (aInfo.isFixedOrientationPortrait()) { 4764 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY; 4765 } else if (aInfo.isFixedOrientationLandscape()) { 4766 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY; 4767 } else if (aInfo.isFixedOrientation()) { 4768 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION; 4769 } else { 4770 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE; 4771 } 4772 } 4773 4774 /** 4775 * Sets every the max aspect ratio of every child activity that doesn't already have an aspect 4776 * ratio set. 4777 */ setMaxAspectRatio(Package owner)4778 private void setMaxAspectRatio(Package owner) { 4779 // Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater. 4780 // NOTE: 16.7:9 was the max aspect ratio Android devices can support pre-O per the CDD. 4781 float maxAspectRatio = owner.applicationInfo.targetSdkVersion < O 4782 ? DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0; 4783 4784 if (owner.applicationInfo.maxAspectRatio != 0) { 4785 // Use the application max aspect ration as default if set. 4786 maxAspectRatio = owner.applicationInfo.maxAspectRatio; 4787 } else if (owner.mAppMetaData != null 4788 && owner.mAppMetaData.containsKey(METADATA_MAX_ASPECT_RATIO)) { 4789 maxAspectRatio = owner.mAppMetaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio); 4790 } 4791 4792 for (Activity activity : owner.activities) { 4793 // If the max aspect ratio for the activity has already been set, skip. 4794 if (activity.hasMaxAspectRatio()) { 4795 continue; 4796 } 4797 4798 // By default we prefer to use a values defined on the activity directly than values 4799 // defined on the application. We do not check the styled attributes on the activity 4800 // as it would have already been set when we processed the activity. We wait to process 4801 // the meta data here since this method is called at the end of processing the 4802 // application and all meta data is guaranteed. 4803 final float activityAspectRatio = activity.metaData != null 4804 ? activity.metaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio) 4805 : maxAspectRatio; 4806 4807 activity.setMaxAspectRatio(activityAspectRatio); 4808 } 4809 } 4810 4811 /** 4812 * Sets every the min aspect ratio of every child activity that doesn't already have an aspect 4813 * ratio set. 4814 */ 4815 private void setMinAspectRatio(Package owner) { 4816 final float minAspectRatio; 4817 if (owner.applicationInfo.minAspectRatio != 0) { 4818 // Use the application max aspect ration as default if set. 4819 minAspectRatio = owner.applicationInfo.minAspectRatio; 4820 } else { 4821 // Default to (1.33) 4:3 aspect ratio for pre-Q apps and unset for Q and greater. 4822 // NOTE: 4:3 was the min aspect ratio Android devices can support pre-Q per the CDD, 4823 // except for watches which always supported 1:1. 4824 minAspectRatio = owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q 4825 ? 0 4826 : (mCallback != null && mCallback.hasFeature(FEATURE_WATCH)) 4827 ? DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH 4828 : DEFAULT_PRE_Q_MIN_ASPECT_RATIO; 4829 } 4830 4831 for (Activity activity : owner.activities) { 4832 if (activity.hasMinAspectRatio()) { 4833 continue; 4834 } 4835 activity.setMinAspectRatio(minAspectRatio); 4836 } 4837 } 4838 4839 /** 4840 * @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml. 4841 * @param recreateOnConfigChanges The bit mask recreateOnConfigChanges fetched from 4842 * AndroidManifest.xml. 4843 * @hide Exposed for unit testing only. 4844 */ getActivityConfigChanges(int configChanges, int recreateOnConfigChanges)4845 public static int getActivityConfigChanges(int configChanges, int recreateOnConfigChanges) { 4846 return configChanges | ((~recreateOnConfigChanges) & RECREATE_ON_CONFIG_CHANGES_MASK); 4847 } 4848 parseLayout(Resources res, AttributeSet attrs, Activity a)4849 private void parseLayout(Resources res, AttributeSet attrs, Activity a) { 4850 TypedArray sw = res.obtainAttributes(attrs, 4851 com.android.internal.R.styleable.AndroidManifestLayout); 4852 int width = -1; 4853 float widthFraction = -1f; 4854 int height = -1; 4855 float heightFraction = -1f; 4856 final int widthType = sw.getType( 4857 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth); 4858 if (widthType == TypedValue.TYPE_FRACTION) { 4859 widthFraction = sw.getFraction( 4860 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth, 4861 1, 1, -1); 4862 } else if (widthType == TypedValue.TYPE_DIMENSION) { 4863 width = sw.getDimensionPixelSize( 4864 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth, 4865 -1); 4866 } 4867 final int heightType = sw.getType( 4868 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight); 4869 if (heightType == TypedValue.TYPE_FRACTION) { 4870 heightFraction = sw.getFraction( 4871 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight, 4872 1, 1, -1); 4873 } else if (heightType == TypedValue.TYPE_DIMENSION) { 4874 height = sw.getDimensionPixelSize( 4875 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight, 4876 -1); 4877 } 4878 int gravity = sw.getInt( 4879 com.android.internal.R.styleable.AndroidManifestLayout_gravity, 4880 Gravity.CENTER); 4881 int minWidth = sw.getDimensionPixelSize( 4882 com.android.internal.R.styleable.AndroidManifestLayout_minWidth, 4883 -1); 4884 int minHeight = sw.getDimensionPixelSize( 4885 com.android.internal.R.styleable.AndroidManifestLayout_minHeight, 4886 -1); 4887 sw.recycle(); 4888 a.info.windowLayout = new ActivityInfo.WindowLayout(width, widthFraction, 4889 height, heightFraction, gravity, minWidth, minHeight); 4890 } 4891 parseActivityAlias(Package owner, Resources res, XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs)4892 private Activity parseActivityAlias(Package owner, Resources res, 4893 XmlResourceParser parser, int flags, String[] outError, 4894 CachedComponentArgs cachedArgs) 4895 throws XmlPullParserException, IOException { 4896 TypedArray sa = res.obtainAttributes(parser, 4897 com.android.internal.R.styleable.AndroidManifestActivityAlias); 4898 4899 String targetActivity = sa.getNonConfigurationString( 4900 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity, 4901 Configuration.NATIVE_CONFIG_VERSION); 4902 if (targetActivity == null) { 4903 outError[0] = "<activity-alias> does not specify android:targetActivity"; 4904 sa.recycle(); 4905 return null; 4906 } 4907 4908 targetActivity = buildClassName(owner.applicationInfo.packageName, 4909 targetActivity, outError); 4910 if (targetActivity == null) { 4911 sa.recycle(); 4912 return null; 4913 } 4914 4915 if (cachedArgs.mActivityAliasArgs == null) { 4916 cachedArgs.mActivityAliasArgs = new ParseComponentArgs(owner, outError, 4917 com.android.internal.R.styleable.AndroidManifestActivityAlias_name, 4918 com.android.internal.R.styleable.AndroidManifestActivityAlias_label, 4919 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon, 4920 com.android.internal.R.styleable.AndroidManifestActivityAlias_roundIcon, 4921 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo, 4922 com.android.internal.R.styleable.AndroidManifestActivityAlias_banner, 4923 mSeparateProcesses, 4924 0, 4925 com.android.internal.R.styleable.AndroidManifestActivityAlias_description, 4926 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled); 4927 cachedArgs.mActivityAliasArgs.tag = "<activity-alias>"; 4928 } 4929 4930 cachedArgs.mActivityAliasArgs.sa = sa; 4931 cachedArgs.mActivityAliasArgs.flags = flags; 4932 4933 Activity target = null; 4934 4935 final int NA = owner.activities.size(); 4936 for (int i=0; i<NA; i++) { 4937 Activity t = owner.activities.get(i); 4938 if (targetActivity.equals(t.info.name)) { 4939 target = t; 4940 break; 4941 } 4942 } 4943 4944 if (target == null) { 4945 outError[0] = "<activity-alias> target activity " + targetActivity 4946 + " not found in manifest"; 4947 sa.recycle(); 4948 return null; 4949 } 4950 4951 ActivityInfo info = new ActivityInfo(); 4952 info.targetActivity = targetActivity; 4953 info.configChanges = target.info.configChanges; 4954 info.flags = target.info.flags; 4955 info.privateFlags = target.info.privateFlags; 4956 info.icon = target.info.icon; 4957 info.logo = target.info.logo; 4958 info.banner = target.info.banner; 4959 info.labelRes = target.info.labelRes; 4960 info.nonLocalizedLabel = target.info.nonLocalizedLabel; 4961 info.launchMode = target.info.launchMode; 4962 info.lockTaskLaunchMode = target.info.lockTaskLaunchMode; 4963 info.processName = target.info.processName; 4964 if (info.descriptionRes == 0) { 4965 info.descriptionRes = target.info.descriptionRes; 4966 } 4967 info.screenOrientation = target.info.screenOrientation; 4968 info.taskAffinity = target.info.taskAffinity; 4969 info.theme = target.info.theme; 4970 info.softInputMode = target.info.softInputMode; 4971 info.uiOptions = target.info.uiOptions; 4972 info.parentActivityName = target.info.parentActivityName; 4973 info.maxRecents = target.info.maxRecents; 4974 info.windowLayout = target.info.windowLayout; 4975 info.resizeMode = target.info.resizeMode; 4976 info.maxAspectRatio = target.info.maxAspectRatio; 4977 info.minAspectRatio = target.info.minAspectRatio; 4978 info.requestedVrComponent = target.info.requestedVrComponent; 4979 4980 info.encryptionAware = info.directBootAware = target.info.directBootAware; 4981 4982 Activity a = new Activity(cachedArgs.mActivityAliasArgs, info); 4983 if (outError[0] != null) { 4984 sa.recycle(); 4985 return null; 4986 } 4987 4988 final boolean setExported = sa.hasValue( 4989 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported); 4990 if (setExported) { 4991 a.info.exported = sa.getBoolean( 4992 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false); 4993 } 4994 4995 String str; 4996 str = sa.getNonConfigurationString( 4997 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0); 4998 if (str != null) { 4999 a.info.permission = str.length() > 0 ? str.toString().intern() : null; 5000 } 5001 5002 String parentName = sa.getNonConfigurationString( 5003 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName, 5004 Configuration.NATIVE_CONFIG_VERSION); 5005 if (parentName != null) { 5006 String parentClassName = buildClassName(a.info.packageName, parentName, outError); 5007 if (outError[0] == null) { 5008 a.info.parentActivityName = parentClassName; 5009 } else { 5010 Log.e(TAG, "Activity alias " + a.info.name + 5011 " specified invalid parentActivityName " + parentName); 5012 outError[0] = null; 5013 } 5014 } 5015 5016 // TODO add visibleToInstantApps attribute to activity alias 5017 final boolean visibleToEphemeral = 5018 ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0); 5019 5020 sa.recycle(); 5021 5022 if (outError[0] != null) { 5023 return null; 5024 } 5025 5026 int outerDepth = parser.getDepth(); 5027 int type; 5028 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 5029 && (type != XmlPullParser.END_TAG 5030 || parser.getDepth() > outerDepth)) { 5031 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 5032 continue; 5033 } 5034 5035 if (parser.getName().equals("intent-filter")) { 5036 ActivityIntentInfo intent = new ActivityIntentInfo(a); 5037 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/, 5038 intent, outError)) { 5039 return null; 5040 } 5041 if (intent.countActions() == 0) { 5042 Slog.w(TAG, "No actions in intent filter at " 5043 + mArchiveSourcePath + " " 5044 + parser.getPositionDescription()); 5045 } else { 5046 a.order = Math.max(intent.getOrder(), a.order); 5047 a.intents.add(intent); 5048 } 5049 // adjust activity flags when we implicitly expose it via a browsable filter 5050 final int visibility = visibleToEphemeral 5051 ? IntentFilter.VISIBILITY_EXPLICIT 5052 : isImplicitlyExposedIntent(intent) 5053 ? IntentFilter.VISIBILITY_IMPLICIT 5054 : IntentFilter.VISIBILITY_NONE; 5055 intent.setVisibilityToInstantApp(visibility); 5056 if (intent.isVisibleToInstantApp()) { 5057 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP; 5058 } 5059 if (intent.isImplicitlyVisibleToInstantApp()) { 5060 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP; 5061 } 5062 } else if (parser.getName().equals("meta-data")) { 5063 if ((a.metaData=parseMetaData(res, parser, a.metaData, 5064 outError)) == null) { 5065 return null; 5066 } 5067 } else { 5068 if (!RIGID_PARSER) { 5069 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName() 5070 + " at " + mArchiveSourcePath + " " 5071 + parser.getPositionDescription()); 5072 XmlUtils.skipCurrentTag(parser); 5073 continue; 5074 } else { 5075 outError[0] = "Bad element under <activity-alias>: " + parser.getName(); 5076 return null; 5077 } 5078 } 5079 } 5080 5081 if (!setExported) { 5082 a.info.exported = a.intents.size() > 0; 5083 } 5084 5085 return a; 5086 } 5087 parseProvider(Package owner, Resources res, XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs)5088 private Provider parseProvider(Package owner, Resources res, 5089 XmlResourceParser parser, int flags, String[] outError, 5090 CachedComponentArgs cachedArgs) 5091 throws XmlPullParserException, IOException { 5092 TypedArray sa = res.obtainAttributes(parser, 5093 com.android.internal.R.styleable.AndroidManifestProvider); 5094 5095 if (cachedArgs.mProviderArgs == null) { 5096 cachedArgs.mProviderArgs = new ParseComponentArgs(owner, outError, 5097 com.android.internal.R.styleable.AndroidManifestProvider_name, 5098 com.android.internal.R.styleable.AndroidManifestProvider_label, 5099 com.android.internal.R.styleable.AndroidManifestProvider_icon, 5100 com.android.internal.R.styleable.AndroidManifestProvider_roundIcon, 5101 com.android.internal.R.styleable.AndroidManifestProvider_logo, 5102 com.android.internal.R.styleable.AndroidManifestProvider_banner, 5103 mSeparateProcesses, 5104 com.android.internal.R.styleable.AndroidManifestProvider_process, 5105 com.android.internal.R.styleable.AndroidManifestProvider_description, 5106 com.android.internal.R.styleable.AndroidManifestProvider_enabled); 5107 cachedArgs.mProviderArgs.tag = "<provider>"; 5108 } 5109 5110 cachedArgs.mProviderArgs.sa = sa; 5111 cachedArgs.mProviderArgs.flags = flags; 5112 5113 Provider p = new Provider(cachedArgs.mProviderArgs, new ProviderInfo()); 5114 if (outError[0] != null) { 5115 sa.recycle(); 5116 return null; 5117 } 5118 5119 boolean providerExportedDefault = false; 5120 5121 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) { 5122 // For compatibility, applications targeting API level 16 or lower 5123 // should have their content providers exported by default, unless they 5124 // specify otherwise. 5125 providerExportedDefault = true; 5126 } 5127 5128 p.info.exported = sa.getBoolean( 5129 com.android.internal.R.styleable.AndroidManifestProvider_exported, 5130 providerExportedDefault); 5131 5132 String cpname = sa.getNonConfigurationString( 5133 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0); 5134 5135 p.info.isSyncable = sa.getBoolean( 5136 com.android.internal.R.styleable.AndroidManifestProvider_syncable, 5137 false); 5138 5139 String permission = sa.getNonConfigurationString( 5140 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0); 5141 String str = sa.getNonConfigurationString( 5142 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0); 5143 if (str == null) { 5144 str = permission; 5145 } 5146 if (str == null) { 5147 p.info.readPermission = owner.applicationInfo.permission; 5148 } else { 5149 p.info.readPermission = 5150 str.length() > 0 ? str.toString().intern() : null; 5151 } 5152 str = sa.getNonConfigurationString( 5153 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0); 5154 if (str == null) { 5155 str = permission; 5156 } 5157 if (str == null) { 5158 p.info.writePermission = owner.applicationInfo.permission; 5159 } else { 5160 p.info.writePermission = 5161 str.length() > 0 ? str.toString().intern() : null; 5162 } 5163 5164 p.info.grantUriPermissions = sa.getBoolean( 5165 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions, 5166 false); 5167 5168 p.info.forceUriPermissions = sa.getBoolean( 5169 com.android.internal.R.styleable.AndroidManifestProvider_forceUriPermissions, 5170 false); 5171 5172 p.info.multiprocess = sa.getBoolean( 5173 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess, 5174 false); 5175 5176 p.info.initOrder = sa.getInt( 5177 com.android.internal.R.styleable.AndroidManifestProvider_initOrder, 5178 0); 5179 5180 p.info.splitName = 5181 sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_splitName, 0); 5182 5183 p.info.flags = 0; 5184 5185 if (sa.getBoolean( 5186 com.android.internal.R.styleable.AndroidManifestProvider_singleUser, 5187 false)) { 5188 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER; 5189 } 5190 5191 p.info.encryptionAware = p.info.directBootAware = sa.getBoolean( 5192 R.styleable.AndroidManifestProvider_directBootAware, 5193 false); 5194 if (p.info.directBootAware) { 5195 owner.applicationInfo.privateFlags |= 5196 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE; 5197 } 5198 5199 final boolean visibleToEphemeral = 5200 sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false); 5201 if (visibleToEphemeral) { 5202 p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP; 5203 owner.visibleToInstantApps = true; 5204 } 5205 5206 sa.recycle(); 5207 5208 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) 5209 != 0) { 5210 // A heavy-weight application can not have providers in its main process 5211 // We can do direct compare because we intern all strings. 5212 if (p.info.processName == owner.packageName) { 5213 outError[0] = "Heavy-weight applications can not have providers in main process"; 5214 return null; 5215 } 5216 } 5217 5218 if (cpname == null) { 5219 outError[0] = "<provider> does not include authorities attribute"; 5220 return null; 5221 } 5222 if (cpname.length() <= 0) { 5223 outError[0] = "<provider> has empty authorities attribute"; 5224 return null; 5225 } 5226 p.info.authority = cpname.intern(); 5227 5228 if (!parseProviderTags( 5229 res, parser, visibleToEphemeral, p, outError)) { 5230 return null; 5231 } 5232 5233 return p; 5234 } 5235 parseProviderTags(Resources res, XmlResourceParser parser, boolean visibleToEphemeral, Provider outInfo, String[] outError)5236 private boolean parseProviderTags(Resources res, XmlResourceParser parser, 5237 boolean visibleToEphemeral, Provider outInfo, String[] outError) 5238 throws XmlPullParserException, IOException { 5239 int outerDepth = parser.getDepth(); 5240 int type; 5241 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 5242 && (type != XmlPullParser.END_TAG 5243 || parser.getDepth() > outerDepth)) { 5244 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 5245 continue; 5246 } 5247 5248 if (parser.getName().equals("intent-filter")) { 5249 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo); 5250 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/, 5251 intent, outError)) { 5252 return false; 5253 } 5254 if (visibleToEphemeral) { 5255 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT); 5256 outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP; 5257 } 5258 outInfo.order = Math.max(intent.getOrder(), outInfo.order); 5259 outInfo.intents.add(intent); 5260 5261 } else if (parser.getName().equals("meta-data")) { 5262 if ((outInfo.metaData=parseMetaData(res, parser, 5263 outInfo.metaData, outError)) == null) { 5264 return false; 5265 } 5266 5267 } else if (parser.getName().equals("grant-uri-permission")) { 5268 TypedArray sa = res.obtainAttributes(parser, 5269 com.android.internal.R.styleable.AndroidManifestGrantUriPermission); 5270 5271 PatternMatcher pa = null; 5272 5273 String str = sa.getNonConfigurationString( 5274 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0); 5275 if (str != null) { 5276 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL); 5277 } 5278 5279 str = sa.getNonConfigurationString( 5280 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0); 5281 if (str != null) { 5282 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX); 5283 } 5284 5285 str = sa.getNonConfigurationString( 5286 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0); 5287 if (str != null) { 5288 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB); 5289 } 5290 5291 sa.recycle(); 5292 5293 if (pa != null) { 5294 if (outInfo.info.uriPermissionPatterns == null) { 5295 outInfo.info.uriPermissionPatterns = new PatternMatcher[1]; 5296 outInfo.info.uriPermissionPatterns[0] = pa; 5297 } else { 5298 final int N = outInfo.info.uriPermissionPatterns.length; 5299 PatternMatcher[] newp = new PatternMatcher[N+1]; 5300 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N); 5301 newp[N] = pa; 5302 outInfo.info.uriPermissionPatterns = newp; 5303 } 5304 outInfo.info.grantUriPermissions = true; 5305 } else { 5306 if (!RIGID_PARSER) { 5307 Slog.w(TAG, "Unknown element under <path-permission>: " 5308 + parser.getName() + " at " + mArchiveSourcePath + " " 5309 + parser.getPositionDescription()); 5310 XmlUtils.skipCurrentTag(parser); 5311 continue; 5312 } else { 5313 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>"; 5314 return false; 5315 } 5316 } 5317 XmlUtils.skipCurrentTag(parser); 5318 5319 } else if (parser.getName().equals("path-permission")) { 5320 TypedArray sa = res.obtainAttributes(parser, 5321 com.android.internal.R.styleable.AndroidManifestPathPermission); 5322 5323 PathPermission pa = null; 5324 5325 String permission = sa.getNonConfigurationString( 5326 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0); 5327 String readPermission = sa.getNonConfigurationString( 5328 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0); 5329 if (readPermission == null) { 5330 readPermission = permission; 5331 } 5332 String writePermission = sa.getNonConfigurationString( 5333 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0); 5334 if (writePermission == null) { 5335 writePermission = permission; 5336 } 5337 5338 boolean havePerm = false; 5339 if (readPermission != null) { 5340 readPermission = readPermission.intern(); 5341 havePerm = true; 5342 } 5343 if (writePermission != null) { 5344 writePermission = writePermission.intern(); 5345 havePerm = true; 5346 } 5347 5348 if (!havePerm) { 5349 if (!RIGID_PARSER) { 5350 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: " 5351 + parser.getName() + " at " + mArchiveSourcePath + " " 5352 + parser.getPositionDescription()); 5353 XmlUtils.skipCurrentTag(parser); 5354 continue; 5355 } else { 5356 outError[0] = "No readPermission or writePermssion for <path-permission>"; 5357 return false; 5358 } 5359 } 5360 5361 String path = sa.getNonConfigurationString( 5362 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0); 5363 if (path != null) { 5364 pa = new PathPermission(path, 5365 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission); 5366 } 5367 5368 path = sa.getNonConfigurationString( 5369 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0); 5370 if (path != null) { 5371 pa = new PathPermission(path, 5372 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission); 5373 } 5374 5375 path = sa.getNonConfigurationString( 5376 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0); 5377 if (path != null) { 5378 pa = new PathPermission(path, 5379 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission); 5380 } 5381 5382 path = sa.getNonConfigurationString( 5383 com.android.internal.R.styleable.AndroidManifestPathPermission_pathAdvancedPattern, 0); 5384 if (path != null) { 5385 pa = new PathPermission(path, 5386 PatternMatcher.PATTERN_ADVANCED_GLOB, readPermission, writePermission); 5387 } 5388 5389 sa.recycle(); 5390 5391 if (pa != null) { 5392 if (outInfo.info.pathPermissions == null) { 5393 outInfo.info.pathPermissions = new PathPermission[1]; 5394 outInfo.info.pathPermissions[0] = pa; 5395 } else { 5396 final int N = outInfo.info.pathPermissions.length; 5397 PathPermission[] newp = new PathPermission[N+1]; 5398 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N); 5399 newp[N] = pa; 5400 outInfo.info.pathPermissions = newp; 5401 } 5402 } else { 5403 if (!RIGID_PARSER) { 5404 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: " 5405 + parser.getName() + " at " + mArchiveSourcePath + " " 5406 + parser.getPositionDescription()); 5407 XmlUtils.skipCurrentTag(parser); 5408 continue; 5409 } 5410 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>"; 5411 return false; 5412 } 5413 XmlUtils.skipCurrentTag(parser); 5414 5415 } else { 5416 if (!RIGID_PARSER) { 5417 Slog.w(TAG, "Unknown element under <provider>: " 5418 + parser.getName() + " at " + mArchiveSourcePath + " " 5419 + parser.getPositionDescription()); 5420 XmlUtils.skipCurrentTag(parser); 5421 continue; 5422 } else { 5423 outError[0] = "Bad element under <provider>: " + parser.getName(); 5424 return false; 5425 } 5426 } 5427 } 5428 return true; 5429 } 5430 parseService(Package owner, Resources res, XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs)5431 private Service parseService(Package owner, Resources res, 5432 XmlResourceParser parser, int flags, String[] outError, 5433 CachedComponentArgs cachedArgs) 5434 throws XmlPullParserException, IOException { 5435 TypedArray sa = res.obtainAttributes(parser, 5436 com.android.internal.R.styleable.AndroidManifestService); 5437 5438 if (cachedArgs.mServiceArgs == null) { 5439 cachedArgs.mServiceArgs = new ParseComponentArgs(owner, outError, 5440 com.android.internal.R.styleable.AndroidManifestService_name, 5441 com.android.internal.R.styleable.AndroidManifestService_label, 5442 com.android.internal.R.styleable.AndroidManifestService_icon, 5443 com.android.internal.R.styleable.AndroidManifestService_roundIcon, 5444 com.android.internal.R.styleable.AndroidManifestService_logo, 5445 com.android.internal.R.styleable.AndroidManifestService_banner, 5446 mSeparateProcesses, 5447 com.android.internal.R.styleable.AndroidManifestService_process, 5448 com.android.internal.R.styleable.AndroidManifestService_description, 5449 com.android.internal.R.styleable.AndroidManifestService_enabled); 5450 cachedArgs.mServiceArgs.tag = "<service>"; 5451 } 5452 5453 cachedArgs.mServiceArgs.sa = sa; 5454 cachedArgs.mServiceArgs.flags = flags; 5455 5456 Service s = new Service(cachedArgs.mServiceArgs, new ServiceInfo()); 5457 if (outError[0] != null) { 5458 sa.recycle(); 5459 return null; 5460 } 5461 5462 boolean setExported = sa.hasValue( 5463 com.android.internal.R.styleable.AndroidManifestService_exported); 5464 if (setExported) { 5465 s.info.exported = sa.getBoolean( 5466 com.android.internal.R.styleable.AndroidManifestService_exported, false); 5467 } 5468 5469 String str = sa.getNonConfigurationString( 5470 com.android.internal.R.styleable.AndroidManifestService_permission, 0); 5471 if (str == null) { 5472 s.info.permission = owner.applicationInfo.permission; 5473 } else { 5474 s.info.permission = str.length() > 0 ? str.toString().intern() : null; 5475 } 5476 5477 s.info.splitName = 5478 sa.getNonConfigurationString(R.styleable.AndroidManifestService_splitName, 0); 5479 5480 s.info.mForegroundServiceType = sa.getInt( 5481 com.android.internal.R.styleable.AndroidManifestService_foregroundServiceType, 5482 ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE); 5483 5484 s.info.flags = 0; 5485 if (sa.getBoolean( 5486 com.android.internal.R.styleable.AndroidManifestService_stopWithTask, 5487 false)) { 5488 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK; 5489 } 5490 if (sa.getBoolean( 5491 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess, 5492 false)) { 5493 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS; 5494 } 5495 if (sa.getBoolean( 5496 com.android.internal.R.styleable.AndroidManifestService_externalService, 5497 false)) { 5498 s.info.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE; 5499 } 5500 if (sa.getBoolean( 5501 com.android.internal.R.styleable.AndroidManifestService_useAppZygote, 5502 false)) { 5503 s.info.flags |= ServiceInfo.FLAG_USE_APP_ZYGOTE; 5504 } 5505 if (sa.getBoolean( 5506 com.android.internal.R.styleable.AndroidManifestService_singleUser, 5507 false)) { 5508 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER; 5509 } 5510 5511 s.info.encryptionAware = s.info.directBootAware = sa.getBoolean( 5512 R.styleable.AndroidManifestService_directBootAware, 5513 false); 5514 if (s.info.directBootAware) { 5515 owner.applicationInfo.privateFlags |= 5516 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE; 5517 } 5518 5519 boolean visibleToEphemeral = 5520 sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false); 5521 if (visibleToEphemeral) { 5522 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP; 5523 owner.visibleToInstantApps = true; 5524 } 5525 5526 sa.recycle(); 5527 5528 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) 5529 != 0) { 5530 // A heavy-weight application can not have services in its main process 5531 // We can do direct compare because we intern all strings. 5532 if (s.info.processName == owner.packageName) { 5533 outError[0] = "Heavy-weight applications can not have services in main process"; 5534 return null; 5535 } 5536 } 5537 5538 int outerDepth = parser.getDepth(); 5539 int type; 5540 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 5541 && (type != XmlPullParser.END_TAG 5542 || parser.getDepth() > outerDepth)) { 5543 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 5544 continue; 5545 } 5546 5547 if (parser.getName().equals("intent-filter")) { 5548 ServiceIntentInfo intent = new ServiceIntentInfo(s); 5549 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/, 5550 intent, outError)) { 5551 return null; 5552 } 5553 if (visibleToEphemeral) { 5554 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT); 5555 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP; 5556 } 5557 s.order = Math.max(intent.getOrder(), s.order); 5558 s.intents.add(intent); 5559 } else if (parser.getName().equals("meta-data")) { 5560 if ((s.metaData=parseMetaData(res, parser, s.metaData, 5561 outError)) == null) { 5562 return null; 5563 } 5564 } else { 5565 if (!RIGID_PARSER) { 5566 Slog.w(TAG, "Unknown element under <service>: " 5567 + parser.getName() + " at " + mArchiveSourcePath + " " 5568 + parser.getPositionDescription()); 5569 XmlUtils.skipCurrentTag(parser); 5570 continue; 5571 } else { 5572 outError[0] = "Bad element under <service>: " + parser.getName(); 5573 return null; 5574 } 5575 } 5576 } 5577 5578 if (!setExported) { 5579 s.info.exported = s.intents.size() > 0; 5580 } 5581 5582 return s; 5583 } 5584 isImplicitlyExposedIntent(IntentInfo intent)5585 private boolean isImplicitlyExposedIntent(IntentInfo intent) { 5586 return intent.hasCategory(Intent.CATEGORY_BROWSABLE) 5587 || intent.hasAction(Intent.ACTION_SEND) 5588 || intent.hasAction(Intent.ACTION_SENDTO) 5589 || intent.hasAction(Intent.ACTION_SEND_MULTIPLE); 5590 } 5591 parseAllMetaData(Resources res, XmlResourceParser parser, String tag, Component<?> outInfo, String[] outError)5592 private boolean parseAllMetaData(Resources res, XmlResourceParser parser, String tag, 5593 Component<?> outInfo, String[] outError) throws XmlPullParserException, IOException { 5594 int outerDepth = parser.getDepth(); 5595 int type; 5596 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 5597 && (type != XmlPullParser.END_TAG 5598 || parser.getDepth() > outerDepth)) { 5599 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 5600 continue; 5601 } 5602 5603 if (parser.getName().equals("meta-data")) { 5604 if ((outInfo.metaData=parseMetaData(res, parser, 5605 outInfo.metaData, outError)) == null) { 5606 return false; 5607 } 5608 } else { 5609 if (!RIGID_PARSER) { 5610 Slog.w(TAG, "Unknown element under " + tag + ": " 5611 + parser.getName() + " at " + mArchiveSourcePath + " " 5612 + parser.getPositionDescription()); 5613 XmlUtils.skipCurrentTag(parser); 5614 continue; 5615 } else { 5616 outError[0] = "Bad element under " + tag + ": " + parser.getName(); 5617 return false; 5618 } 5619 } 5620 } 5621 return true; 5622 } 5623 parseMetaData(Resources res, XmlResourceParser parser, Bundle data, String[] outError)5624 private Bundle parseMetaData(Resources res, 5625 XmlResourceParser parser, Bundle data, String[] outError) 5626 throws XmlPullParserException, IOException { 5627 5628 TypedArray sa = res.obtainAttributes(parser, 5629 com.android.internal.R.styleable.AndroidManifestMetaData); 5630 5631 if (data == null) { 5632 data = new Bundle(); 5633 } 5634 5635 String name = sa.getNonConfigurationString( 5636 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0); 5637 if (name == null) { 5638 outError[0] = "<meta-data> requires an android:name attribute"; 5639 sa.recycle(); 5640 return null; 5641 } 5642 5643 name = name.intern(); 5644 5645 TypedValue v = sa.peekValue( 5646 com.android.internal.R.styleable.AndroidManifestMetaData_resource); 5647 if (v != null && v.resourceId != 0) { 5648 //Slog.i(TAG, "Meta data ref " + name + ": " + v); 5649 data.putInt(name, v.resourceId); 5650 } else { 5651 v = sa.peekValue( 5652 com.android.internal.R.styleable.AndroidManifestMetaData_value); 5653 //Slog.i(TAG, "Meta data " + name + ": " + v); 5654 if (v != null) { 5655 if (v.type == TypedValue.TYPE_STRING) { 5656 CharSequence cs = v.coerceToString(); 5657 data.putString(name, cs != null ? cs.toString() : null); 5658 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) { 5659 data.putBoolean(name, v.data != 0); 5660 } else if (v.type >= TypedValue.TYPE_FIRST_INT 5661 && v.type <= TypedValue.TYPE_LAST_INT) { 5662 data.putInt(name, v.data); 5663 } else if (v.type == TypedValue.TYPE_FLOAT) { 5664 data.putFloat(name, v.getFloat()); 5665 } else { 5666 if (!RIGID_PARSER) { 5667 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: " 5668 + parser.getName() + " at " + mArchiveSourcePath + " " 5669 + parser.getPositionDescription()); 5670 } else { 5671 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types"; 5672 data = null; 5673 } 5674 } 5675 } else { 5676 outError[0] = "<meta-data> requires an android:value or android:resource attribute"; 5677 data = null; 5678 } 5679 } 5680 5681 sa.recycle(); 5682 5683 XmlUtils.skipCurrentTag(parser); 5684 5685 return data; 5686 } 5687 parseVerifier(AttributeSet attrs)5688 private static VerifierInfo parseVerifier(AttributeSet attrs) { 5689 String packageName = null; 5690 String encodedPublicKey = null; 5691 5692 final int attrCount = attrs.getAttributeCount(); 5693 for (int i = 0; i < attrCount; i++) { 5694 final int attrResId = attrs.getAttributeNameResource(i); 5695 switch (attrResId) { 5696 case com.android.internal.R.attr.name: 5697 packageName = attrs.getAttributeValue(i); 5698 break; 5699 5700 case com.android.internal.R.attr.publicKey: 5701 encodedPublicKey = attrs.getAttributeValue(i); 5702 break; 5703 } 5704 } 5705 5706 if (packageName == null || packageName.length() == 0) { 5707 Slog.i(TAG, "verifier package name was null; skipping"); 5708 return null; 5709 } 5710 5711 final PublicKey publicKey = parsePublicKey(encodedPublicKey); 5712 if (publicKey == null) { 5713 Slog.i(TAG, "Unable to parse verifier public key for " + packageName); 5714 return null; 5715 } 5716 5717 return new VerifierInfo(packageName, publicKey); 5718 } 5719 parsePublicKey(final String encodedPublicKey)5720 public static final PublicKey parsePublicKey(final String encodedPublicKey) { 5721 if (encodedPublicKey == null) { 5722 Slog.w(TAG, "Could not parse null public key"); 5723 return null; 5724 } 5725 5726 EncodedKeySpec keySpec; 5727 try { 5728 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT); 5729 keySpec = new X509EncodedKeySpec(encoded); 5730 } catch (IllegalArgumentException e) { 5731 Slog.w(TAG, "Could not parse verifier public key; invalid Base64"); 5732 return null; 5733 } 5734 5735 /* First try the key as an RSA key. */ 5736 try { 5737 final KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 5738 return keyFactory.generatePublic(keySpec); 5739 } catch (NoSuchAlgorithmException e) { 5740 Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build"); 5741 } catch (InvalidKeySpecException e) { 5742 // Not a RSA public key. 5743 } 5744 5745 /* Now try it as a ECDSA key. */ 5746 try { 5747 final KeyFactory keyFactory = KeyFactory.getInstance("EC"); 5748 return keyFactory.generatePublic(keySpec); 5749 } catch (NoSuchAlgorithmException e) { 5750 Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build"); 5751 } catch (InvalidKeySpecException e) { 5752 // Not a ECDSA public key. 5753 } 5754 5755 /* Now try it as a DSA key. */ 5756 try { 5757 final KeyFactory keyFactory = KeyFactory.getInstance("DSA"); 5758 return keyFactory.generatePublic(keySpec); 5759 } catch (NoSuchAlgorithmException e) { 5760 Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build"); 5761 } catch (InvalidKeySpecException e) { 5762 // Not a DSA public key. 5763 } 5764 5765 /* Not a supported key type */ 5766 return null; 5767 } 5768 5769 private static final String ANDROID_RESOURCES 5770 = "http://schemas.android.com/apk/res/android"; 5771 parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs, boolean allowAutoVerify, IntentInfo outInfo, String[] outError)5772 private boolean parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs, 5773 boolean allowAutoVerify, IntentInfo outInfo, String[] outError) 5774 throws XmlPullParserException, IOException { 5775 5776 TypedArray sa = res.obtainAttributes(parser, 5777 com.android.internal.R.styleable.AndroidManifestIntentFilter); 5778 5779 int priority = sa.getInt( 5780 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0); 5781 outInfo.setPriority(priority); 5782 5783 int order = sa.getInt( 5784 com.android.internal.R.styleable.AndroidManifestIntentFilter_order, 0); 5785 outInfo.setOrder(order); 5786 5787 TypedValue v = sa.peekValue( 5788 com.android.internal.R.styleable.AndroidManifestIntentFilter_label); 5789 if (v != null && (outInfo.labelRes=v.resourceId) == 0) { 5790 outInfo.nonLocalizedLabel = v.coerceToString(); 5791 } 5792 5793 int roundIconVal = sUseRoundIcon ? sa.getResourceId( 5794 com.android.internal.R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0; 5795 if (roundIconVal != 0) { 5796 outInfo.icon = roundIconVal; 5797 } else { 5798 outInfo.icon = sa.getResourceId( 5799 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0); 5800 } 5801 5802 outInfo.logo = sa.getResourceId( 5803 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0); 5804 5805 outInfo.banner = sa.getResourceId( 5806 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0); 5807 5808 if (allowAutoVerify) { 5809 outInfo.setAutoVerify(sa.getBoolean( 5810 com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify, 5811 false)); 5812 } 5813 5814 sa.recycle(); 5815 5816 int outerDepth = parser.getDepth(); 5817 int type; 5818 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 5819 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 5820 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 5821 continue; 5822 } 5823 5824 String nodeName = parser.getName(); 5825 if (nodeName.equals("action")) { 5826 String value = parser.getAttributeValue( 5827 ANDROID_RESOURCES, "name"); 5828 if (value == null || value == "") { 5829 outError[0] = "No value supplied for <android:name>"; 5830 return false; 5831 } 5832 XmlUtils.skipCurrentTag(parser); 5833 5834 outInfo.addAction(value); 5835 } else if (nodeName.equals("category")) { 5836 String value = parser.getAttributeValue( 5837 ANDROID_RESOURCES, "name"); 5838 if (value == null || value == "") { 5839 outError[0] = "No value supplied for <android:name>"; 5840 return false; 5841 } 5842 XmlUtils.skipCurrentTag(parser); 5843 5844 outInfo.addCategory(value); 5845 5846 } else if (nodeName.equals("data")) { 5847 sa = res.obtainAttributes(parser, 5848 com.android.internal.R.styleable.AndroidManifestData); 5849 5850 String str = sa.getNonConfigurationString( 5851 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0); 5852 if (str != null) { 5853 try { 5854 outInfo.addDataType(str); 5855 } catch (IntentFilter.MalformedMimeTypeException e) { 5856 outError[0] = e.toString(); 5857 sa.recycle(); 5858 return false; 5859 } 5860 } 5861 5862 str = sa.getNonConfigurationString( 5863 com.android.internal.R.styleable.AndroidManifestData_scheme, 0); 5864 if (str != null) { 5865 outInfo.addDataScheme(str); 5866 } 5867 5868 str = sa.getNonConfigurationString( 5869 com.android.internal.R.styleable.AndroidManifestData_ssp, 0); 5870 if (str != null) { 5871 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL); 5872 } 5873 5874 str = sa.getNonConfigurationString( 5875 com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0); 5876 if (str != null) { 5877 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX); 5878 } 5879 5880 str = sa.getNonConfigurationString( 5881 com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0); 5882 if (str != null) { 5883 if (!allowGlobs) { 5884 outError[0] = "sspPattern not allowed here; ssp must be literal"; 5885 return false; 5886 } 5887 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB); 5888 } 5889 5890 String host = sa.getNonConfigurationString( 5891 com.android.internal.R.styleable.AndroidManifestData_host, 0); 5892 String port = sa.getNonConfigurationString( 5893 com.android.internal.R.styleable.AndroidManifestData_port, 0); 5894 if (host != null) { 5895 outInfo.addDataAuthority(host, port); 5896 } 5897 5898 str = sa.getNonConfigurationString( 5899 com.android.internal.R.styleable.AndroidManifestData_path, 0); 5900 if (str != null) { 5901 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL); 5902 } 5903 5904 str = sa.getNonConfigurationString( 5905 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0); 5906 if (str != null) { 5907 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX); 5908 } 5909 5910 str = sa.getNonConfigurationString( 5911 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0); 5912 if (str != null) { 5913 if (!allowGlobs) { 5914 outError[0] = "pathPattern not allowed here; path must be literal"; 5915 return false; 5916 } 5917 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB); 5918 } 5919 5920 str = sa.getNonConfigurationString( 5921 com.android.internal.R.styleable.AndroidManifestData_pathAdvancedPattern, 0); 5922 if (str != null) { 5923 if (!allowGlobs) { 5924 outError[0] = "pathAdvancedPattern not allowed here; path must be literal"; 5925 return false; 5926 } 5927 outInfo.addDataPath(str, PatternMatcher.PATTERN_ADVANCED_GLOB); 5928 } 5929 5930 sa.recycle(); 5931 XmlUtils.skipCurrentTag(parser); 5932 } else if (!RIGID_PARSER) { 5933 Slog.w(TAG, "Unknown element under <intent-filter>: " 5934 + parser.getName() + " at " + mArchiveSourcePath + " " 5935 + parser.getPositionDescription()); 5936 XmlUtils.skipCurrentTag(parser); 5937 } else { 5938 outError[0] = "Bad element under <intent-filter>: " + parser.getName(); 5939 return false; 5940 } 5941 } 5942 5943 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT); 5944 5945 if (DEBUG_PARSER) { 5946 final StringBuilder cats = new StringBuilder("Intent d="); 5947 cats.append(outInfo.hasDefault); 5948 cats.append(", cat="); 5949 5950 final Iterator<String> it = outInfo.categoriesIterator(); 5951 if (it != null) { 5952 while (it.hasNext()) { 5953 cats.append(' '); 5954 cats.append(it.next()); 5955 } 5956 } 5957 Slog.d(TAG, cats.toString()); 5958 } 5959 5960 return true; 5961 } 5962 5963 /** 5964 * A container for signing-related data of an application package. 5965 * @hide 5966 */ 5967 public static final class SigningDetails implements Parcelable { 5968 5969 @IntDef({SigningDetails.SignatureSchemeVersion.UNKNOWN, 5970 SigningDetails.SignatureSchemeVersion.JAR, 5971 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2, 5972 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3}) 5973 public @interface SignatureSchemeVersion { 5974 int UNKNOWN = 0; 5975 int JAR = 1; 5976 int SIGNING_BLOCK_V2 = 2; 5977 int SIGNING_BLOCK_V3 = 3; 5978 } 5979 5980 @Nullable 5981 @UnsupportedAppUsage 5982 public final Signature[] signatures; 5983 @SignatureSchemeVersion 5984 public final int signatureSchemeVersion; 5985 @Nullable 5986 public final ArraySet<PublicKey> publicKeys; 5987 5988 /** 5989 * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that 5990 * contains two pieces of information: 5991 * 1) the past signing certificates 5992 * 2) the flags that APK wants to assign to each of the past signing certificates. 5993 * 5994 * This collection of {@code Signature} objects, each of which is formed from a former 5995 * signing certificate of this APK before it was changed by signing certificate rotation, 5996 * represents the first piece of information. It is the APK saying to the rest of the 5997 * world: "hey if you trust the old cert, you can trust me!" This is useful, if for 5998 * instance, the platform would like to determine whether or not to allow this APK to do 5999 * something it would've allowed it to do under the old cert (like upgrade). 6000 */ 6001 @Nullable 6002 public final Signature[] pastSigningCertificates; 6003 6004 /** special value used to see if cert is in package - not exposed to callers */ 6005 private static final int PAST_CERT_EXISTS = 0; 6006 6007 @IntDef( 6008 flag = true, 6009 value = {CertCapabilities.INSTALLED_DATA, 6010 CertCapabilities.SHARED_USER_ID, 6011 CertCapabilities.PERMISSION, 6012 CertCapabilities.ROLLBACK}) 6013 public @interface CertCapabilities { 6014 6015 /** accept data from already installed pkg with this cert */ 6016 int INSTALLED_DATA = 1; 6017 6018 /** accept sharedUserId with pkg with this cert */ 6019 int SHARED_USER_ID = 2; 6020 6021 /** grant SIGNATURE permissions to pkgs with this cert */ 6022 int PERMISSION = 4; 6023 6024 /** allow pkg to update to one signed by this certificate */ 6025 int ROLLBACK = 8; 6026 6027 /** allow pkg to continue to have auth access gated by this cert */ 6028 int AUTH = 16; 6029 } 6030 6031 /** A representation of unknown signing details. Use instead of null. */ 6032 public static final SigningDetails UNKNOWN = 6033 new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null, null); 6034 6035 @VisibleForTesting SigningDetails(Signature[] signatures, @SignatureSchemeVersion int signatureSchemeVersion, ArraySet<PublicKey> keys, Signature[] pastSigningCertificates)6036 public SigningDetails(Signature[] signatures, 6037 @SignatureSchemeVersion int signatureSchemeVersion, 6038 ArraySet<PublicKey> keys, Signature[] pastSigningCertificates) { 6039 this.signatures = signatures; 6040 this.signatureSchemeVersion = signatureSchemeVersion; 6041 this.publicKeys = keys; 6042 this.pastSigningCertificates = pastSigningCertificates; 6043 } 6044 SigningDetails(Signature[] signatures, @SignatureSchemeVersion int signatureSchemeVersion, Signature[] pastSigningCertificates)6045 public SigningDetails(Signature[] signatures, 6046 @SignatureSchemeVersion int signatureSchemeVersion, 6047 Signature[] pastSigningCertificates) 6048 throws CertificateException { 6049 this(signatures, signatureSchemeVersion, toSigningKeys(signatures), 6050 pastSigningCertificates); 6051 } 6052 SigningDetails(Signature[] signatures, @SignatureSchemeVersion int signatureSchemeVersion)6053 public SigningDetails(Signature[] signatures, 6054 @SignatureSchemeVersion int signatureSchemeVersion) 6055 throws CertificateException { 6056 this(signatures, signatureSchemeVersion, null); 6057 } 6058 SigningDetails(SigningDetails orig)6059 public SigningDetails(SigningDetails orig) { 6060 if (orig != null) { 6061 if (orig.signatures != null) { 6062 this.signatures = orig.signatures.clone(); 6063 } else { 6064 this.signatures = null; 6065 } 6066 this.signatureSchemeVersion = orig.signatureSchemeVersion; 6067 this.publicKeys = new ArraySet<>(orig.publicKeys); 6068 if (orig.pastSigningCertificates != null) { 6069 this.pastSigningCertificates = orig.pastSigningCertificates.clone(); 6070 } else { 6071 this.pastSigningCertificates = null; 6072 } 6073 } else { 6074 this.signatures = null; 6075 this.signatureSchemeVersion = SignatureSchemeVersion.UNKNOWN; 6076 this.publicKeys = null; 6077 this.pastSigningCertificates = null; 6078 } 6079 } 6080 6081 /** Returns true if the signing details have one or more signatures. */ hasSignatures()6082 public boolean hasSignatures() { 6083 return signatures != null && signatures.length > 0; 6084 } 6085 6086 /** Returns true if the signing details have past signing certificates. */ hasPastSigningCertificates()6087 public boolean hasPastSigningCertificates() { 6088 return pastSigningCertificates != null && pastSigningCertificates.length > 0; 6089 } 6090 6091 /** 6092 * Determines if the provided {@code oldDetails} is an ancestor of or the same as this one. 6093 * If the {@code oldDetails} signing certificate appears in our pastSigningCertificates, 6094 * then that means it has authorized a signing certificate rotation, which eventually leads 6095 * to our certificate, and thus can be trusted. If this method evaluates to true, this 6096 * SigningDetails object should be trusted if the previous one is. 6097 */ hasAncestorOrSelf(SigningDetails oldDetails)6098 public boolean hasAncestorOrSelf(SigningDetails oldDetails) { 6099 if (this == UNKNOWN || oldDetails == UNKNOWN) { 6100 return false; 6101 } 6102 if (oldDetails.signatures.length > 1) { 6103 6104 // multiple-signer packages cannot rotate signing certs, so we just compare current 6105 // signers for an exact match 6106 return signaturesMatchExactly(oldDetails); 6107 } else { 6108 6109 // we may have signing certificate rotation history, check to see if the oldDetails 6110 // was one of our old signing certificates 6111 return hasCertificate(oldDetails.signatures[0]); 6112 } 6113 } 6114 6115 /** 6116 * Similar to {@code hasAncestorOrSelf}. Returns true only if this {@code SigningDetails} 6117 * is a descendant of {@code oldDetails}, not if they're the same. This is used to 6118 * determine if this object is newer than the provided one. 6119 */ hasAncestor(SigningDetails oldDetails)6120 public boolean hasAncestor(SigningDetails oldDetails) { 6121 if (this == UNKNOWN || oldDetails == UNKNOWN) { 6122 return false; 6123 } 6124 if (this.hasPastSigningCertificates() && oldDetails.signatures.length == 1) { 6125 6126 // the last entry in pastSigningCertificates is the current signer, ignore it 6127 for (int i = 0; i < pastSigningCertificates.length - 1; i++) { 6128 if (pastSigningCertificates[i].equals(oldDetails.signatures[i])) { 6129 return true; 6130 } 6131 } 6132 } 6133 return false; 6134 } 6135 6136 /** 6137 * Determines if the provided {@code oldDetails} is an ancestor of this one, and whether or 6138 * not this one grants it the provided capability, represented by the {@code flags} 6139 * parameter. In the event of signing certificate rotation, a package may still interact 6140 * with entities signed by its old signing certificate and not want to break previously 6141 * functioning behavior. The {@code flags} value determines which capabilities the app 6142 * signed by the newer signing certificate would like to continue to give to its previous 6143 * signing certificate(s). 6144 */ checkCapability(SigningDetails oldDetails, @CertCapabilities int flags)6145 public boolean checkCapability(SigningDetails oldDetails, @CertCapabilities int flags) { 6146 if (this == UNKNOWN || oldDetails == UNKNOWN) { 6147 return false; 6148 } 6149 if (oldDetails.signatures.length > 1) { 6150 6151 // multiple-signer packages cannot rotate signing certs, so we must have an exact 6152 // match, which also means all capabilities are granted 6153 return signaturesMatchExactly(oldDetails); 6154 } else { 6155 6156 // we may have signing certificate rotation history, check to see if the oldDetails 6157 // was one of our old signing certificates, and if we grant it the capability it's 6158 // requesting 6159 return hasCertificate(oldDetails.signatures[0], flags); 6160 } 6161 } 6162 6163 /** 6164 * A special case of {@code checkCapability} which re-encodes both sets of signing 6165 * certificates to counteract a previous re-encoding. 6166 */ checkCapabilityRecover(SigningDetails oldDetails, @CertCapabilities int flags)6167 public boolean checkCapabilityRecover(SigningDetails oldDetails, 6168 @CertCapabilities int flags) throws CertificateException { 6169 if (oldDetails == UNKNOWN || this == UNKNOWN) { 6170 return false; 6171 } 6172 if (hasPastSigningCertificates() && oldDetails.signatures.length == 1) { 6173 6174 // signing certificates may have rotated, check entire history for effective match 6175 for (int i = 0; i < pastSigningCertificates.length; i++) { 6176 if (Signature.areEffectiveMatch( 6177 oldDetails.signatures[0], 6178 pastSigningCertificates[i]) 6179 && pastSigningCertificates[i].getFlags() == flags) { 6180 return true; 6181 } 6182 } 6183 } else { 6184 return Signature.areEffectiveMatch(oldDetails.signatures, signatures); 6185 } 6186 return false; 6187 } 6188 6189 /** 6190 * Determine if {@code signature} is in this SigningDetails' signing certificate history, 6191 * including the current signer. Automatically returns false if this object has multiple 6192 * signing certificates, since rotation is only supported for single-signers; this is 6193 * enforced by {@code hasCertificateInternal}. 6194 */ hasCertificate(Signature signature)6195 public boolean hasCertificate(Signature signature) { 6196 return hasCertificateInternal(signature, PAST_CERT_EXISTS); 6197 } 6198 6199 /** 6200 * Determine if {@code signature} is in this SigningDetails' signing certificate history, 6201 * including the current signer, and whether or not it has the given permission. 6202 * Certificates which match our current signer automatically get all capabilities. 6203 * Automatically returns false if this object has multiple signing certificates, since 6204 * rotation is only supported for single-signers. 6205 */ hasCertificate(Signature signature, @CertCapabilities int flags)6206 public boolean hasCertificate(Signature signature, @CertCapabilities int flags) { 6207 return hasCertificateInternal(signature, flags); 6208 } 6209 6210 /** Convenient wrapper for calling {@code hasCertificate} with certificate's raw bytes. */ hasCertificate(byte[] certificate)6211 public boolean hasCertificate(byte[] certificate) { 6212 Signature signature = new Signature(certificate); 6213 return hasCertificate(signature); 6214 } 6215 hasCertificateInternal(Signature signature, int flags)6216 private boolean hasCertificateInternal(Signature signature, int flags) { 6217 if (this == UNKNOWN) { 6218 return false; 6219 } 6220 6221 // only single-signed apps can have pastSigningCertificates 6222 if (hasPastSigningCertificates()) { 6223 6224 // check all past certs, except for the current one, which automatically gets all 6225 // capabilities, since it is the same as the current signature 6226 for (int i = 0; i < pastSigningCertificates.length - 1; i++) { 6227 if (pastSigningCertificates[i].equals(signature)) { 6228 if (flags == PAST_CERT_EXISTS 6229 || (flags & pastSigningCertificates[i].getFlags()) == flags) { 6230 return true; 6231 } 6232 } 6233 } 6234 } 6235 6236 // not in previous certs signing history, just check the current signer and make sure 6237 // we are singly-signed 6238 return signatures.length == 1 && signatures[0].equals(signature); 6239 } 6240 6241 /** 6242 * Determines if the provided {@code sha256String} is an ancestor of this one, and whether 6243 * or not this one grants it the provided capability, represented by the {@code flags} 6244 * parameter. In the event of signing certificate rotation, a package may still interact 6245 * with entities signed by its old signing certificate and not want to break previously 6246 * functioning behavior. The {@code flags} value determines which capabilities the app 6247 * signed by the newer signing certificate would like to continue to give to its previous 6248 * signing certificate(s). 6249 * 6250 * @param sha256String A hex-encoded representation of a sha256 digest. In the case of an 6251 * app with multiple signers, this represents the hex-encoded sha256 6252 * digest of the combined hex-encoded sha256 digests of each individual 6253 * signing certificate according to {@link 6254 * PackageUtils#computeSignaturesSha256Digest(Signature[])} 6255 */ checkCapability(String sha256String, @CertCapabilities int flags)6256 public boolean checkCapability(String sha256String, @CertCapabilities int flags) { 6257 if (this == UNKNOWN) { 6258 return false; 6259 } 6260 6261 // first see if the hash represents a single-signer in our signing history 6262 byte[] sha256Bytes = sha256String == null 6263 ? null : HexEncoding.decode(sha256String, false /* allowSingleChar */); 6264 if (hasSha256Certificate(sha256Bytes, flags)) { 6265 return true; 6266 } 6267 6268 // Not in signing history, either represents multiple signatures or not a match. 6269 // Multiple signers can't rotate, so no need to check flags, just see if the SHAs match. 6270 // We already check the single-signer case above as part of hasSha256Certificate, so no 6271 // need to verify we have multiple signers, just run the old check 6272 // just consider current signing certs 6273 final String[] mSignaturesSha256Digests = 6274 PackageUtils.computeSignaturesSha256Digests(signatures); 6275 final String mSignaturesSha256Digest = 6276 PackageUtils.computeSignaturesSha256Digest(mSignaturesSha256Digests); 6277 return mSignaturesSha256Digest.equals(sha256String); 6278 } 6279 6280 /** 6281 * Determine if the {@code sha256Certificate} is in this SigningDetails' signing certificate 6282 * history, including the current signer. Automatically returns false if this object has 6283 * multiple signing certificates, since rotation is only supported for single-signers. 6284 */ hasSha256Certificate(byte[] sha256Certificate)6285 public boolean hasSha256Certificate(byte[] sha256Certificate) { 6286 return hasSha256CertificateInternal(sha256Certificate, PAST_CERT_EXISTS); 6287 } 6288 6289 /** 6290 * Determine if the {@code sha256Certificate} certificate hash corresponds to a signing 6291 * certificate in this SigningDetails' signing certificate history, including the current 6292 * signer, and whether or not it has the given permission. Certificates which match our 6293 * current signer automatically get all capabilities. Automatically returns false if this 6294 * object has multiple signing certificates, since rotation is only supported for 6295 * single-signers. 6296 */ hasSha256Certificate(byte[] sha256Certificate, @CertCapabilities int flags)6297 public boolean hasSha256Certificate(byte[] sha256Certificate, @CertCapabilities int flags) { 6298 return hasSha256CertificateInternal(sha256Certificate, flags); 6299 } 6300 hasSha256CertificateInternal(byte[] sha256Certificate, int flags)6301 private boolean hasSha256CertificateInternal(byte[] sha256Certificate, int flags) { 6302 if (this == UNKNOWN) { 6303 return false; 6304 } 6305 if (hasPastSigningCertificates()) { 6306 6307 // check all past certs, except for the last one, which automatically gets all 6308 // capabilities, since it is the same as the current signature, and is checked below 6309 for (int i = 0; i < pastSigningCertificates.length - 1; i++) { 6310 byte[] digest = PackageUtils.computeSha256DigestBytes( 6311 pastSigningCertificates[i].toByteArray()); 6312 if (Arrays.equals(sha256Certificate, digest)) { 6313 if (flags == PAST_CERT_EXISTS 6314 || (flags & pastSigningCertificates[i].getFlags()) == flags) { 6315 return true; 6316 } 6317 } 6318 } 6319 } 6320 6321 // not in previous certs signing history, just check the current signer 6322 if (signatures.length == 1) { 6323 byte[] digest = 6324 PackageUtils.computeSha256DigestBytes(signatures[0].toByteArray()); 6325 return Arrays.equals(sha256Certificate, digest); 6326 } 6327 return false; 6328 } 6329 6330 /** Returns true if the signatures in this and other match exactly. */ signaturesMatchExactly(SigningDetails other)6331 public boolean signaturesMatchExactly(SigningDetails other) { 6332 return Signature.areExactMatch(this.signatures, other.signatures); 6333 } 6334 6335 @Override describeContents()6336 public int describeContents() { 6337 return 0; 6338 } 6339 6340 @Override writeToParcel(Parcel dest, int flags)6341 public void writeToParcel(Parcel dest, int flags) { 6342 boolean isUnknown = UNKNOWN == this; 6343 dest.writeBoolean(isUnknown); 6344 if (isUnknown) { 6345 return; 6346 } 6347 dest.writeTypedArray(this.signatures, flags); 6348 dest.writeInt(this.signatureSchemeVersion); 6349 dest.writeArraySet(this.publicKeys); 6350 dest.writeTypedArray(this.pastSigningCertificates, flags); 6351 } 6352 SigningDetails(Parcel in)6353 protected SigningDetails(Parcel in) { 6354 final ClassLoader boot = Object.class.getClassLoader(); 6355 this.signatures = in.createTypedArray(Signature.CREATOR); 6356 this.signatureSchemeVersion = in.readInt(); 6357 this.publicKeys = (ArraySet<PublicKey>) in.readArraySet(boot); 6358 this.pastSigningCertificates = in.createTypedArray(Signature.CREATOR); 6359 } 6360 6361 public static final @android.annotation.NonNull Creator<SigningDetails> CREATOR = new Creator<SigningDetails>() { 6362 @Override 6363 public SigningDetails createFromParcel(Parcel source) { 6364 if (source.readBoolean()) { 6365 return UNKNOWN; 6366 } 6367 return new SigningDetails(source); 6368 } 6369 6370 @Override 6371 public SigningDetails[] newArray(int size) { 6372 return new SigningDetails[size]; 6373 } 6374 }; 6375 6376 @Override equals(Object o)6377 public boolean equals(Object o) { 6378 if (this == o) return true; 6379 if (!(o instanceof SigningDetails)) return false; 6380 6381 SigningDetails that = (SigningDetails) o; 6382 6383 if (signatureSchemeVersion != that.signatureSchemeVersion) return false; 6384 if (!Signature.areExactMatch(signatures, that.signatures)) return false; 6385 if (publicKeys != null) { 6386 if (!publicKeys.equals((that.publicKeys))) { 6387 return false; 6388 } 6389 } else if (that.publicKeys != null) { 6390 return false; 6391 } 6392 6393 // can't use Signature.areExactMatch() because order matters with the past signing certs 6394 if (!Arrays.equals(pastSigningCertificates, that.pastSigningCertificates)) { 6395 return false; 6396 } 6397 6398 return true; 6399 } 6400 6401 @Override hashCode()6402 public int hashCode() { 6403 int result = +Arrays.hashCode(signatures); 6404 result = 31 * result + signatureSchemeVersion; 6405 result = 31 * result + (publicKeys != null ? publicKeys.hashCode() : 0); 6406 result = 31 * result + Arrays.hashCode(pastSigningCertificates); 6407 return result; 6408 } 6409 6410 /** 6411 * Builder of {@code SigningDetails} instances. 6412 */ 6413 public static class Builder { 6414 private Signature[] mSignatures; 6415 private int mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN; 6416 private Signature[] mPastSigningCertificates; 6417 6418 @UnsupportedAppUsage Builder()6419 public Builder() { 6420 } 6421 6422 /** get signing certificates used to sign the current APK */ 6423 @UnsupportedAppUsage setSignatures(Signature[] signatures)6424 public Builder setSignatures(Signature[] signatures) { 6425 mSignatures = signatures; 6426 return this; 6427 } 6428 6429 /** set the signature scheme version used to sign the APK */ 6430 @UnsupportedAppUsage setSignatureSchemeVersion(int signatureSchemeVersion)6431 public Builder setSignatureSchemeVersion(int signatureSchemeVersion) { 6432 mSignatureSchemeVersion = signatureSchemeVersion; 6433 return this; 6434 } 6435 6436 /** set the signing certificates by which the APK proved it can be authenticated */ 6437 @UnsupportedAppUsage setPastSigningCertificates(Signature[] pastSigningCertificates)6438 public Builder setPastSigningCertificates(Signature[] pastSigningCertificates) { 6439 mPastSigningCertificates = pastSigningCertificates; 6440 return this; 6441 } 6442 checkInvariants()6443 private void checkInvariants() { 6444 // must have signatures and scheme version set 6445 if (mSignatures == null) { 6446 throw new IllegalStateException("SigningDetails requires the current signing" 6447 + " certificates."); 6448 } 6449 } 6450 /** build a {@code SigningDetails} object */ 6451 @UnsupportedAppUsage build()6452 public SigningDetails build() 6453 throws CertificateException { 6454 checkInvariants(); 6455 return new SigningDetails(mSignatures, mSignatureSchemeVersion, 6456 mPastSigningCertificates); 6457 } 6458 } 6459 } 6460 6461 /** 6462 * Representation of a full package parsed from APK files on disk. A package 6463 * consists of a single base APK, and zero or more split APKs. 6464 */ 6465 public final static class Package implements Parcelable { 6466 6467 @UnsupportedAppUsage 6468 public String packageName; 6469 6470 // The package name declared in the manifest as the package can be 6471 // renamed, for example static shared libs use synthetic package names. 6472 public String manifestPackageName; 6473 6474 /** Names of any split APKs, ordered by parsed splitName */ 6475 public String[] splitNames; 6476 6477 // TODO: work towards making these paths invariant 6478 6479 public String volumeUuid; 6480 6481 /** 6482 * Path where this package was found on disk. For monolithic packages 6483 * this is path to single base APK file; for cluster packages this is 6484 * path to the cluster directory. 6485 */ 6486 public String codePath; 6487 6488 /** Path of base APK */ 6489 public String baseCodePath; 6490 /** Paths of any split APKs, ordered by parsed splitName */ 6491 public String[] splitCodePaths; 6492 6493 /** Revision code of base APK */ 6494 public int baseRevisionCode; 6495 /** Revision codes of any split APKs, ordered by parsed splitName */ 6496 public int[] splitRevisionCodes; 6497 6498 /** Flags of any split APKs; ordered by parsed splitName */ 6499 public int[] splitFlags; 6500 6501 /** 6502 * Private flags of any split APKs; ordered by parsed splitName. 6503 * 6504 * {@hide} 6505 */ 6506 public int[] splitPrivateFlags; 6507 6508 public boolean baseHardwareAccelerated; 6509 6510 // For now we only support one application per package. 6511 @UnsupportedAppUsage 6512 public ApplicationInfo applicationInfo = new ApplicationInfo(); 6513 6514 @UnsupportedAppUsage 6515 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0); 6516 @UnsupportedAppUsage 6517 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0); 6518 @UnsupportedAppUsage 6519 public final ArrayList<Activity> activities = new ArrayList<Activity>(0); 6520 @UnsupportedAppUsage 6521 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0); 6522 @UnsupportedAppUsage 6523 public final ArrayList<Provider> providers = new ArrayList<Provider>(0); 6524 @UnsupportedAppUsage 6525 public final ArrayList<Service> services = new ArrayList<Service>(0); 6526 @UnsupportedAppUsage 6527 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0); 6528 6529 @UnsupportedAppUsage 6530 public final ArrayList<String> requestedPermissions = new ArrayList<String>(); 6531 6532 /** Permissions requested but not in the manifest. */ 6533 public final ArrayList<String> implicitPermissions = new ArrayList<>(); 6534 6535 @UnsupportedAppUsage 6536 public ArrayList<String> protectedBroadcasts; 6537 6538 public Package parentPackage; 6539 public ArrayList<Package> childPackages; 6540 6541 public String staticSharedLibName = null; 6542 public long staticSharedLibVersion = 0; 6543 public ArrayList<String> libraryNames = null; 6544 @UnsupportedAppUsage 6545 public ArrayList<String> usesLibraries = null; 6546 public ArrayList<String> usesStaticLibraries = null; 6547 public long[] usesStaticLibrariesVersions = null; 6548 public String[][] usesStaticLibrariesCertDigests = null; 6549 @UnsupportedAppUsage 6550 public ArrayList<String> usesOptionalLibraries = null; 6551 @UnsupportedAppUsage 6552 public String[] usesLibraryFiles = null; 6553 public ArrayList<SharedLibraryInfo> usesLibraryInfos = null; 6554 6555 public ArrayList<ActivityIntentInfo> preferredActivityFilters = null; 6556 6557 public ArrayList<String> mOriginalPackages = null; 6558 public String mRealPackage = null; 6559 public ArrayList<String> mAdoptPermissions = null; 6560 6561 // We store the application meta-data independently to avoid multiple unwanted references 6562 @UnsupportedAppUsage 6563 public Bundle mAppMetaData = null; 6564 6565 // The version code declared for this package. 6566 @UnsupportedAppUsage 6567 public int mVersionCode; 6568 6569 // The major version code declared for this package. 6570 public int mVersionCodeMajor; 6571 6572 // Return long containing mVersionCode and mVersionCodeMajor. getLongVersionCode()6573 public long getLongVersionCode() { 6574 return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode); 6575 } 6576 6577 // The version name declared for this package. 6578 @UnsupportedAppUsage 6579 public String mVersionName; 6580 6581 // The shared user id that this package wants to use. 6582 @UnsupportedAppUsage 6583 public String mSharedUserId; 6584 6585 // The shared user label that this package wants to use. 6586 @UnsupportedAppUsage 6587 public int mSharedUserLabel; 6588 6589 // Signatures that were read from the package. 6590 @UnsupportedAppUsage 6591 @NonNull public SigningDetails mSigningDetails = SigningDetails.UNKNOWN; 6592 6593 // For use by package manager service for quick lookup of 6594 // preferred up order. 6595 @UnsupportedAppUsage 6596 public int mPreferredOrder = 0; 6597 6598 // For use by package manager to keep track of when a package was last used. 6599 public long[] mLastPackageUsageTimeInMills = 6600 new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT]; 6601 6602 // // User set enabled state. 6603 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 6604 // 6605 // // Whether the package has been stopped. 6606 // public boolean mSetStopped = false; 6607 6608 // Additional data supplied by callers. 6609 @UnsupportedAppUsage 6610 public Object mExtras; 6611 6612 // Applications hardware preferences 6613 @UnsupportedAppUsage 6614 public ArrayList<ConfigurationInfo> configPreferences = null; 6615 6616 // Applications requested features 6617 @UnsupportedAppUsage 6618 public ArrayList<FeatureInfo> reqFeatures = null; 6619 6620 // Applications requested feature groups 6621 public ArrayList<FeatureGroupInfo> featureGroups = null; 6622 6623 @UnsupportedAppUsage 6624 public int installLocation; 6625 6626 public boolean coreApp; 6627 6628 /* An app that's required for all users and cannot be uninstalled for a user */ 6629 public boolean mRequiredForAllUsers; 6630 6631 /* The restricted account authenticator type that is used by this application */ 6632 public String mRestrictedAccountType; 6633 6634 /* The required account type without which this application will not function */ 6635 public String mRequiredAccountType; 6636 6637 public String mOverlayTarget; 6638 public String mOverlayTargetName; 6639 public String mOverlayCategory; 6640 public int mOverlayPriority; 6641 public boolean mOverlayIsStatic; 6642 6643 public int mCompileSdkVersion; 6644 public String mCompileSdkVersionCodename; 6645 6646 /** 6647 * Data used to feed the KeySetManagerService 6648 */ 6649 @UnsupportedAppUsage 6650 public ArraySet<String> mUpgradeKeySets; 6651 @UnsupportedAppUsage 6652 public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping; 6653 6654 /** 6655 * The install time abi override for this package, if any. 6656 * 6657 * TODO: This seems like a horrible place to put the abiOverride because 6658 * this isn't something the packageParser parsers. However, this fits in with 6659 * the rest of the PackageManager where package scanning randomly pushes 6660 * and prods fields out of {@code this.applicationInfo}. 6661 */ 6662 public String cpuAbiOverride; 6663 /** 6664 * The install time abi override to choose 32bit abi's when multiple abi's 6665 * are present. This is only meaningfull for multiarch applications. 6666 * The use32bitAbi attribute is ignored if cpuAbiOverride is also set. 6667 */ 6668 public boolean use32bitAbi; 6669 6670 public byte[] restrictUpdateHash; 6671 6672 /** Set if the app or any of its components are visible to instant applications. */ 6673 public boolean visibleToInstantApps; 6674 /** Whether or not the package is a stub and must be replaced by the full version. */ 6675 public boolean isStub; 6676 6677 @UnsupportedAppUsage Package(String packageName)6678 public Package(String packageName) { 6679 this.packageName = packageName; 6680 this.manifestPackageName = packageName; 6681 applicationInfo.packageName = packageName; 6682 applicationInfo.uid = -1; 6683 } 6684 setApplicationVolumeUuid(String volumeUuid)6685 public void setApplicationVolumeUuid(String volumeUuid) { 6686 final UUID storageUuid = StorageManager.convert(volumeUuid); 6687 this.applicationInfo.volumeUuid = volumeUuid; 6688 this.applicationInfo.storageUuid = storageUuid; 6689 if (childPackages != null) { 6690 final int packageCount = childPackages.size(); 6691 for (int i = 0; i < packageCount; i++) { 6692 childPackages.get(i).applicationInfo.volumeUuid = volumeUuid; 6693 childPackages.get(i).applicationInfo.storageUuid = storageUuid; 6694 } 6695 } 6696 } 6697 setApplicationInfoCodePath(String codePath)6698 public void setApplicationInfoCodePath(String codePath) { 6699 this.applicationInfo.setCodePath(codePath); 6700 if (childPackages != null) { 6701 final int packageCount = childPackages.size(); 6702 for (int i = 0; i < packageCount; i++) { 6703 childPackages.get(i).applicationInfo.setCodePath(codePath); 6704 } 6705 } 6706 } 6707 6708 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */ 6709 @Deprecated setApplicationInfoResourcePath(String resourcePath)6710 public void setApplicationInfoResourcePath(String resourcePath) { 6711 this.applicationInfo.setResourcePath(resourcePath); 6712 if (childPackages != null) { 6713 final int packageCount = childPackages.size(); 6714 for (int i = 0; i < packageCount; i++) { 6715 childPackages.get(i).applicationInfo.setResourcePath(resourcePath); 6716 } 6717 } 6718 } 6719 6720 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */ 6721 @Deprecated setApplicationInfoBaseResourcePath(String resourcePath)6722 public void setApplicationInfoBaseResourcePath(String resourcePath) { 6723 this.applicationInfo.setBaseResourcePath(resourcePath); 6724 if (childPackages != null) { 6725 final int packageCount = childPackages.size(); 6726 for (int i = 0; i < packageCount; i++) { 6727 childPackages.get(i).applicationInfo.setBaseResourcePath(resourcePath); 6728 } 6729 } 6730 } 6731 setApplicationInfoBaseCodePath(String baseCodePath)6732 public void setApplicationInfoBaseCodePath(String baseCodePath) { 6733 this.applicationInfo.setBaseCodePath(baseCodePath); 6734 if (childPackages != null) { 6735 final int packageCount = childPackages.size(); 6736 for (int i = 0; i < packageCount; i++) { 6737 childPackages.get(i).applicationInfo.setBaseCodePath(baseCodePath); 6738 } 6739 } 6740 } 6741 getChildPackageNames()6742 public List<String> getChildPackageNames() { 6743 if (childPackages == null) { 6744 return null; 6745 } 6746 final int childCount = childPackages.size(); 6747 final List<String> childPackageNames = new ArrayList<>(childCount); 6748 for (int i = 0; i < childCount; i++) { 6749 String childPackageName = childPackages.get(i).packageName; 6750 childPackageNames.add(childPackageName); 6751 } 6752 return childPackageNames; 6753 } 6754 hasChildPackage(String packageName)6755 public boolean hasChildPackage(String packageName) { 6756 final int childCount = (childPackages != null) ? childPackages.size() : 0; 6757 for (int i = 0; i < childCount; i++) { 6758 if (childPackages.get(i).packageName.equals(packageName)) { 6759 return true; 6760 } 6761 } 6762 return false; 6763 } 6764 setApplicationInfoSplitCodePaths(String[] splitCodePaths)6765 public void setApplicationInfoSplitCodePaths(String[] splitCodePaths) { 6766 this.applicationInfo.setSplitCodePaths(splitCodePaths); 6767 // Children have no splits 6768 } 6769 6770 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */ 6771 @Deprecated setApplicationInfoSplitResourcePaths(String[] resroucePaths)6772 public void setApplicationInfoSplitResourcePaths(String[] resroucePaths) { 6773 this.applicationInfo.setSplitResourcePaths(resroucePaths); 6774 // Children have no splits 6775 } 6776 setSplitCodePaths(String[] codePaths)6777 public void setSplitCodePaths(String[] codePaths) { 6778 this.splitCodePaths = codePaths; 6779 } 6780 setCodePath(String codePath)6781 public void setCodePath(String codePath) { 6782 this.codePath = codePath; 6783 if (childPackages != null) { 6784 final int packageCount = childPackages.size(); 6785 for (int i = 0; i < packageCount; i++) { 6786 childPackages.get(i).codePath = codePath; 6787 } 6788 } 6789 } 6790 setBaseCodePath(String baseCodePath)6791 public void setBaseCodePath(String baseCodePath) { 6792 this.baseCodePath = baseCodePath; 6793 if (childPackages != null) { 6794 final int packageCount = childPackages.size(); 6795 for (int i = 0; i < packageCount; i++) { 6796 childPackages.get(i).baseCodePath = baseCodePath; 6797 } 6798 } 6799 } 6800 6801 /** Sets signing details on the package and any of its children. */ setSigningDetails(@onNull SigningDetails signingDetails)6802 public void setSigningDetails(@NonNull SigningDetails signingDetails) { 6803 mSigningDetails = signingDetails; 6804 if (childPackages != null) { 6805 final int packageCount = childPackages.size(); 6806 for (int i = 0; i < packageCount; i++) { 6807 childPackages.get(i).mSigningDetails = signingDetails; 6808 } 6809 } 6810 } 6811 setVolumeUuid(String volumeUuid)6812 public void setVolumeUuid(String volumeUuid) { 6813 this.volumeUuid = volumeUuid; 6814 if (childPackages != null) { 6815 final int packageCount = childPackages.size(); 6816 for (int i = 0; i < packageCount; i++) { 6817 childPackages.get(i).volumeUuid = volumeUuid; 6818 } 6819 } 6820 } 6821 setApplicationInfoFlags(int mask, int flags)6822 public void setApplicationInfoFlags(int mask, int flags) { 6823 applicationInfo.flags = (applicationInfo.flags & ~mask) | (mask & flags); 6824 if (childPackages != null) { 6825 final int packageCount = childPackages.size(); 6826 for (int i = 0; i < packageCount; i++) { 6827 childPackages.get(i).applicationInfo.flags = 6828 (applicationInfo.flags & ~mask) | (mask & flags); 6829 } 6830 } 6831 } 6832 setUse32bitAbi(boolean use32bitAbi)6833 public void setUse32bitAbi(boolean use32bitAbi) { 6834 this.use32bitAbi = use32bitAbi; 6835 if (childPackages != null) { 6836 final int packageCount = childPackages.size(); 6837 for (int i = 0; i < packageCount; i++) { 6838 childPackages.get(i).use32bitAbi = use32bitAbi; 6839 } 6840 } 6841 } 6842 isLibrary()6843 public boolean isLibrary() { 6844 return staticSharedLibName != null || !ArrayUtils.isEmpty(libraryNames); 6845 } 6846 getAllCodePaths()6847 public List<String> getAllCodePaths() { 6848 ArrayList<String> paths = new ArrayList<>(); 6849 paths.add(baseCodePath); 6850 if (!ArrayUtils.isEmpty(splitCodePaths)) { 6851 Collections.addAll(paths, splitCodePaths); 6852 } 6853 return paths; 6854 } 6855 6856 /** 6857 * Filtered set of {@link #getAllCodePaths()} that excludes 6858 * resource-only APKs. 6859 */ getAllCodePathsExcludingResourceOnly()6860 public List<String> getAllCodePathsExcludingResourceOnly() { 6861 ArrayList<String> paths = new ArrayList<>(); 6862 if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) { 6863 paths.add(baseCodePath); 6864 } 6865 if (!ArrayUtils.isEmpty(splitCodePaths)) { 6866 for (int i = 0; i < splitCodePaths.length; i++) { 6867 if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) { 6868 paths.add(splitCodePaths[i]); 6869 } 6870 } 6871 } 6872 return paths; 6873 } 6874 6875 @UnsupportedAppUsage setPackageName(String newName)6876 public void setPackageName(String newName) { 6877 packageName = newName; 6878 applicationInfo.packageName = newName; 6879 for (int i=permissions.size()-1; i>=0; i--) { 6880 permissions.get(i).setPackageName(newName); 6881 } 6882 for (int i=permissionGroups.size()-1; i>=0; i--) { 6883 permissionGroups.get(i).setPackageName(newName); 6884 } 6885 for (int i=activities.size()-1; i>=0; i--) { 6886 activities.get(i).setPackageName(newName); 6887 } 6888 for (int i=receivers.size()-1; i>=0; i--) { 6889 receivers.get(i).setPackageName(newName); 6890 } 6891 for (int i=providers.size()-1; i>=0; i--) { 6892 providers.get(i).setPackageName(newName); 6893 } 6894 for (int i=services.size()-1; i>=0; i--) { 6895 services.get(i).setPackageName(newName); 6896 } 6897 for (int i=instrumentation.size()-1; i>=0; i--) { 6898 instrumentation.get(i).setPackageName(newName); 6899 } 6900 } 6901 hasComponentClassName(String name)6902 public boolean hasComponentClassName(String name) { 6903 for (int i=activities.size()-1; i>=0; i--) { 6904 if (name.equals(activities.get(i).className)) { 6905 return true; 6906 } 6907 } 6908 for (int i=receivers.size()-1; i>=0; i--) { 6909 if (name.equals(receivers.get(i).className)) { 6910 return true; 6911 } 6912 } 6913 for (int i=providers.size()-1; i>=0; i--) { 6914 if (name.equals(providers.get(i).className)) { 6915 return true; 6916 } 6917 } 6918 for (int i=services.size()-1; i>=0; i--) { 6919 if (name.equals(services.get(i).className)) { 6920 return true; 6921 } 6922 } 6923 for (int i=instrumentation.size()-1; i>=0; i--) { 6924 if (name.equals(instrumentation.get(i).className)) { 6925 return true; 6926 } 6927 } 6928 return false; 6929 } 6930 6931 /** @hide */ isExternal()6932 public boolean isExternal() { 6933 return applicationInfo.isExternal(); 6934 } 6935 6936 /** @hide */ isForwardLocked()6937 public boolean isForwardLocked() { 6938 return false; 6939 } 6940 6941 /** @hide */ isOem()6942 public boolean isOem() { 6943 return applicationInfo.isOem(); 6944 } 6945 6946 /** @hide */ isVendor()6947 public boolean isVendor() { 6948 return applicationInfo.isVendor(); 6949 } 6950 6951 /** @hide */ isProduct()6952 public boolean isProduct() { 6953 return applicationInfo.isProduct(); 6954 } 6955 6956 /** @hide */ isSystemExt()6957 public boolean isSystemExt() { 6958 return applicationInfo.isSystemExt(); 6959 } 6960 6961 /** @hide */ isOdm()6962 public boolean isOdm() { 6963 return applicationInfo.isOdm(); 6964 } 6965 6966 /** @hide */ isPrivileged()6967 public boolean isPrivileged() { 6968 return applicationInfo.isPrivilegedApp(); 6969 } 6970 6971 /** @hide */ isSystem()6972 public boolean isSystem() { 6973 return applicationInfo.isSystemApp(); 6974 } 6975 6976 /** @hide */ isUpdatedSystemApp()6977 public boolean isUpdatedSystemApp() { 6978 return applicationInfo.isUpdatedSystemApp(); 6979 } 6980 6981 /** @hide */ canHaveOatDir()6982 public boolean canHaveOatDir() { 6983 // The following app types CANNOT have oat directory 6984 // - non-updated system apps 6985 return !isSystem() || isUpdatedSystemApp(); 6986 } 6987 isMatch(int flags)6988 public boolean isMatch(int flags) { 6989 if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) { 6990 return isSystem(); 6991 } 6992 return true; 6993 } 6994 getLatestPackageUseTimeInMills()6995 public long getLatestPackageUseTimeInMills() { 6996 long latestUse = 0L; 6997 for (long use : mLastPackageUsageTimeInMills) { 6998 latestUse = Math.max(latestUse, use); 6999 } 7000 return latestUse; 7001 } 7002 getLatestForegroundPackageUseTimeInMills()7003 public long getLatestForegroundPackageUseTimeInMills() { 7004 int[] foregroundReasons = { 7005 PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY, 7006 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE 7007 }; 7008 7009 long latestUse = 0L; 7010 for (int reason : foregroundReasons) { 7011 latestUse = Math.max(latestUse, mLastPackageUsageTimeInMills[reason]); 7012 } 7013 return latestUse; 7014 } 7015 toString()7016 public String toString() { 7017 return "Package{" 7018 + Integer.toHexString(System.identityHashCode(this)) 7019 + " " + packageName + "}"; 7020 } 7021 7022 @Override describeContents()7023 public int describeContents() { 7024 return 0; 7025 } 7026 Package(Parcel dest)7027 public Package(Parcel dest) { 7028 // We use the boot classloader for all classes that we load. 7029 final ClassLoader boot = Object.class.getClassLoader(); 7030 7031 packageName = dest.readString().intern(); 7032 manifestPackageName = dest.readString(); 7033 splitNames = dest.readStringArray(); 7034 volumeUuid = dest.readString(); 7035 codePath = dest.readString(); 7036 baseCodePath = dest.readString(); 7037 splitCodePaths = dest.readStringArray(); 7038 baseRevisionCode = dest.readInt(); 7039 splitRevisionCodes = dest.createIntArray(); 7040 splitFlags = dest.createIntArray(); 7041 splitPrivateFlags = dest.createIntArray(); 7042 baseHardwareAccelerated = (dest.readInt() == 1); 7043 applicationInfo = dest.readParcelable(boot); 7044 if (applicationInfo.permission != null) { 7045 applicationInfo.permission = applicationInfo.permission.intern(); 7046 } 7047 7048 // We don't serialize the "owner" package and the application info object for each of 7049 // these components, in order to save space and to avoid circular dependencies while 7050 // serialization. We need to fix them all up here. 7051 dest.readParcelableList(permissions, boot); 7052 fixupOwner(permissions); 7053 dest.readParcelableList(permissionGroups, boot); 7054 fixupOwner(permissionGroups); 7055 dest.readParcelableList(activities, boot); 7056 fixupOwner(activities); 7057 dest.readParcelableList(receivers, boot); 7058 fixupOwner(receivers); 7059 dest.readParcelableList(providers, boot); 7060 fixupOwner(providers); 7061 dest.readParcelableList(services, boot); 7062 fixupOwner(services); 7063 dest.readParcelableList(instrumentation, boot); 7064 fixupOwner(instrumentation); 7065 7066 dest.readStringList(requestedPermissions); 7067 internStringArrayList(requestedPermissions); 7068 dest.readStringList(implicitPermissions); 7069 internStringArrayList(implicitPermissions); 7070 protectedBroadcasts = dest.createStringArrayList(); 7071 internStringArrayList(protectedBroadcasts); 7072 7073 parentPackage = dest.readParcelable(boot); 7074 7075 childPackages = new ArrayList<>(); 7076 dest.readParcelableList(childPackages, boot); 7077 if (childPackages.size() == 0) { 7078 childPackages = null; 7079 } 7080 7081 staticSharedLibName = dest.readString(); 7082 if (staticSharedLibName != null) { 7083 staticSharedLibName = staticSharedLibName.intern(); 7084 } 7085 staticSharedLibVersion = dest.readLong(); 7086 libraryNames = dest.createStringArrayList(); 7087 internStringArrayList(libraryNames); 7088 usesLibraries = dest.createStringArrayList(); 7089 internStringArrayList(usesLibraries); 7090 usesOptionalLibraries = dest.createStringArrayList(); 7091 internStringArrayList(usesOptionalLibraries); 7092 usesLibraryFiles = dest.readStringArray(); 7093 7094 usesLibraryInfos = dest.createTypedArrayList(SharedLibraryInfo.CREATOR); 7095 7096 final int libCount = dest.readInt(); 7097 if (libCount > 0) { 7098 usesStaticLibraries = new ArrayList<>(libCount); 7099 dest.readStringList(usesStaticLibraries); 7100 internStringArrayList(usesStaticLibraries); 7101 usesStaticLibrariesVersions = new long[libCount]; 7102 dest.readLongArray(usesStaticLibrariesVersions); 7103 usesStaticLibrariesCertDigests = new String[libCount][]; 7104 for (int i = 0; i < libCount; i++) { 7105 usesStaticLibrariesCertDigests[i] = dest.createStringArray(); 7106 } 7107 } 7108 7109 preferredActivityFilters = new ArrayList<>(); 7110 dest.readParcelableList(preferredActivityFilters, boot); 7111 if (preferredActivityFilters.size() == 0) { 7112 preferredActivityFilters = null; 7113 } 7114 7115 mOriginalPackages = dest.createStringArrayList(); 7116 mRealPackage = dest.readString(); 7117 mAdoptPermissions = dest.createStringArrayList(); 7118 mAppMetaData = dest.readBundle(); 7119 mVersionCode = dest.readInt(); 7120 mVersionCodeMajor = dest.readInt(); 7121 mVersionName = dest.readString(); 7122 if (mVersionName != null) { 7123 mVersionName = mVersionName.intern(); 7124 } 7125 mSharedUserId = dest.readString(); 7126 if (mSharedUserId != null) { 7127 mSharedUserId = mSharedUserId.intern(); 7128 } 7129 mSharedUserLabel = dest.readInt(); 7130 7131 mSigningDetails = dest.readParcelable(boot); 7132 7133 mPreferredOrder = dest.readInt(); 7134 7135 // long[] packageUsageTimeMillis is not persisted because it isn't information that 7136 // is parsed from the APK. 7137 7138 // Object mExtras is not persisted because it is not information that is read from 7139 // the APK, rather, it is supplied by callers. 7140 7141 7142 configPreferences = new ArrayList<>(); 7143 dest.readParcelableList(configPreferences, boot); 7144 if (configPreferences.size() == 0) { 7145 configPreferences = null; 7146 } 7147 7148 reqFeatures = new ArrayList<>(); 7149 dest.readParcelableList(reqFeatures, boot); 7150 if (reqFeatures.size() == 0) { 7151 reqFeatures = null; 7152 } 7153 7154 featureGroups = new ArrayList<>(); 7155 dest.readParcelableList(featureGroups, boot); 7156 if (featureGroups.size() == 0) { 7157 featureGroups = null; 7158 } 7159 7160 installLocation = dest.readInt(); 7161 coreApp = (dest.readInt() == 1); 7162 mRequiredForAllUsers = (dest.readInt() == 1); 7163 mRestrictedAccountType = dest.readString(); 7164 mRequiredAccountType = dest.readString(); 7165 mOverlayTarget = dest.readString(); 7166 mOverlayTargetName = dest.readString(); 7167 mOverlayCategory = dest.readString(); 7168 mOverlayPriority = dest.readInt(); 7169 mOverlayIsStatic = (dest.readInt() == 1); 7170 mCompileSdkVersion = dest.readInt(); 7171 mCompileSdkVersionCodename = dest.readString(); 7172 mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot); 7173 7174 mKeySetMapping = readKeySetMapping(dest); 7175 7176 cpuAbiOverride = dest.readString(); 7177 use32bitAbi = (dest.readInt() == 1); 7178 restrictUpdateHash = dest.createByteArray(); 7179 visibleToInstantApps = dest.readInt() == 1; 7180 } 7181 internStringArrayList(List<String> list)7182 private static void internStringArrayList(List<String> list) { 7183 if (list != null) { 7184 final int N = list.size(); 7185 for (int i = 0; i < N; ++i) { 7186 list.set(i, list.get(i).intern()); 7187 } 7188 } 7189 } 7190 7191 /** 7192 * Sets the package owner and the the {@code applicationInfo} for every component 7193 * owner by this package. 7194 */ fixupOwner(List<? extends Component<?>> list)7195 private void fixupOwner(List<? extends Component<?>> list) { 7196 if (list != null) { 7197 for (Component<?> c : list) { 7198 c.owner = this; 7199 if (c instanceof Activity) { 7200 ((Activity) c).info.applicationInfo = this.applicationInfo; 7201 } else if (c instanceof Service) { 7202 ((Service) c).info.applicationInfo = this.applicationInfo; 7203 } else if (c instanceof Provider) { 7204 ((Provider) c).info.applicationInfo = this.applicationInfo; 7205 } 7206 } 7207 } 7208 } 7209 7210 @Override writeToParcel(Parcel dest, int flags)7211 public void writeToParcel(Parcel dest, int flags) { 7212 dest.writeString(packageName); 7213 dest.writeString(manifestPackageName); 7214 dest.writeStringArray(splitNames); 7215 dest.writeString(volumeUuid); 7216 dest.writeString(codePath); 7217 dest.writeString(baseCodePath); 7218 dest.writeStringArray(splitCodePaths); 7219 dest.writeInt(baseRevisionCode); 7220 dest.writeIntArray(splitRevisionCodes); 7221 dest.writeIntArray(splitFlags); 7222 dest.writeIntArray(splitPrivateFlags); 7223 dest.writeInt(baseHardwareAccelerated ? 1 : 0); 7224 dest.writeParcelable(applicationInfo, flags); 7225 7226 dest.writeParcelableList(permissions, flags); 7227 dest.writeParcelableList(permissionGroups, flags); 7228 dest.writeParcelableList(activities, flags); 7229 dest.writeParcelableList(receivers, flags); 7230 dest.writeParcelableList(providers, flags); 7231 dest.writeParcelableList(services, flags); 7232 dest.writeParcelableList(instrumentation, flags); 7233 7234 dest.writeStringList(requestedPermissions); 7235 dest.writeStringList(implicitPermissions); 7236 dest.writeStringList(protectedBroadcasts); 7237 7238 // TODO: This doesn't work: b/64295061 7239 dest.writeParcelable(parentPackage, flags); 7240 dest.writeParcelableList(childPackages, flags); 7241 7242 dest.writeString(staticSharedLibName); 7243 dest.writeLong(staticSharedLibVersion); 7244 dest.writeStringList(libraryNames); 7245 dest.writeStringList(usesLibraries); 7246 dest.writeStringList(usesOptionalLibraries); 7247 dest.writeStringArray(usesLibraryFiles); 7248 dest.writeTypedList(usesLibraryInfos); 7249 7250 if (ArrayUtils.isEmpty(usesStaticLibraries)) { 7251 dest.writeInt(-1); 7252 } else { 7253 dest.writeInt(usesStaticLibraries.size()); 7254 dest.writeStringList(usesStaticLibraries); 7255 dest.writeLongArray(usesStaticLibrariesVersions); 7256 for (String[] usesStaticLibrariesCertDigest : usesStaticLibrariesCertDigests) { 7257 dest.writeStringArray(usesStaticLibrariesCertDigest); 7258 } 7259 } 7260 7261 dest.writeParcelableList(preferredActivityFilters, flags); 7262 7263 dest.writeStringList(mOriginalPackages); 7264 dest.writeString(mRealPackage); 7265 dest.writeStringList(mAdoptPermissions); 7266 dest.writeBundle(mAppMetaData); 7267 dest.writeInt(mVersionCode); 7268 dest.writeInt(mVersionCodeMajor); 7269 dest.writeString(mVersionName); 7270 dest.writeString(mSharedUserId); 7271 dest.writeInt(mSharedUserLabel); 7272 7273 dest.writeParcelable(mSigningDetails, flags); 7274 7275 dest.writeInt(mPreferredOrder); 7276 7277 // long[] packageUsageTimeMillis is not persisted because it isn't information that 7278 // is parsed from the APK. 7279 7280 // Object mExtras is not persisted because it is not information that is read from 7281 // the APK, rather, it is supplied by callers. 7282 7283 dest.writeParcelableList(configPreferences, flags); 7284 dest.writeParcelableList(reqFeatures, flags); 7285 dest.writeParcelableList(featureGroups, flags); 7286 7287 dest.writeInt(installLocation); 7288 dest.writeInt(coreApp ? 1 : 0); 7289 dest.writeInt(mRequiredForAllUsers ? 1 : 0); 7290 dest.writeString(mRestrictedAccountType); 7291 dest.writeString(mRequiredAccountType); 7292 dest.writeString(mOverlayTarget); 7293 dest.writeString(mOverlayTargetName); 7294 dest.writeString(mOverlayCategory); 7295 dest.writeInt(mOverlayPriority); 7296 dest.writeInt(mOverlayIsStatic ? 1 : 0); 7297 dest.writeInt(mCompileSdkVersion); 7298 dest.writeString(mCompileSdkVersionCodename); 7299 dest.writeArraySet(mUpgradeKeySets); 7300 writeKeySetMapping(dest, mKeySetMapping); 7301 dest.writeString(cpuAbiOverride); 7302 dest.writeInt(use32bitAbi ? 1 : 0); 7303 dest.writeByteArray(restrictUpdateHash); 7304 dest.writeInt(visibleToInstantApps ? 1 : 0); 7305 } 7306 7307 7308 /** 7309 * Writes the keyset mapping to the provided package. {@code null} mappings are permitted. 7310 */ writeKeySetMapping( Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping)7311 private static void writeKeySetMapping( 7312 Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) { 7313 if (keySetMapping == null) { 7314 dest.writeInt(-1); 7315 return; 7316 } 7317 7318 final int N = keySetMapping.size(); 7319 dest.writeInt(N); 7320 7321 for (int i = 0; i < N; i++) { 7322 dest.writeString(keySetMapping.keyAt(i)); 7323 ArraySet<PublicKey> keys = keySetMapping.valueAt(i); 7324 if (keys == null) { 7325 dest.writeInt(-1); 7326 continue; 7327 } 7328 7329 final int M = keys.size(); 7330 dest.writeInt(M); 7331 for (int j = 0; j < M; j++) { 7332 dest.writeSerializable(keys.valueAt(j)); 7333 } 7334 } 7335 } 7336 7337 /** 7338 * Reads a keyset mapping from the given parcel at the given data position. May return 7339 * {@code null} if the serialized mapping was {@code null}. 7340 */ readKeySetMapping(Parcel in)7341 private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) { 7342 final int N = in.readInt(); 7343 if (N == -1) { 7344 return null; 7345 } 7346 7347 ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>(); 7348 for (int i = 0; i < N; ++i) { 7349 String key = in.readString(); 7350 final int M = in.readInt(); 7351 if (M == -1) { 7352 keySetMapping.put(key, null); 7353 continue; 7354 } 7355 7356 ArraySet<PublicKey> keys = new ArraySet<>(M); 7357 for (int j = 0; j < M; ++j) { 7358 PublicKey pk = (PublicKey) in.readSerializable(); 7359 keys.add(pk); 7360 } 7361 7362 keySetMapping.put(key, keys); 7363 } 7364 7365 return keySetMapping; 7366 } 7367 7368 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() { 7369 public Package createFromParcel(Parcel in) { 7370 return new Package(in); 7371 } 7372 7373 public Package[] newArray(int size) { 7374 return new Package[size]; 7375 } 7376 }; 7377 } 7378 7379 public static abstract class Component<II extends IntentInfo> { 7380 @UnsupportedAppUsage 7381 public final ArrayList<II> intents; 7382 @UnsupportedAppUsage 7383 public final String className; 7384 7385 @UnsupportedAppUsage 7386 public Bundle metaData; 7387 @UnsupportedAppUsage 7388 public Package owner; 7389 /** The order of this component in relation to its peers */ 7390 public int order; 7391 7392 ComponentName componentName; 7393 String componentShortName; 7394 Component(Package owner, ArrayList<II> intents, String className)7395 public Component(Package owner, ArrayList<II> intents, String className) { 7396 this.owner = owner; 7397 this.intents = intents; 7398 this.className = className; 7399 } 7400 Component(Package owner)7401 public Component(Package owner) { 7402 this.owner = owner; 7403 this.intents = null; 7404 this.className = null; 7405 } 7406 Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo)7407 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) { 7408 owner = args.owner; 7409 intents = new ArrayList<II>(0); 7410 if (parsePackageItemInfo(args.owner, outInfo, args.outError, args.tag, args.sa, 7411 true /*nameRequired*/, args.nameRes, args.labelRes, args.iconRes, 7412 args.roundIconRes, args.logoRes, args.bannerRes)) { 7413 className = outInfo.name; 7414 } else { 7415 className = null; 7416 } 7417 } 7418 Component(final ParseComponentArgs args, final ComponentInfo outInfo)7419 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) { 7420 this(args, (PackageItemInfo)outInfo); 7421 if (args.outError[0] != null) { 7422 return; 7423 } 7424 7425 if (args.processRes != 0) { 7426 CharSequence pname; 7427 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) { 7428 pname = args.sa.getNonConfigurationString(args.processRes, 7429 Configuration.NATIVE_CONFIG_VERSION); 7430 } else { 7431 // Some older apps have been seen to use a resource reference 7432 // here that on older builds was ignored (with a warning). We 7433 // need to continue to do this for them so they don't break. 7434 pname = args.sa.getNonResourceString(args.processRes); 7435 } 7436 outInfo.processName = buildProcessName(owner.applicationInfo.packageName, 7437 owner.applicationInfo.processName, pname, 7438 args.flags, args.sepProcesses, args.outError); 7439 } 7440 7441 if (args.descriptionRes != 0) { 7442 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0); 7443 } 7444 7445 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true); 7446 } 7447 Component(Component<II> clone)7448 public Component(Component<II> clone) { 7449 owner = clone.owner; 7450 intents = clone.intents; 7451 className = clone.className; 7452 componentName = clone.componentName; 7453 componentShortName = clone.componentShortName; 7454 } 7455 7456 @UnsupportedAppUsage getComponentName()7457 public ComponentName getComponentName() { 7458 if (componentName != null) { 7459 return componentName; 7460 } 7461 if (className != null) { 7462 componentName = new ComponentName(owner.applicationInfo.packageName, 7463 className); 7464 } 7465 return componentName; 7466 } 7467 Component(Parcel in)7468 protected Component(Parcel in) { 7469 className = in.readString(); 7470 metaData = in.readBundle(); 7471 intents = createIntentsList(in); 7472 7473 owner = null; 7474 } 7475 writeToParcel(Parcel dest, int flags)7476 protected void writeToParcel(Parcel dest, int flags) { 7477 dest.writeString(className); 7478 dest.writeBundle(metaData); 7479 7480 writeIntentsList(intents, dest, flags); 7481 } 7482 7483 /** 7484 * <p> 7485 * Implementation note: The serialized form for the intent list also contains the name 7486 * of the concrete class that's stored in the list, and assumes that every element of the 7487 * list is of the same type. This is very similar to the original parcelable mechanism. 7488 * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable 7489 * and is public API. It also declares Parcelable related methods as final which means 7490 * we can't extend them. The approach of using composition instead of inheritance leads to 7491 * a large set of cascading changes in the PackageManagerService, which seem undesirable. 7492 * 7493 * <p> 7494 * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up 7495 * to make sure their owner fields are consistent. See {@code fixupOwner}. 7496 */ writeIntentsList(ArrayList<? extends IntentInfo> list, Parcel out, int flags)7497 private static void writeIntentsList(ArrayList<? extends IntentInfo> list, Parcel out, 7498 int flags) { 7499 if (list == null) { 7500 out.writeInt(-1); 7501 return; 7502 } 7503 7504 final int N = list.size(); 7505 out.writeInt(N); 7506 7507 // Don't bother writing the component name if the list is empty. 7508 if (N > 0) { 7509 IntentInfo info = list.get(0); 7510 out.writeString(info.getClass().getName()); 7511 7512 for (int i = 0; i < N;i++) { 7513 list.get(i).writeIntentInfoToParcel(out, flags); 7514 } 7515 } 7516 } 7517 createIntentsList(Parcel in)7518 private static <T extends IntentInfo> ArrayList<T> createIntentsList(Parcel in) { 7519 int N = in.readInt(); 7520 if (N == -1) { 7521 return null; 7522 } 7523 7524 if (N == 0) { 7525 return new ArrayList<>(0); 7526 } 7527 7528 String componentName = in.readString(); 7529 final ArrayList<T> intentsList; 7530 try { 7531 final Class<T> cls = (Class<T>) Class.forName(componentName); 7532 final Constructor<T> cons = cls.getConstructor(Parcel.class); 7533 7534 intentsList = new ArrayList<>(N); 7535 for (int i = 0; i < N; ++i) { 7536 intentsList.add(cons.newInstance(in)); 7537 } 7538 } catch (ReflectiveOperationException ree) { 7539 throw new AssertionError("Unable to construct intent list for: " + componentName); 7540 } 7541 7542 return intentsList; 7543 } 7544 appendComponentShortName(StringBuilder sb)7545 public void appendComponentShortName(StringBuilder sb) { 7546 ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className); 7547 } 7548 printComponentShortName(PrintWriter pw)7549 public void printComponentShortName(PrintWriter pw) { 7550 ComponentName.printShortString(pw, owner.applicationInfo.packageName, className); 7551 } 7552 setPackageName(String packageName)7553 public void setPackageName(String packageName) { 7554 componentName = null; 7555 componentShortName = null; 7556 } 7557 } 7558 7559 public final static class Permission extends Component<IntentInfo> implements Parcelable { 7560 @UnsupportedAppUsage 7561 public final PermissionInfo info; 7562 @UnsupportedAppUsage 7563 public boolean tree; 7564 @UnsupportedAppUsage 7565 public PermissionGroup group; 7566 7567 /** 7568 * @hide 7569 */ Permission(Package owner, @Nullable String backgroundPermission)7570 public Permission(Package owner, @Nullable String backgroundPermission) { 7571 super(owner); 7572 info = new PermissionInfo(backgroundPermission); 7573 } 7574 7575 @UnsupportedAppUsage Permission(Package _owner, PermissionInfo _info)7576 public Permission(Package _owner, PermissionInfo _info) { 7577 super(_owner); 7578 info = _info; 7579 } 7580 setPackageName(String packageName)7581 public void setPackageName(String packageName) { 7582 super.setPackageName(packageName); 7583 info.packageName = packageName; 7584 } 7585 toString()7586 public String toString() { 7587 return "Permission{" 7588 + Integer.toHexString(System.identityHashCode(this)) 7589 + " " + info.name + "}"; 7590 } 7591 7592 @Override describeContents()7593 public int describeContents() { 7594 return 0; 7595 } 7596 7597 @Override writeToParcel(Parcel dest, int flags)7598 public void writeToParcel(Parcel dest, int flags) { 7599 super.writeToParcel(dest, flags); 7600 dest.writeParcelable(info, flags); 7601 dest.writeInt(tree ? 1 : 0); 7602 dest.writeParcelable(group, flags); 7603 } 7604 7605 /** @hide */ isAppOp()7606 public boolean isAppOp() { 7607 return info.isAppOp(); 7608 } 7609 Permission(Parcel in)7610 private Permission(Parcel in) { 7611 super(in); 7612 final ClassLoader boot = Object.class.getClassLoader(); 7613 info = in.readParcelable(boot); 7614 if (info.group != null) { 7615 info.group = info.group.intern(); 7616 } 7617 7618 tree = (in.readInt() == 1); 7619 group = in.readParcelable(boot); 7620 } 7621 7622 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Permission>() { 7623 public Permission createFromParcel(Parcel in) { 7624 return new Permission(in); 7625 } 7626 7627 public Permission[] newArray(int size) { 7628 return new Permission[size]; 7629 } 7630 }; 7631 } 7632 7633 public final static class PermissionGroup extends Component<IntentInfo> implements Parcelable { 7634 @UnsupportedAppUsage 7635 public final PermissionGroupInfo info; 7636 PermissionGroup(Package owner, @StringRes int requestDetailResourceId, @StringRes int backgroundRequestResourceId, @StringRes int backgroundRequestDetailResourceId)7637 public PermissionGroup(Package owner, @StringRes int requestDetailResourceId, 7638 @StringRes int backgroundRequestResourceId, 7639 @StringRes int backgroundRequestDetailResourceId) { 7640 super(owner); 7641 info = new PermissionGroupInfo(requestDetailResourceId, backgroundRequestResourceId, 7642 backgroundRequestDetailResourceId); 7643 } 7644 PermissionGroup(Package _owner, PermissionGroupInfo _info)7645 public PermissionGroup(Package _owner, PermissionGroupInfo _info) { 7646 super(_owner); 7647 info = _info; 7648 } 7649 setPackageName(String packageName)7650 public void setPackageName(String packageName) { 7651 super.setPackageName(packageName); 7652 info.packageName = packageName; 7653 } 7654 toString()7655 public String toString() { 7656 return "PermissionGroup{" 7657 + Integer.toHexString(System.identityHashCode(this)) 7658 + " " + info.name + "}"; 7659 } 7660 7661 @Override describeContents()7662 public int describeContents() { 7663 return 0; 7664 } 7665 7666 @Override writeToParcel(Parcel dest, int flags)7667 public void writeToParcel(Parcel dest, int flags) { 7668 super.writeToParcel(dest, flags); 7669 dest.writeParcelable(info, flags); 7670 } 7671 PermissionGroup(Parcel in)7672 private PermissionGroup(Parcel in) { 7673 super(in); 7674 info = in.readParcelable(Object.class.getClassLoader()); 7675 } 7676 7677 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<PermissionGroup>() { 7678 public PermissionGroup createFromParcel(Parcel in) { 7679 return new PermissionGroup(in); 7680 } 7681 7682 public PermissionGroup[] newArray(int size) { 7683 return new PermissionGroup[size]; 7684 } 7685 }; 7686 } 7687 copyNeeded(int flags, Package p, PackageUserState state, Bundle metaData, int userId)7688 private static boolean copyNeeded(int flags, Package p, 7689 PackageUserState state, Bundle metaData, int userId) { 7690 if (userId != UserHandle.USER_SYSTEM) { 7691 // We always need to copy for other users, since we need 7692 // to fix up the uid. 7693 return true; 7694 } 7695 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) { 7696 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED; 7697 if (p.applicationInfo.enabled != enabled) { 7698 return true; 7699 } 7700 } 7701 boolean suspended = (p.applicationInfo.flags & FLAG_SUSPENDED) != 0; 7702 if (state.suspended != suspended) { 7703 return true; 7704 } 7705 if (!state.installed || state.hidden) { 7706 return true; 7707 } 7708 if (state.stopped) { 7709 return true; 7710 } 7711 if (state.instantApp != p.applicationInfo.isInstantApp()) { 7712 return true; 7713 } 7714 if ((flags & PackageManager.GET_META_DATA) != 0 7715 && (metaData != null || p.mAppMetaData != null)) { 7716 return true; 7717 } 7718 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0 7719 && p.usesLibraryFiles != null) { 7720 return true; 7721 } 7722 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0 7723 && p.usesLibraryInfos != null) { 7724 return true; 7725 } 7726 if (p.staticSharedLibName != null) { 7727 return true; 7728 } 7729 return false; 7730 } 7731 7732 @UnsupportedAppUsage generateApplicationInfo(Package p, int flags, PackageUserState state)7733 public static ApplicationInfo generateApplicationInfo(Package p, int flags, 7734 PackageUserState state) { 7735 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId()); 7736 } 7737 updateApplicationInfo(ApplicationInfo ai, int flags, PackageUserState state)7738 private static void updateApplicationInfo(ApplicationInfo ai, int flags, 7739 PackageUserState state) { 7740 // CompatibilityMode is global state. 7741 if (!sCompatibilityModeEnabled) { 7742 ai.disableCompatibilityMode(); 7743 } 7744 if (state.installed) { 7745 ai.flags |= ApplicationInfo.FLAG_INSTALLED; 7746 } else { 7747 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED; 7748 } 7749 if (state.suspended) { 7750 ai.flags |= ApplicationInfo.FLAG_SUSPENDED; 7751 } else { 7752 ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED; 7753 } 7754 if (state.instantApp) { 7755 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_INSTANT; 7756 } else { 7757 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_INSTANT; 7758 } 7759 if (state.virtualPreload) { 7760 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD; 7761 } else { 7762 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD; 7763 } 7764 if (state.hidden) { 7765 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN; 7766 } else { 7767 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN; 7768 } 7769 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) { 7770 ai.enabled = true; 7771 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) { 7772 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0; 7773 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED 7774 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) { 7775 ai.enabled = false; 7776 } 7777 ai.enabledSetting = state.enabled; 7778 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) { 7779 ai.category = state.categoryHint; 7780 } 7781 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) { 7782 ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName); 7783 } 7784 ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state); 7785 ai.resourceDirs = state.overlayPaths; 7786 ai.icon = (sUseRoundIcon && ai.roundIconRes != 0) ? ai.roundIconRes : ai.iconRes; 7787 } 7788 7789 @UnsupportedAppUsage generateApplicationInfo(Package p, int flags, PackageUserState state, int userId)7790 public static ApplicationInfo generateApplicationInfo(Package p, int flags, 7791 PackageUserState state, int userId) { 7792 if (p == null) return null; 7793 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) { 7794 return null; 7795 } 7796 if (!copyNeeded(flags, p, state, null, userId) 7797 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0 7798 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) { 7799 // In this case it is safe to directly modify the internal ApplicationInfo state: 7800 // - CompatibilityMode is global state, so will be the same for every call. 7801 // - We only come in to here if the app should reported as installed; this is the 7802 // default state, and we will do a copy otherwise. 7803 // - The enable state will always be reported the same for the application across 7804 // calls; the only exception is for the UNTIL_USED mode, and in that case we will 7805 // be doing a copy. 7806 updateApplicationInfo(p.applicationInfo, flags, state); 7807 return p.applicationInfo; 7808 } 7809 7810 // Make shallow copy so we can store the metadata/libraries safely 7811 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo); 7812 ai.initForUser(userId); 7813 if ((flags & PackageManager.GET_META_DATA) != 0) { 7814 ai.metaData = p.mAppMetaData; 7815 } 7816 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) { 7817 ai.sharedLibraryFiles = p.usesLibraryFiles; 7818 ai.sharedLibraryInfos = p.usesLibraryInfos; 7819 } 7820 if (state.stopped) { 7821 ai.flags |= ApplicationInfo.FLAG_STOPPED; 7822 } else { 7823 ai.flags &= ~ApplicationInfo.FLAG_STOPPED; 7824 } 7825 updateApplicationInfo(ai, flags, state); 7826 return ai; 7827 } 7828 generateApplicationInfo(ApplicationInfo ai, int flags, PackageUserState state, int userId)7829 public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags, 7830 PackageUserState state, int userId) { 7831 if (ai == null) return null; 7832 if (!checkUseInstalledOrHidden(flags, state, ai)) { 7833 return null; 7834 } 7835 // This is only used to return the ResolverActivity; we will just always 7836 // make a copy. 7837 ai = new ApplicationInfo(ai); 7838 ai.initForUser(userId); 7839 if (state.stopped) { 7840 ai.flags |= ApplicationInfo.FLAG_STOPPED; 7841 } else { 7842 ai.flags &= ~ApplicationInfo.FLAG_STOPPED; 7843 } 7844 updateApplicationInfo(ai, flags, state); 7845 return ai; 7846 } 7847 7848 @UnsupportedAppUsage generatePermissionInfo( Permission p, int flags)7849 public static final PermissionInfo generatePermissionInfo( 7850 Permission p, int flags) { 7851 if (p == null) return null; 7852 if ((flags&PackageManager.GET_META_DATA) == 0) { 7853 return p.info; 7854 } 7855 PermissionInfo pi = new PermissionInfo(p.info); 7856 pi.metaData = p.metaData; 7857 return pi; 7858 } 7859 7860 @UnsupportedAppUsage generatePermissionGroupInfo( PermissionGroup pg, int flags)7861 public static final PermissionGroupInfo generatePermissionGroupInfo( 7862 PermissionGroup pg, int flags) { 7863 if (pg == null) return null; 7864 if ((flags&PackageManager.GET_META_DATA) == 0) { 7865 return pg.info; 7866 } 7867 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info); 7868 pgi.metaData = pg.metaData; 7869 return pgi; 7870 } 7871 7872 public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable { 7873 @UnsupportedAppUsage 7874 public final ActivityInfo info; 7875 private boolean mHasMaxAspectRatio; 7876 private boolean mHasMinAspectRatio; 7877 hasMaxAspectRatio()7878 private boolean hasMaxAspectRatio() { 7879 return mHasMaxAspectRatio; 7880 } 7881 hasMinAspectRatio()7882 private boolean hasMinAspectRatio() { 7883 return mHasMinAspectRatio; 7884 } 7885 7886 // To construct custom activity which does not exist in manifest Activity(final Package owner, final String className, final ActivityInfo info)7887 Activity(final Package owner, final String className, final ActivityInfo info) { 7888 super(owner, new ArrayList<>(0), className); 7889 this.info = info; 7890 this.info.applicationInfo = owner.applicationInfo; 7891 } 7892 Activity(final ParseComponentArgs args, final ActivityInfo _info)7893 public Activity(final ParseComponentArgs args, final ActivityInfo _info) { 7894 super(args, _info); 7895 info = _info; 7896 info.applicationInfo = args.owner.applicationInfo; 7897 } 7898 setPackageName(String packageName)7899 public void setPackageName(String packageName) { 7900 super.setPackageName(packageName); 7901 info.packageName = packageName; 7902 } 7903 7904 setMaxAspectRatio(float maxAspectRatio)7905 private void setMaxAspectRatio(float maxAspectRatio) { 7906 if (info.resizeMode == RESIZE_MODE_RESIZEABLE 7907 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) { 7908 // Resizeable activities can be put in any aspect ratio. 7909 return; 7910 } 7911 7912 if (maxAspectRatio < 1.0f && maxAspectRatio != 0) { 7913 // Ignore any value lesser than 1.0. 7914 return; 7915 } 7916 7917 info.maxAspectRatio = maxAspectRatio; 7918 mHasMaxAspectRatio = true; 7919 } 7920 setMinAspectRatio(float minAspectRatio)7921 private void setMinAspectRatio(float minAspectRatio) { 7922 if (info.resizeMode == RESIZE_MODE_RESIZEABLE 7923 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) { 7924 // Resizeable activities can be put in any aspect ratio. 7925 return; 7926 } 7927 7928 if (minAspectRatio < 1.0f && minAspectRatio != 0) { 7929 // Ignore any value lesser than 1.0. 7930 return; 7931 } 7932 7933 info.minAspectRatio = minAspectRatio; 7934 mHasMinAspectRatio = true; 7935 } 7936 toString()7937 public String toString() { 7938 StringBuilder sb = new StringBuilder(128); 7939 sb.append("Activity{"); 7940 sb.append(Integer.toHexString(System.identityHashCode(this))); 7941 sb.append(' '); 7942 appendComponentShortName(sb); 7943 sb.append('}'); 7944 return sb.toString(); 7945 } 7946 7947 @Override describeContents()7948 public int describeContents() { 7949 return 0; 7950 } 7951 7952 @Override writeToParcel(Parcel dest, int flags)7953 public void writeToParcel(Parcel dest, int flags) { 7954 super.writeToParcel(dest, flags); 7955 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES); 7956 dest.writeBoolean(mHasMaxAspectRatio); 7957 dest.writeBoolean(mHasMinAspectRatio); 7958 } 7959 Activity(Parcel in)7960 private Activity(Parcel in) { 7961 super(in); 7962 info = in.readParcelable(Object.class.getClassLoader()); 7963 mHasMaxAspectRatio = in.readBoolean(); 7964 mHasMinAspectRatio = in.readBoolean(); 7965 7966 for (ActivityIntentInfo aii : intents) { 7967 aii.activity = this; 7968 order = Math.max(aii.getOrder(), order); 7969 } 7970 7971 if (info.permission != null) { 7972 info.permission = info.permission.intern(); 7973 } 7974 } 7975 7976 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Activity>() { 7977 public Activity createFromParcel(Parcel in) { 7978 return new Activity(in); 7979 } 7980 7981 public Activity[] newArray(int size) { 7982 return new Activity[size]; 7983 } 7984 }; 7985 } 7986 7987 @UnsupportedAppUsage generateActivityInfo(Activity a, int flags, PackageUserState state, int userId)7988 public static final ActivityInfo generateActivityInfo(Activity a, int flags, 7989 PackageUserState state, int userId) { 7990 if (a == null) return null; 7991 if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) { 7992 return null; 7993 } 7994 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) { 7995 updateApplicationInfo(a.info.applicationInfo, flags, state); 7996 return a.info; 7997 } 7998 // Make shallow copies so we can store the metadata safely 7999 ActivityInfo ai = new ActivityInfo(a.info); 8000 ai.metaData = a.metaData; 8001 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId); 8002 return ai; 8003 } 8004 generateActivityInfo(ActivityInfo ai, int flags, PackageUserState state, int userId)8005 public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags, 8006 PackageUserState state, int userId) { 8007 if (ai == null) return null; 8008 if (!checkUseInstalledOrHidden(flags, state, ai.applicationInfo)) { 8009 return null; 8010 } 8011 // This is only used to return the ResolverActivity; we will just always 8012 // make a copy. 8013 ai = new ActivityInfo(ai); 8014 ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId); 8015 return ai; 8016 } 8017 8018 public final static class Service extends Component<ServiceIntentInfo> implements Parcelable { 8019 @UnsupportedAppUsage 8020 public final ServiceInfo info; 8021 Service(final ParseComponentArgs args, final ServiceInfo _info)8022 public Service(final ParseComponentArgs args, final ServiceInfo _info) { 8023 super(args, _info); 8024 info = _info; 8025 info.applicationInfo = args.owner.applicationInfo; 8026 } 8027 setPackageName(String packageName)8028 public void setPackageName(String packageName) { 8029 super.setPackageName(packageName); 8030 info.packageName = packageName; 8031 } 8032 toString()8033 public String toString() { 8034 StringBuilder sb = new StringBuilder(128); 8035 sb.append("Service{"); 8036 sb.append(Integer.toHexString(System.identityHashCode(this))); 8037 sb.append(' '); 8038 appendComponentShortName(sb); 8039 sb.append('}'); 8040 return sb.toString(); 8041 } 8042 8043 @Override describeContents()8044 public int describeContents() { 8045 return 0; 8046 } 8047 8048 @Override writeToParcel(Parcel dest, int flags)8049 public void writeToParcel(Parcel dest, int flags) { 8050 super.writeToParcel(dest, flags); 8051 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES); 8052 } 8053 Service(Parcel in)8054 private Service(Parcel in) { 8055 super(in); 8056 info = in.readParcelable(Object.class.getClassLoader()); 8057 8058 for (ServiceIntentInfo aii : intents) { 8059 aii.service = this; 8060 order = Math.max(aii.getOrder(), order); 8061 } 8062 8063 if (info.permission != null) { 8064 info.permission = info.permission.intern(); 8065 } 8066 } 8067 8068 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Service>() { 8069 public Service createFromParcel(Parcel in) { 8070 return new Service(in); 8071 } 8072 8073 public Service[] newArray(int size) { 8074 return new Service[size]; 8075 } 8076 }; 8077 } 8078 8079 @UnsupportedAppUsage generateServiceInfo(Service s, int flags, PackageUserState state, int userId)8080 public static final ServiceInfo generateServiceInfo(Service s, int flags, 8081 PackageUserState state, int userId) { 8082 if (s == null) return null; 8083 if (!checkUseInstalledOrHidden(flags, state, s.owner.applicationInfo)) { 8084 return null; 8085 } 8086 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) { 8087 updateApplicationInfo(s.info.applicationInfo, flags, state); 8088 return s.info; 8089 } 8090 // Make shallow copies so we can store the metadata safely 8091 ServiceInfo si = new ServiceInfo(s.info); 8092 si.metaData = s.metaData; 8093 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId); 8094 return si; 8095 } 8096 8097 public final static class Provider extends Component<ProviderIntentInfo> implements Parcelable { 8098 @UnsupportedAppUsage 8099 public final ProviderInfo info; 8100 @UnsupportedAppUsage 8101 public boolean syncable; 8102 Provider(final ParseComponentArgs args, final ProviderInfo _info)8103 public Provider(final ParseComponentArgs args, final ProviderInfo _info) { 8104 super(args, _info); 8105 info = _info; 8106 info.applicationInfo = args.owner.applicationInfo; 8107 syncable = false; 8108 } 8109 8110 @UnsupportedAppUsage Provider(Provider existingProvider)8111 public Provider(Provider existingProvider) { 8112 super(existingProvider); 8113 this.info = existingProvider.info; 8114 this.syncable = existingProvider.syncable; 8115 } 8116 setPackageName(String packageName)8117 public void setPackageName(String packageName) { 8118 super.setPackageName(packageName); 8119 info.packageName = packageName; 8120 } 8121 toString()8122 public String toString() { 8123 StringBuilder sb = new StringBuilder(128); 8124 sb.append("Provider{"); 8125 sb.append(Integer.toHexString(System.identityHashCode(this))); 8126 sb.append(' '); 8127 appendComponentShortName(sb); 8128 sb.append('}'); 8129 return sb.toString(); 8130 } 8131 8132 @Override describeContents()8133 public int describeContents() { 8134 return 0; 8135 } 8136 8137 @Override writeToParcel(Parcel dest, int flags)8138 public void writeToParcel(Parcel dest, int flags) { 8139 super.writeToParcel(dest, flags); 8140 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES); 8141 dest.writeInt((syncable) ? 1 : 0); 8142 } 8143 Provider(Parcel in)8144 private Provider(Parcel in) { 8145 super(in); 8146 info = in.readParcelable(Object.class.getClassLoader()); 8147 syncable = (in.readInt() == 1); 8148 8149 for (ProviderIntentInfo aii : intents) { 8150 aii.provider = this; 8151 } 8152 8153 if (info.readPermission != null) { 8154 info.readPermission = info.readPermission.intern(); 8155 } 8156 8157 if (info.writePermission != null) { 8158 info.writePermission = info.writePermission.intern(); 8159 } 8160 8161 if (info.authority != null) { 8162 info.authority = info.authority.intern(); 8163 } 8164 } 8165 8166 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Provider>() { 8167 public Provider createFromParcel(Parcel in) { 8168 return new Provider(in); 8169 } 8170 8171 public Provider[] newArray(int size) { 8172 return new Provider[size]; 8173 } 8174 }; 8175 } 8176 8177 @UnsupportedAppUsage generateProviderInfo(Provider p, int flags, PackageUserState state, int userId)8178 public static final ProviderInfo generateProviderInfo(Provider p, int flags, 8179 PackageUserState state, int userId) { 8180 if (p == null) return null; 8181 if (!checkUseInstalledOrHidden(flags, state, p.owner.applicationInfo)) { 8182 return null; 8183 } 8184 if (!copyNeeded(flags, p.owner, state, p.metaData, userId) 8185 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0 8186 || p.info.uriPermissionPatterns == null)) { 8187 updateApplicationInfo(p.info.applicationInfo, flags, state); 8188 return p.info; 8189 } 8190 // Make shallow copies so we can store the metadata safely 8191 ProviderInfo pi = new ProviderInfo(p.info); 8192 pi.metaData = p.metaData; 8193 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) { 8194 pi.uriPermissionPatterns = null; 8195 } 8196 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId); 8197 return pi; 8198 } 8199 8200 public final static class Instrumentation extends Component<IntentInfo> implements 8201 Parcelable { 8202 @UnsupportedAppUsage 8203 public final InstrumentationInfo info; 8204 Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info)8205 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) { 8206 super(args, _info); 8207 info = _info; 8208 } 8209 setPackageName(String packageName)8210 public void setPackageName(String packageName) { 8211 super.setPackageName(packageName); 8212 info.packageName = packageName; 8213 } 8214 toString()8215 public String toString() { 8216 StringBuilder sb = new StringBuilder(128); 8217 sb.append("Instrumentation{"); 8218 sb.append(Integer.toHexString(System.identityHashCode(this))); 8219 sb.append(' '); 8220 appendComponentShortName(sb); 8221 sb.append('}'); 8222 return sb.toString(); 8223 } 8224 8225 @Override describeContents()8226 public int describeContents() { 8227 return 0; 8228 } 8229 8230 @Override writeToParcel(Parcel dest, int flags)8231 public void writeToParcel(Parcel dest, int flags) { 8232 super.writeToParcel(dest, flags); 8233 dest.writeParcelable(info, flags); 8234 } 8235 Instrumentation(Parcel in)8236 private Instrumentation(Parcel in) { 8237 super(in); 8238 info = in.readParcelable(Object.class.getClassLoader()); 8239 8240 if (info.targetPackage != null) { 8241 info.targetPackage = info.targetPackage.intern(); 8242 } 8243 8244 if (info.targetProcesses != null) { 8245 info.targetProcesses = info.targetProcesses.intern(); 8246 } 8247 } 8248 8249 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Instrumentation>() { 8250 public Instrumentation createFromParcel(Parcel in) { 8251 return new Instrumentation(in); 8252 } 8253 8254 public Instrumentation[] newArray(int size) { 8255 return new Instrumentation[size]; 8256 } 8257 }; 8258 } 8259 8260 @UnsupportedAppUsage generateInstrumentationInfo( Instrumentation i, int flags)8261 public static final InstrumentationInfo generateInstrumentationInfo( 8262 Instrumentation i, int flags) { 8263 if (i == null) return null; 8264 if ((flags&PackageManager.GET_META_DATA) == 0) { 8265 return i.info; 8266 } 8267 InstrumentationInfo ii = new InstrumentationInfo(i.info); 8268 ii.metaData = i.metaData; 8269 return ii; 8270 } 8271 8272 public static abstract class IntentInfo extends IntentFilter { 8273 @UnsupportedAppUsage 8274 public boolean hasDefault; 8275 @UnsupportedAppUsage 8276 public int labelRes; 8277 @UnsupportedAppUsage 8278 public CharSequence nonLocalizedLabel; 8279 @UnsupportedAppUsage 8280 public int icon; 8281 @UnsupportedAppUsage 8282 public int logo; 8283 @UnsupportedAppUsage 8284 public int banner; 8285 public int preferred; 8286 8287 @UnsupportedAppUsage IntentInfo()8288 protected IntentInfo() { 8289 } 8290 IntentInfo(Parcel dest)8291 protected IntentInfo(Parcel dest) { 8292 super(dest); 8293 hasDefault = (dest.readInt() == 1); 8294 labelRes = dest.readInt(); 8295 nonLocalizedLabel = dest.readCharSequence(); 8296 icon = dest.readInt(); 8297 logo = dest.readInt(); 8298 banner = dest.readInt(); 8299 preferred = dest.readInt(); 8300 } 8301 8302 writeIntentInfoToParcel(Parcel dest, int flags)8303 public void writeIntentInfoToParcel(Parcel dest, int flags) { 8304 super.writeToParcel(dest, flags); 8305 dest.writeInt(hasDefault ? 1 : 0); 8306 dest.writeInt(labelRes); 8307 dest.writeCharSequence(nonLocalizedLabel); 8308 dest.writeInt(icon); 8309 dest.writeInt(logo); 8310 dest.writeInt(banner); 8311 dest.writeInt(preferred); 8312 } 8313 } 8314 8315 public final static class ActivityIntentInfo extends IntentInfo { 8316 @UnsupportedAppUsage 8317 public Activity activity; 8318 ActivityIntentInfo(Activity _activity)8319 public ActivityIntentInfo(Activity _activity) { 8320 activity = _activity; 8321 } 8322 toString()8323 public String toString() { 8324 StringBuilder sb = new StringBuilder(128); 8325 sb.append("ActivityIntentInfo{"); 8326 sb.append(Integer.toHexString(System.identityHashCode(this))); 8327 sb.append(' '); 8328 activity.appendComponentShortName(sb); 8329 sb.append('}'); 8330 return sb.toString(); 8331 } 8332 ActivityIntentInfo(Parcel in)8333 public ActivityIntentInfo(Parcel in) { 8334 super(in); 8335 } 8336 } 8337 8338 public final static class ServiceIntentInfo extends IntentInfo { 8339 @UnsupportedAppUsage 8340 public Service service; 8341 ServiceIntentInfo(Service _service)8342 public ServiceIntentInfo(Service _service) { 8343 service = _service; 8344 } 8345 toString()8346 public String toString() { 8347 StringBuilder sb = new StringBuilder(128); 8348 sb.append("ServiceIntentInfo{"); 8349 sb.append(Integer.toHexString(System.identityHashCode(this))); 8350 sb.append(' '); 8351 service.appendComponentShortName(sb); 8352 sb.append('}'); 8353 return sb.toString(); 8354 } 8355 ServiceIntentInfo(Parcel in)8356 public ServiceIntentInfo(Parcel in) { 8357 super(in); 8358 } 8359 } 8360 8361 public static final class ProviderIntentInfo extends IntentInfo { 8362 @UnsupportedAppUsage 8363 public Provider provider; 8364 ProviderIntentInfo(Provider provider)8365 public ProviderIntentInfo(Provider provider) { 8366 this.provider = provider; 8367 } 8368 toString()8369 public String toString() { 8370 StringBuilder sb = new StringBuilder(128); 8371 sb.append("ProviderIntentInfo{"); 8372 sb.append(Integer.toHexString(System.identityHashCode(this))); 8373 sb.append(' '); 8374 provider.appendComponentShortName(sb); 8375 sb.append('}'); 8376 return sb.toString(); 8377 } 8378 ProviderIntentInfo(Parcel in)8379 public ProviderIntentInfo(Parcel in) { 8380 super(in); 8381 } 8382 } 8383 8384 /** 8385 * @hide 8386 */ 8387 @UnsupportedAppUsage setCompatibilityModeEnabled(boolean compatibilityModeEnabled)8388 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) { 8389 sCompatibilityModeEnabled = compatibilityModeEnabled; 8390 } 8391 8392 /** 8393 * @hide 8394 */ readConfigUseRoundIcon(Resources r)8395 public static void readConfigUseRoundIcon(Resources r) { 8396 if (r != null) { 8397 sUseRoundIcon = r.getBoolean(com.android.internal.R.bool.config_useRoundIcon); 8398 return; 8399 } 8400 8401 ApplicationInfo androidAppInfo; 8402 try { 8403 androidAppInfo = ActivityThread.getPackageManager().getApplicationInfo( 8404 "android", 0 /* flags */, 8405 UserHandle.myUserId()); 8406 } catch (RemoteException e) { 8407 throw e.rethrowFromSystemServer(); 8408 } 8409 Resources systemResources = Resources.getSystem(); 8410 8411 // Create in-flight as this overlayable resource is only used when config changes 8412 Resources overlayableRes = ResourcesManager.getInstance().getResources(null, 8413 null, 8414 null, 8415 androidAppInfo.resourceDirs, 8416 androidAppInfo.sharedLibraryFiles, 8417 Display.DEFAULT_DISPLAY, 8418 null, 8419 systemResources.getCompatibilityInfo(), 8420 systemResources.getClassLoader()); 8421 8422 sUseRoundIcon = overlayableRes.getBoolean(com.android.internal.R.bool.config_useRoundIcon); 8423 } 8424 8425 public static class PackageParserException extends Exception { 8426 public final int error; 8427 PackageParserException(int error, String detailMessage)8428 public PackageParserException(int error, String detailMessage) { 8429 super(detailMessage); 8430 this.error = error; 8431 } 8432 PackageParserException(int error, String detailMessage, Throwable throwable)8433 public PackageParserException(int error, String detailMessage, Throwable throwable) { 8434 super(detailMessage, throwable); 8435 this.error = error; 8436 } 8437 } 8438 8439 } 8440