Merge "Support v41 DEX version for dexdeps." into main am: 1bed4bab8b am: e5ed58210b am: f075e91770

Original change: https://android-review.googlesource.com/c/platform/dalvik/+/2902247

Change-Id: Ic1807a823e240e4a5e01cca6e8758d5441926a8e
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/tools/dexdeps/src/com/android/dexdeps/DexData.java b/tools/dexdeps/src/com/android/dexdeps/DexData.java
index 1b6cc98..e7f9a53 100644
--- a/tools/dexdeps/src/com/android/dexdeps/DexData.java
+++ b/tools/dexdeps/src/com/android/dexdeps/DexData.java
@@ -23,13 +23,11 @@
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 
-/**
- * Data extracted from a DEX file.
- */
+/** Data extracted from a DEX file. */
 public class DexData {
     private RandomAccessFile mDexFile;
     private HeaderItem mHeaderItem;
-    private String[] mStrings;              // strings from string_data_*
+    private String[] mStrings; // strings from string_data_*
     private TypeIdItem[] mTypeIds;
     private ProtoIdItem[] mProtoIds;
     private FieldIdItem[] mFieldIds;
@@ -39,9 +37,7 @@
     private byte tmpBuf[] = new byte[4];
     private ByteOrder mByteOrder = ByteOrder.LITTLE_ENDIAN;
 
-    /**
-     * Constructs a new DexData for this file.
-     */
+    /** Constructs a new DexData for this file. */
     public DexData(RandomAccessFile raf) {
         mDexFile = raf;
     }
@@ -65,19 +61,16 @@
         markInternalClasses();
     }
 
-    /**
-     * Verifies the given magic number.
-     */
+    /** Verifies the given magic number. */
     private static boolean verifyMagic(byte[] magic) {
-        return Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC_v035) ||
-            Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC_v037) ||
-            Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC_v038) ||
-            Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC_v039);
+        return Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC_v035)
+                || Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC_v037)
+                || Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC_v038)
+                || Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC_v039)
+                || Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC_v041);
     }
 
