Search in sources :

Example 1 with BuilderField

use of org.jf.dexlib2.writer.builder.BuilderField in project tinker by Tencent.

the class DexDiffDecoder method generateChangedClassesDexFile.

@SuppressWarnings("NewApi")
private void generateChangedClassesDexFile() throws IOException {
    final String dexMode = config.mDexRaw ? "raw" : "jar";
    List<File> oldDexList = new ArrayList<>();
    List<File> newDexList = new ArrayList<>();
    for (AbstractMap.SimpleEntry<File, File> oldAndNewDexFilePair : oldAndNewDexFilePairList) {
        File oldDexFile = oldAndNewDexFilePair.getKey();
        File newDexFile = oldAndNewDexFilePair.getValue();
        if (oldDexFile != null) {
            oldDexList.add(oldDexFile);
        }
        if (newDexFile != null) {
            newDexList.add(newDexFile);
        }
    }
    DexGroup oldDexGroup = DexGroup.wrap(oldDexList);
    DexGroup newDexGroup = DexGroup.wrap(newDexList);
    ChangedClassesDexClassInfoCollector collector = new ChangedClassesDexClassInfoCollector();
    collector.setExcludedClassPatterns(config.mDexLoaderPattern);
    collector.setLogger(dexPatcherLoggerBridge);
    collector.setIncludeRefererToRefererAffectedClasses(true);
    Set<DexClassInfo> classInfosInChangedClassesDex = collector.doCollect(oldDexGroup, newDexGroup);
    Set<Dex> owners = new HashSet<>();
    Map<Dex, Set<String>> ownerToDescOfChangedClassesMap = new HashMap<>();
    for (DexClassInfo classInfo : classInfosInChangedClassesDex) {
        owners.add(classInfo.owner);
        Set<String> descOfChangedClasses = ownerToDescOfChangedClassesMap.get(classInfo.owner);
        if (descOfChangedClasses == null) {
            descOfChangedClasses = new HashSet<>();
            ownerToDescOfChangedClassesMap.put(classInfo.owner, descOfChangedClasses);
        }
        descOfChangedClasses.add(classInfo.classDesc);
    }
    StringBuilder metaBuilder = new StringBuilder();
    int changedDexId = 1;
    for (Dex dex : owners) {
        Set<String> descOfChangedClassesInCurrDex = ownerToDescOfChangedClassesMap.get(dex);
        DexFile dexFile = new DexBackedDexFile(org.jf.dexlib2.Opcodes.forApi(20), dex.getBytes());
        boolean isCurrentDexHasChangedClass = false;
        for (org.jf.dexlib2.iface.ClassDef classDef : dexFile.getClasses()) {
            if (descOfChangedClassesInCurrDex.contains(classDef.getType())) {
                isCurrentDexHasChangedClass = true;
                break;
            }
        }
        if (!isCurrentDexHasChangedClass) {
            continue;
        }
        DexBuilder dexBuilder = new DexBuilder(Opcodes.forApi(23));
        for (org.jf.dexlib2.iface.ClassDef classDef : dexFile.getClasses()) {
            if (!descOfChangedClassesInCurrDex.contains(classDef.getType())) {
                continue;
            }
            Logger.d("Class %s will be added into changed classes dex ...", classDef.getType());
            List<BuilderField> builderFields = new ArrayList<>();
            for (Field field : classDef.getFields()) {
                final BuilderField builderField = dexBuilder.internField(field.getDefiningClass(), field.getName(), field.getType(), field.getAccessFlags(), field.getInitialValue(), field.getAnnotations());
                builderFields.add(builderField);
            }
            List<BuilderMethod> builderMethods = new ArrayList<>();
            for (Method method : classDef.getMethods()) {
                MethodImplementation methodImpl = method.getImplementation();
                if (methodImpl != null) {
                    methodImpl = new BuilderMutableMethodImplementation(dexBuilder, methodImpl);
                }
                BuilderMethod builderMethod = dexBuilder.internMethod(method.getDefiningClass(), method.getName(), method.getParameters(), method.getReturnType(), method.getAccessFlags(), method.getAnnotations(), methodImpl);
                builderMethods.add(builderMethod);
            }
            dexBuilder.internClassDef(classDef.getType(), classDef.getAccessFlags(), classDef.getSuperclass(), classDef.getInterfaces(), classDef.getSourceFile(), classDef.getAnnotations(), builderFields, builderMethods);
        }
        // Write constructed changed classes dex to file and record it in meta file.
        String changedDexName = null;
        if (changedDexId == 1) {
            changedDexName = "classes.dex";
        } else {
            changedDexName = "classes" + changedDexId + ".dex";
        }
        final File dest = new File(config.mTempResultDir + "/" + changedDexName);
        final FileDataStore fileDataStore = new FileDataStore(dest);
        dexBuilder.writeTo(fileDataStore);
        final String md5 = MD5.getMD5(dest);
        appendMetaLine(metaBuilder, changedDexName, "", md5, md5, 0, 0, 0, dexMode);
        ++changedDexId;
    }
    final String meta = metaBuilder.toString();
    Logger.d("\nDexDecoder:write changed classes dex meta file data:\n%s", meta);
    metaWriter.writeLineToInfoFile(meta);
}
Also used : DexGroup(com.tencent.tinker.build.util.DexClassesComparator.DexGroup) MethodImplementation(org.jf.dexlib2.iface.MethodImplementation) BuilderMutableMethodImplementation(org.jf.dexlib2.builder.BuilderMutableMethodImplementation) Set(java.util.Set) HashSet(java.util.HashSet) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) AbstractMap(java.util.AbstractMap) BuilderField(org.jf.dexlib2.writer.builder.BuilderField) Field(org.jf.dexlib2.iface.Field) BuilderField(org.jf.dexlib2.writer.builder.BuilderField) FileDataStore(org.jf.dexlib2.writer.io.FileDataStore) HashSet(java.util.HashSet) DexBackedDexFile(org.jf.dexlib2.dexbacked.DexBackedDexFile) ChangedClassesDexClassInfoCollector(com.tencent.tinker.build.dexpatcher.util.ChangedClassesDexClassInfoCollector) BuilderMutableMethodImplementation(org.jf.dexlib2.builder.BuilderMutableMethodImplementation) Method(org.jf.dexlib2.iface.Method) BuilderMethod(org.jf.dexlib2.writer.builder.BuilderMethod) DexFile(org.jf.dexlib2.iface.DexFile) DexBackedDexFile(org.jf.dexlib2.dexbacked.DexBackedDexFile) DexBuilder(org.jf.dexlib2.writer.builder.DexBuilder) Dex(com.tencent.tinker.android.dex.Dex) BuilderMethod(org.jf.dexlib2.writer.builder.BuilderMethod) JarFile(java.util.jar.JarFile) DexFile(org.jf.dexlib2.iface.DexFile) DexBackedDexFile(org.jf.dexlib2.dexbacked.DexBackedDexFile) File(java.io.File) DexClassInfo(com.tencent.tinker.build.util.DexClassesComparator.DexClassInfo)

