Search in sources :

Example 1 with DexDiffInfo

use of com.taobao.android.object.DexDiffInfo in project atlas by alibaba.

the class TPatchTool method createBundleDexPatch.

/**
     * 得到bundle的dex diff文件,支持多dex
     *
     * @param newApkUnzipFolder
     * @param baseApkUnzipFolder
     * @param destDex
     * @param tmpDexFile
     * @param diffTxtFile
     * @return
     * @throws IOException
     * @throws RecognitionException
     */
private File createBundleDexPatch(File newApkUnzipFolder, File baseApkUnzipFolder, File destDex, File tmpDexFile, File diffTxtFile) throws IOException, RecognitionException, PatchException {
    List<File> dexs = Lists.newArrayList();
    // 比较主bundle的dex
    List<File> baseDexFiles = getFolderDexFiles(baseApkUnzipFolder);
    List<File> newDexFiles = getFolderDexFiles(newApkUnzipFolder);
    File dexDiffFile = new File(tmpDexFile, "diff.dex");
    TPatchDexTool dexTool = new TPatchDexTool(baseDexFiles, newDexFiles, DEFAULT_API_LEVEL, bundleClassMap.get(tmpDexFile.getName().substring(0, tmpDexFile.getName().length() - 4)));
    DexDiffInfo dexDiffInfo = dexTool.createTPatchDex(dexDiffFile);
    if (dexDiffFile.exists() && validDiffInfo(dexDiffInfo)) {
        dexs.add(dexDiffFile);
        dexDiffInfo.writeDiffToFile(diffTxtFile, true);
    }
    // 合并dex
    if (dexs.size() > 1) {
        if (null != logger) {
            logger.info("To merged dex is:" + StringUtils.join(dexs, ","));
        }
        DexBuilderUtils.mergeDex(dexs, destDex, CollisionPolicy.FAIL);
    } else if (dexs.size() > 0) {
        FileUtils.copyFile(dexs.get(0), destDex);
    }
    FileUtils.deleteDirectory(tmpDexFile);
    return destDex;
}
Also used : DexDiffInfo(com.taobao.android.object.DexDiffInfo) File(java.io.File)

Example 2 with DexDiffInfo

use of com.taobao.android.object.DexDiffInfo in project atlas by alibaba.

the class ApkPatch method doPatch.