-    /**
-     * Parses the interesting bits out of the header.
-     */
+    /** Parses the interesting bits out of the header. */
     void parseHeaderItem() throws IOException {
         mHeaderItem = new HeaderItem();
 
@@ -86,8 +79,7 @@
         byte[] magic = new byte[8];
         readBytes(magic);
         if (!verifyMagic(magic)) {
-            System.err.println("Magic number is wrong -- are you sure " +
-                "this is a DEX file?");
+            System.err.println("Magic number is wrong -- are you sure " + "this is a DEX file?");
             throw new DexDataException();
         }
 
@@ -95,20 +87,21 @@
          * Read the endian tag, so we properly swap things as we read
          * them from here on.
          */
-        seek(8+4+20+4+4);
+        seek(8 + 4 + 20 + 4 + 4);
         mHeaderItem.endianTag = readInt();
         if (mHeaderItem.endianTag == HeaderItem.ENDIAN_CONSTANT) {
             /* do nothing */
-        } else if (mHeaderItem.endianTag == HeaderItem.REVERSE_ENDIAN_CONSTANT){
+        } else if (mHeaderItem.endianTag == HeaderItem.REVERSE_ENDIAN_CONSTANT) {
             /* file is big-endian (!), reverse future reads */
             mByteOrder = ByteOrder.BIG_ENDIAN;
         } else {
-            System.err.println("Endian constant has unexpected value " +
-                Integer.toHexString(mHeaderItem.endianTag));
+            System.err.println(
+                    "Endian constant has unexpected value "
+                            + Integer.toHexString(mHeaderItem.endianTag));
             throw new DexDataException();
         }
 
-        seek(8+4+20);  // magic, checksum, signature
+        seek(8 + 4 + 20); // magic, checksum, signature
         ByteBuffer buffer = readByteBuffer(Integer.BYTES * 20);
         mHeaderItem.fileSize = buffer.getInt();
         mHeaderItem.headerSize = buffer.getInt();
@@ -135,15 +128,14 @@
     /**
      * Loads the string table out of the DEX.
      *
-     * First we read all of the string_id_items, then we read all of the
-     * string_data_item.  Doing it this way should allow us to avoid
-     * seeking around in the file.
+     * <p>First we read all of the string_id_items, then we read all of the string_data_item. Doing
+     * it this way should allow us to avoid seeking around in the file.
      */
     void loadStrings() throws IOException {
         int count = mHeaderItem.stringIdsSize;
         int stringOffsets[] = new int[count];
 
-        //System.out.println("reading " + count + " strings");
+        // System.out.println("reading " + count + " strings");
 
         seek(mHeaderItem.stringIdsOff);
         readByteBuffer(Integer.BYTES * count).asIntBuffer().get(stringOffsets);
@@ -152,39 +144,35 @@
 
         seek(stringOffsets[0]);
         for (int i = 0; i < count; i++) {
-            seek(stringOffsets[i]);         // should be a no-op
+            seek(stringOffsets[i]); // should be a no-op
             mStrings[i] = readString();
-            //System.out.println("STR: " + i + ": " + mStrings[i]);
+            // System.out.println("STR: " + i + ": " + mStrings[i]);
         }
     }
 
-    /**
-     * Loads the type ID list.
-     */
+    /** Loads the type ID list. */
     void loadTypeIds() throws IOException {
         int count = mHeaderItem.typeIdsSize;
         mTypeIds = new TypeIdItem[count];
 
-        //System.out.println("reading " + count + " typeIds");
+        // System.out.println("reading " + count + " typeIds");
         seek(mHeaderItem.typeIdsOff);
         ByteBuffer buffer = readByteBuffer(Integer.BYTES * count);
         for (int i = 0; i < count; i++) {
             mTypeIds[i] = new TypeIdItem();
             mTypeIds[i].descriptorIdx = buffer.getInt();
 
-            //System.out.println(i + ": " + mTypeIds[i].descriptorIdx +
+            // System.out.println(i + ": " + mTypeIds[i].descriptorIdx +
             //    " " + mStrings[mTypeIds[i].descriptorIdx]);
         }
     }
 
-    /**
-     * Loads the proto ID list.
-     */
+    /** Loads the proto ID list. */
     void loadProtoIds() throws IOException {
         int count = mHeaderItem.protoIdsSize;
         mProtoIds = new ProtoIdItem[count];
 
-        //System.out.println("reading " + count + " protoIds");
+        // System.out.println("reading " + count + " protoIds");
         seek(mHeaderItem.protoIdsOff);
         ByteBuffer buffer = readByteBuffer(Integer.BYTES * 3 * count);
 
@@ -197,7 +185,7 @@
             mProtoIds[i].returnTypeIdx = buffer.getInt();
             mProtoIds[i].parametersOff = buffer.getInt();
 
-            //System.out.println(i + ": " + mProtoIds[i].shortyIdx +
+            // System.out.println(i + ": " + mProtoIds[i].shortyIdx +
             //    " " + mStrings[mProtoIds[i].shortyIdx]);
         }
 
@@ -214,7 +202,7 @@
                 continue;
             } else {
                 seek(offset);
-                int size = readInt();       // #of entries in list
+                int size = readInt(); // #of entries in list
                 buffer = readByteBuffer(Short.BYTES * size);
                 protoId.types = new int[size];
 
@@ -225,14 +213,12 @@
         }
     }
 
-    /**
-     * Loads the field ID list.
-     */
+    /** Loads the field ID list. */
     void loadFieldIds() throws IOException {
         int count = mHeaderItem.fieldIdsSize;
         mFieldIds = new FieldIdItem[count];
 
-        //System.out.println("reading " + count + " fieldIds");
+        // System.out.println("reading " + count + " fieldIds");
         seek(mHeaderItem.fieldIdsOff);
         ByteBuffer buffer = readByteBuffer((Integer.BYTES + Short.BYTES * 2) * count);
         for (int i = 0; i < count; i++) {
@@ -241,19 +227,17 @@
             mFieldIds[i].typeIdx = buffer.getShort() & 0xffff;
             mFieldIds[i].nameIdx = buffer.getInt();
 
-            //System.out.println(i + ": " + mFieldIds[i].nameIdx +
+            // System.out.println(i + ": " + mFieldIds[i].nameIdx +
             //    " " + mStrings[mFieldIds[i].nameIdx]);
         }
     }
 
