FileDocCategorySizeDatePackage
FindUsages.javaAPI DocAndroid 5.1 API7721Thu Mar 12 22:18:30 GMT 2015com.android.dx.command.findusages

FindUsages

public final class FindUsages extends Object

Fields Summary
private final com.android.dex.Dex
dex
private final Set
methodIds
private final Set
fieldIds
private final com.android.dx.io.CodeReader
codeReader
private final PrintWriter
out
private com.android.dex.ClassDef
currentClass
private ClassData.Method
currentMethod
Constructors Summary
public FindUsages(com.android.dex.Dex dex, String declaredBy, String memberName, PrintWriter out)


               
        this.dex = dex;
        this.out = out;

        Set<Integer> typeStringIndexes = new HashSet<Integer>();
        Set<Integer> memberNameIndexes = new HashSet<Integer>();
        Pattern declaredByPattern = Pattern.compile(declaredBy);
        Pattern memberNamePattern = Pattern.compile(memberName);
        List<String> strings = dex.strings();
        for (int i = 0; i < strings.size(); ++i) {
            String string = strings.get(i);
            if (declaredByPattern.matcher(string).matches()) {
                typeStringIndexes.add(i);
            }
            if (memberNamePattern.matcher(string).matches()) {
                memberNameIndexes.add(i);
            }
        }
        if (typeStringIndexes.isEmpty() || memberNameIndexes.isEmpty()) {
            methodIds = fieldIds = null;
            return; // these symbols are not mentioned in this dex
        }

        methodIds = new HashSet<Integer>();
        fieldIds = new HashSet<Integer>();
        for (int typeStringIndex : typeStringIndexes) {
            int typeIndex = Collections.binarySearch(dex.typeIds(), typeStringIndex);
            if (typeIndex < 0) {
                continue; // this type name isn't used as a type in this dex
            }
            methodIds.addAll(getMethodIds(dex, memberNameIndexes, typeIndex));
            fieldIds.addAll(getFieldIds(dex, memberNameIndexes, typeIndex));
        }

        codeReader.setFieldVisitor(new CodeReader.Visitor() {
            public void visit(DecodedInstruction[] all,
                    DecodedInstruction one) {
                int fieldId = one.getIndex();
                if (fieldIds.contains(fieldId)) {
                    out.println(location() + ": field reference " + dex.fieldIds().get(fieldId)
                            + " (" + OpcodeInfo.getName(one.getOpcode()) + ")");
                }
            }
        });

        codeReader.setMethodVisitor(new CodeReader.Visitor() {
            public void visit(DecodedInstruction[] all, DecodedInstruction one) {
                int methodId = one.getIndex();
                if (methodIds.contains(methodId)) {
                    out.println(location() + ": method reference " + dex.methodIds().get(methodId)
                            + " (" + OpcodeInfo.getName(one.getOpcode()) + ")");
                }
            }
        });
    
Methods Summary
private java.util.SetfindAssignableTypes(com.android.dex.Dex dex, int typeIndex)
Returns the set of types that can be assigned to {@code typeIndex}.

        Set<Integer> assignableTypes = new HashSet<Integer>();
        assignableTypes.add(typeIndex);

        for (ClassDef classDef : dex.classDefs()) {
            if (assignableTypes.contains(classDef.getSupertypeIndex())) {
                assignableTypes.add(classDef.getTypeIndex());
                continue;
            }

            for (int implemented : classDef.getInterfaces()) {
                if (assignableTypes.contains(implemented)) {
                    assignableTypes.add(classDef.getTypeIndex());
                    break;
                }
            }
        }

        return assignableTypes;
    
public voidfindUsages()
Prints usages to out.

        if (fieldIds == null || methodIds == null) {
            return;
        }

        for (ClassDef classDef : dex.classDefs()) {
            currentClass = classDef;
            currentMethod = null;

            if (classDef.getClassDataOffset() == 0) {
                continue;
            }

            ClassData classData = dex.readClassData(classDef);
            for (ClassData.Field field : classData.allFields()) {
                int fieldIndex = field.getFieldIndex();
                if (fieldIds.contains(fieldIndex)) {
                    out.println(location() + " field declared " + dex.fieldIds().get(fieldIndex));
                }
            }

            for (ClassData.Method method : classData.allMethods()) {
                currentMethod = method;
                int methodIndex = method.getMethodIndex();
                if (methodIds.contains(methodIndex)) {
                    out.println(location() + " method declared " + dex.methodIds().get(methodIndex));
                }
                if (method.getCodeOffset() != 0) {
                    codeReader.visitAll(dex.readCode(method).getInstructions());
                }
            }
        }

        currentClass = null;
        currentMethod = null;
    
private java.util.SetgetFieldIds(com.android.dex.Dex dex, java.util.Set memberNameIndexes, int declaringType)
Returns the fields with {@code memberNameIndex} declared by {@code declaringType}.

        Set<Integer> fields = new HashSet<Integer>();
        int fieldIndex = 0;
        for (FieldId fieldId : dex.fieldIds()) {
            if (memberNameIndexes.contains(fieldId.getNameIndex())
                    && declaringType == fieldId.getDeclaringClassIndex()) {
                fields.add(fieldIndex);
            }
            fieldIndex++;
        }
        return fields;
    
private java.util.SetgetMethodIds(com.android.dex.Dex dex, java.util.Set memberNameIndexes, int declaringType)
Returns the methods with {@code memberNameIndex} declared by {@code declaringType} and its subtypes.

        Set<Integer> subtypes = findAssignableTypes(dex, declaringType);

        Set<Integer> methods = new HashSet<Integer>();
        int methodIndex = 0;
        for (MethodId method : dex.methodIds()) {
            if (memberNameIndexes.contains(method.getNameIndex())
                    && subtypes.contains(method.getDeclaringClassIndex())) {
                methods.add(methodIndex);
            }
            methodIndex++;
        }
        return methods;
    
private java.lang.Stringlocation()

        String className = dex.typeNames().get(currentClass.getTypeIndex());
        if (currentMethod != null) {
            MethodId methodId = dex.methodIds().get(currentMethod.getMethodIndex());
            return className + "." + dex.strings().get(methodId.getNameIndex());
        } else {
            return className;
        }