Merge "pm: Require manifest.json for .dm (dex-metadata) files."
This commit is contained in:
@@ -22,17 +22,26 @@ import static android.content.pm.PackageParser.APK_FILE_EXTENSION;
|
||||
import android.content.pm.PackageParser;
|
||||
import android.content.pm.PackageParser.PackageLite;
|
||||
import android.content.pm.PackageParser.PackageParserException;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.jar.StrictJarFile;
|
||||
import android.util.JsonReader;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
/**
|
||||
* Helper class used to compute and validate the location of dex metadata files.
|
||||
@@ -40,6 +49,12 @@ import java.util.Map;
|
||||
* @hide
|
||||
*/
|
||||
public class DexMetadataHelper {
|
||||
public static final String TAG = "DexMetadataHelper";
|
||||
/** $> adb shell 'setprop log.tag.DexMetadataHelper VERBOSE' */
|
||||
public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
/** $> adb shell 'setprop pm.dexopt.dm.require_manifest true' */
|
||||
private static String PROPERTY_DM_JSON_MANIFEST_REQUIRED = "pm.dexopt.dm.require_manifest";
|
||||
|
||||
private static final String DEX_METADATA_FILE_EXTENSION = ".dm";
|
||||
|
||||
private DexMetadataHelper() {}
|
||||
@@ -147,14 +162,31 @@ public class DexMetadataHelper {
|
||||
|
||||
/**
|
||||
* Validate that the given file is a dex metadata archive.
|
||||
* This is just a validation that the file is a zip archive.
|
||||
* This is just a validation that the file is a zip archive that contains a manifest.json
|
||||
* with the package name and version code.
|
||||
*
|
||||
* @throws PackageParserException if the file is not a .dm file.
|
||||
*/
|
||||
public static void validateDexMetadataFile(String dmaPath) throws PackageParserException {
|
||||
public static void validateDexMetadataFile(String dmaPath, String packageName, long versionCode)
|
||||
throws PackageParserException {
|
||||
validateDexMetadataFile(dmaPath, packageName, versionCode,
|
||||
SystemProperties.getBoolean(PROPERTY_DM_JSON_MANIFEST_REQUIRED, false));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static void validateDexMetadataFile(String dmaPath, String packageName, long versionCode,
|
||||
boolean requireManifest) throws PackageParserException {
|
||||
StrictJarFile jarFile = null;
|
||||
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "validateDexMetadataFile: " + dmaPath + ", " + packageName +
|
||||
", " + versionCode);
|
||||
}
|
||||
|
||||
try {
|
||||
jarFile = new StrictJarFile(dmaPath, false, false);
|
||||
validateDexMetadataManifest(dmaPath, jarFile, packageName, versionCode,
|
||||
requireManifest);
|
||||
} catch (IOException e) {
|
||||
throw new PackageParserException(INSTALL_FAILED_BAD_DEX_METADATA,
|
||||
"Error opening " + dmaPath, e);
|
||||
@@ -168,6 +200,72 @@ public class DexMetadataHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/** Ensure that packageName and versionCode match the manifest.json in the .dm file */
|
||||
private static void validateDexMetadataManifest(String dmaPath, StrictJarFile jarFile,
|
||||
String packageName, long versionCode, boolean requireManifest)
|
||||
throws IOException, PackageParserException {
|
||||
if (!requireManifest) {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "validateDexMetadataManifest: " + dmaPath
|
||||
+ " manifest.json check skipped");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ZipEntry zipEntry = jarFile.findEntry("manifest.json");
|
||||
if (zipEntry == null) {
|
||||
throw new PackageParserException(INSTALL_FAILED_BAD_DEX_METADATA,
|
||||
"Missing manifest.json in " + dmaPath);
|
||||
}
|
||||
InputStream inputStream = jarFile.getInputStream(zipEntry);
|
||||
|
||||
JsonReader reader;
|
||||
try {
|
||||
reader = new JsonReader(new InputStreamReader(inputStream, "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new PackageParserException(INSTALL_FAILED_BAD_DEX_METADATA,
|
||||
"Error opening manifest.json in " + dmaPath, e);
|
||||
}
|
||||
String jsonPackageName = null;
|
||||
long jsonVersionCode = -1;
|
||||
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
String name = reader.nextName();
|
||||
if (name.equals("packageName")) {
|
||||
jsonPackageName = reader.nextString();
|
||||
} else if (name.equals("versionCode")) {
|
||||
jsonVersionCode = reader.nextLong();
|
||||
} else {
|
||||
reader.skipValue();
|
||||
}
|
||||
}
|
||||
reader.endObject();
|
||||
|
||||
if (jsonPackageName == null || jsonVersionCode == -1) {
|
||||
throw new PackageParserException(INSTALL_FAILED_BAD_DEX_METADATA,
|
||||
"manifest.json in " + dmaPath
|
||||
+ " is missing 'packageName' and/or 'versionCode'");
|
||||
}
|
||||
|
||||
if (!jsonPackageName.equals(packageName)) {
|
||||
throw new PackageParserException(INSTALL_FAILED_BAD_DEX_METADATA,
|
||||
"manifest.json in " + dmaPath + " has invalid packageName: " + jsonPackageName
|
||||
+ ", expected: " + packageName);
|
||||
}
|
||||
|
||||
if (versionCode != jsonVersionCode) {
|
||||
throw new PackageParserException(INSTALL_FAILED_BAD_DEX_METADATA,
|
||||
"manifest.json in " + dmaPath + " has invalid versionCode: " + jsonVersionCode
|
||||
+ ", expected: " + versionCode);
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "validateDexMetadataManifest: " + dmaPath + ", " + packageName +
|
||||
", " + versionCode + ": successful");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that all dex metadata paths in the given list have a matching apk.
|
||||
* (for any foo.dm there should be either a 'foo' of a 'foo.apk' file).
|
||||
|
||||
@@ -125,8 +125,10 @@ public class AndroidPackageUtils {
|
||||
public static void validatePackageDexMetadata(AndroidPackage pkg)
|
||||
throws PackageParserException {
|
||||
Collection<String> apkToDexMetadataList = getPackageDexMetadata(pkg).values();
|
||||
String packageName = pkg.getPackageName();
|
||||
long versionCode = pkg.toAppInfoWithoutState().longVersionCode;
|
||||
for (String dexMetadata : apkToDexMetadataList) {
|
||||
DexMetadataHelper.validateDexMetadataFile(dexMetadata);
|
||||
DexMetadataHelper.validateDexMetadataFile(dexMetadata, packageName, versionCode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.frameworks.servicestests.R;
|
||||
import com.android.server.pm.parsing.TestPackageParser2;
|
||||
import com.android.server.pm.parsing.pkg.AndroidPackage;
|
||||
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
|
||||
import com.android.server.pm.parsing.pkg.ParsedPackage;
|
||||
|
||||
@@ -57,6 +58,8 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
@@ -66,6 +69,9 @@ import java.util.zip.ZipOutputStream;
|
||||
public class DexMetadataHelperTest {
|
||||
private static final String APK_FILE_EXTENSION = ".apk";
|
||||
private static final String DEX_METADATA_FILE_EXTENSION = ".dm";
|
||||
private static final String DEX_METADATA_PACKAGE_NAME =
|
||||
"com.android.frameworks.servicestests.install_split";
|
||||
private static long DEX_METADATA_VERSION_CODE = 30;
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
|
||||
@@ -78,12 +84,46 @@ public class DexMetadataHelperTest {
|
||||
}
|
||||
|
||||
private File createDexMetadataFile(String apkFileName) throws IOException {
|
||||
return createDexMetadataFile(apkFileName, /*validManifest=*/true);
|
||||
}
|
||||
|
||||
private File createDexMetadataFile(String apkFileName, boolean validManifest) throws IOException
|
||||
{
|
||||
return createDexMetadataFile(apkFileName,DEX_METADATA_PACKAGE_NAME,
|
||||
DEX_METADATA_VERSION_CODE, /*emptyManifest=*/false, validManifest);
|
||||
}
|
||||
|
||||
private File createDexMetadataFile(String apkFileName, String packageName, Long versionCode,
|
||||
boolean emptyManifest, boolean validManifest) throws IOException {
|
||||
File dmFile = new File(mTmpDir, apkFileName.replace(APK_FILE_EXTENSION,
|
||||
DEX_METADATA_FILE_EXTENSION));
|
||||
try (FileOutputStream fos = new FileOutputStream(dmFile)) {
|
||||
try (ZipOutputStream zipOs = new ZipOutputStream(fos)) {
|
||||
zipOs.putNextEntry(new ZipEntry("primary.prof"));
|
||||
zipOs.closeEntry();
|
||||
|
||||
if (validManifest) {
|
||||
zipOs.putNextEntry(new ZipEntry("manifest.json"));
|
||||
if (!emptyManifest) {
|
||||
String manifestStr = "{";
|
||||
|
||||
if (packageName != null) {
|
||||
manifestStr += "\"packageName\": " + "\"" + packageName + "\"";
|
||||
|
||||
if (versionCode != null) {
|
||||
manifestStr += ", ";
|
||||
}
|
||||
}
|
||||
if (versionCode != null) {
|
||||
manifestStr += " \"versionCode\": " + versionCode;
|
||||
}
|
||||
|
||||
manifestStr += "}";
|
||||
byte[] bytes = manifestStr.getBytes(StandardCharsets.UTF_8);
|
||||
zipOs.write(bytes, /*off=*/0, /*len=*/bytes.length);
|
||||
}
|
||||
zipOs.closeEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
return dmFile;
|
||||
@@ -98,17 +138,38 @@ public class DexMetadataHelperTest {
|
||||
return outFile;
|
||||
}
|
||||
|
||||
private static void validatePackageDexMetadata(AndroidPackage pkg, boolean requireManifest)
|
||||
throws PackageParserException {
|
||||
Collection<String> apkToDexMetadataList =
|
||||
AndroidPackageUtils.getPackageDexMetadata(pkg).values();
|
||||
String packageName = pkg.getPackageName();
|
||||
long versionCode = pkg.toAppInfoWithoutState().longVersionCode;
|
||||
for (String dexMetadata : apkToDexMetadataList) {
|
||||
DexMetadataHelper.validateDexMetadataFile(
|
||||
dexMetadata, packageName, versionCode, requireManifest);
|
||||
}
|
||||
}
|
||||
|
||||
private static void validatePackageDexMetatadataVaryingRequireManifest(ParsedPackage pkg)
|
||||
throws PackageParserException {
|
||||
validatePackageDexMetadata(pkg, /*requireManifest=*/true);
|
||||
validatePackageDexMetadata(pkg, /*requireManifest=*/false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParsePackageWithDmFileValid() throws IOException, PackageParserException {
|
||||
copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
|
||||
createDexMetadataFile("install_split_base.apk");
|
||||
ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, 0 /* flags */, false);
|
||||
ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false);
|
||||
|
||||
Map<String, String> packageDexMetadata = AndroidPackageUtils.getPackageDexMetadata(pkg);
|
||||
assertEquals(1, packageDexMetadata.size());
|
||||
String baseDexMetadata = packageDexMetadata.get(pkg.getBaseCodePath());
|
||||
assertNotNull(baseDexMetadata);
|
||||
assertTrue(isDexMetadataForApk(baseDexMetadata, pkg.getBaseCodePath()));
|
||||
|
||||
// Should throw no exceptions.
|
||||
validatePackageDexMetatadataVaryingRequireManifest(pkg);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -118,7 +179,7 @@ public class DexMetadataHelperTest {
|
||||
copyApkToToTmpDir("install_split_feature_a.apk", R.raw.install_split_feature_a);
|
||||
createDexMetadataFile("install_split_base.apk");
|
||||
createDexMetadataFile("install_split_feature_a.apk");
|
||||
ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, 0 /* flags */, false);
|
||||
ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false);
|
||||
|
||||
Map<String, String> packageDexMetadata = AndroidPackageUtils.getPackageDexMetadata(pkg);
|
||||
assertEquals(2, packageDexMetadata.size());
|
||||
@@ -129,6 +190,9 @@ public class DexMetadataHelperTest {
|
||||
String splitDexMetadata = packageDexMetadata.get(pkg.getSplitCodePaths()[0]);
|
||||
assertNotNull(splitDexMetadata);
|
||||
assertTrue(isDexMetadataForApk(splitDexMetadata, pkg.getSplitCodePaths()[0]));
|
||||
|
||||
// Should throw no exceptions.
|
||||
validatePackageDexMetatadataVaryingRequireManifest(pkg);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -137,7 +201,7 @@ public class DexMetadataHelperTest {
|
||||
copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
|
||||
copyApkToToTmpDir("install_split_feature_a.apk", R.raw.install_split_feature_a);
|
||||
createDexMetadataFile("install_split_feature_a.apk");
|
||||
ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, 0 /* flags */, false);
|
||||
ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false);
|
||||
|
||||
Map<String, String> packageDexMetadata = AndroidPackageUtils.getPackageDexMetadata(pkg);
|
||||
assertEquals(1, packageDexMetadata.size());
|
||||
@@ -145,6 +209,9 @@ public class DexMetadataHelperTest {
|
||||
String splitDexMetadata = packageDexMetadata.get(pkg.getSplitCodePaths()[0]);
|
||||
assertNotNull(splitDexMetadata);
|
||||
assertTrue(isDexMetadataForApk(splitDexMetadata, pkg.getSplitCodePaths()[0]));
|
||||
|
||||
// Should throw no exceptions.
|
||||
validatePackageDexMetatadataVaryingRequireManifest(pkg);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -153,9 +220,17 @@ public class DexMetadataHelperTest {
|
||||
File invalidDmFile = new File(mTmpDir, "install_split_base.dm");
|
||||
Files.createFile(invalidDmFile.toPath());
|
||||
try {
|
||||
ParsedPackage pkg = new TestPackageParser2()
|
||||
.parsePackage(mTmpDir, 0 /* flags */, false);
|
||||
AndroidPackageUtils.validatePackageDexMetadata(pkg);
|
||||
ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false);
|
||||
validatePackageDexMetadata(pkg, /*requireManifest=*/true);
|
||||
fail("Should fail validation: empty .dm file");
|
||||
} catch (PackageParserException e) {
|
||||
assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA);
|
||||
}
|
||||
|
||||
try {
|
||||
ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false);
|
||||
validatePackageDexMetadata(pkg, /*requireManifest=*/false);
|
||||
fail("Should fail validation: empty .dm file");
|
||||
} catch (PackageParserException e) {
|
||||
assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA);
|
||||
}
|
||||
@@ -171,9 +246,112 @@ public class DexMetadataHelperTest {
|
||||
Files.createFile(invalidDmFile.toPath());
|
||||
|
||||
try {
|
||||
ParsedPackage pkg = new TestPackageParser2()
|
||||
.parsePackage(mTmpDir, 0 /* flags */, false);
|
||||
AndroidPackageUtils.validatePackageDexMetadata(pkg);
|
||||
ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false);
|
||||
validatePackageDexMetadata(pkg, /*requireManifest=*/true);
|
||||
fail("Should fail validation: empty .dm file");
|
||||
} catch (PackageParserException e) {
|
||||
assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA);
|
||||
}
|
||||
|
||||
try {
|
||||
ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false);
|
||||
validatePackageDexMetadata(pkg, /*requireManifest=*/false);
|
||||
fail("Should fail validation: empty .dm file");
|
||||
} catch (PackageParserException e) {
|
||||
assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParsePackageWithDmFileInvalidManifest()
|
||||
throws IOException, PackageParserException {
|
||||
copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
|
||||
createDexMetadataFile("install_split_base.apk", /*validManifest=*/false);
|
||||
|
||||
try {
|
||||
ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false);
|
||||
validatePackageDexMetadata(pkg, /*requireManifest=*/true);
|
||||
fail("Should fail validation: missing manifest.json in the .dm archive");
|
||||
} catch (PackageParserException e) {
|
||||
assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParsePackageWithDmFileEmptyManifest()
|
||||
throws IOException, PackageParserException {
|
||||
copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
|
||||
createDexMetadataFile("install_split_base.apk", /*packageName=*/"doesn't matter",
|
||||
/*versionCode=*/-12345L, /*emptyManifest=*/true, /*validManifest=*/true);
|
||||
|
||||
try {
|
||||
ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false);
|
||||
validatePackageDexMetadata(pkg, /*requireManifest=*/true);
|
||||
fail("Should fail validation: empty manifest.json in the .dm archive");
|
||||
} catch (PackageParserException e) {
|
||||
assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParsePackageWithDmFileBadPackageName()
|
||||
throws IOException, PackageParserException {
|
||||
copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
|
||||
createDexMetadataFile("install_split_base.apk", /*packageName=*/"bad package name",
|
||||
DEX_METADATA_VERSION_CODE, /*emptyManifest=*/false, /*validManifest=*/true);
|
||||
|
||||
try {
|
||||
ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false);
|
||||
validatePackageDexMetadata(pkg, /*requireManifest=*/true);
|
||||
fail("Should fail validation: bad package name in the .dm archive");
|
||||
} catch (PackageParserException e) {
|
||||
assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParsePackageWithDmFileBadVersionCode()
|
||||
throws IOException, PackageParserException {
|
||||
copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
|
||||
createDexMetadataFile("install_split_base.apk", DEX_METADATA_PACKAGE_NAME,
|
||||
/*versionCode=*/12345L, /*emptyManifest=*/false, /*validManifest=*/true);
|
||||
|
||||
try {
|
||||
ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false);
|
||||
validatePackageDexMetadata(pkg, /*requireManifest=*/true);
|
||||
fail("Should fail validation: bad version code in the .dm archive");
|
||||
} catch (PackageParserException e) {
|
||||
assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParsePackageWithDmFileMissingPackageName()
|
||||
throws IOException, PackageParserException {
|
||||
copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
|
||||
createDexMetadataFile("install_split_base.apk", /*packageName=*/null,
|
||||
DEX_METADATA_VERSION_CODE, /*emptyManifest=*/false, /*validManifest=*/true);
|
||||
|
||||
try {
|
||||
ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false);
|
||||
validatePackageDexMetadata(pkg, /*requireManifest=*/true);
|
||||
fail("Should fail validation: missing package name in the .dm archive");
|
||||
} catch (PackageParserException e) {
|
||||
assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParsePackageWithDmFileMissingVersionCode()
|
||||
throws IOException, PackageParserException {
|
||||
copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
|
||||
createDexMetadataFile("install_split_base.apk", DEX_METADATA_PACKAGE_NAME,
|
||||
/*versionCode=*/null, /*emptyManifest=*/false, /*validManifest=*/true);
|
||||
|
||||
try {
|
||||
ParsedPackage pkg = new TestPackageParser2().parsePackage(mTmpDir, /*flags=*/0, false);
|
||||
validatePackageDexMetadata(pkg, /*requireManifest=*/true);
|
||||
fail("Should fail validation: missing version code in the .dm archive");
|
||||
} catch (PackageParserException e) {
|
||||
assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA);
|
||||
}
|
||||
@@ -186,7 +364,7 @@ public class DexMetadataHelperTest {
|
||||
|
||||
try {
|
||||
DexMetadataHelper.validateDexPaths(mTmpDir.list());
|
||||
fail("Should fail validation");
|
||||
fail("Should fail validation: split .dm filename unmatched against .apk");
|
||||
} catch (IllegalStateException e) {
|
||||
// expected.
|
||||
}
|
||||
@@ -202,7 +380,7 @@ public class DexMetadataHelperTest {
|
||||
|
||||
try {
|
||||
DexMetadataHelper.validateDexPaths(mTmpDir.list());
|
||||
fail("Should fail validation");
|
||||
fail("Should fail validation: .dm filename has no match against .apk");
|
||||
} catch (IllegalStateException e) {
|
||||
// expected.
|
||||
}
|
||||
@@ -214,7 +392,7 @@ public class DexMetadataHelperTest {
|
||||
copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
|
||||
File dm = createDexMetadataFile("install_split_base.apk");
|
||||
ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite(
|
||||
ParseTypeImpl.forDefaultParsing().reset(), mTmpDir, 0 /* flags */);
|
||||
ParseTypeImpl.forDefaultParsing().reset(), mTmpDir, /*flags=*/0);
|
||||
if (result.isError()) {
|
||||
throw new IllegalStateException(result.getErrorMessage(), result.getException());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user