use of com.tencent.tinker.build.dexpatcher.util.ChangedClassesDexClassInfoCollector 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);
}
Aggregations