summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
authorPedro Loureiro <pedroql@google.com>2021-12-30 16:48:08 +0000
committerPedro Loureiro <pedroql@google.com>2022-01-25 10:05:57 +0000
commitc6d1dec22ca189a059807360678269cfa67d74ec (patch)
tree5d8969358385ae68464696c82a95e4a68913d06e /core/java/android
parent9c74d734719393e3604213dd5f6590c712af0216 (diff)
Allow framework-res APK splits from Apexes
Test: m FrameworkResApkSplitsHostTest Bug: 195732042 Change-Id: I516e6267c661e112c234aed27e2eef2ce9ffaf9a
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/content/pm/parsing/ApkLiteParseUtils.java58
1 files changed, 45 insertions, 13 deletions
diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
index d5498a0dc8cd..165cae826187 100644
--- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
+++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
@@ -78,6 +78,7 @@ public class ApkLiteParseUtils {
public static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
private static final int PARSE_IS_SYSTEM_DIR = 1 << 4;
private static final int PARSE_COLLECT_CERTIFICATES = 1 << 5;
+ private static final int PARSE_FRAMEWORK_RES_SPLITS = 1 << 8;
private static final String TAG_APPLICATION = "application";
private static final String TAG_PACKAGE_VERIFIER = "package-verifier";
private static final String TAG_PROFILEABLE = "profileable";
@@ -101,7 +102,7 @@ public class ApkLiteParseUtils {
public static ParseResult<PackageLite> parsePackageLite(ParseInput input,
File packageFile, int flags) {
if (packageFile.isDirectory()) {
- return parseClusterPackageLite(input, packageFile, flags);
+ return parseClusterPackageLite(input, packageFile, /* frameworkSplits= */ null, flags);
} else {
return parseMonolithicPackageLite(input, packageFile, flags);
}
@@ -134,21 +135,44 @@ public class ApkLiteParseUtils {
/**
* Parse lightweight details about a directory of APKs.
+ *
+ * @param packageDirOrApk is the folder that contains split apks for a regular app or the
+ * framework-res.apk for framwork-res splits (in which case the
+ * splits come in the <code>frameworkSplits</code> parameter)
*/
public static ParseResult<PackageLite> parseClusterPackageLite(ParseInput input,
- File packageDir, int flags) {
- final File[] files = packageDir.listFiles();
- if (ArrayUtils.isEmpty(files)) {
- return input.error(PackageManager.INSTALL_PARSE_FAILED_NOT_APK,
- "No packages found in split");
+ File packageDirOrApk, List<File> frameworkSplits, int flags) {
+ final File[] files;
+ final boolean parsingFrameworkSplits = (flags & PARSE_FRAMEWORK_RES_SPLITS) != 0;
+ if (parsingFrameworkSplits) {
+ if (ArrayUtils.isEmpty(frameworkSplits)) {
+ return input.error(PackageManager.INSTALL_PARSE_FAILED_NOT_APK,
+ "No packages found in split");
+ }
+ files = frameworkSplits.toArray(new File[frameworkSplits.size() + 1]);
+ // we also want to process the base apk so add it to the array
+ files[files.length - 1] = packageDirOrApk;
+ } else {
+ files = packageDirOrApk.listFiles();
+ if (ArrayUtils.isEmpty(files)) {
+ return input.error(PackageManager.INSTALL_PARSE_FAILED_NOT_APK,
+ "No packages found in split");
+ }
+ // Apk directory is directly nested under the current directory
+ if (files.length == 1 && files[0].isDirectory()) {
+ return parseClusterPackageLite(input, files[0], frameworkSplits, flags);
+ }
}
- // Apk directory is directly nested under the current directory
- if (files.length == 1 && files[0].isDirectory()) {
- return parseClusterPackageLite(input, files[0], flags);
+
+ if (parsingFrameworkSplits) {
+ // disable the flag for checking the certificates of the splits. We know they
+ // won't match, but we rely on the mainline apex to be safe if it was installed
+ flags = flags & ~PARSE_COLLECT_CERTIFICATES;
}
String packageName = null;
int versionCode = 0;
+ ApkLite baseApk = null;
final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
@@ -161,6 +185,10 @@ public class ApkLiteParseUtils {
}
final ApkLite lite = result.getResult();
+ if (parsingFrameworkSplits && file == files[files.length - 1]) {
+ baseApk = lite;
+ break;
+ }
// Assert that all package names and version codes are
// consistent with the first one we encounter.
if (packageName == null) {
@@ -172,7 +200,8 @@ public class ApkLiteParseUtils {
"Inconsistent package " + lite.getPackageName() + " in " + file
+ "; expected " + packageName);
}
- if (versionCode != lite.getVersionCode()) {
+ // we allow version codes that do not match for framework splits
+ if (!parsingFrameworkSplits && versionCode != lite.getVersionCode()) {
return input.error(PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST,
"Inconsistent version " + lite.getVersionCode() + " in " + file
+ "; expected " + versionCode);
@@ -187,12 +216,15 @@ public class ApkLiteParseUtils {
}
}
}
+ // baseApk is set in the last iteration of the for each loop when we are parsing
+ // frameworkRes splits or needs to be done now otherwise
+ if (!parsingFrameworkSplits) {
+ baseApk = apks.remove(null);
+ }
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
-
- final ApkLite baseApk = apks.remove(null);
- return composePackageLiteFromApks(input, packageDir, baseApk, apks);
+ return composePackageLiteFromApks(input, packageDirOrApk, baseApk, apks);
}
/**