Version 2.1.7-r1

Cherry-pick: Update backports for Android R
CL: https://r8-review.google

Clean and rename test for backports and min API levels.
CL: https://r8-review.googlesource.com/c/r8/+/51160

Update latest API level to R.
CL: https://r8-review.googlesource.com/c/r8/+/51141

Conflicts where resolved for the first and third cherry-pick.
Test code for the second cherry-pick was slightly modified due
to changes in the testing infrastructure.

Bug: 155694125
Change-Id: Ib4857c82d96bf4bceef378e02504fc5123d93086
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 8eec9bf..0dcfa7b 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
 
   // This field is accessed from release scripts using simple pattern matching.
   // Therefore, changing this field could break our release scripts.
-  public static final String LABEL = "2.1.7";
+  public static final String LABEL = "2.1.7-r1";
 
   private Version() {
   }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index fd0e452..24dbf4c 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -563,6 +563,9 @@
       if (options.minApiLevel < AndroidApiLevel.O.getLevel()) {
         initializeAndroidOMethodProviders(factory);
       }
+      if (options.minApiLevel < AndroidApiLevel.R.getLevel()) {
+        initializeAndroidRMethodProviders(factory);
+      }
 
       // The following providers are currently not implemented at any API level in Android.
       // They however require the Optional/Stream class to be present, either through
@@ -1258,74 +1261,11 @@
               method, BackportedMethods::StringMethods_joinIterable, "joinIterable"));
     }
 