-    /**
-     * Loads the method ID list.
-     */
+    /** Loads the method ID list. */
     void loadMethodIds() throws IOException {
         int count = mHeaderItem.methodIdsSize;
         mMethodIds = new MethodIdItem[count];
 
-        //System.out.println("reading " + count + " methodIds");
+        // System.out.println("reading " + count + " methodIds");
         seek(mHeaderItem.methodIdsOff);
         ByteBuffer buffer = readByteBuffer((Integer.BYTES + Short.BYTES * 2) * count);
         for (int i = 0; i < count; i++) {
@@ -262,44 +246,42 @@
             mMethodIds[i].protoIdx = buffer.getShort() & 0xffff;
             mMethodIds[i].nameIdx = buffer.getInt();
 
-            //System.out.println(i + ": " + mMethodIds[i].nameIdx +
+            // System.out.println(i + ": " + mMethodIds[i].nameIdx +
             //    " " + mStrings[mMethodIds[i].nameIdx]);
         }
     }
 
-    /**
-     * Loads the class defs list.
-     */
+    /** Loads the class defs list. */
     void loadClassDefs() throws IOException {
         int count = mHeaderItem.classDefsSize;
         mClassDefs = new ClassDefItem[count];
 
-        //System.out.println("reading " + count + " classDefs");
+        // System.out.println("reading " + count + " classDefs");
         seek(mHeaderItem.classDefsOff);
         ByteBuffer buffer = readByteBuffer(Integer.BYTES * 8 * count);
         for (int i = 0; i < count; i++) {
             mClassDefs[i] = new ClassDefItem();
             mClassDefs[i].classIdx = buffer.getInt();
 
-            /* access_flags = */ buffer.getInt();
-            /* superclass_idx = */ buffer.getInt();
-            /* interfaces_off = */ buffer.getInt();
-            /* source_file_idx = */ buffer.getInt();
-            /* annotations_off = */ buffer.getInt();
-            /* class_data_off = */ buffer.getInt();
-            /* static_values_off = */ buffer.getInt();
+            /* access_flags= */ buffer.getInt();
+            /* superclass_idx= */ buffer.getInt();
+            /* interfaces_off= */ buffer.getInt();
+            /* source_file_idx= */ buffer.getInt();
+            /* annotations_off= */ buffer.getInt();
+            /* class_data_off= */ buffer.getInt();
+            /* static_values_off= */ buffer.getInt();
 
-            //System.out.println(i + ": " + mClassDefs[i].classIdx + " " +
+            // System.out.println(i + ": " + mClassDefs[i].classIdx + " " +
             //    mStrings[mTypeIds[mClassDefs[i].classIdx].descriptorIdx]);
         }
     }
 
     /**
-     * Sets the "internal" flag on type IDs which are defined in the
-     * DEX file or within the VM (e.g. primitive classes and arrays).
+     * Sets the "internal" flag on type IDs which are defined in the DEX file or within the VM (e.g.
+     * primitive classes and arrays).
      */
     void markInternalClasses() {
-        for (int i = mClassDefs.length -1; i >= 0; i--) {
+        for (int i = mClassDefs.length - 1; i >= 0; i--) {
             mTypeIds[mClassDefs[i].classIdx].internal = true;
         }
 
@@ -313,29 +295,25 @@
                 mTypeIds[i].internal = true;
             }
 
-            //System.out.println(i + " " +
+            // System.out.println(i + " " +
             //    (mTypeIds[i].internal ? "INTERNAL" : "external") + " - " +
             //    mStrings[mTypeIds[i].descriptorIdx]);
         }
     }
 
-
     /*
      * =======================================================================
      *      Queries
      * =======================================================================
      */
 
