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