Search in sources :

Example 1 with DexPatchApplier

use of com.tencent.tinker.commons.dexpatcher.DexPatchApplier in project tinker by Tencent.

the class DexDiffPatchInternal method patchDexFile.

/**
 * Generate patched dex file (May wrapped it by a jar if needed.)
 *
 * @param baseApk        OldApk.
 * @param patchPkg       Patch package, it is also a zip file.
 * @param oldDexEntry    ZipEntry of old dex.
 * @param patchFileEntry ZipEntry of patch file. (also ends with .dex) This could be null.
 * @param patchInfo      Parsed patch info from package-meta.txt
 * @param patchedDexFile Patched dex file, may be a jar.
 *                       <p>
 *                       <b>Notice: patchFileEntry and smallPatchInfoFile cannot both be null.</b>
 * @throws IOException
 */
private static void patchDexFile(ZipFile baseApk, ZipFile patchPkg, ZipEntry oldDexEntry, ZipEntry patchFileEntry, ShareDexDiffPatchInfo patchInfo, File patchedDexFile) throws IOException {
    InputStream oldDexStream = null;
    InputStream patchFileStream = null;
    try {
        oldDexStream = new BufferedInputStream(baseApk.getInputStream(oldDexEntry));
        patchFileStream = (patchFileEntry != null ? new BufferedInputStream(patchPkg.getInputStream(patchFileEntry)) : null);
        final boolean isRawDexFile = SharePatchFileUtil.isRawDexFile(patchInfo.rawName);
        if (!isRawDexFile || patchInfo.isJarMode) {
            ZipOutputStream zos = null;
            try {
                zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(patchedDexFile)));
                zos.putNextEntry(new ZipEntry(ShareConstants.DEX_IN_JAR));
                // Old dex is not a raw dex file.
                if (!isRawDexFile) {
                    ZipInputStream zis = null;
                    try {
                        zis = new ZipInputStream(oldDexStream);
                        ZipEntry entry;
                        while ((entry = zis.getNextEntry()) != null) {
                            if (ShareConstants.DEX_IN_JAR.equals(entry.getName()))
                                break;
                        }
                        if (entry == null) {
                            throw new TinkerRuntimeException("can't recognize zip dex format file:" + patchedDexFile.getAbsolutePath());
                        }
                        new DexPatchApplier(zis, patchFileStream).executeAndSaveTo(zos);
                    } finally {
                        IOHelper.closeQuietly(zis);
                    }
                } else {
                    new DexPatchApplier(oldDexStream, patchFileStream).executeAndSaveTo(zos);
                }
                zos.closeEntry();
            } finally {
                IOHelper.closeQuietly(zos);
            }
        } else {
            new DexPatchApplier(oldDexStream, patchFileStream).executeAndSaveTo(patchedDexFile);
        }
    } finally {
        IOHelper.closeQuietly(oldDexStream);
        IOHelper.closeQuietly(patchFileStream);
    }
}
Also used : TinkerRuntimeException(com.tencent.tinker.loader.TinkerRuntimeException) ZipInputStream(java.util.zip.ZipInputStream) DexPatchApplier(com.tencent.tinker.commons.dexpatcher.DexPatchApplier) BufferedInputStream(java.io.BufferedInputStream) BufferedInputStream(java.io.BufferedInputStream) ZipInputStream(java.util.zip.ZipInputStream) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) ZipOutputStream(java.util.zip.ZipOutputStream) AlignedZipOutputStream(com.tencent.tinker.ziputils.ziputil.AlignedZipOutputStream) FileOutputStream(java.io.FileOutputStream) ZipEntry(java.util.zip.ZipEntry) BufferedOutputStream(java.io.BufferedOutputStream)

Example 2 with DexPatchApplier

use of com.tencent.tinker.commons.dexpatcher.DexPatchApplier in project tinker by Tencent.

the class DexDiffDecoder method diffDexPairAndFillRelatedInfo.

