summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYohann Roussel <yroussel@google.com>2018-01-22 15:28:50 +0000
committerandroid-build-merger <android-build-merger@google.com>2018-01-22 15:28:50 +0000
commitb9693ede38ec67d5bcfb2efd413aa3ab11b870eb (patch)
treeb3ef2bdb853f145d5249a28838482ebddfae5dd8
parent0baaa696211975b17156d7faa34790cc9593b830 (diff)
parent88e540c4dc424d0ac574ffce1069ed9a92e7d024 (diff)
downloadmultidex-b9693ede38ec67d5bcfb2efd413aa3ab11b870eb.tar.gz
Use a rewriten makeDexElement on V 14 to 18 am: b2483811cf am: 5c2b756124
am: 88e540c4dc Change-Id: I166a9da6525494e3959ff6634a492a532e20d2ec
-rw-r--r--library/src/android/support/multidex/MultiDex.java80
-rw-r--r--library/src/android/support/multidex/MultiDexExtractor.java4
2 files changed, 61 insertions, 23 deletions
diff --git a/library/src/android/support/multidex/MultiDex.java b/library/src/android/support/multidex/MultiDex.java
index 646e023..2b681db 100644
--- a/library/src/android/support/multidex/MultiDex.java
+++ b/library/src/android/support/multidex/MultiDex.java
@@ -28,6 +28,7 @@ import dalvik.system.DexFile;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -202,7 +203,8 @@ public final class MultiDex {
String secondaryFolderName, String prefsKeyPrefix,
boolean reinstallOnPatchRecoverableException) throws IOException,
IllegalArgumentException, IllegalAccessException, NoSuchFieldException,
- InvocationTargetException, NoSuchMethodException {
+ InvocationTargetException, NoSuchMethodException, SecurityException,
+ ClassNotFoundException, InstantiationException {
synchronized (installedApk) {
if (installedApk.contains(sourceApk)) {
return;
@@ -340,12 +342,13 @@ public final class MultiDex {
private static void installSecondaryDexes(ClassLoader loader, File dexDir,
List<? extends File> files)
throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException,
- InvocationTargetException, NoSuchMethodException, IOException {
+ InvocationTargetException, NoSuchMethodException, IOException, SecurityException,
+ ClassNotFoundException, InstantiationException {
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);
+ V14.install(loader, files);
} else {
V4.install(loader, files);
}
@@ -495,7 +498,7 @@ public final class MultiDex {
*/
private static final class V19 {
- private static void install(ClassLoader loader,
+ static void install(ClassLoader loader,
List<? extends File> additionalClassPathEntries,
File optimizedDirectory)
throws IllegalArgumentException, IllegalAccessException,
@@ -566,11 +569,16 @@ public final class MultiDex {
*/
private static final class V14 {
- private static void install(ClassLoader loader,
- List<? extends File> additionalClassPathEntries,
- File optimizedDirectory)
- throws IllegalArgumentException, IllegalAccessException,
- NoSuchFieldException, InvocationTargetException, NoSuchMethodException {
+ private static final int EXTRACTED_SUFFIX_LENGTH =
+ MultiDexExtractor.EXTRACTED_SUFFIX.length();
+
+ private final Constructor<?> elementConstructor;
+
+ static void install(ClassLoader loader,
+ List<? extends File> additionalClassPathEntries)
+ throws IOException, SecurityException, IllegalArgumentException,
+ ClassNotFoundException, NoSuchMethodException, InstantiationException,
+ IllegalAccessException, InvocationTargetException, NoSuchFieldException {
/* The patched class loader is expected to be a descendant of
* dalvik.system.BaseDexClassLoader. We modify its
* dalvik.system.DexPathList pathList field to append additional DEX
@@ -578,22 +586,52 @@ public final class MultiDex {
*/
Field pathListField = findField(loader, "pathList");
Object dexPathList = pathListField.get(loader);
- expandFieldArray(dexPathList, "dexElements", makeDexElements(dexPathList,
- new ArrayList<File>(additionalClassPathEntries), optimizedDirectory));
+ expandFieldArray(dexPathList, "dexElements",
+ new V14().makeDexElements(additionalClassPathEntries));
+ }
+
+ private V14() throws ClassNotFoundException, SecurityException, NoSuchMethodException {
+ Class<?> elementClass = Class.forName("dalvik.system.DexPathList$Element");
+ elementConstructor =
+ elementClass.getConstructor(File.class, ZipFile.class, DexFile.class);
+ elementConstructor.setAccessible(true);
}
/**
- * A wrapper around
- * {@code private static final dalvik.system.DexPathList#makeDexElements}.
+ * An emulation of {@code private static final dalvik.system.DexPathList#makeDexElements}
+ * accepting only extracted secondary dex files.
+ * OS version is catching IOException and just logging some of them, this version is letting
+ * them through.
*/
- private static Object[] makeDexElements(
- Object dexPathList, ArrayList<File> files, File optimizedDirectory)
- throws IllegalAccessException, InvocationTargetException,
- NoSuchMethodException {
- Method makeDexElements =
- findMethod(dexPathList, "makeDexElements", ArrayList.class, File.class);
+ private Object[] makeDexElements(List<? extends File> files)
+ throws IOException, SecurityException, IllegalArgumentException,
+ InstantiationException, IllegalAccessException, InvocationTargetException {
+ Object[] elements = new Object[files.size()];
+ for (int i = 0; i < elements.length; i++) {
+ File file = files.get(i);
+ elements[i] = elementConstructor.newInstance(
+ file,
+ new ZipFile(file),
+ DexFile.loadDex(file.getPath(), optimizedPathFor(file), 0));
+ }
+ return elements;
+ }
- return (Object[]) makeDexElements.invoke(dexPathList, files, optimizedDirectory);
+ /**
+ * Converts a zip file path of an extracted secondary dex to an output file path for an
+ * associated optimized dex file.
+ */
+ private static String optimizedPathFor(File path) {
+ // Any reproducible name ending with ".dex" should do but lets keep the same name
+ // as DexPathList.optimizedPathFor
+
+ File optimizedDirectory = path.getParentFile();
+ String fileName = path.getName();
+ String optimizedFileName =
+ fileName.substring(0, fileName.length() - EXTRACTED_SUFFIX_LENGTH)
+ + MultiDexExtractor.DEX_SUFFIX;
+ File result = new File(optimizedDirectory, optimizedFileName);
+ return result.getPath();
}
}
@@ -601,7 +639,7 @@ public final class MultiDex {
* Installer for platform versions 4 to 13.
*/
private static final class V4 {
- private static void install(ClassLoader loader,
+ static void install(ClassLoader loader,
List<? extends File> additionalClassPathEntries)
throws IllegalArgumentException, IllegalAccessException,
NoSuchFieldException, IOException {
diff --git a/library/src/android/support/multidex/MultiDexExtractor.java b/library/src/android/support/multidex/MultiDexExtractor.java
index ed3c125..f0fd6d4 100644
--- a/library/src/android/support/multidex/MultiDexExtractor.java
+++ b/library/src/android/support/multidex/MultiDexExtractor.java
@@ -63,10 +63,10 @@ final class MultiDexExtractor implements Closeable {
* {@code classes3.dex}, etc.
*/
private static final String DEX_PREFIX = "classes";
- private static final String DEX_SUFFIX = ".dex";
+ static final String DEX_SUFFIX = ".dex";
private static final String EXTRACTED_NAME_EXT = ".classes";
- private static final String EXTRACTED_SUFFIX = ".zip";
+ static final String EXTRACTED_SUFFIX = ".zip";
private static final int MAX_EXTRACT_ATTEMPTS = 3;
private static final String PREFS_FILE = "multidex.version";