use of com.tencent.tinker.build.dexpatcher.algorithms.diff.ClassDataSectionDiffAlgorithm in project tinker by Tencent.
the class DexPatchGenerator method executeAndSaveTo.
public void executeAndSaveTo(OutputStream out) throws IOException {
// Firstly, collect information of items we want to remove additionally
// in new dex and set them to corresponding diff algorithm implementations.
Pattern[] classNamePatterns = new Pattern[this.additionalRemovingClassPatternSet.size()];
int classNamePatternCount = 0;
for (String regExStr : this.additionalRemovingClassPatternSet) {
classNamePatterns[classNamePatternCount++] = Pattern.compile(regExStr);
}
List<Integer> typeIdOfClassDefsToRemove = new ArrayList<>(classNamePatternCount);
List<Integer> offsetOfClassDatasToRemove = new ArrayList<>(classNamePatternCount);
for (ClassDef classDef : this.newDex.classDefs()) {
String typeName = this.newDex.typeNames().get(classDef.typeIndex);
for (Pattern pattern : classNamePatterns) {
if (pattern.matcher(typeName).matches()) {
typeIdOfClassDefsToRemove.add(classDef.typeIndex);
offsetOfClassDatasToRemove.add(classDef.classDataOffset);
break;
}
}
}
((ClassDefSectionDiffAlgorithm) this.classDefSectionDiffAlg).setTypeIdOfClassDefsToRemove(typeIdOfClassDefsToRemove);
((ClassDataSectionDiffAlgorithm) this.classDataSectionDiffAlg).setOffsetOfClassDatasToRemove(offsetOfClassDatasToRemove);
// Then, run diff algorithms according to sections' dependencies.
// Use size calculated by algorithms above or from dex file definition to
// calculate sections' offset and patched dex size.
// Calculate header and id sections size, so that we can work out
// the base offset of typeLists Section.
int patchedheaderSize = SizeOf.HEADER_ITEM;
int patchedStringIdsSize = newDex.getTableOfContents().stringIds.size * SizeOf.STRING_ID_ITEM;
int patchedTypeIdsSize = newDex.getTableOfContents().typeIds.size * SizeOf.TYPE_ID_ITEM;
// Although simulatePatchOperation can calculate this value, since protoIds section
// depends on typeLists section, we can't run protoIds Section's simulatePatchOperation
// method so far. Instead we calculate protoIds section's size using information in newDex
// directly.
int patchedProtoIdsSize = newDex.getTableOfContents().protoIds.size * SizeOf.PROTO_ID_ITEM;
int patchedFieldIdsSize = newDex.getTableOfContents().fieldIds.size * SizeOf.MEMBER_ID_ITEM;
int patchedMethodIdsSize = newDex.getTableOfContents().methodIds.size * SizeOf.MEMBER_ID_ITEM;
int patchedClassDefsSize = newDex.getTableOfContents().classDefs.size * SizeOf.CLASS_DEF_ITEM;
int patchedIdSectionSize = patchedStringIdsSize + patchedTypeIdsSize + patchedProtoIdsSize + patchedFieldIdsSize + patchedMethodIdsSize + patchedClassDefsSize;
this.patchedHeaderOffset = 0;
// The diff works on each sections obey such procedure:
// 1. Execute diff algorithms to calculate indices of items we need to add, del and replace.
// 2. Execute patch algorithm simulation to calculate indices and offsets mappings that is
// necessary to next section's diff works.
// Immediately do the patch simulation so that we can know:
// 1. Indices and offsets mapping between old dex and patched dex.
// 2. Indices and offsets mapping between new dex and patched dex.
// These information will be used to do next diff works.
this.patchedStringIdsOffset = patchedHeaderOffset + patchedheaderSize;
if (this.oldDex.getTableOfContents().stringIds.isElementFourByteAligned) {
this.patchedStringIdsOffset = SizeOf.roundToTimesOfFour(this.patchedStringIdsOffset);
}
this.stringDataSectionDiffAlg.execute();
this.patchedStringDataItemsOffset = patchedheaderSize + patchedIdSectionSize;
if (this.oldDex.getTableOfContents().stringDatas.isElementFourByteAligned) {
this.patchedStringDataItemsOffset = SizeOf.roundToTimesOfFour(this.patchedStringDataItemsOffset);
}
this.stringDataSectionDiffAlg.simulatePatchOperation(this.patchedStringDataItemsOffset);
this.typeIdSectionDiffAlg.execute();
this.patchedTypeIdsOffset = this.patchedStringIdsOffset + patchedStringIdsSize;
if (this.oldDex.getTableOfContents().typeIds.isElementFourByteAligned) {
this.patchedTypeIdsOffset = SizeOf.roundToTimesOfFour(this.patchedTypeIdsOffset);
}
this.typeIdSectionDiffAlg.simulatePatchOperation(this.patchedTypeIdsOffset);
this.typeListSectionDiffAlg.execute();
this.patchedTypeListsOffset = patchedheaderSize + patchedIdSectionSize + this.stringDataSectionDiffAlg.getPatchedSectionSize();
if (this.oldDex.getTableOfContents().typeLists.isElementFourByteAligned) {
this.patchedTypeListsOffset = SizeOf.roundToTimesOfFour(this.patchedTypeListsOffset);
}
this.typeListSectionDiffAlg.simulatePatchOperation(this.patchedTypeListsOffset);
this.protoIdSectionDiffAlg.execute();
this.patchedProtoIdsOffset = this.patchedTypeIdsOffset + patchedTypeIdsSize;
if (this.oldDex.getTableOfContents().protoIds.isElementFourByteAligned) {
this.patchedProtoIdsOffset = SizeOf.roundToTimesOfFour(this.patchedProtoIdsOffset);
}
this.protoIdSectionDiffAlg.simulatePatchOperation(this.patchedProtoIdsOffset);
this.fieldIdSectionDiffAlg.execute();
this.patchedFieldIdsOffset = this.patchedProtoIdsOffset + patchedProtoIdsSize;
if (this.oldDex.getTableOfContents().fieldIds.isElementFourByteAligned) {
this.patchedFieldIdsOffset = SizeOf.roundToTimesOfFour(this.patchedFieldIdsOffset);
}
this.fieldIdSectionDiffAlg.simulatePatchOperation(this.patchedFieldIdsOffset);
this.methodIdSectionDiffAlg.execute();
this.patchedMethodIdsOffset = this.patchedFieldIdsOffset + patchedFieldIdsSize;
if (this.oldDex.getTableOfContents().methodIds.isElementFourByteAligned) {
this.patchedMethodIdsOffset = SizeOf.roundToTimesOfFour(this.patchedMethodIdsOffset);
}
this.methodIdSectionDiffAlg.simulatePatchOperation(this.patchedMethodIdsOffset);
this.annotationSectionDiffAlg.execute();
this.patchedAnnotationItemsOffset = this.patchedTypeListsOffset + this.typeListSectionDiffAlg.getPatchedSectionSize();
if (this.oldDex.getTableOfContents().annotations.isElementFourByteAligned) {
this.patchedAnnotationItemsOffset = SizeOf.roundToTimesOfFour(this.patchedAnnotationItemsOffset);
}
this.annotationSectionDiffAlg.simulatePatchOperation(this.patchedAnnotationItemsOffset);
this.annotationSetSectionDiffAlg.execute();
this.patchedAnnotationSetItemsOffset = this.patchedAnnotationItemsOffset + this.annotationSectionDiffAlg.getPatchedSectionSize();
if (this.oldDex.getTableOfContents().annotationSets.isElementFourByteAligned) {
this.patchedAnnotationSetItemsOffset = SizeOf.roundToTimesOfFour(this.patchedAnnotationSetItemsOffset);
}
this.annotationSetSectionDiffAlg.simulatePatchOperation(this.patchedAnnotationSetItemsOffset);
this.annotationSetRefListSectionDiffAlg.execute();
this.patchedAnnotationSetRefListItemsOffset = this.patchedAnnotationSetItemsOffset + this.annotationSetSectionDiffAlg.getPatchedSectionSize();
if (this.oldDex.getTableOfContents().annotationSetRefLists.isElementFourByteAligned) {
this.patchedAnnotationSetRefListItemsOffset = SizeOf.roundToTimesOfFour(this.patchedAnnotationSetRefListItemsOffset);
}
this.annotationSetRefListSectionDiffAlg.simulatePatchOperation(this.patchedAnnotationSetRefListItemsOffset);
this.annotationsDirectorySectionDiffAlg.execute();
this.patchedAnnotationsDirectoryItemsOffset = this.patchedAnnotationSetRefListItemsOffset + this.annotationSetRefListSectionDiffAlg.getPatchedSectionSize();
if (this.oldDex.getTableOfContents().annotationsDirectories.isElementFourByteAligned) {
this.patchedAnnotationsDirectoryItemsOffset = SizeOf.roundToTimesOfFour(this.patchedAnnotationsDirectoryItemsOffset);
}
this.annotationsDirectorySectionDiffAlg.simulatePatchOperation(this.patchedAnnotationsDirectoryItemsOffset);
this.debugInfoSectionDiffAlg.execute();
this.patchedDebugInfoItemsOffset = this.patchedAnnotationsDirectoryItemsOffset + this.annotationsDirectorySectionDiffAlg.getPatchedSectionSize();
if (this.oldDex.getTableOfContents().debugInfos.isElementFourByteAligned) {
this.patchedDebugInfoItemsOffset = SizeOf.roundToTimesOfFour(this.patchedDebugInfoItemsOffset);
}
this.debugInfoSectionDiffAlg.simulatePatchOperation(this.patchedDebugInfoItemsOffset);
this.codeSectionDiffAlg.execute();
this.patchedCodeItemsOffset = this.patchedDebugInfoItemsOffset + this.debugInfoSectionDiffAlg.getPatchedSectionSize();
if (this.oldDex.getTableOfContents().codes.isElementFourByteAligned) {
this.patchedCodeItemsOffset = SizeOf.roundToTimesOfFour(this.patchedCodeItemsOffset);
}
this.codeSectionDiffAlg.simulatePatchOperation(this.patchedCodeItemsOffset);
this.classDataSectionDiffAlg.execute();
this.patchedClassDataItemsOffset = this.patchedCodeItemsOffset + this.codeSectionDiffAlg.getPatchedSectionSize();
if (this.oldDex.getTableOfContents().classDatas.isElementFourByteAligned) {
this.patchedClassDataItemsOffset = SizeOf.roundToTimesOfFour(this.patchedClassDataItemsOffset);
}
this.classDataSectionDiffAlg.simulatePatchOperation(this.patchedClassDataItemsOffset);
this.encodedArraySectionDiffAlg.execute();
this.patchedEncodedArrayItemsOffset = this.patchedClassDataItemsOffset + this.classDataSectionDiffAlg.getPatchedSectionSize();
if (this.oldDex.getTableOfContents().encodedArrays.isElementFourByteAligned) {
this.patchedEncodedArrayItemsOffset = SizeOf.roundToTimesOfFour(this.patchedEncodedArrayItemsOffset);
}
this.encodedArraySectionDiffAlg.simulatePatchOperation(this.patchedEncodedArrayItemsOffset);
this.classDefSectionDiffAlg.execute();
this.patchedClassDefsOffset = this.patchedMethodIdsOffset + patchedMethodIdsSize;
if (this.oldDex.getTableOfContents().classDefs.isElementFourByteAligned) {
this.patchedClassDefsOffset = SizeOf.roundToTimesOfFour(this.patchedClassDefsOffset);
}
// Calculate any values we still know nothing about them.
this.patchedMapListOffset = this.patchedEncodedArrayItemsOffset + this.encodedArraySectionDiffAlg.getPatchedSectionSize();
if (this.oldDex.getTableOfContents().mapList.isElementFourByteAligned) {
this.patchedMapListOffset = SizeOf.roundToTimesOfFour(this.patchedMapListOffset);
}
int patchedMapListSize = newDex.getTableOfContents().mapList.byteCount;
this.patchedDexSize = this.patchedMapListOffset + patchedMapListSize;
// Finally, write results to patch file.
writeResultToStream(out);
}
Aggregations