Add additional check for valid Zip file before multidex install
Bug: 11895788
Change-Id: Id4f6e5b09be809eeb29367bebe78c03e49864cbf
diff --git a/library/src/android/support/multidex/MultiDex.java b/library/src/android/support/multidex/MultiDex.java
index 064c66a..7a99142 100644
--- a/library/src/android/support/multidex/MultiDex.java
+++ b/library/src/android/support/multidex/MultiDex.java
@@ -151,14 +151,18 @@
}
File dexDir = new File(context.getFilesDir(), SECONDARY_FOLDER_NAME);
- List<File> files = MultiDexExtractor.load(applicationInfo, dexDir);
- if (!files.isEmpty()) {
- if (Build.VERSION.SDK_INT >= 19) {
- V19.install(loader, files, dexDir);
- } else if (Build.VERSION.SDK_INT >= 14) {
- V14.install(loader, files, dexDir);
+ List<File> files = MultiDexExtractor.load(applicationInfo, dexDir, false);
+ if (checkValidZipFiles(files)) {
+ installSecondaryDexes(loader, dexDir, files);
+ } else {
+ Log.w(TAG, "Files were not valid zip files. Forcing a reload.");
+ // Try again, but this time force a reload of the zip file.
+ files = MultiDexExtractor.load(applicationInfo, dexDir, true);
+ if (checkValidZipFiles(files)) {
+ installSecondaryDexes(loader, dexDir, files);
} else {
- V4.install(loader, files);
+ // Second time didn't work, give up
+ throw new RuntimeException("Zip files were not valid.");
}
}
}
@@ -169,6 +173,33 @@
}
}
+ private static void installSecondaryDexes(ClassLoader loader, File dexDir, List<File> files)
+ throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException,
+ InvocationTargetException, NoSuchMethodException, IOException {
+ if (!files.isEmpty()) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ V19.install(loader, files, dexDir);
+ } else if (Build.VERSION.SDK_INT >= 14) {
+ V14.install(loader, files, dexDir);
+ } else {
+ V4.install(loader, files);
+ }
+ }
+ }
+
+ /**
+ * Returns whether all files in the list are valid zip files. If {@code files} is empty, then
+ * returns true.
+ */
+ private static boolean checkValidZipFiles(List<File> files) {
+ for (File file : files) {
+ if (!MultiDexExtractor.verifyZipFile(file)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
/**
* Locates a given field anywhere in the class inheritance hierarchy.
*
diff --git a/library/src/android/support/multidex/MultiDexExtractor.java b/library/src/android/support/multidex/MultiDexExtractor.java
index e9eec82..66bf75f 100644
--- a/library/src/android/support/multidex/MultiDexExtractor.java
+++ b/library/src/android/support/multidex/MultiDexExtractor.java
@@ -64,9 +64,9 @@
* @throws IOException if encounters a problem while reading or writing
* secondary dex files
*/
- static List<File> load(ApplicationInfo applicationInfo, File dexDir)
+ static List<File> load(ApplicationInfo applicationInfo, File dexDir, boolean forceReload)
throws IOException {
- Log.i(TAG, "load(" + applicationInfo.sourceDir + ")");
+ Log.i(TAG, "load(" + applicationInfo.sourceDir + ", forceReload=" + forceReload + ")");
File sourceApk = new File(applicationInfo.sourceDir);
long lastModified = sourceApk.lastModified();
String extractedFilePrefix = sourceApk.getName()
@@ -87,7 +87,7 @@
files.add(extractedFile);
Log.i(TAG, "Need extracted file " + extractedFile);
- if (!extractedFile.isFile()) {
+ if (forceReload || !extractedFile.isFile()) {
Log.i(TAG, "Extraction is needed for file " + extractedFile);
int numAttempts = 0;
boolean isExtractionSuccessful = false;
@@ -133,6 +133,10 @@
return files;
}
+ /**
+ * This removes any old zip and dex files or extraneous files from the secondary-dexes
+ * directory.
+ */
private static void prepareDexDir(File dexDir, final String extractedFilePrefix,
final long sourceLastModified) throws IOException {
dexDir.mkdir();
@@ -146,7 +150,7 @@
@Override
public boolean accept(File pathname) {
return (!pathname.getName().startsWith(extractedFilePrefix))
- || (pathname.lastModified() < sourceLastModified);
+ || (pathname.lastModified() < sourceLastModified);
}
};
File[] files = dexDir.listFiles(filter);
@@ -209,7 +213,7 @@
/**
* Returns whether the file is a valid zip file.
*/
- private static boolean verifyZipFile(File file) {
+ static boolean verifyZipFile(File file) {
try {
ZipFile zipFile = new ZipFile(file);
try {