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