-    /**
-     * Returns the class name, given an index into the type_ids table.
-     */
+    /** Returns the class name, given an index into the type_ids table. */
     private String classNameFromTypeIndex(int idx) {
         return mStrings[mTypeIds[idx].descriptorIdx];
     }
 
     /**
-     * Returns an array of method argument type strings, given an index
-     * into the proto_ids table.
+     * Returns an array of method argument type strings, given an index into the proto_ids table.
      */
     private String[] argArrayFromProtoIndex(int idx) {
         ProtoIdItem protoId = mProtoIds[idx];
@@ -349,8 +327,8 @@
     }
 
     /**
-     * Returns a string representing the method's return type, given an
-     * index into the proto_ids table.
+     * Returns a string representing the method's return type, given an index into the proto_ids
+     * table.
      */
     private String returnTypeFromProtoIndex(int idx) {
         ProtoIdItem protoId = mProtoIds[idx];
@@ -358,9 +336,8 @@
     }
 
     /**
-     * Returns an array with all of the class references that don't
-     * correspond to classes in the DEX file.  Each class reference has
-     * a list of the referenced fields and methods associated with
+     * Returns an array with all of the class references that don't correspond to classes in the DEX
+     * file. Each class reference has a list of the referenced fields and methods associated with
      * that class.
      */
     public ClassRef[] getExternalReferences() {
@@ -371,8 +348,7 @@
         int count = 0;
         for (int i = 0; i < mTypeIds.length; i++) {
             if (!mTypeIds[i].internal) {
-                sparseRefs[i] =
-                    new ClassRef(mStrings[mTypeIds[i].descriptorIdx]);
+                sparseRefs[i] = new ClassRef(mStrings[mTypeIds[i].descriptorIdx]);
                 count++;
             }
         }
@@ -385,8 +361,7 @@
         ClassRef[] classRefs = new ClassRef[count];
         int idx = 0;
         for (int i = 0; i < mTypeIds.length; i++) {
-            if (sparseRefs[i] != null)
-                classRefs[idx++] = sparseRefs[i];
+            if (sparseRefs[i] != null) classRefs[idx++] = sparseRefs[i];
         }
 
         assert idx == count;
@@ -395,87 +370,84 @@
     }
 
     /**
-     * Runs through the list of field references, inserting external
-     * references into the appropriate ClassRef.
+     * Runs through the list of field references, inserting external references into the appropriate
+     * ClassRef.
      */
     private void addExternalFieldReferences(ClassRef[] sparseRefs) {
         for (int i = 0; i < mFieldIds.length; i++) {
             if (!mTypeIds[mFieldIds[i].classIdx].internal) {
                 FieldIdItem fieldId = mFieldIds[i];
-                FieldRef newFieldRef = new FieldRef(
-                        classNameFromTypeIndex(fieldId.classIdx),
-                        classNameFromTypeIndex(fieldId.typeIdx),
-                        mStrings[fieldId.nameIdx]);
+                FieldRef newFieldRef =
+                        new FieldRef(
+                                classNameFromTypeIndex(fieldId.classIdx),
+                                classNameFromTypeIndex(fieldId.typeIdx),
+                                mStrings[fieldId.nameIdx]);
                 sparseRefs[mFieldIds[i].classIdx].addField(newFieldRef);
             }
         }
     }
 
     /**
-     * Runs through the list of method references, inserting external
-     * references into the appropriate ClassRef.
+     * Runs through the list of method references, inserting external references into the
+     * appropriate ClassRef.
      */
     private void addExternalMethodReferences(ClassRef[] sparseRefs) {
         for (int i = 0; i < mMethodIds.length; i++) {
             if (!mTypeIds[mMethodIds[i].classIdx].internal) {
                 MethodIdItem methodId = mMethodIds[i];
-                MethodRef newMethodRef = new MethodRef(
-                        classNameFromTypeIndex(methodId.classIdx),
-                        argArrayFromProtoIndex(methodId.protoIdx),
-                        returnTypeFromProtoIndex(methodId.protoIdx),
-                        mStrings[methodId.nameIdx]);
+                MethodRef newMethodRef =
+                        new MethodRef(
+                                classNameFromTypeIndex(methodId.classIdx),
+                                argArrayFromProtoIndex(methodId.protoIdx),
+                                returnTypeFromProtoIndex(methodId.protoIdx),
+                                mStrings[methodId.nameIdx]);
                 sparseRefs[mMethodIds[i].classIdx].addMethod(newMethodRef);
             }
         }
     }
 
