diff options
| author | Pedro Loureiro <pedroql@google.com> | 2021-12-30 16:48:08 +0000 |
|---|---|---|
| committer | Pedro Loureiro <pedroql@google.com> | 2022-01-25 10:05:57 +0000 |
| commit | c6d1dec22ca189a059807360678269cfa67d74ec (patch) | |
| tree | 5d8969358385ae68464696c82a95e4a68913d06e /core/java/android | |
| parent | 9c74d734719393e3604213dd5f6590c712af0216 (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.java | 58 |
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); } /** |
