merge in pi-release history after reset to master
diff --git a/library/src/android/support/multidex/MultiDex.java b/library/src/android/support/multidex/MultiDex.java
index 2b681db..646e023 100644
--- a/library/src/android/support/multidex/MultiDex.java
+++ b/library/src/android/support/multidex/MultiDex.java
@@ -28,7 +28,6 @@
 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;
@@ -203,8 +202,7 @@
             String secondaryFolderName, String prefsKeyPrefix,
             boolean reinstallOnPatchRecoverableException) throws IOException,
                 IllegalArgumentException, IllegalAccessException, NoSuchFieldException,
-                InvocationTargetException, NoSuchMethodException, SecurityException,
-                ClassNotFoundException, InstantiationException {
+                InvocationTargetException, NoSuchMethodException {
         synchronized (installedApk) {
             if (installedApk.contains(sourceApk)) {
                 return;
@@ -342,13 +340,12 @@
     private static void installSecondaryDexes(ClassLoader loader, File dexDir,
         List<? extends File> files)
             throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException,
-            InvocationTargetException, NoSuchMethodException, IOException, SecurityException,
-            ClassNotFoundException, InstantiationException {
+            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);
+                V14.install(loader, files, dexDir);
             } else {
                 V4.install(loader, files);
             }
@@ -498,7 +495,7 @@
      */
     private static final class V19 {
 
-        static void install(ClassLoader loader,
+        private static void install(ClassLoader loader,
                 List<? extends File> additionalClassPathEntries,
                 File optimizedDirectory)
                         throws IllegalArgumentException, IllegalAccessException,
@@ -569,16 +566,11 @@
      */
     private static final class V14 {
 
-        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 {
+        private static void install(ClassLoader loader,
+                List<? extends File> additionalClassPathEntries,
+                File optimizedDirectory)
+                        throws IllegalArgumentException, IllegalAccessException,
+                        NoSuchFieldException, InvocationTargetException, NoSuchMethodException {
             /* 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
@@ -586,52 +578,22 @@
              */
             Field pathListField = findField(loader, "pathList");
             Object dexPathList = pathListField.get(loader);
-            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);
+            expandFieldArray(dexPathList, "dexElements", makeDexElements(dexPathList,
+                    new ArrayList<File>(additionalClassPathEntries), optimizedDirectory));
         }
 
         /**
-         * 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.
+         * A wrapper around
+         * {@code private static final dalvik.system.DexPathList#makeDexElements}.
          */
-        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;
-        }
+        private static Object[] makeDexElements(
+                Object dexPathList, ArrayList<File> files, File optimizedDirectory)
+                        throws IllegalAccessException, InvocationTargetException,
+                        NoSuchMethodException {
+            Method makeDexElements =
+                    findMethod(dexPathList, "makeDexElements", ArrayList.class, File.class);
 
-        /**
-         * 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();
+            return (Object[]) makeDexElements.invoke(dexPathList, files, optimizedDirectory);
         }
     }
 
@@ -639,7 +601,7 @@
      * Installer for platform versions 4 to 13.
      */
     private static final class V4 {
-        static void install(ClassLoader loader,
+        private 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 f0fd6d4..ed3c125 100644
--- a/library/src/android/support/multidex/MultiDexExtractor.java
+++ b/library/src/android/support/multidex/MultiDexExtractor.java
@@ -63,10 +63,10 @@
      * {@code classes3.dex}, etc.
      */
     private static final String DEX_PREFIX = "classes";
-    static final String DEX_SUFFIX = ".dex";
+    private static final String DEX_SUFFIX = ".dex";
 
     private static final String EXTRACTED_NAME_EXT = ".classes";
-    static final String EXTRACTED_SUFFIX = ".zip";
+    private static final String EXTRACTED_SUFFIX = ".zip";
     private static final int MAX_EXTRACT_ATTEMPTS = 3;
 
     private static final String PREFS_FILE = "multidex.version";