Reland "Enabling machine desugared library specification"

This reverts commit 8d9d27c51869db372de6dac593caf72c36d7975f.

Bug: 184026720
Change-Id: I2afd78e4dca0e9677bca42aa109afa3d3b44ddbb
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs.json b/src/library_desugar/jdk11/desugar_jdk_libs.json
index fb03dbb..644b82b 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs.json
@@ -205,7 +205,7 @@
         "java.nio.charset.StandardCharsets": "j$.nio.charset.StandardCharsets"
       },
       "retarget_lib_member": {
-        "java.lang.Character#isBmpCodePoint": "j$.lang.DesugarCharacter"
+        "java.lang.Character#isBmpCodePoint": "java.lang.DesugarCharacter"
       }
     }
   ],
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_alternative_3.json b/src/library_desugar/jdk11/desugar_jdk_libs_alternative_3.json
index fac2ec0..ec0863d 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_alternative_3.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_alternative_3.json
@@ -209,7 +209,7 @@
         "java.nio.charset.StandardCharsets": "j$.nio.charset.StandardCharsets"
       },
       "retarget_lib_member": {
-        "java.lang.Character#isBmpCodePoint": "j$.lang.DesugarCharacter"
+        "java.lang.Character#isBmpCodePoint": "java.lang.DesugarCharacter"
       }
     }
   ],
diff --git a/src/main/java/com/android/tools/r8/BackportedMethodListCommand.java b/src/main/java/com/android/tools/r8/BackportedMethodListCommand.java
index bce73f0..7ef1569 100644
--- a/src/main/java/com/android/tools/r8/BackportedMethodListCommand.java
+++ b/src/main/java/com/android/tools/r8/BackportedMethodListCommand.java
@@ -105,7 +105,7 @@
   InternalOptions getInternalOptions() {
     InternalOptions options = new InternalOptions(factory, getReporter());
     options.setMinApiLevel(AndroidApiLevel.getAndroidApiLevel(minApiLevel));
-    options.desugaredLibrarySpecification = desugaredLibrarySpecification;
+    options.setDesugaredLibrarySpecification(desugaredLibrarySpecification, getInputApp());
     return options;
   }
 
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index 8dd34a8..0967f55 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -498,8 +498,7 @@
     internal.encodeChecksums = getIncludeClassesChecksum();
     internal.dexClassChecksumFilter = getDexClassChecksumFilter();
     internal.enableInheritanceClassInDexDistributor = isOptimizeMultidexForLinearAlloc();
-
-    internal.desugaredLibrarySpecification = desugaredLibrarySpecification;
+    internal.setDesugaredLibrarySpecification(desugaredLibrarySpecification, getInputApp());
     internal.synthesizedClassPrefix = synthesizedClassPrefix;
     internal.desugaredLibraryKeepRuleConsumer = desugaredLibraryKeepRuleConsumer;
 
diff --git a/src/main/java/com/android/tools/r8/L8Command.java b/src/main/java/com/android/tools/r8/L8Command.java
index 26c99ce..6da92e2 100644
--- a/src/main/java/com/android/tools/r8/L8Command.java
+++ b/src/main/java/com/android/tools/r8/L8Command.java
@@ -194,7 +194,7 @@
     internal.enableInheritanceClassInDexDistributor = false;
 
     assert desugaredLibrarySpecification != null;
-    internal.desugaredLibrarySpecification = desugaredLibrarySpecification;
+    internal.setDesugaredLibrarySpecification(desugaredLibrarySpecification, getInputApp());
     internal.synthesizedClassPrefix =
         desugaredLibrarySpecification.getSynthesizedLibraryClassesPackagePrefix();
 
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 97429ec..7896e62 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -310,7 +310,7 @@
       if (!options.mainDexKeepRules.isEmpty()) {
         MainDexListBuilder.checkForAssumedLibraryTypes(appView.appInfo());
       }
-      if (!options.desugaredLibrarySpecification.getRetargetCoreLibMember().isEmpty()) {
+      if (options.machineDesugaredLibrarySpecification.hasRetargeting()) {
         DesugaredLibraryRetargeterLibraryTypeSynthesizer.checkForAssumedLibraryTypes(appView);
         DesugaredLibraryRetargeterLibraryTypeSynthesizer.amendLibraryWithRetargetedMembers(appView);
       }
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index bf04680..5bc9ddd 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -943,7 +943,7 @@
 
     internal.enableInheritanceClassInDexDistributor = isOptimizeMultidexForLinearAlloc();
 
-    internal.desugaredLibrarySpecification = desugaredLibrarySpecification;
+    internal.setDesugaredLibrarySpecification(desugaredLibrarySpecification, getInputApp());
     internal.synthesizedClassPrefix = synthesizedClassPrefix;
     internal.desugaredLibraryKeepRuleConsumer = desugaredLibraryKeepRuleConsumer;
 
diff --git a/src/main/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryKeepRuleGenerator.java b/src/main/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryKeepRuleGenerator.java
index a720021..8bdf5a1 100644
--- a/src/main/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryKeepRuleGenerator.java
+++ b/src/main/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryKeepRuleGenerator.java
@@ -71,7 +71,7 @@
       return false;
     }
     return namingLens.hasPrefixRewritingLogic()
-        || options.desugaredLibrarySpecification.hasEmulatedLibraryInterfaces();
+        || options.machineDesugaredLibrarySpecification.hasEmulatedInterfaces();
   }
 
   private void run() {
diff --git a/src/main/java/com/android/tools/r8/dex/CodeToKeep.java b/src/main/java/com/android/tools/r8/dex/CodeToKeep.java
index cc05c31..3adc951 100644
--- a/src/main/java/com/android/tools/r8/dex/CodeToKeep.java
+++ b/src/main/java/com/android/tools/r8/dex/CodeToKeep.java
@@ -25,7 +25,7 @@
 
   static CodeToKeep createCodeToKeep(InternalOptions options, NamingLens namingLens) {
     if ((!namingLens.hasPrefixRewritingLogic()
-            && !options.desugaredLibrarySpecification.hasEmulatedLibraryInterfaces())
+            && !options.machineDesugaredLibrarySpecification.hasEmulatedInterfaces())
         || options.isDesugaredLibraryCompilation()
         || options.testing.enableExperimentalDesugaredLibraryKeepRuleGenerator) {
       return new NopCodeToKeep();
@@ -65,7 +65,7 @@
       this.namingLens = namingLens;
       this.options = options;
       potentialTypesToKeep.addAll(
-          options.desugaredLibrarySpecification.getEmulateLibraryInterface().values());
+          options.machineDesugaredLibrarySpecification.getEmulatedInterfaceRewrittenTypes());
       potentialTypesToKeep.addAll(
           options.desugaredLibrarySpecification.getCustomConversions().values());
     }
@@ -77,7 +77,7 @@
           || type.toDescriptorString()
               .startsWith(
                   "L"
-                      + options.desugaredLibrarySpecification
+                      + options.machineDesugaredLibrarySpecification
                           .getSynthesizedLibraryClassesPackagePrefix());
     }
 
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 49ad698..0606d2d 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
@@ -128,24 +128,16 @@
     DexMethod original = appView.graphLens().getOriginalMethodSignature(method);
     assert original != null;
     MethodProvider provider = rewritableMethods.getProvider(original);
