auto import from //branches/cupcake_rel/...@138607
diff --git a/tools/dex-tools/src/dex/reader/DexAnnotationAttributeImpl.java b/tools/dex-tools/src/dex/reader/DexAnnotationAttributeImpl.java
new file mode 100644
index 0000000..deec93c
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexAnnotationAttributeImpl.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import dex.reader.DexFileReader.FieldIdItem;
+import dex.structure.DexAnnotation;
+import dex.structure.DexAnnotationAttribute;
+import dex.structure.DexEncodedValue;
+
+/* package */final class DexAnnotationAttributeImpl implements
+        DexAnnotationAttribute {
+    int nameIdx; // uleb128
+    DexEncodedValue value;// encoded_value
+    private String[] stringPool;
+    private DexBuffer buffer;
+    private final int[] typeIds;
+    private final FieldIdItem[] fieldIdItems;
+    private final DexAnnotation annotation;
+
+    public DexAnnotationAttributeImpl(DexBuffer buffer,
+            DexAnnotation annotation, int[] typeIds, String[] stringPool,
+            FieldIdItem[] fieldIdItems) {
+        this.buffer = buffer;
+        this.annotation = annotation;
+        this.typeIds = typeIds;
+        this.stringPool = stringPool;
+        this.fieldIdItems = fieldIdItems;
+        parseValue();
+    }
+
+    private void parseValue() {
+        nameIdx = buffer.readUleb128();
+        value = new DexEncodedValueImpl(buffer, annotation, typeIds,
+                stringPool, fieldIdItems);
+    }
+
+    public String getName() {
+        return stringPool[nameIdx];
+    }
+
+    public DexEncodedValue getEncodedValue() {
+        return value;
+    }
+
+    @Override
+    public String toString() {
+        return getName() + " " + getEncodedValue();
+    }
+
+    public DexAnnotation getAnnotation() {
+        return annotation;
+    }
+
+}
diff --git a/tools/dex-tools/src/dex/reader/DexAnnotationImpl.java b/tools/dex-tools/src/dex/reader/DexAnnotationImpl.java
new file mode 100644
index 0000000..49a93ae
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexAnnotationImpl.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import dex.reader.DexFileReader.FieldIdItem;
+import dex.structure.DexAnnotation;
+import dex.structure.DexAnnotationAttribute;
+
+import java.util.List;
+
+// FIXME provide special type for Signature annotation
+/* package */final class DexAnnotationImpl implements DexAnnotation {
+
+    private int offset;
+    private DexBuffer buffer;
+    private int[] typeIds;
+    private String[] stringPool;
+    private Visibility visibility;
+    private DexEncodedAnnotationImpl encodedAnnotation;
+
+    private TypeFormatter formatter = new TypeFormatter();
+    private final FieldIdItem[] fieldIdItems;
+
+    public DexAnnotationImpl(DexBuffer buffer, int offset, int[] typeIds,
+            String[] stringPool, FieldIdItem[] fieldIdItems) {
+        this.buffer = buffer;
+        this.offset = offset;
+        this.typeIds = typeIds;
+        this.stringPool = stringPool;
+        this.fieldIdItems = fieldIdItems;
+        parseAnnotations();
+    }
+
+    private void parseAnnotations() {
+        buffer.setPosition(offset);
+        visibility = Visibility.get(buffer.readUByte());
+        encodedAnnotation = new DexEncodedAnnotationImpl(buffer, this, typeIds,
+                stringPool, fieldIdItems);
+    }
+
+    public List<DexAnnotationAttribute> getAttributes() {
+        return encodedAnnotation.getValue();
+    }
+
+    public String getTypeName() {
+        return encodedAnnotation.getTypeName();
+    }
+
+    public Visibility getVisibility() {
+        return visibility;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("@");
+        builder.append(formatter.format(encodedAnnotation.getTypeName()));
+        if (!getAttributes().isEmpty()) {
+            builder.append(" (");
+            for (DexAnnotationAttribute value : getAttributes()) {
+                builder.append(value.toString());
+                builder.append(" ");
+            }
+            builder.append(")");
+        }
+        return builder.toString();
+    }
+
+}
diff --git a/tools/dex-tools/src/dex/reader/DexBuffer.java b/tools/dex-tools/src/dex/reader/DexBuffer.java
new file mode 100644
index 0000000..6292e28
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexBuffer.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public final class DexBuffer {
+
+    private ByteBuffer b;
+
+    public DexBuffer(String fileName) throws IOException {
+
+        // FIXME channel? allocate fix size?
+        FileInputStream fis = null;
+        try {
+            fis = new FileInputStream(fileName);
+
+            BufferedInputStream bis = new BufferedInputStream(fis);
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            byte[] buf = new byte[1024];
+            int len;
+            while ((len = bis.read(buf)) > 0) {
+                bos.write(buf, 0, len);
+            }
+            byte[] bytes = bos.toByteArray();
+            initialize(ByteBuffer.wrap(bytes));
+        } finally {
+            if (fis != null) {
+                fis.close();
+            }
+        }
+    }
+
+    public DexBuffer(byte[] bytes) {
+        initialize(ByteBuffer.wrap(bytes));
+    }
+
+    private DexBuffer(ByteBuffer slice) {
+        initialize(slice);
+    }
+
+    private void initialize(ByteBuffer buffer) {
+        b = buffer.asReadOnlyBuffer();
+        b.clear();
+        b.order(ByteOrder.LITTLE_ENDIAN);
+    }
+
+    public void setPosition(int offset) {
+        b.position(offset);
+    }
+
+    public void readBytes(byte[] dst) {
+        b.get(dst, 0, dst.length);
+    }
+
+    /**
+     * FIXME make endian dependent
+     */
+    public int readUleb128() {
+        int endValue = 0;
+        int value = 0;
+        int nr = 0;
+        do {
+            value = (b.get() & 0xFF);
+            endValue |= ((value & 0x7F) << 7 * nr);// cut away left most bit
+            nr++;
+        } while ((value & 0x80) != 0); // highest bit set?
+        return endValue;
+    }
+
+    /**
+     * pre 0 < nBytes <=4
+     */
+    public int readInt(int nBytes) {
+        int endValue = 0;
+        int tmp = 0;
+        for (int i = 0; i < nBytes; i++) {
+            tmp = b.get() & 0xFF;
+            endValue |= (tmp << i * 8);
+        }
+        return endValue;
+    }
+
+    /**
+     * pre 0 < nBytes <=1 FIXME: Sign extension
+     */
+    public short readShort(int nBytes) {
+        short endValue = 0;
+        int tmp = 0;
+        for (int i = 0; i < nBytes; i++) {
+            tmp = b.get() & 0xFF;
+            endValue |= (tmp << i * 8);
+        }
+        return endValue;
+    }
+
+    /**
+     * pre 0 < nBytes <=1
+     */
+    public char readChar(int nBytes) {
+        char endValue = 0;
+        int tmp = 0;
+        for (int i = 0; i < nBytes; i++) {
+            tmp = b.get() & 0xFF;
+            endValue |= (tmp << i * 8);
+        }
+        return endValue;
+    }
+
+    /**
+     * pre 0 < nBytes <=7 FIXME: Sign extension
+     */
+    public long readLong(int nBytes) {
+        long endValue = 0;
+        int tmp = 0;
+        for (int i = 0; i < nBytes; i++) {
+            tmp = b.get() & 0xFF;
+            endValue |= (tmp << i * 8);
+        }
+        return endValue;
+    }
+
+    /**
+     * pre 0 < nBytes <=4
+     */
+    public float readFloat(int nBytes) {
+        int bits = readInt(nBytes);
+        int bytesToMove = (4 - nBytes) * 8;
+        bits <<= bytesToMove;
+        return Float.intBitsToFloat(bits);
+    }
+
+    // returns int form current position
+    public int readUInt() {
+        int value = b.getInt();
+        // assert value >= 0;
+        return value;
+    }
+
+    public int readUShort() {
+        return b.getShort() & 0xFFFF;
+    }
+
+    // returns byte form current position
+    public byte readUByte() {
+        return b.get();
+    }
+
+    public DexBuffer createCopy() {
+        return new DexBuffer(b.duplicate());
+    }
+
+    public double readDouble(int nBytes) {
+        long bits = readLong(nBytes);
+        int bytesToMove = (8 - nBytes) * 8;
+        bits <<= bytesToMove;
+        return Double.longBitsToDouble(bits);
+    }
+
+    public void skip(int nBytes) {
+        b.position(b.position() + nBytes);
+    }
+}
diff --git a/tools/dex-tools/src/dex/reader/DexClassImpl.java b/tools/dex-tools/src/dex/reader/DexClassImpl.java
new file mode 100644
index 0000000..f15e809
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexClassImpl.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import dex.reader.DexFileReader.ClassDefItem;
+import dex.reader.DexFileReader.FieldIdItem;
+import dex.reader.DexFileReader.MethodsIdItem;
+import dex.reader.DexFileReader.ProtIdItem;
+import dex.structure.DexAnnotation;
+import dex.structure.DexClass;
+import dex.structure.DexField;
+import dex.structure.DexMethod;
+
+/* package */final class DexClassImpl implements DexClass {
+    // constant
+    private final int NO_INDEX = -1;
+    // dex bytes
+    private final DexBuffer buffer;
+    // allready parsed
+    private final ClassDefItem classDefItem;
+    private final int[] typeIds;
+    private final String[] stringPool;
+    private ProtIdItem[] protoIdItems;
+    private FieldIdItem[] fieldIdItems;
+    private MethodsIdItem[] methodIdItems;
+
+    //
+    private List<DexField> fields;
+    private List<DexMethod> methods;
+    private List<String> interfaces;
+    private ClassDataItem classDataItem;
+    private AnnotationsDirectoryItem annotationDir;
+    private Map<Integer, FieldAnnotation> idToFieldAnnotation =
+            new HashMap<Integer, FieldAnnotation>();
+    private Map<Integer, MethodAnnotation> idToMethodAnnotation =
+            new HashMap<Integer, MethodAnnotation>();
+    private Map<Integer, ParameterAnnotation> idToParameterAnnotation =
+            new HashMap<Integer, ParameterAnnotation>();
+
+    private Set<DexAnnotation> annotations;
+    private TypeFormatter formatter = new TypeFormatter();
+
+    private boolean hasClassData;
+
+
+    public DexClassImpl(DexBuffer buffer, ClassDefItem classDefItem,
+            String[] stringPool, int[] typeIds, ProtIdItem[] protoIdItems,
+            FieldIdItem[] fieldIdItems, MethodsIdItem[] methodIdItems) {
+        this.buffer = buffer;
+        this.classDefItem = classDefItem;
+        this.stringPool = stringPool;
+        this.typeIds = typeIds;
+        this.protoIdItems = protoIdItems;
+        this.fieldIdItems = fieldIdItems;
+        this.methodIdItems = methodIdItems;
+        hasClassData = classDefItem.class_data_off != 0;
+        parseClassData();
+        parseAnnotationDirectory();
+        parseClassAnnotations();
+    }
+
+    static class AnnotationsDirectoryItem {
+        int class_annotations_off; // uint
+        int fields_size; // uint
+        int methods_size; // uint
+        int annotated_params_size; // uint
+        FieldAnnotation[] fieldAnnotations;
+        MethodAnnotation[] methodAnnotations;
+        ParameterAnnotation[] parameterAnnotations;
+    }
+
+    static class AnnotationSetItem {
+        int size;// uint
+        int[] annotationOffItem;
+    }
+
+    static class FieldAnnotation {
+        int fieldIdx;// uint
+        int annotationsOff;// uint
+        AnnotationSetItem[] annotationSetItems;
+    }
+
+    static class MethodAnnotation {
+        int methodIdx;// uint
+        int annotationsOff;// uint
+        AnnotationSetItem[] annotationSetItems;
+    }
+
+    static class ParameterAnnotation {
+        int methodIdx;// uint
+        int annotationsOff;// uint
+        // AnnotationSetRefListItem[] annotationSetRefListItems;
+    }
+
+    private void parseAnnotationDirectory() {
+        if (classDefItem.annotations_off != 0) {
+            buffer.setPosition(classDefItem.annotations_off);
+            annotationDir = new AnnotationsDirectoryItem();
+            annotationDir.class_annotations_off = buffer.readUInt();
+            annotationDir.fields_size = buffer.readUInt();
+            annotationDir.methods_size = buffer.readUInt();
+            annotationDir.annotated_params_size = buffer.readUInt();
+
+            if (annotationDir.fields_size != 0) {
+                annotationDir.fieldAnnotations =
+                        new FieldAnnotation[annotationDir.fields_size];
+                for (int i = 0; i < annotationDir.fields_size; i++) {
+                    annotationDir.fieldAnnotations[i] = new FieldAnnotation();
+                    annotationDir.fieldAnnotations[i].fieldIdx = buffer
+                            .readUInt();
+                    annotationDir.fieldAnnotations[i].annotationsOff = buffer
+                            .readUInt();
+                    idToFieldAnnotation.put(
+                            annotationDir.fieldAnnotations[i].fieldIdx,
+                            annotationDir.fieldAnnotations[i]);
+                }
+            }
+            if (annotationDir.methods_size != 0) {
+                annotationDir.methodAnnotations =
+                        new MethodAnnotation[annotationDir.methods_size];
+                for (int i = 0; i < annotationDir.methods_size; i++) {
+                    annotationDir.methodAnnotations[i] = new MethodAnnotation();
+                    annotationDir.methodAnnotations[i].methodIdx = buffer
+                            .readUInt();
+                    annotationDir.methodAnnotations[i].annotationsOff = buffer
+                            .readUInt();
+                    idToMethodAnnotation.put(
+                            annotationDir.methodAnnotations[i].methodIdx,
+                            annotationDir.methodAnnotations[i]);
+                }
+            }
+            if (annotationDir.annotated_params_size != 0) {
+                annotationDir.parameterAnnotations =
+                        new ParameterAnnotation[annotationDir
+                                .annotated_params_size];
+                for (int i = 0; i < annotationDir.annotated_params_size; i++) {
+                    annotationDir.parameterAnnotations[i] =
+                            new ParameterAnnotation();
+                    annotationDir.parameterAnnotations[i].methodIdx = buffer
+                            .readUInt();
+                    annotationDir.parameterAnnotations[i].annotationsOff =
+                            buffer.readUInt();
+                    idToParameterAnnotation.put(
+                            annotationDir.parameterAnnotations[i].methodIdx,
+                            annotationDir.parameterAnnotations[i]);
+                }
+            }
+        }
+    }
+
+    static class ClassDataItem {
+        int static_fields_size;// uleb128
+        int instance_fields_size;// uleb128
+        int direct_methods_size;// uleb128
+        int virtual_methods_size;// uleb128
+        EncodedField[] staticFields;
+        EncodedField[] instanceFields;
+        EncodedMethod[] directMethods;
+        EncodedMethod[] virtualMethods;
+    }
+
+    static class EncodedField {
+        int field_idx_diff; // uleb128
+        int access_flags; // uleb128
+    }
+
+    static class EncodedMethod {
+        int method_idx_diff;// uleb128
+        int access_flags;// uleb128
+        int code_off; // uleb128
+    }
+
+    private void parseClassData() {
+        if (hasClassData) {
+            buffer.setPosition(classDefItem.class_data_off);
+            classDataItem = new ClassDataItem();
+            classDataItem.static_fields_size = buffer.readUleb128();
+            classDataItem.instance_fields_size = buffer.readUleb128();
+            classDataItem.direct_methods_size = buffer.readUleb128();
+            classDataItem.virtual_methods_size = buffer.readUleb128();
+            classDataItem.staticFields = parseFields(
+                    classDataItem.static_fields_size);
+            classDataItem.instanceFields = parseFields(
+                    classDataItem.instance_fields_size);
+            classDataItem.directMethods = parseMethods(
+                    classDataItem.direct_methods_size);
+            classDataItem.virtualMethods = parseMethods(
+                    classDataItem.virtual_methods_size);
+        }
+    }
+
+    private EncodedField[] parseFields(int size) {
+        EncodedField[] fields = new EncodedField[size];
+        for (int i = 0; i < fields.length; i++) {
+            fields[i] = new EncodedField();
+            fields[i].field_idx_diff = buffer.readUleb128();
+            fields[i].access_flags = buffer.readUleb128();
+        }
+        return fields;
+    }
+
+    private EncodedMethod[] parseMethods(int size) {
+        EncodedMethod[] methods = new EncodedMethod[size];
+        for (int i = 0; i < methods.length; i++) {
+            methods[i] = new EncodedMethod();
+            methods[i].method_idx_diff = buffer.readUleb128();
+            methods[i].access_flags = buffer.readUleb128();
+            methods[i].code_off = buffer.readUleb128();
+        }
+        return methods;
+    }
+
+    private void parseClassAnnotations() {
+        annotations = new HashSet<DexAnnotation>();
+        if (annotationDir != null && annotationDir.class_annotations_off != 0) {
+            buffer.setPosition(annotationDir.class_annotations_off);
+            final int size = buffer.readUInt();
+            for (int i = 0; i < size; i++) {
+                annotations.add(new DexAnnotationImpl(buffer.createCopy(),
+                        buffer.readUInt(), typeIds, stringPool, fieldIdItems));
+            }
+        }
+    }
+
+    public synchronized List<DexField> getFields() {
+        if (fields == null) {
+            fields = new ArrayList<DexField>();
+            if (hasClassData) {
+                fields.addAll(getDexFields(classDataItem.staticFields));
+                fields.addAll(getDexFields(classDataItem.instanceFields));
+            }
+        }
+        return fields;
+    }
+
+    private List<DexField> getDexFields(EncodedField[] fields) {
+        List<DexField> dexFields = new ArrayList<DexField>(fields.length);
+        if (fields.length != 0) {
+            int fieldIdIdx = 0;
+            for (int i = 0; i < fields.length; i++) {
+                int accessFlags = fields[i].access_flags;
+                fieldIdIdx = (i == 0) ? fields[i].field_idx_diff : fieldIdIdx
+                        + fields[i].field_idx_diff;
+                dexFields.add(new DexFieldImpl(buffer.createCopy(), this,
+                        fieldIdItems[fieldIdIdx], accessFlags,
+                        idToFieldAnnotation.get(fieldIdIdx), stringPool,
+                        typeIds, fieldIdItems));
+            }
+        }
+        return dexFields;
+    }
+
+    public synchronized List<DexMethod> getMethods() {
+        if (methods == null) {
+            methods = new ArrayList<DexMethod>();
+            if (hasClassData) {
+                methods.addAll(getDexMethods(classDataItem.directMethods));
+                methods.addAll(getDexMethods(classDataItem.virtualMethods));
+            }
+        }
+        return methods;
+    }
+
+    private List<DexMethod> getDexMethods(EncodedMethod[] methods) {
+        List<DexMethod> dexMethods = new ArrayList<DexMethod>(methods.length);
+        if (methods.length != 0) {
+            int methodIdIdx = 0;
+            EncodedMethod method = null;
+            for (int i = 0; i < methods.length; i++) {
+                method = methods[i];
+                methodIdIdx = (i == 0) ? method.method_idx_diff : methodIdIdx
+                        + method.method_idx_diff;
+                dexMethods.add(new DexMethodImpl(buffer, this,
+                        methodIdItems[methodIdIdx],
+                        protoIdItems[methodIdItems[methodIdIdx].proto_idx],
+                        method.access_flags, idToMethodAnnotation
+                                .get(methodIdIdx), idToParameterAnnotation
+                                .get(methodIdIdx), stringPool, typeIds,
+                        fieldIdItems));
+            }
+        }
+        return dexMethods;
+    }
+
+
+
+    public synchronized List<String> getInterfaces() {
+        if (interfaces == null) {
+            interfaces = new LinkedList<String>();
+            if (classDefItem.interfaces_off != 0) {
+                buffer.setPosition(classDefItem.interfaces_off);
+                int size = buffer.readUInt();
+                for (int i = 0; i < size; i++) {
+                    interfaces.add(stringPool[typeIds[buffer.readUShort()]]);
+                }
+            }
+        }
+        return interfaces;
+    }
+
+    // returns null if no super class is present
+    public String getSuperClass() {
+        return classDefItem.superclass_idx == NO_INDEX ? null
+                : stringPool[typeIds[classDefItem.superclass_idx]];
+    }
+
+    public Set<DexAnnotation> getAnnotations() {
+        return annotations;
+    }
+
+    public String getName() {
+        return stringPool[typeIds[classDefItem.class_idx]];
+    }
+
+    public int getModifiers() {
+        return classDefItem.access_flags;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append(formatter.formatAnnotations(getAnnotations()));
+        builder.append(Modifier.toString(getModifiers()));
+        builder.append(" class ");
+        builder.append(formatter.format(getName()));
+        if (getSuperClass() != null) {
+            builder.append(" extends ");
+            builder.append(formatter.format(getSuperClass()));
+        }
+        if (!getInterfaces().isEmpty()) {
+            builder.append(" implements ");
+            builder.append(formatter.format(getInterfaces()));
+        }
+        return builder.toString();
+    }
+
+}
diff --git a/tools/dex-tools/src/dex/reader/DexEncodedAnnotationImpl.java b/tools/dex-tools/src/dex/reader/DexEncodedAnnotationImpl.java
new file mode 100644
index 0000000..0114ce3
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexEncodedAnnotationImpl.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import dex.reader.DexFileReader.FieldIdItem;
+import dex.structure.DexAnnotation;
+import dex.structure.DexAnnotationAttribute;
+import dex.structure.DexEncodedAnnotation;
+import dex.structure.DexEncodedValueType;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/* package */final class DexEncodedAnnotationImpl implements
+        DexEncodedAnnotation {
+
+    private List<DexAnnotationAttribute> values;
+    private final DexBuffer buffer;
+    private final int[] typeIds;
+    private final String[] stringPool;
+    private int typeIdx;
+    private final FieldIdItem[] fieldIdItems;
+    private final DexAnnotation annotation;
+
+    public DexEncodedAnnotationImpl(DexBuffer buffer, DexAnnotation annotation,
+            int[] typeIds, String[] stringPool, FieldIdItem[] fieldIdItems) {
+        this.buffer = buffer;
+        this.annotation = annotation;
+        this.typeIds = typeIds;
+        this.stringPool = stringPool;
+        this.fieldIdItems = fieldIdItems;
+        parseEncodedAnnotation();
+    }
+
+    private void parseEncodedAnnotation() {
+        typeIdx = buffer.readUleb128();
+        int size = buffer.readUleb128();
+        values = new ArrayList<DexAnnotationAttribute>(size);
+        for (int j = 0; j < size; j++) {
+            values.add(new DexAnnotationAttributeImpl(buffer, annotation,
+                    typeIds, stringPool, fieldIdItems));
+        }
+    }
+
+    public DexEncodedValueType getType() {
+        return DexEncodedValueType.VALUE_ANNOTATION;
+    }
+
+    public List<DexAnnotationAttribute> getValue() {
+        return values;
+    }
+
+    public String getTypeName() {
+        return stringPool[typeIds[typeIdx]];
+    }
+
+    @Override
+    public String toString() {
+        return getTypeName() + ":" + getValue();
+    }
+}
diff --git a/tools/dex-tools/src/dex/reader/DexEncodedValueImpl.java b/tools/dex-tools/src/dex/reader/DexEncodedValueImpl.java
new file mode 100644
index 0000000..82ba184
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexEncodedValueImpl.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import static dex.structure.DexEncodedValueType.*;
+import dex.reader.DexFileReader.FieldIdItem;
+import dex.structure.DexAnnotation;
+import dex.structure.DexEncodedValue;
+import dex.structure.DexEncodedValueType;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/* package */final class DexEncodedValueImpl implements DexEncodedValue {
+
+    private final DexBuffer buffer;
+    private byte typeAndValueArg;
+    private DexEncodedValueType type;
+    private String[] stringPool;
+    private Object value;
+    private int[] typeIds;
+    private final FieldIdItem[] fieldIdItems;
+    private final DexAnnotation annotation;
+
+    /**
+     * 
+     * @param buffer
+     *            the buffer with the correct position
+     * @param annotation
+     * @param stringPool
+     * @param fieldIdItems
+     */
+    public DexEncodedValueImpl(DexBuffer buffer, DexAnnotation annotation,
+            int[] typeIds, String[] stringPool, FieldIdItem[] fieldIdItems) {
+        this.buffer = buffer;
+        this.annotation = annotation;
+        this.typeIds = typeIds;
+        this.stringPool = stringPool;
+        this.fieldIdItems = fieldIdItems;
+        parseValue();
+    }
+
+    private void parseValue() {
+        typeAndValueArg = buffer.readUByte();
+        type = DexEncodedValueType.get(typeAndValueArg);
+        int valueArg = DexEncodedValueType.valueArg(typeAndValueArg);
+        switch (type) {
+        case VALUE_BYTE:
+            value = getByteValue(valueArg);
+            break;
+        case VALUE_SHORT:
+            value = getShortValue(valueArg);
+            break;
+        case VALUE_CHAR:
+            value = getCharValue(valueArg);
+            break;
+        case VALUE_INT:
+            value = getIntValue(valueArg);
+            break;
+        case VALUE_LONG:
+            value = getLongValue(valueArg);
+            break;
+        case VALUE_FLOAT:
+            value = getFloatValue(valueArg);
+            break;
+        case VALUE_DOUBLE:
+            value = getDoubleValue(valueArg);
+            break;
+        case VALUE_STRING:
+            value = getStringValue(valueArg);
+            break;
+        case VALUE_TYPE:
+            value = getTypeValue(valueArg);
+            break;
+        case VALUE_FIELD:
+            value = getFieldValue(valueArg);
+            break;
+        case VALUE_METHOD:
+            value = getMethodValue(valueArg);
+            break;
+        case VALUE_ENUM:
+            value = getEnumValue(valueArg);
+            break;
+        case VALUE_ARRAY:
+            value = getArrayValue(valueArg);
+            break;
+        case VALUE_ANNOTATION:
+            value = getAnnotationValue(valueArg);
+            break;
+        case VALUE_NULL:
+            value = getNullValue(valueArg);
+            break;
+        case VALUE_BOOLEAN:
+            value = getBooleanValue(valueArg);
+            break;
+        default:
+            throw new IllegalArgumentException("DexEncodedValueType " + type
+                    + " not recognized");
+        }
+    }
+
+    /**
+     * VALUE_BOOLEAN 0x1f boolean (0...1) (none) one-bit value; 0 for false and
+     * 1 for true. The bit is represented in the value_arg.
+     */
+    private Boolean getBooleanValue(int valueArg) {
+        return valueArg == 1;
+    }
+
+    /** VALUE_NULL 0x1e (none; must be 0) (none) null reference value */
+    private Object getNullValue(int valueArg) {
+        return null; // must be like that!
+    }
+
+    /**
+     * VALUE_ANNOTATION 0x1d (none; must be 0) encoded_annotation a
+     * sub-annotation, in the format specified by "encoded_annotation Format"
+     * below. The size of the value is implicit in the encoding.
+     */
+    private Object getAnnotationValue(int valueArg) {
+        // use the buffer directly to get adjusted offset
+        return new DexEncodedAnnotationImpl(buffer, annotation, typeIds,
+                stringPool, fieldIdItems);
+    }
+
+    /**
+     * VALUE_ARRAY 0x1c (none; must be 0) encoded_array an array of values, in
+     * the format specified by "encoded_array Format" below. The size of the
+     * value is implicit in the encoding.
+     */
+    private List<DexEncodedValue> getArrayValue(int valueArg) {
+        int size = buffer.readUleb128();
+        List<DexEncodedValue> values = new ArrayList<DexEncodedValue>(size);
+        for (int i = 0; i < size; i++) {
+            values.add(new DexEncodedValueImpl(buffer, annotation, typeIds,
+                    stringPool, fieldIdItems));
+        }
+        return values;
+    }
+
+    /**
+     * VALUE_ENUM 0x1b size - 1 (0...3) ubyte[size] unsigned (zero-extended)
+     * four-byte integer value, interpreted as an index into the field_ids
+     * section and representing the value of an enumerated type constant
+     */
+    private Object getEnumValue(int valueArg) {
+        int fieldOffset = buffer.readInt(valueArg + 1);
+        FieldIdItem fieldIdItem = fieldIdItems[fieldOffset];
+        // FORMAT La/b/E;!CONSTANT
+        String constantName = stringPool[fieldIdItem.name_idx];
+        String typeName = stringPool[typeIds[fieldIdItem.type_idx]];
+        return typeName + "!" + constantName;
+    }
+
+    /**
+     * VALUE_METHOD 0x1a size - 1 (0...3) ubyte[size] unsigned (zero-extended)
+     * four-byte integer value, interpreted as an index into the method_ids
+     * section and representing a reflective method value
+     */
+    private Object getMethodValue(int valueArg) {
+        // FIXME lookup value
+        buffer.skip(valueArg + 1);
+        return null;
+    }
+
+    /**
+     * VALUE_FIELD 0x19 size - 1 (0...3) ubyte[size] unsigned (zero-extended)
+     * four-byte integer value, interpreted as an index into the field_ids
+     * section and representing a reflective field value
+     */
+    private Object getFieldValue(int valueArg) {
+        int fieldOffset = buffer.readInt(valueArg + 1);
+        FieldIdItem fieldIdItem = fieldIdItems[fieldOffset];
+        // FORMAT La/b/E;!CONSTANT
+        String fieldName = stringPool[fieldIdItem.name_idx];
+        String typeName = stringPool[typeIds[fieldIdItem.type_idx]];
+        return typeName + "!" + fieldName;
+    }
+
+    /**
+     * VALUE_TYPE 0x18 size - 1 (0...3) ubyte[size] unsigned (zero-extended)
+     * four-byte integer value, interpreted as an index into the type_ids
+     * section and representing a reflective type/class value
+     */
+    private Object getTypeValue(int valueArg) {
+        valueArg++; // size - 1 (0...3)
+        // FIXME SPEC!! states: unsigned (zero-extended) four-byte integer value
+        return stringPool[typeIds[buffer.readInt(valueArg)]];
+    }
+
+    /**
+     * VALUE_STRING 0x17 size - 1 (0...3) ubyte[size] unsigned (zero-extended)
+     * four-byte integer value, interpreted as an index into the string_ids
+     * section and representing a string value
+     */
+    private Object getStringValue(int valueArg) {
+        valueArg++;
+        return stringPool[buffer.readInt(valueArg)];
+    }
+
+    /**
+     * VALUE_DOUBLE 0x11 size - 1 (0...7) ubyte[size] eight-byte bit pattern,
+     * zero-extended to the right, and interpreted as an IEEE754 64-bit floating
+     * point value
+     */
+    private Object getDoubleValue(int valueArg) {
+        return buffer.readDouble(valueArg + 1);
+    }
+
+    /**
+     * VALUE_FLOAT 0x10 size - 1 (0...3) ubyte[size] four-byte bit pattern,
+     * zero-extended to the right, and interpreted as an IEEE754 32-bit floating
+     * point value
+     */
+    private Float getFloatValue(int valueArg) {
+        return buffer.readFloat(valueArg + 1);
+    }
+
+    /**
+     * VALUE_LONG 0x06 size - 1 (0...7) ubyte[size] signed eight-byte integer
+     * value, sign-extended
+     */
+    private Long getLongValue(int valueArg) {
+        return buffer.readLong(valueArg + 1);
+    }
+
+    /**
+     * VALUE_INT 0x04 size - 1 (0...3) ubyte[size] signed four-byte integer
+     * value, sign-extended
+     */
+    private Integer getIntValue(int valueArg) {
+        return buffer.readInt(valueArg + 1);
+    }
+
+    /**
+     * VALUE_CHAR 0x03 size - 1 (0...1) ubyte[size] unsigned two-byte integer
+     * value, zero-extended
+     */
+    private Character getCharValue(int valueArg) {
+        return buffer.readChar(valueArg + 1);
+    }
+
+    /**
+     * VALUE_SHORT 0x02 size - 1 (0...1) ubyte[size] signed two-byte integer
+     * value, sign-extended
+     */
+    private Short getShortValue(int valueArg) {
+        return buffer.readShort(valueArg + 1);
+    }
+
+    /**
+     * VALUE_BYTE 0x00 (none; must be 0) ubyte[1] signed one-byte integer value
+     */
+    private Byte getByteValue(int valueArg) {
+        assert valueArg == 0 : "Illegal valueArg for VALUE_BYTE: " + valueArg;
+        return null;
+    }
+
+    public DexEncodedValueType getType() {
+        return type;
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("=");
+        if (type == VALUE_ARRAY) {
+            if (getValue() instanceof List<?>) {
+                List<?> values = (List<?>) getValue();
+                for (Object object : values) {
+                    DexEncodedValue val = (DexEncodedValue) object;
+                    builder.append(val.getValue());
+                }
+            }
+        } else {
+            builder.append(getValue());
+        }
+        return builder.toString();
+    }
+}
diff --git a/tools/dex-tools/src/dex/reader/DexFieldImpl.java b/tools/dex-tools/src/dex/reader/DexFieldImpl.java
new file mode 100644
index 0000000..f4a8c72
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexFieldImpl.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import dex.reader.DexClassImpl.FieldAnnotation;
+import dex.reader.DexFileReader.FieldIdItem;
+import dex.structure.DexAnnotation;
+import dex.structure.DexClass;
+import dex.structure.DexField;
+
+import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.Set;
+
+/* package */final class DexFieldImpl implements DexField {
+
+    private DexBuffer buffer;
+    private String[] stringPool;
+    private FieldIdItem fieldIdItem;
+    private int[] typeIds;
+    private final int accessFlags;
+    private Set<DexAnnotation> annotations;
+    private FieldAnnotation fieldAnnotation;
+    private TypeFormatter formatter = new TypeFormatter();
+    private final DexClass declaringClass;
+    private final FieldIdItem[] fieldIdItems;
+
+    public DexFieldImpl(DexBuffer buffer, DexClass declaringClass,
+            FieldIdItem fieldIdItem, int accessFlags,
+            FieldAnnotation fieldAnnotation, String[] stringPool,
+            int[] typeIds, FieldIdItem[] fieldIdItems) {
+        this.buffer = buffer;
+        this.declaringClass = declaringClass;
+        this.fieldIdItem = fieldIdItem;
+        this.accessFlags = accessFlags;
+        this.fieldAnnotation = fieldAnnotation;
+        this.stringPool = stringPool;
+        this.typeIds = typeIds;
+        this.fieldIdItems = fieldIdItems;
+        parseAnnotations();
+    }
+
+    private void parseAnnotations() {
+        annotations = new HashSet<DexAnnotation>();
+        if (fieldAnnotation != null) {
+            buffer.setPosition(fieldAnnotation.annotationsOff);
+            final int size = buffer.readUInt();
+            for (int i = 0; i < size; i++) {
+                annotations.add(new DexAnnotationImpl(buffer.createCopy(),
+                        buffer.readUInt(), typeIds, stringPool, fieldIdItems));
+            }
+        }
+    }
+
+    public String getName() {
+        return stringPool[fieldIdItem.name_idx];
+    }
+
+    public String getType() {
+        return stringPool[typeIds[fieldIdItem.type_idx]];
+    }
+
+    public int getModifiers() {
+        return accessFlags;
+    }
+
+    public synchronized Set<DexAnnotation> getAnnotations() {
+        return annotations;
+    }
+
+    public DexClass getDeclaringClass() {
+        return declaringClass;
+    }
+
+    public boolean isEnumConstant() {
+        return (getModifiers() & 0x4000) > 0;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append(formatter.formatAnnotations(getAnnotations()));
+        builder.append(Modifier.toString(getModifiers()));
+        builder.append(" ");
+        builder.append(formatter.format(getType()));
+        builder.append(" ");
+        builder.append(getName());
+        return builder.toString();
+    }
+}
diff --git a/tools/dex-tools/src/dex/reader/DexFileImpl.java b/tools/dex-tools/src/dex/reader/DexFileImpl.java
new file mode 100644
index 0000000..da066f1
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexFileImpl.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import dex.reader.DexFileReader.ClassDefItem;
+import dex.reader.DexFileReader.FieldIdItem;
+import dex.reader.DexFileReader.MethodsIdItem;
+import dex.reader.DexFileReader.ProtIdItem;
+import dex.structure.DexClass;
+import dex.structure.DexFile;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/* package */final class DexFileImpl implements DexFile {
+
+    private final String[] stringPool;
+    private final int[] typeIds;
+    private ProtIdItem[] protoIdItems;
+    private FieldIdItem[] fieldIdItems;
+    private MethodsIdItem[] methodIdItems;
+    private ClassDefItem[] classDefItems;
+    private final DexBuffer buffer;
+
+    private List<DexClass> classes = null;
+
+    public DexFileImpl(DexBuffer buffer, String[] stringPool, int[] typeIds,
+            ProtIdItem[] protoIds, FieldIdItem[] fieldIdItems,
+            MethodsIdItem[] methodIdItems, ClassDefItem[] classDefItems) {
+        this.buffer = buffer;
+        this.stringPool = stringPool;
+        this.typeIds = typeIds;
+        this.protoIdItems = protoIds;
+        this.fieldIdItems = fieldIdItems;
+        this.methodIdItems = methodIdItems;
+        this.classDefItems = classDefItems;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see dex.reader.DexFile#getDefinedClasses()
+     */
+    public synchronized List<DexClass> getDefinedClasses() {
+        if (classes == null) {
+            classes = new ArrayList<DexClass>(classDefItems.length);
+            for (int i = 0; i < classDefItems.length; i++) {
+                classes.add(new DexClassImpl(buffer.createCopy(),
+                        classDefItems[i], stringPool, typeIds, protoIdItems,
+                        fieldIdItems, methodIdItems));
+            }
+        }
+        return classes;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder b = new StringBuilder();
+        b.append("StringPool:\n").append(Arrays.toString(stringPool));
+        b.append("\nTypes:\n");
+        for (int i = 0; i < typeIds.length; i++) {
+            b.append(stringPool[typeIds[i]] + "\n");
+        }
+        b.append("\nProtos:\n").append(Arrays.toString(protoIdItems));
+        b.append("\nFields:\n").append(Arrays.toString(fieldIdItems));
+        b.append("\nMethods:\n").append(Arrays.toString(methodIdItems));
+        b.append("\nClasses:\n").append(Arrays.toString(classDefItems));
+        return b.toString();
+    }
+
+    public String getName() {
+        return "DexFile";
+    }
+}
diff --git a/tools/dex-tools/src/dex/reader/DexFileReader.java b/tools/dex-tools/src/dex/reader/DexFileReader.java
new file mode 100644
index 0000000..1fd17f6
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexFileReader.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import dex.structure.DexFile;
+
+import java.util.Arrays;
+
+public final class DexFileReader {
+
+    // DEX constants
+    private int ENDIAN_CONSTANT = 0x12345678;
+    @SuppressWarnings("unused")
+    private int REVERSE_ENDIAN_CONSTANT = 0x78563412;
+    private final byte[] REF_MAGIC = new byte[] {
+            0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x35, 0x00};
+
+    // Header values
+    private DexBuffer b;
+    private byte[] magic = new byte[8];
+    @SuppressWarnings("unused")
+    private int checksum = 0;
+    private byte[] signature = new byte[20];
+    @SuppressWarnings("unused")
+    private int fileSize = 0;
+    @SuppressWarnings("unused")
+    private int headerSize = 0;
+    private int endianTag = 0;
+
+    // Indices of offset and size items
+    private static final int LINK = 0;
+    private static final int MAP = 1; // no size!
+    private static final int STRING_IDS = 2;
+    private static final int TYPE_IDS = 3;
+    private static final int PROTO_IDS = 4;
+    private static final int FIELD_IDS = 5;
+    private static final int METHOD_IDS = 6;
+    private static final int CLASS_DEFS = 7;
+    private static final int DATA = 8;
+
+    private int[] size = new int[9];
+    private int[] off = new int[9];
+
+
+    //
+    private String[] stringPool;
+    private int[] typeIds; // values are index of stringPool
+    private ProtIdItem[] protoIdItems;
+    private FieldIdItem[] fieldIdItems;
+    private MethodsIdItem[] methodIdItems;
+    private ClassDefItem[] classDefItems;
+
+    // starting buffer at zero
+    public DexFile read(DexBuffer buffer) {
+        this.b = buffer;
+        readMagic();
+        readChecksum();
+        readSignature();
+        readFileSize();
+        readHeaderSize();
+        readEndianTag();
+        readSize(LINK);
+        readOffset(LINK);
+        readOffset(MAP);
+        readSize(STRING_IDS);
+        readOffset(STRING_IDS);
+        readSize(TYPE_IDS);
+        readOffset(TYPE_IDS);
+        readSize(PROTO_IDS);
+        readOffset(PROTO_IDS);
+        readSize(FIELD_IDS);
+        readOffset(FIELD_IDS);
+        readSize(METHOD_IDS);
+        readOffset(METHOD_IDS);
+        readSize(CLASS_DEFS);
+        readOffset(CLASS_DEFS);
+        readSize(DATA);
+        readOffset(DATA);
+        // from now on, index is not automatically on the desired position
+        readStrings();
+        readTypeIds();
+        readProtos();
+        readFields();
+        readMethods();
+        readClasses();
+
+        return new DexFileImpl(b.createCopy(), stringPool, typeIds,
+                protoIdItems, fieldIdItems, methodIdItems, classDefItems);
+    }
+
+    // MAGIC (8, U_BYTE)
+    // "dex\n035\0"
+    private void readMagic() {
+        b.readBytes(magic);
+        assert Arrays.equals(magic, REF_MAGIC) : "Not a DEX file";
+    }
+
+    // CHECKSUM (1, U_INT)
+    private void readChecksum() {
+        checksum = b.readUInt();
+    }
+
+    // SIGNATURE (20, U_BYTE)
+    private void readSignature() {
+        b.readBytes(signature);
+    }
+
+    // FILE_SIZE (1, U_INT)
+    private void readFileSize() {
+        fileSize = b.readUInt();
+    }
+
+    // HEADER_SIZE (1, U_INT), //0x70
+    private void readHeaderSize() {
+        headerSize = b.readUInt();
+    }
+
+    // ENDIAN_TAG (1, U_INT), //ENDIAN_CONSTANT
+    private void readEndianTag() {
+        endianTag = b.readUInt();
+        // FIXME Support for big endian encoded dex files
+        assert endianTag == ENDIAN_CONSTANT : "Byteorder NOT in little endian";
+    }
+
+    private void readSize(int attribute) {
+        size[attribute] = b.readUInt();
+    }
+
+    private void readOffset(int attribute) {
+        off[attribute] = b.readUInt();
+    }
+
+    // reads the string pool
+    private void readStrings() {
+        int nStrings = size[STRING_IDS];
+        b.setPosition(off[STRING_IDS]); // the first string offset is here
+        int[] stringDataOffsets = new int[nStrings];
+
+        for (int i = 0; i < stringDataOffsets.length; i++) {
+            stringDataOffsets[i] = b.readUInt();
+        }
+
+        stringPool = new String[nStrings];
+        for (int i = 0; i < stringDataOffsets.length; i++) {
+            b.setPosition(stringDataOffsets[i]); // set buffer to offset
+            // Position
+            int lenght = b.readUleb128(); // read uleb128
+            byte[] values = new byte[lenght];
+            b.readBytes(values);
+            stringPool[i] = new String(values);
+        }
+    }
+
+    private void readTypeIds() {
+        int nTypes = size[TYPE_IDS];
+        b.setPosition(off[TYPE_IDS]); // the first element is here
+        typeIds = new int[nTypes];
+
+        for (int i = 0; i < typeIds.length; i++) {
+            typeIds[i] = b.readUInt();
+        }
+    }
+
+    static class ProtIdItem {
+        public int shorty_idx;
+        public int return_type_idx;
+        public int parameter_off;
+    }
+
+    private void readProtos() {
+        int nProtos = size[PROTO_IDS];
+        b.setPosition(off[PROTO_IDS]);
+        protoIdItems = new ProtIdItem[nProtos];
+
+        ProtIdItem item = null;
+        for (int i = 0; i < protoIdItems.length; i++) {
+            item = new ProtIdItem();
+            item.shorty_idx = b.readUInt();
+            item.return_type_idx = b.readUInt();
+            item.parameter_off = b.readUInt();
+            protoIdItems[i] = item;
+        }
+    }
+
+    static class FieldIdItem {
+        public int class_idx; // defining class : index of type_ids
+        public int type_idx; // type of field : index of type_ids
+        public int name_idx; // name of field : index into string id (or
+        // directly stringpool)
+    }
+
+    private void readFields() {
+        int nFields = size[FIELD_IDS];
+        b.setPosition(off[FIELD_IDS]);
+        fieldIdItems = new FieldIdItem[nFields];
+
+        FieldIdItem item = null;
+        for (int i = 0; i < fieldIdItems.length; i++) {
+            item = new FieldIdItem();
+            item.class_idx = b.readUShort();
+            item.type_idx = b.readUShort();
+            item.name_idx = b.readUInt();
+            fieldIdItems[i] = item;
+        }
+    }
+
+    static class MethodsIdItem {
+        public int class_idx; // defining class : index of typeIds
+        public int proto_idx; // proto of method : index of protoIdItems
+        public int name_idx; // name of method : index into string id (or
+        // directly stringpool)
+    }
+
+    private void readMethods() {
+        int nMethods = size[METHOD_IDS];
+        b.setPosition(off[METHOD_IDS]);
+        methodIdItems = new MethodsIdItem[nMethods];
+
+        MethodsIdItem item = null;
+        for (int i = 0; i < methodIdItems.length; i++) {
+            item = new MethodsIdItem();
+            item.class_idx = b.readUShort();
+            item.proto_idx = b.readUShort();
+            item.name_idx = b.readUInt();
+            methodIdItems[i] = item;
+        }
+    }
+
+    public static class ClassDefItem {
+        public int class_idx;
+        public int access_flags;
+        public int superclass_idx;
+        public int interfaces_off;
+        public int source_file_idx;
+        public int annotations_off;
+        public int class_data_off;
+        public int static_values_off;
+    }
+
+    private void readClasses() {
+        int nClassDefs = size[CLASS_DEFS];
+        b.setPosition(off[CLASS_DEFS]);
+        classDefItems = new ClassDefItem[nClassDefs];
+
+        ClassDefItem item = null;
+        for (int i = 0; i < classDefItems.length; i++) {
+            item = new ClassDefItem();
+            item.class_idx = b.readUInt();
+            item.access_flags = b.readUInt();
+            item.superclass_idx = b.readUInt();
+            item.interfaces_off = b.readUInt();
+            item.source_file_idx = b.readUInt();
+            item.annotations_off = b.readUInt();
+            item.class_data_off = b.readUInt();
+            item.static_values_off = b.readUInt();
+            classDefItems[i] = item;
+        }
+    }
+}
diff --git a/tools/dex-tools/src/dex/reader/DexMethodImpl.java b/tools/dex-tools/src/dex/reader/DexMethodImpl.java
new file mode 100644
index 0000000..21a19e5
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexMethodImpl.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import dex.reader.DexClassImpl.MethodAnnotation;
+import dex.reader.DexClassImpl.ParameterAnnotation;
+import dex.reader.DexFileReader.FieldIdItem;
+import dex.reader.DexFileReader.MethodsIdItem;
+import dex.reader.DexFileReader.ProtIdItem;
+import dex.structure.DexAnnotation;
+import dex.structure.DexClass;
+import dex.structure.DexMethod;
+import dex.structure.DexParameter;
+
+/* package */final class DexMethodImpl implements DexMethod {
+
+    private DexBuffer buffer;
+    private MethodsIdItem methodsIdItem;
+    private String[] stringPool;
+    private int[] typeIds;
+    private ProtIdItem protoIdItem;
+    private List<DexParameter> parameters;
+    private final int accessFlags;
+    private final MethodAnnotation methodAnnotation;
+    private Set<DexAnnotation> annotations;
+    private final TypeFormatter formatter = new TypeFormatter();
+    private final DexClass declaringClass;
+    private final ParameterAnnotation parameterAnnotation;
+    private Map<Integer, Integer> parameterIdToIndex;
+    private final FieldIdItem[] fieldIdItems;
+
+    public DexMethodImpl(DexBuffer buffer, DexClass declaringClass,
+            MethodsIdItem methodsIdItem, ProtIdItem protoIdItem,
+            int accessFlags, MethodAnnotation methodAnnotation,
+            ParameterAnnotation parameterAnnotation, String[] stringPool,
+            int[] typeIds, FieldIdItem[] fieldIdItems) {
+        this.buffer = buffer;
+        this.declaringClass = declaringClass;
+        this.methodsIdItem = methodsIdItem;
+        this.protoIdItem = protoIdItem;
+        this.accessFlags = accessFlags;
+        this.methodAnnotation = methodAnnotation;
+        this.parameterAnnotation = parameterAnnotation;
+        this.stringPool = stringPool;
+        this.typeIds = typeIds;
+        this.fieldIdItems = fieldIdItems;
+        parseAnnotations();
+        parseParameterAnnotations();
+    }
+
+    private void parseParameterAnnotations() {
+        parameterIdToIndex = new HashMap<Integer, Integer>();
+        if (parameterAnnotation != null) {
+            buffer.setPosition(parameterAnnotation.annotationsOff);
+            int numberOfParameters = buffer.readUInt();
+            for (int i = 0; i < numberOfParameters; i++) {
+                parameterIdToIndex.put(i, buffer.readUInt());
+            }
+        }
+    }
+
+    private void parseAnnotations() {
+        annotations = new HashSet<DexAnnotation>();
+        if (methodAnnotation != null) {
+            buffer.setPosition(methodAnnotation.annotationsOff);
+            final int size = buffer.readUInt();
+            for (int i = 0; i < size; i++) {
+                annotations.add(new DexAnnotationImpl(buffer.createCopy(),
+                        buffer.readUInt(), typeIds, stringPool, fieldIdItems));
+            }
+        }
+    }
+
+    public String getName() {
+        return stringPool[methodsIdItem.name_idx];
+    }
+
+    public String getReturnType() {
+        return stringPool[typeIds[protoIdItem.return_type_idx]];
+    }
+
+    public synchronized List<DexParameter> getParameters() {
+        if (parameters == null) {
+            parameters = new LinkedList<DexParameter>();
+            if (protoIdItem.parameter_off != 0) {
+
+                buffer.setPosition(protoIdItem.parameter_off);
+                int size = buffer.readUInt();
+
+                int[] paramTypeIdx = new int[size];
+                for (int i = 0; i < size; i++) {
+                    paramTypeIdx[i] = buffer.readUShort();
+                }
+                for (int i = 0; i < paramTypeIdx.length; i++) {
+                    parameters.add(new DexParameterImpl(buffer.createCopy(),
+                            stringPool[typeIds[paramTypeIdx[i]]],
+                            parameterIdToIndex.get(i), typeIds, stringPool,
+                            fieldIdItems));
+                }
+            }
+        }
+        return parameters;
+    }
+
+    public int getModifiers() {
+        return accessFlags;
+    }
+
+    public Set<DexAnnotation> getAnnotations() {
+        return annotations;
+    }
+
+    public DexClass getDeclaringClass() {
+        return declaringClass;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append(formatter.formatAnnotations(getAnnotations()));
+        builder.append(Modifier.toString(getModifiers()));
+        builder.append(" ");
+        builder.append(formatter.format(getReturnType()));
+        builder.append(" ");
+        builder.append(getName());
+        builder.append("(");
+        List<DexParameter> parameters = getParameters();
+        for (DexParameter dexParameter : parameters) {
+            builder.append(formatter.formatAnnotations(dexParameter
+                    .getAnnotations()));
+            builder.append(formatter.format(dexParameter.getTypeName()));
+        }
+        builder.append(")");
+        return builder.toString();
+    }
+}
diff --git a/tools/dex-tools/src/dex/reader/DexParameterImpl.java b/tools/dex-tools/src/dex/reader/DexParameterImpl.java
new file mode 100644
index 0000000..ec2db05
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexParameterImpl.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import dex.reader.DexFileReader.FieldIdItem;
+import dex.structure.DexAnnotation;
+import dex.structure.DexParameter;
+
+public class DexParameterImpl implements DexParameter {
+
+    private final String typeName;
+    private final Integer annotationOffset;
+    private Set<DexAnnotation> annotations;
+    private final DexBuffer buffer;
+    private final int[] typeIds;
+    private final String[] stringPool;
+    private final FieldIdItem[] fieldIdItems;
+
+    public DexParameterImpl(DexBuffer buffer, String typeName,
+            Integer annotationOffset, int[] typeIds, String[] stringPool,
+            FieldIdItem[] fieldIdItems) {
+        this.buffer = buffer;
+        this.typeName = typeName;
+        this.annotationOffset = annotationOffset;
+        this.typeIds = typeIds;
+        this.stringPool = stringPool;
+        this.fieldIdItems = fieldIdItems;
+        parseAnnotations();
+    }
+
+    private void parseAnnotations() {
+        annotations = new HashSet<DexAnnotation>();
+        if (annotationOffset != null) {
+            buffer.setPosition(annotationOffset);
+            final int size = buffer.readUInt();
+            for (int i = 0; i < size; i++) {
+                annotations.add(new DexAnnotationImpl(buffer.createCopy(),
+                        buffer.readUInt(), typeIds, stringPool, fieldIdItems));
+            }
+        }
+    }
+
+    public String getTypeName() {
+        return typeName;
+    }
+
+    public Set<DexAnnotation> getAnnotations() {
+        return annotations;
+    }
+
+    @Override
+    public String toString() {
+        return getTypeName();
+    }
+}
diff --git a/tools/dex-tools/src/dex/reader/TypeFormatter.java b/tools/dex-tools/src/dex/reader/TypeFormatter.java
new file mode 100644
index 0000000..f54b30f
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/TypeFormatter.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import dex.structure.DexAnnotation;
+import dex.structure.DexClass;
+import dex.structure.DexField;
+import dex.structure.DexFile;
+import dex.structure.DexMethod;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * <pre>
+ * TypeDescriptor := 'V' | FieldTypeDescriptor
+ * FieldTypeDescriptor := NonArrayFieldTypeDescriptor | ('[' * 1...255) NonArrayFieldTypeDescriptor
+ * NonArrayFieldTypeDescriptor := 'Z' | 'B' | 'S' | 'C' | 'I' | 'J' | 'F' | 'D' | 'L' FullClassName ';'
+ * </pre>
+ */
+public final class TypeFormatter {
+
+    /**
+     * V void; only valid for return types Z boolean B byte S short C char I int
+     * J long F float D double Lfully/qualified/Name; the class
+     * fully.qualified.Name [descriptor array of descriptor, usable recursively
+     * for arrays-of-arrays, though it is invalid to have more than 255
+     * dimensions.
+     */
+    public String format(String typeName) {
+        if (typeName.length() == 1) {
+            switch (typeName.charAt(0)) {
+            case 'V':
+                return "void";
+            case 'Z':
+                return "boolean";
+            case 'B':
+                return "byte";
+            case 'S':
+                return "short";
+            case 'C':
+                return "char";
+            case 'I':
+                return "int";
+            case 'J':
+                return "long";
+            case 'F':
+                return "float";
+            case 'D':
+                return "double";
+            }
+        } else {
+            if (typeName.startsWith("L")) {
+                return typeName.substring(1, typeName.length() - 1).replace(
+                        "/", "."); // remove 'L' and ';', replace '/' with '.'
+            } else if (typeName.startsWith("[")) {
+                return format(typeName.substring(1)) + "[]";
+            }
+        }
+        System.err.println("Strange type in formatter: " + typeName);
+        return typeName;
+    }
+
+    public String format(List<String> typeNames) {
+        List<String> types = new ArrayList<String>(typeNames.size());
+        for (String type : typeNames) {
+            types.add(format(type));
+        }
+        return format(types, ", ");
+    }
+
+    public String formatAnnotations(Set<DexAnnotation> annotations) {
+        return format(new ArrayList<DexAnnotation>(annotations), "\n") + "\n";
+    }
+
+    private String format(List<?> elements, String separator) {
+        StringBuilder builder = new StringBuilder();
+        boolean first = true;
+        for (Object element : elements) {
+            if (!first) {
+                builder.append(separator);
+            }
+            builder.append(element.toString());
+            first = false;
+        }
+        return builder.toString();
+    }
+
+
+    public String formatDexFile(DexFile file) {
+        StringBuilder builder = new StringBuilder();
+        builder.append("----------------DEX_FILE--------------\n\n");
+        builder.append("Filename: ").append(file.getName());
+        builder.append("\n-----------DEFINED_CLASSES------------\n\n");
+        for (DexClass dexClass : file.getDefinedClasses()) {
+            builder.append("\n________________CLASS________________\n\n");
+            builder.append(dexClass);
+            builder.append("\n\n----------------FIELDS----------------\n");
+            for (DexField field : dexClass.getFields()) {
+                builder.append(field).append("\n");
+            }
+            builder.append("----------------METHODS----------------\n");
+            for (DexMethod method : dexClass.getMethods()) {
+                builder.append(method).append("\n");
+            }
+        }
+        return builder.toString();
+    }
+}
diff --git a/tools/dex-tools/src/dex/structure/DexAnnotatedElement.java b/tools/dex-tools/src/dex/structure/DexAnnotatedElement.java
new file mode 100644
index 0000000..0b69ca8
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexAnnotatedElement.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+import java.util.Set;
+
+/**
+ * {@code DexAnnotatedElement} is implemented by all Elements that could have
+ * attached annotations.
+ */
+public interface DexAnnotatedElement {
+
+    /**
+     * Returns a list of {@code DexAnnotation} elements.
+     * 
+     * @return a list of {@code DexAnnotation} elements
+     */
+    Set<DexAnnotation> getAnnotations();
+}
diff --git a/tools/dex-tools/src/dex/structure/DexAnnotation.java b/tools/dex-tools/src/dex/structure/DexAnnotation.java
new file mode 100644
index 0000000..9cd372d
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexAnnotation.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+import java.util.List;
+
+/**
+ * {@code DexAnnotation} represents an annotation.
+ */
+public interface DexAnnotation {
+
+    /**
+     * {@code Visibility} indicates the retention of a {@code DexAnnotation}.
+     */
+    enum Visibility {
+        /**
+         * Intended only to be visible at build time (e.g., during compilation
+         * of other code).
+         */
+        VISIBILITY_BUILD((byte) 0x00),
+        /**
+         * Intended to be visible at runtime. FIXME missing words in spec
+         */
+        VISIBILITY_RUNTIME((byte) 0X01),
+        /**
+         * Intended to be visible at runtime, but only to the underlying system
+         * (and not to regular user code). FIXME missing words in spec
+         */
+        VISIBILITY_SYSTEM((byte) 0x02);
+
+        @SuppressWarnings("unused")
+        private byte value;
+
+        private Visibility(byte value) {
+            this.value = value;
+        }
+
+        /**
+         * Returns the {@code Visibility} identified by the given {@code byte}.
+         * pre: 0 <= {@code value} <=2
+         * 
+         * @param value
+         *            the {@code byte} value which identifies a {@code
+         *            Visibility}
+         * @return the {@code Visibility} for the given {@code byte}
+         */
+        public static Visibility get(byte value) {
+            // FIXME loop and compare instead of switch?
+            switch (value) {
+            case 0x00:
+                return VISIBILITY_BUILD;
+            case 0x01:
+                return VISIBILITY_RUNTIME;
+            case 0x02:
+                return VISIBILITY_SYSTEM;
+            default:
+                throw new IllegalArgumentException("Visibility doesn't exist!");
+            }
+        }
+    }
+
+    /**
+     * Returns the {@code Visibility} of this {@code DexAnnotation}.
+     * 
+     * @return the {@code Visibility} of this {@code DexAnnotation}
+     */
+    Visibility getVisibility();
+
+    /**
+     * Returns the attributes of this {@code DexAnnotation}.
+     * 
+     * @return the attributes of this {@code DexAnnotation}
+     */
+    List<DexAnnotationAttribute> getAttributes();
+
+    /**
+     * Returns the class name of this {@code DexAnnotation}.
+     * 
+     * @return the class name of this {@code DexAnnotation}
+     */
+    String getTypeName();
+}
diff --git a/tools/dex-tools/src/dex/structure/DexAnnotationAttribute.java b/tools/dex-tools/src/dex/structure/DexAnnotationAttribute.java
new file mode 100644
index 0000000..4d51c08
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexAnnotationAttribute.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+/**
+ * {@code DexAnnotationValue} is implemented by annotation values. In the
+ * following example:
+ * 
+ * <pre>
+ * &#064;Text(value=&quot;hello&quot;)
+ * </pre>
+ * 
+ * 'value="hello"' is represented by a {@code DexAnnotationValue}. "value" is
+ * its name and "hello" is its encoded value.
+ */
+public interface DexAnnotationAttribute extends NamedElement {
+    /**
+     * Returns the encoded value of this {@code DexAnnotationValue}.
+     * 
+     * @return the encoded value of this {@code DexAnnotationValue}
+     */
+    public DexEncodedValue getEncodedValue();
+
+    public DexAnnotation getAnnotation();
+}
diff --git a/tools/dex-tools/src/dex/structure/DexClass.java b/tools/dex-tools/src/dex/structure/DexClass.java
new file mode 100644
index 0000000..198f4ee
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexClass.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+import java.util.List;
+
+/**
+ * {@code DexClass} represents a class.
+ */
+public interface DexClass extends DexAnnotatedElement, WithModifiers,
+        NamedElement {
+    /**
+     * Returns a list containing the names of all implemented interfaces.
+     * 
+     * @return a list containing the names of all implemented interfaces
+     */
+    List<String> getInterfaces();
+
+    /**
+     * Returns the name of the super class.
+     * 
+     * @return the name of the super class, maybe {@code null}
+     */
+    String getSuperClass();
+
+    /**
+     * Returns a list containing all fields declared by this {@code DexClass}.
+     * 
+     * @return a list containing all fields declared by this {@code DexClass}
+     */
+    List<DexField> getFields();
+
+    /**
+     * Returns a list containing all methods declared by this {@code DexClass}.
+     * 
+     * @return a list containing all methods declared by this {@code DexClass}
+     */
+    List<DexMethod> getMethods();
+}
diff --git a/tools/dex-tools/src/dex/structure/DexEncodedAnnotation.java b/tools/dex-tools/src/dex/structure/DexEncodedAnnotation.java
new file mode 100644
index 0000000..f31fe74
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexEncodedAnnotation.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+import java.util.List;
+
+public interface DexEncodedAnnotation extends DexEncodedValue {
+    String getTypeName();
+
+    List<DexAnnotationAttribute> getValue();
+
+}
diff --git a/tools/dex-tools/src/dex/structure/DexEncodedValue.java b/tools/dex-tools/src/dex/structure/DexEncodedValue.java
new file mode 100644
index 0000000..1d09f34
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexEncodedValue.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+/**
+ * {@code DexEncodedValue} represents an encoded value. The value of a {@code
+ * DexAnnotationValue} is encoded as {@code DexEncodedValue}.
+ */
+public interface DexEncodedValue {
+
+    /**
+     * Returns the type of this {@code DexEncodedValue}.
+     * 
+     * @return the type of this {@code DexEncodedValue}
+     */
+    DexEncodedValueType getType();
+
+    /**
+     * Returns the value of this {@code DexEncodedValue}.
+     * 
+     * @return the value of this {@code DexEncodedValue}
+     */
+    Object getValue();
+}
diff --git a/tools/dex-tools/src/dex/structure/DexEncodedValueType.java b/tools/dex-tools/src/dex/structure/DexEncodedValueType.java
new file mode 100644
index 0000000..00560f3
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexEncodedValueType.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+/**
+ * {@code DexEncodedValueType} represents the type of an {code DexEncodedValue}.
+ */
+public enum DexEncodedValueType {
+    /**
+     * <pre>
+     * VALUE_BYTE 0x00 (none; must be 0) ubyte[1]
+     * </pre>
+     * 
+     * signed one-byte integer value
+     */
+    VALUE_BYTE((byte) 0x00),
+    /**
+     * <pre>
+     * VALUE_SHORT 0x02 size - 1 (0...1) ubyte[size]
+     * </pre>
+     * 
+     * signed two-byte integer value, sign-extended
+     */
+    VALUE_SHORT((byte) 0x02),
+    /**
+     * <pre>
+     * VALUE_CHAR 0x03 size - 1 (0...1) ubyte[size]
+     * </pre>
+     * 
+     * unsigned two-byte integer value, zero-extended
+     */
+    VALUE_CHAR((byte) 0x03),
+    /**
+     * <pre>
+     * VALUE_INT 0x04 size - 1 (0...3) ubyte[size]
+     * </pre>
+     * 
+     * signed four-byte integer value, sign-extended
+     */
+    VALUE_INT((byte) 0x04),
+    /**
+     * <pre>
+     * VALUE_LONG 0x06 size - 1 (0...7) ubyte[size]
+     * </pre>
+     * 
+     * signed eight-byte integer value, sign-extended
+     */
+    VALUE_LONG((byte) 0x06),
+    /**
+     * <pre>
+     * VALUE_FLOAT 0x10 size - 1 (0...3) ubyte[size]
+     * </pre>
+     * 
+     * four-byte bit pattern, zero-extended to the right, and interpreted as an
+     * IEEE754 32-bit floating point value
+     */
+    VALUE_FLOAT((byte) 0x10),
+    /**
+     * <pre>
+     * VALUE_DOUBLE 0x11 size - 1 (0...7) ubyte[size]
+     * </pre>
+     * 
+     * eight-byte bit pattern, zero-extended to the right, and interpreted as an
+     * IEEE754 64-bit floating point value
+     */
+    VALUE_DOUBLE((byte) 0x11),
+    /**
+     * <pre>
+     * VALUE_STRING    0x17     size - 1 (0...3)     ubyte[size]
+     * </pre>
+     * 
+     * unsigned (zero-extended) four-byte integer value, interpreted as an index
+     * into the string_ids section and representing a string value
+     */
+    VALUE_STRING((byte) 0x17),
+    /**
+     * <pre>
+     * VALUE_TYPE 0x18 size - 1 (0...3) ubyte[size]
+     * </pre>
+     * 
+     * unsigned (zero-extended) four-byte integer value, interpreted as an index
+     * into the type_ids section and representing a reflective type/class value
+     */
+    VALUE_TYPE((byte) 0x18),
+    /**
+     * <pre>
+     * VALUE_FIELD 0x19 size - 1 (0...3) ubyte[size]
+     * </pre>
+     * 
+     * unsigned (zero-extended) four-byte integer value, interpreted as an index
+     * into the field_ids section and representing a reflective field value
+     */
+    VALUE_FIELD((byte) 0x19),
+    /**
+     * <pre>
+     * VALUE_METHOD 0x1a size - 1 (0...3) ubyte[size]
+     * </pre>
+     * 
+     * unsigned (zero-extended) four-byte integer value, interpreted as an index
+     * into the method_ids section and representing a reflective method value
+     */
+    VALUE_METHOD((byte) 0x1a),
+    /**
+     * <pre>
+     * VALUE_ENUM 0x1b size - 1 (0...3) ubyte[size]
+     * </pre>
+     * 
+     * unsigned (zero-extended) four-byte integer value, interpreted as an index
+     * into the field_ids section and representing the value of an enumerated
+     * type constant
+     */
+    VALUE_ENUM((byte) 0x1b),
+    /**
+     * <pre>
+     * VALUE_ARRAY 0x1c (none; must be 0) encoded_array
+     * </pre>
+     * 
+     * an array of values, in the format specified by "encoded_array Format"
+     * below. The size of the value is implicit in the encoding.
+     */
+    VALUE_ARRAY((byte) 0x1c),
+    /**
+     * <pre>
+     * VALUE_ANNOTATION 0x1d (none; must be 0) encoded_annotation
+     * </pre>
+     * 
+     * a sub-annotation, in the format specified by "encoded_annotation Format"
+     * below. The size of the value is implicit in the encoding.
+     */
+    VALUE_ANNOTATION((byte) 0x1d),
+    /**
+     * <pre>
+     * VALUE_NULL 0x1e (none; must be 0) (none)
+     * </pre>
+     * 
+     * null reference value
+     */
+    VALUE_NULL((byte) 0x1e),
+    /**
+     * <pre>
+     * VALUE_BOOLEAN 0x1f boolean (0...1) (none)
+     * </pre>
+     * 
+     * one-bit value; 0 for false and 1 for true. The bit is represented in the
+     * value_arg.
+     */
+    VALUE_BOOLEAN((byte) 0x1f);
+
+    private byte value;
+
+    /**
+     * Creates a new instance of {@code DexEncodedValueType} using the provided
+     * byte.
+     * <p>
+     * Format: value := (value_arg << 5) | value_type
+     * 
+     * @param value
+     *            the {@code byte} containing the type and the value argument
+     */
+    private DexEncodedValueType(byte value) {
+        this.value = value;
+    }
+
+    /**
+     * Returns the {@code DexEncodedValueType} for the given {@code byte}.
+     * 
+     * @param value
+     *            the {@code byte} containing the type and the value argument
+     * @return the {@code DexEncodedValueType} for the given {@code byte}
+     */
+    public static DexEncodedValueType get(byte value) {
+        // FIXME don't loop -> switch to get performance boost
+        for (DexEncodedValueType type : values()) {
+            if (type.value == (value & 0x1F)) {
+                return type;
+            }
+        }
+        throw new IllegalArgumentException("Type does not exist!");
+    }
+
+    /**
+     * Returns the value argument of the given {@code byte}.
+     * <p>
+     * Format: value := (value_arg << 5) | value_type
+     * 
+     * @param value
+     *            the {@code byte} containing the type and the value argument
+     * @return the value argument of the given {@code byte}
+     */
+    public static byte valueArg(byte value) {
+        return (byte) (value >>> 5);
+    }
+}
diff --git a/tools/dex-tools/src/dex/structure/DexField.java b/tools/dex-tools/src/dex/structure/DexField.java
new file mode 100644
index 0000000..419bfad
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexField.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+/**
+ * {@code DexField} represents a field.
+ */
+public interface DexField extends DexAnnotatedElement, WithModifiers,
+        NamedElement {
+
+    /**
+     * Returns the name of the type of this {@code DexField}.
+     * 
+     * @return the name of the type of this {@code DexField}
+     */
+    String getType();
+
+    DexClass getDeclaringClass();
+
+    boolean isEnumConstant();
+}
diff --git a/tools/dex-tools/src/dex/structure/DexFile.java b/tools/dex-tools/src/dex/structure/DexFile.java
new file mode 100644
index 0000000..f7ee50e
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexFile.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+
+import java.util.List;
+
+/**
+ * {@code DexFile} represents a whole dex file, containing multiple classes.
+ */
+public interface DexFile extends NamedElement {
+
+    /**
+     * Returns a list of {@code DexClass} elements that are part of this {@code
+     * DexFile}.
+     * 
+     * @return a list of {@code DexClass} elements that are part of this {@code
+     *         DexFile}
+     */
+    public List<DexClass> getDefinedClasses();
+
+}
diff --git a/tools/dex-tools/src/dex/structure/DexInterface.java b/tools/dex-tools/src/dex/structure/DexInterface.java
new file mode 100644
index 0000000..639b14d
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexInterface.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+/**
+ * {@code DexInterface} represents an interface.
+ */
+public interface DexInterface extends DexAnnotatedElement {
+}
diff --git a/tools/dex-tools/src/dex/structure/DexMethod.java b/tools/dex-tools/src/dex/structure/DexMethod.java
new file mode 100644
index 0000000..a2e3a09
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexMethod.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+import java.util.List;
+
+/**
+ * {@code DexMethod} represents a method.
+ */
+public interface DexMethod extends WithModifiers, DexAnnotatedElement,
+        NamedElement {
+    /**
+     * Returns a list of strings representing the types of the parameters of
+     * this method.
+     * 
+     * @return a list of strings representing the types of the parameters of
+     *         this method
+     */
+    public List<DexParameter> getParameters();
+
+    public String getReturnType();
+
+    public DexClass getDeclaringClass();
+}
diff --git a/tools/dex-tools/src/dex/structure/DexParameter.java b/tools/dex-tools/src/dex/structure/DexParameter.java
new file mode 100644
index 0000000..22a21e0
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexParameter.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+public interface DexParameter extends DexAnnotatedElement {
+    String getTypeName();
+}
diff --git a/tools/dex-tools/src/dex/structure/NamedElement.java b/tools/dex-tools/src/dex/structure/NamedElement.java
new file mode 100644
index 0000000..ab8b128
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/NamedElement.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+/**
+ * {@code NamedElement} represents an element with a name.
+ */
+public interface NamedElement {
+    /**
+     * Returns the name of this {@code NamedElement}.
+     * 
+     * @return the name of this {@code NamedElement}
+     */
+    String getName();
+}
diff --git a/tools/dex-tools/src/dex/structure/WithModifiers.java b/tools/dex-tools/src/dex/structure/WithModifiers.java
new file mode 100644
index 0000000..804c461
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/WithModifiers.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+import java.lang.reflect.Modifier;
+
+/**
+ * {@link WithModifiers} is implemented by all language elements that have
+ * modifiers.
+ */
+public interface WithModifiers {
+
+    /**
+     * The {@link Modifier} class should be used to decode the result.
+     * 
+     * @return the modifiers for this member
+     * 
+     * @see Modifier
+     */
+    int getModifiers();
+}