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