-
     /*
      * =======================================================================
      *      Basic I/O functions
      * =======================================================================
      */
 
-    /**
-     * Seeks the DEX file to the specified absolute position.
-     */
+    /** Seeks the DEX file to the specified absolute position. */
     void seek(int position) throws IOException {
         mDexFile.seek(position);
     }
 
-    /**
-     * Fills the buffer by reading bytes from the DEX file.
-     */
+    /** Fills the buffer by reading bytes from the DEX file. */
     void readBytes(byte[] buffer) throws IOException {
         mDexFile.readFully(buffer);
     }
 
-    /**
-     * Reads a single signed byte value.
-     */
+    /** Reads a single signed byte value. */
     byte readByte() throws IOException {
         mDexFile.readFully(tmpBuf, 0, 1);
         return tmpBuf[0];
     }
 
-    /**
-     * Reads a signed 32-bit integer, byte-swapping if necessary.
-     */
+    /** Reads a signed 32-bit integer, byte-swapping if necessary. */
     int readInt() throws IOException {
         mDexFile.readFully(tmpBuf, 0, 4);
 
         if (mByteOrder == ByteOrder.BIG_ENDIAN) {
-            return (tmpBuf[3] & 0xff) | ((tmpBuf[2] & 0xff) << 8) |
-                   ((tmpBuf[1] & 0xff) << 16) | ((tmpBuf[0] & 0xff) << 24);
+            return (tmpBuf[3] & 0xff)
+                    | ((tmpBuf[2] & 0xff) << 8)
+                    | ((tmpBuf[1] & 0xff) << 16)
+                    | ((tmpBuf[0] & 0xff) << 24);
         } else {
-            return (tmpBuf[0] & 0xff) | ((tmpBuf[1] & 0xff) << 8) |
-                   ((tmpBuf[2] & 0xff) << 16) | ((tmpBuf[3] & 0xff) << 24);
+            return (tmpBuf[0] & 0xff)
+                    | ((tmpBuf[1] & 0xff) << 8)
+                    | ((tmpBuf[2] & 0xff) << 16)
+                    | ((tmpBuf[3] & 0xff) << 24);
         }
     }
 
     /**
-     * Reads a variable-length unsigned LEB128 value.  Does not attempt to
-     * verify that the value is valid.
+     * Reads a variable-length unsigned LEB128 value. Does not attempt to verify that the value is
+     * valid.
      *
      * @throws EOFException if we run off the end of the file
      */
