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 load(Context context, String str, boolean z) throws IOException { List 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 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 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 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); } } }