summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/dexdeps/src/com/android/dexdeps/ClassRef.java70
-rw-r--r--tools/dexdeps/src/com/android/dexdeps/DexData.java89
-rw-r--r--tools/dexdeps/src/com/android/dexdeps/Output.java161
3 files changed, 218 insertions, 102 deletions
diff --git a/tools/dexdeps/src/com/android/dexdeps/ClassRef.java b/tools/dexdeps/src/com/android/dexdeps/ClassRef.java
new file mode 100644
index 000000000..8065a0aab
--- /dev/null
+++ b/tools/dexdeps/src/com/android/dexdeps/ClassRef.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dexdeps;
+
+import java.util.ArrayList;
+
+public class ClassRef {
+ private String mClassName;
+ private ArrayList<FieldRef> mFieldRefs;
+ private ArrayList<MethodRef> mMethodRefs;
+
+ /**
+ * Initializes a new class reference.
+ */
+ public ClassRef(String className) {
+ mClassName = className;
+ mFieldRefs = new ArrayList<FieldRef>();
+ mMethodRefs = new ArrayList<MethodRef>();
+ }
+
+ /**
+ * Adds the field to the field list.
+ */
+ public void addField(FieldRef fref) {
+ mFieldRefs.add(fref);
+ }
+
+ /**
+ * Returns the field list as an array.
+ */
+ public FieldRef[] getFieldArray() {
+ return mFieldRefs.toArray(new FieldRef[mFieldRefs.size()]);
+ }
+
+ /**
+ * Adds the method to the method list.
+ */
+ public void addMethod(MethodRef mref) {
+ mMethodRefs.add(mref);
+ }
+
+ /**
+ * Returns the method list as an array.
+ */
+ public MethodRef[] getMethodArray() {
+ return mMethodRefs.toArray(new MethodRef[mMethodRefs.size()]);
+ }
+
+ /**
+ * Gets the class name.
+ */
+ public String getName() {
+ return mClassName;
+ }
+}
+
diff --git a/tools/dexdeps/src/com/android/dexdeps/DexData.java b/tools/dexdeps/src/com/android/dexdeps/DexData.java
index fa79d60b6..0a7fa2d4e 100644
--- a/tools/dexdeps/src/com/android/dexdeps/DexData.java
+++ b/tools/dexdeps/src/com/android/dexdeps/DexData.java
@@ -341,66 +341,75 @@ public class DexData {
}
/**
- * Returns an array with all of the field references that don't
- * correspond to classes in the DEX file.
+ * Returns an array with all of the class references that don't
+ * correspond to classes in the DEX file. Each class reference has
+ * a list of the referenced fields and methods associated with
+ * that class.
*/
- public FieldRef[] getExternalFieldReferences() {
- // get a count
+ public ClassRef[] getExternalReferences() {
+ // create a sparse array of ClassRef that parallels mTypeIds
+ ClassRef[] sparseRefs = new ClassRef[mTypeIds.length];
+
+ // create entries for all externally-referenced classes
int count = 0;
- for (int i = 0; i < mFieldIds.length; i++) {
- if (!mTypeIds[mFieldIds[i].classIdx].internal)
+ for (int i = 0; i < mTypeIds.length; i++) {
+ if (!mTypeIds[i].internal) {
+ sparseRefs[i] =
+ new ClassRef(mStrings[mTypeIds[i].descriptorIdx]);
count++;
+ }
}
- //System.out.println("count is " + count + " of " + mFieldIds.length);
+ // add fields and methods to the appropriate class entry
+ addExternalFieldReferences(sparseRefs);
+ addExternalMethodReferences(sparseRefs);
- FieldRef[] fieldRefs = new FieldRef[count];
- count = 0;
- for (int i = 0; i < mFieldIds.length; i++) {
- if (!mTypeIds[mFieldIds[i].classIdx].internal) {
- FieldIdItem fieldId = mFieldIds[i];
- fieldRefs[count++] =
- new FieldRef(classNameFromTypeIndex(fieldId.classIdx),
- classNameFromTypeIndex(fieldId.typeIdx),
- mStrings[fieldId.nameIdx]);
- }
+ // crunch out the sparseness
+ ClassRef[] classRefs = new ClassRef[count];
+ int idx = 0;
+ for (int i = 0; i < mTypeIds.length; i++) {
+ if (sparseRefs[i] != null)
+ classRefs[idx++] = sparseRefs[i];
}
- assert count == fieldRefs.length;
+ assert idx == count;
- return fieldRefs;
+ return classRefs;
}
/**
- * Returns an array with all of the method references that don't
- * correspond to classes in the DEX file.
+ * Runs through the list of field references, inserting external
+ * references into the appropriate ClassRef.
*/
- public MethodRef[] getExternalMethodReferences() {
- // get a count
- int count = 0;
- for (int i = 0; i < mMethodIds.length; i++) {
- if (!mTypeIds[mMethodIds[i].classIdx].internal)
- count++;
+ private void addExternalFieldReferences(ClassRef[] sparseRefs) {
+ for (int i = 0; i < mFieldIds.length; i++) {
+ if (!mTypeIds[mFieldIds[i].classIdx].internal) {
+ FieldIdItem fieldId = mFieldIds[i];
+ FieldRef newFieldRef = new FieldRef(
+ classNameFromTypeIndex(fieldId.classIdx),
+ classNameFromTypeIndex(fieldId.typeIdx),
+ mStrings[fieldId.nameIdx]);
+ sparseRefs[mFieldIds[i].classIdx].addField(newFieldRef);
+ }
}
+ }
- //System.out.println("count is " + count + " of " + mMethodIds.length);
-
- MethodRef[] methodRefs = new MethodRef[count];
- count = 0;
+ /**
+ * Runs through the list of method references, inserting external
+ * references into the appropriate ClassRef.
+ */
+ private void addExternalMethodReferences(ClassRef[] sparseRefs) {
for (int i = 0; i < mMethodIds.length; i++) {
if (!mTypeIds[mMethodIds[i].classIdx].internal) {
MethodIdItem methodId = mMethodIds[i];
- methodRefs[count++] =
- new MethodRef(classNameFromTypeIndex(methodId.classIdx),
- argArrayFromProtoIndex(methodId.protoIdx),
- returnTypeFromProtoIndex(methodId.protoIdx),
- mStrings[methodId.nameIdx]);
+ MethodRef newMethodRef = new MethodRef(
+ classNameFromTypeIndex(methodId.classIdx),
+ argArrayFromProtoIndex(methodId.protoIdx),
+ returnTypeFromProtoIndex(methodId.protoIdx),
+ mStrings[methodId.nameIdx]);
+ sparseRefs[mMethodIds[i].classIdx].addMethod(newMethodRef);
}
}
-
- assert count == methodRefs.length;
-
- return methodRefs;
}
diff --git a/tools/dexdeps/src/com/android/dexdeps/Output.java b/tools/dexdeps/src/com/android/dexdeps/Output.java
index 0039b3302..7114951dc 100644
--- a/tools/dexdeps/src/com/android/dexdeps/Output.java
+++ b/tools/dexdeps/src/com/android/dexdeps/Output.java
@@ -20,6 +20,12 @@ package com.android.dexdeps;
* Generate fancy output.
*/
public class Output {
+ private static final String IN0 = "";
+ private static final String IN1 = " ";
+ private static final String IN2 = " ";
+ private static final String IN3 = " ";
+ private static final String IN4 = " ";
+
public static void generate(DexData dexData, String format) {
if (format.equals("brief")) {
printBrief(dexData);
@@ -35,36 +41,56 @@ public class Output {
* Prints the data in a simple human-readable format.
*/
static void printBrief(DexData dexData) {
- FieldRef[] externFieldRefs = dexData.getExternalFieldReferences();
- MethodRef[] externMethodRefs = dexData.getExternalMethodReferences();
+ ClassRef[] externClassRefs = dexData.getExternalReferences();
- printFieldRefs(externFieldRefs);
- printMethodRefs(externMethodRefs);
+ printClassRefs(externClassRefs);
+ printFieldRefs(externClassRefs);
+ printMethodRefs(externClassRefs);
+ }
+
+ /**
+ * Prints the list of classes in a simple human-readable format.
+ */
+ static void printClassRefs(ClassRef[] classes) {
+ System.out.println("Classes:");
+ for (int i = 0; i < classes.length; i++) {
+ ClassRef ref = classes[i];
+
+ System.out.println(descriptorToDot(ref.getName()));
+ }
}
/**
* Prints the list of fields in a simple human-readable format.
*/
- static void printFieldRefs(FieldRef[] fields) {
+ static void printFieldRefs(ClassRef[] classes) {
System.out.println("Fields:");
- for (int i = 0; i < fields.length; i++) {
- FieldRef ref = fields[i];
+ for (int i = 0; i < classes.length; i++) {
+ FieldRef[] fields = classes[i].getFieldArray();
+
+ for (int j = 0; j < fields.length; j++) {
+ FieldRef ref = fields[j];
- System.out.println(descriptorToDot(ref.getDeclClassName()) + "." +
- ref.getName() + " : " + ref.getTypeName());
+ System.out.println(descriptorToDot(ref.getDeclClassName()) +
+ "." + ref.getName() + " : " + ref.getTypeName());
+ }
}
}
/**
* Prints the list of methods in a simple human-readable format.
*/
- static void printMethodRefs(MethodRef[] methods) {
+ static void printMethodRefs(ClassRef[] classes) {
System.out.println("Methods:");
- for (int i = 0; i < methods.length; i++) {
- MethodRef ref = methods[i];
+ for (int i = 0; i < classes.length; i++) {
+ MethodRef[] methods = classes[i].getMethodArray();
- System.out.println(descriptorToDot(ref.getDeclClassName()) +
- "." + ref.getName() + " : " + ref.getDescriptor());
+ for (int j = 0; j < methods.length; j++) {
+ MethodRef ref = methods[j];
+
+ System.out.println(descriptorToDot(ref.getDeclClassName()) +
+ "." + ref.getName() + " : " + ref.getDescriptor());
+ }
}
}
@@ -75,79 +101,90 @@ public class Output {
* We shouldn't need to XML-escape the field/method info.
*/
static void printXml(DexData dexData) {
- final String IN0 = "";
- final String IN1 = " ";
- final String IN2 = " ";
- final String IN3 = " ";
- FieldRef[] externFieldRefs = dexData.getExternalFieldReferences();
- MethodRef[] externMethodRefs = dexData.getExternalMethodReferences();
- String prevClass = null;
+ ClassRef[] externClassRefs = dexData.getExternalReferences();
System.out.println(IN0 + "<external>");
- /* print fields */
- for (int i = 0; i < externFieldRefs.length; i++) {
- FieldRef fref = externFieldRefs[i];
- String declClassName = fref.getDeclClassName();
-
- if (prevClass != null && !prevClass.equals(declClassName)) {
- System.out.println(IN1 + "</class>");
- }
- if (!declClassName.equals(prevClass)) {
- String className = classNameOnly(declClassName);
- String packageName = packageNameOnly(declClassName);
- System.out.println(IN1 + "<class package=\"" + packageName +
- "\" name=\"" + className + "\">");
- prevClass = declClassName;
+ /*
+ * Iterate through externClassRefs. For each class, dump all of
+ * the matching fields and methods.
+ */
+ String prevPackage = null;
+ for (int i = 0; i < externClassRefs.length; i++) {
+ ClassRef cref = externClassRefs[i];
+ String declClassName = cref.getName();
+ String className = classNameOnly(declClassName);
+ String packageName = packageNameOnly(declClassName);
+
+ /*
+ * If we're in a different package, emit the appropriate tags.
+ */
+ if (!packageName.equals(prevPackage)) {
+ if (prevPackage != null) {
+ System.out.println(IN1 + "</package>");
+ }
+
+ System.out.println(IN1 +
+ "<package name=\"" + packageName + "\">");
+
+ prevPackage = packageName;
}
- System.out.println(IN2 + "<field name=\"" + fref.getName() +
+ System.out.println(IN2 + "<class name=\"" + className + "\">");
+ printXmlFields(cref);
+ printXmlMethods(cref);
+ System.out.println(IN2 + "</class>");
+ }
+
+ if (prevPackage != null)
+ System.out.println(IN1 + "</package>");
+ System.out.println(IN0 + "</external>");
+ }
+
+ /**
+ * Prints the externally-visible fields in XML format.
+ */
+ private static void printXmlFields(ClassRef cref) {
+ FieldRef[] fields = cref.getFieldArray();
+ for (int i = 0; i < fields.length; i++) {
+ FieldRef fref = fields[i];
+
+ System.out.println(IN3 + "<field name=\"" + fref.getName() +
"\" type=\"" + descriptorToDot(fref.getTypeName()) + "\"/>");
}
+ }
- /* print methods */
- for (int i = 0; i < externMethodRefs.length; i++) {
- MethodRef mref = externMethodRefs[i];
+ /**
+ * Prints the externally-visible methods in XML format.
+ */
+ private static void printXmlMethods(ClassRef cref) {
+ MethodRef[] methods = cref.getMethodArray();
+ for (int i = 0; i < methods.length; i++) {
+ MethodRef mref = methods[i];
String declClassName = mref.getDeclClassName();
boolean constructor;
- if (prevClass != null && !prevClass.equals(declClassName)) {
- System.out.println(IN1 + "</class>");
- }
- if (!declClassName.equals(prevClass)) {
- String className = classNameOnly(declClassName);
- String packageName = packageNameOnly(declClassName);
- System.out.println(IN1 + "<class package=\"" + packageName +
- "\" name=\"" + className + "\">");
- prevClass = declClassName;
- }
-
constructor = mref.getName().equals("<init>");
if (constructor) {
- /* use class name instead of method name */
- System.out.println(IN2 + "<constructor name=\"" +
- classNameOnly(declClassName) + "\" return=\"" +
- descriptorToDot(mref.getReturnTypeName()) + "\">");
+ // use class name instead of method name
+ System.out.println(IN3 + "<constructor name=\"" +
+ classNameOnly(declClassName) + "\">");
} else {
- System.out.println(IN2 + "<method name=\"" + mref.getName() +
+ System.out.println(IN3 + "<method name=\"" + mref.getName() +
"\" return=\"" + descriptorToDot(mref.getReturnTypeName()) +
"\">");
}
String[] args = mref.getArgumentTypeNames();
for (int j = 0; j < args.length; j++) {
- System.out.println(IN3 + "<parameter type=\"" +
+ System.out.println(IN4 + "<parameter type=\"" +
descriptorToDot(args[j]) + "\"/>");
}
if (constructor) {
- System.out.println(IN2 + "</constructor>");
+ System.out.println(IN3 + "</constructor>");
} else {
- System.out.println(IN2 + "</method>");
+ System.out.println(IN3 + "</method>");
}
}
-
- if (prevClass != null)
- System.out.println(IN1 + "</class>");
- System.out.println(IN0 + "</external>");
}