@@ -504,14 +476,15 @@
     /**
      * Reads a UTF-8 string.
      *
-     * We don't know how long the UTF-8 string is, so we try to read the worst case amount of bytes.
+     * <p>We don't know how long the UTF-8 string is, so we try to read the worst case amount of
+     * bytes.
      *
-     * Note that the dex file pointer will likely be at a wrong location after this operation, which
-     * means it can't be used in the middle of sequential reads.
+     * <p>Note that the dex file pointer will likely be at a wrong location after this operation,
+     * which means it can't be used in the middle of sequential reads.
      */
     String readString() throws IOException {
         int utf16len = readUnsignedLeb128();
-        byte inBuf[] = new byte[utf16len * 3];      // worst case
+        byte inBuf[] = new byte[utf16len * 3]; // worst case
 
         int bytesRead = mDexFile.read(inBuf);
         for (int i = 0; i < bytesRead; i++) {
@@ -530,9 +503,7 @@
      * =======================================================================
      */
 
-    /**
-     * Holds the contents of a header_item.
-     */
+    /** Holds the contents of a header_item. */
     static class HeaderItem {
         public int fileSize;
         public int headerSize;
@@ -546,7 +517,7 @@
 
         /* expected magic values */
         public static final byte[] DEX_FILE_MAGIC_v035 =
-            "dex\n035\0".getBytes(StandardCharsets.US_ASCII);
+                "dex\n035\0".getBytes(StandardCharsets.US_ASCII);
 
         // Dex version 036 skipped because of an old dalvik bug on some versions
         // of android where dex files with that version number would erroneously
@@ -554,15 +525,19 @@
 
         // V037 was introduced in API LEVEL 24
         public static final byte[] DEX_FILE_MAGIC_v037 =
-            "dex\n037\0".getBytes(StandardCharsets.US_ASCII);
+                "dex\n037\0".getBytes(StandardCharsets.US_ASCII);
 
         // V038 was introduced in API LEVEL 26
         public static final byte[] DEX_FILE_MAGIC_v038 =
-            "dex\n038\0".getBytes(StandardCharsets.US_ASCII);
+                "dex\n038\0".getBytes(StandardCharsets.US_ASCII);
 
         // V039 was introduced in API LEVEL 28
         public static final byte[] DEX_FILE_MAGIC_v039 =
-            "dex\n039\0".getBytes(StandardCharsets.US_ASCII);
+                "dex\n039\0".getBytes(StandardCharsets.US_ASCII);
+
+        // V041 will be introduced in API LEVEL 35
+        public static final byte[] DEX_FILE_MAGIC_v041 =
+                "dex\n041\0".getBytes(StandardCharsets.US_ASCII);
 
         public static final int ENDIAN_CONSTANT = 0x12345678;
         public static final int REVERSE_ENDIAN_CONSTANT = 0x78563412;
@@ -571,54 +546,47 @@
     /**
      * Holds the contents of a type_id_item.
      *
-     * This is chiefly a list of indices into the string table.  We need
-     * some additional bits of data, such as whether or not the type ID
-     * represents a class defined in this DEX, so we use an object for
-     * each instead of a simple integer.  (Could use a parallel array, but
-     * since this is a desktop app it's not essential.)
+     * <p>This is chiefly a list of indices into the string table. We need some additional bits of
+     * data, such as whether or not the type ID represents a class defined in this DEX, so we use an
+     * object for each instead of a simple integer. (Could use a parallel array, but since this is a
+     * desktop app it's not essential.)
      */
     static class TypeIdItem {
-        public int descriptorIdx;       // index into string_ids
+        public int descriptorIdx; // index into string_ids
 
-        public boolean internal;        // defined within this DEX file?
+        public boolean internal; // defined within this DEX file?
     }
 
-    /**
-     * Holds the contents of a proto_id_item.
-     */
+    /** Holds the contents of a proto_id_item. */
     static class ProtoIdItem {
-        public int shortyIdx;           // index into string_ids
-        public int returnTypeIdx;       // index into type_ids
-        public int parametersOff;       // file offset to a type_list
+        public int shortyIdx; // index into string_ids
+        public int returnTypeIdx; // index into type_ids
+        public int parametersOff; // file offset to a type_list
 
-        public int types[];             // contents of type list
+        public int types[]; // contents of type list
     }
 
-    /**
-     * Holds the contents of a field_id_item.
-     */
+    /** Holds the contents of a field_id_item. */
     static class FieldIdItem {
-        public int classIdx;            // index into type_ids (defining class)
-        public int typeIdx;             // index into type_ids (field type)
-        public int nameIdx;             // index into string_ids
+        public int classIdx; // index into type_ids (defining class)
+        public int typeIdx; // index into type_ids (field type)
+        public int nameIdx; // index into string_ids
     }
 
-    /**
-     * Holds the contents of a method_id_item.
-     */
+    /** Holds the contents of a method_id_item. */
     static class MethodIdItem {
-        public int classIdx;            // index into type_ids
-        public int protoIdx;            // index into proto_ids
-        public int nameIdx;             // index into string_ids
+        public int classIdx; // index into type_ids
+        public int protoIdx; // index into proto_ids
+        public int nameIdx; // index into string_ids
     }
 
     /**
      * Holds the contents of a class_def_item.
      *
-     * We don't really need a class for this, but there's some stuff in
-     * the class_def_item that we might want later.
+     * <p>We don't really need a class for this, but there's some stuff in the class_def_item that
+     * we might want later.
      */
     static class ClassDefItem {
-        public int classIdx;            // index into type_ids
+        public int classIdx; // index into type_ids
     }
 }