-    private void initializeJava9MethodProviders(DexItemFactory factory) {
-      // Math & StrictMath, which have some symmetric, binary-compatible APIs
-      DexType[] mathTypes = {factory.mathType, factory.strictMathType};
-      for (int i = 0; i < mathTypes.length; i++) {
-        DexType type = mathTypes[i];
-
-        // long {Math,StrictMath}.multiplyExact(long, int)
-        DexString name = factory.createString("multiplyExact");
-        DexProto proto = factory.createProto(factory.longType, factory.longType, factory.intType);
-        DexMethod method = factory.createMethod(type, proto, name);
-        addProvider(
-            new MethodGenerator(
-                method,
-                BackportedMethods::MathMethods_multiplyExactLongInt,
-                "multiplyExactLongInt"));
-
-        // long {Math,StrictMath}.multiplyFull(int, int)
-        name = factory.createString("multiplyFull");
-        proto = factory.createProto(factory.longType, factory.intType, factory.intType);
-        method = factory.createMethod(type, proto, name);
-        addProvider(
-            new MethodGenerator(
-                method,
-                BackportedMethods::MathMethods_multiplyFull));
-
-        // long {Math,StrictMath}.multiplyHigh(long, long)
-        name = factory.createString("multiplyHigh");
-        proto = factory.createProto(factory.longType, factory.longType, factory.longType);
-        method = factory.createMethod(type, proto, name);
-        addProvider(
-            new MethodGenerator(
-                method,
-                BackportedMethods::MathMethods_multiplyHigh));
-
-        // long {Math,StrictMath}.floorDiv(long, int)
-        name = factory.createString("floorDiv");
-        proto = factory.createProto(factory.longType, factory.longType, factory.intType);
-        method = factory.createMethod(type, proto, name);
-        addProvider(
-            new MethodGenerator(
-                method, BackportedMethods::MathMethods_floorDivLongInt, "floorDivLongInt"));
-
-        // int {Math,StrictMath}.floorMod(long, int)
-        name = factory.createString("floorMod");
-        proto = factory.createProto(factory.intType, factory.longType, factory.intType);
-        method = factory.createMethod(type, proto, name);
-        addProvider(
-            new MethodGenerator(
-                method, BackportedMethods::MathMethods_floorModLongInt, "floorModLongInt"));
-      }
-
-      // Byte
-      DexType type = factory.boxedByteType;
-
-      // int Byte.compareUnsigned(byte, byte)
-      DexString name = factory.createString("compareUnsigned");
-      DexProto proto = factory.createProto(factory.intType, factory.byteType, factory.byteType);
-      DexMethod method = factory.createMethod(type, proto, name);
-      addProvider(new MethodGenerator(method, BackportedMethods::ByteMethods_compareUnsigned));
-
-      // Short
-      type = factory.boxedShortType;
-
-      // int Short.compareUnsigned(short, short)
-      name = factory.createString("compareUnsigned");
-      proto = factory.createProto(factory.intType, factory.shortType, factory.shortType);
-      method = factory.createMethod(type, proto, name);
-      addProvider(new MethodGenerator(method, BackportedMethods::ShortMethods_compareUnsigned));
+    private void initializeAndroidRMethodProviders(DexItemFactory factory) {
+      DexType type;
+      DexString name;
+      DexProto proto;
+      DexMethod method;
 
       // Objects
       type = factory.objectsType;
@@ -1436,6 +1376,70 @@
       addProvider(new MethodGenerator(method, BackportedMethods::CollectionMethods_mapEntry));
     }
 
+    private void initializeJava9MethodProviders(DexItemFactory factory) {
+      // Math & StrictMath, which have some symmetric, binary-compatible APIs
+      DexType[] mathTypes = {factory.mathType, factory.strictMathType};
+      for (int i = 0; i < mathTypes.length; i++) {
+        DexType type = mathTypes[i];
+
+        // long {Math,StrictMath}.multiplyExact(long, int)
+        DexString name = factory.createString("multiplyExact");
+        DexProto proto = factory.createProto(factory.longType, factory.longType, factory.intType);
+        DexMethod method = factory.createMethod(type, proto, name);
+        addProvider(
+            new MethodGenerator(
+                method,
+                BackportedMethods::MathMethods_multiplyExactLongInt,
+                "multiplyExactLongInt"));
+
+        // long {Math,StrictMath}.multiplyFull(int, int)
+        name = factory.createString("multiplyFull");
+        proto = factory.createProto(factory.longType, factory.intType, factory.intType);
+        method = factory.createMethod(type, proto, name);
+        addProvider(new MethodGenerator(method, BackportedMethods::MathMethods_multiplyFull));
+
+        // long {Math,StrictMath}.multiplyHigh(long, long)
+        name = factory.createString("multiplyHigh");
+        proto = factory.createProto(factory.longType, factory.longType, factory.longType);
+        method = factory.createMethod(type, proto, name);
+        addProvider(new MethodGenerator(method, BackportedMethods::MathMethods_multiplyHigh));
+
+        // long {Math,StrictMath}.floorDiv(long, int)
+        name = factory.createString("floorDiv");
+        proto = factory.createProto(factory.longType, factory.longType, factory.intType);
+        method = factory.createMethod(type, proto, name);
+        addProvider(
+            new MethodGenerator(
+                method, BackportedMethods::MathMethods_floorDivLongInt, "floorDivLongInt"));
+
+        // int {Math,StrictMath}.floorMod(long, int)
+        name = factory.createString("floorMod");
+        proto = factory.createProto(factory.intType, factory.longType, factory.intType);
+        method = factory.createMethod(type, proto, name);
+        addProvider(
+            new MethodGenerator(
+                method, BackportedMethods::MathMethods_floorModLongInt, "floorModLongInt"));
+      }
+
+      // Byte
+      DexType type = factory.boxedByteType;
+
+      // int Byte.compareUnsigned(byte, byte)
+      DexString name = factory.createString("compareUnsigned");
+      DexProto proto = factory.createProto(factory.intType, factory.byteType, factory.byteType);
+      DexMethod method = factory.createMethod(type, proto, name);
+      addProvider(new MethodGenerator(method, BackportedMethods::ByteMethods_compareUnsigned));
+
+      // Short
+      type = factory.boxedShortType;
+
+      // int Short.compareUnsigned(short, short)
+      name = factory.createString("compareUnsigned");
+      proto = factory.createProto(factory.intType, factory.shortType, factory.shortType);
+      method = factory.createMethod(type, proto, name);
+      addProvider(new MethodGenerator(method, BackportedMethods::ShortMethods_compareUnsigned));
+    }
+
     private void initializeJava10MethodProviders(DexItemFactory factory) {
       // List
       DexType type = factory.listType;
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java b/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
index 8c5c3b2..cbf6e2a 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
@@ -12,7 +12,7 @@
  * Android API level description
  */
 public enum AndroidApiLevel {
-  R(30),  // Speculative, this can change.
+  R(30),
   Q(29),
   P(28),
   O_MR1(27),
@@ -43,7 +43,7 @@
   B_1_1(2),
   B(1);
 
-  public static final AndroidApiLevel LATEST = Q;
+  public static final AndroidApiLevel LATEST = R;
 
   public static final int magicApiLevelUsedByAndroidPlatformBuild = 10000;
 
diff --git a/src/main/java/com/android/tools/r8/utils/DexVersion.java b/src/main/java/com/android/tools/r8/utils/DexVersion.java
index 99098d8..e9557fa 100644
--- a/src/main/java/com/android/tools/r8/utils/DexVersion.java
+++ b/src/main/java/com/android/tools/r8/utils/DexVersion.java
@@ -38,6 +38,7 @@
 
   public static DexVersion getDexVersion(AndroidApiLevel androidApiLevel) {
     switch (androidApiLevel) {
+      case R:
       case Q:
       case P:
         return DexVersion.V39;
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java b/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
index 190e7ee..d2dd4dc 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
@@ -28,7 +28,7 @@
 import org.junit.Test;
 
 abstract class AbstractBackportTest extends TestBase {
-  private final TestParameters parameters;
+  protected final TestParameters parameters;
   private final Class<?> targetClass;
   private final Class<?> testClass;
   private final Path testJar;
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/ApiLevelBackportsTest.java b/src/test/java/com/android/tools/r8/desugar/backports/ApiLevelBackportsTest.java
new file mode 100644
index 0000000..00c9bc3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/backports/ApiLevelBackportsTest.java
@@ -0,0 +1,163 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.desugar.backports;
+
+import static org.hamcrest.core.StringContains.containsString;
+
+import com.android.tools.r8.D8TestRunResult;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class ApiLevelBackportsTest extends TestBase {
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    // NOTE: Most of the 'run' invocations below work only because the static configured APIs do not
+    // give rise to DEX file versions larger than what can be accepted by VM 9.0.0.
+    return getTestParameters().withDexRuntimesStartingFromIncluding(Version.V9_0_0).build();
+  }
+
+  public ApiLevelBackportsTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Test
+  public void backportSucceedsOnSupportedApiLevel() throws Exception {
+    testForD8()
+        .addProgramClassFileData(transformTestMathMultiplyExactLongInt())
+        .setMinApi(AndroidApiLevel.B)
+        .run(parameters.getRuntime(), TestMathMultiplyExactLongInt.class)
+        .assertSuccessWithOutputLines("4");
+  }
+
+  @Test
+  public void backportOfNonPresentMethodOnLatest() throws Exception {
+    testForD8()
+        .addProgramClassFileData(transformTestMathMultiplyExactLongInt())
+        .setMinApi(AndroidApiLevel.LATEST)
+        .compile()
+        .assertNoMessages()
+        .run(parameters.getRuntime(), TestMathMultiplyExactLongInt.class)
+        .assertSuccessWithOutputLines("4");
+  }
+
+  @Test
+  public void backportOfPresentMethodOnLatest() throws Exception {
+    D8TestRunResult result =
+        testForD8()
+            .addProgramClassFileData(transformTestListOf())
+            .setMinApi(AndroidApiLevel.LATEST)
+            .compile()
+            .assertNoMessages()
+            .run(parameters.getRuntime(), TestListOf.class);
+    if (runtimeHasListOf()) {
+      result.assertSuccessWithOutputLines("0");
+    } else {
+      result.assertFailureWithErrorThatMatches(
+          containsString("java.lang.NoSuchMethodError: No static method of()Ljava/util/List;"));
+    }
+  }
+
+  @Test
+  public void warningForFutureNonPlatformBuild() throws Exception {
+    testForD8()
+        .addProgramClassFileData(transformTestMathMultiplyExactLongInt())
+        .setMinApi(AndroidApiLevel.LATEST.getLevel() + 1)
+        .compile()
+        .assertOnlyWarnings()
+        .assertWarningMessageThatMatches(containsString("is not supported by this compiler"))
+        .run(parameters.getRuntime(), TestMathMultiplyExactLongInt.class)
+        .assertFailureWithErrorThatMatches(
+            containsString("java.lang.NoSuchMethodError: No static method multiplyExact(JI)J"));
+  }
+
+  @Test
+  public void noWarningForPlatformBuild() throws Exception {
+    testForD8()
+        .addProgramClassFileData(transformTestMathMultiplyExactLongInt())
+        .setMinApi(AndroidApiLevel.magicApiLevelUsedByAndroidPlatformBuild)
+        .run(parameters.getRuntime(), TestMathMultiplyExactLongInt.class)
+        .assertFailureWithErrorThatMatches(
+            containsString("java.lang.NoSuchMethodError: No static method multiplyExact(JI)J"));
+  }
+
+  // Test class for using: List List.of()
+  // Introduced in Android R.
+
+  boolean runtimeHasListOf() {
+    return parameters
+        .getRuntime()
+        .asDex()
+        .getMinApiLevel()
+        .isGreaterThanOrEqualTo(AndroidApiLevel.R);
+  }
+
+  byte[] transformTestListOf() throws Exception {
+    return transformer(TestListOf.class)
+        .transformMethodInsnInMethod(
+            "main",
+            (opcode, owner, name, descriptor, isInterface, continuation) -> {
+              if (name.equals("List_of")) {
+                continuation.apply(opcode, "java/util/List", "of", descriptor, isInterface);
+              } else {
+                continuation.apply(opcode, owner, name, descriptor, isInterface);
+              }
+            })
+        .transform();
+  }
+
+  static class TestListOf {
+    public static List List_of() {
+      throw null;
+    }
+
+    public static void main(String[] args) {
+      System.out.println(List_of().size());
+    }
+  }
+
+  // Test class for the method: long Math.multiplyExact(long, int)
+  // Not present on any currently known Android platforms.
+
+  boolean runtimeHasMathMultiplyExactLongInt() {
+    // NOTE: This may change with a future release.
+    return false;
+  }
+
+  byte[] transformTestMathMultiplyExactLongInt() throws Exception {
+    return transformer(TestMathMultiplyExactLongInt.class)
+        .transformMethodInsnInMethod(
+            "main",
+            (opcode, owner, name, descriptor, isInterface, continuation) -> {
+              if (name.equals("Math_multiplyExact")) {
+                continuation.apply(
+                    opcode, "java/lang/Math", "multiplyExact", descriptor, isInterface);
+              } else {
+                continuation.apply(opcode, owner, name, descriptor, isInterface);
+              }
+            })
+        .transform();
+  }
+
+  static class TestMathMultiplyExactLongInt {
+    public static long Math_multiplyExact(long l, int i) {
+      throw null;
+    }
+
+    public static void main(String[] args) {
+      System.out.println(Math_multiplyExact(2L, 2));
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/ListBackportJava9Test.java b/src/test/java/com/android/tools/r8/desugar/backports/ListBackportJava9Test.java
index 03843cc0..0d55065 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/ListBackportJava9Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/ListBackportJava9Test.java
@@ -5,13 +5,16 @@
 package com.android.tools.r8.desugar.backports;
 
 import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+import static org.hamcrest.CoreMatchers.containsString;
 
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestRuntime.CfVm;
 import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.List;
+import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
@@ -29,9 +32,10 @@
 
   private static final Path TEST_JAR =
       Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
+  private static final String TEST_CLASS = "backport.ListBackportJava9Main";
 
   public ListBackportJava9Test(TestParameters parameters) {
-    super(parameters, List.class, TEST_JAR, "backport.ListBackportJava9Main");
+    super(parameters, List.class, TEST_JAR, TEST_CLASS);
     // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
     // an actual API level, migrate these tests to ListBackportTest.
 
@@ -41,4 +45,20 @@
     ignoreInvokes("set");
     ignoreInvokes("size");
   }
+
+  @Test
+  public void desugaringApiLevelR() throws Exception {
+    // TODO(154759404): This test should start to fail when testing on an Android R VM.
+    if (parameters.getRuntime().isDex()
+        && parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.Q)) {
+      testForD8()
+          .setMinApi(AndroidApiLevel.R)
+          .addProgramClasses(MiniAssert.class, IgnoreInvokes.class)
+          .addProgramFiles(TEST_JAR)
+          .setIncludeClassesChecksum(true)
+          .compile()
+          .run(parameters.getRuntime(), TEST_CLASS)
+          .assertFailureWithErrorThatMatches(containsString("java.lang.NoSuchMethodError"));
+    }
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/MapBackportJava9Test.java b/src/test/java/com/android/tools/r8/desugar/backports/MapBackportJava9Test.java
index fb39b49..27cb824 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/MapBackportJava9Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/MapBackportJava9Test.java
@@ -4,18 +4,21 @@
 
 package com.android.tools.r8.desugar.backports;
 
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+import static org.hamcrest.CoreMatchers.containsString;
+
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestRuntime.CfVm;
 import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Map;
+import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
 
-import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
-
 @RunWith(Parameterized.class)
 public class MapBackportJava9Test extends AbstractBackportTest {
   @Parameters(name = "{0}")
@@ -29,9 +32,10 @@
 
   private static final Path TEST_JAR =
       Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
+  private static final String TEST_CLASS = "backport.MapBackportJava9Main";
 
   public MapBackportJava9Test(TestParameters parameters) {
-    super(parameters, Map.class, TEST_JAR, "backport.MapBackportJava9Main");
+    super(parameters, Map.class, TEST_JAR, TEST_CLASS);
     // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
     // an actual API level, migrate these tests to MapBackportTest.
 
@@ -41,4 +45,20 @@
     ignoreInvokes("put");
     ignoreInvokes("size");
   }
+
+  @Test
+  public void desugaringApiLevelR() throws Exception {
+    // TODO(154759404): This test should start to fail when testing on an Android R VM.
+    if (parameters.getRuntime().isDex()
+        && parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.Q)) {
+      testForD8()
+          .setMinApi(AndroidApiLevel.R)
+          .addProgramClasses(MiniAssert.class, IgnoreInvokes.class)
+          .addProgramFiles(TEST_JAR)
+          .setIncludeClassesChecksum(true)
+          .compile()
+          .run(parameters.getRuntime(), TEST_CLASS)
+          .assertFailureWithErrorThatMatches(containsString("java.lang.NoSuchMethodError"));
+    }
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/NoBackportForAndroidPlatform.java b/src/test/java/com/android/tools/r8/desugar/backports/NoBackportForAndroidPlatform.java
deleted file mode 100644
index 47081ab..0000000
--- a/src/test/java/com/android/tools/r8/desugar/backports/NoBackportForAndroidPlatform.java
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-package com.android.tools.r8.desugar.backports;
-
-import static org.hamcrest.core.StringContains.containsString;
-
-import com.android.tools.r8.TestBase;
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.utils.AndroidApiLevel;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-
-@RunWith(Parameterized.class)
-public class NoBackportForAndroidPlatform extends TestBase implements Opcodes {
-
-  private final TestParameters parameters;
-
-  @Parameterized.Parameters(name = "{0}")
-  public static TestParametersCollection data() {
-    // The use of high API level will produce dex files with high DEX version, so only run on high
-    // API level VMs.
-    return getTestParameters()
-        .withDexRuntimes()
-        .withApiLevelsStartingAtIncluding(AndroidApiLevel.P)
-        .build();
-  }
-
-  public NoBackportForAndroidPlatform(TestParameters parameters) {
-    this.parameters = parameters;
-  }
-
-  @Test
-  public void backportSucceedsOnSupportedApiLevel() throws Exception {
-    testForD8()
-        .addProgramClassFileData(mainWithMathMultiplyExactLongInt())
-        .setMinApi(AndroidApiLevel.B)
-        .run(parameters.getRuntime(), "Test")
-        .assertSuccessWithOutputLines("4");
-  }
-
-  @Test
-  public void warningForNonPlatformBuild() throws Exception {
-    testForD8()
-        .addProgramClassFileData(mainWithMathMultiplyExactLongInt())
-        .setMinApi(30)
-        .compile()
-        .assertOnlyWarnings()
-        .assertWarningMessageThatMatches(
-            containsString("An API level of 30 is not supported by this compiler"))
-        .run(parameters.getRuntime(), "Test")
-        .assertFailureWithErrorThatMatches(
-            containsString("java.lang.NoSuchMethodError: No static method multiplyExact(JI)J"));
-  }
-
-  @Test
-  public void noWarningForPlatformBuild() throws Exception {
-    testForD8()
-        .addProgramClassFileData(mainWithMathMultiplyExactLongInt())
-        .setMinApi(AndroidApiLevel.magicApiLevelUsedByAndroidPlatformBuild)
-        .run(parameters.getRuntime(), "Test")
-        .assertFailureWithErrorThatMatches(
-            containsString("java.lang.NoSuchMethodError: No static method multiplyExact(JI)J"));
-  }
-
-  // Code for:
-  //
-  // class Test {
-  //   public static void main(String[] args) {
-  //     // Call Math.multiplyExact(long, int), which is not in Android Q.
-  //     System.out.println(Math.multiplyExact(2L, 2));
-  //   }
-  // }
-  //
-  private byte[] mainWithMathMultiplyExactLongInt() {
-
-    ClassWriter classWriter = new ClassWriter(0);
-    MethodVisitor methodVisitor;
-
-    classWriter.visit(V1_8, ACC_SUPER, "Test", null, "java/lang/Object", null);
-
-    classWriter.visitSource("Test.java", null);
-
-    {
-      methodVisitor = classWriter.visitMethod(0, "<init>", "()V", null, null);
-      methodVisitor.visitCode();
-      Label label0 = new Label();
-      methodVisitor.visitLabel(label0);
-      methodVisitor.visitLineNumber(1, label0);
-      methodVisitor.visitVarInsn(ALOAD, 0);
-      methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
-      methodVisitor.visitInsn(RETURN);
-      methodVisitor.visitMaxs(1, 1);
-      methodVisitor.visitEnd();
-    }
-    {
-      methodVisitor =
-          classWriter.visitMethod(
-              ACC_PUBLIC | ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
-      methodVisitor.visitCode();
-      Label label0 = new Label();
-      methodVisitor.visitLabel(label0);
-      methodVisitor.visitLineNumber(3, label0);
-      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
-      methodVisitor.visitLdcInsn(Long.valueOf(2L));
-      methodVisitor.visitLdcInsn(Integer.valueOf(2));
-      methodVisitor.visitMethodInsn(
-          INVOKESTATIC, "java/lang/Math", "multiplyExact", "(JI)J", false);
-      methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(J)V", false);
-      Label label1 = new Label();
-      methodVisitor.visitLabel(label1);
-      methodVisitor.visitLineNumber(4, label1);
-      methodVisitor.visitInsn(RETURN);
-      methodVisitor.visitMaxs(5, 1);
-      methodVisitor.visitEnd();
-    }
-    classWriter.visitEnd();
-
-    return classWriter.toByteArray();
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/ObjectsBackportJava9Test.java b/src/test/java/com/android/tools/r8/desugar/backports/ObjectsBackportJava9Test.java
index ef8b990..09aef1e 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/ObjectsBackportJava9Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/ObjectsBackportJava9Test.java
@@ -4,17 +4,20 @@
 
 package com.android.tools.r8.desugar.backports;
 
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+import static org.hamcrest.CoreMatchers.containsString;
+
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestRuntime.CfVm;
 import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
 
-import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
-
 @RunWith(Parameterized.class)
 public final class ObjectsBackportJava9Test extends AbstractBackportTest {
   @Parameters(name = "{0}")
@@ -28,10 +31,27 @@
 
   private static final Path TEST_JAR =
       Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
+  private static final String TEST_CLASS = "backport.ObjectsBackportJava9Main";
 
   public ObjectsBackportJava9Test(TestParameters parameters) {
-    super(parameters, Short.class, TEST_JAR, "backport.ObjectsBackportJava9Main");
+    super(parameters, Short.class, TEST_JAR, TEST_CLASS);
     // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
     // an actual API level, migrate these tests to ObjectsBackportTest.
   }
+
+  @Test
+  public void desugaringApiLevelR() throws Exception {
+    // TODO(154759404): This test should start to fail when testing on an Android R VM.
+    if (parameters.getRuntime().isDex()
+        && parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.Q)) {
+      testForD8()
+          .setMinApi(AndroidApiLevel.R)
+          .addProgramClasses(MiniAssert.class, IgnoreInvokes.class)
+          .addProgramFiles(TEST_JAR)
+          .setIncludeClassesChecksum(true)
+          .compile()
+          .run(parameters.getRuntime(), TEST_CLASS)
+          .assertFailureWithErrorThatMatches(containsString("java.lang.NoSuchMethodError"));
+    }
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/SetBackportJava9Test.java b/src/test/java/com/android/tools/r8/desugar/backports/SetBackportJava9Test.java
index 6947ff2..408b203 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/SetBackportJava9Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/SetBackportJava9Test.java
@@ -4,18 +4,21 @@
 
 package com.android.tools.r8.desugar.backports;
 
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+import static org.hamcrest.CoreMatchers.containsString;
+
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestRuntime.CfVm;
 import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Set;
+import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
 
-import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
-
 @RunWith(Parameterized.class)
 public class SetBackportJava9Test extends AbstractBackportTest {
   @Parameters(name = "{0}")
@@ -29,9 +32,10 @@
 
   private static final Path TEST_JAR =
       Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
+  private static final String TEST_CLASS = "backport.SetBackportJava9Main";
 
   public SetBackportJava9Test(TestParameters parameters) {
-    super(parameters, Set.class, TEST_JAR, "backport.SetBackportJava9Main");
+    super(parameters, Set.class, TEST_JAR, TEST_CLASS);
     // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
     // an actual API level, migrate these tests to SetBackportTest.
 
@@ -40,4 +44,20 @@
     ignoreInvokes("contains");
     ignoreInvokes("size");
   }
+
+  @Test
+  public void desugaringApiLevelR() throws Exception {
+    // TODO(154759404): This test should start to fail when testing on an Android R VM.
+    if (parameters.getRuntime().isDex()
+        && parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.Q)) {
+      testForD8()
+          .setMinApi(AndroidApiLevel.R)
+          .addProgramClasses(MiniAssert.class, IgnoreInvokes.class)
+          .addProgramFiles(TEST_JAR)
+          .setIncludeClassesChecksum(true)
+          .compile()
+          .run(parameters.getRuntime(), TEST_CLASS)
+          .assertFailureWithErrorThatMatches(containsString("java.lang.NoSuchMethodError"));
+    }
+  }
 }