private void diffDexPairAndFillRelatedInfo(File oldDexFile, File newDexFile, RelatedInfo relatedInfo) {
    File tempFullPatchDexPath = new File(config.mOutFolder + File.separator + TypedValue.DEX_TEMP_PATCH_DIR);
    final String dexName = getRelativeDexName(oldDexFile, newDexFile);
    File dexDiffOut = getOutputPath(newDexFile).toFile();
    ensureDirectoryExist(dexDiffOut.getParentFile());
    try {
        DexPatchGenerator dexPatchGen = new DexPatchGenerator(oldDexFile, newDexFile);
        dexPatchGen.setAdditionalRemovingClassPatterns(config.mDexLoaderPattern);
        logWriter.writeLineToInfoFile(String.format("Start diff between [%s] as old and [%s] as new:", getRelativeStringBy(oldDexFile, config.mTempUnzipOldDir), getRelativeStringBy(newDexFile, config.mTempUnzipNewDir)));
        dexPatchGen.executeAndSaveTo(dexDiffOut);
    } catch (Exception e) {
        throw new TinkerPatchException(e);
    }
    if (!dexDiffOut.exists()) {
        throw new TinkerPatchException("can not find the diff file:" + dexDiffOut.getAbsolutePath());
    }
    relatedInfo.dexDiffFile = dexDiffOut;
    relatedInfo.dexDiffMd5 = MD5.getMD5(dexDiffOut);
    Logger.d("\nGen %s patch file:%s, size:%d, md5:%s", dexName, relatedInfo.dexDiffFile.getAbsolutePath(), relatedInfo.dexDiffFile.length(), relatedInfo.dexDiffMd5);
    File tempFullPatchedDexFile = new File(tempFullPatchDexPath, dexName);
    if (!tempFullPatchedDexFile.exists()) {
        ensureDirectoryExist(tempFullPatchedDexFile.getParentFile());
    }
    try {
        new DexPatchApplier(oldDexFile, dexDiffOut).executeAndSaveTo(tempFullPatchedDexFile);
        Logger.d(String.format("Verifying if patched new dex is logically the same as original new dex: %s ...", getRelativeStringBy(newDexFile, config.mTempUnzipNewDir)));
        Dex origNewDex = new Dex(newDexFile);
        Dex patchedNewDex = new Dex(tempFullPatchedDexFile);
        checkDexChange(origNewDex, patchedNewDex);
        relatedInfo.newOrFullPatchedFile = tempFullPatchedDexFile;
        relatedInfo.newOrFullPatchedMd5 = MD5.getMD5(tempFullPatchedDexFile);
        relatedInfo.newOrFullPatchedCRC = FileOperation.getFileCrc32(tempFullPatchedDexFile);
    } catch (Exception e) {
        e.printStackTrace();
        throw new TinkerPatchException("Failed to generate temporary patched dex, which makes MD5 generating procedure of new dex failed, either.", e);
    }
    if (!tempFullPatchedDexFile.exists()) {
        throw new TinkerPatchException("can not find the temporary full patched dex file:" + tempFullPatchedDexFile.getAbsolutePath());
    }
    Logger.d("\nGen %s for dalvik full dex file:%s, size:%d, md5:%s", dexName, tempFullPatchedDexFile.getAbsolutePath(), tempFullPatchedDexFile.length(), relatedInfo.newOrFullPatchedMd5);
}
Also used : DexPatchApplier(com.tencent.tinker.commons.dexpatcher.DexPatchApplier) Dex(com.tencent.tinker.android.dex.Dex) JarFile(java.util.jar.JarFile) DexFile(org.jf.dexlib2.iface.DexFile) DexBackedDexFile(org.jf.dexlib2.dexbacked.DexBackedDexFile) File(java.io.File) DexPatchGenerator(com.tencent.tinker.build.dexpatcher.DexPatchGenerator) TinkerPatchException(com.tencent.tinker.build.util.TinkerPatchException) IOException(java.io.IOException) TinkerPatchException(com.tencent.tinker.build.util.TinkerPatchException)

Aggregations

DexPatchApplier (com.tencent.tinker.commons.dexpatcher.DexPatchApplier)2 Dex (com.tencent.tinker.android.dex.Dex)1 DexPatchGenerator (com.tencent.tinker.build.dexpatcher.DexPatchGenerator)1 TinkerPatchException (com.tencent.tinker.build.util.TinkerPatchException)1 TinkerRuntimeException (com.tencent.tinker.loader.TinkerRuntimeException)1 AlignedZipOutputStream (com.tencent.tinker.ziputils.ziputil.AlignedZipOutputStream)1 BufferedInputStream (java.io.BufferedInputStream)1 BufferedOutputStream (java.io.BufferedOutputStream)1 File (java.io.File)1 FileInputStream (java.io.FileInputStream)1 FileOutputStream (java.io.FileOutputStream)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 JarFile (java.util.jar.JarFile)1 ZipEntry (java.util.zip.ZipEntry)1 ZipInputStream (java.util.zip.ZipInputStream)1 ZipOutputStream (java.util.zip.ZipOutputStream)1 DexBackedDexFile (org.jf.dexlib2.dexbacked.DexBackedDexFile)1 DexFile (org.jf.dexlib2.iface.DexFile)1