use of com.tencent.tinker.android.dex.ClassDef in project tinker by Tencent.
the class DexDiffDecoder method collectAddedOrDeletedClasses.
/**
* Before starting real diff works, we collect added class descriptor
* and deleted class descriptor for further analysing in {@code checkCrossDexMovingClasses}.
*/
private void collectAddedOrDeletedClasses(File oldFile, File newFile) throws IOException {
Dex oldDex = new Dex(oldFile);
Dex newDex = new Dex(newFile);
Set<String> oldClassDescs = new HashSet<>();
for (ClassDef oldClassDef : oldDex.classDefs()) {
oldClassDescs.add(oldDex.typeNames().get(oldClassDef.typeIndex));
}
Set<String> newClassDescs = new HashSet<>();
for (ClassDef newClassDef : newDex.classDefs()) {
newClassDescs.add(newDex.typeNames().get(newClassDef.typeIndex));
}
Set<String> addedClassDescs = new HashSet<>(newClassDescs);
addedClassDescs.removeAll(oldClassDescs);
Set<String> deletedClassDescs = new HashSet<>(oldClassDescs);
deletedClassDescs.removeAll(newClassDescs);
for (String addedClassDesc : addedClassDescs) {
if (addedClassDescToDexNameMap.containsKey(addedClassDesc)) {
throw new TinkerPatchException(String.format("Class Duplicate. Class [%s] is added in both new dex: [%s] and [%s]. Please check your newly apk.", addedClassDesc, addedClassDescToDexNameMap.get(addedClassDesc), newFile.toString()));
} else {
addedClassDescToDexNameMap.put(addedClassDesc, newFile.toString());
}
}
for (String deletedClassDesc : deletedClassDescs) {
if (deletedClassDescToDexNameMap.containsKey(deletedClassDesc)) {
throw new TinkerPatchException(String.format("Class Duplicate. Class [%s] is deleted in both old dex: [%s] and [%s]. Please check your base apk.", deletedClassDesc, addedClassDescToDexNameMap.get(deletedClassDesc), oldFile.toString()));
} else {
deletedClassDescToDexNameMap.put(deletedClassDesc, newFile.toString());
}
}
}
use of com.tencent.tinker.android.dex.ClassDef in project tinker by Tencent.
the class ExcludedClassModifiedChecker method checkIfExcludedClassWasModifiedInNewDex.
public void checkIfExcludedClassWasModifiedInNewDex(File oldFile, File newFile) throws IOException, TinkerPatchException {
if (oldFile == null && newFile == null) {
throw new TinkerPatchException("both oldFile and newFile are null.");
}
oldDex = (oldFile != null ? new Dex(oldFile) : null);
newDex = (newFile != null ? new Dex(newFile) : null);
int stmCode = STMCODE_START;
while (stmCode != STMCODE_END) {
switch(stmCode) {
/**
* Check rule:
* Loader classes must only appear in primary dex and each of them in primary old dex should keep
* completely consistent in new primary dex.
*
* An error is announced when any of these conditions below is fit:
* 1. Primary old dex is missing.
* 2. Primary new dex is missing.
* 3. There are not any loader classes in primary old dex.
* 4. There are some new loader classes added in new primary dex.
* 5. Loader classes in old primary dex are modified, deleted in new primary dex.
* 6. Loader classes are found in secondary old dexes.
* 7. Loader classes are found in secondary new dexes.
*/
case STMCODE_START:
{
boolean isPrimaryDex = isPrimaryDex((oldFile == null ? newFile : oldFile));
if (isPrimaryDex) {
if (oldFile == null) {
stmCode = STMCODE_ERROR_PRIMARY_OLD_DEX_IS_MISSING;
} else if (newFile == null) {
stmCode = STMCODE_ERROR_PRIMARY_NEW_DEX_IS_MISSING;
} else {
dexCmptor.startCheck(oldDex, newDex);
deletedClassInfos = dexCmptor.getDeletedClassInfos();
addedClassInfos = dexCmptor.getAddedClassInfos();
changedClassInfosMap = dexCmptor.getChangedClassDescToInfosMap();
// All loader classes are in new dex, while none of them in old one.
if (deletedClassInfos.isEmpty() && changedClassInfosMap.isEmpty() && !addedClassInfos.isEmpty()) {
stmCode = STMCODE_ERROR_LOADER_CLASS_NOT_IN_PRIMARY_OLD_DEX;
} else {
if (deletedClassInfos.isEmpty() && addedClassInfos.isEmpty()) {
// class descriptor is completely matches, see if any contents changes.
if (changedClassInfosMap.isEmpty()) {
stmCode = STMCODE_END;
} else {
stmCode = STMCODE_ERROR_LOADER_CLASS_CHANGED;
}
} else {
stmCode = STMCODE_ERROR_LOADER_CLASS_IN_PRIMARY_DEX_MISMATCH;
}
}
}
} else {
Set<Pattern> patternsOfClassDescToCheck = new HashSet<>();
for (String patternStr : config.mDexLoaderPattern) {
patternsOfClassDescToCheck.add(Pattern.compile(PatternUtils.dotClassNamePatternToDescriptorRegEx(patternStr)));
}
if (oldDex != null) {
oldClassesDescToCheck.clear();
for (ClassDef classDef : oldDex.classDefs()) {
String desc = oldDex.typeNames().get(classDef.typeIndex);
if (Utils.isStringMatchesPatterns(desc, patternsOfClassDescToCheck)) {
oldClassesDescToCheck.add(desc);
}
}
if (!oldClassesDescToCheck.isEmpty()) {
stmCode = STMCODE_ERROR_LOADER_CLASS_FOUND_IN_SECONDARY_OLD_DEX;
break;
}
}
if (newDex != null) {
newClassesDescToCheck.clear();
for (ClassDef classDef : newDex.classDefs()) {
String desc = newDex.typeNames().get(classDef.typeIndex);
if (Utils.isStringMatchesPatterns(desc, patternsOfClassDescToCheck)) {
newClassesDescToCheck.add(desc);
}
}
if (!newClassesDescToCheck.isEmpty()) {
stmCode = STMCODE_ERROR_LOADER_CLASS_FOUND_IN_SECONDARY_NEW_DEX;
break;
}
}
stmCode = STMCODE_END;
}
break;
}
case STMCODE_ERROR_PRIMARY_OLD_DEX_IS_MISSING:
{
throw new TinkerPatchException("old primary dex is missing.");
}
case STMCODE_ERROR_PRIMARY_NEW_DEX_IS_MISSING:
{
throw new TinkerPatchException("new primary dex is missing.");
}
case STMCODE_ERROR_LOADER_CLASS_NOT_IN_PRIMARY_OLD_DEX:
{
throw new TinkerPatchException("all loader classes don't appear in old primary dex.");
}
case STMCODE_ERROR_LOADER_CLASS_IN_PRIMARY_DEX_MISMATCH:
{
throw new TinkerPatchException("loader classes in old primary dex are mismatched to those in new primary dex, \n" + "if deleted classes is not empty, check if your dex division strategy is fine. \n" + "added classes: " + Utils.collectionToString(addedClassInfos) + "\n" + "deleted classes: " + Utils.collectionToString(deletedClassInfos));
}
case STMCODE_ERROR_LOADER_CLASS_FOUND_IN_SECONDARY_OLD_DEX:
{
throw new TinkerPatchException("loader classes are found in old secondary dex. Found classes: " + Utils.collectionToString(oldClassesDescToCheck));
}
case STMCODE_ERROR_LOADER_CLASS_FOUND_IN_SECONDARY_NEW_DEX:
{
throw new TinkerPatchException("loader classes are found in new secondary dex. Found classes: " + Utils.collectionToString(newClassesDescToCheck));
}
case STMCODE_ERROR_LOADER_CLASS_CHANGED:
{
String msg = "some loader class has been changed in new dex." + " Such these changes will not take effect!!" + " related classes: " + Utils.collectionToString(changedClassInfosMap.keySet());
throw new TinkerPatchException(msg);
}
default:
{
Logger.e("internal-error: unexpected stmCode.");
stmCode = STMCODE_END;
break;
}
}
}
}
use of com.tencent.tinker.android.dex.ClassDef in project tinker by Tencent.
the class DexClassesComparator method isTypeChangeAffectedToRef.
private boolean isTypeChangeAffectedToRef(Dex oldDex, Dex newDex, int oldTypeId, int newTypeId) {
if (oldTypeId != ClassDef.NO_INDEX && newTypeId != ClassDef.NO_INDEX) {
String oldClassDesc = oldDex.typeNames().get(oldTypeId);
String newClassDesc = newDex.typeNames().get(newTypeId);
if (!oldClassDesc.equals(newClassDesc)) {
return true;
}
final DexClassInfo oldClassInfo = oldClassDescriptorToClassInfoMap.get(oldClassDesc);
final DexClassInfo newClassInfo = newClassDescriptorToClassInfoMap.get(newClassDesc);
ClassDef oldClassDef = (oldClassInfo != null ? oldClassInfo.classDef : null);
ClassDef newClassDef = (newClassInfo != null ? newClassInfo.classDef : null);
if (oldClassDef != null && newClassDef != null) {
return isClassChangeAffectedToRef(oldClassInfo.owner, newClassInfo.owner, oldClassDef, newClassDef);
} else if (oldClassDef == null && newClassDef == null) {
return false;
} else {
// in patched dexes as we expected, here we ignore this kind of changes.
return !Utils.isStringMatchesPatterns(oldClassDesc, patternsOfIgnoredRemovedClassDesc);
}
} else {
if (!(oldTypeId == ClassDef.NO_INDEX && newTypeId == ClassDef.NO_INDEX)) {
return true;
}
}
return false;
}
use of com.tencent.tinker.android.dex.ClassDef 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);
}
use of com.tencent.tinker.android.dex.ClassDef in project tinker by Tencent.
the class DexClassesComparator method startCheck.
public void startCheck(DexGroup oldDexGroup, DexGroup newDexGroup) {
// Init assist structures.
addedClassInfoList.clear();
deletedClassInfoList.clear();
changedClassDescToClassInfosMap.clear();
oldDescriptorOfClassesToCheck.clear();
newDescriptorOfClassesToCheck.clear();
oldClassDescriptorToClassInfoMap.clear();
newClassDescriptorToClassInfoMap.clear();
refAffectedClassDescs.clear();
// and collect typeIndex of classes to check in oldDexes.
for (Dex oldDex : oldDexGroup.dexes) {
int classDefIndex = 0;
for (ClassDef oldClassDef : oldDex.classDefs()) {
String desc = oldDex.typeNames().get(oldClassDef.typeIndex);
if (Utils.isStringMatchesPatterns(desc, patternsOfClassDescToCheck)) {
if (!oldDescriptorOfClassesToCheck.add(desc)) {
throw new IllegalStateException(String.format("duplicate class descriptor [%s] in different old dexes.", desc));
}
}
DexClassInfo classInfo = new DexClassInfo(desc, classDefIndex, oldClassDef, oldDex);
++classDefIndex;
oldClassDescriptorToClassInfoMap.put(desc, classInfo);
}
}
// and collect typeIndex of classes to check in newDexes.
for (Dex newDex : newDexGroup.dexes) {
int classDefIndex = 0;
for (ClassDef newClassDef : newDex.classDefs()) {
String desc = newDex.typeNames().get(newClassDef.typeIndex);
if (Utils.isStringMatchesPatterns(desc, patternsOfClassDescToCheck)) {
if (!newDescriptorOfClassesToCheck.add(desc)) {
throw new IllegalStateException(String.format("duplicate class descriptor [%s] in different new dexes.", desc));
}
}
DexClassInfo classInfo = new DexClassInfo(desc, classDefIndex, newClassDef, newDex);
++classDefIndex;
newClassDescriptorToClassInfoMap.put(desc, classInfo);
}
}
Set<String> deletedClassDescs = new HashSet<>(oldDescriptorOfClassesToCheck);
deletedClassDescs.removeAll(newDescriptorOfClassesToCheck);
for (String desc : deletedClassDescs) {
// from result.
if (Utils.isStringMatchesPatterns(desc, patternsOfIgnoredRemovedClassDesc)) {
logger.i(TAG, "Ignored deleted class: %s", desc);
continue;
} else {
logger.i(TAG, "Deleted class: %s", desc);
}
deletedClassInfoList.add(oldClassDescriptorToClassInfoMap.get(desc));
}
Set<String> addedClassDescs = new HashSet<>(newDescriptorOfClassesToCheck);
addedClassDescs.removeAll(oldDescriptorOfClassesToCheck);
for (String desc : addedClassDescs) {
logger.i(TAG, "Added class: %s", desc);
addedClassInfoList.add(newClassDescriptorToClassInfoMap.get(desc));
}
Set<String> mayBeChangedClassDescs = new HashSet<>(oldDescriptorOfClassesToCheck);
mayBeChangedClassDescs.retainAll(newDescriptorOfClassesToCheck);
for (String desc : mayBeChangedClassDescs) {
DexClassInfo oldClassInfo = oldClassDescriptorToClassInfoMap.get(desc);
DexClassInfo newClassInfo = newClassDescriptorToClassInfoMap.get(desc);
switch(compareMode) {
case COMPARE_MODE_NORMAL:
{
if (!isSameClass(oldClassInfo.owner, newClassInfo.owner, oldClassInfo.classDef, newClassInfo.classDef)) {
logger.i(TAG, "Changed class: %s", desc);
changedClassDescToClassInfosMap.put(desc, new DexClassInfo[] { oldClassInfo, newClassInfo });
}
break;
}
case COMPARE_MODE_CAUSE_REF_CHANGE_ONLY:
{
if (isClassChangeAffectedToRef(oldClassInfo.owner, newClassInfo.owner, oldClassInfo.classDef, newClassInfo.classDef)) {
logger.i(TAG, "Ref-changed class: %s", desc);
changedClassDescToClassInfosMap.put(desc, new DexClassInfo[] { oldClassInfo, newClassInfo });
}
break;
}
}
}
}
Aggregations