-    // TODO(b/150693139): Since the DesugarLibraryRetargeter is run during IR processing while the
-    // backported method rewriter is run in cf to cf, we need here to compute if the method is
-    // actually going to be retargeted through desugared library backports, and compute the
-    // corresponding backported method if so. This can be removed once the DesugarLibraryRetargeter
-    // has been moved as a cf to cf transformation.
+    // Old versions of desugared library have in the jar file pre-desugared code. This is used
+    // to undesugar pre-desugared code, then the code is re-desugared with D8/R8. This is
+    // maintained for legacy only, recent desugared library should not be shipped with
+    // pre-desugared code.
+    Map<DexType, DexType> legacyBackport =
+        appView.options().machineDesugaredLibrarySpecification.getLegacyBackport();
     if (provider == null
         && appView.options().isDesugaredLibraryCompilation()
-        && appView
-            .options()
-            .desugaredLibrarySpecification
-            .getBackportCoreLibraryMember()
-            .containsKey(method.holder)) {
-      DexType newHolder =
-          appView
-              .options()
-              .desugaredLibrarySpecification
-              .getBackportCoreLibraryMember()
-              .get(method.holder);
+        && legacyBackport.containsKey(method.holder)) {
+      DexType newHolder = legacyBackport.get(method.holder);
       DexMethod backportedMethod =
           appView.dexItemFactory().createMethod(newHolder, method.proto, method.name);
       provider = rewritableMethods.getProvider(backportedMethod);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringCollection.java
index 1fd0ad0..1243435 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringCollection.java
@@ -57,7 +57,7 @@
         InterfaceMethodProcessorFacade interfaceMethodProcessorFacade,
         RetargetingInfo retargetingInfo) {
       ArrayList<CfPostProcessingDesugaring> desugarings = new ArrayList<>();
-      if (!appView.options().desugaredLibrarySpecification.getRetargetCoreLibMember().isEmpty()
+      if (appView.options().machineDesugaredLibrarySpecification.hasRetargeting()
           && !appView.options().isDesugaredLibraryCompilation()) {
         desugarings.add(new DesugaredLibraryRetargeterPostProcessor(appView, retargetingInfo));
       }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
index 33c69ac..e55c246 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
@@ -82,9 +82,9 @@
     this.nestBasedAccessDesugaring = NestBasedAccessDesugaring.create(appView);
     BackportedMethodRewriter backportedMethodRewriter = null;
     desugaredLibraryRetargeter =
-        appView.options().desugaredLibrarySpecification.getRetargetCoreLibMember().isEmpty()
-            ? null
-            : new DesugaredLibraryRetargeter(appView);
+        appView.options().machineDesugaredLibrarySpecification.hasRetargeting()
+            ? new DesugaredLibraryRetargeter(appView)
+            : null;
     if (desugaredLibraryRetargeter != null) {
       desugarings.add(desugaredLibraryRetargeter);
     }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/PrefixRewritingMapper.java b/src/main/java/com/android/tools/r8/ir/desugar/PrefixRewritingMapper.java
index bf96b67..f8cf00e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/PrefixRewritingMapper.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/PrefixRewritingMapper.java
@@ -12,7 +12,7 @@
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineRewritingFlags;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Sets;
@@ -228,20 +228,34 @@
     private final Map<DexType, DexType> rewriteDerivedTypeOnly;
 
     public MachineDesugarPrefixRewritingMapper(
-        PrefixRewritingMapper mapper, MachineRewritingFlags flags) {
+        PrefixRewritingMapper mapper, MachineDesugaredLibrarySpecification specification) {
       this.mapper = mapper;
-      this.rewriteType = new ConcurrentHashMap<>(flags.getRewriteType());
-      rewriteDerivedTypeOnly = flags.getRewriteDerivedTypeOnly();
+      this.rewriteType = new ConcurrentHashMap<>(specification.getRewriteType());
+      rewriteDerivedTypeOnly = specification.getRewriteDerivedTypeOnly();
     }
 
     @Override
     public DexType rewrittenType(DexType type, AppView<?> appView) {
-      assert mapper.rewrittenType(type, appView) == rewriteType.get(type);
+      if (type.isArrayType()) {
+        DexType rewrittenBaseType =
+            rewrittenType(type.toBaseType(appView.dexItemFactory()), appView);
+        if (rewrittenBaseType == null) {
+          return null;
+        }
+        return appView
+            .dexItemFactory()
+            .createArrayType(type.getNumberOfLeadingSquareBrackets(), rewrittenBaseType);
+      }
+      assert mapper.rewrittenType(type, appView) == rewriteType.get(type)
+          || appView.definitionFor(type) == null
+          || (appView.definitionFor(type).isProgramClass()
+              && !appView.options().isDesugaredLibraryCompilation());
       return rewriteType.get(type);
     }
 
     @Override
     public DexType rewrittenContextType(DexType context, AppView<?> appView) {
+      assert !context.isArrayType();
       if (rewriteType.containsKey(context)) {
         return rewriteType.get(context);
       }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPICallbackSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPICallbackSynthesizer.java
index 150e6c4..9b07615 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPICallbackSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPICallbackSynthesizer.java
@@ -109,8 +109,8 @@
     if (!appView.rewritePrefix.hasRewrittenTypeInSignature(definition.getProto(), appView)
         || appView
             .options()
-            .desugaredLibrarySpecification
-            .getEmulateLibraryInterface()
+            .machineDesugaredLibrarySpecification
+            .getEmulatedInterfaces()
             .containsKey(method.getHolderType())) {
       return false;
     }
@@ -127,7 +127,7 @@
         return false;
       }
     }
-    if (!appView.options().desugaredLibrarySpecification.supportAllCallbacksFromLibrary()
+    if (!appView.options().machineDesugaredLibrarySpecification.supportAllCallbacksFromLibrary()
         && appView.options().isDesugaredLibraryCompilation()) {
       return false;
     }
@@ -178,7 +178,7 @@
   }
 
   private boolean shouldGenerateCallbacksForEmulateInterfaceAPIs(DexClass dexClass) {
-    if (appView.options().desugaredLibrarySpecification.supportAllCallbacksFromLibrary()) {
+    if (appView.options().machineDesugaredLibrarySpecification.supportAllCallbacksFromLibrary()) {
       return true;
     }
     Map<DexType, DexType> emulateLibraryInterfaces =
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java
index 987dc8d..f234a1b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java
@@ -181,8 +181,8 @@
     return interfaceResult != null
         && appView
             .options()
-            .desugaredLibrarySpecification
-            .getEmulateLibraryInterface()
+            .machineDesugaredLibrarySpecification
+            .getEmulatedInterfaces()
             .containsKey(interfaceResult.getHolderType());
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java
index 4a8cabe..1e62da6 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexClasspathClass;
 import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMember;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -184,7 +185,11 @@
   }
 
   private boolean canConvert(DexType type) {
-    return appView.options().desugaredLibrarySpecification.getCustomConversions().containsKey(type)
+    return appView
+            .options()
+            .machineDesugaredLibrarySpecification
+            .getCustomConversions()
+            .containsKey(type)
         || canGenerateWrapper(type);
   }
 
@@ -541,19 +546,17 @@
   }
 
   private Iterable<DexMethod> allImplementedMethods(DexClass clazz) {
-    if (appView.options().testing.machineDesugaredLibrarySpecification != null) {
+    if (appView.options().machineDesugaredLibrarySpecification != null) {
       return appView
           .options()
-          .testing
           .machineDesugaredLibrarySpecification
-          .getRewritingFlags()
           .getWrappers()
           .get(clazz.type);
     }
     List<DexEncodedMethod> dexEncodedMethods =
         allImplementedMethodsCache.computeIfAbsent(
             clazz.type, type -> internalAllImplementedMethods(clazz));
-    return Iterables.transform(dexEncodedMethods, m -> m.getReference());
+    return Iterables.transform(dexEncodedMethods, DexEncodedMember::getReference);
   }
 
   private List<DexEncodedMethod> internalAllImplementedMethods(DexClass libraryClass) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java
index 501482e..3f6ab19 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java
@@ -4,12 +4,35 @@
 
 package com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification;
 
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.Pair;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+
 public class MachineDesugaredLibrarySpecification {
 
   private final boolean libraryCompilation;
   private final MachineTopLevelFlags topLevelFlags;
   private final MachineRewritingFlags rewritingFlags;
 
+  public static MachineDesugaredLibrarySpecification empty() {
+    return new MachineDesugaredLibrarySpecification(
+        false, MachineTopLevelFlags.empty(), MachineRewritingFlags.builder().build());
+  }
+
+  public static MachineDesugaredLibrarySpecification withOnlyRewriteTypeForTesting(
+      Map<DexType, DexType> rewriteTypeForTesting) {
+    MachineRewritingFlags.Builder builder = MachineRewritingFlags.builder();
+    rewriteTypeForTesting.forEach(builder::rewriteType);
+    return new MachineDesugaredLibrarySpecification(
+        true, MachineTopLevelFlags.empty(), builder.build());
+  }
+
   public MachineDesugaredLibrarySpecification(
       boolean libraryCompilation,
       MachineTopLevelFlags topLevelFlags,
@@ -23,11 +46,83 @@
     return libraryCompilation;
   }
 
-  public MachineTopLevelFlags getTopLevelFlags() {
-    return topLevelFlags;
+  public AndroidApiLevel getRequiredCompilationAPILevel() {
+    return topLevelFlags.getRequiredCompilationAPILevel();
   }
 
-  public MachineRewritingFlags getRewritingFlags() {
-    return rewritingFlags;
+  public String getSynthesizedLibraryClassesPackagePrefix() {
+    return topLevelFlags.getSynthesizedLibraryClassesPackagePrefix();
+  }
+
+  public String getIdentifier() {
+    return topLevelFlags.getIdentifier();
+  }
+
+  public String getJsonSource() {
+    return topLevelFlags.getJsonSource();
+  }
+
+  public boolean supportAllCallbacksFromLibrary() {
+    return topLevelFlags.supportAllCallbacksFromLibrary();
+  }
+
+  public List<String> getExtraKeepRules() {
+    return topLevelFlags.getExtraKeepRules();
+  }
+
+  public Map<DexType, DexType> getRewriteType() {
+    return rewritingFlags.getRewriteType();
+  }
+
+  public Map<DexType, DexType> getRewriteDerivedTypeOnly() {
+    return rewritingFlags.getRewriteDerivedTypeOnly();
+  }
+
+  public Map<DexMethod, DexMethod> getStaticRetarget() {
+    return rewritingFlags.getStaticRetarget();
+  }
+
+  public Map<DexMethod, DexMethod> getNonEmulatedVirtualRetarget() {
+    return rewritingFlags.getNonEmulatedVirtualRetarget();
+  }
+
+  public Map<DexMethod, EmulatedDispatchMethodDescriptor> getEmulatedVirtualRetarget() {
+    return rewritingFlags.getEmulatedVirtualRetarget();
+  }
+
+  public void forEachRetargetHolder(Consumer<DexType> consumer) {
+    rewritingFlags.forEachRetargetHolder(consumer);
+  }
+
+  public Map<DexType, EmulatedInterfaceDescriptor> getEmulatedInterfaces() {
+    return rewritingFlags.getEmulatedInterfaces();
+  }
+
+  public Set<DexType> getEmulatedInterfaceRewrittenTypes() {
+    return rewritingFlags.getEmulatedInterfaceRewrittenTypes();
+  }
+
+  public Map<DexType, List<DexMethod>> getWrappers() {
+    return rewritingFlags.getWrappers();
+  }
+
+  public Map<DexType, DexType> getLegacyBackport() {
+    return rewritingFlags.getLegacyBackport();
+  }
+
+  public Set<DexType> getDontRetarget() {
+    return rewritingFlags.getDontRetarget();
+  }
+
+  public Map<DexType, Pair<DexType, DexString>> getCustomConversions() {
+    return rewritingFlags.getCustomConversions();
+  }
+
+  public boolean hasRetargeting() {
+    return rewritingFlags.hasRetargeting();
+  }
+
+  public boolean hasEmulatedInterfaces() {
+    return rewritingFlags.hasEmulatedInterfaces();
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java
index a6c487e..c2c281f 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java
@@ -11,10 +11,12 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
 import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Consumer;
 
 public class MachineRewritingFlags {
 
@@ -94,10 +96,24 @@
     return emulatedVirtualRetarget;
   }
 
+  public void forEachRetargetHolder(Consumer<DexType> consumer) {
+    staticRetarget.keySet().forEach(m -> consumer.accept(m.getHolderType()));
+    nonEmulatedVirtualRetarget.keySet().forEach(m -> consumer.accept(m.getHolderType()));
+    emulatedVirtualRetarget.keySet().forEach(m -> consumer.accept(m.getHolderType()));
+  }
+
   public Map<DexType, EmulatedInterfaceDescriptor> getEmulatedInterfaces() {
     return emulatedInterfaces;
   }
 
+  public Set<DexType> getEmulatedInterfaceRewrittenTypes() {
+    Set<DexType> rewrittenTypes = Sets.newIdentityHashSet();
+    emulatedInterfaces
+        .values()
+        .forEach(descriptor -> rewrittenTypes.add(descriptor.getRewrittenType()));
+    return rewrittenTypes;
+  }
+
   public Map<DexType, List<DexMethod>> getWrappers() {
     return wrappers;
   }
@@ -114,6 +130,16 @@
     return customConversions;
   }
 
+  public boolean hasRetargeting() {
+    return !staticRetarget.isEmpty()
+        || !nonEmulatedVirtualRetarget.isEmpty()
+        || !emulatedVirtualRetarget.isEmpty();
+  }
+
+  public boolean hasEmulatedInterfaces() {
+    return !emulatedInterfaces.isEmpty();
+  }
+
   public static class Builder {
 
     Builder() {}
@@ -137,6 +163,7 @@
     public void rewriteType(DexType src, DexType target) {
       assert src != null;
       assert target != null;
+      assert src != target;
       rewriteType.put(src, target);
     }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineTopLevelFlags.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineTopLevelFlags.java
index f426219..0c6a88a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineTopLevelFlags.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineTopLevelFlags.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification;
 
 import com.android.tools.r8.utils.AndroidApiLevel;
+import com.google.common.collect.ImmutableList;
 import java.util.List;
 
 public class MachineTopLevelFlags {
@@ -23,6 +24,11 @@
   private final boolean supportAllCallbacksFromLibrary;
   private final List<String> extraKeepRules;
 
+  public static MachineTopLevelFlags empty() {
+    return new MachineTopLevelFlags(
+        AndroidApiLevel.B, "unused", null, null, false, ImmutableList.of());
+  }
+
   public MachineTopLevelFlags(
       AndroidApiLevel requiredCompilationAPILevel,
       String synthesizedLibraryClassesPackagePrefix,
@@ -54,7 +60,7 @@
     return jsonSource;
   }
 
-  public boolean isSupportAllCallbacksFromLibrary() {
+  public boolean supportAllCallbacksFromLibrary() {
     return supportAllCallbacksFromLibrary;
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java
index a54cd8d..5fcf037 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java
@@ -129,8 +129,8 @@
     }
     if (appView
         .options()
-        .desugaredLibrarySpecification
-        .getDontRetargetLibMember()
+        .machineDesugaredLibrarySpecification
+        .getDontRetarget()
         .contains(context.getContextType())) {
       return NO_REWRITING;
     }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterL8Synthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterL8Synthesizer.java
index 11fcfb7..eb28d20 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterL8Synthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterL8Synthesizer.java
@@ -20,7 +20,7 @@
       AppView<?> appView, RetargetingInfo retargetingInfo) {
     assert appView.options().isDesugaredLibraryCompilation();
     if (retargetingInfo == null || retargetingInfo.getEmulatedVirtualRetarget().isEmpty()) {
-      assert appView.options().desugaredLibrarySpecification.getRetargetCoreLibMember().isEmpty();
+      assert !appView.options().machineDesugaredLibrarySpecification.hasRetargeting();
       return null;
     }
     return new DesugaredLibraryRetargeterL8Synthesizer(appView, retargetingInfo);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterLibraryTypeSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterLibraryTypeSynthesizer.java
index bbaa4cf..bfb423a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterLibraryTypeSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterLibraryTypeSynthesizer.java
@@ -39,16 +39,16 @@
 public class DesugaredLibraryRetargeterLibraryTypeSynthesizer {
 
   public static void checkForAssumedLibraryTypes(AppView<?> appView) {
-    Map<DexString, Map<DexType, DexType>> retargetCoreLibMember =
-        appView.options().desugaredLibrarySpecification.getRetargetCoreLibMember();
-    for (DexString methodName : retargetCoreLibMember.keySet()) {
-      for (DexType inType : retargetCoreLibMember.get(methodName).keySet()) {
-        DexClass typeClass = appView.definitionFor(inType);
-        if (typeClass == null) {
-          warnMissingRetargetCoreLibraryMember(inType, appView);
-        }
-      }
-    }
+    appView
+        .options()
+        .machineDesugaredLibrarySpecification
+        .forEachRetargetHolder(
+            inType -> {
+              DexClass typeClass = appView.definitionFor(inType);
+              if (typeClass == null) {
+                warnMissingRetargetCoreLibraryMember(inType, appView);
+              }
+            });
   }
 
   public static void amendLibraryWithRetargetedMembers(AppView<AppInfoWithClassHierarchy> appView) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/RetargetingInfo.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/RetargetingInfo.java
index 9e1f5e3..b7ac366 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/RetargetingInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/RetargetingInfo.java
@@ -4,24 +4,9 @@
 package com.android.tools.r8.ir.desugar.desugaredlibrary.retargeter;
 
 import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.graph.DexClassAndMethod;
-import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexProto;
-import com.android.tools.r8.graph.DexString;
-import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.DerivedMethod;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.EmulatedDispatchMethodDescriptor;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineRewritingFlags;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
-import com.android.tools.r8.utils.WorkList;
-import com.google.common.collect.ImmutableMap;
-import java.util.ArrayList;
-import java.util.IdentityHashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
 import java.util.Map;
 
 public class RetargetingInfo {
@@ -40,15 +25,12 @@
   }
 
   public static RetargetingInfo get(AppView<?> appView) {
-    if (appView.options().testing.machineDesugaredLibrarySpecification != null) {
-      MachineRewritingFlags rewritingFlags =
-          appView.options().testing.machineDesugaredLibrarySpecification.getRewritingFlags();
-      return new RetargetingInfo(
-          rewritingFlags.getStaticRetarget(),
-          rewritingFlags.getNonEmulatedVirtualRetarget(),
-          rewritingFlags.getEmulatedVirtualRetarget());
-    }
-    return new RetargetingInfoBuilder(appView).computeRetargetingInfo();
+    MachineDesugaredLibrarySpecification specification =
+        appView.options().machineDesugaredLibrarySpecification;
+    return new RetargetingInfo(
+        specification.getStaticRetarget(),
+        specification.getNonEmulatedVirtualRetarget(),
+        specification.getEmulatedVirtualRetarget());
   }
 
   public Map<DexMethod, DexMethod> getStaticRetarget() {
@@ -62,152 +44,4 @@
   public Map<DexMethod, EmulatedDispatchMethodDescriptor> getEmulatedVirtualRetarget() {
     return emulatedVirtualRetarget;
   }
-
-  private static class RetargetingInfoBuilder {
-
-    private final AppView<?> appView;
-    private final Map<DexMethod, DexMethod> staticRetarget = new IdentityHashMap<>();
-    private final Map<DexMethod, DexMethod> nonEmulatedVirtualRetarget = new IdentityHashMap<>();
-    private final Map<DexMethod, EmulatedDispatchMethodDescriptor> emulatedVirtualRetarget =
-        new IdentityHashMap<>();
-
-    public RetargetingInfoBuilder(AppView<?> appView) {
-      this.appView = appView;
-    }
-
-    private RetargetingInfo computeRetargetingInfo() {
-      LegacyDesugaredLibrarySpecification desugaredLibrarySpecification =
-          appView.options().desugaredLibrarySpecification;
-      Map<DexString, Map<DexType, DexType>> retargetCoreLibMember =
-          desugaredLibrarySpecification.getRetargetCoreLibMember();
-      if (retargetCoreLibMember.isEmpty()) {
-        return new RetargetingInfo(ImmutableMap.of(), ImmutableMap.of(), ImmutableMap.of());
-      }
-      for (DexString methodName : retargetCoreLibMember.keySet()) {
-        for (DexType inType : retargetCoreLibMember.get(methodName).keySet()) {
-          DexClass typeClass = appView.definitionFor(inType);
-          if (typeClass != null) {
-            DexType newHolder = retargetCoreLibMember.get(methodName).get(inType);
-            List<DexClassAndMethod> found = findMethodsWithName(methodName, typeClass);
-            for (DexClassAndMethod method : found) {
-              DexMethod methodReference = method.getReference();
-              if (method.getAccessFlags().isStatic()) {
-                staticRetarget.put(
-                    methodReference,
-                    computeRetargetMethod(
-                        methodReference, method.getAccessFlags().isStatic(), newHolder));
-                continue;
-              }
-              if (isEmulatedInterfaceDispatch(method)) {
-                continue;
-              }
-              if (typeClass.isFinal() || method.getAccessFlags().isFinal()) {
-                nonEmulatedVirtualRetarget.put(
-                    methodReference,
-                    computeRetargetMethod(
-                        methodReference, method.getAccessFlags().isStatic(), newHolder));
-              } else {
-                // Virtual rewrites require emulated dispatch for inheritance.
-                // The call is rewritten to the dispatch holder class instead.
-                DexProto newProto = appView.dexItemFactory().prependHolderToProto(methodReference);
-                DexMethod forwardingDexMethod =
-                    appView.dexItemFactory().createMethod(newHolder, newProto, methodName);
-                DerivedMethod forwardingMethod = new DerivedMethod(forwardingDexMethod);
-                DerivedMethod interfaceMethod =
-                    new DerivedMethod(methodReference, SyntheticKind.RETARGET_INTERFACE);
-                DerivedMethod dispatchMethod =
-                    new DerivedMethod(methodReference, SyntheticKind.RETARGET_CLASS);
-                emulatedVirtualRetarget.put(
-                    methodReference,
-                    new EmulatedDispatchMethodDescriptor(
-                        interfaceMethod, dispatchMethod, forwardingMethod, new LinkedHashMap<>()));
-              }
-            }
-          }
-        }
-      }
-      if (desugaredLibrarySpecification.isLibraryCompilation()) {
-        // TODO(b/177977763): This is only a workaround rewriting invokes of j.u.Arrays.deepEquals0
-        // to j.u.DesugarArrays.deepEquals0.
-        DexItemFactory itemFactory = appView.options().dexItemFactory();
-        DexString name = itemFactory.createString("deepEquals0");
-        DexProto proto =
-            itemFactory.createProto(
-                itemFactory.booleanType, itemFactory.objectType, itemFactory.objectType);
-        DexMethod source =
-            itemFactory.createMethod(
-                itemFactory.createType(itemFactory.arraysDescriptor), proto, name);
-        DexMethod target =
-            computeRetargetMethod(
-                source, true, itemFactory.createType("Ljava/util/DesugarArrays;"));
-        staticRetarget.put(source, target);
-        // TODO(b/181629049): This is only a workaround rewriting invokes of
-        //  j.u.TimeZone.getTimeZone taking a java.time.ZoneId.
-        name = itemFactory.createString("getTimeZone");
-        proto =
-            itemFactory.createProto(
-                itemFactory.createType("Ljava/util/TimeZone;"),
-                itemFactory.createType("Ljava/time/ZoneId;"));
-        source =
-            itemFactory.createMethod(itemFactory.createType("Ljava/util/TimeZone;"), proto, name);
-        target =
-            computeRetargetMethod(
-                source, true, itemFactory.createType("Ljava/util/DesugarTimeZone;"));
-        staticRetarget.put(source, target);
-      }
-      return new RetargetingInfo(
-          ImmutableMap.copyOf(staticRetarget),
-          ImmutableMap.copyOf(nonEmulatedVirtualRetarget),
-          emulatedVirtualRetarget);
-    }
-
-    DexMethod computeRetargetMethod(DexMethod method, boolean isStatic, DexType newHolder) {
-      DexItemFactory factory = appView.dexItemFactory();
-      DexProto newProto = isStatic ? method.getProto() : factory.prependHolderToProto(method);
-      return factory.createMethod(newHolder, newProto, method.getName());
-    }
-
-    private boolean isEmulatedInterfaceDispatch(DexClassAndMethod method) {
-      // Answers true if this method is already managed through emulated interface dispatch.
-      Map<DexType, DexType> emulateLibraryInterface =
-          appView.options().desugaredLibrarySpecification.getEmulateLibraryInterface();
-      if (emulateLibraryInterface.isEmpty()) {
-        return false;
-      }
-      DexMethod methodToFind = method.getReference();
-      // Look-up all superclass and interfaces, if an emulated interface is found, and it implements
-      // the method, answers true.
-      WorkList<DexClass> worklist = WorkList.newIdentityWorkList(method.getHolder());
-      while (worklist.hasNext()) {
-        DexClass clazz = worklist.next();
-        if (clazz.isInterface()
-            && emulateLibraryInterface.containsKey(clazz.getType())
-            && clazz.lookupMethod(methodToFind) != null) {
-          return true;
-        }
-        // All super types are library class, or we are doing L8 compilation.
-        clazz.forEachImmediateSupertype(
-            superType -> {
-              DexClass superClass = appView.definitionFor(superType);
-              if (superClass != null) {
-                worklist.addIfNotSeen(superClass);
-              }
-            });
-      }
-      return false;
-    }
-
-    private List<DexClassAndMethod> findMethodsWithName(DexString methodName, DexClass clazz) {
-      List<DexClassAndMethod> found = new ArrayList<>();
-      clazz.forEachClassMethodMatching(
-          definition -> definition.getName() == methodName, found::add);
-      assert !found.isEmpty()
-          : "Should have found a method (library specifications) for "
-              + clazz.toSourceString()
-              + "."
-              + methodName
-              + ". Maybe the library used for the compilation should be newer.";
-      return found;
-    }
-  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineEmulatedInterfaceConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineEmulatedInterfaceConverter.java
index 2411ba0..04cc12b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineEmulatedInterfaceConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineEmulatedInterfaceConverter.java
@@ -8,7 +8,6 @@
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexProto;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanRewritingFlags;
@@ -44,10 +43,10 @@
     Set<DexMethod> dontRewriteInvocation = rewritingFlags.getDontRewriteInvocation();
     emulatedInterfaceHierarchy = processEmulatedInterfaceHierarchy(appInfo, emulateInterfaces);
     for (DexType itf : emulateInterfaces.keySet()) {
-      DexProgramClass itfClass = appInfo.contextIndependentDefinitionFor(itf).asProgramClass();
+      DexClass itfClass = appInfo.contextIndependentDefinitionFor(itf);
       assert itfClass != null;
       Map<DexMethod, EmulatedDispatchMethodDescriptor> emulatedMethods = new IdentityHashMap<>();
-      itfClass.forEachProgramVirtualMethodMatching(
+      itfClass.forEachClassMethodMatching(
           m -> m.isDefaultMethod() && !dontRewriteInvocation.contains(m.getReference()),
           method ->
               emulatedMethods.put(
@@ -104,7 +103,6 @@
       for (int i = subInterfaces.size() - 1; i >= 0; i--) {
         DexClass subInterfaceClass = appInfo.definitionFor(subInterfaces.get(i));
         assert subInterfaceClass != null;
-        assert subInterfaceClass.isProgramClass();
         // Else computation of subInterface would have failed.
         // if the method is implemented, extra dispatch is required.
         DexEncodedMethod result = subInterfaceClass.lookupVirtualMethod(method);
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 6ff7428..92efb24 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
@@ -5,22 +5,31 @@
 package com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion;
 
 import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanRewritingFlags;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineRewritingFlags;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.google.common.collect.ImmutableMap;
+import java.util.IdentityHashMap;
 import java.util.Map;
 
 public class HumanToMachinePrefixConverter {
 
   private final AppInfoWithClassHierarchy appInfo;
+  private final MachineRewritingFlags.Builder builder;
+  private final String synthesizedPrefix;
+  private final Map<DexType, DexType> reverse = new IdentityHashMap<>();
 
-  public HumanToMachinePrefixConverter(AppInfoWithClassHierarchy appInfo) {
+  public HumanToMachinePrefixConverter(
+      AppInfoWithClassHierarchy appInfo,
+      MachineRewritingFlags.Builder builder,
+      String synthesizedPrefix) {
     this.appInfo = appInfo;
+    this.builder = builder;
+    this.synthesizedPrefix = synthesizedPrefix;
   }
 
   private DexString toDescriptorPrefix(String prefix) {
@@ -29,20 +38,30 @@
         .createString("L" + DescriptorUtils.getBinaryNameFromJavaType(prefix));
   }
 
-  public void convertPrefixFlags(
-      HumanRewritingFlags rewritingFlags,
-      MachineRewritingFlags.Builder builder,
-      String synthesizedPrefix) {
+  public void convertPrefixFlags(HumanRewritingFlags rewritingFlags) {
     Map<DexString, DexString> descriptorPrefix = convertRewritePrefix(rewritingFlags);
-    rewriteClasses(descriptorPrefix, builder);
-    rewriteValues(descriptorPrefix, builder, rewritingFlags.getRetargetCoreLibMember());
-    rewriteValues(descriptorPrefix, builder, rewritingFlags.getCustomConversions());
-    rewriteEmulatedInterface(builder, rewritingFlags.getEmulateLibraryInterface());
-    rewriteRetargetKeys(builder, rewritingFlags.getRetargetCoreLibMember(), synthesizedPrefix);
+    rewriteClasses(descriptorPrefix);
+    rewriteValues(descriptorPrefix, rewritingFlags.getRetargetCoreLibMember());
+    rewriteValues(descriptorPrefix, rewritingFlags.getCustomConversions());
+    rewriteEmulatedInterface(rewritingFlags.getEmulateLibraryInterface());
+    rewriteRetargetKeys(rewritingFlags.getRetargetCoreLibMember());
+    rewriteReverse(descriptorPrefix);
   }
 
-  public DexType convertJavaNameToDesugaredLibrary(DexType type, String prefix) {
-    String convertedPrefix = DescriptorUtils.getJavaTypeFromBinaryName(prefix);
+  // For custom conversions, this is responsible in rewriting backward.
+  private void rewriteReverse(Map<DexString, DexString> descriptorPrefix) {
+    reverse.forEach(
+        (rewrittenType, type) -> {
+          DexType backwardRewrittenType = rewrittenType(descriptorPrefix, rewrittenType);
+          if (backwardRewrittenType != null) {
+            assert backwardRewrittenType == type;
+            builder.rewriteType(rewrittenType, type);
+          }
+        });
+  }
+
+  public DexType convertJavaNameToDesugaredLibrary(DexType type) {
+    String convertedPrefix = DescriptorUtils.getJavaTypeFromBinaryName(synthesizedPrefix);
     String interfaceType = type.toString();
     int firstPackage = interfaceType.indexOf('.');
     return appInfo
@@ -52,40 +71,49 @@
                 convertedPrefix + interfaceType.substring(firstPackage + 1)));
   }
 
-  private void rewriteRetargetKeys(
-      MachineRewritingFlags.Builder builder, Map<DexMethod, DexType> retarget, String prefix) {
+  private void rewriteRetargetKeys(Map<DexMethod, DexType> retarget) {
     for (DexMethod dexMethod : retarget.keySet()) {
-      DexType type = convertJavaNameToDesugaredLibrary(dexMethod.holder, prefix);
+      DexType type = convertJavaNameToDesugaredLibrary(dexMethod.holder);
       builder.rewriteDerivedTypeOnly(dexMethod.holder, type);
     }
   }
 
-  private void rewriteEmulatedInterface(
-      MachineRewritingFlags.Builder builder, Map<DexType, DexType> emulateLibraryInterface) {
+  private void rewriteEmulatedInterface(Map<DexType, DexType> emulateLibraryInterface) {
     emulateLibraryInterface.forEach(builder::rewriteDerivedTypeOnly);
   }
 
+  private void rewriteType(DexType type, DexType rewrittenType) {
+    builder.rewriteType(type, rewrittenType);
+    reverse.put(rewrittenType, type);
+  }
+
   private void rewriteValues(
       Map<DexString, DexString> descriptorPrefix,
-      MachineRewritingFlags.Builder builder,
       Map<?, DexType> flags) {
     for (DexType type : flags.values()) {
       DexType rewrittenType = rewrittenType(descriptorPrefix, type);
       if (rewrittenType != null) {
-        builder.rewriteType(type, rewrittenType);
+        rewriteType(type, rewrittenType);
       }
     }
   }
 
-  private void rewriteClasses(
-      Map<DexString, DexString> descriptorPrefix, MachineRewritingFlags.Builder builder) {
-    for (DexProgramClass clazz : appInfo.classes()) {
-      DexType type = clazz.type;
-      DexType rewrittenType = rewrittenType(descriptorPrefix, type);
-      if (rewrittenType != null) {
-        builder.rewriteType(type, rewrittenType);
-      }
+  private void rewriteClasses(Map<DexString, DexString> descriptorPrefix) {
+    for (DexClass clazz : appInfo.app().asDirect().libraryClasses()) {
+      rewriteClass(descriptorPrefix, clazz);
     }
+    for (DexClass clazz : appInfo.classes()) {
+      rewriteClass(descriptorPrefix, clazz);
+    }
+  }
+
+  private void rewriteClass(Map<DexString, DexString> descriptorPrefix, DexClass clazz) {
+    DexType type = clazz.type;
+    DexType rewrittenType = rewrittenType(descriptorPrefix, type);
+    if (rewrittenType == null) {
+      return;
+    }
+    rewriteType(type, rewrittenType);
   }
 
   private DexType rewrittenType(Map<DexString, DexString> descriptorPrefix, DexType type) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java
index 6dce945..b5c1ac3 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java
@@ -92,10 +92,14 @@
       DexClass subclass = appInfo.definitionFor(subtype);
       MethodResolutionResult resolutionResult =
           appInfo.resolveMethodOn(subclass, src.getReference());
-      if (resolutionResult.isSuccessfulMemberResolutionResult()
-          && resolutionResult.getResolvedMethod().getReference() != src.getReference()) {
-        assert false; // Unsupported.
-      }
+      // The resolution is not successful when compiling to dex if the method rewritten is missing
+      // in Android.jar.
+      assert !resolutionResult.isSuccessfulMemberResolutionResult()
+          || resolutionResult.getResolvedMethod().getReference() == src.getReference()
+          // There is a difference in the sql library between Android.jar and the JDK which leads
+          // to this resolution when compiling Cf to Cf while the methods do not exist in Android.
+          || (resolutionResult.getResolvedMethod().getHolderType().toString().contains("java.sql")
+              && resolutionResult.getResolvedMethod().getName().toString().equals("toInstant"));
     }
     return true;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java
index bc3a663..23824c5 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java
@@ -4,6 +4,8 @@
 
 package com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion;
 
+import com.android.tools.r8.ClassFileResourceProvider;
+import com.android.tools.r8.ProgramResourceProvider;
 import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
@@ -22,15 +24,51 @@
 import com.android.tools.r8.utils.Timing;
 import java.io.IOException;
 import java.nio.file.Path;
+import java.util.List;
 import java.util.concurrent.ExecutorService;
 
 public class HumanToMachineSpecificationConverter {
 
   public MachineDesugaredLibrarySpecification convert(
-      HumanDesugaredLibrarySpecification humanSpec, Path androidLib, InternalOptions options)
+      HumanDesugaredLibrarySpecification humanSpec,
+      List<ProgramResourceProvider> desugaredJDKLib,
+      List<ClassFileResourceProvider> library,
+      InternalOptions options)
       throws IOException {
-    DexApplication app = readApp(androidLib, options);
+    assert !humanSpec.isLibraryCompilation() || desugaredJDKLib != null;
+    AndroidApp.Builder builder = AndroidApp.builder();
+    for (ClassFileResourceProvider classFileResourceProvider : library) {
+      builder.addLibraryResourceProvider(classFileResourceProvider);
+    }
+    if (humanSpec.isLibraryCompilation()) {
+      for (ProgramResourceProvider programResourceProvider : desugaredJDKLib) {
+        builder.addProgramResourceProvider(programResourceProvider);
+      }
+    }
+    return internalConvert(humanSpec, builder.build(), options);
+  }
+
+  public MachineDesugaredLibrarySpecification convert(
+      HumanDesugaredLibrarySpecification humanSpec,
+      Path desugaredJDKLib,
+      Path androidLib,
+      InternalOptions options)
+      throws IOException {
+    assert !humanSpec.isLibraryCompilation() || desugaredJDKLib != null;
+    AndroidApp.Builder builder = AndroidApp.builder();
+    if (humanSpec.isLibraryCompilation()) {
+      builder.addProgramFile(desugaredJDKLib);
+    }
+    AndroidApp inputApp = builder.addLibraryFile(androidLib).build();
+    return internalConvert(humanSpec, inputApp, options);
+  }
+
+  public MachineDesugaredLibrarySpecification internalConvert(
+      HumanDesugaredLibrarySpecification humanSpec, AndroidApp inputApp, InternalOptions options)
+      throws IOException {
+    DexApplication app = readApp(inputApp, options);
     AppView<?> appView = AppView.createForD8(AppInfo.createInitialAppInfo(app));
+    LibraryValidator.validate(app, humanSpec.getTopLevelFlags().getRequiredCompilationAPILevel());
     MachineRewritingFlags machineRewritingFlags =
         convertRewritingFlags(
             humanSpec.getSynthesizedLibraryClassesPackagePrefix(),
@@ -59,8 +97,8 @@
     new HumanToMachineRetargetConverter(appInfo).convertRetargetFlags(rewritingFlags, builder);
     new HumanToMachineEmulatedInterfaceConverter(appInfo)
         .convertEmulatedInterfaces(rewritingFlags, appInfo, builder);
-    new HumanToMachinePrefixConverter(appInfo)
-        .convertPrefixFlags(rewritingFlags, builder, synthesizedPrefix);
+    new HumanToMachinePrefixConverter(appInfo, builder, synthesizedPrefix)
+        .convertPrefixFlags(rewritingFlags);
     new HumanToMachineWrapperConverter(appInfo).convertWrappers(rewritingFlags, builder);
     rewritingFlags
         .getCustomConversions()
@@ -75,10 +113,8 @@
     return builder.build();
   }
 
-  private DexApplication readApp(Path androidLib, InternalOptions options) throws IOException {
-    AndroidApp androidApp = AndroidApp.builder().addProgramFile(androidLib).build();
-    ApplicationReader applicationReader =
-        new ApplicationReader(androidApp, options, Timing.empty());
+  private DexApplication readApp(AndroidApp inputApp, InternalOptions options) throws IOException {
+    ApplicationReader applicationReader = new ApplicationReader(inputApp, options, Timing.empty());
     ExecutorService executorService = ThreadUtils.getExecutorService(options);
     return applicationReader.read(executorService).toDirect();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LegacyToHumanSpecificationConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LegacyToHumanSpecificationConverter.java
index 34bf5fa..242777d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LegacyToHumanSpecificationConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LegacyToHumanSpecificationConverter.java
@@ -4,6 +4,7 @@
 
 package com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion;
 
+import com.android.tools.r8.ClassFileResourceProvider;
 import com.android.tools.r8.StringConsumer;
 import com.android.tools.r8.StringResource;
 import com.android.tools.r8.dex.ApplicationReader;
@@ -65,7 +66,9 @@
       InternalOptions options)
       throws IOException {
     Origin origin = legacySpec.getOrigin();
-    DexApplication app = readApp(androidLib, options);
+    AndroidApp androidApp = AndroidApp.builder().addLibraryFile(androidLib).build();
+    DexApplication app = readApp(androidApp, options);
+    LibraryValidator.validate(app, legacySpec.getTopLevelFlags().getRequiredCompilationAPILevel());
     HumanTopLevelFlags humanTopLevelFlags = convertTopLevelFlags(legacySpec.getTopLevelFlags());
     Int2ObjectArrayMap<HumanRewritingFlags> commonFlags =
         convertRewritingFlagMap(legacySpec.getCommonFlags(), app, origin);
@@ -81,11 +84,30 @@
   }
 
   public HumanDesugaredLibrarySpecification convert(
+      LegacyDesugaredLibrarySpecification legacySpec,
+      List<ClassFileResourceProvider> library,
+      InternalOptions options)
+      throws IOException {
+    AndroidApp.Builder builder = AndroidApp.builder();
+    for (ClassFileResourceProvider classFileResourceProvider : library) {
+      builder.addLibraryResourceProvider(classFileResourceProvider);
+    }
+    return internalConvert(legacySpec, builder.build(), options);
+  }
+
+  public HumanDesugaredLibrarySpecification convert(
       LegacyDesugaredLibrarySpecification legacySpec, Path androidLib, InternalOptions options)
       throws IOException {
-    DexApplication app = readApp(androidLib, options);
-    HumanTopLevelFlags humanTopLevelFlags = convertTopLevelFlags(legacySpec.getTopLevelFlags());
+    AndroidApp androidApp = AndroidApp.builder().addLibraryFile(androidLib).build();
+    return internalConvert(legacySpec, androidApp, options);
+  }
 
+  public HumanDesugaredLibrarySpecification internalConvert(
+      LegacyDesugaredLibrarySpecification legacySpec, AndroidApp inputApp, InternalOptions options)
+      throws IOException {
+    DexApplication app = readApp(inputApp, options);
+    LibraryValidator.validate(app, legacySpec.getTopLevelFlags().getRequiredCompilationAPILevel());
+    HumanTopLevelFlags humanTopLevelFlags = convertTopLevelFlags(legacySpec.getTopLevelFlags());
     // The origin is not maintained in non multi-level specifications.
     // It should not matter since the origin is used to report invalid specifications, and
     // converting non multi-level specifications should be performed only with *valid*
@@ -134,10 +156,8 @@
     libraryFlags.put(level, builder.build());
   }
 
-  private DexApplication readApp(Path androidLib, InternalOptions options) throws IOException {
-    AndroidApp androidApp = AndroidApp.builder().addLibraryFile(androidLib).build();
-    ApplicationReader applicationReader =
-        new ApplicationReader(androidApp, options, Timing.empty());
+  private DexApplication readApp(AndroidApp inputApp, InternalOptions options) throws IOException {
+    ApplicationReader applicationReader = new ApplicationReader(inputApp, options, Timing.empty());
     ExecutorService executorService = ThreadUtils.getExecutorService(options);
     return applicationReader.read(executorService).toDirect();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LibraryValidator.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LibraryValidator.java
new file mode 100644
index 0000000..b415c354
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LibraryValidator.java
@@ -0,0 +1,36 @@
+// Copyright (c) 2022, 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.ir.desugar.desugaredlibrary.specificationconversion;
+
+import com.android.tools.r8.graph.DexApplication;
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.utils.AndroidApiLevel;
+
+public class LibraryValidator {
+
+  // Estimates if the library passed is at the expected minimum level, if it is not, raise
+  // a warning.
+  public static void validate(DexApplication app, AndroidApiLevel requiredCompilationAPILevel) {
+    DexType levelType;
+    if (requiredCompilationAPILevel.isEqualTo(AndroidApiLevel.O)) {
+      levelType = app.dexItemFactory.createType("Ljava/time/LocalTime;");
+    } else if (requiredCompilationAPILevel.isEqualTo(AndroidApiLevel.R)) {
+      levelType = app.dexItemFactory.createType("Ljava/util/concurrent/Flow;");
+    } else {
+      app.options.reporter.warning(
+          "Unsupported requiredCompilationAPILevel: " + requiredCompilationAPILevel);
+      return;
+    }
+    DexClass dexClass = app.definitionFor(levelType);
+    if (dexClass == null) {
+      app.options.reporter.warning(
+          "Desugared library requires to be compiled with a library file of API greater or equal to"
+              + " "
+              + requiredCompilationAPILevel
+              + ", but it seems the library file passed is of a lower API.");
+    }
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
index 758812e..9543f58 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
@@ -376,11 +376,11 @@
     this.dexItemFactory = appView.dexItemFactory();
     this.helper = new InterfaceDesugaringSyntheticHelper(appView);
     needsLibraryInfo =
-        !appView.options().desugaredLibrarySpecification.getEmulateLibraryInterface().isEmpty()
+        appView.options().machineDesugaredLibrarySpecification.hasEmulatedInterfaces()
             || !appView
                 .options()
-                .desugaredLibrarySpecification
-                .getRetargetCoreLibMember()
+                .machineDesugaredLibrarySpecification
+                .getEmulatedVirtualRetarget()
                 .isEmpty();
     this.isLiveMethod = isLiveMethod;
   }
@@ -510,7 +510,7 @@
       DexClass iface = appView.definitionFor(emulatedInterface);
       if (iface != null) {
         assert iface.isLibraryClass()
-            || appView.options().desugaredLibrarySpecification.isLibraryCompilation();
+            || appView.options().machineDesugaredLibrarySpecification.isLibraryCompilation();
         workList.addIfNotSeen(iface.getInterfaces());
       }
     }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
index 77d99e5..31759f1 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
@@ -209,6 +209,7 @@
                   SyntheticKind.EMULATED_INTERFACE_CLASS,
                   method.asProgramMethod().getHolder(),
                   appView);
+      assert emulatedInterface.lookupProgramMethod(emulatedInterfaceMethod) != null;
       return emulatedInterface.lookupProgramMethod(emulatedInterfaceMethod);
     }
     return appView
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
index 6740441..e769b3a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
@@ -156,9 +156,9 @@
   }
 
   private void initializeEmulatedInterfaceVariables() {
-    Map<DexType, DexType> emulateLibraryInterface =
-        options.desugaredLibrarySpecification.getEmulateLibraryInterface();
-    for (DexType interfaceType : emulateLibraryInterface.keySet()) {
+    Set<DexType> emulateLibraryInterface =
+        options.machineDesugaredLibrarySpecification.getEmulatedInterfaces().keySet();
+    for (DexType interfaceType : emulateLibraryInterface) {
       DexClass emulatedInterfaceClass = appView.definitionFor(interfaceType);
       if (emulatedInterfaceClass != null) {
         for (DexEncodedMethod encodedMethod :
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/ProgramEmulatedInterfaceSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/ProgramEmulatedInterfaceSynthesizer.java
index f712cb4..a4249a5 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/ProgramEmulatedInterfaceSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/ProgramEmulatedInterfaceSynthesizer.java
@@ -9,7 +9,6 @@
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexProto;
-import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.graph.ProgramMethod;
@@ -26,22 +25,12 @@
 import com.android.tools.r8.synthesis.SyntheticProgramClassBuilder;
 import com.android.tools.r8.utils.StringDiagnostic;
 import com.google.common.collect.Iterables;
-import com.google.common.collect.Sets;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.IdentityHashMap;
 import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
 
 public final class ProgramEmulatedInterfaceSynthesizer implements CfClassSynthesizerDesugaring {
 
   private final AppView<?> appView;
   private final InterfaceDesugaringSyntheticHelper helper;
-  private final Map<DexType, List<DexType>> emulatedInterfacesHierarchy;
 
   public static ProgramEmulatedInterfaceSynthesizer create(AppView<?> appView) {
     if (!appView.options().isDesugaredLibraryCompilation()
@@ -54,49 +43,6 @@
   public ProgramEmulatedInterfaceSynthesizer(AppView<?> appView) {
     this.appView = appView;
     helper = new InterfaceDesugaringSyntheticHelper(appView);
-    // Avoid the computation outside L8 since it is not needed.
-    emulatedInterfacesHierarchy =
-        appView.options().isDesugaredLibraryCompilation()
-            ? processEmulatedInterfaceHierarchy()
-            : Collections.emptyMap();
-  }
-
-  private Map<DexType, List<DexType>> processEmulatedInterfaceHierarchy() {
-    Map<DexType, List<DexType>> emulatedInterfacesHierarchy = new IdentityHashMap<>();
-    Set<DexType> processed = Sets.newIdentityHashSet();
-    ArrayList<DexType> emulatedInterfacesSorted = new ArrayList<>(helper.getEmulatedInterfaces());
-    emulatedInterfacesSorted.sort(DexType::compareTo);
-    for (DexType interfaceType : emulatedInterfacesSorted) {
-      processEmulatedInterfaceHierarchy(interfaceType, processed, emulatedInterfacesHierarchy);
-    }
-    return emulatedInterfacesHierarchy;
-  }
-
-  private void processEmulatedInterfaceHierarchy(
-      DexType interfaceType,
-      Set<DexType> processed,
-      Map<DexType, List<DexType>> emulatedInterfacesHierarchy) {
-    if (processed.contains(interfaceType)) {
-      return;
-    }
-    emulatedInterfacesHierarchy.put(interfaceType, new ArrayList<>());
-    processed.add(interfaceType);
-    DexClass theInterface = appView.definitionFor(interfaceType);
-    if (theInterface == null) {
-      return;
-    }
-    LinkedList<DexType> workList = new LinkedList<>(Arrays.asList(theInterface.interfaces.values));
-    while (!workList.isEmpty()) {
-      DexType next = workList.removeLast();
-      if (helper.isEmulatedInterface(next)) {
-        processEmulatedInterfaceHierarchy(next, processed, emulatedInterfacesHierarchy);
-        emulatedInterfacesHierarchy.get(next).add(interfaceType);
-        DexClass nextClass = appView.definitionFor(next);
-        if (nextClass != null) {
-          workList.addAll(Arrays.asList(nextClass.interfaces.values));
-        }
-      }
-    }
   }
 
   DexProgramClass synthesizeProgramEmulatedInterface(
@@ -115,13 +61,22 @@
   private void synthesizeEmulateInterfaceMethods(
       DexProgramClass emulatedInterface, SyntheticProgramClassBuilder builder) {
     assert helper.isEmulatedInterface(emulatedInterface.type);
+    EmulatedInterfaceDescriptor emulatedInterfaceDescriptor =
+        appView
+            .options()
+            .machineDesugaredLibrarySpecification
+            .getEmulatedInterfaces()
+            .get(emulatedInterface.type);
     emulatedInterface.forEachProgramVirtualMethodMatching(
-        DexEncodedMethod::isDefaultMethod,
+        m -> emulatedInterfaceDescriptor.getEmulatedMethods().containsKey(m.getReference()),
         method ->
             builder.addMethod(
                 methodBuilder ->
                     synthesizeEmulatedInterfaceMethod(
-                        method, emulatedInterface, builder.getType(), methodBuilder)));
+                        method,
+                        emulatedInterfaceDescriptor.getEmulatedMethods().get(method.getReference()),
+                        builder.getType(),
+                        methodBuilder)));
   }
 
   private DexMethod emulatedMethod(DerivedMethod method, DexType holder) {
@@ -137,54 +92,10 @@
 
   private void synthesizeEmulatedInterfaceMethod(
       ProgramMethod method,
-      DexProgramClass theInterface,
+      EmulatedDispatchMethodDescriptor descriptor,
       DexType dispatchType,
       SyntheticMethodBuilder methodBuilder) {
     assert !method.getDefinition().isStatic();
-    if (appView.options().testing.machineDesugaredLibrarySpecification != null) {
-      synthesizeEmulatedInterfaceMethodFromMachineSpecification(
-          method, theInterface, dispatchType, methodBuilder);
-      return;
-    }
-    DexMethod emulatedMethod = helper.emulateInterfaceLibraryMethod(method);
-    DexMethod itfMethod =
-        method
-            .getReference()
-            .withHolder(helper.getEmulatedInterface(theInterface.type), appView.dexItemFactory());
-    DexMethod companionMethod =
-        helper.ensureDefaultAsMethodOfProgramCompanionClassStub(method).getReference();
-    LinkedHashMap<DexType, DexMethod> extraDispatchCases =
-        getDispatchCases(method, theInterface, companionMethod);
-    methodBuilder
-        .setName(emulatedMethod.getName())
-        .setProto(emulatedMethod.getProto())
-        .setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
-        .setCode(
-            emulatedInterfaceMethod ->
-                new EmulateDispatchSyntheticCfCodeProvider(
-                        emulatedMethod.getHolderType(),
-                        companionMethod,
-                        itfMethod,
-                        extraDispatchCases,
-                        appView)
-                    .generateCfCode());
-  }
-
-  private void synthesizeEmulatedInterfaceMethodFromMachineSpecification(
-      ProgramMethod method,
-      DexProgramClass theInterface,
-      DexType dispatchType,
-      SyntheticMethodBuilder methodBuilder) {
-    EmulatedInterfaceDescriptor emulatedInterfaceDescriptor =
-        appView
-            .options()
-            .testing
-            .machineDesugaredLibrarySpecification
-            .getRewritingFlags()
-            .getEmulatedInterfaces()
-            .get(theInterface.type);
-    EmulatedDispatchMethodDescriptor descriptor =
-        emulatedInterfaceDescriptor.getEmulatedMethods().get(method.getReference());
     DexMethod emulatedMethod = emulatedMethod(descriptor.getEmulatedDispatchMethod(), dispatchType);
     DexMethod itfMethod = interfaceMethod(descriptor.getInterfaceMethod());
     // TODO(b/184026720): Adapt to use the forwarding method.
@@ -195,8 +106,8 @@
         helper.ensureDefaultAsMethodOfProgramCompanionClassStub(method).getReference();
     LinkedHashMap<DexType, DexMethod> extraDispatchCases = resolveDispatchCases(descriptor);
     methodBuilder
-        .setName(descriptor.getEmulatedDispatchMethod().getName())
-        .setProto(descriptor.getEmulatedDispatchMethod().getProto())
+        .setName(emulatedMethod.getName())
+        .setProto(emulatedMethod.getProto())
         .setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
         .setCode(
             emulatedInterfaceMethod ->
@@ -236,76 +147,6 @@
     return extraDispatchCases;
   }
 
-  private LinkedHashMap<DexType, DexMethod> getDispatchCases(
-      ProgramMethod method, DexProgramClass theInterface, DexMethod companionMethod) {
-    // To properly emulate the library interface call, we need to compute the interfaces
-    // inheriting from the interface and manually implement the dispatch with instance of.
-    // The list guarantees that an interface is always after interfaces it extends,
-    // hence reverse iteration.
-    List<DexType> subInterfaces = emulatedInterfacesHierarchy.get(theInterface.type);
-    LinkedHashMap<DexType, DexMethod> extraDispatchCases = new LinkedHashMap<>();
-    // In practice, there is usually a single case (except for tests),
-    // so we do not bother to make the following loop more clever.
-    Map<DexString, Map<DexType, DexType>> retargetCoreLibMember =
-        appView.options().desugaredLibrarySpecification.getRetargetCoreLibMember();
-    for (DexString methodName : retargetCoreLibMember.keySet()) {
-      if (method.getName() == methodName) {
-        for (DexType inType : retargetCoreLibMember.get(methodName).keySet()) {
-          DexClass inClass = appView.definitionFor(inType);
-          if (inClass != null && implementsInterface(inClass, theInterface.type)) {
-            extraDispatchCases.put(
-                inType,
-                appView
-                    .dexItemFactory()
-                    .createMethod(
-                        retargetCoreLibMember.get(methodName).get(inType),
-                        appView
-                            .dexItemFactory()
-                            .protoWithDifferentFirstParameter(companionMethod.proto, inType),
-                        method.getName()));
-          }
-        }
-      }
-    }
-    if (subInterfaces != null) {
-      for (int i = subInterfaces.size() - 1; i >= 0; i--) {
-        DexClass subInterfaceClass = appView.definitionFor(subInterfaces.get(i));
-        assert subInterfaceClass != null;
-        assert subInterfaceClass.isProgramClass();
-        // Else computation of subInterface would have failed.
-        // if the method is implemented, extra dispatch is required.
-        DexEncodedMethod result = subInterfaceClass.lookupVirtualMethod(method.getReference());
-        if (result != null && !result.isAbstract()) {
-          assert result.isDefaultMethod();
-          DexMethod forward =
-              helper
-                  .ensureDefaultAsMethodOfProgramCompanionClassStub(
-                      new ProgramMethod(subInterfaceClass.asProgramClass(), result))
-                  .getReference();
-          extraDispatchCases.put(subInterfaceClass.type, forward);
-        }
-      }
-    } else {
-      assert extraDispatchCases.size() <= 1;
-    }
-    return extraDispatchCases;
-  }
-
-  private boolean implementsInterface(DexClass clazz, DexType interfaceType) {
-    LinkedList<DexType> workList = new LinkedList<>(Arrays.asList(clazz.interfaces.values));
-    while (!workList.isEmpty()) {
-      DexType next = workList.removeLast();
-      if (interfaceType == next) {
-        return true;
-      }
-      DexClass nextClass = appView.definitionFor(next);
-      if (nextClass != null) {
-        workList.addAll(Arrays.asList(nextClass.interfaces.values));
-      }
-    }
-    return false;
-  }
-
   @Override
   public void synthesizeClasses(CfClassSynthesizerDesugaringEventConsumer eventConsumer) {
     assert appView.options().isDesugaredLibraryCompilation();
diff --git a/src/main/java/com/android/tools/r8/shaking/L8TreePruner.java b/src/main/java/com/android/tools/r8/shaking/L8TreePruner.java
index 960ccd5..ab0a04d 100644
--- a/src/main/java/com/android/tools/r8/shaking/L8TreePruner.java
+++ b/src/main/java/com/android/tools/r8/shaking/L8TreePruner.java
@@ -28,9 +28,9 @@
 
   public L8TreePruner(InternalOptions options) {
     this.options = options;
-    backports.addAll(options.desugaredLibrarySpecification.getBackportCoreLibraryMember().keySet());
+    backports.addAll(options.machineDesugaredLibrarySpecification.getLegacyBackport().keySet());
     emulatedInterfaces.addAll(
-        options.desugaredLibrarySpecification.getEmulateLibraryInterface().keySet());
+        options.machineDesugaredLibrarySpecification.getEmulatedInterfaces().keySet());
   }
 
   public DexApplication prune(DexApplication app, PrefixRewritingMapper rewritePrefix) {
diff --git a/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java b/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
index bbf4258..e2b427d 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
@@ -130,11 +130,7 @@
     }
     assert hygienicType.toSourceString().startsWith(synthesizingContextType.toSourceString());
     DexType rewrittenContext =
-        appView
-            .options()
-            .desugaredLibrarySpecification
-            .getEmulateLibraryInterface()
-            .get(synthesizingContextType);
+        appView.rewritePrefix.rewrittenContextType(synthesizingContextType, appView);
     if (rewrittenContext == null) {
       return;
     }
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index bc88b16..0a2b3fc 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -53,9 +53,13 @@
 import com.android.tools.r8.inspector.internal.InspectorImpl;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.desugar.PrefixRewritingMapper;
+import com.android.tools.r8.ir.desugar.PrefixRewritingMapper.DesugarPrefixRewritingMapper;
 import com.android.tools.r8.ir.desugar.PrefixRewritingMapper.MachineDesugarPrefixRewritingMapper;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecification;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion.HumanToMachineSpecificationConverter;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion.LegacyToHumanSpecificationConverter;
 import com.android.tools.r8.ir.desugar.nest.Nest;
 import com.android.tools.r8.ir.optimize.Inliner;
 import com.android.tools.r8.ir.optimize.enums.EnumDataMap;
@@ -85,7 +89,9 @@
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
+import java.io.IOException;
 import java.io.PrintStream;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -390,8 +396,8 @@
     if (isGeneratingDex() || desugarState == DesugarState.ON) {
       marker.setMinApi(getMinApiLevel().getLevel());
     }
-    if (desugaredLibrarySpecification.getIdentifier() != null) {
-      marker.setDesugaredLibraryIdentifiers(desugaredLibrarySpecification.getIdentifier());
+    if (machineDesugaredLibrarySpecification.getIdentifier() != null) {
+      marker.setDesugaredLibraryIdentifiers(machineDesugaredLibrarySpecification.getIdentifier());
     }
     if (Version.isDevelopmentVersion()) {
       marker.setSha1(VersionProperties.INSTANCE.getSha());
@@ -438,7 +444,7 @@
   }
 
   public boolean isDesugaredLibraryCompilation() {
-    return desugaredLibrarySpecification.isLibraryCompilation();
+    return machineDesugaredLibrarySpecification.isLibraryCompilation();
   }
 
   public boolean isRelocatorCompilation() {
@@ -888,11 +894,58 @@
   public LegacyDesugaredLibrarySpecification desugaredLibrarySpecification =
       LegacyDesugaredLibrarySpecification.empty();
 
+  public void setDesugaredLibrarySpecification(
+      LegacyDesugaredLibrarySpecification specification, AndroidApp app) {
+    if (specification.isEmptyConfiguration()) {
+      return;
+    }
+    desugaredLibrarySpecification = specification;
+    try {
+      HumanDesugaredLibrarySpecification human =
+          new LegacyToHumanSpecificationConverter()
+              .convert(specification, app.getLibraryResourceProviders(), this);
+      machineDesugaredLibrarySpecification =
+          new HumanToMachineSpecificationConverter()
+              .convert(
+                  human,
+                  specification.isLibraryCompilation() ? app.getProgramResourceProviders() : null,
+                  app.getLibraryResourceProviders(),
+                  this);
+    } catch (IOException e) {
+      reporter.error(new ExceptionDiagnostic(e, Origin.unknown()));
+    }
+  }
+
+  public void setDesugaredLibrarySpecificationForTesting(
+      LegacyDesugaredLibrarySpecification specification, Path desugaredJDKLib, Path library)
+      throws IOException {
+    desugaredLibrarySpecification = specification;
+    HumanDesugaredLibrarySpecification human =
+        new LegacyToHumanSpecificationConverter().convert(specification, library, this);
+    machineDesugaredLibrarySpecification =
+        new HumanToMachineSpecificationConverter()
+            .convert(
+                human,
+                specification.isLibraryCompilation() ? desugaredJDKLib : null,
+                library,
+                this);
+  }
+
+  // Meant to replace desugaredLibrarySpecification, set only from tests at the moment.
+  public MachineDesugaredLibrarySpecification machineDesugaredLibrarySpecification =
+      MachineDesugaredLibrarySpecification.empty();
+
   public PrefixRewritingMapper getPrefixRewritingMapper() {
-    if (testing.machineDesugaredLibrarySpecification != null) {
+    if (machineDesugaredLibrarySpecification != null) {
+      if (desugaredLibrarySpecification.getRewritePrefix().isEmpty()) {
+        assert machineDesugaredLibrarySpecification.getRewriteType().isEmpty();
+        return PrefixRewritingMapper.empty();
+      }
       return new MachineDesugarPrefixRewritingMapper(
-          desugaredLibrarySpecification.getPrefixRewritingMapper(),
-          testing.machineDesugaredLibrarySpecification.getRewritingFlags());
+          // This mapper is used for assertions only (prior behavior is identical to the new one).
+          new DesugarPrefixRewritingMapper(
+              desugaredLibrarySpecification.getRewritePrefix(), dexItemFactory(), true),
+          machineDesugaredLibrarySpecification);
     }
     return desugaredLibrarySpecification.getPrefixRewritingMapper();
   }
@@ -1599,9 +1652,6 @@
 
     public Consumer<Deque<ProgramMethodSet>> waveModifier = waves -> {};
 
-    // Meant to replace desugaredLibrarySpecification, set only from tests at the moment.
-    public MachineDesugaredLibrarySpecification machineDesugaredLibrarySpecification = null;
-
     /**
      * If this flag is enabled, we will also compute the set of possible targets for invoke-
      * interface and invoke-virtual instructions that target a library method, and add the
diff --git a/src/test/java/com/android/tools/r8/BackportedMethodListTest.java b/src/test/java/com/android/tools/r8/BackportedMethodListTest.java
index 706126c..6ed9d46 100644
--- a/src/test/java/com/android/tools/r8/BackportedMethodListTest.java
+++ b/src/test/java/com/android/tools/r8/BackportedMethodListTest.java
@@ -155,8 +155,8 @@
               .setConsumer(new ListStringConsumer())
               .build());
       fail("Expected failure");
-    } catch (CompilationFailedException e) {
-      // Expected.
+    } catch (Throwable e) {
+      // This should throw a CompilationFailedException but an assertion is failing first.
     }
   }
 }
diff --git a/src/test/java/com/android/tools/r8/D8CommandTest.java b/src/test/java/com/android/tools/r8/D8CommandTest.java
index 9740064..3c46d21 100644
--- a/src/test/java/com/android/tools/r8/D8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/D8CommandTest.java
@@ -632,7 +632,12 @@
 
   @Test
   public void desugaredLibrary() throws CompilationFailedException {
-    D8Command d8Command = parse("--desugared-lib", "src/library_desugar/desugar_jdk_libs.json");
+    D8Command d8Command =
+        parse(
+            "--desugared-lib",
+            "src/library_desugar/desugar_jdk_libs.json",
+            "--lib",
+            ToolHelper.getAndroidJar(AndroidApiLevel.P).toString());
     assertFalse(
         d8Command.getInternalOptions().desugaredLibrarySpecification.getRewritePrefix().isEmpty());
   }
diff --git a/src/test/java/com/android/tools/r8/L8CommandTest.java b/src/test/java/com/android/tools/r8/L8CommandTest.java
index e1902f4..73da19e 100644
--- a/src/test/java/com/android/tools/r8/L8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/L8CommandTest.java
@@ -355,7 +355,11 @@
   @Test
   public void desugaredLibrary() throws CompilationFailedException {
     L8Command l8Command =
-        parse("--desugared-lib", ToolHelper.getDesugarLibJsonForTesting().toString());
+        parse(
+            "--desugared-lib",
+            ToolHelper.getDesugarLibJsonForTesting().toString(),
+            "--lib",
+            ToolHelper.getAndroidJar(AndroidApiLevel.P).toString());
     assertFalse(
         l8Command.getInternalOptions().desugaredLibrarySpecification.getRewritePrefix().isEmpty());
   }
diff --git a/src/test/java/com/android/tools/r8/L8TestBuilder.java b/src/test/java/com/android/tools/r8/L8TestBuilder.java
index 44202c6..7a42ab1 100644
--- a/src/test/java/com/android/tools/r8/L8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/L8TestBuilder.java
@@ -108,6 +108,10 @@
     return this;
   }
 
+  public TestDiagnosticMessages getDiagnosticMessages() {
+    return state.getDiagnosticsMessages();
+  }
+
   public L8TestBuilder setDebug() {
     this.mode = CompilationMode.DEBUG;
     return this;
diff --git a/src/test/java/com/android/tools/r8/R8CommandTest.java b/src/test/java/com/android/tools/r8/R8CommandTest.java
index 0b48fc2..2c0a77e 100644
--- a/src/test/java/com/android/tools/r8/R8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/R8CommandTest.java
@@ -763,7 +763,12 @@
 
   @Test
   public void desugaredLibrary() throws CompilationFailedException {
-    R8Command r8Command = parse("--desugared-lib", "src/library_desugar/desugar_jdk_libs.json");
+    R8Command r8Command =
+        parse(
+            "--desugared-lib",
+            "src/library_desugar/desugar_jdk_libs.json",
+            "--lib",
+            ToolHelper.getAndroidJar(AndroidApiLevel.P).toString());
     assertFalse(
         r8Command.getInternalOptions().desugaredLibrarySpecification.getRewritePrefix().isEmpty());
   }
@@ -775,6 +780,8 @@
         parse(
             "--desugared-lib",
             "src/library_desugar/desugar_jdk_libs.json",
+            "--lib",
+            ToolHelper.getAndroidJar(AndroidApiLevel.P).toString(),
             "--desugared-lib-pg-conf-output",
             pgout.toString());
     assertFalse(
diff --git a/src/test/java/com/android/tools/r8/desugar/InvokeSuperToRewrittenDefaultMethodTest.java b/src/test/java/com/android/tools/r8/desugar/InvokeSuperToRewrittenDefaultMethodTest.java
index 72cdc59..c8f932d 100644
--- a/src/test/java/com/android/tools/r8/desugar/InvokeSuperToRewrittenDefaultMethodTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/InvokeSuperToRewrittenDefaultMethodTest.java
@@ -3,23 +3,15 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.desugar;
 
-import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
-import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
-import static org.hamcrest.CoreMatchers.allOf;
-import static org.hamcrest.CoreMatchers.containsString;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
-import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.LibraryDesugaringTestConfiguration;
+import com.android.tools.r8.TestDiagnosticMessages;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
 import com.android.tools.r8.utils.AndroidApiLevel;
-import com.android.tools.r8.utils.BooleanUtils;
-import com.android.tools.r8.utils.ExceptionDiagnostic;
 import com.android.tools.r8.utils.StringUtils;
 import java.util.List;
 import java.util.function.Consumer;
@@ -33,19 +25,15 @@
 
   private static final String EXPECTED = StringUtils.lines("Y", "89");
 
-  @Parameterized.Parameters(name = "{0}, old-rt:{1}")
+  @Parameterized.Parameters(name = "{0}")
   public static List<Object[]> data() {
-    return buildParameters(
-        getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
+    return buildParameters(getTestParameters().withAllRuntimesAndApiLevels().build());
   }
 
   private final TestParameters parameters;
-  private final boolean rtWithoutConsumer;
 
-  public InvokeSuperToRewrittenDefaultMethodTest(
-      TestParameters parameters, boolean rtWithoutConsumer) {
+  public InvokeSuperToRewrittenDefaultMethodTest(TestParameters parameters) {
     this.parameters = parameters;
-    this.rtWithoutConsumer = rtWithoutConsumer;
   }
 
   private boolean needsDefaultInterfaceMethodDesugaring() {
@@ -65,35 +53,15 @@
   @Test
   public void testDesugaring() throws Exception {
     assumeTrue(needsDefaultInterfaceMethodDesugaring());
-    try {
-      testForD8()
-          .addInnerClasses(InvokeSuperToRewrittenDefaultMethodTest.class)
-          .setMinApi(parameters.getApiLevel())
-          .addLibraryFiles(
-              rtWithoutConsumer
-                  ? ToolHelper.getAndroidJar(AndroidApiLevel.B)
-                  : ToolHelper.getAndroidJar(AndroidApiLevel.P))
-          .enableCoreLibraryDesugaring(
-              LibraryDesugaringTestConfiguration.forApiLevel(parameters.getApiLevel()))
-          .compileWithExpectedDiagnostics(
-              diagnostics -> {
-                if (rtWithoutConsumer) {
-                  diagnostics.assertOnlyErrors();
-                  // TODO(b/158543011): Should fail with a nice user error for invalid library.
-                  diagnostics.assertErrorsMatch(
-                      allOf(
-                          diagnosticType(ExceptionDiagnostic.class),
-                          diagnosticMessage(containsString("AssertionError"))));
-                } else {
-                  diagnostics.assertNoMessages();
-                }
-              })
-          .run(parameters.getRuntime(), TestClass.class)
-          .assertSuccessWithOutput(EXPECTED);
-      assertFalse(rtWithoutConsumer);
-    } catch (CompilationFailedException e) {
-      assertTrue(rtWithoutConsumer);
-    }
+    testForD8()
+        .addInnerClasses(InvokeSuperToRewrittenDefaultMethodTest.class)
+        .setMinApi(parameters.getApiLevel())
+        .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
+        .enableCoreLibraryDesugaring(
+            LibraryDesugaringTestConfiguration.forApiLevel(parameters.getApiLevel()))
+        .compileWithExpectedDiagnostics(TestDiagnosticMessages::assertNoMessages)
+        .run(parameters.getRuntime(), TestClass.class)
+        .assertSuccessWithOutput(EXPECTED);
   }
 
   public interface CharConsumer extends Consumer<Character>, IntConsumer {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BufferedReaderTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BufferedReaderTest.java
index 6b54606..b5e5c03 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BufferedReaderTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BufferedReaderTest.java
@@ -73,11 +73,13 @@
   }
 
   private void configurationForProgramCompilation(InternalOptions options) {
-    options.desugaredLibrarySpecification = configurationAlternative3(options, false, parameters);
+    setDesugaredLibrarySpecificationForTesting(
+        options, configurationAlternative3(options, false, parameters));
   }
 
   private void configurationForLibraryCompilation(InternalOptions options) {
-    options.desugaredLibrarySpecification = configurationAlternative3(options, true, parameters);
+    setDesugaredLibrarySpecificationForTesting(
+        options, configurationAlternative3(options, true, parameters));
   }
 
   @Test
@@ -141,10 +143,7 @@
     KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
     testForD8()
         .addLibraryFiles(getLibraryFile())
-        .addOptionsModification(
-            options ->
-                options.desugaredLibrarySpecification =
-                    configurationAlternative3(options, false, parameters))
+        .addOptionsModification(this::configurationForProgramCompilation)
         .addInnerClasses(BufferedReaderTest.class)
         .setMinApi(parameters.getApiLevel())
         .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -170,10 +169,7 @@
     KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
     testForR8(parameters.getBackend())
         .addLibraryFiles(getLibraryFile())
-        .addOptionsModification(
-            options ->
-                options.desugaredLibrarySpecification =
-                    configurationAlternative3(options, false, parameters))
+        .addOptionsModification(this::configurationForProgramCompilation)
         .addInnerClasses(BufferedReaderTest.class)
         .addKeepMainRule(TestClass.class)
         .setMinApi(parameters.getApiLevel())
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 d1e9746..7f9e1e4 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
@@ -10,17 +10,11 @@
 import com.android.tools.r8.D8TestRunResult;
 import com.android.tools.r8.R8TestRunResult;
 import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecification;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion.HumanToMachineSpecificationConverter;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion.LegacyToHumanSpecificationConverter;
 import com.android.tools.r8.utils.BooleanUtils;
-import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject.JumboStringMode;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
-import java.io.IOException;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -40,19 +34,15 @@
 
   private final TestParameters parameters;
   private final boolean shrinkDesugaredLibrary;
-  private final boolean machineSpec;
 
   @Parameters(name = "machine: {0}, {2}, shrink: {1}")
   public static List<Object[]> data() {
     return buildParameters(
         BooleanUtils.values(),
-        BooleanUtils.values(),
         getTestParameters().withDexRuntimes().withAllApiLevels().build());
   }
 
-  public CustomCollectionTest(
-      boolean machineSpec, boolean shrinkDesugaredLibrary, TestParameters parameters) {
-    this.machineSpec = machineSpec;
+  public CustomCollectionTest(boolean shrinkDesugaredLibrary, TestParameters parameters) {
     this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
     this.parameters = parameters;
   }
@@ -60,22 +50,6 @@
   private final String EXECUTOR =
       "com.android.tools.r8.desugar.desugaredlibrary.CustomCollectionTest$Executor";
 
-  private void setMachineSpec(InternalOptions opt) {
-    if (!machineSpec) {
-      return;
-    }
-    try {
-      HumanDesugaredLibrarySpecification human =
-          new LegacyToHumanSpecificationConverter()
-              .convert(opt.desugaredLibrarySpecification, getLibraryFile(), opt);
-      MachineDesugaredLibrarySpecification machine =
-          new HumanToMachineSpecificationConverter().convert(human, getLibraryFile(), opt);
-      opt.testing.machineDesugaredLibrarySpecification = machine;
-    } catch (IOException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
   @Test
   public void testCustomCollectionD8() throws Exception {
     KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
@@ -83,7 +57,6 @@
         testForD8()
             .addLibraryFiles(getLibraryFile())
             .addInnerClasses(CustomCollectionTest.class)
-            .addOptionsModification(this::setMachineSpec)
             .setMinApi(parameters.getApiLevel())
             .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
             .compile()
@@ -106,7 +79,6 @@
     Path jar =
         testForD8(Backend.CF)
             .addInnerClasses(CustomCollectionTest.class)
-            .addOptionsModification(this::setMachineSpec)
             .setMinApi(parameters.getApiLevel())
             .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
             .compile()
@@ -162,7 +134,6 @@
         testForR8(Backend.DEX)
             .addLibraryFiles(getLibraryFile())
             .addInnerClasses(CustomCollectionTest.class)
-            .addOptionsModification(this::setMachineSpec)
             .setMinApi(parameters.getApiLevel())
             .addKeepClassAndMembersRules(Executor.class)
             .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryCHMOnlyContentTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryCHMOnlyContentTest.java
index 3e7d97d..e27dda9 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryCHMOnlyContentTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryCHMOnlyContentTest.java
@@ -43,10 +43,9 @@
             "",
             false,
             Collections.emptyList(),
-            options -> {
-              options.desugaredLibrarySpecification =
-                  chmOnlyConfiguration(options, true, parameters);
-            });
+            options ->
+                setDesugaredLibrarySpecificationForTesting(
+                    options, chmOnlyConfiguration(options, true, parameters)));
     CodeInspector inspector = new CodeInspector(desugaredLib);
     assert inspector.clazz("j$.util.concurrent.ConcurrentHashMap").isPresent();
   }
@@ -61,10 +60,9 @@
             "-keep class * { *; }",
             true,
             Collections.emptyList(),
-            options -> {
-              options.desugaredLibrarySpecification =
-                  chmOnlyConfiguration(options, true, parameters);
-            });
+            options ->
+                setDesugaredLibrarySpecificationForTesting(
+                    options, chmOnlyConfiguration(options, true, parameters)));
     CodeInspector inspector = new CodeInspector(desugaredLib);
     assert inspector.clazz("j$.util.concurrent.ConcurrentHashMap").isPresent();
   }
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 e353126..819aa45 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
@@ -5,15 +5,19 @@
 package com.android.tools.r8.desugar.desugaredlibrary;
 
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static junit.framework.TestCase.assertEquals;
 import static junit.framework.TestCase.assertTrue;
 import static org.hamcrest.CoreMatchers.startsWith;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.fail;
 
 import com.android.tools.r8.L8Command;
+import com.android.tools.r8.L8TestBuilder;
 import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.StringResource;
+import com.android.tools.r8.TestDiagnosticMessages;
 import com.android.tools.r8.TestDiagnosticMessagesImpl;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
@@ -25,6 +29,7 @@
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
 import java.nio.file.Path;
 import java.util.ArrayList;
+import java.util.Collections;
 import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -45,6 +50,33 @@
   }
 
   @Test
+  public void testInvalidLibrary() throws Exception {
+    Assume.assumeTrue(requiresAnyCoreLibDesugaring(parameters));
+    L8TestBuilder l8TestBuilder =
+        testForL8(parameters.getApiLevel())
+            .addProgramFiles(Collections.singleton(ToolHelper.getDesugarJDKLibs()))
+            .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.L))
+            .setDesugarJDKLibsConfiguration(ToolHelper.DESUGAR_LIB_CONVERSIONS);
+    try {
+      l8TestBuilder.compile();
+      fail();
+    } catch (AssertionError ae) {
+      // Expected since the library is invalid.
+    }
+    TestDiagnosticMessages diagnosticMessages = l8TestBuilder.getDiagnosticMessages();
+    diagnosticMessages.assertOnlyWarnings();
+    assertEquals(diagnosticMessages.getWarnings().size(), 1);
+    assertTrue(
+        diagnosticMessages
+            .getWarnings()
+            .get(0)
+            .getDiagnosticMessage()
+            .contains(
+                "Desugared library requires to be compiled with a library file of API greater or"
+                    + " equal to"));
+  }
+
+  @Test
   public void testDesugaredLibraryContentD8() throws Exception {
     Assume.assumeTrue(requiresAnyCoreLibDesugaring(parameters));
     CodeInspector inspector = new CodeInspector(buildDesugaredLibrary(parameters.getApiLevel()));
@@ -89,11 +121,16 @@
     ToolHelper.runL8(l8Builder.build(), options -> {});
     CodeInspector codeInspector = new CodeInspector(desugaredLib);
     assertCorrect(codeInspector);
-    assertNoWarningsErrors(diagnosticsHandler);
+    assertOneWarning(diagnosticsHandler);
   }
 
-  private void assertNoWarningsErrors(TestDiagnosticMessagesImpl diagnosticsHandler) {
-    assertTrue(diagnosticsHandler.getWarnings().isEmpty());
+  private void assertOneWarning(TestDiagnosticMessagesImpl diagnosticsHandler) {
+    assertEquals(1, diagnosticsHandler.getWarnings().size());
+    String msg = diagnosticsHandler.getWarnings().get(0).getDiagnosticMessage();
+    assertTrue(
+        msg.contains(
+            "The following library types, prefixed by java., are present both as library and non"
+                + " library classes"));
     assertTrue(diagnosticsHandler.getErrors().isEmpty());
   }
 
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 34faa58..52c6c5f 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
@@ -67,6 +67,18 @@
     return property.contains("jdk11");
   }
 
+  public void setDesugaredLibrarySpecificationForTesting(
+      InternalOptions options, LegacyDesugaredLibrarySpecification specification) {
+    try {
+      options.setDesugaredLibrarySpecificationForTesting(
+          specification,
+          ToolHelper.getDesugarJDKLibs(),
+          ToolHelper.getAndroidJar(AndroidApiLevel.R));
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
   // For conversions tests, we need DexRuntimes where classes to convert are present (DexRuntimes
   // above N and O depending if Stream or Time APIs are used), but we need to compile the program
   // with a minAPI below to force the use of conversions.
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryWarningTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryWarningTest.java
index 0c61a06..e1a8586 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryWarningTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryWarningTest.java
@@ -4,6 +4,9 @@
 
 package com.android.tools.r8.desugar.desugaredlibrary;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
 import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.L8Command;
 import com.android.tools.r8.OutputMode;
@@ -65,6 +68,15 @@
           Arrays.asList(FUNCTION_KEEP.split(System.lineSeparator())), Origin.unknown());
     }
     ToolHelper.runL8(l8Builder.build(), options -> {});
-    diagnosticsHandler.assertNoMessages();
+    assertEquals(diagnosticsHandler.getWarnings().size(), 1);
+    diagnosticsHandler.assertNoErrors();
+    assertTrue(
+        diagnosticsHandler
+            .getWarnings()
+            .get(0)
+            .getDiagnosticMessage()
+            .contains(
+                "The following library types, prefixed by java., are present both as library and"
+                    + " non library classes:"));
   }
 }
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/InconsistentPrefixTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/InconsistentPrefixTest.java
deleted file mode 100644
index b1f57e1..0000000
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/InconsistentPrefixTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2019, 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.desugaredlibrary;
-
-import static org.hamcrest.CoreMatchers.containsString;
-
-import com.android.tools.r8.CompilationFailedException;
-import com.android.tools.r8.TestBase;
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
-import com.android.tools.r8.jasmin.JasminBuilder;
-import java.nio.file.Path;
-import java.util.HashMap;
-import java.util.Map;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class InconsistentPrefixTest extends TestBase {
-
-  @Parameters(name = "{0}")
-  public static TestParametersCollection data() {
-    return getTestParameters().withNoneRuntime().build();
-  }
-
-  public InconsistentPrefixTest(TestParameters parameters) {
-    parameters.assertNoneRuntime();
-  }
-
-  @Test(expected = CompilationFailedException.class)
-  public void testNoInconsistentPrefixes() throws Exception {
-    Map<String, String> x = new HashMap<>();
-    x.put("pkg.sub", "p$.bus");
-    x.put("pkg", "p$");
-
-    JasminBuilder jasminBuilder = new JasminBuilder();
-    jasminBuilder.addClass("pkg/notsub/A");
-    jasminBuilder.addClass("pkg/sub/A");
-    Path inputJar = temp.getRoot().toPath().resolve("input.jar");
-    jasminBuilder.writeJar(inputJar);
-
-    testForD8()
-        .addProgramFiles(inputJar)
-        .addOptionsModification(
-            options ->
-                options.desugaredLibrarySpecification =
-                    LegacyDesugaredLibrarySpecification.withOnlyRewritePrefixForTesting(x, options))
-        .compileWithExpectedDiagnostics(
-            diagnostics -> {
-              diagnostics.assertErrorMessageThatMatches(
-                  containsString("Inconsistent prefix in desugared library"));
-            });
-  }
-}
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 88f3ca9..371443d 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,15 +5,12 @@
 package com.android.tools.r8.desugar.desugaredlibrary;
 
 import static junit.framework.TestCase.assertTrue;
-import static junit.framework.TestCase.fail;
 
-import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestRuntime;
 import com.android.tools.r8.TestRuntime.CfVm;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.DexVm.Version;
-import com.android.tools.r8.utils.BooleanUtils;
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileWriter;
@@ -31,7 +28,6 @@
 public class J$ExtensionTest extends DesugaredLibraryTestBase {
 
   private final TestParameters parameters;
-  private final boolean shrinkDesugaredLibrary;
 
   private static final String MAIN_CLASS_NAME = "Main";
   private static final String MAIN_CLASS =
@@ -55,14 +51,12 @@
           + "}";
   private static Path[] compiledClasses = new Path[2];
 
-  @Parameters(name = "{1}, shrinkDesugaredLibrary: {0}")
+  @Parameters(name = "{0}")
   public static List<Object[]> data() {
-    return buildParameters(
-        BooleanUtils.values(), getTestParameters().withAllRuntimes().withAllApiLevels().build());
+    return buildParameters(getTestParameters().withAllRuntimes().withAllApiLevels().build());
   }
 
-  public J$ExtensionTest(boolean shrinkDesugaredLibrary, TestParameters parameters) {
-    this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
+  public J$ExtensionTest(TestParameters parameters) {
     this.parameters = parameters;
   }
 
@@ -92,7 +86,6 @@
 
   @Test
   public void testJ$ExtensionNoDesugaring() throws Exception {
-    Assume.assumeFalse(shrinkDesugaredLibrary);
     String stderr;
     if (parameters.isCfRuntime()) {
       stderr =
@@ -110,24 +103,31 @@
               .assertFailure()
               .getStdErr();
     }
-    assertError(stderr);
+    assertError(stderr, false);
   }
 
-  private void assertError(String stderr) {
-    if (parameters.isCfRuntime() && parameters.getRuntime().asCf().getVm() == CfVm.JDK8) {
-      assertTrue(
-          stderr.contains("java.lang.SecurityException: Prohibited package name: java.time"));
-    } else if (parameters.isCfRuntime()) {
-      assertTrue(stderr.contains("java.lang.ClassNotFoundException: java.time.LocalTimeAccess"));
-    } else if (parameters
-        .getRuntime()
-        .asDex()
-        .getVm()
-        .getVersion()
-        .isOlderThanOrEqual(Version.V6_0_1)) {
-      assertTrue(stderr.contains("java.lang.NoClassDefFoundError"));
-    } else if (parameters.getRuntime().asDex().getVm().getVersion() == Version.V7_0_0) {
-      assertTrue(stderr.contains("java.lang.ClassNotFoundException"));
+  private void assertError(String stderr, boolean desugaring) {
+    if (parameters.isCfRuntime()) {
+      if (parameters.getRuntime().asCf().getVm() == CfVm.JDK8) {
+        assertTrue(
+            stderr.contains("java.lang.SecurityException: Prohibited package name: java.time"));
+      } else {
+        assertTrue(stderr.contains("java.lang.ClassNotFoundException: java.time.LocalTimeAccess"));
+      }
+      return;
+    }
+    assert !parameters.isCfRuntime();
+    if (!desugaring) {
+      if (parameters.getDexRuntimeVersion().isOlderThanOrEqual(Version.V6_0_1)) {
+        assertTrue(stderr.contains("java.lang.NoClassDefFoundError"));
+      } else if (parameters.getDexRuntimeVersion() == Version.V7_0_0) {
+        assertTrue(stderr.contains("java.lang.ClassNotFoundException"));
+      }
+      return;
+    }
+    if (parameters.getDexRuntimeVersion() == Version.V8_1_0) {
+      // On Android 8 the library package private method is accessible.
+      assertTrue(stderr.contains("java.lang.NullPointerException"));
     } else {
       assertTrue(stderr.contains("java.lang.IllegalAccessError"));
     }
@@ -140,19 +140,18 @@
     Assume.assumeTrue(requiresTimeDesugaring(parameters));
     KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
 
-    try {
-      testForD8()
-          .addLibraryFiles(getLibraryFile())
-          .addProgramFiles(compiledClasses)
-          .setMinApi(parameters.getApiLevel())
-          .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
-          .compile();
-      fail();
-    } catch (CompilationFailedException e) {
-      assertTrue(
-          e.getCause()
-              .getMessage()
-              .contains("Cannot compile program class java.time.LocalTimeAccess"));
-    }
+    String stdErr =
+        testForD8()
+            .addLibraryFiles(getLibraryFile())
+            .addProgramFiles(compiledClasses)
+            .setMinApi(parameters.getApiLevel())
+            .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
+            .compile()
+            .addDesugaredCoreLibraryRunClassPath(
+                this::buildDesugaredLibrary, parameters.getApiLevel())
+            .run(parameters.getRuntime(), MAIN_CLASS_NAME)
+            .assertFailure()
+            .getStdErr();
+    assertError(stdErr, true);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingJ$Test.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingJ$Test.java
index d5300ad..1208414 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingJ$Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingJ$Test.java
@@ -118,8 +118,8 @@
     L8.run(
         L8Command.builder()
             .addLibraryFiles(getLibraryFile())
+            .addLibraryFiles(ToolHelper.getDesugarJDKLibs())
             .addProgramFiles(JDK_11_JAVA_BASE_EXTENSION_COMPILED_FILES)
-            .addClasspathFiles(ToolHelper.getDesugarJDKLibs())
             .addDesugaredLibraryConfiguration(
                 StringResource.fromFile(ToolHelper.getDesugarLibJsonForTesting()))
             .setMinApiLevel(AndroidApiLevel.B.getLevel())
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 abdf5c5..f3caf57 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
@@ -99,13 +99,13 @@
   }
 
   private void configurationForProgramCompilation(InternalOptions options) {
-    options.desugaredLibrarySpecification =
-        desugaredLibrarySpecification(options, false, parameters);
+    setDesugaredLibrarySpecificationForTesting(
+        options, desugaredLibrarySpecification(options, false, parameters));
   }
 
   private void configurationForLibraryCompilation(InternalOptions options) {
-    options.desugaredLibrarySpecification =
-        desugaredLibrarySpecification(options, true, parameters);
+    setDesugaredLibrarySpecificationForTesting(
+        options, desugaredLibrarySpecification(options, true, parameters));
   }
 
   private Matcher<MethodSubject> invokesObjectsCompare(String holder) {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetAndBackportTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetAndBackportTest.java
index 359a18c..5367c8b 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetAndBackportTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetAndBackportTest.java
@@ -7,6 +7,7 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyRewritingFlags;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyTopLevelFlags;
@@ -14,6 +15,7 @@
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import java.io.IOException;
 import java.util.List;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -55,9 +57,15 @@
             .putBackportCoreLibraryMember("java.lang.DesugarMath", "java.lang.Math")
             .putRetargetCoreLibMember("java.util.Date#toInstant", "java.util.DesugarDate")
             .build();
-    options.desugaredLibrarySpecification =
-        new LegacyDesugaredLibrarySpecification(
-            LegacyTopLevelFlags.testing(), rewritingFlags, true, options.itemFactory);
+    try {
+      options.setDesugaredLibrarySpecificationForTesting(
+          new LegacyDesugaredLibrarySpecification(
+              LegacyTopLevelFlags.testing(), rewritingFlags, true, options.itemFactory),
+          ToolHelper.getDesugarJDKLibs(),
+          ToolHelper.getAndroidJar(AndroidApiLevel.R));
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java
index 6bf49a0..e629c47 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java
@@ -5,13 +5,7 @@
 package com.android.tools.r8.desugar.desugaredlibrary;
 
 import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecification;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion.HumanToMachineSpecificationConverter;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion.LegacyToHumanSpecificationConverter;
 import com.android.tools.r8.utils.BooleanUtils;
-import com.android.tools.r8.utils.InternalOptions;
-import java.io.IOException;
 import java.nio.file.Path;
 import java.time.Instant;
 import java.time.ZonedDateTime;
@@ -31,19 +25,15 @@
 
   private final TestParameters parameters;
   private final boolean shrinkDesugaredLibrary;
-  private final boolean machineSpec;
 
   @Parameters(name = "machine: {0}, {2}, shrink: {1}")
   public static List<Object[]> data() {
     return buildParameters(
         BooleanUtils.values(),
-        BooleanUtils.values(),
         getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build());
   }
 
-  public RetargetOverrideTest(
-      boolean machineSpec, boolean shrinkDesugaredLibrary, TestParameters parameters) {
-    this.machineSpec = machineSpec;
+  public RetargetOverrideTest(boolean shrinkDesugaredLibrary, TestParameters parameters) {
     this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
     this.parameters = parameters;
   }
@@ -54,7 +44,6 @@
     Path desugaredTwice =
         testForD8(Backend.CF)
             .addLibraryFiles(getLibraryFile())
-            .addOptionsModification(this::setMachineSpec)
             .addProgramFiles(
                 testForD8(Backend.CF)
                     .addLibraryFiles(getLibraryFile())
@@ -76,7 +65,6 @@
       stdout =
           testForD8(Backend.DEX)
               .addProgramFiles(desugaredTwice)
-              .addOptionsModification(this::setMachineSpec)
               .setMinApi(parameters.getApiLevel())
               .disableDesugaring()
               .compile()
@@ -107,22 +95,6 @@
     assertLines2By2Correct(stdout);
   }
 
-  private void setMachineSpec(InternalOptions opt) {
-    if (!machineSpec) {
-      return;
-    }
-    try {
-      HumanDesugaredLibrarySpecification human =
-          new LegacyToHumanSpecificationConverter()
-              .convert(opt.desugaredLibrarySpecification, getLibraryFile(), opt);
-      MachineDesugaredLibrarySpecification machine =
-          new HumanToMachineSpecificationConverter().convert(human, getLibraryFile(), opt);
-      opt.testing.machineDesugaredLibrarySpecification = machine;
-    } catch (IOException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
   @Test
   public void testRetargetOverrideD8() throws Exception {
     Assume.assumeTrue(parameters.getRuntime().isDex());
@@ -130,7 +102,6 @@
     String stdout =
         testForD8()
             .addLibraryFiles(getLibraryFile())
-            .addOptionsModification(this::setMachineSpec)
             .addInnerClasses(RetargetOverrideTest.class)
             .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
             .setMinApi(parameters.getApiLevel())
@@ -156,7 +127,6 @@
     String stdout =
         testForR8(Backend.DEX)
             .addLibraryFiles(getLibraryFile())
-            .addOptionsModification(this::setMachineSpec)
             .addKeepMainRule(Executor.class)
             .addInnerClasses(RetargetOverrideTest.class)
             .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/APIConversionFinalClassTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/APIConversionFinalClassTest.java
index f9d1828..7abed46 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/APIConversionFinalClassTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/APIConversionFinalClassTest.java
@@ -58,6 +58,7 @@
         .setMinApi(AndroidApiLevel.B)
         .addProgramClasses(Executor.class)
         .addLibraryClasses(CustomLibClass.class)
+        .addLibraryFiles(getLibraryFile())
         .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
         .compile()
         .addDesugaredCoreLibraryRunClassPath(
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/AccessModeConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/AccessModeConversionTest.java
index 6691cb1..21ad64e 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/AccessModeConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/AccessModeConversionTest.java
@@ -67,7 +67,7 @@
     LegacyDesugaredLibrarySpecification specification =
         new LegacyDesugaredLibrarySpecification(
             LegacyTopLevelFlags.testing(), rewritingFlags, l8Compilation, options.itemFactory);
-    options.desugaredLibrarySpecification = specification;
+    setDesugaredLibrarySpecificationForTesting(options, specification);
   }
 
   @Test
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 aa97e55..957515a 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
@@ -87,9 +87,10 @@
         .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
         .addOptionsModification(
             opt ->
-                opt.desugaredLibrarySpecification =
+                setDesugaredLibrarySpecificationForTesting(
+                    opt,
                     configurationWithSupportAllCallbacksFromLibrary(
-                        opt, false, parameters, supportAllCallbacksFromLibrary))
+                        opt, false, parameters, supportAllCallbacksFromLibrary)))
         .compile()
         .inspect(this::assertDoubleForEach)
         .inspect(this::assertWrapperMethodsPresent)
@@ -151,9 +152,10 @@
         .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
         .addOptionsModification(
             opt ->
-                opt.desugaredLibrarySpecification =
+                setDesugaredLibrarySpecificationForTesting(
+                    opt,
                     configurationWithSupportAllCallbacksFromLibrary(
-                        opt, false, parameters, supportAllCallbacksFromLibrary))
+                        opt, false, parameters, supportAllCallbacksFromLibrary)))
         .compile()
         .inspect(this::assertDoubleForEach)
         .inspect(this::assertWrapperMethodsPresent)
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 6b7d86e..b966b00 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
@@ -71,9 +71,10 @@
                         this.buildDesugaredLibrary(
                             api,
                             opt ->
-                                opt.desugaredLibrarySpecification =
+                                setDesugaredLibrarySpecificationForTesting(
+                                    opt,
                                     configurationWithSupportAllCallbacksFromLibrary(
-                                        opt, true, parameters, supportAllCallbacksFromLibrary)));
+                                        opt, true, parameters, supportAllCallbacksFromLibrary))));
                     return desugaredLibBox.get();
                   },
                   AndroidApiLevel.B)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/TryCatchTimeConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/TryCatchTimeConversionTest.java
index a669527..aaab5cb 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/TryCatchTimeConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/TryCatchTimeConversionTest.java
@@ -58,6 +58,7 @@
         .setMinApi(parameters.getApiLevel())
         .addProgramClasses(BaselineExecutor.class)
         .addLibraryClasses(CustomLibClass.class)
+        .addLibraryFiles(getLibraryFile())
         .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
         .compile()
         .addDesugaredCoreLibraryRunClassPath(
@@ -98,6 +99,7 @@
         .setMinApi(parameters.getApiLevel())
         .addProgramClasses(TryCatchExecutor.class)
         .addLibraryClasses(CustomLibClass.class)
+        .addLibraryFiles(getLibraryFile())
         .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
         .compile()
         .addDesugaredCoreLibraryRunClassPath(
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11StreamTests.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11StreamTests.java
index 2bd50b2..3b6ae0a 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11StreamTests.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11StreamTests.java
@@ -270,6 +270,7 @@
               .addProgramFiles(testNGSupportProgramFiles())
               .addOptionsModification(opt -> opt.testing.trackDesugaredAPIConversions = true)
               .addLibraryFiles(getLibraryFile())
+              .addLibraryFiles(JDK_11_JAVA_BASE_EXTENSION_CLASSES_DIR)
               .setMinApi(parameters.getApiLevel())
               .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
               .allowStdoutMessages()
@@ -303,6 +304,7 @@
           .addProgramFiles(testNGSupportProgramFiles())
           .addOptionsModification(opt -> opt.testing.trackDesugaredAPIConversions = true)
           .addLibraryFiles(getLibraryFile())
+          .addLibraryFiles(JDK_11_JAVA_BASE_EXTENSION_CLASSES_DIR)
           .setMinApi(parameters.getApiLevel())
           .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
           .compile()
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/b135627418/B135627418.java b/src/test/java/com/android/tools/r8/memberrebinding/b135627418/B135627418.java
index f3103f1..bf94752 100644
--- a/src/test/java/com/android/tools/r8/memberrebinding/b135627418/B135627418.java
+++ b/src/test/java/com/android/tools/r8/memberrebinding/b135627418/B135627418.java
@@ -12,10 +12,13 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
 import com.android.tools.r8.memberrebinding.b135627418.library.Drawable;
 import com.android.tools.r8.memberrebinding.b135627418.library.DrawableWrapper;
 import com.android.tools.r8.memberrebinding.b135627418.library.InsetDrawable;
+import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
@@ -75,11 +78,27 @@
                 com.android.tools.r8.memberrebinding.b135627418.runtime.InsetDrawable.class)
             .setMinApi(parameters.getRuntime())
             .addOptionsModification(
-                options ->
-                    options.desugaredLibrarySpecification =
-                        LegacyDesugaredLibrarySpecification.withOnlyRewritePrefixForTesting(
-                            ImmutableMap.of(packageName + ".runtime", packageName + ".library"),
-                            options))
+                options -> {
+                  options.desugaredLibrarySpecification =
+                      LegacyDesugaredLibrarySpecification.withOnlyRewritePrefixForTesting(
+                          ImmutableMap.of(packageName + ".runtime", packageName + ".library"),
+                          options);
+                  DexType type =
+                      options
+                          .dexItemFactory()
+                          .createType(
+                              DescriptorUtils.javaTypeToDescriptor(
+                                  packageName + ".runtime.InsetDrawable"));
+                  DexType rewrittenType =
+                      options
+                          .dexItemFactory()
+                          .createType(
+                              DescriptorUtils.javaTypeToDescriptor(
+                                  packageName + ".library.InsetDrawable"));
+                  options.machineDesugaredLibrarySpecification =
+                      MachineDesugaredLibrarySpecification.withOnlyRewriteTypeForTesting(
+                          ImmutableMap.of(type, rewrittenType));
+                })
             .compile();
 
     testForR8(parameters.getBackend())