Aggregations

Dex (com.tencent.tinker.android.dex.Dex)1 ChangedClassesDexClassInfoCollector (com.tencent.tinker.build.dexpatcher.util.ChangedClassesDexClassInfoCollector)1 DexClassInfo (com.tencent.tinker.build.util.DexClassesComparator.DexClassInfo)1 DexGroup (com.tencent.tinker.build.util.DexClassesComparator.DexGroup)1 File (java.io.File)1 AbstractMap (java.util.AbstractMap)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 Set (java.util.Set)1 JarFile (java.util.jar.JarFile)1 BuilderMutableMethodImplementation (org.jf.dexlib2.builder.BuilderMutableMethodImplementation)1 DexBackedDexFile (org.jf.dexlib2.dexbacked.DexBackedDexFile)1 DexFile (org.jf.dexlib2.iface.DexFile)1 Field (org.jf.dexlib2.iface.Field)1 Method (org.jf.dexlib2.iface.Method)1 MethodImplementation (org.jf.dexlib2.iface.MethodImplementation)1 BuilderField (org.jf.dexlib2.writer.builder.BuilderField)1 BuilderMethod (org.jf.dexlib2.writer.builder.BuilderMethod)1 DexBuilder (org.jf.dexlib2.writer.builder.DexBuilder)1