Reland "Enable maintain_prefix for function"

This reverts commit cf1e8d417680278fae15d4c66dc03e2031871f22.

Reland "Move desugared lib test method"

This reverts commit 06f3809eac0750754bf5d4a86b710417f406d107.

Change-Id: I8d2422029b1d1a6ea3beafedb500e66c7553cb0b
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs.json b/src/library_desugar/jdk11/desugar_jdk_libs.json
index 238f3ee..ef9b604 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs.json
@@ -52,10 +52,10 @@
         "java.util.concurrent.ConcurrentHashMap": "j$.util.concurrent.ConcurrentHashMap",
         "java.util.concurrent.ThreadLocalRandom": "j$.util.concurrent.ThreadLocalRandom",
         "java.util.concurrent.atomic.DesugarAtomic": "j$.util.concurrent.atomic.DesugarAtomic",
-        "java.util.function.": "j$.util.function.",
         "java.util.stream.": "j$.util.stream."
       },
       "maintain_prefix": [
+        "java.util.function.",
         "java.io.UncheckedIOException"
       ],
       "emulate_interface": {
@@ -266,6 +266,7 @@
     "-keepclassmembers class j$.util.concurrent.ConcurrentHashMap { private void readObject(java.io.ObjectInputStream); private void writeObject(java.io.ObjectOutputStream); private void readObjectNoData(); private static final java.io.ObjectStreamField[] serialPersistentFields; private static final long serialVersionUID;}",
     "-keepclassmembers class j$.util.concurrent.ConcurrentHashMap$CounterCell { long value; }",
     "-keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); public static final !synthetic <fields>; }",
+    "-keeppackagenames java.**",
     "-keeppackagenames j$.**",
     "-keepclassmembers class j$.util.IntSummaryStatistics { long count; long sum; int min; int max; }",
     "-keepclassmembers class j$.util.LongSummaryStatistics { long count; long sum; long min; long max; }",
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_minimal.json b/src/library_desugar/jdk11/desugar_jdk_libs_minimal.json
index 73fa330..8064ed0 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_minimal.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_minimal.json
@@ -17,6 +17,7 @@
   "library_flags": [],
   "shrinker_config": [
     "-keeppackagenames java.**",
+    "-keeppackagenames j$.**",
     "-keepattributes Signature",
     "-keepattributes EnclosingMethod",
     "-keepattributes InnerClasses"
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_path.json b/src/library_desugar/jdk11/desugar_jdk_libs_path.json
index 03ca930..4f0ec65 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_path.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_path.json
@@ -60,6 +60,48 @@
         "java.nio.channels.CompletionHandler": "j$.nio.channels.CompletionHandler",
         "java.nio.file.": "j$.nio.file."
       },
+      "dont_rewrite_prefix": [
+        "java.nio.file.AccessDeniedException",
+        "java.nio.file.AtomicMoveNotSupportedException",
+        "java.nio.file.ClosedDirectoryStreamException",
+        "java.nio.file.ClosedFileSystemException",
+        "java.nio.file.ClosedWatchServiceException",
+        "java.nio.file.DirectoryIteratorException",
+        "java.nio.file.DirectoryNotEmptyException",
+        "java.nio.file.FileAlreadyExistsException",
+        "java.nio.file.FileSystemAlreadyExistsException",
+        "java.nio.file.FileSystemException",
+        "java.nio.file.FileSystemLoopException",
+        "java.nio.file.FileSystemNotFoundException",
+        "java.nio.file.InvalidPathException",
+        "java.nio.file.NoSuchFileException",
+        "java.nio.file.NotDirectoryException",
+        "java.nio.file.NotLinkException",
+        "java.nio.file.ProviderMismatchException",
+        "java.nio.file.ProviderNotFoundException",
+        "java.nio.file.ReadOnlyFileSystemException"
+      ],
+      "maintain_prefix": [
+        "java.nio.file.AccessDeniedException",
+        "java.nio.file.AtomicMoveNotSupportedException",
+        "java.nio.file.ClosedDirectoryStreamException",
+        "java.nio.file.ClosedFileSystemException",
+        "java.nio.file.ClosedWatchServiceException",
+        "java.nio.file.DirectoryIteratorException",
+        "java.nio.file.DirectoryNotEmptyException",
+        "java.nio.file.FileAlreadyExistsException",
+        "java.nio.file.FileSystemAlreadyExistsException",
+        "java.nio.file.FileSystemException",
+        "java.nio.file.FileSystemLoopException",
+        "java.nio.file.FileSystemNotFoundException",
+        "java.nio.file.InvalidPathException",
+        "java.nio.file.NoSuchFileException",
+        "java.nio.file.NotDirectoryException",
+        "java.nio.file.NotLinkException",
+        "java.nio.file.ProviderMismatchException",
+        "java.nio.file.ProviderNotFoundException",
+        "java.nio.file.ReadOnlyFileSystemException"
+      ],
       "retarget_method_with_emulated_dispatch": {
         "java.nio.file.Path java.io.File#toPath()": "java.io.DesugarFile"
       },
@@ -131,13 +173,13 @@
         "java.util.concurrent.ConcurrentHashMap": "j$.util.concurrent.ConcurrentHashMap",
         "java.util.concurrent.ThreadLocalRandom": "j$.util.concurrent.ThreadLocalRandom",
         "java.util.concurrent.atomic.DesugarAtomic": "j$.util.concurrent.atomic.DesugarAtomic",
-        "java.util.function.": "j$.util.function.",
         "java.util.stream.": "j$.util.stream."
       },
       "dont_rewrite_prefix": [
         "java.nio.channels.FileChannel$MapMode"
       ],
       "maintain_prefix": [
+        "java.util.function.",
         "java.io.UncheckedIOException"
       ],
       "emulate_interface": {
@@ -411,6 +453,7 @@
     "-keepclassmembers class j$.util.concurrent.ConcurrentHashMap { private void readObject(java.io.ObjectInputStream); private void writeObject(java.io.ObjectOutputStream); private void readObjectNoData(); private static final java.io.ObjectStreamField[] serialPersistentFields; private static final long serialVersionUID;}",
     "-keepclassmembers class j$.util.concurrent.ConcurrentHashMap$CounterCell { long value; }",
     "-keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); public static final !synthetic <fields>; }",
+    "-keeppackagenames java.**",
     "-keeppackagenames j$.**",
     "-keepclassmembers class j$.util.IntSummaryStatistics { long count; long sum; int min; int max; }",
     "-keepclassmembers class j$.util.LongSummaryStatistics { long count; long sum; long min; long max; }",
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java
index af2f6f8..473cfda 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java
@@ -125,6 +125,12 @@
       return;
     }
     builder.maintainType(type);
+    // We cannot rely on the synthetic classes being on the same package anyway since the runtime
+    // may use a class from the Android framework which is considered in a different package even
+    // if the package name is identical.
+    // This is required since the Android framework also generates external synthetics for lambdas
+    // that are publicly visible.
+    builder.rewriteDerivedTypeOnly(type, convertJavaNameToDesugaredLibrary(type));
     usedPrefix.add(prefix);
   }
 
diff --git a/src/test/java/com/android/tools/r8/benchmarks/desugaredlib/L8Benchmark.java b/src/test/java/com/android/tools/r8/benchmarks/desugaredlib/L8Benchmark.java
index 147d601..46f8916 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/desugaredlib/L8Benchmark.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/desugaredlib/L8Benchmark.java
@@ -64,6 +64,7 @@
             ImmutableSet.of(undesugarJdkLib),
             Paths.get("src/library_desugar/jdk11/desugar_jdk_libs.json"),
             ImmutableSet.of(androidJar.getRoot(environment).resolve("android.jar")),
+            LibraryDesugaringSpecification.JDK11_DESCRIPTOR,
             "");
     runner(environment.getConfig())
         .setWarmupIterations(1)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionTest.java