public File doPatch() throws PatchException {
    try {
        File aptchFolder = new File(out, name);
        File smaliDir = new File(aptchFolder, "smali");
        if (!smaliDir.exists()) {
            smaliDir.mkdirs();
        }
        try {
            FileUtils.cleanDirectory(smaliDir);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        File dexFile = new File(aptchFolder, "diff.dex");
        if (dexFile.exists() && !dexFile.delete()) {
            throw new RuntimeException("diff.dex can't be removed.");
        }
        File outFile = new File(aptchFolder, "diff" + SUFFIX);
        if (outFile.exists() && !outFile.delete()) {
            throw new RuntimeException("diff" + SUFFIX + " can't be removed.");
        }
        currentTimeStamp = System.currentTimeMillis();
        DexDiffer dexDiffer = new DexDiffer(baseFiles, newFiles, 19);
        // 创建白名单过滤类
        if ((this.filterPath != null) && !(this.filterPath.equals(""))) {
            dexDiffer.createFilter(this.filterPath);
        }
        //diff
        DexDiffInfo info = dexDiffer.doDiff();
        dexDiffer.setDexDiffFilter(new AndFixFilterImpl(info));
        //diffFilter
        dexDiffer.dexFilter();
        info.update();
        //写json
        if (null != diffFile && null != diffJsonFile) {
            info.writeToFile(name, diffFile, diffJsonFile);
        }
        //生成dex
        classes = SmaliDiffUtils.buildCode(smaliDir, dexFile, info);
        if (null == classes || classes.size() <= 0) {
            return null;
        }
        //是否修改dex
        if (APatchTool.debug) {
            PatchMethodTool.modifyMethod(dexFile.getAbsolutePath(), dexFile.getAbsolutePath(), true);
        }
        File smaliDir2 = new File(aptchFolder, "smali2");
        if (!smaliDir2.exists()) {
            smaliDir2.mkdirs();
        }
        try {
            FileUtils.cleanDirectory(smaliDir2);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        prepareClasses = buildPrepareClass(smaliDir2, newFiles, info);
        DexDiffInfo.release();
        build(outFile, dexFile);
        File file = release(aptchFolder, dexFile, outFile);
        release();
        return file;
    } catch (Exception e) {
        throw new PatchException(e);
    }
}
Also used : DexDiffInfo(com.taobao.android.object.DexDiffInfo) DexDiffer(com.taobao.android.differ.dex.DexDiffer) IOException(java.io.IOException) PatchException(com.taobao.android.differ.dex.PatchException) File(java.io.File) PatchException(com.taobao.android.differ.dex.PatchException) IOException(java.io.IOException)

Example 3 with DexDiffInfo

use of com.taobao.android.object.DexDiffInfo in project atlas by alibaba.

the class FastPatchTool method doPatch.

public void doPatch() throws IOException, PatchException, RecognitionException {
    MappingReader mappingReader = null;
    MappingProcessor mappingProcessor = null;
    if (outDir == null || !outDir.exists()) {
        return;
    }
    outPatchFile = new File(outDir, "apatch-unsigned.apatch");
    if (mappingFile != null && mappingFile.exists()) {
        mappingReader = new MappingReader(mappingFile);
        mappingProcessor = new MappingProcessorImpl(superClassMap);
        mappingReader.pump(mappingProcessor);
        mappingProcessor.updateMethod();
        mappingProcessor.updateFieldType();
    }
    for (FastPatchObject fastPatchObject : patchObjects) {
        Set<ClassDef> classes = new HashSet<ClassDef>();
        Map<ClassDef, List<Method>> patchClassDefs = new HashMap<ClassDef, List<Method>>();
        Set<ClassDef> addedClasses = new HashSet<ClassDef>();
        Map<ClassDef, List<Method>> newClassDef = new HashMap<ClassDef, List<Method>>();
        ArrayList<Method> methods = new ArrayList<Method>();
        for (File dexFile : fastPatchObject.DexFiles) {
            DexFile dFile = DexFileFactory.loadDexFile(dexFile.getAbsolutePath(), 19, true);
            classes.addAll(dFile.getClasses());
        }
        final Set<ClassDef> newClasses = new HashSet<ClassDef>();
        for (ClassDef classDef : classes) {
            String type = classDef.getType();
            if (fastPatchObject.addedClass.contains(SmaliUtils.getDalvikClassName(type))) {
                System.out.println("patch added class:" + type);
                addedClasses.add(classDef);
                continue;
            }
            for (Map.Entry<String, List<String>> entry : fastPatchObject.modifyClasses.entrySet()) {
                if (entry.getKey().equals(SmaliUtils.getDalvikClassName(type))) {
                    ArrayList<Method> newMethods = new ArrayList<Method>();
                    for (Method method : classDef.getMethods()) {
                        System.err.println(getMethodFullName(method));
                        if (entry.getValue().contains(getMethodFullName(method))) {
                            newMethods.add(method);
                        }
                    }
                    patchClassDefs.put(classDef, newMethods);
                    break;
                }
            }
        }
        if (patchClassDefs.size() == 0 && addedClasses.size() == 0) {
            continue;
        }
        if (mappingFile != null && mappingFile.exists()) {
            //第一步先将prepareclass混淆掉
            for (String className : fastPatchObject.prepareClasses) {
                ApkPatch.prepareClasses.add(mappingProcessor.getNewClassName(className).className);
            }
            //将replaceanatation混淆掉
            MethodReplaceAnnotation.ANNOTATION = DefineUtils.getDefineClassName(mappingProcessor.getNewClassName(DefineUtils.getDalvikClassName("Lcom/alipay/euler/andfix/annotation/MethodReplace;")).className, false);
            //将dex代码混淆掉
            InsTructionsReIClassDef insTructionsReDef = new InsTructionsReIClassDef(new MappingClassProcessor(mappingProcessor));
            for (ClassDef c : classes) {
                if (patchClassDefs.containsKey(c)) {
                    for (Method method : c.getMethods()) {
                        if (patchClassDefs.get(c).contains(method)) {
                            methods.add(insTructionsReDef.reMethod(method));
                        }
                    }
                    newClassDef.put(insTructionsReDef.reClassDef(c), methods);
                } else if (addedClasses.contains(c)) {
                    newClassDef.put(insTructionsReDef.reClassDef(c), new ArrayList<Method>());
                }
                if (c.getType().contains("/R$")) {
                    continue;
                }
                newClasses.add(insTructionsReDef.reClassDef(c));
            }
        } else {
            ApkPatch.prepareClasses.addAll(fastPatchObject.prepareClasses);
        }
        File patchDexFile = new File(outDir, "patch.dex");
        for (ClassDef classDef : newClassDef.keySet()) {
            System.out.println("modify class:" + classDef.getType());
        }
        if (newClassDef.size() > 0) {
            DexFileFactory.writeDexFile(patchDexFile.getAbsolutePath(), new ImmutableDexFile(newClassDef.keySet()));
        } else if (patchClassDefs.size() > 0) {
            DexFileFactory.writeDexFile(patchDexFile.getAbsolutePath(), new ImmutableDexFile(patchClassDefs.keySet()));
        }
        File tempDexFile = new File(outDir, "temp.dex");
        if (newClasses.size() > 0) {
            DexFileFactory.writeDexFile(tempDexFile.getAbsolutePath(), new DexFile() {

                @Nonnull
                @Override
                public Set<? extends ClassDef> getClasses() {
                    return new AbstractSet<ClassDef>() {

                        @Nonnull
                        @Override
                        public Iterator<ClassDef> iterator() {
                            return newClasses.iterator();
                        }

                        @Override
                        public int size() {
                            return newClasses.size();
                        }
                    };
                }
            });
        } else if (classes.size() > 0) {
            DexFileFactory.writeDexFile(tempDexFile.getAbsolutePath(), new ImmutableDexFile(classes));
        }
        SmaliDiffUtils.scanClasses(new File(outDir, "smali2"), Lists.newArrayList(tempDexFile));
        DexFile patchDex = DexFileFactory.loadDexFile(patchDexFile.getAbsolutePath(), 19, true);
        DexFile tempDex = DexFileFactory.loadDexFile(tempDexFile.getAbsolutePath(), 19, true);
        Set<? extends ClassDef> patchClasses = patchDex.getClasses();
        DexDiffInfo dexDiffInfo = new DexDiffInfo();
        for (ClassDef patchClassDef : patchClasses) {
            String type = patchClassDef.getType();
            if (fastPatchObject.addedClass.contains(SmaliUtils.getDalvikClassName(type))) {
                dexDiffInfo.getAddedClasses().add((DexBackedClassDef) patchClassDef);
                dexDiffInfo.addManifestAddClass(type);
                continue;
            }
            for (Method method : patchClassDef.getMethods()) {
                List<? extends CharSequence> parameters = method.getParameterTypes();
                if (methods.size() > 0) {
                    for (Method modifyMethod : methods) {
                        List<? extends CharSequence> modifyParameters = modifyMethod.getParameterTypes();
                        if (parameters.size() != modifyParameters.size() || !isEqualObj(parameters, modifyParameters)) {
                            continue;
                        }
                        if (modifyMethod.getName().equals(method.getName()))
                            dexDiffInfo.addModifiedMethods((DexBackedMethod) method);
                    }
                } else if (patchClassDefs.size() > 0) {
                    for (ClassDef classDef : patchClassDefs.keySet()) {
                        if (classDef.getType().equals(patchClassDef.getType())) {
                            List<Method> methodList = patchClassDefs.get(classDef);
                            for (Method method1 : methodList) {
                                if (method1.getName().equals(method.getName())) {
                                    dexDiffInfo.addModifiedMethods((DexBackedMethod) method);
                                }
                            }
                        }
                    }
                }
            }
        }
        FastBuild fastBuild = new FastBuild(fastPatchObject.bundleName, new File(outDir, bundleName));
        fastBuild.setClasses(tempDex.getClasses());
        fastBuild.setDiffInfo(dexDiffInfo);
        new AndFixFilterImpl(dexDiffInfo).filterDex();
        dexDiffInfo.update();
        APatchTool.isApatch = true;
        File adiffFile = new File(outDir, "apatch-diff.txt");
        File adiffJsonFile = new File(outDir, "apatch-diff.json");
        dexDiffInfo.writeToFile(fastPatchObject.bundleName, adiffFile, adiffJsonFile);
        try {
            File patchJarFile = fastBuild.dopatch();
            patchJarFiles.add(patchJarFile);
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (UnrecoverableEntryException e) {
            e.printStackTrace();
        }
    }
    File[] aPatchFiles = new File[patchJarFiles.size()];
    aPatchFiles = patchJarFiles.toArray(aPatchFiles);
    File mergePatchFile = null;
    if (null != aPatchFiles && aPatchFiles.length > 1) {
        MergePatch mergePatch = new MergePatch(aPatchFiles, "com_taobao_android", outDir);
        mergePatchFile = mergePatch.doMerge();
    } else if (null != aPatchFiles && aPatchFiles.length == 1) {
        mergePatchFile = aPatchFiles[0];
    }
    if (null != mergePatchFile && mergePatchFile.exists()) {
        FileUtils.moveFile(mergePatchFile, outPatchFile);
    }
}
Also used : DexBackedMethod(org.jf.dexlib2.dexbacked.DexBackedMethod) CertificateException(java.security.cert.CertificateException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) DexBackedClassDef(org.jf.dexlib2.dexbacked.DexBackedClassDef) InsTructionsReIClassDef(com.taobao.android.repatch.InsTructionsReIClassDef) ClassDef(org.jf.dexlib2.iface.ClassDef) MappingReader(com.taobao.android.repatch.mapping.MappingReader) UnrecoverableEntryException(java.security.UnrecoverableEntryException) Nonnull(javax.annotation.Nonnull) AndFixFilterImpl(com.taobao.android.apatch.AndFixFilterImpl) MappingClassProcessor(com.taobao.android.repatch.processor.MappingClassProcessor) Method(org.jf.dexlib2.iface.Method) DexBackedMethod(org.jf.dexlib2.dexbacked.DexBackedMethod) KeyStoreException(java.security.KeyStoreException) FastBuild(com.taobao.android.apatch.FastBuild) ImmutableDexFile(org.jf.dexlib2.immutable.ImmutableDexFile) DexFile(org.jf.dexlib2.iface.DexFile) DexDiffInfo(com.taobao.android.object.DexDiffInfo) FastPatchObject(com.taobao.android.repatch.FastPatchObject) MappingProcessor(com.taobao.android.repatch.mapping.MappingProcessor) MappingProcessorImpl(com.taobao.android.repatch.mapping.MappingProcessorImpl) InsTructionsReIClassDef(com.taobao.android.repatch.InsTructionsReIClassDef) ImmutableDexFile(org.jf.dexlib2.immutable.ImmutableDexFile) File(java.io.File) DexFile(org.jf.dexlib2.iface.DexFile) ImmutableDexFile(org.jf.dexlib2.immutable.ImmutableDexFile) MergePatch(com.taobao.android.apatch.MergePatch)

Example 4 with DexDiffInfo

use of com.taobao.android.object.DexDiffInfo in project atlas by alibaba.

the class TPatchDexTool method createTPatchDex.

/**
     * 生成淘宝的动态部署的patch的Dex文件
     *
     * @param outDexFile
     */
public DexDiffInfo createTPatchDex(File outDexFile) throws IOException, RecognitionException, PatchException {
    outDexFile.getParentFile().mkdirs();
    DexDiffInfo dexDiffInfo = dexDiffer.doDiff();
    // 将有变动的类写入到diff.dex
    final Set<ClassDef> modifyClasses = new HashSet<ClassDef>();
    for (ClassDiffInfo classDiffInfo : dexDiffInfo.getClassDiffInfoMap().values()) {
        if (DiffType.MODIFY.equals(classDiffInfo.getType()) || DiffType.ADD.equals(classDiffInfo.getType()) || DiffType.OVERRIDE.equals(classDiffInfo.getType())) {
            modifyClasses.add(classDiffInfo.getClassDef());
        }
    }
    if (modifyClasses.size() > 0) {
        DexFileFactory.writeDexFile(outDexFile.getAbsolutePath(), new DexFile() {

            @Nonnull
            @Override
            public Set<? extends ClassDef> getClasses() {
                return new AbstractSet<ClassDef>() {

                    @Nonnull
                    @Override
                    public Iterator<ClassDef> iterator() {
                        return modifyClasses.iterator();
                    }

                    @Override
                    public int size() {
                        return modifyClasses.size();
                    }
                };
            }
        });
    }
    return dexDiffInfo;
}
Also used : ClassDef(org.jf.dexlib2.iface.ClassDef) DexDiffInfo(com.taobao.android.object.DexDiffInfo) Nonnull(javax.annotation.Nonnull) ClassDiffInfo(com.taobao.android.object.ClassDiffInfo) DexFile(org.jf.dexlib2.iface.DexFile)

Aggregations

DexDiffInfo (com.taobao.android.object.DexDiffInfo)4 File (java.io.File)3 Nonnull (javax.annotation.Nonnull)2 ClassDef (org.jf.dexlib2.iface.ClassDef)2 DexFile (org.jf.dexlib2.iface.DexFile)2 AndFixFilterImpl (com.taobao.android.apatch.AndFixFilterImpl)1 FastBuild (com.taobao.android.apatch.FastBuild)1 MergePatch (com.taobao.android.apatch.MergePatch)1 DexDiffer (com.taobao.android.differ.dex.DexDiffer)1 PatchException (com.taobao.android.differ.dex.PatchException)1 ClassDiffInfo (com.taobao.android.object.ClassDiffInfo)1 FastPatchObject (com.taobao.android.repatch.FastPatchObject)1 InsTructionsReIClassDef (com.taobao.android.repatch.InsTructionsReIClassDef)1 MappingProcessor (com.taobao.android.repatch.mapping.MappingProcessor)1 MappingProcessorImpl (com.taobao.android.repatch.mapping.MappingProcessorImpl)1 MappingReader (com.taobao.android.repatch.mapping.MappingReader)1 MappingClassProcessor (com.taobao.android.repatch.processor.MappingClassProcessor)1 IOException (java.io.IOException)1 KeyStoreException (java.security.KeyStoreException)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1