mirror of
https://github.com/Pinball3D/Rabbit-R1.git
synced 2024-12-26 09:02:34 -06:00
451 lines
22 KiB
Java
451 lines
22 KiB
Java
package androidx.multidex;
|
|
|
|
import android.content.Context;
|
|
import android.content.pm.ApplicationInfo;
|
|
import android.os.Build;
|
|
import android.util.Log;
|
|
import dalvik.system.BaseDexClassLoader;
|
|
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;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.ListIterator;
|
|
import java.util.Set;
|
|
import java.util.StringTokenizer;
|
|
import java.util.zip.ZipFile;
|
|
|
|
/* loaded from: classes2.dex */
|
|
public final class MultiDex {
|
|
private static final String CODE_CACHE_NAME = "code_cache";
|
|
private static final String CODE_CACHE_SECONDARY_FOLDER_NAME = "secondary-dexes";
|
|
private static final int MAX_SUPPORTED_SDK_VERSION = 20;
|
|
private static final int MIN_SDK_VERSION = 4;
|
|
private static final String NO_KEY_PREFIX = "";
|
|
private static final String OLD_SECONDARY_FOLDER_NAME = "secondary-dexes";
|
|
static final String TAG = "MultiDex";
|
|
private static final int VM_WITH_MULTIDEX_VERSION_MAJOR = 2;
|
|
private static final int VM_WITH_MULTIDEX_VERSION_MINOR = 1;
|
|
private static final Set<File> installedApk = new HashSet();
|
|
private static final boolean IS_VM_MULTIDEX_CAPABLE = isVMMultidexCapable(System.getProperty("java.vm.version"));
|
|
|
|
private MultiDex() {
|
|
}
|
|
|
|
public static void install(Context context) {
|
|
Log.i(TAG, "Installing application");
|
|
if (IS_VM_MULTIDEX_CAPABLE) {
|
|
Log.i(TAG, "VM has multidex support, MultiDex support library is disabled.");
|
|
return;
|
|
}
|
|
try {
|
|
ApplicationInfo applicationInfo = getApplicationInfo(context);
|
|
if (applicationInfo == null) {
|
|
Log.i(TAG, "No ApplicationInfo available, i.e. running on a test Context: MultiDex support library is disabled.");
|
|
} else {
|
|
doInstallation(context, new File(applicationInfo.sourceDir), new File(applicationInfo.dataDir), "secondary-dexes", "", true);
|
|
Log.i(TAG, "install done");
|
|
}
|
|
} catch (Exception e) {
|
|
Log.e(TAG, "MultiDex installation failure", e);
|
|
throw new RuntimeException("MultiDex installation failed (" + e.getMessage() + ").");
|
|
}
|
|
}
|
|
|
|
public static void installInstrumentation(Context context, Context context2) {
|
|
Log.i(TAG, "Installing instrumentation");
|
|
if (IS_VM_MULTIDEX_CAPABLE) {
|
|
Log.i(TAG, "VM has multidex support, MultiDex support library is disabled.");
|
|
return;
|
|
}
|
|
try {
|
|
ApplicationInfo applicationInfo = getApplicationInfo(context);
|
|
if (applicationInfo == null) {
|
|
Log.i(TAG, "No ApplicationInfo available for instrumentation, i.e. running on a test Context: MultiDex support library is disabled.");
|
|
return;
|
|
}
|
|
ApplicationInfo applicationInfo2 = getApplicationInfo(context2);
|
|
if (applicationInfo2 == null) {
|
|
Log.i(TAG, "No ApplicationInfo available, i.e. running on a test Context: MultiDex support library is disabled.");
|
|
return;
|
|
}
|
|
String str = context.getPackageName() + ".";
|
|
File file = new File(applicationInfo2.dataDir);
|
|
doInstallation(context2, new File(applicationInfo.sourceDir), file, str + "secondary-dexes", str, false);
|
|
doInstallation(context2, new File(applicationInfo2.sourceDir), file, "secondary-dexes", "", false);
|
|
Log.i(TAG, "Installation done");
|
|
} catch (Exception e) {
|
|
Log.e(TAG, "MultiDex installation failure", e);
|
|
throw new RuntimeException("MultiDex installation failed (" + e.getMessage() + ").");
|
|
}
|
|
}
|
|
|
|
private static void doInstallation(Context context, File file, File file2, String str, String str2, boolean z) throws IOException, IllegalArgumentException, IllegalAccessException, NoSuchFieldException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException, InstantiationException {
|
|
Set<File> set = installedApk;
|
|
synchronized (set) {
|
|
if (set.contains(file)) {
|
|
return;
|
|
}
|
|
set.add(file);
|
|
Log.w(TAG, "MultiDex is not guaranteed to work in SDK version " + Build.VERSION.SDK_INT + ": SDK version higher than 20 should be backed by runtime with built-in multidex capabilty but it's not the case here: java.vm.version=\"" + System.getProperty("java.vm.version") + "\"");
|
|
ClassLoader dexClassloader = getDexClassloader(context);
|
|
if (dexClassloader == null) {
|
|
return;
|
|
}
|
|
try {
|
|
clearOldDexDir(context);
|
|
} catch (Throwable th) {
|
|
Log.w(TAG, "Something went wrong when trying to clear old MultiDex extraction, continuing without cleaning.", th);
|
|
}
|
|
File dexDir = getDexDir(context, file2, str);
|
|
MultiDexExtractor multiDexExtractor = new MultiDexExtractor(file, dexDir);
|
|
try {
|
|
try {
|
|
installSecondaryDexes(dexClassloader, dexDir, multiDexExtractor.load(context, str2, false));
|
|
} catch (IOException e) {
|
|
if (!z) {
|
|
throw e;
|
|
}
|
|
Log.w(TAG, "Failed to install extracted secondary dex files, retrying with forced extraction", e);
|
|
installSecondaryDexes(dexClassloader, dexDir, multiDexExtractor.load(context, str2, true));
|
|
}
|
|
try {
|
|
e = null;
|
|
} catch (IOException e2) {
|
|
e = e2;
|
|
}
|
|
if (e != null) {
|
|
throw e;
|
|
}
|
|
} finally {
|
|
try {
|
|
multiDexExtractor.close();
|
|
} catch (IOException unused) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static ClassLoader getDexClassloader(Context context) {
|
|
try {
|
|
ClassLoader classLoader = context.getClassLoader();
|
|
if (classLoader instanceof BaseDexClassLoader) {
|
|
return classLoader;
|
|
}
|
|
Log.e(TAG, "Context class loader is null or not dex-capable. Must be running in test mode. Skip patching.");
|
|
return null;
|
|
} catch (RuntimeException e) {
|
|
Log.w(TAG, "Failure while trying to obtain Context class loader. Must be running in test mode. Skip patching.", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static ApplicationInfo getApplicationInfo(Context context) {
|
|
try {
|
|
return context.getApplicationInfo();
|
|
} catch (RuntimeException e) {
|
|
Log.w(TAG, "Failure while trying to obtain ApplicationInfo from Context. Must be running in test mode. Skip patching.", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
static boolean isVMMultidexCapable(String str) {
|
|
boolean z = false;
|
|
if (str != null) {
|
|
StringTokenizer stringTokenizer = new StringTokenizer(str, ".");
|
|
String nextToken = stringTokenizer.hasMoreTokens() ? stringTokenizer.nextToken() : null;
|
|
String nextToken2 = stringTokenizer.hasMoreTokens() ? stringTokenizer.nextToken() : null;
|
|
if (nextToken != null && nextToken2 != null) {
|
|
try {
|
|
int parseInt = Integer.parseInt(nextToken);
|
|
int parseInt2 = Integer.parseInt(nextToken2);
|
|
if (parseInt > 2 || (parseInt == 2 && parseInt2 >= 1)) {
|
|
z = true;
|
|
}
|
|
} catch (NumberFormatException unused) {
|
|
}
|
|
}
|
|
}
|
|
Log.i(TAG, "VM with version " + str + (z ? " has multidex support" : " does not have multidex support"));
|
|
return z;
|
|
}
|
|
|
|
private static void installSecondaryDexes(ClassLoader classLoader, File file, List<? extends File> list) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, InvocationTargetException, NoSuchMethodException, IOException, SecurityException, ClassNotFoundException, InstantiationException {
|
|
if (list.isEmpty()) {
|
|
return;
|
|
}
|
|
V19.install(classLoader, list, file);
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: private */
|
|
public static Field findField(Object obj, String str) throws NoSuchFieldException {
|
|
for (Class<?> cls = obj.getClass(); cls != null; cls = cls.getSuperclass()) {
|
|
try {
|
|
Field declaredField = cls.getDeclaredField(str);
|
|
if (!declaredField.isAccessible()) {
|
|
declaredField.setAccessible(true);
|
|
}
|
|
return declaredField;
|
|
} catch (NoSuchFieldException unused) {
|
|
}
|
|
}
|
|
throw new NoSuchFieldException("Field " + str + " not found in " + obj.getClass());
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: private */
|
|
public static Method findMethod(Object obj, String str, Class<?>... clsArr) throws NoSuchMethodException {
|
|
for (Class<?> cls = obj.getClass(); cls != null; cls = cls.getSuperclass()) {
|
|
try {
|
|
Method declaredMethod = cls.getDeclaredMethod(str, clsArr);
|
|
if (!declaredMethod.isAccessible()) {
|
|
declaredMethod.setAccessible(true);
|
|
}
|
|
return declaredMethod;
|
|
} catch (NoSuchMethodException unused) {
|
|
}
|
|
}
|
|
throw new NoSuchMethodException("Method " + str + " with parameters " + Arrays.asList(clsArr) + " not found in " + obj.getClass());
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: private */
|
|
public static void expandFieldArray(Object obj, String str, Object[] objArr) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
|
|
Field findField = findField(obj, str);
|
|
Object[] objArr2 = (Object[]) findField.get(obj);
|
|
Object[] objArr3 = (Object[]) Array.newInstance(objArr2.getClass().getComponentType(), objArr2.length + objArr.length);
|
|
System.arraycopy(objArr2, 0, objArr3, 0, objArr2.length);
|
|
System.arraycopy(objArr, 0, objArr3, objArr2.length, objArr.length);
|
|
findField.set(obj, objArr3);
|
|
}
|
|
|
|
private static void clearOldDexDir(Context context) throws Exception {
|
|
File file = new File(context.getFilesDir(), "secondary-dexes");
|
|
if (file.isDirectory()) {
|
|
Log.i(TAG, "Clearing old secondary dex dir (" + file.getPath() + ").");
|
|
File[] listFiles = file.listFiles();
|
|
if (listFiles == null) {
|
|
Log.w(TAG, "Failed to list secondary dex dir content (" + file.getPath() + ").");
|
|
return;
|
|
}
|
|
for (File file2 : listFiles) {
|
|
Log.i(TAG, "Trying to delete old file " + file2.getPath() + " of size " + file2.length());
|
|
if (!file2.delete()) {
|
|
Log.w(TAG, "Failed to delete old file " + file2.getPath());
|
|
} else {
|
|
Log.i(TAG, "Deleted old file " + file2.getPath());
|
|
}
|
|
}
|
|
if (!file.delete()) {
|
|
Log.w(TAG, "Failed to delete secondary dex dir " + file.getPath());
|
|
} else {
|
|
Log.i(TAG, "Deleted old secondary dex dir " + file.getPath());
|
|
}
|
|
}
|
|
}
|
|
|
|
private static File getDexDir(Context context, File file, String str) throws IOException {
|
|
File file2 = new File(file, CODE_CACHE_NAME);
|
|
try {
|
|
mkdirChecked(file2);
|
|
} catch (IOException unused) {
|
|
file2 = new File(context.getFilesDir(), CODE_CACHE_NAME);
|
|
mkdirChecked(file2);
|
|
}
|
|
File file3 = new File(file2, str);
|
|
mkdirChecked(file3);
|
|
return file3;
|
|
}
|
|
|
|
private static void mkdirChecked(File file) throws IOException {
|
|
file.mkdir();
|
|
if (file.isDirectory()) {
|
|
return;
|
|
}
|
|
File parentFile = file.getParentFile();
|
|
if (parentFile == null) {
|
|
Log.e(TAG, "Failed to create dir " + file.getPath() + ". Parent file is null.");
|
|
} else {
|
|
Log.e(TAG, "Failed to create dir " + file.getPath() + ". parent file is a dir " + parentFile.isDirectory() + ", a file " + parentFile.isFile() + ", exists " + parentFile.exists() + ", readable " + parentFile.canRead() + ", writable " + parentFile.canWrite());
|
|
}
|
|
throw new IOException("Failed to create directory " + file.getPath());
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: private */
|
|
/* loaded from: classes2.dex */
|
|
public static final class V19 {
|
|
private V19() {
|
|
}
|
|
|
|
static void install(ClassLoader classLoader, List<? extends File> list, File file) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, InvocationTargetException, NoSuchMethodException, IOException {
|
|
IOException[] iOExceptionArr;
|
|
Object obj = MultiDex.findField(classLoader, "pathList").get(classLoader);
|
|
ArrayList arrayList = new ArrayList();
|
|
MultiDex.expandFieldArray(obj, "dexElements", makeDexElements(obj, new ArrayList(list), file, arrayList));
|
|
if (arrayList.size() > 0) {
|
|
Iterator it = arrayList.iterator();
|
|
while (it.hasNext()) {
|
|
Log.w(MultiDex.TAG, "Exception in makeDexElement", (IOException) it.next());
|
|
}
|
|
Field findField = MultiDex.findField(obj, "dexElementsSuppressedExceptions");
|
|
IOException[] iOExceptionArr2 = (IOException[]) findField.get(obj);
|
|
if (iOExceptionArr2 == null) {
|
|
iOExceptionArr = (IOException[]) arrayList.toArray(new IOException[arrayList.size()]);
|
|
} else {
|
|
IOException[] iOExceptionArr3 = new IOException[arrayList.size() + iOExceptionArr2.length];
|
|
arrayList.toArray(iOExceptionArr3);
|
|
System.arraycopy(iOExceptionArr2, 0, iOExceptionArr3, arrayList.size(), iOExceptionArr2.length);
|
|
iOExceptionArr = iOExceptionArr3;
|
|
}
|
|
findField.set(obj, iOExceptionArr);
|
|
IOException iOException = new IOException("I/O exception during makeDexElement");
|
|
iOException.initCause((Throwable) arrayList.get(0));
|
|
throw iOException;
|
|
}
|
|
}
|
|
|
|
private static Object[] makeDexElements(Object obj, ArrayList<File> arrayList, File file, ArrayList<IOException> arrayList2) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
|
return (Object[]) MultiDex.findMethod(obj, "makeDexElements", ArrayList.class, File.class, ArrayList.class).invoke(obj, arrayList, file, arrayList2);
|
|
}
|
|
}
|
|
|
|
/* loaded from: classes2.dex */
|
|
private static final class V14 {
|
|
private static final int EXTRACTED_SUFFIX_LENGTH = 4;
|
|
private final ElementConstructor elementConstructor;
|
|
|
|
/* JADX INFO: Access modifiers changed from: private */
|
|
/* loaded from: classes2.dex */
|
|
public interface ElementConstructor {
|
|
Object newInstance(File file, DexFile dexFile) throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, IOException;
|
|
}
|
|
|
|
/* loaded from: classes2.dex */
|
|
private static class ICSElementConstructor implements ElementConstructor {
|
|
private final Constructor<?> elementConstructor;
|
|
|
|
ICSElementConstructor(Class<?> cls) throws SecurityException, NoSuchMethodException {
|
|
Constructor<?> constructor = cls.getConstructor(File.class, ZipFile.class, DexFile.class);
|
|
this.elementConstructor = constructor;
|
|
constructor.setAccessible(true);
|
|
}
|
|
|
|
@Override // androidx.multidex.MultiDex.V14.ElementConstructor
|
|
public Object newInstance(File file, DexFile dexFile) throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, IOException {
|
|
return this.elementConstructor.newInstance(file, new ZipFile(file), dexFile);
|
|
}
|
|
}
|
|
|
|
/* loaded from: classes2.dex */
|
|
private static class JBMR11ElementConstructor implements ElementConstructor {
|
|
private final Constructor<?> elementConstructor;
|
|
|
|
JBMR11ElementConstructor(Class<?> cls) throws SecurityException, NoSuchMethodException {
|
|
Constructor<?> constructor = cls.getConstructor(File.class, File.class, DexFile.class);
|
|
this.elementConstructor = constructor;
|
|
constructor.setAccessible(true);
|
|
}
|
|
|
|
@Override // androidx.multidex.MultiDex.V14.ElementConstructor
|
|
public Object newInstance(File file, DexFile dexFile) throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
|
|
return this.elementConstructor.newInstance(file, file, dexFile);
|
|
}
|
|
}
|
|
|
|
/* loaded from: classes2.dex */
|
|
private static class JBMR2ElementConstructor implements ElementConstructor {
|
|
private final Constructor<?> elementConstructor;
|
|
|
|
JBMR2ElementConstructor(Class<?> cls) throws SecurityException, NoSuchMethodException {
|
|
Constructor<?> constructor = cls.getConstructor(File.class, Boolean.TYPE, File.class, DexFile.class);
|
|
this.elementConstructor = constructor;
|
|
constructor.setAccessible(true);
|
|
}
|
|
|
|
@Override // androidx.multidex.MultiDex.V14.ElementConstructor
|
|
public Object newInstance(File file, DexFile dexFile) throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
|
|
return this.elementConstructor.newInstance(file, Boolean.FALSE, file, dexFile);
|
|
}
|
|
}
|
|
|
|
static void install(ClassLoader classLoader, List<? extends File> list) throws IOException, SecurityException, IllegalArgumentException, ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchFieldException {
|
|
Object obj = MultiDex.findField(classLoader, "pathList").get(classLoader);
|
|
Object[] makeDexElements = new V14().makeDexElements(list);
|
|
try {
|
|
MultiDex.expandFieldArray(obj, "dexElements", makeDexElements);
|
|
} catch (NoSuchFieldException e) {
|
|
Log.w(MultiDex.TAG, "Failed find field 'dexElements' attempting 'pathElements'", e);
|
|
MultiDex.expandFieldArray(obj, "pathElements", makeDexElements);
|
|
}
|
|
}
|
|
|
|
private V14() throws ClassNotFoundException, SecurityException, NoSuchMethodException {
|
|
ElementConstructor jBMR2ElementConstructor;
|
|
Class<?> cls = Class.forName("dalvik.system.DexPathList$Element");
|
|
try {
|
|
try {
|
|
jBMR2ElementConstructor = new ICSElementConstructor(cls);
|
|
} catch (NoSuchMethodException unused) {
|
|
jBMR2ElementConstructor = new JBMR11ElementConstructor(cls);
|
|
}
|
|
} catch (NoSuchMethodException unused2) {
|
|
jBMR2ElementConstructor = new JBMR2ElementConstructor(cls);
|
|
}
|
|
this.elementConstructor = jBMR2ElementConstructor;
|
|
}
|
|
|
|
private Object[] makeDexElements(List<? extends File> list) throws IOException, SecurityException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
|
|
int size = list.size();
|
|
Object[] objArr = new Object[size];
|
|
for (int i = 0; i < size; i++) {
|
|
File file = list.get(i);
|
|
objArr[i] = this.elementConstructor.newInstance(file, DexFile.loadDex(file.getPath(), optimizedPathFor(file), 0));
|
|
}
|
|
return objArr;
|
|
}
|
|
|
|
private static String optimizedPathFor(File file) {
|
|
File parentFile = file.getParentFile();
|
|
String name = file.getName();
|
|
return new File(parentFile, name.substring(0, name.length() - EXTRACTED_SUFFIX_LENGTH) + ".dex").getPath();
|
|
}
|
|
}
|
|
|
|
/* loaded from: classes2.dex */
|
|
private static final class V4 {
|
|
private V4() {
|
|
}
|
|
|
|
static void install(ClassLoader classLoader, List<? extends File> list) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, IOException {
|
|
int size = list.size();
|
|
Field findField = MultiDex.findField(classLoader, "path");
|
|
StringBuilder sb = new StringBuilder((String) findField.get(classLoader));
|
|
String[] strArr = new String[size];
|
|
File[] fileArr = new File[size];
|
|
ZipFile[] zipFileArr = new ZipFile[size];
|
|
DexFile[] dexFileArr = new DexFile[size];
|
|
ListIterator<? extends File> listIterator = list.listIterator();
|
|
while (listIterator.hasNext()) {
|
|
File next = listIterator.next();
|
|
String absolutePath = next.getAbsolutePath();
|
|
sb.append(':').append(absolutePath);
|
|
int previousIndex = listIterator.previousIndex();
|
|
strArr[previousIndex] = absolutePath;
|
|
fileArr[previousIndex] = next;
|
|
zipFileArr[previousIndex] = new ZipFile(next);
|
|
dexFileArr[previousIndex] = DexFile.loadDex(absolutePath, absolutePath + ".dex", 0);
|
|
}
|
|
findField.set(classLoader, sb.toString());
|
|
MultiDex.expandFieldArray(classLoader, "mPaths", strArr);
|
|
MultiDex.expandFieldArray(classLoader, "mFiles", fileArr);
|
|
MultiDex.expandFieldArray(classLoader, "mZips", zipFileArr);
|
|
MultiDex.expandFieldArray(classLoader, "mDexs", dexFileArr);
|
|
}
|
|
}
|
|
}
|