index 4681e27..6b61085 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionTest.java
@@ -68,7 +68,7 @@
   }
 
   private void assertResultCorrect(String stdOut) {
-    if (requiresEmulatedInterfaceCoreLibDesugaring(parameters)
+    if (libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters)
         && !compilationSpecification.isL8Shrink()) {
       // When shrinking the class names are not printed correctly anymore due to minification.
       // Expected output is emulated interfaces expected output.
@@ -81,8 +81,7 @@
       return;
     }
     MethodSubject direct = inspector.clazz(Executor.class).uniqueMethodWithName("directTypes");
-    System.out.println(direct);
-    if (requiresEmulatedInterfaceCoreLibDesugaring(parameters)) {
+    if (libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters)) {
       assertTrue(
           direct
               .streamInstructions()
@@ -97,7 +96,7 @@
     }
     MethodSubject inherited =
         inspector.clazz(Executor.class).uniqueMethodWithName("inheritedTypes");
-    if (!requiresEmulatedInterfaceCoreLibDesugaring(parameters)) {
+    if (!libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters)) {
       assertTrue(
           inherited.streamInstructions().noneMatch(instr -> instr.toString().contains("$-EL")));
       return;
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DateTimeFormatterTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DateTimeFormatterTest.java
index 8f725ba..16021f7 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DateTimeFormatterTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DateTimeFormatterTest.java
@@ -5,7 +5,6 @@
 package com.android.tools.r8.desugar.desugaredlibrary;
 
 import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.DEFAULT_SPECIFICATIONS;
-import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK8;
 import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.getJdk8Jdk11;
 
 import com.android.tools.r8.SingleTestRunResult;
@@ -61,7 +60,7 @@
             .addKeepMainRule(TestClass.class)
             .run(parameters.getRuntime(), TestClass.class)
             .assertSuccess();
-    if (requiresTimeDesugaring(parameters, libraryDesugaringSpecification != JDK8)) {
+    if (libraryDesugaringSpecification.hasTimeDesugaring(parameters)) {
       run.assertSuccessWithOutput(expectedOutputDesugaredLib);
     } else {
       run.assertSuccessWithOutput(expectedOutput);
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredGenericSignatureTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredGenericSignatureTest.java
index 02e844e..7ba2614 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredGenericSignatureTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredGenericSignatureTest.java
@@ -75,7 +75,7 @@
   }
 
   private void checkRewrittenSignature(CodeInspector inspector) {
-    if (!requiresEmulatedInterfaceCoreLibDesugaring(parameters)) {
+    if (!libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters)) {
       return;
     }
     ClassSubject javaTimeBox = inspector.clazz(JavaTimeDateBox.class);
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryContentTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryContentTest.java
index 716e073..d17c851 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryContentTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryContentTest.java
@@ -61,9 +61,7 @@
 
   @Test
   public void testDesugaredLibraryContent() throws Exception {
-    Assume.assumeTrue(
-        requiresAnyCoreLibDesugaring(
-            parameters.getApiLevel(), libraryDesugaringSpecification != JDK8));
+    Assume.assumeTrue(libraryDesugaringSpecification.hasAnyDesugaring(parameters));
     testForL8(parameters.getApiLevel())
         .apply(libraryDesugaringSpecification::configureL8TestBuilder)
         .compile()
@@ -72,9 +70,7 @@
 
   @Test
   public void testDesugaredLibraryContentWithCoreLambdaStubsAsProgram() throws Exception {
-    Assume.assumeTrue(
-        requiresAnyCoreLibDesugaring(
-            parameters.getApiLevel(), libraryDesugaringSpecification != JDK8));
+    Assume.assumeTrue(libraryDesugaringSpecification.hasAnyDesugaring(parameters));
     ArrayList<Path> coreLambdaStubs = new ArrayList<>();
     coreLambdaStubs.add(ToolHelper.getCoreLambdaStubs());
     testForL8(parameters.getApiLevel())
@@ -86,9 +82,7 @@
 
   @Test
   public void testDesugaredLibraryContentWithCoreLambdaStubsAsLibrary() throws Exception {
-    Assume.assumeTrue(
-        requiresAnyCoreLibDesugaring(
-            parameters.getApiLevel(), libraryDesugaringSpecification != JDK8));
+    Assume.assumeTrue(libraryDesugaringSpecification.hasAnyDesugaring(parameters));
     testForL8(parameters.getApiLevel())
         .apply(libraryDesugaringSpecification::configureL8TestBuilder)
         .addLibraryFiles(ToolHelper.getCoreLambdaStubs())
@@ -122,7 +116,9 @@
       return;
     }
     assertThat(inspector.clazz("j$.util.Optional"), isPresent());
-    assertThat(inspector.clazz("j$.util.function.Function"), isPresent());
+    if (libraryDesugaringSpecification.hasJDollarFunction(parameters)) {
+      assertThat(inspector.clazz("j$.util.function.Function"), isPresent());
+    }
     if (parameters.getApiLevel().isLessThan(AndroidApiLevel.K)) {
       inspector.forAllClasses(clazz -> clazz.forAllMethods(this::assertNoSupressedInvocations));
     }
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryDeterminismTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryDeterminismTest.java
index 810f1d0..8245517 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryDeterminismTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryDeterminismTest.java
@@ -4,7 +4,6 @@
 package com.android.tools.r8.desugar.desugaredlibrary;
 
 import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.D8_L8DEBUG;
-import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK8;
 import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.getJdk8Jdk11;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -61,9 +60,7 @@
     Set<String> contextsRoundOne = ConcurrentHashMap.newKeySet();
     Set<String> contextsRoundTwo = ConcurrentHashMap.newKeySet();
     Path determinismLogDir = temp.newFolder().toPath();
-    Assume.assumeTrue(
-        requiresAnyCoreLibDesugaring(
-            parameters.getApiLevel(), libraryDesugaringSpecification != JDK8));
+    Assume.assumeTrue(libraryDesugaringSpecification.hasAnyDesugaring(parameters));
 
     Path libDexFile1 =
         testForL8(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryDumpInputsTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryDumpInputsTest.java
index 4a9b0a0..6200ec5 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryDumpInputsTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryDumpInputsTest.java
@@ -4,7 +4,6 @@
 package com.android.tools.r8.desugar.desugaredlibrary;
 
 import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.DEFAULT_SPECIFICATIONS;
-import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK8;
 import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.getJdk8Jdk11;
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertEquals;
@@ -54,9 +53,7 @@
 
   @Test
   public void testDumpToDirectory() throws Exception {
-    Assume.assumeTrue(
-        requiresAnyCoreLibDesugaring(
-            parameters.getApiLevel(), libraryDesugaringSpecification != JDK8));
+    Assume.assumeTrue(libraryDesugaringSpecification.hasAnyDesugaring(parameters));
     Path dumpDir = temp.newFolder().toPath();
     testForDesugaredLibrary(parameters, libraryDesugaringSpecification, compilationSpecification)
         .addProgramClasses(TestClass.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryInvalidTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryInvalidTest.java
index d31aa91..6a169bf 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryInvalidTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryInvalidTest.java
@@ -39,13 +39,15 @@
             "JDK8_INVALID_LIB",
             DESUGARED_JDK_8_LIB_JAR,
             "desugar_jdk_libs.json",
-            AndroidApiLevel.L);
+            AndroidApiLevel.L,
+            LibraryDesugaringSpecification.JDK8_DESCRIPTOR);
     LibraryDesugaringSpecification jdk11InvalidLib =
         new LibraryDesugaringSpecification(
             "JDK11_INVALID_LIB",
             ToolHelper.getUndesugaredJdk11LibJarForTesting(),
             "jdk11/desugar_jdk_libs.json",
-            AndroidApiLevel.L);
+            AndroidApiLevel.L,
+            LibraryDesugaringSpecification.JDK11_DESCRIPTOR);
     return buildParameters(
         getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build(),
         ImmutableList.of(jdk8InvalidLib, jdk11InvalidLib),
@@ -63,9 +65,7 @@
 
   @Test
   public void testInvalidLibrary() throws IOException {
-    Assume.assumeTrue(
-        requiresAnyCoreLibDesugaring(
-            parameters.getApiLevel(), !libraryDesugaringSpecification.toString().contains("JDK8")));
+    Assume.assumeTrue(libraryDesugaringSpecification.hasAnyDesugaring(parameters));
     DesugaredLibraryTestBuilder<?> testBuilder =
         testForDesugaredLibrary(
                 parameters, libraryDesugaringSpecification, compilationSpecification)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryMismatchTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryMismatchTest.java
index 1f4d9c1..71026ba 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryMismatchTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryMismatchTest.java
@@ -7,7 +7,6 @@
 import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
 import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
 import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.D8_L8DEBUG;
-import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK8;
 import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.getJdk8Jdk11;
 import static org.hamcrest.CoreMatchers.allOf;
 import static org.hamcrest.CoreMatchers.containsString;
@@ -76,8 +75,7 @@
           .addProgramClasses(TestRunner.class)
           .compileWithExpectedDiagnostics(
               diagnostics -> {
-                if (requiresAnyCoreLibDesugaring(
-                    parameters.getApiLevel(), libraryDesugaringSpecification != JDK8)) {
+                if (libraryDesugaringSpecification.hasAnyDesugaring(parameters)) {
                   diagnostics.assertNoInfos();
                   diagnostics.assertAllWarningsMatch(
                       diagnosticMessage(
@@ -158,8 +156,7 @@
           .setMinApi(parameters.getApiLevel())
           .compileWithExpectedDiagnostics(
               diagnostics -> {
-                if (requiresAnyCoreLibDesugaring(
-                    parameters.getApiLevel(), libraryDesugaringSpecification != JDK8)) {
+                if (libraryDesugaringSpecification.hasAnyDesugaring(parameters)) {
                   diagnostics.assertOnlyErrors();
                   diagnostics.assertErrorsMatch(
                       diagnosticType(DesugaredLibraryMismatchDiagnostic.class));
@@ -196,8 +193,7 @@
           .setMinApi(parameters.getApiLevel())
           .compileWithExpectedDiagnostics(
               diagnostics -> {
-                if (requiresAnyCoreLibDesugaring(
-                    parameters.getApiLevel(), libraryDesugaringSpecification != JDK8)) {
+                if (libraryDesugaringSpecification.hasAnyDesugaring(parameters)) {
                   diagnostics.assertOnlyErrors();
                   diagnostics.assertErrorsMatch(
                       diagnosticType(DesugaredLibraryMismatchDiagnostic.class));
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
index 4c05352..4f1b017 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
@@ -45,20 +45,6 @@
     throw new Error("Unsupported conversion parameters");
   }
 
-  protected boolean requiresEmulatedInterfaceCoreLibDesugaring(TestParameters parameters) {
-    return parameters.getApiLevel().isLessThan(apiLevelWithDefaultInterfaceMethodsSupport());
-  }
-
-  protected boolean requiresTimeDesugaring(TestParameters parameters, boolean isJDK11) {
-    return parameters.getApiLevel().getLevel()
-        < (isJDK11 ? AndroidApiLevel.S.getLevel() : AndroidApiLevel.O.getLevel());
-  }
-
-  protected boolean requiresAnyCoreLibDesugaring(AndroidApiLevel apiLevel, boolean isJDK11) {
-    return apiLevel.getLevel()
-        <= (isJDK11 ? AndroidApiLevel.R.getLevel() : AndroidApiLevel.N_MR1.getLevel());
-  }
-
   protected DesugaredLibraryTestBuilder<?> testForDesugaredLibrary(
       TestParameters parameters,
       LibraryDesugaringSpecification libraryDesugaringSpecification,
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLocalDateReflectedTypePassedToStaticType.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLocalDateReflectedTypePassedToStaticType.java
index 2505e7f..c4af0ff 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLocalDateReflectedTypePassedToStaticType.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLocalDateReflectedTypePassedToStaticType.java
@@ -5,7 +5,6 @@
 package com.android.tools.r8.desugar.desugaredlibrary;
 
 import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.DEFAULT_SPECIFICATIONS;
-import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK8;
 import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.getJdk8Jdk11;
 import static org.hamcrest.core.StringContains.containsString;
 
@@ -56,7 +55,7 @@
             .addKeepMainRule(Main.class)
             .run(parameters.getRuntime(), Main.class);
     if (compilationSpecification.isL8Shrink()
-        && requiresTimeDesugaring(parameters, libraryDesugaringSpecification != JDK8)) {
+        && libraryDesugaringSpecification.hasTimeDesugaring(parameters)) {
       run.assertFailureWithErrorThatMatches(containsString("java.lang.NoSuchMethodException"));
     } else {
       run.assertSuccessWithOutput(EXPECTED);
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredReflectedDesugaredTypePassedToStaticTypeTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredReflectedDesugaredTypePassedToStaticTypeTest.java
index 6c1f23f..4466e5d 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredReflectedDesugaredTypePassedToStaticTypeTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredReflectedDesugaredTypePassedToStaticTypeTest.java
@@ -5,7 +5,6 @@
 package com.android.tools.r8.desugar.desugaredlibrary;
 
 import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.DEFAULT_SPECIFICATIONS;
-import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK8;
 import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.getJdk8Jdk11;
 import static org.hamcrest.core.StringContains.containsString;
 
@@ -55,7 +54,7 @@
             .addInnerClasses(getClass())
             .addKeepMainRule(Main.class)
             .run(parameters.getRuntime(), Main.class);
-    if (!requiresTimeDesugaring(parameters, libraryDesugaringSpecification != JDK8)) {
+    if (!libraryDesugaringSpecification.hasTimeDesugaring(parameters)) {
       runResult.assertFailureWithErrorThatMatches(
           containsString("java.lang.ClassNotFoundException: j$.time.LocalDate"));
     } else {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DontKeepBootstrapClassesTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DontKeepBootstrapClassesTest.java
index 70554a0..542c71e 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DontKeepBootstrapClassesTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DontKeepBootstrapClassesTest.java
@@ -54,10 +54,13 @@
         .compile()
         .inspectKeepRules(
             keepRule -> {
-              if (requiresEmulatedInterfaceCoreLibDesugaring(parameters)) {
+              if (libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters)) {
+                String prefix = libraryDesugaringSpecification.functionPrefix(parameters);
                 assertTrue(
                     keepRule.stream()
-                        .anyMatch(kr -> kr.contains("-keep class j$.util.function.Consumer")));
+                        .anyMatch(
+                            kr ->
+                                kr.contains("-keep class " + prefix + ".util.function.Consumer")));
                 // TODO(b/158635415): Don't generate keep rules targeting items outside desugared
                 // library.
                 assertTrue(keepRule.stream().anyMatch(kr -> kr.contains("-keep class java.util")));
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/EmptyDesugaredLibrary.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/EmptyDesugaredLibrary.java
index f744809..9a5ac53 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/EmptyDesugaredLibrary.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/EmptyDesugaredLibrary.java
@@ -5,7 +5,6 @@
 package com.android.tools.r8.desugar.desugaredlibrary;
 
 import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.D8_L8DEBUG;
-import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK8;
 import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.getJdk8Jdk11;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -75,7 +74,7 @@
   }
 
   private boolean expectsEmptyDesugaredLibrary(AndroidApiLevel apiLevel) {
-    return !requiresAnyCoreLibDesugaring(apiLevel, libraryDesugaringSpecification != JDK8);
+    return !libraryDesugaringSpecification.hasAnyDesugaring(apiLevel);
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/EmulatedInterfacesTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/EmulatedInterfacesTest.java
index 1ca61c5..2a185ea 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/EmulatedInterfacesTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/EmulatedInterfacesTest.java
@@ -59,7 +59,7 @@
 
   @Test
   public void testEmulatedInterface() throws Exception {
-    Assume.assumeTrue(requiresEmulatedInterfaceCoreLibDesugaring(parameters));
+    Assume.assumeTrue(libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters));
     CodeInspector inspector =
         testForL8(parameters.getApiLevel())
             .apply(
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/FeatureSplitTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/FeatureSplitTest.java
index 42ee197..6799d90 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/FeatureSplitTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/FeatureSplitTest.java
@@ -87,10 +87,13 @@
       return;
     }
     // Ensure count, toArray and forEach are kept.
+    String prefix = libraryDesugaringSpecification.functionPrefix(parameters);
     assertTrue(
         keepRules.contains(
             "-keep class j$.lang.Iterable$-EL {\n"
-                + "    void forEach(java.lang.Iterable, j$.util.function.Consumer);"));
+                + "    void forEach(java.lang.Iterable, "
+                + prefix
+                + ".util.function.Consumer);"));
     assertTrue(
         keepRules.contains(
             "-keep class j$.util.stream.Stream {\n"
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/FunctionOnlyTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/FunctionOnlyTest.java
index 12ff1ae..791a6b3 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/FunctionOnlyTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/FunctionOnlyTest.java
@@ -32,7 +32,7 @@
 public class FunctionOnlyTest extends DesugaredLibraryTestBase {
 
   private static final String EXPECTED_RESULT =
-      StringUtils.lines(" true true true", "2", "false", "3", "true", "5", "42.0");
+      StringUtils.lines(" true true true", "2", "false", "3", "true", "5", "42.0", "last");
 
   private final TestParameters parameters;
   private final CompilationSpecification compilationSpecification;
@@ -56,7 +56,7 @@
   }
 
   @Test
-  public void testFunction() throws Exception {
+  public void testFunction() throws Throwable {
     testForDesugaredLibrary(parameters, libraryDesugaringSpecification, compilationSpecification)
         .addInnerClasses(getClass())
         .addKeepMainRule(Executor.class)
@@ -84,6 +84,7 @@
       System.out.println(doublePredicate.test(2.0));
       System.out.println(FunctionClass.extractInt(() -> 5));
       System.out.println(FunctionClass.getDoubleSupplier().get());
+      System.out.println(Function.identity().apply("last"));
     }
 
     static class Object1 {}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IteratorTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IteratorTest.java
index 605854a..9f0f613 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IteratorTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IteratorTest.java
@@ -33,7 +33,6 @@
   private final TestParameters parameters;
   private final LibraryDesugaringSpecification libraryDesugaringSpecification;
   private final CompilationSpecification compilationSpecification;
-  private final boolean canUseDefaultAndStaticInterfaceMethods;
 
   @Parameters(name = "{0}, spec: {1}, {2}")
   public static List<Object[]> data() {
@@ -50,10 +49,6 @@
     this.parameters = parameters;
     this.libraryDesugaringSpecification = libraryDesugaringSpecification;
     this.compilationSpecification = compilationSpecification;
-    this.canUseDefaultAndStaticInterfaceMethods =
-        parameters
-            .getApiLevel()
-            .isGreaterThanOrEqualTo(apiLevelWithDefaultInterfaceMethodsSupport());
   }
 
   @Test
@@ -70,12 +65,12 @@
   private void assertInterface(CodeInspector inspector) {
     ClassSubject clazz = inspector.clazz(MyIterator.class);
     assertEquals(
-        canUseDefaultAndStaticInterfaceMethods ? 0 : 1,
+        libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters) ? 1 : 0,
         clazz.getDexProgramClass().getInterfaces().stream()
             .filter(name -> name.toString().equals("j$.util.Iterator"))
             .count());
     assertEquals(
-        canUseDefaultAndStaticInterfaceMethods ? 1 : 2,
+        libraryDesugaringSpecification.hasJDollarFunction(parameters) ? 2 : 1,
         clazz.getDexProgramClass().allMethodsSorted().stream()
             .filter(m -> m.getReference().getName().toString().equals("forEachRemaining"))
             .count());
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/J$ExtensionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/J$ExtensionTest.java
index dd036e2..7d4a771 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/J$ExtensionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/J$ExtensionTest.java
@@ -5,7 +5,6 @@
 package com.android.tools.r8.desugar.desugaredlibrary;
 
 import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.D8_L8DEBUG;
-import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK8;
 import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.getJdk8Jdk11;
 import static junit.framework.TestCase.assertTrue;
 
@@ -152,7 +151,7 @@
   @Test
   public void testJ$ExtensionDesugaring() throws Throwable {
     Assume.assumeFalse(parameters.isCfRuntime());
-    Assume.assumeTrue(requiresTimeDesugaring(parameters, libraryDesugaringSpecification != JDK8));
+    Assume.assumeTrue(libraryDesugaringSpecification.hasTimeDesugaring(parameters));
     String stdErr =
         testForDesugaredLibrary(
                 parameters, libraryDesugaringSpecification, compilationSpecification)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java
index 4b7a485..8d8f669 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java
@@ -5,7 +5,6 @@
 package com.android.tools.r8.desugar.desugaredlibrary;
 
 import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.SPECIFICATIONS_WITH_CF2CF;
-import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK8;
 import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.getJdk8Jdk11;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static org.hamcrest.CoreMatchers.not;
@@ -98,7 +97,7 @@
     Set<String> expectedCatchGuards;
     Set<String> expectedCheckCastType;
     String expectedInstanceOfTypes;
-    if (!requiresTimeDesugaring(parameters, libraryDesugaringSpecification != JDK8)) {
+    if (!libraryDesugaringSpecification.hasTimeDesugaring(parameters)) {
       expectedInvokeHolders =
           SetUtils.newHashSet("java.time.Clock", "java.time.LocalDate", "java.time.ZoneId");
       if (!isR8) {
@@ -151,7 +150,7 @@
             .isGreaterThanOrEqualTo(TestBase.apiLevelWithDefaultInterfaceMethodsSupport())
         && isR8) {
       String holder =
-          requiresTimeDesugaring(parameters, libraryDesugaringSpecification != JDK8)
+          libraryDesugaringSpecification.hasTimeDesugaring(parameters)
               ? "j$.time.temporal.TemporalAccessor"
               : "java.time.temporal.TemporalAccessor";
       assertThat(
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilFunctionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilFunctionTest.java
index d14b845..2f146bb 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilFunctionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilFunctionTest.java
@@ -57,13 +57,17 @@
   }
 
   private void checkRewrittenArguments(CodeInspector inspector) {
-    if (!requiresEmulatedInterfaceCoreLibDesugaring(parameters)) {
+    if (!libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters)) {
       return;
     }
     ClassSubject classSubject = inspector.clazz(TestClass.class);
     assertThat(classSubject, isPresent());
+    String function =
+        libraryDesugaringSpecification.hasJDollarFunction(parameters)
+            ? "j$.util.function.Function"
+            : "java.util.function.Function";
     assertEquals(
-        "j$.util.function.Function",
+        function,
         classSubject
             .uniqueMethodWithName("applyFunction")
             .getMethod()
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilOptionalTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilOptionalTest.java
index 7c98967..23a13b6 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilOptionalTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilOptionalTest.java
@@ -58,7 +58,7 @@
   }
 
   private void checkRewrittenInvokes(CodeInspector inspector) {
-    if (!requiresEmulatedInterfaceCoreLibDesugaring(parameters)) {
+    if (!libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters)) {
       return;
     }
     ClassSubject classSubject = inspector.clazz(TestClass.class);
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LibraryEmptySubclassInterfaceTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LibraryEmptySubclassInterfaceTest.java
index 0b048b4..fe5364c 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LibraryEmptySubclassInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LibraryEmptySubclassInterfaceTest.java
@@ -56,7 +56,7 @@
   }
 
   private void assertExpectedKeepRules(List<String> keepRuleList) {
-    if (!requiresEmulatedInterfaceCoreLibDesugaring(parameters)) {
+    if (!libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters)) {
       return;
     }
     StringBuilder keepRules = new StringBuilder();
@@ -68,7 +68,7 @@
   }
 
   private String getResult() {
-    return requiresEmulatedInterfaceCoreLibDesugaring(parameters)
+    return libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters)
         ? "class j$.util.concurrent.ConcurrentHashMap"
         : "class java.util.concurrent.ConcurrentHashMap";
   }
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingWithDesugaredLibraryTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingWithDesugaredLibraryTest.java
index ca676d3..be8001a 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingWithDesugaredLibraryTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingWithDesugaredLibraryTest.java
@@ -11,7 +11,6 @@
 import static com.android.tools.r8.MarkerMatcher.markerIsDesugared;
 import static com.android.tools.r8.MarkerMatcher.markerMinApi;
 import static com.android.tools.r8.MarkerMatcher.markerTool;
-import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK8;
 import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.getJdk8Jdk11;
 import static org.hamcrest.CoreMatchers.allOf;
 import static org.hamcrest.CoreMatchers.not;
@@ -135,8 +134,7 @@
             markerTool(Tool.D8),
             markerIsDesugared(),
             markerHasDesugaredLibraryIdentifier(
-                requiresAnyCoreLibDesugaring(
-                    parameters.getApiLevel(), libraryDesugaringSpecification != JDK8)));
+                libraryDesugaringSpecification.hasAnyDesugaring(parameters)));
     assertMarkersMatch(
         ExtractMarker.extractMarkerFromDexFile(app), ImmutableList.of(libraryMatcher, d8Matcher));
   }
@@ -222,8 +220,7 @@
   }
 
   private boolean someLibraryDesugaringRequired() {
-    return requiresAnyCoreLibDesugaring(
-        parameters.getApiLevel(), libraryDesugaringSpecification != JDK8);
+    return libraryDesugaringSpecification.hasAnyDesugaring(parameters);
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MonthTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MonthTest.java
index 943c7a9..0fbcc8c 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MonthTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MonthTest.java
@@ -5,7 +5,6 @@
 package com.android.tools.r8.desugar.desugaredlibrary;
 
 import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.DEFAULT_SPECIFICATIONS;
-import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK8;
 import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.getJdk8Jdk11;
 
 import com.android.tools.r8.TestParameters;
@@ -57,7 +56,7 @@
       return EXPECTED_JAVA_8_OUTPUT;
     }
     assert parameters.isDexRuntime();
-    if (requiresTimeDesugaring(parameters, libraryDesugaringSpecification != JDK8)) {
+    if (libraryDesugaringSpecification.hasTimeDesugaring(parameters)) {
       return EXPECTED_JAVA_8_OUTPUT;
     }
     return EXPECTED_JAVA_9_OUTPUT;
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NeverMergeCoreLibDesugarClasses.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NeverMergeCoreLibDesugarClasses.java
index 9e8583f..0462bc2 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NeverMergeCoreLibDesugarClasses.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NeverMergeCoreLibDesugarClasses.java
@@ -116,14 +116,17 @@
     Assume.assumeTrue(parameters.getApiLevel().getLevel() < AndroidApiLevel.N.getLevel());
     testForDesugaredLibrary(parameters, libraryDesugaringSpecification, compilationSpecification)
         .addInnerClasses(getClass())
-        .run(parameters.getRuntime(), TestClass.class)
+        .run(
+            parameters.getRuntime(),
+            TestClass.class,
+            libraryDesugaringSpecification.functionPrefix(parameters))
         .assertSuccessWithOutputLines("Hello, world!");
   }
 
   static class TestClass {
 
     public static void main(String[] args) throws Exception {
-      Class.forName("j$.util.function.Function");
+      Class.forName(args[0] + ".util.function.Function");
       System.out.println("Hello, world!");
     }
   }
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NoDesugaredLibraryDexFileTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NoDesugaredLibraryDexFileTest.java
index 5ddc567..a3f36be 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NoDesugaredLibraryDexFileTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NoDesugaredLibraryDexFileTest.java
@@ -52,7 +52,7 @@
 
   @Test
   public void testNoDesugaredLibraryDexFile() throws Throwable {
-    Assume.assumeTrue(requiresEmulatedInterfaceCoreLibDesugaring(parameters));
+    Assume.assumeTrue(libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters));
     testForDesugaredLibrary(parameters, libraryDesugaringSpecification, compilationSpecification)
         .addInnerClasses(getClass())
         .addKeepClassAndMembersRules(Executor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java
index f5717d8..66438e9 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java
@@ -72,13 +72,18 @@
   public static List<Object[]> data() {
     LibraryDesugaringSpecification jdk8MaxCompileSdk =
         new LibraryDesugaringSpecification(
-            "JDK8_MAX", DESUGARED_JDK_8_LIB_JAR, "desugar_jdk_libs.json", AndroidApiLevel.LATEST);
+            "JDK8_MAX",
+            DESUGARED_JDK_8_LIB_JAR,
+            "desugar_jdk_libs.json",
+            AndroidApiLevel.LATEST,
+            LibraryDesugaringSpecification.JDK8_DESCRIPTOR);
     LibraryDesugaringSpecification jdk11MaxCompileSdk =
         new LibraryDesugaringSpecification(
             "JDK11_MAX",
             ToolHelper.getUndesugaredJdk11LibJarForTesting(),
             "jdk11/desugar_jdk_libs.json",
-            AndroidApiLevel.LATEST);
+            AndroidApiLevel.LATEST,
+            LibraryDesugaringSpecification.JDK11_DESCRIPTOR);
     return buildParameters(
         getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build(),
         ImmutableList.of(JDK8, JDK11, jdk8MaxCompileSdk, jdk11MaxCompileSdk),
@@ -188,6 +193,10 @@
         parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N);
     boolean invokeJDollarUtilObjectsWithSupplier =
         libraryDesugarJavaUtilObjects && parameters.getApiLevel().isLessThan(AndroidApiLevel.N);
+    String supplier =
+        libraryDesugaringSpecification.hasJDollarFunction(parameters)
+            ? "j$.util.function.Supplier"
+            : "java.util.function.Supplier";
 
     assertThat(
         testClass.uniqueMethodWithName("objectsCompare"),
@@ -244,14 +253,12 @@
         testClass.uniqueMethodWithName("objectsRequireNonNullWithSupplier"),
         onlyIf(
             invokeJavaUtilObjectsWithSupplier,
-            invokesObjectsRequireNonNullWithSupplier(
-                "java.util.Objects", "java.util.function.Supplier")));
+            invokesObjectsRequireNonNullWithSupplier("java.util.Objects", supplier)));
     assertThat(
         testClass.uniqueMethodWithName("objectsRequireNonNullWithSupplier"),
         onlyIf(
             invokeJDollarUtilObjectsWithSupplier,
-            invokesObjectsRequireNonNullWithSupplier(
-                "j$.util.Objects", "j$.util.function.Supplier")));
+            invokesObjectsRequireNonNullWithSupplier("j$.util.Objects", supplier)));
 
     assertThat(
         testClass.uniqueMethodWithName("objectsToString"),
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramInterfaceWithLibraryMethod.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramInterfaceWithLibraryMethod.java
index 18ccc4e..13074ce 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramInterfaceWithLibraryMethod.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramInterfaceWithLibraryMethod.java
@@ -55,8 +55,8 @@
         .addKeepMainRule(Executor.class)
         .run(parameters.getRuntime(), Executor.class)
         .applyIf(
-            parameters.isDexRuntime()
-                && parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N),
+            !libraryDesugaringSpecification.hasJDollarFunction(parameters)
+                || parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N),
             r -> r.assertSuccessWithOutput(EXPECTED_RESULT),
             r -> {
               if (compilationSpecification.isProgramShrink()) {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java
index 492964e..566b0a0 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java
@@ -56,6 +56,7 @@
                 ToolHelper.getCoreLambdaStubs()),
             JDK8.getSpecification(),
             ImmutableSet.of(ToolHelper.getAndroidJar(AndroidApiLevel.O)),
+            LibraryDesugaringSpecification.JDK8_DESCRIPTOR,
             "");
     LibraryDesugaringSpecification jdk11CoreLambdaStubs =
         new LibraryDesugaringSpecification(
@@ -66,6 +67,7 @@
                 ToolHelper.getCoreLambdaStubs()),
             JDK11.getSpecification(),
             ImmutableSet.of(ToolHelper.getAndroidJar(AndroidApiLevel.R)),
+            LibraryDesugaringSpecification.JDK11_DESCRIPTOR,
             "");
     return buildParameters(
         getTestParameters().withDexRuntimes().withAllApiLevels().build(),
@@ -175,13 +177,15 @@
   }
 
   private void assertGeneratedKeepRulesAreCorrect(String keepRules) {
+
+    String prefix = libraryDesugaringSpecification.functionPrefix(parameters);
     String expectedResult =
         StringUtils.lines(
             "-keep class j$.util.Collection$-EL {",
             "    j$.util.stream.Stream stream(java.util.Collection);",
             "}",
             "-keep class j$.util.Comparator$-CC {",
-            "    java.util.Comparator comparingInt(j$.util.function.ToIntFunction);",
+            "    java.util.Comparator comparingInt(" + prefix + ".util.function.ToIntFunction);",
             "}",
             "-keep class j$.util.DesugarArrays {",
             "    j$.util.Spliterator spliterator(java.lang.Object[]);",
@@ -196,7 +200,7 @@
             "    j$.util.Spliterator spliterator(java.util.Set);",
             "}",
             "-keep class j$.util.Spliterator",
-            "-keep class j$.util.function.ToIntFunction { *; }",
+            "-keep class " + prefix + ".util.function.ToIntFunction { *; }",
             "-keep class j$.util.stream.IntStream$-CC {",
             "    j$.util.stream.IntStream range(int, int);",
             "}",
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SimpleStreamTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SimpleStreamTest.java
index 3cdfedb..78a082c 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SimpleStreamTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SimpleStreamTest.java
@@ -48,7 +48,7 @@
 
   @Test
   public void testSimpleStream() throws Throwable {
-    Assume.assumeTrue(requiresEmulatedInterfaceCoreLibDesugaring(parameters));
+    Assume.assumeTrue(libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters));
     testForDesugaredLibrary(parameters, libraryDesugaringSpecification, compilationSpecification)
         .addInnerClasses(getClass())
         .addKeepMainRule(Executor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SpliteratorTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SpliteratorTest.java
index 7b45541..3839d19 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SpliteratorTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SpliteratorTest.java
@@ -64,7 +64,7 @@
 
   @Test
   public void testSpliterator() throws Throwable {
-    Assume.assumeTrue(requiresEmulatedInterfaceCoreLibDesugaring(parameters));
+    Assume.assumeTrue(libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters));
     testForDesugaredLibrary(parameters, libraryDesugaringSpecification, compilationSpecification)
         .addInnerClasses(getClass())
         .compile()
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/CallBackConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/CallBackConversionTest.java
index 0a65d49..2478d19 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/CallBackConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/CallBackConversionTest.java
@@ -54,6 +54,11 @@
 
   private void assertDuplicatedAPI(CodeInspector i) {
     List<FoundMethodSubject> virtualMethods = i.clazz(Impl.class).virtualMethods();
+    if (!libraryDesugaringSpecification.hasJDollarFunction(parameters)) {
+      // No need to duplicate the API with maintain prefix.
+      assertEquals(1, virtualMethods.size());
+      return;
+    }
     assertEquals(2, virtualMethods.size());
     assertTrue(anyVirtualMethodFirstParameterMatches(virtualMethods, "j$.util.function.Consumer"));
     assertTrue(
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionIntroduceInterfaceMethodTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionIntroduceInterfaceMethodTest.java
index c12c86d..112fd70 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionIntroduceInterfaceMethodTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionIntroduceInterfaceMethodTest.java
@@ -86,7 +86,10 @@
         .inspect(this::assertWrapperMethodsPresent)
         .run(parameters.getRuntime(), Executor.class)
         .assertSuccessWithOutput(
-            supportAllCallbacksFromLibrary ? EXPECTED_RESULT : FAILING_EXPECTED_RESULT);
+            (supportAllCallbacksFromLibrary
+                    || !libraryDesugaringSpecification.hasJDollarFunction(parameters))
+                ? EXPECTED_RESULT
+                : FAILING_EXPECTED_RESULT);
   }
 
   private void assertDoubleForEach(CodeInspector inspector) {
@@ -103,7 +106,10 @@
             .collect(toSingle());
     assertEquals(
         "Missing duplicated forEach",
-        supportAllCallbacksFromLibrary ? 2 : 1,
+        supportAllCallbacksFromLibrary
+                && libraryDesugaringSpecification.hasJDollarFunction(parameters)
+            ? 2
+            : 1,
         IterableUtils.size(
             myCollection
                 .getDexProgramClass()
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionsPresentTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionsPresentTest.java
index 69b83bf..42fbe70 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionsPresentTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionsPresentTest.java
@@ -4,7 +4,6 @@
 
 package com.android.tools.r8.desugar.desugaredlibrary.conversiontests;
 
-import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK8;
 import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.getJdk8Jdk11;
 import static junit.framework.TestCase.assertEquals;
 import static junit.framework.TestCase.assertTrue;
@@ -58,14 +57,14 @@
                     c.getOriginalName().contains(".util.")
                         || c.getOriginalName().contains(".time."))
             .collect(Collectors.toList());
-    if (requiresEmulatedInterfaceCoreLibDesugaring(parameters)) {
+    if (libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters)) {
       assertEquals(5, conversionsClasses.size());
       assertTrue(inspector.clazz("j$.util.OptionalConversions").isPresent());
       assertTrue(inspector.clazz("j$.time.TimeConversions").isPresent());
       assertTrue(inspector.clazz("j$.util.LongSummaryStatisticsConversions").isPresent());
       assertTrue(inspector.clazz("j$.util.IntSummaryStatisticsConversions").isPresent());
       assertTrue(inspector.clazz("j$.util.DoubleSummaryStatisticsConversions").isPresent());
-    } else if (requiresTimeDesugaring(parameters, libraryDesugaringSpecification != JDK8)) {
+    } else if (libraryDesugaringSpecification.hasTimeDesugaring(parameters)) {
       assertEquals(1, conversionsClasses.size());
       assertTrue(inspector.clazz("j$.time.TimeConversions").isPresent());
     } else {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIDesugaredLibTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIDesugaredLibTest.java
index 91850cf..59a6a1b 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIDesugaredLibTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIDesugaredLibTest.java
@@ -80,10 +80,10 @@
 
   private void assertDupMethod(CodeInspector inspector) {
     ClassSubject clazz = inspector.clazz("j$.util.concurrent.ConcurrentHashMap");
+    boolean duplicate =
+        supportCallbacks && libraryDesugaringSpecification.hasJDollarFunction(parameters);
     int numForEachMethods =
-        libraryDesugaringSpecification == JDK8
-            ? supportCallbacks ? 2 : 1
-            : supportCallbacks ? 4 : 3;
+        libraryDesugaringSpecification == JDK8 ? duplicate ? 2 : 1 : duplicate ? 4 : 3;
     assertEquals(
         numForEachMethods,
         clazz.virtualMethods().stream().filter(m -> m.getOriginalName().equals("forEach")).count());
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIProgramTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIProgramTest.java
index 3e547fa..7c34edc 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIProgramTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIProgramTest.java
@@ -67,7 +67,7 @@
 
   private void assertDupMethod(CodeInspector i) {
     assertEquals(
-        2,
+        libraryDesugaringSpecification.hasJDollarFunction(parameters) ? 2 : 1,
         i.clazz(MyMap.class).virtualMethods().stream()
             .filter(m -> m.getOriginalName().equals("forEach"))
             .count());
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/WrapperEqualityTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/WrapperEqualityTest.java
index 1353145..77b7738 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/WrapperEqualityTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/WrapperEqualityTest.java
@@ -71,7 +71,10 @@
         .addKeepMainRule(Executor.class)
         .compile()
         .run(parameters.getRuntime(), Executor.class)
-        .assertSuccessWithOutput(DESUGARED_LIBRARY_EXPECTED_RESULT);
+        .assertSuccessWithOutput(
+            libraryDesugaringSpecification.hasJDollarFunction(parameters)
+                ? DESUGARED_LIBRARY_EXPECTED_RESULT
+                : EXPECTED_RESULT);
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonAllMapsTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonAllMapsTest.java
index f66418a..e7421fe 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonAllMapsTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonAllMapsTest.java
@@ -48,7 +48,7 @@
 
   @Test
   public void testGsonAllMaps() throws Exception {
-    Assume.assumeTrue(requiresEmulatedInterfaceCoreLibDesugaring(parameters));
+    Assume.assumeTrue(libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters));
     testForDesugaredLibrary(parameters, libraryDesugaringSpecification, compilationSpecification)
         .addProgramClassesAndInnerClasses(AllMapsTestClass.class)
         .addProgramFiles(GSON_2_8_1_JAR)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonEnumTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonEnumTest.java
index 09f6bcf..716e3da 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonEnumTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonEnumTest.java
@@ -49,7 +49,7 @@
 
   @Test
   public void testEnum() throws Exception {
-    Assume.assumeTrue(requiresEmulatedInterfaceCoreLibDesugaring(parameters));
+    Assume.assumeTrue(libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters));
     testForDesugaredLibrary(parameters, libraryDesugaringSpecification, compilationSpecification)
         .addInnerClasses(GsonEnumTest.class)
         .addKeepMainRule(Executor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonOptionalTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonOptionalTest.java
index 5c033ce..d42473c 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonOptionalTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonOptionalTest.java
@@ -45,7 +45,7 @@
 
   @Test
   public void testGson() throws Exception {
-    Assume.assumeTrue(requiresEmulatedInterfaceCoreLibDesugaring(parameters));
+    Assume.assumeTrue(libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters));
     testForDesugaredLibrary(parameters, libraryDesugaringSpecification, compilationSpecification)
         .addProgramClassesAndInnerClasses(OptionalTestClass.class)
         .addProgramFiles(GSON_2_8_1_JAR)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11AtomicTests.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11AtomicTests.java
index 7d09ee0..ddeddc0 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11AtomicTests.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11AtomicTests.java
@@ -94,7 +94,8 @@
             ATOMIC_COMPILED_TESTS_FOLDER.resolve(ATOMIC_REFERENCE_TEST + CLASS_EXTENSION))
         .addProgramFiles(testNGSupportProgramFiles())
         .applyIf(
-            libraryDesugaringSpecification != JDK11_PATH, b -> b.addProgramFiles(getPathsFiles()))
+            !libraryDesugaringSpecification.hasNioFileDesugaring(parameters),
+            b -> b.addProgramFiles(getPathsFiles()))
         .compile()
         .withArt6Plus64BitsLib()
         .run(parameters.getRuntime(), "TestNGMainRunner", verbosity, ATOMIC_REFERENCE_TEST)
@@ -110,7 +111,8 @@
             getAllFilesWithSuffixInDirectory(ATOMIC_COMPILED_TESTS_FOLDER, CLASS_EXTENSION))
         .addProgramFiles(testNGSupportProgramFiles())
         .applyIf(
-            libraryDesugaringSpecification != JDK11_PATH, b -> b.addProgramFiles(getPathsFiles()))
+            !libraryDesugaringSpecification.hasNioFileDesugaring(parameters),
+            b -> b.addProgramFiles(getPathsFiles()))
         .compile()
         .withArt6Plus64BitsLib()
         .run(parameters.getRuntime(), "TestNGMainRunner", verbosity, ATOMIC_UPDATERS)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11ConcurrentMapTests.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11ConcurrentMapTests.java
index a3641d6..f4b8b17 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11ConcurrentMapTests.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11ConcurrentMapTests.java
@@ -119,7 +119,8 @@
         .addProgramFiles(CONCURRENT_COMPILED_TESTS_FILES)
         .addProgramFiles(testNGSupportProgramFiles())
         .applyIf(
-            libraryDesugaringSpecification != JDK11_PATH, b -> b.addProgramFiles(getPathsFiles()))
+            !libraryDesugaringSpecification.hasNioFileDesugaring(parameters),
+            b -> b.addProgramFiles(getPathsFiles()))
         .compile()
         .withArt6Plus64BitsLib()
         .run(parameters.getRuntime(), "TestNGMainRunner", verbosity, "ConcurrentModification")
@@ -168,7 +169,7 @@
             .addProgramFiles(concurrentHashTestToCompile())
             .addProgramFiles(testNGSupportProgramFiles())
             .applyIf(
-                libraryDesugaringSpecification != JDK11_PATH,
+                !libraryDesugaringSpecification.hasNioFileDesugaring(parameters),
                 b -> b.addProgramFiles(getPathsFiles()))
             .compile()
             .withArt6Plus64BitsLib();
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11StreamAbstractTests.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11StreamAbstractTests.java
index 94b9162..ad2644b 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11StreamAbstractTests.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11StreamAbstractTests.java
@@ -307,7 +307,7 @@
             parameters, libraryDesugaringSpecification, compilationSpecification)
         .addProgramFiles(filesToCompile)
         .applyIf(
-            libraryDesugaringSpecification != JDK11_PATH_JAVA_BASE_EXT,
+            !libraryDesugaringSpecification.hasNioFileDesugaring(parameters),
             b -> b.addProgramFiles(getPathsFiles()))
         .addProgramFiles(getSafeVarArgsFile())
         .addProgramFiles(testNGSupportProgramFiles())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11TestLibraryDesugaringSpecification.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11TestLibraryDesugaringSpecification.java
index 6249cf1..7a2760a 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11TestLibraryDesugaringSpecification.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11TestLibraryDesugaringSpecification.java
@@ -73,7 +73,12 @@
     Set<Path> libFiles = new HashSet<>(template.getLibraryFiles());
     libFiles.add(EXTENSION_PATH);
     return new LibraryDesugaringSpecification(
-        name, desugaredJDKLibFiles, template.getSpecification(), libFiles, getTestNGKeepRules());
+        name,
+        desugaredJDKLibFiles,
+        template.getSpecification(),
+        libFiles,
+        template.getDescriptor(),
+        getTestNGKeepRules());
   }
 
   private static synchronized void ensureJavaBaseExtensionsCompiled() throws Exception {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11TimeAbstractTests.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11TimeAbstractTests.java
index ee4cad8..3e0dc37 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11TimeAbstractTests.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11TimeAbstractTests.java
@@ -219,7 +219,7 @@
             .addProgramFiles(JDK_11_TIME_TEST_COMPILED_FILES)
             .addProgramFiles(testNGSupportProgramFiles())
             .applyIf(
-                libraryDesugaringSpecification != JDK11_PATH,
+                !libraryDesugaringSpecification.hasNioFileDesugaring(parameters),
                 b -> b.addProgramFiles(getPathsFiles()))
             .compile()
             .withArt6Plus64BitsLib();
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/kotlin/KotlinMetadataTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/kotlin/KotlinMetadataTest.java
index 3458390..8c572cf 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/kotlin/KotlinMetadataTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/kotlin/KotlinMetadataTest.java
@@ -7,7 +7,6 @@
 import static com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion.KOTLINC_1_3_72;
 import static com.android.tools.r8.KotlinTestBase.getCompileMemoizer;
 import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.DEFAULT_SPECIFICATIONS;
-import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK8;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.hamcrest.CoreMatchers.not;
@@ -103,7 +102,7 @@
         .compile()
         .inspect(
             i -> {
-              if (requiresTimeDesugaring(parameters, libraryDesugaringSpecification != JDK8)) {
+              if (libraryDesugaringSpecification.hasTimeDesugaring(parameters)) {
                 inspectRewrittenMetadata(i);
               }
             })
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/r8ondex/HelloWorldCompiledOnArtTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/r8ondex/HelloWorldCompiledOnArtTest.java
index 9567481..c1224a8 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/r8ondex/HelloWorldCompiledOnArtTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/r8ondex/HelloWorldCompiledOnArtTest.java
@@ -139,7 +139,7 @@
         .addProgramFiles(ToolHelper.R8_WITH_RELOCATED_DEPS_JAR)
         .applyIf(
             parameters.getApiLevel().getLevel() < AndroidApiLevel.O.getLevel()
-                && libraryDesugaringSpecification != JDK11_PATH,
+                && !libraryDesugaringSpecification.hasNioFileDesugaring(parameters),
             b -> b.addProgramFiles(pathBackport))
         .addOptionsModification(
             options -> {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/LibraryDesugaringSpecification.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/LibraryDesugaringSpecification.java
index edff04e..539ad9a 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/LibraryDesugaringSpecification.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/LibraryDesugaringSpecification.java
@@ -9,6 +9,7 @@
 import static com.android.tools.r8.ToolHelper.getUndesugaredJdk11LibJarForTesting;
 
 import com.android.tools.r8.L8TestBuilder;
+import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.google.common.collect.ImmutableList;
@@ -20,28 +21,87 @@
 
 public class LibraryDesugaringSpecification {
 
+  public static Descriptor JDK8_DESCRIPTOR = new Descriptor(24, 26, -1, 26, 24);
+  public static Descriptor JDK11_DESCRIPTOR = new Descriptor(24, 30, -1, 30, -1);
+  public static Descriptor EMPTY_DESCRIPTOR_24 = new Descriptor(-1, -1, -1, 24, -1);
+  public static Descriptor JDK11_PATH_DESCRIPTOR = new Descriptor(24, 30, 26, 32, -1);
+  public static Descriptor JDK11_LEGACY_DESCRIPTOR = new Descriptor(24, 10000, -1, 10000, 24);
+
+  private static class Descriptor {
+    // Above this level emulated interface are not *entirely* desugared.
+    private final int emulatedInterfaceDesugaring;
+    // Above this level java.time is not *entirely* desugared.
+    private final int timeDesugaring;
+    // Above this level java.nio.file is not *entirely* desugared.
+    private final int nioFileDesugaring;
+    // Above this level no desugaring is required.
+    private final int anyDesugaring;
+    // Above this level java.function is used, below j$.function is used.
+    private final int jDollarFunction;
+
+    private Descriptor(
+        int emulatedInterfaceDesugaring,
+        int timeDesugaring,
+        int nioFileDesugaring,
+        int anyDesugaring,
+        int jDollarFunction) {
+      this.emulatedInterfaceDesugaring = emulatedInterfaceDesugaring;
+      this.timeDesugaring = timeDesugaring;
+      this.nioFileDesugaring = nioFileDesugaring;
+      this.anyDesugaring = anyDesugaring;
+      this.jDollarFunction = jDollarFunction;
+    }
+
+    public int getEmulatedInterfaceDesugaring() {
+      return emulatedInterfaceDesugaring;
+    }
+
+    public int getTimeDesugaring() {
+      return timeDesugaring;
+    }
+
+    public int getNioFileDesugaring() {
+      return nioFileDesugaring;
+    }
+
+    public int getAnyDesugaring() {
+      return anyDesugaring;
+    }
+
+    public int getJDollarFunction() {
+      return jDollarFunction;
+    }
+  }
+
   // Main head specifications.
   public static LibraryDesugaringSpecification JDK8 =
       new LibraryDesugaringSpecification(
-          "JDK8", DESUGARED_JDK_8_LIB_JAR, "desugar_jdk_libs.json", AndroidApiLevel.P);
+          "JDK8",
+          DESUGARED_JDK_8_LIB_JAR,
+          "desugar_jdk_libs.json",
+          AndroidApiLevel.P,
+          JDK8_DESCRIPTOR);
   public static LibraryDesugaringSpecification JDK11 =
       new LibraryDesugaringSpecification(
           "JDK11",
           getUndesugaredJdk11LibJarForTesting(),
           "jdk11/desugar_jdk_libs.json",
-          AndroidApiLevel.R);
+          AndroidApiLevel.R,
+          JDK11_DESCRIPTOR);
   public static LibraryDesugaringSpecification JDK11_MINIMAL =
       new LibraryDesugaringSpecification(
           "JDK11_MINIMAL",
           getUndesugaredJdk11LibJarForTesting(),
           "jdk11/desugar_jdk_libs_minimal.json",
-          AndroidApiLevel.R);
+          AndroidApiLevel.R,
+          EMPTY_DESCRIPTOR_24);
   public static LibraryDesugaringSpecification JDK11_PATH =
       new LibraryDesugaringSpecification(
           "JDK11_PATH",
           getUndesugaredJdk11LibJarForTesting(),
           "jdk11/desugar_jdk_libs_path.json",
-          AndroidApiLevel.R);
+          AndroidApiLevel.R,
+          JDK11_PATH_DESCRIPTOR);
 
   // Legacy specifications.
   public static LibraryDesugaringSpecification JDK11_PATH_ALTERNATIVE_3 =
@@ -49,20 +109,23 @@
           "JDK11_PATH_ALTERNATIVE_3",
           getUndesugaredJdk11LibJarForTesting(),
           "jdk11/desugar_jdk_libs_path_alternative_3.json",
-          AndroidApiLevel.R);
+          AndroidApiLevel.R,
+          JDK11_PATH_DESCRIPTOR);
   public static LibraryDesugaringSpecification JDK11_CHM_ONLY =
       new LibraryDesugaringSpecification(
           "JDK11_CHM_ONLY",
           getUndesugaredJdk11LibJarForTesting(),
           "jdk11/chm_only_desugar_jdk_libs.json",
-          AndroidApiLevel.R);
+          AndroidApiLevel.R,
+          EMPTY_DESCRIPTOR_24);
   public static LibraryDesugaringSpecification JDK11_LEGACY =
       new LibraryDesugaringSpecification(
           "JDK11_LEGACY",
           // The legacy specification is not using the undesugared JAR.
           DESUGARED_JDK_11_LIB_JAR,
           "jdk11/desugar_jdk_libs_legacy.json",
-          AndroidApiLevel.R);
+          AndroidApiLevel.R,
+          JDK11_LEGACY_DESCRIPTOR);
   public static final LibraryDesugaringSpecification RELEASED_1_0_9 =
       new LibraryDesugaringSpecification("1.0.9", AndroidApiLevel.P);
   public static final LibraryDesugaringSpecification RELEASED_1_0_10 =
@@ -78,15 +141,21 @@
   private final Set<Path> desugarJdkLibs;
   private final Path specification;
   private final Set<Path> libraryFiles;
+  private final Descriptor descriptor;
   private final String extraKeepRules;
 
   public LibraryDesugaringSpecification(
-      String name, Path desugarJdkLibs, String specificationPath, AndroidApiLevel androidJarLevel) {
+      String name,
+      Path desugarJdkLibs,
+      String specificationPath,
+      AndroidApiLevel androidJarLevel,
+      Descriptor descriptor) {
     this(
         name,
         ImmutableSet.of(desugarJdkLibs, ToolHelper.DESUGAR_LIB_CONVERSIONS),
         Paths.get("src/library_desugar/" + specificationPath),
         ImmutableSet.of(ToolHelper.getAndroidJar(androidJarLevel)),
+        descriptor,
         "");
   }
 
@@ -96,11 +165,13 @@
       Set<Path> desugarJdkLibs,
       Path specification,
       Set<Path> libraryFiles,
+      Descriptor descriptor,
       String extraKeepRules) {
     this.name = name;
     this.desugarJdkLibs = desugarJdkLibs;
     this.specification = specification;
     this.libraryFiles = libraryFiles;
+    this.descriptor = descriptor;
     this.extraKeepRules = extraKeepRules;
   }
 
@@ -112,6 +183,7 @@
             Paths.get(DESUGARED_LIB_RELEASES_DIR, version, "desugar_jdk_libs_configuration.jar")),
         Paths.get(DESUGARED_LIB_RELEASES_DIR, version, "desugar.json"),
         ImmutableSet.of(ToolHelper.getAndroidJar(androidJarLevel)),
+        JDK8_DESCRIPTOR,
         "");
   }
 
@@ -132,6 +204,10 @@
     return libraryFiles;
   }
 
+  public Descriptor getDescriptor() {
+    return descriptor;
+  }
+
   public String getExtraKeepRules() {
     return extraKeepRules;
   }
@@ -165,4 +241,32 @@
   public static List<LibraryDesugaringSpecification> getJdk8Jdk11() {
     return ImmutableList.of(JDK8, JDK11);
   }
+
+  public boolean hasEmulatedInterfaceDesugaring(TestParameters parameters) {
+    return parameters.getApiLevel().getLevel() < descriptor.getEmulatedInterfaceDesugaring();
+  }
+
+  public boolean hasTimeDesugaring(TestParameters parameters) {
+    return parameters.getApiLevel().getLevel() < descriptor.getTimeDesugaring();
+  }
+
+  public boolean hasNioFileDesugaring(TestParameters parameters) {
+    return parameters.getApiLevel().getLevel() < descriptor.getNioFileDesugaring();
+  }
+
+  public boolean hasAnyDesugaring(TestParameters parameters) {
+    return hasAnyDesugaring(parameters.getApiLevel());
+  }
+
+  public boolean hasAnyDesugaring(AndroidApiLevel apiLevel) {
+    return apiLevel.getLevel() < descriptor.getAnyDesugaring();
+  }
+
+  public boolean hasJDollarFunction(TestParameters parameters) {
+    return parameters.getApiLevel().getLevel() < descriptor.getJDollarFunction();
+  }
+
+  public String functionPrefix(TestParameters parameters) {
+    return hasJDollarFunction(parameters) ? "j$" : "java";
+  }
 }