Merge "Refactor PackageParser (2/n)" into sc-dev
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 45f072a..fe8bf9d 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -30,6 +30,7 @@
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
+import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
@@ -53,8 +54,6 @@
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.split.DefaultSplitAssetLoader;
-import android.content.pm.split.SplitAssetDependencyLoader;
import android.content.pm.split.SplitAssetLoader;
import android.content.res.ApkAssets;
import android.content.res.AssetManager;
@@ -80,6 +79,7 @@
import android.util.AttributeSet;
import android.util.Base64;
import android.util.DisplayMetrics;
+import android.util.IntArray;
import android.util.Log;
import android.util.PackageUtils;
import android.util.Pair;
@@ -118,6 +118,7 @@
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.BitSet;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
@@ -8573,4 +8574,410 @@
this.error = error;
}
}
+
+ // Duplicate the SplitAsset related classes with PackageParser.Package/ApkLite here, and
+ // change the original one using new Package/ApkLite. The propose is that we don't want to
+ // have two branches of methods in SplitAsset related classes so we can keep real classes
+ // clean and move all the legacy code to one place.
+
+ /**
+ * A helper class that implements the dependency tree traversal for splits. Callbacks
+ * are implemented by subclasses to notify whether a split has already been constructed
+ * and is cached, and to actually create the split requested.
+ *
+ * This helper is meant to be subclassed so as to reduce the number of allocations
+ * needed to make use of it.
+ *
+ * All inputs and outputs are assumed to be indices into an array of splits.
+ *
+ * @hide
+ * @deprecated Do not use. New changes should use
+ * {@link android.content.pm.split.SplitDependencyLoader} instead.
+ */
+ @Deprecated
+ private abstract static class SplitDependencyLoader<E extends Exception> {
+ private final @NonNull SparseArray<int[]> mDependencies;
+
+ /**
+ * Construct a new SplitDependencyLoader. Meant to be called from the
+ * subclass constructor.
+ * @param dependencies The dependency tree of splits.
+ */
+ protected SplitDependencyLoader(@NonNull SparseArray<int[]> dependencies) {
+ mDependencies = dependencies;
+ }
+
+ /**
+ * Traverses the dependency tree and constructs any splits that are not already
+ * cached. This routine short-circuits and skips the creation of splits closer to the
+ * root if they are cached, as reported by the subclass implementation of
+ * {@link #isSplitCached(int)}. The construction of splits is delegated to the subclass
+ * implementation of {@link #constructSplit(int, int[], int)}.
+ * @param splitIdx The index of the split to load. 0 represents the base Application.
+ */
+ protected void loadDependenciesForSplit(@IntRange(from = 0) int splitIdx) throws E {
+ // Quick check before any allocations are done.
+ if (isSplitCached(splitIdx)) {
+ return;
+ }
+
+ // Special case the base, since it has no dependencies.
+ if (splitIdx == 0) {
+ final int[] configSplitIndices = collectConfigSplitIndices(0);
+ constructSplit(0, configSplitIndices, -1);
+ return;
+ }
+
+ // Build up the dependency hierarchy.
+ final IntArray linearDependencies = new IntArray();
+ linearDependencies.add(splitIdx);
+
+ // Collect all the dependencies that need to be constructed.
+ // They will be listed from leaf to root.
+ while (true) {
+ // Only follow the first index into the array. The others are config splits and
+ // get loaded with the split.
+ final int[] deps = mDependencies.get(splitIdx);
+ if (deps != null && deps.length > 0) {
+ splitIdx = deps[0];
+ } else {
+ splitIdx = -1;
+ }
+
+ if (splitIdx < 0 || isSplitCached(splitIdx)) {
+ break;
+ }
+
+ linearDependencies.add(splitIdx);
+ }
+
+ // Visit each index, from right to left (root to leaf).
+ int parentIdx = splitIdx;
+ for (int i = linearDependencies.size() - 1; i >= 0; i--) {
+ final int idx = linearDependencies.get(i);
+ final int[] configSplitIndices = collectConfigSplitIndices(idx);
+ constructSplit(idx, configSplitIndices, parentIdx);
+ parentIdx = idx;
+ }
+ }
+
+ private @NonNull int[] collectConfigSplitIndices(int splitIdx) {
+ // The config splits appear after the first element.
+ final int[] deps = mDependencies.get(splitIdx);
+ if (deps == null || deps.length <= 1) {
+ return EmptyArray.INT;
+ }
+ return Arrays.copyOfRange(deps, 1, deps.length);
+ }
+
+ /**
+ * Subclass to report whether the split at `splitIdx` is cached and need not be constructed.
+ * It is assumed that if `splitIdx` is cached, any parent of `splitIdx` is also cached.
+ * @param splitIdx The index of the split to check for in the cache.
+ * @return true if the split is cached and does not need to be constructed.
+ */
+ protected abstract boolean isSplitCached(@IntRange(from = 0) int splitIdx);
+
+ /**
+ * Subclass to construct a split at index `splitIdx` with parent split `parentSplitIdx`.
+ * The result is expected to be cached by the subclass in its own structures.
+ * @param splitIdx The index of the split to construct. 0 represents the base Application.
+ * @param configSplitIndices The array of configuration splits to load along with this
+ * split. May be empty (length == 0) but never null.
+ * @param parentSplitIdx The index of the parent split. -1 if there is no parent.
+ * @throws E Subclass defined exception representing failure to construct a split.
+ */
+ protected abstract void constructSplit(@IntRange(from = 0) int splitIdx,
+ @NonNull @IntRange(from = 1) int[] configSplitIndices,
+ @IntRange(from = -1) int parentSplitIdx) throws E;
+
+ public static class IllegalDependencyException extends Exception {
+ private IllegalDependencyException(String message) {
+ super(message);
+ }
+ }
+
+ private static int[] append(int[] src, int elem) {
+ if (src == null) {
+ return new int[] { elem };
+ }
+ int[] dst = Arrays.copyOf(src, src.length + 1);
+ dst[src.length] = elem;
+ return dst;
+ }
+
+ public static @NonNull SparseArray<int[]> createDependenciesFromPackage(
+ PackageLite pkg)
+ throws SplitDependencyLoader.IllegalDependencyException {
+ // The data structure that holds the dependencies. In PackageParser, splits are stored
+ // in their own array, separate from the base. We treat all paths as equals, so
+ // we need to insert the base as index 0, and shift all other splits.
+ final SparseArray<int[]> splitDependencies = new SparseArray<>();
+
+ // The base depends on nothing.
+ splitDependencies.put(0, new int[] {-1});
+
+ // First write out the <uses-split> dependencies. These must appear first in the
+ // array of ints, as is convention in this class.
+ for (int splitIdx = 0; splitIdx < pkg.splitNames.length; splitIdx++) {
+ if (!pkg.isFeatureSplits[splitIdx]) {
+ // Non-feature splits don't have dependencies.
+ continue;
+ }
+
+ // Implicit dependency on the base.
+ final int targetIdx;
+ final String splitDependency = pkg.usesSplitNames[splitIdx];
+ if (splitDependency != null) {
+ final int depIdx = Arrays.binarySearch(pkg.splitNames, splitDependency);
+ if (depIdx < 0) {
+ throw new SplitDependencyLoader.IllegalDependencyException(
+ "Split '" + pkg.splitNames[splitIdx] + "' requires split '"
+ + splitDependency + "', which is missing.");
+ }
+ targetIdx = depIdx + 1;
+ } else {
+ // Implicitly depend on the base.
+ targetIdx = 0;
+ }
+ splitDependencies.put(splitIdx + 1, new int[] {targetIdx});
+ }
+
+ // Write out the configForSplit reverse-dependencies. These appear after the
+ // <uses-split> dependencies and are considered leaves.
+ //
+ // At this point, all splits in splitDependencies have the first element in their
+ // array set.
+ for (int splitIdx = 0, size = pkg.splitNames.length; splitIdx < size; splitIdx++) {
+ if (pkg.isFeatureSplits[splitIdx]) {
+ // Feature splits are not configForSplits.
+ continue;
+ }
+
+ // Implicit feature for the base.
+ final int targetSplitIdx;
+ final String configForSplit = pkg.configForSplit[splitIdx];
+ if (configForSplit != null) {
+ final int depIdx = Arrays.binarySearch(pkg.splitNames, configForSplit);
+ if (depIdx < 0) {
+ throw new SplitDependencyLoader.IllegalDependencyException(
+ "Split '" + pkg.splitNames[splitIdx] + "' targets split '"
+ + configForSplit + "', which is missing.");
+ }
+
+ if (!pkg.isFeatureSplits[depIdx]) {
+ throw new SplitDependencyLoader.IllegalDependencyException(
+ "Split '" + pkg.splitNames[splitIdx] + "' declares itself as "
+ + "configuration split for a non-feature split '"
+ + pkg.splitNames[depIdx] + "'");
+ }
+ targetSplitIdx = depIdx + 1;
+ } else {
+ targetSplitIdx = 0;
+ }
+ splitDependencies.put(targetSplitIdx,
+ append(splitDependencies.get(targetSplitIdx), splitIdx + 1));
+ }
+
+ // Verify that there are no cycles.
+ final BitSet bitset = new BitSet();
+ for (int i = 0, size = splitDependencies.size(); i < size; i++) {
+ int splitIdx = splitDependencies.keyAt(i);
+
+ bitset.clear();
+ while (splitIdx != -1) {
+ // Check if this split has been visited yet.
+ if (bitset.get(splitIdx)) {
+ throw new SplitDependencyLoader.IllegalDependencyException(
+ "Cycle detected in split dependencies.");
+ }
+
+ // Mark the split so that if we visit it again, we no there is a cycle.
+ bitset.set(splitIdx);
+
+ // Follow the first dependency only, the others are leaves by definition.
+ final int[] deps = splitDependencies.get(splitIdx);
+ splitIdx = deps != null ? deps[0] : -1;
+ }
+ }
+ return splitDependencies;
+ }
+ }
+
+ /**
+ * Loads the base and split APKs into a single AssetManager.
+ * @hide
+ * @deprecated Do not use. New changes should use
+ * {@link android.content.pm.split.DefaultSplitAssetLoader} instead.
+ */
+ @Deprecated
+ private static class DefaultSplitAssetLoader implements SplitAssetLoader {
+ private final String mBaseCodePath;
+ private final String[] mSplitCodePaths;
+ private final @ParseFlags int mFlags;
+ private AssetManager mCachedAssetManager;
+
+ DefaultSplitAssetLoader(PackageLite pkg, @ParseFlags int flags) {
+ mBaseCodePath = pkg.baseCodePath;
+ mSplitCodePaths = pkg.splitCodePaths;
+ mFlags = flags;
+ }
+
+ private static ApkAssets loadApkAssets(String path, @ParseFlags int flags)
+ throws PackageParserException {
+ if ((flags & PackageParser.PARSE_MUST_BE_APK) != 0 && !PackageParser.isApkPath(path)) {
+ throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
+ "Invalid package file: " + path);
+ }
+
+ try {
+ return ApkAssets.loadFromPath(path);
+ } catch (IOException e) {
+ throw new PackageParserException(INSTALL_FAILED_INVALID_APK,
+ "Failed to load APK at path " + path, e);
+ }
+ }
+
+ @Override
+ public AssetManager getBaseAssetManager() throws PackageParserException {
+ if (mCachedAssetManager != null) {
+ return mCachedAssetManager;
+ }
+
+ ApkAssets[] apkAssets = new ApkAssets[(mSplitCodePaths != null
+ ? mSplitCodePaths.length : 0) + 1];
+
+ // Load the base.
+ int splitIdx = 0;
+ apkAssets[splitIdx++] = loadApkAssets(mBaseCodePath, mFlags);
+
+ // Load any splits.
+ if (!ArrayUtils.isEmpty(mSplitCodePaths)) {
+ for (String apkPath : mSplitCodePaths) {
+ apkAssets[splitIdx++] = loadApkAssets(apkPath, mFlags);
+ }
+ }
+
+ AssetManager assets = new AssetManager();
+ assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ Build.VERSION.RESOURCES_SDK_INT);
+ assets.setApkAssets(apkAssets, false /*invalidateCaches*/);
+
+ mCachedAssetManager = assets;
+ return mCachedAssetManager;
+ }
+
+ @Override
+ public AssetManager getSplitAssetManager(int splitIdx) throws PackageParserException {
+ return getBaseAssetManager();
+ }
+
+ @Override
+ public void close() throws Exception {
+ IoUtils.closeQuietly(mCachedAssetManager);
+ }
+ }
+
+ /**
+ * Loads AssetManagers for splits and their dependencies. This SplitAssetLoader implementation
+ * is to be used when an application opts-in to isolated split loading.
+ * @hide
+ * @deprecated Do not use. New changes should use
+ * {@link android.content.pm.split.SplitAssetDependencyLoader} instead.
+ */
+ @Deprecated
+ private static class SplitAssetDependencyLoader extends
+ SplitDependencyLoader<PackageParserException> implements SplitAssetLoader {
+ private final String[] mSplitPaths;
+ private final @ParseFlags int mFlags;
+ private final ApkAssets[][] mCachedSplitApks;
+ private final AssetManager[] mCachedAssetManagers;
+
+ SplitAssetDependencyLoader(PackageLite pkg,
+ SparseArray<int[]> dependencies, @ParseFlags int flags) {
+ super(dependencies);
+
+ // The base is inserted into index 0, so we need to shift all the splits by 1.
+ mSplitPaths = new String[pkg.splitCodePaths.length + 1];
+ mSplitPaths[0] = pkg.baseCodePath;
+ System.arraycopy(pkg.splitCodePaths, 0, mSplitPaths, 1, pkg.splitCodePaths.length);
+
+ mFlags = flags;
+ mCachedSplitApks = new ApkAssets[mSplitPaths.length][];
+ mCachedAssetManagers = new AssetManager[mSplitPaths.length];
+ }
+
+ @Override
+ protected boolean isSplitCached(int splitIdx) {
+ return mCachedAssetManagers[splitIdx] != null;
+ }
+
+ private static ApkAssets loadApkAssets(String path, @ParseFlags int flags)
+ throws PackageParserException {
+ if ((flags & PackageParser.PARSE_MUST_BE_APK) != 0 && !PackageParser.isApkPath(path)) {
+ throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
+ "Invalid package file: " + path);
+ }
+
+ try {
+ return ApkAssets.loadFromPath(path);
+ } catch (IOException e) {
+ throw new PackageParserException(PackageManager.INSTALL_FAILED_INVALID_APK,
+ "Failed to load APK at path " + path, e);
+ }
+ }
+
+ private static AssetManager createAssetManagerWithAssets(ApkAssets[] apkAssets) {
+ final AssetManager assets = new AssetManager();
+ assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ Build.VERSION.RESOURCES_SDK_INT);
+ assets.setApkAssets(apkAssets, false /*invalidateCaches*/);
+ return assets;
+ }
+
+ @Override
+ protected void constructSplit(int splitIdx, @NonNull int[] configSplitIndices,
+ int parentSplitIdx) throws PackageParserException {
+ final ArrayList<ApkAssets> assets = new ArrayList<>();
+
+ // Include parent ApkAssets.
+ if (parentSplitIdx >= 0) {
+ Collections.addAll(assets, mCachedSplitApks[parentSplitIdx]);
+ }
+
+ // Include this ApkAssets.
+ assets.add(loadApkAssets(mSplitPaths[splitIdx], mFlags));
+
+ // Load and include all config splits for this feature.
+ for (int configSplitIdx : configSplitIndices) {
+ assets.add(loadApkAssets(mSplitPaths[configSplitIdx], mFlags));
+ }
+
+ // Cache the results.
+ mCachedSplitApks[splitIdx] = assets.toArray(new ApkAssets[assets.size()]);
+ mCachedAssetManagers[splitIdx] = createAssetManagerWithAssets(
+ mCachedSplitApks[splitIdx]);
+ }
+
+ @Override
+ public AssetManager getBaseAssetManager() throws PackageParserException {
+ loadDependenciesForSplit(0);
+ return mCachedAssetManagers[0];
+ }
+
+ @Override
+ public AssetManager getSplitAssetManager(int idx) throws PackageParserException {
+ // Since we insert the base at position 0, and PackageParser keeps splits separate from
+ // the base, we need to adjust the index.
+ loadDependenciesForSplit(idx + 1);
+ return mCachedAssetManagers[idx + 1];
+ }
+
+ @Override
+ public void close() throws Exception {
+ for (AssetManager assets : mCachedAssetManagers) {
+ IoUtils.closeQuietly(assets);
+ }
+ }
+ }
}
diff --git a/core/java/android/content/pm/dex/DexMetadataHelper.java b/core/java/android/content/pm/dex/DexMetadataHelper.java
index 982fce9..bf35c4d 100644
--- a/core/java/android/content/pm/dex/DexMetadataHelper.java
+++ b/core/java/android/content/pm/dex/DexMetadataHelper.java
@@ -17,11 +17,11 @@
package android.content.pm.dex;
import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_DEX_METADATA;
-import static android.content.pm.PackageParser.APK_FILE_EXTENSION;
+import static android.content.pm.parsing.ApkLiteParseUtils.APK_FILE_EXTENSION;
-import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
+import android.content.pm.parsing.ApkLiteParseUtils;
+import android.content.pm.parsing.PackageLite;
import android.util.ArrayMap;
import android.util.jar.StrictJarFile;
@@ -87,7 +87,7 @@
* NOTE: involves I/O checks.
*/
private static Map<String, String> getPackageDexMetadata(PackageLite pkg) {
- return buildPackageApkToDexMetadataMap(pkg.getAllCodePaths());
+ return buildPackageApkToDexMetadataMap(pkg.getAllApkPaths());
}
/**
@@ -125,7 +125,7 @@
* @throws IllegalArgumentException if the code path is not an .apk.
*/
public static String buildDexMetadataPathForApk(String codePath) {
- if (!PackageParser.isApkPath(codePath)) {
+ if (!ApkLiteParseUtils.isApkPath(codePath)) {
throw new IllegalStateException(
"Corrupted package. Code path is not an apk " + codePath);
}
@@ -140,7 +140,7 @@
* extension (e.g. 'foo.dm' will match 'foo' or 'foo.apk').
*/
private static String buildDexMetadataPathForFile(File targetFile) {
- return PackageParser.isApkFile(targetFile)
+ return ApkLiteParseUtils.isApkFile(targetFile)
? buildDexMetadataPathForApk(targetFile.getPath())
: targetFile.getPath() + DEX_METADATA_FILE_EXTENSION;
}
@@ -179,7 +179,7 @@
public static void validateDexPaths(String[] paths) {
ArrayList<String> apks = new ArrayList<>();
for (int i = 0; i < paths.length; i++) {
- if (PackageParser.isApkPath(paths[i])) {
+ if (ApkLiteParseUtils.isApkPath(paths[i])) {
apks.add(paths[i]);
}
}
diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
index 51b81b6..a3c2cbc 100644
--- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
+++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
@@ -66,6 +66,8 @@
private static final int PARSE_DEFAULT_INSTALL_LOCATION =
PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+ private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
+
public static final String APK_FILE_EXTENSION = ".apk";
/**
@@ -79,7 +81,7 @@
*
* @see PackageParser#parsePackage(File, int)
*/
- public static ParseResult<PackageParser.PackageLite> parsePackageLite(ParseInput input,
+ public static ParseResult<PackageLite> parsePackageLite(ParseInput input,
File packageFile, int flags) {
if (packageFile.isDirectory()) {
return parseClusterPackageLite(input, packageFile, flags);
@@ -88,26 +90,32 @@
}
}
- public static ParseResult<PackageParser.PackageLite> parseMonolithicPackageLite(
- ParseInput input, File packageFile, int flags) {
+ /**
+ * Parse lightweight details about a single APK files.
+ */
+ public static ParseResult<PackageLite> parseMonolithicPackageLite(ParseInput input,
+ File packageFile, int flags) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
try {
- ParseResult<PackageParser.ApkLite> result = parseApkLite(input, packageFile, flags);
+ final ParseResult<ApkLite> result = parseApkLite(input, packageFile, flags);
if (result.isError()) {
return input.error(result);
}
- final PackageParser.ApkLite baseApk = result.getResult();
+ final ApkLite baseApk = result.getResult();
final String packagePath = packageFile.getAbsolutePath();
return input.success(
- new PackageParser.PackageLite(packagePath, baseApk.codePath, baseApk, null,
+ new PackageLite(packagePath, baseApk.getPath(), baseApk, null,
null, null, null, null, null));
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
- public static ParseResult<PackageParser.PackageLite> parseClusterPackageLite(ParseInput input,
+ /**
+ * Parse lightweight details about a directory of APKs.
+ */
+ public static ParseResult<PackageLite> parseClusterPackageLite(ParseInput input,
File packageDir, int flags) {
final File[] files = packageDir.listFiles();
if (ArrayUtils.isEmpty(files)) {
@@ -122,39 +130,39 @@
String packageName = null;
int versionCode = 0;
- final ArrayMap<String, PackageParser.ApkLite> apks = new ArrayMap<>();
+ final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
try {
for (File file : files) {
- if (PackageParser.isApkFile(file)) {
- ParseResult<PackageParser.ApkLite> result = parseApkLite(input, file, flags);
+ if (isApkFile(file)) {
+ final ParseResult<ApkLite> result = parseApkLite(input, file, flags);
if (result.isError()) {
return input.error(result);
}
- final PackageParser.ApkLite lite = result.getResult();
+ final ApkLite lite = result.getResult();
// Assert that all package names and version codes are
// consistent with the first one we encounter.
if (packageName == null) {
- packageName = lite.packageName;
- versionCode = lite.versionCode;
+ packageName = lite.getPackageName();
+ versionCode = lite.getVersionCode();
} else {
- if (!packageName.equals(lite.packageName)) {
+ if (!packageName.equals(lite.getPackageName())) {
return input.error(PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST,
- "Inconsistent package " + lite.packageName + " in " + file
+ "Inconsistent package " + lite.getPackageName() + " in " + file
+ "; expected " + packageName);
}
- if (versionCode != lite.versionCode) {
+ if (versionCode != lite.getVersionCode()) {
return input.error(PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST,
- "Inconsistent version " + lite.versionCode + " in " + file
+ "Inconsistent version " + lite.getVersionCode() + " in " + file
+ "; expected " + versionCode);
}
}
// Assert that each split is defined only oncuses-static-libe
- if (apks.put(lite.splitName, lite) != null) {
+ if (apks.put(lite.getSplitName(), lite) != null) {
return input.error(PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST,
- "Split name " + lite.splitName
+ "Split name " + lite.getSplitName()
+ " defined more than once; most recent was " + file);
}
}
@@ -163,7 +171,7 @@
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
- final PackageParser.ApkLite baseApk = apks.remove(null);
+ final ApkLite baseApk = apks.remove(null);
return composePackageLiteFromApks(input, packageDir, baseApk, apks);
}
@@ -176,9 +184,8 @@
* @param splitApks Parsed split APKs
* @return PackageLite
*/
- public static ParseResult<PackageParser.PackageLite> composePackageLiteFromApks(
- ParseInput input, File packageDir, PackageParser.ApkLite baseApk,
- ArrayMap<String, PackageParser.ApkLite> splitApks) {
+ public static ParseResult<PackageLite> composePackageLiteFromApks(ParseInput input,
+ File packageDir, ApkLite baseApk, ArrayMap<String, ApkLite> splitApks) {
return composePackageLiteFromApks(input, packageDir, baseApk, splitApks, false);
}
@@ -192,9 +199,9 @@
* @param apkRenamed Indicate whether the APKs are renamed after parsed.
* @return PackageLite
*/
- public static ParseResult<PackageParser.PackageLite> composePackageLiteFromApks(
- ParseInput input, File packageDir, PackageParser.ApkLite baseApk,
- ArrayMap<String, PackageParser.ApkLite> splitApks, boolean apkRenamed) {
+ public static ParseResult<PackageLite> composePackageLiteFromApks(
+ ParseInput input, File packageDir, ApkLite baseApk,
+ ArrayMap<String, ApkLite> splitApks, boolean apkRenamed) {
if (baseApk == null) {
return input.error(PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST,
"Missing base APK in " + packageDir);
@@ -217,26 +224,25 @@
splitRevisionCodes = new int[size];
splitNames = splitApks.keySet().toArray(splitNames);
- Arrays.sort(splitNames, PackageParser.sSplitNameComparator);
+ Arrays.sort(splitNames, sSplitNameComparator);
for (int i = 0; i < size; i++) {
- final PackageParser.ApkLite apk = splitApks.get(splitNames[i]);
- usesSplitNames[i] = apk.usesSplitName;
- isFeatureSplits[i] = apk.isFeatureSplit;
- configForSplits[i] = apk.configForSplit;
+ final ApkLite apk = splitApks.get(splitNames[i]);
+ usesSplitNames[i] = apk.getUsesSplitName();
+ isFeatureSplits[i] = apk.isFeatureSplit();
+ configForSplits[i] = apk.getConfigForSplit();
splitCodePaths[i] = apkRenamed ? new File(packageDir,
- splitNameToFileName(apk)).getAbsolutePath() : apk.codePath;
- splitRevisionCodes[i] = apk.revisionCode;
+ splitNameToFileName(apk)).getAbsolutePath() : apk.getPath();
+ splitRevisionCodes[i] = apk.getRevisionCode();
}
}
final String codePath = packageDir.getAbsolutePath();
final String baseCodePath = apkRenamed ? new File(packageDir,
- splitNameToFileName(baseApk)).getAbsolutePath() : baseApk.codePath;
+ splitNameToFileName(baseApk)).getAbsolutePath() : baseApk.getPath();
return input.success(
- new PackageParser.PackageLite(codePath, baseCodePath, baseApk, splitNames,
- isFeatureSplits, usesSplitNames, configForSplits, splitCodePaths,
- splitRevisionCodes));
+ new PackageLite(codePath, baseCodePath, baseApk, splitNames, isFeatureSplits,
+ usesSplitNames, configForSplits, splitCodePaths, splitRevisionCodes));
}
/**
@@ -245,9 +251,9 @@
* @param apk Parsed APK
* @return The canonical file name
*/
- public static String splitNameToFileName(@NonNull PackageParser.ApkLite apk) {
+ public static String splitNameToFileName(@NonNull ApkLite apk) {
Objects.requireNonNull(apk);
- final String fileName = apk.splitName == null ? "base" : "split_" + apk.splitName;
+ final String fileName = apk.getSplitName() == null ? "base" : "split_" + apk.getSplitName();
return fileName + APK_FILE_EXTENSION;
}
@@ -257,10 +263,9 @@
*
* @param apkFile path to a single APK
* @param flags optional parse flags, such as
- * {@link PackageParser#PARSE_COLLECT_CERTIFICATES}
+ * {@link ParsingPackageUtils#PARSE_COLLECT_CERTIFICATES}
*/
- public static ParseResult<PackageParser.ApkLite> parseApkLite(ParseInput input, File apkFile,
- int flags) {
+ public static ParseResult<ApkLite> parseApkLite(ParseInput input, File apkFile, int flags) {
return parseApkLiteInner(input, apkFile, null, null, flags);
}
@@ -271,14 +276,14 @@
* @param fd already open file descriptor of an apk file
* @param debugPathName arbitrary text name for this file, for debug output
* @param flags optional parse flags, such as
- * {@link PackageParser#PARSE_COLLECT_CERTIFICATES}
+ * {@link ParsingPackageUtils#PARSE_COLLECT_CERTIFICATES}
*/
- public static ParseResult<PackageParser.ApkLite> parseApkLite(ParseInput input,
+ public static ParseResult<ApkLite> parseApkLite(ParseInput input,
FileDescriptor fd, String debugPathName, int flags) {
return parseApkLiteInner(input, null, fd, debugPathName, flags);
}
- private static ParseResult<PackageParser.ApkLite> parseApkLiteInner(ParseInput input,
+ private static ParseResult<ApkLite> parseApkLiteInner(ParseInput input,
File apkFile, FileDescriptor fd, String debugPathName, int flags) {
final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();
@@ -294,11 +299,11 @@
"Failed to parse " + apkPath, e);
}
- parser = apkAssets.openXml(PackageParser.ANDROID_MANIFEST_FILENAME);
+ parser = apkAssets.openXml(ParsingPackageUtils.ANDROID_MANIFEST_FILENAME);
final PackageParser.SigningDetails signingDetails;
- if ((flags & PackageParser.PARSE_COLLECT_CERTIFICATES) != 0) {
- final boolean skipVerify = (flags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0;
+ if ((flags & ParsingPackageUtils.PARSE_COLLECT_CERTIFICATES) != 0) {
+ final boolean skipVerify = (flags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) != 0;
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
try {
ParseResult<PackageParser.SigningDetails> result =
@@ -335,9 +340,8 @@
}
}
- private static ParseResult<PackageParser.ApkLite> parseApkLite(ParseInput input,
- String codePath, XmlPullParser parser, AttributeSet attrs,
- PackageParser.SigningDetails signingDetails)
+ private static ParseResult<ApkLite> parseApkLite(ParseInput input, String codePath,
+ XmlPullParser parser, AttributeSet attrs, PackageParser.SigningDetails signingDetails)
throws IOException, XmlPullParserException {
ParseResult<Pair<String, String>> result = parsePackageSplitNames(input, parser, attrs);
if (result.isError()) {
@@ -421,12 +425,12 @@
continue;
}
- if (PackageParser.TAG_PACKAGE_VERIFIER.equals(parser.getName())) {
+ if (ParsingPackageUtils.TAG_PACKAGE_VERIFIER.equals(parser.getName())) {
final VerifierInfo verifier = parseVerifier(attrs);
if (verifier != null) {
verifiers.add(verifier);
}
- } else if (PackageParser.TAG_APPLICATION.equals(parser.getName())) {
+ } else if (ParsingPackageUtils.TAG_APPLICATION.equals(parser.getName())) {
for (int i = 0; i < attrs.getAttributeCount(); ++i) {
final String attr = attrs.getAttributeName(i);
switch (attr) {
@@ -464,7 +468,7 @@
continue;
}
- if (PackageParser.TAG_PROFILEABLE.equals(parser.getName())) {
+ if (ParsingPackageUtils.TAG_PROFILEABLE.equals(parser.getName())) {
for (int i = 0; i < attrs.getAttributeCount(); ++i) {
final String attr = attrs.getAttributeName(i);
if ("shell".equals(attr)) {
@@ -474,7 +478,7 @@
}
}
}
- } else if (PackageParser.TAG_OVERLAY.equals(parser.getName())) {
+ } else if (ParsingPackageUtils.TAG_OVERLAY.equals(parser.getName())) {
for (int i = 0; i < attrs.getAttributeCount(); ++i) {
final String attr = attrs.getAttributeName(i);
if ("requiredSystemPropertyName".equals(attr)) {
@@ -489,7 +493,7 @@
overlayPriority = attrs.getAttributeIntValue(i, 0);
}
}
- } else if (PackageParser.TAG_USES_SPLIT.equals(parser.getName())) {
+ } else if (ParsingPackageUtils.TAG_USES_SPLIT.equals(parser.getName())) {
if (usesSplitName != null) {
Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
continue;
@@ -500,7 +504,7 @@
return input.error(PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
"<uses-split> tag requires 'android:name' attribute");
}
- } else if (PackageParser.TAG_USES_SDK.equals(parser.getName())) {
+ } else if (ParsingPackageUtils.TAG_USES_SDK.equals(parser.getName())) {
for (int i = 0; i < attrs.getAttributeCount(); ++i) {
final String attr = attrs.getAttributeName(i);
if ("targetSdkVersion".equals(attr)) {
@@ -526,8 +530,8 @@
}
return input.success(
- new PackageParser.ApkLite(codePath, packageSplit.first, packageSplit.second,
- isFeatureSplit, configForSplit, usesSplitName, isSplitRequired, versionCode,
+ new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
+ configForSplit, usesSplitName, isSplitRequired, versionCode,
versionCodeMajor, revisionCode, installLocation, verifiers, signingDetails,
coreApp, debuggable, profilableByShell, multiArch, use32bitAbi,
useEmbeddedDex, extractNativeLibs, isolatedSplits, targetPackage,
@@ -546,7 +550,7 @@
return input.error(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
"No start tag found");
}
- if (!parser.getName().equals(PackageParser.TAG_MANIFEST)) {
+ if (!parser.getName().equals(ParsingPackageUtils.TAG_MANIFEST)) {
return input.error(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
"No <manifest> tag");
}
@@ -625,4 +629,24 @@
}
}
}
+
+ /**
+ * Check if the given file is an APK file.
+ *
+ * @param file the file to check.
+ * @return {@code true} if the given file is an APK file.
+ */
+ public static boolean isApkFile(File file) {
+ return isApkPath(file.getName());
+ }
+
+ /**
+ * Check if the given path ends with APK file extension.
+ *
+ * @param path the path to check.
+ * @return {@code true} if the given path ends with APK file extension.
+ */
+ public static boolean isApkPath(String path) {
+ return path.endsWith(APK_FILE_EXTENSION);
+ }
}
diff --git a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
index f8fd4a5..b7365b3 100644
--- a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
+++ b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
@@ -385,7 +385,7 @@
}
// CompatibilityMode is global state.
- if (!PackageParser.sCompatibilityModeEnabled) {
+ if (!ParsingPackageUtils.sCompatibilityModeEnabled) {
ai.disableCompatibilityMode();
}
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index 38d3940..51ec297 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -335,7 +335,7 @@
private int fullBackupContent;
private int iconRes;
- private int installLocation = PackageParser.PARSE_DEFAULT_INSTALL_LOCATION;
+ private int installLocation = ParsingPackageUtils.PARSE_DEFAULT_INSTALL_LOCATION;
private int labelRes;
private int largestWidthLimitDp;
private int logo;
@@ -1013,7 +1013,8 @@
// TODO(b/135203078): See ParsingPackageImpl#getHiddenApiEnforcementPolicy
// appInfo.mHiddenApiPolicy
// appInfo.hiddenUntilInstalled
- appInfo.icon = (PackageParser.sUseRoundIcon && roundIconRes != 0) ? roundIconRes : iconRes;
+ appInfo.icon =
+ (ParsingPackageUtils.sUseRoundIcon && roundIconRes != 0) ? roundIconRes : iconRes;
appInfo.iconRes = iconRes;
appInfo.roundIconRes = roundIconRes;
appInfo.installLocation = installLocation;
diff --git a/core/java/android/content/pm/parsing/ParsingPackageRead.java b/core/java/android/content/pm/parsing/ParsingPackageRead.java
index 13ae7a2..a102e82 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageRead.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageRead.java
@@ -66,7 +66,7 @@
/**
* The names of packages to adopt ownership of permissions from, parsed under
- * {@link PackageParser#TAG_ADOPT_PERMISSIONS}.
+ * {@link ParsingPackageUtils#TAG_ADOPT_PERMISSIONS}.
* @see R.styleable#AndroidManifestOriginalPackage_name
*/
@NonNull
@@ -105,7 +105,7 @@
/**
* For use with {@link com.android.server.pm.KeySetManagerService}. Parsed in
- * {@link PackageParser#TAG_KEY_SETS}.
+ * {@link ParsingPackageUtils#TAG_KEY_SETS}.
* @see R.styleable#AndroidManifestKeySet
* @see R.styleable#AndroidManifestPublicKey
*/
@@ -816,7 +816,7 @@
/**
* For use with {@link com.android.server.pm.KeySetManagerService}. Parsed in
- * {@link PackageParser#TAG_KEY_SETS}.
+ * {@link ParsingPackageUtils#TAG_KEY_SETS}.
* @see R.styleable#AndroidManifestUpgradeKeySet
*/
@NonNull
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index 494b3cc..b054304 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -189,6 +189,12 @@
PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
public static final int PARSE_DEFAULT_TARGET_SANDBOX = 1;
+ /** If set to true, we will only allow package files that exactly match
+ * the DTD. Otherwise, we try to get as much from the package as we
+ * can without failing. This should normally be set to false, to
+ * support extensions to the DTD in future versions. */
+ public static final boolean RIGID_PARSER = false;
+
public static final int PARSE_MUST_BE_APK = 1 << 0;
public static final int PARSE_IGNORE_PROCESSES = 1 << 1;
public static final int PARSE_EXTERNAL_STORAGE = 1 << 3;
@@ -220,7 +226,7 @@
*/
@NonNull
public static ParseResult<ParsingPackage> parseDefaultOneTime(File file,
- @PackageParser.ParseFlags int parseFlags, boolean collectCertificates) {
+ @ParseFlags int parseFlags, boolean collectCertificates) {
ParseInput input = ParseTypeImpl.forDefaultParsing().reset();
return parseDefault(input, file, parseFlags, collectCertificates);
}
@@ -232,7 +238,7 @@
*/
@NonNull
public static ParseResult<ParsingPackage> parseDefault(ParseInput input, File file,
- @PackageParser.ParseFlags int parseFlags, boolean collectCertificates) {
+ @ParseFlags int parseFlags, boolean collectCertificates) {
ParseResult<ParsingPackage> result;
ParsingPackageUtils parser = new ParsingPackageUtils(false, null, null, new Callback() {
@@ -334,14 +340,14 @@
*/
private ParseResult<ParsingPackage> parseClusterPackage(ParseInput input, File packageDir,
int flags) {
- ParseResult<PackageParser.PackageLite> liteResult =
+ final ParseResult<PackageLite> liteResult =
ApkLiteParseUtils.parseClusterPackageLite(input, packageDir, 0);
if (liteResult.isError()) {
return input.error(liteResult);
}
- final PackageParser.PackageLite lite = liteResult.getResult();
- if (mOnlyCoreApps && !lite.coreApp) {
+ final PackageLite lite = liteResult.getResult();
+ if (mOnlyCoreApps && !lite.isCoreApp()) {
return input.error(INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED,
"Not a coreApp: " + packageDir);
}
@@ -349,7 +355,7 @@
// Build the split dependency tree.
SparseArray<int[]> splitDependencies = null;
final SplitAssetLoader assetLoader;
- if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) {
+ if (lite.isIsolatedSplits() && !ArrayUtils.isEmpty(lite.getSplitNames())) {
try {
splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite);
assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags);
@@ -362,22 +368,22 @@
try {
final AssetManager assets = assetLoader.getBaseAssetManager();
- final File baseApk = new File(lite.baseCodePath);
- ParseResult<ParsingPackage> result = parseBaseApk(input, baseApk,
- lite.codePath, assets, flags);
+ final File baseApk = new File(lite.getBaseApkPath());
+ final ParseResult<ParsingPackage> result = parseBaseApk(input, baseApk,
+ lite.getPath(), assets, flags);
if (result.isError()) {
return input.error(result);
}
ParsingPackage pkg = result.getResult();
- if (!ArrayUtils.isEmpty(lite.splitNames)) {
+ if (!ArrayUtils.isEmpty(lite.getSplitNames())) {
pkg.asSplit(
- lite.splitNames,
- lite.splitCodePaths,
- lite.splitRevisionCodes,
+ lite.getSplitNames(),
+ lite.getSplitApkPaths(),
+ lite.getSplitRevisionCodes(),
splitDependencies
);
- final int num = lite.splitNames.length;
+ final int num = lite.getSplitNames().length;
for (int i = 0; i < num; i++) {
final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
@@ -385,11 +391,11 @@
}
}
- pkg.setUse32BitAbi(lite.use32bitAbi);
+ pkg.setUse32BitAbi(lite.isUse32bitAbi());
return input.success(pkg);
} catch (PackageParserException e) {
return input.error(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
- "Failed to load assets: " + lite.baseCodePath, e);
+ "Failed to load assets: " + lite.getBaseApkPath(), e);
} finally {
IoUtils.closeQuietly(assetLoader);
}
@@ -403,21 +409,21 @@
*/
private ParseResult<ParsingPackage> parseMonolithicPackage(ParseInput input, File apkFile,
int flags) throws PackageParserException {
- ParseResult<PackageParser.PackageLite> liteResult =
+ final ParseResult<PackageLite> liteResult =
ApkLiteParseUtils.parseMonolithicPackageLite(input, apkFile, flags);
if (liteResult.isError()) {
return input.error(liteResult);
}
- final PackageParser.PackageLite lite = liteResult.getResult();
- if (mOnlyCoreApps && !lite.coreApp) {
+ final PackageLite lite = liteResult.getResult();
+ if (mOnlyCoreApps && !lite.isCoreApp()) {
return input.error(INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED,
"Not a coreApp: " + apkFile);
}
final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
try {
- ParseResult<ParsingPackage> result = parseBaseApk(input,
+ final ParseResult<ParsingPackage> result = parseBaseApk(input,
apkFile,
apkFile.getCanonicalPath(),
assetLoader.getBaseAssetManager(), flags);
@@ -426,7 +432,7 @@
}
return input.success(result.getResult()
- .setUse32BitAbi(lite.use32bitAbi));
+ .setUse32BitAbi(lite.isUse32bitAbi()));
} catch (IOException e) {
return input.error(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
"Failed to get path: " + apkFile, e);
@@ -440,12 +446,12 @@
final String apkPath = apkFile.getAbsolutePath();
String volumeUuid = null;
- if (apkPath.startsWith(PackageParser.MNT_EXPAND)) {
- final int end = apkPath.indexOf('/', PackageParser.MNT_EXPAND.length());
- volumeUuid = apkPath.substring(PackageParser.MNT_EXPAND.length(), end);
+ if (apkPath.startsWith(MNT_EXPAND)) {
+ final int end = apkPath.indexOf('/', MNT_EXPAND.length());
+ volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
}
- if (PackageParser.DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
+ if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
final int cookie = assets.findCookieForPath(apkPath);
if (cookie == 0) {
@@ -454,7 +460,7 @@
}
try (XmlResourceParser parser = assets.openXmlResourceParser(cookie,
- PackageParser.ANDROID_MANIFEST_FILENAME)) {
+ ANDROID_MANIFEST_FILENAME)) {
final Resources res = new Resources(assets, mDisplayMetrics, null);
ParseResult<ParsingPackage> result = parseBaseApk(input, apkPath, codePath, res,
@@ -495,7 +501,7 @@
pkg.setVolumeUuid(volumeUuid);
- if ((flags & PackageParser.PARSE_COLLECT_CERTIFICATES) != 0) {
+ if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
pkg.setSigningDetails(getSigningDetails(pkg, false));
} else {
pkg.setSigningDetails(SigningDetails.UNKNOWN);
@@ -512,7 +518,7 @@
ParsingPackage pkg, int splitIndex, AssetManager assets, int flags) {
final String apkPath = pkg.getSplitCodePaths()[splitIndex];
- if (PackageParser.DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
+ if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
// This must always succeed, as the path has been added to the AssetManager before.
final int cookie = assets.findCookieForPath(apkPath);
@@ -521,7 +527,7 @@
"Failed adding asset path: " + apkPath);
}
try (XmlResourceParser parser = assets.openXmlResourceParser(cookie,
- PackageParser.ANDROID_MANIFEST_FILENAME)) {
+ ANDROID_MANIFEST_FILENAME)) {
Resources res = new Resources(assets, mDisplayMetrics, null);
ParseResult<ParsingPackage> parseResult = parseSplitApk(input, pkg, res,
parser, flags, splitIndex);
@@ -620,9 +626,9 @@
final ParseResult result;
String tagName = parser.getName();
- if (PackageParser.TAG_APPLICATION.equals(tagName)) {
+ if (TAG_APPLICATION.equals(tagName)) {
if (foundApp) {
- if (PackageParser.RIGID_PARSER) {
+ if (RIGID_PARSER) {
result = input.error("<manifest> has more than one <application>");
} else {
Slog.w(TAG, "<manifest> has more than one <application>");
@@ -701,7 +707,7 @@
ParseResult<ParsedActivity> activityResult =
ParsedActivityUtils.parseActivityOrReceiver(mSeparateProcesses, pkg,
res,
- parser, flags, PackageParser.sUseRoundIcon, input);
+ parser, flags, sUseRoundIcon, input);
if (activityResult.isSuccess()) {
ParsedActivity activity = activityResult.getResult();
if (isActivity) {
@@ -716,7 +722,7 @@
case "service":
ParseResult<ParsedService> serviceResult = ParsedServiceUtils.parseService(
mSeparateProcesses, pkg, res, parser, flags,
- PackageParser.sUseRoundIcon, input);
+ sUseRoundIcon, input);
if (serviceResult.isSuccess()) {
ParsedService service = serviceResult.getResult();
pkg.addService(service);
@@ -727,7 +733,7 @@
case "provider":
ParseResult<ParsedProvider> providerResult =
ParsedProviderUtils.parseProvider(mSeparateProcesses, pkg, res, parser,
- flags, PackageParser.sUseRoundIcon, input);
+ flags, sUseRoundIcon, input);
if (providerResult.isSuccess()) {
ParsedProvider provider = providerResult.getResult();
pkg.addProvider(provider);
@@ -737,7 +743,7 @@
break;
case "activity-alias":
activityResult = ParsedActivityUtils.parseActivityAlias(pkg, res, parser,
- PackageParser.sUseRoundIcon, input);
+ sUseRoundIcon, input);
if (activityResult.isSuccess()) {
ParsedActivity activity = activityResult.getResult();
pkg.addActivity(activity);
@@ -815,12 +821,12 @@
return sharedUserResult;
}
- pkg.setInstallLocation(anInteger(PackageParser.PARSE_DEFAULT_INSTALL_LOCATION,
+ pkg.setInstallLocation(anInteger(PARSE_DEFAULT_INSTALL_LOCATION,
R.styleable.AndroidManifest_installLocation, sa))
- .setTargetSandboxVersion(anInteger(PackageParser.PARSE_DEFAULT_TARGET_SANDBOX,
+ .setTargetSandboxVersion(anInteger(PARSE_DEFAULT_TARGET_SANDBOX,
R.styleable.AndroidManifest_targetSandboxVersion, sa))
/* Set the global "on SD card" flag */
- .setExternalStorage((flags & PackageParser.PARSE_EXTERNAL_STORAGE) != 0);
+ .setExternalStorage((flags & PARSE_EXTERNAL_STORAGE) != 0);
boolean foundApp = false;
final int depth = parser.getDepth();
@@ -836,9 +842,9 @@
final ParseResult result;
// <application> has special logic, so it's handled outside the general method
- if (PackageParser.TAG_APPLICATION.equals(tagName)) {
+ if (TAG_APPLICATION.equals(tagName)) {
if (foundApp) {
- if (PackageParser.RIGID_PARSER) {
+ if (RIGID_PARSER) {
result = input.error("<manifest> has more than one <application>");
} else {
Slog.w(TAG, "<manifest> has more than one <application>");
@@ -897,51 +903,51 @@
ParsingPackage pkg, Resources res, XmlResourceParser parser, int flags)
throws IOException, XmlPullParserException {
switch (tag) {
- case PackageParser.TAG_OVERLAY:
+ case TAG_OVERLAY:
return parseOverlay(input, pkg, res, parser);
- case PackageParser.TAG_KEY_SETS:
+ case TAG_KEY_SETS:
return parseKeySets(input, pkg, res, parser);
case "feature": // TODO moltmann: Remove
- case PackageParser.TAG_ATTRIBUTION:
+ case TAG_ATTRIBUTION:
return parseAttribution(input, pkg, res, parser);
- case PackageParser.TAG_PERMISSION_GROUP:
+ case TAG_PERMISSION_GROUP:
return parsePermissionGroup(input, pkg, res, parser);
- case PackageParser.TAG_PERMISSION:
+ case TAG_PERMISSION:
return parsePermission(input, pkg, res, parser);
- case PackageParser.TAG_PERMISSION_TREE:
+ case TAG_PERMISSION_TREE:
return parsePermissionTree(input, pkg, res, parser);
- case PackageParser.TAG_USES_PERMISSION:
- case PackageParser.TAG_USES_PERMISSION_SDK_M:
- case PackageParser.TAG_USES_PERMISSION_SDK_23:
+ case TAG_USES_PERMISSION:
+ case TAG_USES_PERMISSION_SDK_M:
+ case TAG_USES_PERMISSION_SDK_23:
return parseUsesPermission(input, pkg, res, parser);
- case PackageParser.TAG_USES_CONFIGURATION:
+ case TAG_USES_CONFIGURATION:
return parseUsesConfiguration(input, pkg, res, parser);
- case PackageParser.TAG_USES_FEATURE:
+ case TAG_USES_FEATURE:
return parseUsesFeature(input, pkg, res, parser);
- case PackageParser.TAG_FEATURE_GROUP:
+ case TAG_FEATURE_GROUP:
return parseFeatureGroup(input, pkg, res, parser);
- case PackageParser.TAG_USES_SDK:
+ case TAG_USES_SDK:
return parseUsesSdk(input, pkg, res, parser);
- case PackageParser.TAG_SUPPORT_SCREENS:
+ case TAG_SUPPORT_SCREENS:
return parseSupportScreens(input, pkg, res, parser);
- case PackageParser.TAG_PROTECTED_BROADCAST:
+ case TAG_PROTECTED_BROADCAST:
return parseProtectedBroadcast(input, pkg, res, parser);
- case PackageParser.TAG_INSTRUMENTATION:
+ case TAG_INSTRUMENTATION:
return parseInstrumentation(input, pkg, res, parser);
- case PackageParser.TAG_ORIGINAL_PACKAGE:
+ case TAG_ORIGINAL_PACKAGE:
return parseOriginalPackage(input, pkg, res, parser);
- case PackageParser.TAG_ADOPT_PERMISSIONS:
+ case TAG_ADOPT_PERMISSIONS:
return parseAdoptPermissions(input, pkg, res, parser);
- case PackageParser.TAG_USES_GL_TEXTURE:
- case PackageParser.TAG_COMPATIBLE_SCREENS:
- case PackageParser.TAG_SUPPORTS_INPUT:
- case PackageParser.TAG_EAT_COMMENT:
+ case TAG_USES_GL_TEXTURE:
+ case TAG_COMPATIBLE_SCREENS:
+ case TAG_SUPPORTS_INPUT:
+ case TAG_EAT_COMMENT:
// Just skip this tag
XmlUtils.skipCurrentTag(parser);
return input.success(pkg);
- case PackageParser.TAG_RESTRICT_UPDATE:
+ case TAG_RESTRICT_UPDATE:
return parseRestrictUpdateHash(flags, input, pkg, res, parser);
- case PackageParser.TAG_QUERIES:
+ case TAG_QUERIES:
return parseQueries(input, pkg, res, parser);
default:
return ParsingUtils.unknownTag("<manifest>", pkg, parser, input);
@@ -1125,7 +1131,7 @@
ParsingPackage pkg, Resources res, XmlResourceParser parser)
throws XmlPullParserException, IOException {
ParseResult<ParsedPermissionGroup> result = ParsedPermissionUtils.parsePermissionGroup(
- pkg, res, parser, PackageParser.sUseRoundIcon, input);
+ pkg, res, parser, sUseRoundIcon, input);
if (result.isError()) {
return input.error(result);
}
@@ -1136,7 +1142,7 @@
ParsingPackage pkg, Resources res, XmlResourceParser parser)
throws XmlPullParserException, IOException {
ParseResult<ParsedPermission> result = ParsedPermissionUtils.parsePermission(
- pkg, res, parser, PackageParser.sUseRoundIcon, input);
+ pkg, res, parser, sUseRoundIcon, input);
if (result.isError()) {
return input.error(result);
}
@@ -1147,7 +1153,7 @@
ParsingPackage pkg, Resources res, XmlResourceParser parser)
throws XmlPullParserException, IOException {
ParseResult<ParsedPermission> result = ParsedPermissionUtils.parsePermissionTree(
- pkg, res, parser, PackageParser.sUseRoundIcon, input);
+ pkg, res, parser, sUseRoundIcon, input);
if (result.isError()) {
return input.error(result);
}
@@ -1405,7 +1411,7 @@
private static ParseResult<ParsingPackage> parseUsesSdk(ParseInput input,
ParsingPackage pkg, Resources res, XmlResourceParser parser)
throws IOException, XmlPullParserException {
- if (PackageParser.SDK_VERSION > 0) {
+ if (SDK_VERSION > 0) {
TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesSdk);
try {
int minVers = 1;
@@ -1440,7 +1446,7 @@
}
ParseResult<Integer> targetSdkVersionResult = computeTargetSdkVersion(
- targetVers, targetCode, PackageParser.SDK_CODENAMES, input);
+ targetVers, targetCode, SDK_CODENAMES, input);
if (targetSdkVersionResult.isError()) {
return input.error(targetSdkVersionResult);
}
@@ -1454,7 +1460,7 @@
}
ParseResult<Integer> minSdkVersionResult = computeMinSdkVersion(minVers, minCode,
- PackageParser.SDK_VERSION, PackageParser.SDK_CODENAMES, input);
+ SDK_VERSION, SDK_CODENAMES, input);
if (minSdkVersionResult.isError()) {
return input.error(minSdkVersionResult);
}
@@ -1637,7 +1643,7 @@
private static ParseResult<ParsingPackage> parseRestrictUpdateHash(int flags, ParseInput input,
ParsingPackage pkg, Resources res, XmlResourceParser parser) {
- if ((flags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
+ if ((flags & PARSE_IS_SYSTEM_DIR) != 0) {
TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestRestrictUpdate);
try {
final String hash = sa.getNonConfigurationString(
@@ -1846,7 +1852,7 @@
return input.error("Empty class name in package " + pkgName);
}
- if (PackageParser.DEBUG_BACKUP) {
+ if (DEBUG_BACKUP) {
Slog.v(TAG, "android:backupAgent = " + backupAgentName
+ " from " + pkgName + "+" + backupAgent);
}
@@ -1870,7 +1876,7 @@
fullBackupContent = v.resourceId;
if (v.resourceId == 0) {
- if (PackageParser.DEBUG_BACKUP) {
+ if (DEBUG_BACKUP) {
Slog.v(TAG, "fullBackupContent specified as boolean=" +
(v.data == 0 ? "false" : "true"));
}
@@ -1880,7 +1886,7 @@
pkg.setFullBackupContent(fullBackupContent);
}
- if (PackageParser.DEBUG_BACKUP) {
+ if (DEBUG_BACKUP) {
Slog.v(TAG, "fullBackupContent=" + fullBackupContent + " for " + pkgName);
}
}
@@ -1994,7 +2000,7 @@
case "receiver":
ParseResult<ParsedActivity> activityResult =
ParsedActivityUtils.parseActivityOrReceiver(mSeparateProcesses, pkg,
- res, parser, flags, PackageParser.sUseRoundIcon, input);
+ res, parser, flags, sUseRoundIcon, input);
if (activityResult.isSuccess()) {
ParsedActivity activity = activityResult.getResult();
@@ -2012,7 +2018,7 @@
case "service":
ParseResult<ParsedService> serviceResult =
ParsedServiceUtils.parseService(mSeparateProcesses, pkg, res, parser,
- flags, PackageParser.sUseRoundIcon, input);
+ flags, sUseRoundIcon, input);
if (serviceResult.isSuccess()) {
ParsedService service = serviceResult.getResult();
hasServiceOrder |= (service.getOrder() != 0);
@@ -2024,7 +2030,7 @@
case "provider":
ParseResult<ParsedProvider> providerResult =
ParsedProviderUtils.parseProvider(mSeparateProcesses, pkg, res, parser,
- flags, PackageParser.sUseRoundIcon, input);
+ flags, sUseRoundIcon, input);
if (providerResult.isSuccess()) {
pkg.addProvider(providerResult.getResult());
}
@@ -2033,7 +2039,7 @@
break;
case "activity-alias":
activityResult = ParsedActivityUtils.parseActivityAlias(pkg, res,
- parser, PackageParser.sUseRoundIcon, input);
+ parser, sUseRoundIcon, input);
if (activityResult.isSuccess()) {
ParsedActivity activity = activityResult.getResult();
hasActivityOrder |= (activity.getOrder() != 0);
@@ -2505,8 +2511,7 @@
private static void setMaxAspectRatio(ParsingPackage pkg) {
// Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater.
// NOTE: 16.7:9 was the max aspect ratio Android devices can support pre-O per the CDD.
- float maxAspectRatio = pkg.getTargetSdkVersion() < O
- ? PackageParser.DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0;
+ float maxAspectRatio = pkg.getTargetSdkVersion() < O ? DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0;
float packageMaxAspectRatio = pkg.getMaxAspectRatio();
if (packageMaxAspectRatio != 0) {
@@ -2514,10 +2519,8 @@
maxAspectRatio = packageMaxAspectRatio;
} else {
Bundle appMetaData = pkg.getMetaData();
- if (appMetaData != null && appMetaData.containsKey(
- PackageParser.METADATA_MAX_ASPECT_RATIO)) {
- maxAspectRatio = appMetaData.getFloat(PackageParser.METADATA_MAX_ASPECT_RATIO,
- maxAspectRatio);
+ if (appMetaData != null && appMetaData.containsKey(METADATA_MAX_ASPECT_RATIO)) {
+ maxAspectRatio = appMetaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio);
}
}
@@ -2536,8 +2539,7 @@
// process the meta data here since this method is called at the end of processing
// the application and all meta data is guaranteed.
final float activityAspectRatio = activity.getMetaData() != null
- ? activity.getMetaData().getFloat(PackageParser.METADATA_MAX_ASPECT_RATIO,
- maxAspectRatio)
+ ? activity.getMetaData().getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio)
: maxAspectRatio;
activity.setMaxAspectRatio(activity.getResizeMode(), activityAspectRatio);
@@ -2565,7 +2567,7 @@
private void setSupportsSizeChanges(ParsingPackage pkg) {
final Bundle appMetaData = pkg.getMetaData();
final boolean supportsSizeChanges = appMetaData != null
- && appMetaData.getBoolean(PackageParser.METADATA_SUPPORTS_SIZE_CHANGES, false);
+ && appMetaData.getBoolean(METADATA_SUPPORTS_SIZE_CHANGES, false);
List<ParsedActivity> activities = pkg.getActivities();
int activitiesSize = activities.size();
@@ -2573,7 +2575,7 @@
ParsedActivity activity = activities.get(index);
if (supportsSizeChanges || (activity.getMetaData() != null
&& activity.getMetaData().getBoolean(
- PackageParser.METADATA_SUPPORTS_SIZE_CHANGES, false))) {
+ METADATA_SUPPORTS_SIZE_CHANGES, false))) {
activity.setSupportsSizeChanges(true);
}
}
@@ -2674,7 +2676,7 @@
ParsingPackage pkg, Resources res, XmlResourceParser parser)
throws XmlPullParserException, IOException {
ParseResult<ParsedInstrumentation> result = ParsedInstrumentationUtils.parseInstrumentation(
- pkg, res, parser, PackageParser.sUseRoundIcon, input);
+ pkg, res, parser, sUseRoundIcon, input);
if (result.isError()) {
return input.error(result);
}
@@ -2860,7 +2862,7 @@
} else if (v.type == TypedValue.TYPE_FLOAT) {
property = new Property(name, v.getFloat(), packageName, className);
} else {
- if (!PackageParser.RIGID_PARSER) {
+ if (!RIGID_PARSER) {
Slog.w(TAG,
tagName + " only supports string, integer, float, color, "
+ "boolean, and resource reference types: "
diff --git a/core/java/android/content/pm/parsing/component/ComponentParseUtils.java b/core/java/android/content/pm/parsing/component/ComponentParseUtils.java
index d65f8ff..0403a25 100644
--- a/core/java/android/content/pm/parsing/component/ComponentParseUtils.java
+++ b/core/java/android/content/pm/parsing/component/ComponentParseUtils.java
@@ -22,9 +22,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Intent;
-import android.content.pm.PackageParser;
import android.content.pm.PackageUserState;
import android.content.pm.parsing.ParsingPackage;
+import android.content.pm.parsing.ParsingPackageUtils;
import android.content.pm.parsing.ParsingUtils;
import android.content.pm.parsing.result.ParseInput;
import android.content.pm.parsing.result.ParseResult;
@@ -77,7 +77,7 @@
@NonNull
public static ParseResult<String> buildProcessName(@NonNull String pkg, String defProc,
CharSequence procSeq, int flags, String[] separateProcesses, ParseInput input) {
- if ((flags & PackageParser.PARSE_IGNORE_PROCESSES) != 0 && !"system".contentEquals(
+ if ((flags & ParsingPackageUtils.PARSE_IGNORE_PROCESSES) != 0 && !"system".contentEquals(
procSeq)) {
return input.success(defProc != null ? defProc : pkg);
}
diff --git a/core/java/android/content/pm/parsing/component/ParsedActivity.java b/core/java/android/content/pm/parsing/component/ParsedActivity.java
index 1915028..2ea24f7 100644
--- a/core/java/android/content/pm/parsing/component/ParsedActivity.java
+++ b/core/java/android/content/pm/parsing/component/ParsedActivity.java
@@ -28,7 +28,6 @@
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageParser;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -127,7 +126,7 @@
activity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
activity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NONE;
activity.maxRecents = ActivityTaskManager.getDefaultAppRecentsLimitStatic();
- activity.configChanges = PackageParser.getActivityConfigChanges(0, 0);
+ activity.configChanges = ParsedActivityUtils.getActivityConfigChanges(0, 0);
activity.softInputMode = 0;
activity.persistableMode = ActivityInfo.PERSIST_NEVER;
activity.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
diff --git a/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java b/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java
index f96bd54..f821e08 100644
--- a/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java
@@ -23,8 +23,8 @@
import android.app.ActivityTaskManager;
import android.content.Intent;
import android.content.pm.ActivityInfo;
-import android.content.pm.PackageParser;
import android.content.pm.parsing.ParsingPackage;
+import android.content.pm.parsing.ParsingPackageUtils;
import android.content.pm.parsing.ParsingUtils;
import android.content.pm.parsing.result.ParseInput;
import android.content.pm.parsing.result.ParseInput.DeferredError;
@@ -67,6 +67,12 @@
SAFE_BROADCASTS.add(Intent.ACTION_BOOT_COMPLETED);
}
+ /**
+ * Bit mask of all the valid bits that can be set in recreateOnConfigChanges.
+ */
+ private static final int RECREATE_ON_CONFIG_CHANGES_MASK =
+ ActivityInfo.CONFIG_MCC | ActivityInfo.CONFIG_MNC;
+
@NonNull
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public static ParseResult<ParsedActivity> parseActivityOrReceiver(String[] separateProcesses,
@@ -153,7 +159,7 @@
activity.rotationAnimation = sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED);
activity.softInputMode = sa.getInt(R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
- activity.configChanges = PackageParser.getActivityConfigChanges(
+ activity.configChanges = getActivityConfigChanges(
sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0),
sa.getInt(R.styleable.AndroidManifestActivity_recreateOnConfigChanges, 0));
@@ -345,7 +351,7 @@
if (intent != null) {
activity.order = Math.max(intent.getOrder(), activity.order);
activity.addIntent(intent);
- if (PackageParser.LOG_UNSAFE_BROADCASTS && isReceiver
+ if (LOG_UNSAFE_BROADCASTS && isReceiver
&& pkg.getTargetSdkVersion() >= Build.VERSION_CODES.O) {
int actionCount = intent.countActions();
for (int i = 0; i < actionCount; i++) {
@@ -354,7 +360,7 @@
continue;
}
- if (!PackageParser.SAFE_BROADCASTS.contains(action)) {
+ if (!SAFE_BROADCASTS.contains(action)) {
Slog.w(TAG,
"Broadcast " + action + " may never be delivered to "
+ pkg.getPackageName() + " as requested at: "
@@ -532,7 +538,7 @@
ParsedActivity activity, ParseInput input) {
// There isn't a metadata for us to fall back. Whatever is in layout is correct.
if (activity.metaData == null || !activity.metaData.containsKey(
- PackageParser.METADATA_ACTIVITY_WINDOW_LAYOUT_AFFINITY)) {
+ ParsingPackageUtils.METADATA_ACTIVITY_WINDOW_LAYOUT_AFFINITY)) {
return input.success(activity.windowLayout);
}
@@ -542,7 +548,7 @@
}
String windowLayoutAffinity = activity.metaData.getString(
- PackageParser.METADATA_ACTIVITY_WINDOW_LAYOUT_AFFINITY);
+ ParsingPackageUtils.METADATA_ACTIVITY_WINDOW_LAYOUT_AFFINITY);
ActivityInfo.WindowLayout layout = activity.windowLayout;
if (layout == null) {
layout = new ActivityInfo.WindowLayout(-1 /* width */, -1 /* widthFraction */,
@@ -553,4 +559,14 @@
}
return input.success(layout);
}
+
+ /**
+ * @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml.
+ * @param recreateOnConfigChanges The bit mask recreateOnConfigChanges fetched from
+ * AndroidManifest.xml.
+ * @hide
+ */
+ static int getActivityConfigChanges(int configChanges, int recreateOnConfigChanges) {
+ return configChanges | ((~recreateOnConfigChanges) & RECREATE_ON_CONFIG_CHANGES_MASK);
+ }
}
diff --git a/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java b/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java
index 368dcfd..939e77f 100644
--- a/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java
@@ -21,6 +21,7 @@
import android.content.IntentFilter;
import android.content.pm.PackageParser;
import android.content.pm.parsing.ParsingPackage;
+import android.content.pm.parsing.ParsingPackageUtils;
import android.content.pm.parsing.ParsingUtils;
import android.content.pm.parsing.result.ParseInput;
import android.content.pm.parsing.result.ParseResult;
@@ -65,7 +66,7 @@
}
}
- if (PackageParser.sUseRoundIcon) {
+ if (ParsingPackageUtils.sUseRoundIcon) {
intentInfo.icon = sa.getResourceId(
R.styleable.AndroidManifestIntentFilter_roundIcon, 0);
}
@@ -141,7 +142,7 @@
intentInfo.hasDefault = intentInfo.hasCategory(Intent.CATEGORY_DEFAULT);
- if (PackageParser.DEBUG_PARSER) {
+ if (DEBUG) {
final StringBuilder cats = new StringBuilder("Intent d=");
cats.append(intentInfo.isHasDefault());
cats.append(", cat=");
diff --git a/core/java/android/content/pm/split/DefaultSplitAssetLoader.java b/core/java/android/content/pm/split/DefaultSplitAssetLoader.java
index 9e3a8f4..f3caf60 100644
--- a/core/java/android/content/pm/split/DefaultSplitAssetLoader.java
+++ b/core/java/android/content/pm/split/DefaultSplitAssetLoader.java
@@ -18,9 +18,11 @@
import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
-import android.content.pm.PackageParser;
import android.content.pm.PackageParser.PackageParserException;
-import android.content.pm.PackageParser.ParseFlags;
+import android.content.pm.parsing.ApkLiteParseUtils;
+import android.content.pm.parsing.PackageLite;
+import android.content.pm.parsing.ParsingPackageUtils;
+import android.content.pm.parsing.ParsingPackageUtils.ParseFlags;
import android.content.res.ApkAssets;
import android.content.res.AssetManager;
import android.os.Build;
@@ -36,20 +38,21 @@
* @hide
*/
public class DefaultSplitAssetLoader implements SplitAssetLoader {
- private final String mBaseCodePath;
- private final String[] mSplitCodePaths;
+ private final String mBaseApkPath;
+ private final String[] mSplitApkPaths;
private final @ParseFlags int mFlags;
private AssetManager mCachedAssetManager;
- public DefaultSplitAssetLoader(PackageParser.PackageLite pkg, @ParseFlags int flags) {
- mBaseCodePath = pkg.baseCodePath;
- mSplitCodePaths = pkg.splitCodePaths;
+ public DefaultSplitAssetLoader(PackageLite pkg, @ParseFlags int flags) {
+ mBaseApkPath = pkg.getBaseApkPath();
+ mSplitApkPaths = pkg.getSplitApkPaths();
mFlags = flags;
}
private static ApkAssets loadApkAssets(String path, @ParseFlags int flags)
throws PackageParserException {
- if ((flags & PackageParser.PARSE_MUST_BE_APK) != 0 && !PackageParser.isApkPath(path)) {
+ if ((flags & ParsingPackageUtils.PARSE_MUST_BE_APK) != 0
+ && !ApkLiteParseUtils.isApkPath(path)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
"Invalid package file: " + path);
}
@@ -68,16 +71,16 @@
return mCachedAssetManager;
}
- ApkAssets[] apkAssets = new ApkAssets[(mSplitCodePaths != null
- ? mSplitCodePaths.length : 0) + 1];
+ ApkAssets[] apkAssets = new ApkAssets[(mSplitApkPaths != null
+ ? mSplitApkPaths.length : 0) + 1];
// Load the base.
int splitIdx = 0;
- apkAssets[splitIdx++] = loadApkAssets(mBaseCodePath, mFlags);
+ apkAssets[splitIdx++] = loadApkAssets(mBaseApkPath, mFlags);
// Load any splits.
- if (!ArrayUtils.isEmpty(mSplitCodePaths)) {
- for (String apkPath : mSplitCodePaths) {
+ if (!ArrayUtils.isEmpty(mSplitApkPaths)) {
+ for (String apkPath : mSplitApkPaths) {
apkAssets[splitIdx++] = loadApkAssets(apkPath, mFlags);
}
}
diff --git a/core/java/android/content/pm/split/SplitAssetDependencyLoader.java b/core/java/android/content/pm/split/SplitAssetDependencyLoader.java
index 58eaabf..523ca40 100644
--- a/core/java/android/content/pm/split/SplitAssetDependencyLoader.java
+++ b/core/java/android/content/pm/split/SplitAssetDependencyLoader.java
@@ -19,9 +19,11 @@
import android.annotation.NonNull;
import android.content.pm.PackageManager;
-import android.content.pm.PackageParser;
import android.content.pm.PackageParser.PackageParserException;
-import android.content.pm.PackageParser.ParseFlags;
+import android.content.pm.parsing.ApkLiteParseUtils;
+import android.content.pm.parsing.PackageLite;
+import android.content.pm.parsing.ParsingPackageUtils;
+import android.content.pm.parsing.ParsingPackageUtils.ParseFlags;
import android.content.res.ApkAssets;
import android.content.res.AssetManager;
import android.os.Build;
@@ -45,14 +47,14 @@
private final ApkAssets[][] mCachedSplitApks;
private final AssetManager[] mCachedAssetManagers;
- public SplitAssetDependencyLoader(PackageParser.PackageLite pkg,
+ public SplitAssetDependencyLoader(PackageLite pkg,
SparseArray<int[]> dependencies, @ParseFlags int flags) {
super(dependencies);
// The base is inserted into index 0, so we need to shift all the splits by 1.
- mSplitPaths = new String[pkg.splitCodePaths.length + 1];
- mSplitPaths[0] = pkg.baseCodePath;
- System.arraycopy(pkg.splitCodePaths, 0, mSplitPaths, 1, pkg.splitCodePaths.length);
+ mSplitPaths = new String[pkg.getSplitApkPaths().length + 1];
+ mSplitPaths[0] = pkg.getBaseApkPath();
+ System.arraycopy(pkg.getSplitApkPaths(), 0, mSplitPaths, 1, pkg.getSplitApkPaths().length);
mFlags = flags;
mCachedSplitApks = new ApkAssets[mSplitPaths.length][];
@@ -66,7 +68,8 @@
private static ApkAssets loadApkAssets(String path, @ParseFlags int flags)
throws PackageParserException {
- if ((flags & PackageParser.PARSE_MUST_BE_APK) != 0 && !PackageParser.isApkPath(path)) {
+ if ((flags & ParsingPackageUtils.PARSE_MUST_BE_APK) != 0
+ && !ApkLiteParseUtils.isApkPath(path)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
"Invalid package file: " + path);
}
diff --git a/core/java/android/content/pm/split/SplitDependencyLoader.java b/core/java/android/content/pm/split/SplitDependencyLoader.java
index 3586546..3e68132 100644
--- a/core/java/android/content/pm/split/SplitDependencyLoader.java
+++ b/core/java/android/content/pm/split/SplitDependencyLoader.java
@@ -17,7 +17,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
-import android.content.pm.PackageParser;
+import android.content.pm.parsing.PackageLite;
import android.util.IntArray;
import android.util.SparseArray;
@@ -149,10 +149,19 @@
return dst;
}
- public static @NonNull SparseArray<int[]> createDependenciesFromPackage(
- PackageParser.PackageLite pkg) throws IllegalDependencyException {
- // The data structure that holds the dependencies. In PackageParser, splits are stored
- // in their own array, separate from the base. We treat all paths as equals, so
+ /**
+ * Build the split dependency tree by the given package
+ *
+ * @param pkg The package to retrieve the dependency tree
+ * @return The dependency tree of splits
+ * @throws IllegalDependencyException if the requires split is missing, targets split is
+ * missing, it declares itself as configuration split for a non-feature split, or
+ * cycle detected in split dependencies.
+ */
+ public static @NonNull SparseArray<int[]> createDependenciesFromPackage(PackageLite pkg)
+ throws IllegalDependencyException {
+ // The data structure that holds the dependencies. In ParsingPackageUtils, splits are
+ // stored in their own array, separate from the base. We treat all paths as equals, so
// we need to insert the base as index 0, and shift all other splits.
final SparseArray<int[]> splitDependencies = new SparseArray<>();
@@ -161,19 +170,19 @@
// First write out the <uses-split> dependencies. These must appear first in the
// array of ints, as is convention in this class.
- for (int splitIdx = 0; splitIdx < pkg.splitNames.length; splitIdx++) {
- if (!pkg.isFeatureSplits[splitIdx]) {
+ for (int splitIdx = 0; splitIdx < pkg.getSplitNames().length; splitIdx++) {
+ if (!pkg.getIsFeatureSplits()[splitIdx]) {
// Non-feature splits don't have dependencies.
continue;
}
// Implicit dependency on the base.
final int targetIdx;
- final String splitDependency = pkg.usesSplitNames[splitIdx];
+ final String splitDependency = pkg.getUsesSplitNames()[splitIdx];
if (splitDependency != null) {
- final int depIdx = Arrays.binarySearch(pkg.splitNames, splitDependency);
+ final int depIdx = Arrays.binarySearch(pkg.getSplitNames(), splitDependency);
if (depIdx < 0) {
- throw new IllegalDependencyException("Split '" + pkg.splitNames[splitIdx]
+ throw new IllegalDependencyException("Split '" + pkg.getSplitNames()[splitIdx]
+ "' requires split '" + splitDependency + "', which is missing.");
}
targetIdx = depIdx + 1;
@@ -188,26 +197,26 @@
// dependencies and are considered leaves.
//
// At this point, all splits in splitDependencies have the first element in their array set.
- for (int splitIdx = 0; splitIdx < pkg.splitNames.length; splitIdx++) {
- if (pkg.isFeatureSplits[splitIdx]) {
+ for (int splitIdx = 0, size = pkg.getSplitNames().length; splitIdx < size; splitIdx++) {
+ if (pkg.getIsFeatureSplits()[splitIdx]) {
// Feature splits are not configForSplits.
continue;
}
// Implicit feature for the base.
final int targetSplitIdx;
- final String configForSplit = pkg.configForSplit[splitIdx];
+ final String configForSplit = pkg.getConfigForSplit()[splitIdx];
if (configForSplit != null) {
- final int depIdx = Arrays.binarySearch(pkg.splitNames, configForSplit);
+ final int depIdx = Arrays.binarySearch(pkg.getSplitNames(), configForSplit);
if (depIdx < 0) {
- throw new IllegalDependencyException("Split '" + pkg.splitNames[splitIdx]
+ throw new IllegalDependencyException("Split '" + pkg.getSplitNames()[splitIdx]
+ "' targets split '" + configForSplit + "', which is missing.");
}
- if (!pkg.isFeatureSplits[depIdx]) {
- throw new IllegalDependencyException("Split '" + pkg.splitNames[splitIdx]
+ if (!pkg.getIsFeatureSplits()[depIdx]) {
+ throw new IllegalDependencyException("Split '" + pkg.getSplitNames()[splitIdx]
+ "' declares itself as configuration split for a non-feature split '"
- + pkg.splitNames[depIdx] + "'");
+ + pkg.getSplitNames()[depIdx] + "'");
}
targetSplitIdx = depIdx + 1;
} else {
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
index c6c7142..935cb37 100755
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
@@ -25,7 +25,10 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
-import android.content.pm.PackageParser;
+import android.content.pm.parsing.ApkLiteParseUtils;
+import android.content.pm.parsing.PackageLite;
+import android.content.pm.parsing.result.ParseResult;
+import android.content.pm.parsing.result.ParseTypeImpl;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
@@ -143,16 +146,21 @@
File file = new File(mPackageURI.getPath());
try {
- PackageParser.PackageLite pkg = PackageParser.parsePackageLite(file, 0);
- params.setAppPackageName(pkg.packageName);
- params.setInstallLocation(pkg.installLocation);
- params.setSize(
- PackageHelper.calculateInstalledSize(pkg, false, params.abiOverride));
- } catch (PackageParser.PackageParserException e) {
- Log.e(LOG_TAG, "Cannot parse package " + file + ". Assuming defaults.");
- Log.e(LOG_TAG,
- "Cannot calculate installed size " + file + ". Try only apk size.");
- params.setSize(file.length());
+ final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
+ final ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite(
+ input.reset(), file, /* flags */ 0);
+ if (result.isError()) {
+ Log.e(LOG_TAG, "Cannot parse package " + file + ". Assuming defaults.");
+ Log.e(LOG_TAG,
+ "Cannot calculate installed size " + file + ". Try only apk size.");
+ params.setSize(file.length());
+ } else {
+ final PackageLite pkg = result.getResult();
+ params.setAppPackageName(pkg.getPackageName());
+ params.setInstallLocation(pkg.getInstallLocation());
+ params.setSize(
+ PackageHelper.calculateInstalledSize(pkg, params.abiOverride));
+ }
} catch (IOException e) {
Log.e(LOG_TAG,
"Cannot calculate installed size " + file + ". Try only apk size.");
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index a12932a8..de85d9e 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -30,9 +30,9 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
-import android.content.pm.PackageParser;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.parsing.PackageInfoWithoutStateUtils;
+import android.content.pm.parsing.ParsingPackageUtils;
import android.os.Binder;
import android.os.Environment;
import android.os.RemoteException;
@@ -508,7 +508,8 @@
for (ApexInfo ai : allPkgs) {
File apexFile = new File(ai.modulePath);
- parallelPackageParser.submit(apexFile, PackageParser.PARSE_COLLECT_CERTIFICATES);
+ parallelPackageParser.submit(apexFile,
+ ParsingPackageUtils.PARSE_COLLECT_CERTIFICATES);
parsingApexInfo.put(apexFile, ai);
}
diff --git a/services/core/java/com/android/server/pm/ApkChecksums.java b/services/core/java/com/android/server/pm/ApkChecksums.java
index ff3a12a..5373f99 100644
--- a/services/core/java/com/android/server/pm/ApkChecksums.java
+++ b/services/core/java/com/android/server/pm/ApkChecksums.java
@@ -24,7 +24,7 @@
import static android.content.pm.Checksum.TYPE_WHOLE_SHA256;
import static android.content.pm.Checksum.TYPE_WHOLE_SHA512;
import static android.content.pm.PackageManager.EXTRA_CHECKSUMS;
-import static android.content.pm.PackageParser.APK_FILE_EXTENSION;
+import static android.content.pm.parsing.ApkLiteParseUtils.APK_FILE_EXTENSION;
import static android.util.apk.ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256;
import static android.util.apk.ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512;
import static android.util.apk.ApkSigningBlockUtils.CONTENT_DIGEST_VERITY_CHUNKED_SHA256;
@@ -39,6 +39,7 @@
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageParser;
import android.content.pm.Signature;
+import android.content.pm.parsing.ApkLiteParseUtils;
import android.os.Handler;
import android.os.SystemClock;
import android.os.incremental.IncrementalManager;
@@ -171,7 +172,7 @@
* @throws IllegalArgumentException if the code path is not an .apk.
*/
public static String buildDigestsPathForApk(String codePath) {
- if (!PackageParser.isApkPath(codePath)) {
+ if (!ApkLiteParseUtils.isApkPath(codePath)) {
throw new IllegalStateException("Code path is not an apk " + codePath);
}
return codePath.substring(0, codePath.length() - APK_FILE_EXTENSION.length())
diff --git a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
index 71b99bd..13fe8a0 100644
--- a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
+++ b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
@@ -17,7 +17,7 @@
package com.android.server.pm;
import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
-import static android.content.pm.PackageParser.isApkFile;
+import static android.content.pm.parsing.ApkLiteParseUtils.isApkFile;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.os.incremental.IncrementalManager.isIncrementalPath;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index e143bd0..e218dc1 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -81,11 +81,12 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.ApkLite;
-import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.dex.DexMetadataHelper;
+import android.content.pm.parsing.ApkLite;
import android.content.pm.parsing.ApkLiteParseUtils;
+import android.content.pm.parsing.PackageLite;
+import android.content.pm.parsing.ParsingPackageUtils;
import android.content.pm.parsing.result.ParseResult;
import android.content.pm.parsing.result.ParseTypeImpl;
import android.graphics.Bitmap;
@@ -2671,16 +2672,17 @@
// Populate package name of the apex session
mPackageName = null;
- final ApkLite apk;
- try {
- apk = PackageParser.parseApkLite(
- mResolvedBaseFile, PackageParser.PARSE_COLLECT_CERTIFICATES);
- } catch (PackageParserException e) {
- throw PackageManagerException.from(e);
+ final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
+ final ParseResult<ApkLite> ret = ApkLiteParseUtils.parseApkLite(input.reset(),
+ mResolvedBaseFile, ParsingPackageUtils.PARSE_COLLECT_CERTIFICATES);
+ if (ret.isError()) {
+ throw new PackageManagerException(ret.getErrorCode(), ret.getErrorMessage(),
+ ret.getException());
}
+ final ApkLite apk = ret.getResult();
if (mPackageName == null) {
- mPackageName = apk.packageName;
+ mPackageName = apk.getPackageName();
mVersionCode = apk.getLongVersionCode();
}
}
@@ -2745,29 +2747,29 @@
// Verify that all staged packages are internally consistent
final ArraySet<String> stagedSplits = new ArraySet<>();
- final ArrayMap<String, PackageParser.ApkLite> splitApks = new ArrayMap<>();
- ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
+ final ArrayMap<String, ApkLite> splitApks = new ArrayMap<>();
+ final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
for (File addedFile : addedFiles) {
- ParseResult<ApkLite> result = ApkLiteParseUtils.parseApkLite(input.reset(),
- addedFile, PackageParser.PARSE_COLLECT_CERTIFICATES);
+ final ParseResult<ApkLite> result = ApkLiteParseUtils.parseApkLite(input.reset(),
+ addedFile, ParsingPackageUtils.PARSE_COLLECT_CERTIFICATES);
if (result.isError()) {
throw new PackageManagerException(result.getErrorCode(),
result.getErrorMessage(), result.getException());
}
final ApkLite apk = result.getResult();
- if (!stagedSplits.add(apk.splitName)) {
+ if (!stagedSplits.add(apk.getSplitName())) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
- "Split " + apk.splitName + " was defined multiple times");
+ "Split " + apk.getSplitName() + " was defined multiple times");
}
// Use first package to define unknown values
if (mPackageName == null) {
- mPackageName = apk.packageName;
+ mPackageName = apk.getPackageName();
mVersionCode = apk.getLongVersionCode();
}
if (mSigningDetails == PackageParser.SigningDetails.UNKNOWN) {
- mSigningDetails = apk.signingDetails;
+ mSigningDetails = apk.getSigningDetails();
}
assertApkConsistentLocked(String.valueOf(addedFile), apk);
@@ -2780,10 +2782,10 @@
}
// Yell loudly if installers drop attribute installLocation when apps explicitly set.
- if (apk.installLocation != PackageInfo.INSTALL_LOCATION_UNSPECIFIED) {
+ if (apk.getInstallLocation() != PackageInfo.INSTALL_LOCATION_UNSPECIFIED) {
final String installerPackageName = getInstallerPackageName();
if (installerPackageName != null
- && (params.installLocation != apk.installLocation)) {
+ && (params.installLocation != apk.getInstallLocation())) {
Slog.wtf(TAG, installerPackageName
+ " drops manifest attribute android:installLocation in " + targetName
+ " for " + mPackageName);
@@ -2791,14 +2793,14 @@
}
final File targetFile = new File(stageDir, targetName);
- resolveAndStageFileLocked(addedFile, targetFile, apk.splitName);
+ resolveAndStageFileLocked(addedFile, targetFile, apk.getSplitName());
// Base is coming from session
- if (apk.splitName == null) {
+ if (apk.getSplitName() == null) {
mResolvedBaseFile = targetFile;
baseApk = apk;
} else {
- splitApks.put(apk.splitName, apk);
+ splitApks.put(apk.getSplitName(), apk);
}
}
@@ -2854,7 +2856,7 @@
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
"Full install must include a base package");
}
- if (baseApk.isSplitRequired && stagedSplits.size() <= 1) {
+ if (baseApk.isSplitRequired() && stagedSplits.size() <= 1) {
throw new PackageManagerException(INSTALL_FAILED_MISSING_SPLIT,
"Missing split for " + mPackageName);
}
@@ -2879,10 +2881,10 @@
}
final PackageLite existing = pkgLiteResult.getResult();
packageLite = existing;
- assertPackageConsistentLocked("Existing", existing.packageName,
+ assertPackageConsistentLocked("Existing", existing.getPackageName(),
existing.getLongVersionCode());
final PackageParser.SigningDetails signingDetails =
- unsafeGetCertsWithoutVerification(existing.baseCodePath);
+ unsafeGetCertsWithoutVerification(existing.getBaseApkPath());
if (!mSigningDetails.signaturesMatchExactly(signingDetails)) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
"Existing signatures are inconsistent");
@@ -2895,10 +2897,10 @@
}
// Inherit splits if not overridden.
- if (!ArrayUtils.isEmpty(existing.splitNames)) {
- for (int i = 0; i < existing.splitNames.length; i++) {
- final String splitName = existing.splitNames[i];
- final File splitFile = new File(existing.splitCodePaths[i]);
+ if (!ArrayUtils.isEmpty(existing.getSplitNames())) {
+ for (int i = 0; i < existing.getSplitNames().length; i++) {
+ final String splitName = existing.getSplitNames()[i];
+ final File splitFile = new File(existing.getSplitApkPaths()[i]);
final boolean splitRemoved = removeSplitList.contains(splitName);
if (!stagedSplits.contains(splitName) && !splitRemoved) {
inheritFileLocked(splitFile);
@@ -2978,8 +2980,8 @@
}
}
// For the case of split required, failed if no splits existed
- if (packageLite.isSplitRequired) {
- final int existingSplits = ArrayUtils.size(existing.splitNames);
+ if (packageLite.isSplitRequired()) {
+ final int existingSplits = ArrayUtils.size(existing.getSplitNames());
final boolean allSplitsRemoved = (existingSplits == removeSplitList.size());
final boolean onlyBaseFileStaged = (stagedSplits.size() == 1
&& stagedSplits.contains(null));
@@ -2989,7 +2991,7 @@
}
}
}
- if (packageLite.useEmbeddedDex) {
+ if (packageLite.isUseEmbeddedDex()) {
for (File file : mResolvedStagedFiles) {
if (file.getName().endsWith(".apk")
&& !DexManager.auditUncompressedDexInApk(file.getPath())) {
@@ -3002,7 +3004,7 @@
final boolean isInstallerShell = (mInstallerUid == Process.SHELL_UID);
if (isInstallerShell && isIncrementalInstallation() && mIncrementalFileStorages != null) {
- if (!packageLite.debuggable && !packageLite.profilableByShell) {
+ if (!packageLite.isDebuggable() && !packageLite.isProfileableByShell()) {
mIncrementalFileStorages.disallowReadLogs();
}
}
@@ -3174,8 +3176,8 @@
@GuardedBy("mLock")
private void assertApkConsistentLocked(String tag, ApkLite apk)
throws PackageManagerException {
- assertPackageConsistentLocked(tag, apk.packageName, apk.getLongVersionCode());
- if (!mSigningDetails.signaturesMatchExactly(apk.signingDetails)) {
+ assertPackageConsistentLocked(tag, apk.getPackageName(), apk.getLongVersionCode());
+ if (!mSigningDetails.signaturesMatchExactly(apk.getSigningDetails())) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
tag + " signatures are inconsistent");
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 68b0698..50aacd6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -101,7 +101,7 @@
import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN;
import static android.content.pm.PackageManagerInternal.LAST_KNOWN_PACKAGE;
import static android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V4;
-import static android.content.pm.PackageParser.isApkFile;
+import static android.content.pm.parsing.ApkLiteParseUtils.isApkFile;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.os.incremental.IncrementalManager.isIncrementalPath;
import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
@@ -211,9 +211,7 @@
import android.content.pm.PackageManagerInternal.PackageListObserver;
import android.content.pm.PackageManagerInternal.PrivateResolveFlags;
import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
-import android.content.pm.PackageParser.ParseFlags;
import android.content.pm.PackageParser.SigningDetails;
import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
import android.content.pm.PackagePartitions;
@@ -241,7 +239,9 @@
import android.content.pm.dex.DexMetadataHelper;
import android.content.pm.dex.IArtManager;
import android.content.pm.parsing.ApkLiteParseUtils;
+import android.content.pm.parsing.PackageLite;
import android.content.pm.parsing.ParsingPackageUtils;
+import android.content.pm.parsing.ParsingPackageUtils.ParseFlags;
import android.content.pm.parsing.component.ParsedActivity;
import android.content.pm.parsing.component.ParsedInstrumentation;
import android.content.pm.parsing.component.ParsedIntentInfo;
@@ -6251,7 +6251,7 @@
if (separateProcesses != null && separateProcesses.length() > 0) {
if ("*".equals(separateProcesses)) {
- mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
+ mDefParseFlags = ParsingPackageUtils.PARSE_IGNORE_PROCESSES;
mSeparateProcesses = null;
Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
} else {
@@ -6451,7 +6451,7 @@
scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
}
- final int systemParseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR;
+ final int systemParseFlags = mDefParseFlags | ParsingPackageUtils.PARSE_IS_SYSTEM_DIR;
final int systemScanFlags = scanFlags | SCAN_AS_SYSTEM;
PackageParser2 packageParser = injector.getScanningCachingPackageParser();
@@ -7091,7 +7091,7 @@
*/
private boolean enableCompressedPackage(AndroidPackage stubPkg,
@NonNull PackageSetting stubPkgSetting) {
- final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
+ final int parseFlags = mDefParseFlags | ParsingPackageUtils.PARSE_CHATTY
| PackageParser.PARSE_ENFORCE_CODE;
synchronized (mInstallLock) {
final AndroidPackage pkg;
@@ -11317,7 +11317,8 @@
@ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime,
@Nullable UserHandle user)
throws PackageManagerException {
- final boolean scanSystemPartition = (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0;
+ final boolean scanSystemPartition =
+ (parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) != 0;
final String renamedPkgName;
final PackageSetting disabledPkgSetting;
final boolean isSystemPkgUpdated;
@@ -11360,7 +11361,7 @@
0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, true)
: null;
if (DEBUG_PACKAGE_SCANNING
- && (parseFlags & PackageParser.PARSE_CHATTY) != 0
+ && (parseFlags & ParsingPackageUtils.PARSE_CHATTY) != 0
&& sharedUserSetting != null) {
Log.d(TAG, "Shared UserID " + parsedPackage.getSharedUserId()
+ " (uid=" + sharedUserSetting.userId + "):"
@@ -13179,10 +13180,11 @@
sharedUserSetting = mSettings.getSharedUserLPw(parsedPackage.getSharedUserId(),
0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, true /*create*/);
if (DEBUG_PACKAGE_SCANNING) {
- if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
+ if ((parseFlags & ParsingPackageUtils.PARSE_CHATTY) != 0) {
Log.d(TAG, "Shared UserID " + parsedPackage.getSharedUserId()
+ " (uid=" + sharedUserSetting.userId + "):"
+ " packages=" + sharedUserSetting.packages);
+ }
}
}
String platformPackageName = mPlatformPackage == null
@@ -13339,7 +13341,7 @@
final int userId = user == null ? 0 : user.getIdentifier();
// Modify state for the given package setting
commitPackageSettings(pkg, oldPkg, pkgSetting, scanFlags,
- (parseFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/, reconciledPkg);
+ (parseFlags & ParsingPackageUtils.PARSE_CHATTY) != 0 /*chatty*/, reconciledPkg);
if (pkgSetting.getInstantApp(userId)) {
mInstantAppRegistry.addInstantAppLPw(userId, pkgSetting.appId);
}
@@ -13548,8 +13550,9 @@
List<String> changedAbiCodePath = null;
if (DEBUG_PACKAGE_SCANNING) {
- if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
+ if ((parseFlags & ParsingPackageUtils.PARSE_CHATTY) != 0) {
Log.d(TAG, "Scanning package " + parsedPackage.getPackageName());
+ }
}
// Initialize package source and resource directories
@@ -13816,7 +13819,7 @@
} else if (pkgSetting.firstInstallTime == 0) {
// We need *something*. Take time time stamp of the file.
pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
- } else if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
+ } else if ((parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) != 0) {
if (scanFileTime != pkgSetting.timeStamp) {
// A package on the system image has changed; consider this
// to be an update.
@@ -14013,7 +14016,7 @@
private void assertPackageIsValid(AndroidPackage pkg, final @ParseFlags int parseFlags,
final @ScanFlags int scanFlags)
throws PackageManagerException {
- if ((parseFlags & PackageParser.PARSE_ENFORCE_CODE) != 0) {
+ if ((parseFlags & ParsingPackageUtils.PARSE_ENFORCE_CODE) != 0) {
assertCodePolicy(pkg);
}
@@ -14270,7 +14273,7 @@
if ((scanFlags & SCAN_AS_SYSTEM) != 0) {
// We are scanning a system overlay. This can be the first scan of the
// system/vendor/oem partition, or an update to the system overlay.
- if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+ if ((parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) == 0) {
// This must be an update to a system overlay. Immutable overlays cannot be
// upgraded.
Objects.requireNonNull(mOverlayConfig,
@@ -14350,7 +14353,7 @@
// If the package is not on a system partition ensure it is signed with at least the
// minimum signature scheme version required for its target SDK.
- if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+ if ((parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) == 0) {
int minSignatureSchemeVersion =
ApkSignatureVerifier.getMinimumSignatureSchemeVersionForTargetSdk(
pkg.getTargetSdkVersion());
@@ -18015,11 +18018,12 @@
// Try enumerating all code paths before deleting
List<String> allCodePaths = Collections.EMPTY_LIST;
if (codeFile != null && codeFile.exists()) {
- try {
- final PackageLite pkg = PackageParser.parsePackageLite(codeFile, 0);
- allCodePaths = pkg.getAllCodePaths();
- } catch (PackageParserException e) {
- // Ignored; we tried our best
+ final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
+ final ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite(
+ input.reset(), codeFile, /* flags */ 0);
+ if (result.isSuccess()) {
+ // Ignore error; we tried our best
+ allCodePaths = result.getResult().getAllApkPaths();
}
}
@@ -18637,7 +18641,7 @@
// We just determined the app is signed correctly, so bring
// over the latest parsed certs.
} else {
- if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+ if ((parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) == 0) {
throw new ReconcileFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
"Package " + parsedPackage.getPackageName()
+ " upgrade keys do not match the previously installed"
@@ -18687,7 +18691,7 @@
}
}
} catch (PackageManagerException e) {
- if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+ if ((parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) == 0) {
throw new ReconcileFailure(e);
}
signingDetails = parsedPackage.getSigningDetails();
@@ -18766,7 +18770,8 @@
// apps are scanned to avoid dependency based scanning.
final ScanResult scanResult = scannedPackages.get(installPackageName);
if ((scanResult.request.scanFlags & SCAN_BOOTING) != 0
- || (scanResult.request.parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
+ || (scanResult.request.parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR)
+ != 0) {
continue;
}
try {
@@ -19652,9 +19657,9 @@
}
// Retrieve PackageSettings and parse package
- @ParseFlags final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
- | PackageParser.PARSE_ENFORCE_CODE
- | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0);
+ @ParseFlags final int parseFlags = mDefParseFlags | ParsingPackageUtils.PARSE_CHATTY
+ | ParsingPackageUtils.PARSE_ENFORCE_CODE
+ | (onExternal ? ParsingPackageUtils.PARSE_EXTERNAL_STORAGE : 0);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
final ParsedPackage parsedPackage;
@@ -21384,8 +21389,8 @@
final File codePath = new File(codePathString);
@ParseFlags int parseFlags =
mDefParseFlags
- | PackageParser.PARSE_MUST_BE_APK
- | PackageParser.PARSE_IS_SYSTEM_DIR;
+ | ParsingPackageUtils.PARSE_MUST_BE_APK
+ | ParsingPackageUtils.PARSE_IS_SYSTEM_DIR;
@ScanFlags int scanFlags = SCAN_AS_SYSTEM;
for (int i = mDirsToScanAsSystem.size() - 1; i >= 0; i--) {
ScanPartition partition = mDirsToScanAsSystem.get(i);
@@ -24837,7 +24842,7 @@
final ArrayList<PackageFreezer> freezers = new ArrayList<>();
final ArrayList<AndroidPackage> loaded = new ArrayList<>();
- final int parseFlags = mDefParseFlags | PackageParser.PARSE_EXTERNAL_STORAGE;
+ final int parseFlags = mDefParseFlags | ParsingPackageUtils.PARSE_EXTERNAL_STORAGE;
final VersionInfo ver;
final List<PackageSetting> packages;
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index d3d7c60..ee94b85 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -35,9 +35,12 @@
import android.content.pm.PackageInfoLite;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
+import android.content.pm.parsing.ApkLiteParseUtils;
+import android.content.pm.parsing.PackageLite;
+import android.content.pm.parsing.result.ParseResult;
+import android.content.pm.parsing.result.ParseTypeImpl;
import android.os.Build;
import android.os.Debug;
import android.os.Environment;
@@ -819,8 +822,8 @@
/**
* Parse given package and return minimal details.
*/
- public static PackageInfoLite getMinimalPackageInfo(Context context,
- PackageParser.PackageLite pkg, String packagePath, int flags, String abiOverride) {
+ public static PackageInfoLite getMinimalPackageInfo(Context context, PackageLite pkg,
+ String packagePath, int flags, String abiOverride) {
final PackageInfoLite ret = new PackageInfoLite();
if (packagePath == null || pkg == null) {
Slog.i(TAG, "Invalid package file " + packagePath);
@@ -843,19 +846,19 @@
}
final int recommendedInstallLocation = PackageHelper.resolveInstallLocation(context,
- pkg.packageName, pkg.installLocation, sizeBytes, flags);
+ pkg.getPackageName(), pkg.getInstallLocation(), sizeBytes, flags);
- ret.packageName = pkg.packageName;
- ret.splitNames = pkg.splitNames;
- ret.versionCode = pkg.versionCode;
- ret.versionCodeMajor = pkg.versionCodeMajor;
- ret.baseRevisionCode = pkg.baseRevisionCode;
- ret.splitRevisionCodes = pkg.splitRevisionCodes;
- ret.installLocation = pkg.installLocation;
- ret.verifiers = pkg.verifiers;
+ ret.packageName = pkg.getPackageName();
+ ret.splitNames = pkg.getSplitNames();
+ ret.versionCode = pkg.getVersionCode();
+ ret.versionCodeMajor = pkg.getVersionCodeMajor();
+ ret.baseRevisionCode = pkg.getBaseRevisionCode();
+ ret.splitRevisionCodes = pkg.getSplitRevisionCodes();
+ ret.installLocation = pkg.getInstallLocation();
+ ret.verifiers = pkg.getVerifiers();
ret.recommendedInstallLocation = recommendedInstallLocation;
- ret.multiArch = pkg.multiArch;
- ret.debuggable = pkg.debuggable;
+ ret.multiArch = pkg.isMultiArch();
+ ret.debuggable = pkg.isDebuggable();
return ret;
}
@@ -868,11 +871,16 @@
*/
public static long calculateInstalledSize(String packagePath, String abiOverride) {
final File packageFile = new File(packagePath);
- final PackageParser.PackageLite pkg;
try {
- pkg = PackageParser.parsePackageLite(packageFile, 0);
- return PackageHelper.calculateInstalledSize(pkg, abiOverride);
- } catch (PackageParserException | IOException e) {
+ final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
+ final ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite(
+ input.reset(), packageFile, /* flags */ 0);
+ if (result.isError()) {
+ throw new PackageManagerException(result.getErrorCode(),
+ result.getErrorMessage(), result.getException());
+ }
+ return PackageHelper.calculateInstalledSize(result.getResult(), abiOverride);
+ } catch (PackageManagerException | IOException e) {
Slog.w(TAG, "Failed to calculate installed size: " + e);
return -1;
}
@@ -931,16 +939,23 @@
try {
final File packageFile = new File(packagePath);
- final PackageParser.PackageLite pkg = PackageParser.parsePackageLite(packageFile, 0);
- copyFile(pkg.baseCodePath, targetDir, "base.apk");
- if (!ArrayUtils.isEmpty(pkg.splitNames)) {
- for (int i = 0; i < pkg.splitNames.length; i++) {
- copyFile(pkg.splitCodePaths[i], targetDir,
- "split_" + pkg.splitNames[i] + ".apk");
+ final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
+ final ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite(
+ input.reset(), packageFile, /* flags */ 0);
+ if (result.isError()) {
+ Slog.w(TAG, "Failed to parse package at " + packagePath);
+ return result.getErrorCode();
+ }
+ final PackageLite pkg = result.getResult();
+ copyFile(pkg.getBaseApkPath(), targetDir, "base.apk");
+ if (!ArrayUtils.isEmpty(pkg.getSplitNames())) {
+ for (int i = 0; i < pkg.getSplitNames().length; i++) {
+ copyFile(pkg.getSplitApkPaths()[i], targetDir,
+ "split_" + pkg.getSplitNames()[i] + ".apk");
}
}
return PackageManager.INSTALL_SUCCEEDED;
- } catch (PackageParserException | IOException | ErrnoException e) {
+ } catch (IOException | ErrnoException e) {
Slog.w(TAG, "Failed to copy package at " + packagePath + ": " + e);
return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 446342a..3207d56a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -49,8 +49,6 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManagerInternal;
-import android.content.pm.PackageParser.ApkLite;
-import android.content.pm.PackageParser.PackageLite;
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
@@ -61,7 +59,9 @@
import android.content.pm.dex.ArtManager;
import android.content.pm.dex.DexMetadataHelper;
import android.content.pm.dex.ISnapshotRuntimeProfileCallback;
+import android.content.pm.parsing.ApkLite;
import android.content.pm.parsing.ApkLiteParseUtils;
+import android.content.pm.parsing.PackageLite;
import android.content.pm.parsing.result.ParseResult;
import android.content.pm.parsing.result.ParseTypeImpl;
import android.content.res.AssetManager;
@@ -555,8 +555,8 @@
apkLiteResult.getException());
}
final ApkLite apkLite = apkLiteResult.getResult();
- PackageLite pkgLite = new PackageLite(null, apkLite.codePath, apkLite, null, null,
- null, null, null, null);
+ final PackageLite pkgLite = new PackageLite(null, apkLite.getPath(), apkLite, null,
+ null, null, null, null, null);
sessionSize += PackageHelper.calculateInstalledSize(pkgLite,
params.sessionParams.abiOverride, fd.getFileDescriptor());
} catch (IOException e) {
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java
index a13680a..471a4d3 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java
@@ -24,6 +24,7 @@
import android.content.pm.PackageParser;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.parsing.ParsingPackageRead;
+import android.content.pm.parsing.ParsingPackageUtils;
import android.content.pm.parsing.component.ParsedAttribution;
import android.content.pm.parsing.component.ParsedIntentInfo;
import android.content.pm.parsing.component.ParsedPermissionGroup;
@@ -56,7 +57,7 @@
/**
* The names of packages to adopt ownership of permissions from, parsed under
- * {@link PackageParser#TAG_ADOPT_PERMISSIONS}.
+ * {@link ParsingPackageUtils#TAG_ADOPT_PERMISSIONS}.
* @see R.styleable#AndroidManifestOriginalPackage_name
*/
@NonNull
@@ -84,7 +85,7 @@
/**
* For use with {@link com.android.server.pm.KeySetManagerService}. Parsed in
- * {@link PackageParser#TAG_KEY_SETS}.
+ * {@link ParsingPackageUtils#TAG_KEY_SETS}.
* @see R.styleable#AndroidManifestKeySet
* @see R.styleable#AndroidManifestPublicKey
*/
@@ -230,7 +231,7 @@
/**
* For use with {@link com.android.server.pm.KeySetManagerService}. Parsed in
- * {@link PackageParser#TAG_KEY_SETS}.
+ * {@link ParsingPackageUtils#TAG_KEY_SETS}.
* @see R.styleable#AndroidManifestUpgradeKeySet
*/
@NonNull
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
index ab25a7c..37dfea4 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
@@ -21,12 +21,12 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageParser;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.VersionedPackage;
import android.content.pm.dex.DexMetadataHelper;
import android.content.pm.parsing.ParsingPackageRead;
+import android.content.pm.parsing.ParsingPackageUtils;
import android.content.pm.parsing.component.ParsedActivity;
import android.content.pm.parsing.component.ParsedInstrumentation;
import android.content.pm.parsing.component.ParsedProvider;
@@ -233,7 +233,7 @@
}
public static int getIcon(ParsingPackageRead pkg) {
- return (PackageParser.sUseRoundIcon && pkg.getRoundIconRes() != 0)
+ return (ParsingPackageUtils.sUseRoundIcon && pkg.getRoundIconRes() != 0)
? pkg.getRoundIconRes() : pkg.getIconRes();
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
index eaf62cb..0dcd608 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
@@ -23,12 +23,11 @@
import android.content.Context;
import android.content.pm.PackageManager;
-import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.ApkLite;
-import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.dex.DexMetadataHelper;
+import android.content.pm.parsing.ApkLite;
import android.content.pm.parsing.ApkLiteParseUtils;
+import android.content.pm.parsing.PackageLite;
import android.content.pm.parsing.result.ParseResult;
import android.content.pm.parsing.result.ParseTypeImpl;
import android.os.FileUtils;
@@ -38,6 +37,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.frameworks.servicestests.R;
+import com.android.server.pm.PackageManagerException;
import com.android.server.pm.parsing.TestPackageParser2;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.parsing.pkg.ParsedPackage;
@@ -207,28 +207,35 @@
}
@Test
- public void testPackageSizeWithDmFile()
- throws IOException, PackageParserException {
+ public void testPackageSizeWithDmFile() throws IOException {
copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
- File dm = createDexMetadataFile("install_split_base.apk");
- ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite(
+ final File dm = createDexMetadataFile("install_split_base.apk");
+ final ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite(
ParseTypeImpl.forDefaultParsing().reset(), mTmpDir, 0 /* flags */);
if (result.isError()) {
throw new IllegalStateException(result.getErrorMessage(), result.getException());
}
- PackageParser.PackageLite pkg = result.getResult();
+ final PackageLite pkg = result.getResult();
Assert.assertEquals(dm.length(), DexMetadataHelper.getPackageDexMetadataSize(pkg));
}
// This simulates the 'adb shell pm install' flow.
@Test
- public void testPackageSizeWithPartialPackageLite() throws IOException, PackageParserException {
- File base = copyApkToToTmpDir("install_split_base", R.raw.install_split_base);
- File dm = createDexMetadataFile("install_split_base.apk");
+ public void testPackageSizeWithPartialPackageLite() throws IOException,
+ PackageManagerException {
+ final File base = copyApkToToTmpDir("install_split_base", R.raw.install_split_base);
+ final File dm = createDexMetadataFile("install_split_base.apk");
try (FileInputStream is = new FileInputStream(base)) {
- ApkLite baseApk = PackageParser.parseApkLite(is.getFD(), base.getAbsolutePath(), 0);
- PackageLite pkgLite = new PackageLite(null, baseApk.codePath, baseApk, null, null, null,
- null, null, null);
+ final ParseResult<ApkLite> result = ApkLiteParseUtils.parseApkLite(
+ ParseTypeImpl.forDefaultParsing().reset(), is.getFD(),
+ base.getAbsolutePath(), /* flags */ 0);
+ if (result.isError()) {
+ throw new PackageManagerException(result.getErrorCode(),
+ result.getErrorMessage(), result.getException());
+ }
+ final ApkLite baseApk = result.getResult();
+ final PackageLite pkgLite = new PackageLite(null, baseApk.getPath(), baseApk, null,
+ null, null, null, null, null);
Assert.assertEquals(dm.length(), DexMetadataHelper.getPackageDexMetadataSize(pkgLite));
}