Merge "Revert "Revert "Increment dex version for N api level use""" into ub-jack-carnac
diff --git a/dexlib/src/main/java/org/jf/dexlib/HeaderItem.java b/dexlib/src/main/java/org/jf/dexlib/HeaderItem.java
index e3f9a0f..249bd68 100644
--- a/dexlib/src/main/java/org/jf/dexlib/HeaderItem.java
+++ b/dexlib/src/main/java/org/jf/dexlib/HeaderItem.java
@@ -40,7 +40,8 @@
*/
public static final byte[][] MAGIC_VALUES = new byte[][] {
new byte[] {0x64, 0x65, 0x78, 0x0A, 0x30, 0x33, 0x35, 0x00}, //"dex\n035" + '\0';
- new byte[] {0x64, 0x65, 0x78, 0x0A, 0x30, 0x33, 0x36, 0x00}}; //"dex\n036" + '\0';
+ new byte[] {0x64, 0x65, 0x78, 0x0A, 0x30, 0x33, 0x36, 0x00}, //"dex\n036" + '\0';
+ new byte[] {0x64, 0x65, 0x78, 0x0A, 0x30, 0x33, 0x37, 0x00}}; //"dex\n037" + '\0';
/** size of this section, in bytes */
diff --git a/dx/src/com/android/jack/dx/dex/DexFormat.java b/dx/src/com/android/jack/dx/dex/DexFormat.java
index 1c87cda..2648066 100644
--- a/dx/src/com/android/jack/dx/dex/DexFormat.java
+++ b/dx/src/com/android/jack/dx/dex/DexFormat.java
@@ -27,7 +27,7 @@
* API level to target in order to produce the most modern file
* format
*/
- public static final int API_CURRENT = 14;
+ public static final int API_CURRENT = 24;
/** API level to target in order to suppress extended opcode usage */
public static final int API_NO_EXTENDED_OPCODES = 13;
@@ -44,8 +44,14 @@
/** common suffix for all dex file "magic numbers" */
public static final String MAGIC_SUFFIX = "\0";
- /** dex file version number for the current format variant */
- public static final String VERSION_CURRENT = "036";
+ /**
+ * Dex file version number for dalvik.
+ * <p>
+ * Note: Dex version 36 was loadable in some versions of Dalvik but was never fully supported or
+ * completed and is not considered a valid dex file format.
+ * </p>
+ */
+ public static final String VERSION_CURRENT = "037";
/** dex file version number for API level 13 and earlier */
public static final String VERSION_FOR_API_13 = "035";
@@ -88,7 +94,7 @@
if (version.equals(VERSION_CURRENT)) {
return API_CURRENT;
} else if (version.equals(VERSION_FOR_API_13)) {
- return 13;
+ return API_NO_EXTENDED_OPCODES;
}
return -1;
@@ -108,4 +114,9 @@
return MAGIC_PREFIX + version + MAGIC_SUFFIX;
}
+
+ public static boolean isSupportedDexMagic(byte[] magic) {
+ int api = magicToApi(magic);
+ return api == API_NO_EXTENDED_OPCODES || api == API_CURRENT;
+ }
}
diff --git a/dx/src/com/android/jack/dx/dex/TableOfContents.java b/dx/src/com/android/jack/dx/dex/TableOfContents.java
index 0585c3d8..6eef864 100644
--- a/dx/src/com/android/jack/dx/dex/TableOfContents.java
+++ b/dx/src/com/android/jack/dx/dex/TableOfContents.java
@@ -68,6 +68,7 @@
encodedArrays,
annotationsDirectories};
+ public int apiLevel;
public int checksum;
public byte[] signature;
public int fileSize;
@@ -88,12 +89,12 @@
private void readHeader(DexBuffer.Section headerIn) {
byte[] magic = headerIn.readByteArray(8);
- int apiTarget = DexFormat.magicToApi(magic);
- if (apiTarget != DexFormat.API_NO_EXTENDED_OPCODES) {
+ if (!DexFormat.isSupportedDexMagic(magic)) {
throw new DexException("Unexpected magic: " + Arrays.toString(magic));
}
+ apiLevel = DexFormat.magicToApi(magic);
checksum = headerIn.readInt();
signature = headerIn.readByteArray(20);
fileSize = headerIn.readInt();
@@ -178,8 +179,8 @@
throw new IllegalArgumentException("No such map item: " + type);
}
- public void writeHeader(DexBuffer.Section out) throws IOException {
- out.write(DexFormat.apiToMagic(DexFormat.API_NO_EXTENDED_OPCODES).getBytes("UTF-8"));
+ public void writeHeader(DexBuffer.Section out, int api) throws IOException {
+ out.write(DexFormat.apiToMagic(api).getBytes("UTF-8"));
out.writeInt(checksum);
out.write(signature);
out.writeInt(fileSize);
diff --git a/jack-tests/tests/com/android/jack/dx/DxTests.java b/jack-tests/tests/com/android/jack/dx/DxTests.java
index dfe4e71..75792d7 100644
--- a/jack-tests/tests/com/android/jack/dx/DxTests.java
+++ b/jack-tests/tests/com/android/jack/dx/DxTests.java
@@ -16,7 +16,9 @@
package com.android.jack.dx;
+import com.android.jack.Options;
import com.android.jack.TestTools;
+import com.android.jack.dx.dex.DexFormat;
import com.android.jack.test.category.RuntimeRegressionTest;
import com.android.jack.test.helper.FileChecker;
import com.android.jack.test.helper.RuntimeTestHelper;
@@ -24,6 +26,11 @@
import com.android.jack.test.runtime.RuntimeTestInfo;
import com.android.jack.test.toolchain.AbstractTestTools;
import com.android.jack.test.toolchain.IToolchain;
+import com.android.jack.test.toolchain.JackApiToolchainBase;
+import com.android.jack.test.toolchain.JackApiV01;
+import com.android.jack.test.toolchain.JackApiV02;
+import com.android.jack.test.toolchain.JackBasedToolchain;
+import com.android.jack.test.toolchain.JillBasedToolchain;
import junit.framework.Assert;
@@ -40,8 +47,12 @@
import org.junit.experimental.categories.Category;
import java.io.File;
+import java.io.FileInputStream;
+import java.util.ArrayList;
+import java.util.List;
import javax.annotation.Nonnull;
+import javax.xml.bind.attachment.AttachmentMarshaller;
public class DxTests extends RuntimeTest {
@@ -126,6 +137,56 @@
Assert.assertTrue(hasOpcode(ci, Opcode.DIV_INT_2ADDR));
}
+ @Test
+ public void testDexVersionIsIncremented() throws Exception {
+
+ String dex37Magic = new String(new byte[] {0x64, 0x65, 0x78, 0x0A, 0x30, 0x33, 0x37, 0x00});
+ String dex35Magic = new String(new byte[] {0x64, 0x65, 0x78, 0x0A, 0x30, 0x33, 0x35, 0x00});
+
+ List<Class<? extends IToolchain>> excludedToolchains =
+ new ArrayList<Class<? extends IToolchain>>();
+ excludedToolchains.add(JillBasedToolchain.class);
+
+ JackApiToolchainBase toolchain =
+ AbstractTestTools.getCandidateToolchain(JackApiV02.class, excludedToolchains);
+
+ File dexOutDir = AbstractTestTools.createTempDir();
+ File outFile = new File(dexOutDir, "classes.dex");
+
+ toolchain.addToClasspath(toolchain.getDefaultBootClasspath());
+ toolchain.addProperty(Options.ANDROID_MIN_API_LEVEL.getName(), "23");
+ toolchain.srcToExe(dexOutDir, /* zipFile = */ false,
+ AbstractTestTools.getTestRootDir("com.android.jack.dx.version"));
+
+ byte[] magic = new byte[8];
+
+ FileInputStream fis = new FileInputStream(outFile);
+ fis.read(magic);
+ fis.close();
+
+ Assert.assertEquals(dex35Magic, new String(magic));
+
+ toolchain =
+ AbstractTestTools.getCandidateToolchain(JackApiV02.class, excludedToolchains);
+
+ dexOutDir = AbstractTestTools.createTempDir();
+ outFile = new File(dexOutDir, "classes.dex");
+
+ toolchain.addToClasspath(toolchain.getDefaultBootClasspath());
+ toolchain.addProperty(Options.ANDROID_MIN_API_LEVEL.getName(), "24");
+ toolchain.srcToExe(dexOutDir, /* zipFile = */ false,
+ AbstractTestTools.getTestRootDir("com.android.jack.dx.version"));
+
+ magic = new byte[8];
+
+ fis = new FileInputStream(outFile);
+ fis.read(magic);
+ fis.close();
+
+ Assert.assertEquals(dex37Magic, new String(magic));
+
+ }
+
private boolean hasOpcode(@Nonnull CodeItem codeItem, @Nonnull Opcode opcode) {
for (Instruction inst : codeItem.getInstructions()) {
if (inst.opcode == opcode) {
diff --git a/jack-tests/tests/com/android/jack/dx/version/C.java b/jack-tests/tests/com/android/jack/dx/version/C.java
new file mode 100644
index 0000000..e09b991
--- /dev/null
+++ b/jack-tests/tests/com/android/jack/dx/version/C.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.jack.dx.version;
+
+public class C {
+
+ public void m() {
+
+ }
+
+}
+
diff --git a/jack/src/com/android/jack/backend/dex/DexInLibraryWriter.java b/jack/src/com/android/jack/backend/dex/DexInLibraryWriter.java
index 9526d61..e2416ab 100644
--- a/jack/src/com/android/jack/backend/dex/DexInLibraryWriter.java
+++ b/jack/src/com/android/jack/backend/dex/DexInLibraryWriter.java
@@ -63,6 +63,8 @@
private final boolean forceJumbo = ThreadConfig.get(CodeItemBuilder.FORCE_JUMBO).booleanValue();
+ private final int apiLevel = ThreadConfig.get(Options.ANDROID_MIN_API_LEVEL).intValue();
+
private final boolean usePrebuilts =
ThreadConfig.get(Options.USE_PREBUILT_FROM_LIBRARY).booleanValue();
@@ -106,6 +108,7 @@
DexOptions options = new DexOptions();
options.forceJumbo = forceJumbo;
+ options.targetApiLevel = apiLevel;
DexFile typeDex = new DexFile(options);
typeDex.add(cdiMarker.getClassDefItem());
OutputStream outStream = null;
diff --git a/jack/src/com/android/jack/backend/dex/DexWritingTool.java b/jack/src/com/android/jack/backend/dex/DexWritingTool.java
index a1b6f2c..c5d5c62 100644
--- a/jack/src/com/android/jack/backend/dex/DexWritingTool.java
+++ b/jack/src/com/android/jack/backend/dex/DexWritingTool.java
@@ -74,6 +74,8 @@
private final boolean forceJumbo = ThreadConfig.get(CodeItemBuilder.FORCE_JUMBO).booleanValue();
+ private final int apiLevel = ThreadConfig.get(Options.ANDROID_MIN_API_LEVEL).intValue();
+
private final boolean usePrebuilts =
ThreadConfig.get(Options.USE_PREBUILT_FROM_LIBRARY).booleanValue();
@@ -81,6 +83,7 @@
protected DexFile createDexFile() {
DexOptions options = new DexOptions();
options.forceJumbo = forceJumbo;
+ options.targetApiLevel = apiLevel;
return new DexFile(options);
}
diff --git a/jack/src/com/android/jack/backend/dex/rop/CodeItemBuilder.java b/jack/src/com/android/jack/backend/dex/rop/CodeItemBuilder.java
index 44c7bb2..79f2d26 100644
--- a/jack/src/com/android/jack/backend/dex/rop/CodeItemBuilder.java
+++ b/jack/src/com/android/jack/backend/dex/rop/CodeItemBuilder.java
@@ -174,6 +174,7 @@
ThreadConfig.get(Options.EMIT_LOCAL_DEBUG_INFO).booleanValue();
private final boolean runDxOptimizations = ThreadConfig.get(DEX_OPTIMIZE).booleanValue();
private final boolean forceJumbo = ThreadConfig.get(FORCE_JUMBO).booleanValue();
+ private final int apiLevel = ThreadConfig.get(Options.ANDROID_MIN_API_LEVEL).intValue();
private final boolean emitLineNumberTable =
ThreadConfig.get(Options.EMIT_LINE_NUMBER_DEBUG_INFO).booleanValue();
@@ -486,6 +487,7 @@
private DalvCode createCode(@Nonnull JMethod method, @Nonnull RopMethod ropMethod) {
DexOptions options = new DexOptions();
options.forceJumbo = forceJumbo;
+ options.targetApiLevel = apiLevel;
int paramSize = getParameterWordCount(method);
int positionListKind;
LocalVariableInfo lvInfo;