Add decompiled APK source code (JADX)

- 28,932 files
- Full Java source code
- Smali files
- Resources

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-02-18 14:52:23 -08:00
parent cc210a65ea
commit f9d20bb3fc
26991 changed files with 2541449 additions and 0 deletions

View File

@@ -0,0 +1,352 @@
package androidx.multidex;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import com.facebook.internal.AnalyticsEvents;
import com.ironsource.v8;
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/* loaded from: classes.dex */
final class MultiDexExtractor implements Closeable {
private static final int BUFFER_SIZE = 16384;
private static final String DEX_PREFIX = "classes";
static final String DEX_SUFFIX = ".dex";
private static final String EXTRACTED_NAME_EXT = ".classes";
static final String EXTRACTED_SUFFIX = ".zip";
private static final String KEY_CRC = "crc";
private static final String KEY_DEX_CRC = "dex.crc.";
private static final String KEY_DEX_NUMBER = "dex.number";
private static final String KEY_DEX_TIME = "dex.time.";
private static final String KEY_TIME_STAMP = "timestamp";
private static final String LOCK_FILENAME = "MultiDex.lock";
private static final int MAX_EXTRACT_ATTEMPTS = 3;
private static final long NO_VALUE = -1;
private static final String PREFS_FILE = "multidex.version";
private static final String TAG = "MultiDex";
private final FileLock cacheLock;
private final File dexDir;
private final FileChannel lockChannel;
private final RandomAccessFile lockRaf;
private final File sourceApk;
private final long sourceCrc;
public static class ExtractedDex extends File {
public long crc;
public ExtractedDex(File file, String str) {
super(file, str);
this.crc = -1L;
}
}
public MultiDexExtractor(File file, File file2) throws IOException {
StringBuilder sb = new StringBuilder();
sb.append("MultiDexExtractor(");
sb.append(file.getPath());
sb.append(", ");
sb.append(file2.getPath());
sb.append(")");
this.sourceApk = file;
this.dexDir = file2;
this.sourceCrc = getZipCrc(file);
File file3 = new File(file2, LOCK_FILENAME);
RandomAccessFile randomAccessFile = new RandomAccessFile(file3, "rw");
this.lockRaf = randomAccessFile;
try {
FileChannel channel = randomAccessFile.getChannel();
this.lockChannel = channel;
try {
StringBuilder sb2 = new StringBuilder();
sb2.append("Blocking on lock ");
sb2.append(file3.getPath());
this.cacheLock = channel.lock();
StringBuilder sb3 = new StringBuilder();
sb3.append(file3.getPath());
sb3.append(" locked");
} catch (IOException e) {
e = e;
closeQuietly(this.lockChannel);
throw e;
} catch (Error e2) {
e = e2;
closeQuietly(this.lockChannel);
throw e;
} catch (RuntimeException e3) {
e = e3;
closeQuietly(this.lockChannel);
throw e;
}
} catch (IOException e4) {
e = e4;
closeQuietly(this.lockRaf);
throw e;
} catch (Error e5) {
e = e5;
closeQuietly(this.lockRaf);
throw e;
} catch (RuntimeException e6) {
e = e6;
closeQuietly(this.lockRaf);
throw e;
}
}
public List<? extends File> load(Context context, String str, boolean z) throws IOException {
List<ExtractedDex> performExtractions;
StringBuilder sb = new StringBuilder();
sb.append("MultiDexExtractor.load(");
sb.append(this.sourceApk.getPath());
sb.append(", ");
sb.append(z);
sb.append(", ");
sb.append(str);
sb.append(")");
if (!this.cacheLock.isValid()) {
throw new IllegalStateException("MultiDexExtractor was closed");
}
if (!z && !isModified(context, this.sourceApk, this.sourceCrc, str)) {
try {
performExtractions = loadExistingExtractions(context, str);
} catch (IOException e) {
Log.w(TAG, "Failed to reload existing extracted secondary dex files, falling back to fresh extraction", e);
performExtractions = performExtractions();
putStoredApkInfo(context, str, getTimeStamp(this.sourceApk), this.sourceCrc, performExtractions);
}
} else {
performExtractions = performExtractions();
putStoredApkInfo(context, str, getTimeStamp(this.sourceApk), this.sourceCrc, performExtractions);
}
StringBuilder sb2 = new StringBuilder();
sb2.append("load found ");
sb2.append(performExtractions.size());
sb2.append(" secondary dex files");
return performExtractions;
}
@Override // java.io.Closeable, java.lang.AutoCloseable
public void close() throws IOException {
this.cacheLock.release();
this.lockChannel.close();
this.lockRaf.close();
}
private List<ExtractedDex> loadExistingExtractions(Context context, String str) throws IOException {
String str2 = this.sourceApk.getName() + EXTRACTED_NAME_EXT;
SharedPreferences multiDexPreferences = getMultiDexPreferences(context);
int i = multiDexPreferences.getInt(str + KEY_DEX_NUMBER, 1);
ArrayList arrayList = new ArrayList(i + (-1));
int i2 = 2;
while (i2 <= i) {
ExtractedDex extractedDex = new ExtractedDex(this.dexDir, str2 + i2 + EXTRACTED_SUFFIX);
if (extractedDex.isFile()) {
extractedDex.crc = getZipCrc(extractedDex);
long j = multiDexPreferences.getLong(str + KEY_DEX_CRC + i2, -1L);
long j2 = multiDexPreferences.getLong(str + KEY_DEX_TIME + i2, -1L);
long lastModified = extractedDex.lastModified();
if (j2 == lastModified) {
String str3 = str2;
SharedPreferences sharedPreferences = multiDexPreferences;
if (j == extractedDex.crc) {
arrayList.add(extractedDex);
i2++;
multiDexPreferences = sharedPreferences;
str2 = str3;
}
}
throw new IOException("Invalid extracted dex: " + extractedDex + " (key \"" + str + "\"), expected modification time: " + j2 + ", modification time: " + lastModified + ", expected crc: " + j + ", file crc: " + extractedDex.crc);
}
throw new IOException("Missing extracted secondary dex file '" + extractedDex.getPath() + "'");
}
return arrayList;
}
private static boolean isModified(Context context, File file, long j, String str) {
SharedPreferences multiDexPreferences = getMultiDexPreferences(context);
if (multiDexPreferences.getLong(str + "timestamp", -1L) == getTimeStamp(file)) {
if (multiDexPreferences.getLong(str + KEY_CRC, -1L) == j) {
return false;
}
}
return true;
}
private static long getTimeStamp(File file) {
long lastModified = file.lastModified();
return lastModified == -1 ? lastModified - 1 : lastModified;
}
private static long getZipCrc(File file) throws IOException {
long zipCrc = ZipUtil.getZipCrc(file);
return zipCrc == -1 ? zipCrc - 1 : zipCrc;
}
private List<ExtractedDex> performExtractions() throws IOException {
boolean z;
String str = this.sourceApk.getName() + EXTRACTED_NAME_EXT;
clearDexDir();
ArrayList arrayList = new ArrayList();
ZipFile zipFile = new ZipFile(this.sourceApk);
try {
int i = 2;
ZipEntry entry = zipFile.getEntry(DEX_PREFIX + 2 + DEX_SUFFIX);
while (entry != null) {
ExtractedDex extractedDex = new ExtractedDex(this.dexDir, str + i + EXTRACTED_SUFFIX);
arrayList.add(extractedDex);
StringBuilder sb = new StringBuilder();
sb.append("Extraction is needed for file ");
sb.append(extractedDex);
int i2 = 0;
boolean z2 = false;
while (i2 < 3 && !z2) {
int i3 = i2 + 1;
extract(zipFile, entry, extractedDex, str);
try {
extractedDex.crc = getZipCrc(extractedDex);
z = true;
} catch (IOException e) {
Log.w(TAG, "Failed to read crc from " + extractedDex.getAbsolutePath(), e);
z = false;
}
StringBuilder sb2 = new StringBuilder();
sb2.append("Extraction ");
sb2.append(z ? AnalyticsEvents.PARAMETER_SHARE_OUTCOME_SUCCEEDED : v8.h.t);
sb2.append(" '");
sb2.append(extractedDex.getAbsolutePath());
sb2.append("': length ");
sb2.append(extractedDex.length());
sb2.append(" - crc: ");
sb2.append(extractedDex.crc);
if (!z) {
extractedDex.delete();
if (extractedDex.exists()) {
Log.w(TAG, "Failed to delete corrupted secondary dex '" + extractedDex.getPath() + "'");
}
}
z2 = z;
i2 = i3;
}
if (!z2) {
throw new IOException("Could not create zip file " + extractedDex.getAbsolutePath() + " for secondary dex (" + i + ")");
}
i++;
entry = zipFile.getEntry(DEX_PREFIX + i + DEX_SUFFIX);
}
try {
zipFile.close();
} catch (IOException e2) {
Log.w(TAG, "Failed to close resource", e2);
}
return arrayList;
} finally {
}
}
private static void putStoredApkInfo(Context context, String str, long j, long j2, List<ExtractedDex> list) {
SharedPreferences.Editor edit = getMultiDexPreferences(context).edit();
edit.putLong(str + "timestamp", j);
edit.putLong(str + KEY_CRC, j2);
edit.putInt(str + KEY_DEX_NUMBER, list.size() + 1);
int i = 2;
for (ExtractedDex extractedDex : list) {
edit.putLong(str + KEY_DEX_CRC + i, extractedDex.crc);
edit.putLong(str + KEY_DEX_TIME + i, extractedDex.lastModified());
i++;
}
edit.commit();
}
private static SharedPreferences getMultiDexPreferences(Context context) {
return context.getSharedPreferences(PREFS_FILE, 4);
}
private void clearDexDir() {
File[] listFiles = this.dexDir.listFiles(new FileFilter() { // from class: androidx.multidex.MultiDexExtractor.1
@Override // java.io.FileFilter
public boolean accept(File file) {
return !file.getName().equals(MultiDexExtractor.LOCK_FILENAME);
}
});
if (listFiles == null) {
Log.w(TAG, "Failed to list secondary dex dir content (" + this.dexDir.getPath() + ").");
return;
}
for (File file : listFiles) {
StringBuilder sb = new StringBuilder();
sb.append("Trying to delete old file ");
sb.append(file.getPath());
sb.append(" of size ");
sb.append(file.length());
if (file.delete()) {
StringBuilder sb2 = new StringBuilder();
sb2.append("Deleted old file ");
sb2.append(file.getPath());
} else {
Log.w(TAG, "Failed to delete old file " + file.getPath());
}
}
}
private static void extract(ZipFile zipFile, ZipEntry zipEntry, File file, String str) throws IOException, FileNotFoundException {
InputStream inputStream = zipFile.getInputStream(zipEntry);
File createTempFile = File.createTempFile("tmp-" + str, EXTRACTED_SUFFIX, file.getParentFile());
StringBuilder sb = new StringBuilder();
sb.append("Extracting ");
sb.append(createTempFile.getPath());
try {
ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(createTempFile)));
try {
ZipEntry zipEntry2 = new ZipEntry("classes.dex");
zipEntry2.setTime(zipEntry.getTime());
zipOutputStream.putNextEntry(zipEntry2);
byte[] bArr = new byte[16384];
for (int read = inputStream.read(bArr); read != -1; read = inputStream.read(bArr)) {
zipOutputStream.write(bArr, 0, read);
}
zipOutputStream.closeEntry();
zipOutputStream.close();
if (!createTempFile.setReadOnly()) {
throw new IOException("Failed to mark readonly \"" + createTempFile.getAbsolutePath() + "\" (tmp of \"" + file.getAbsolutePath() + "\")");
}
StringBuilder sb2 = new StringBuilder();
sb2.append("Renaming to ");
sb2.append(file.getPath());
if (!createTempFile.renameTo(file)) {
throw new IOException("Failed to rename \"" + createTempFile.getAbsolutePath() + "\" to \"" + file.getAbsolutePath() + "\"");
}
closeQuietly(inputStream);
createTempFile.delete();
} catch (Throwable th) {
zipOutputStream.close();
throw th;
}
} catch (Throwable th2) {
closeQuietly(inputStream);
createTempFile.delete();
throw th2;
}
}
private static void closeQuietly(Closeable closeable) {
try {
closeable.close();
} catch (IOException e) {
Log.w(TAG, "Failed to close resource", e);
}
}
}