Emulated interface desugaring above 24

Change-Id: Ia175c867262dde1ab5d4e51605ab8b4a2df684a1
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs.json b/src/library_desugar/jdk11/desugar_jdk_libs.json
index 8cb9509..97c9ae5 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs.json
@@ -1,5 +1,5 @@
 {
-  "identifier": "com.tools.android:desugar_jdk_libs_configuration:2.0.1",
+  "identifier": "com.tools.android:desugar_jdk_libs_configuration:2.0.2",
   "configuration_format_version": 100,
   "required_compilation_api_level": 30,
   "synthesized_library_classes_package_prefix": "j$.",
@@ -46,6 +46,20 @@
       ]
     },
     {
+      "api_level_below_or_equal": 33,
+      "api_level_greater_or_equal": 24,
+      "emulate_interface": {
+        "java.util.Collection": "j$.util.Collection"
+      },
+      "dont_rewrite": [
+        "boolean java.util.Collection#removeIf(java.util.function.Predicate)",
+        "java.util.Spliterator java.util.Collection#spliterator()",
+        "java.util.stream.Stream java.util.Collection#parallelStream()",
+        "java.util.stream.Stream java.util.Collection#stream()",
+        "void java.util.Collection#forEach(java.util.function.Consumer)"
+      ]
+    },
+    {
       "api_level_below_or_equal": 23,
       "rewrite_prefix": {
         "java.io.DesugarBufferedReader": "j$.io.DesugarBufferedReader",
@@ -147,6 +161,12 @@
   ],
   "program_flags": [
     {
+      "api_level_below_or_equal": 33,
+      "amend_library_method": [
+        "public java.lang.Object[] java.util.Collection#toArray(java.util.function.IntFunction)"
+      ]
+    },
+    {
       "api_level_below_or_equal": 32,
       "api_level_greater_or_equal": 26,
       "covariant_retarget_method": {
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_minimal.json b/src/library_desugar/jdk11/desugar_jdk_libs_minimal.json
index 119b674..15939bc 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_minimal.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_minimal.json
@@ -1,5 +1,5 @@
 {
-  "identifier": "com.tools.android:desugar_jdk_libs_configuration_minimal:2.0.1",
+  "identifier": "com.tools.android:desugar_jdk_libs_configuration_minimal:2.0.2",
   "configuration_format_version": 100,
   "required_compilation_api_level": 24,
   "synthesized_library_classes_package_prefix": "j$.",
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_nio.json b/src/library_desugar/jdk11/desugar_jdk_libs_nio.json
index 0b7d6cf..c308b06 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_nio.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_nio.json
@@ -1,5 +1,5 @@
 {
-  "identifier": "com.tools.android:desugar_jdk_libs_configuration_nio:2.0.1",
+  "identifier": "com.tools.android:desugar_jdk_libs_configuration_nio:2.0.2",
   "configuration_format_version": 100,
   "required_compilation_api_level": 30,
   "synthesized_library_classes_package_prefix": "j$.",
@@ -60,6 +60,20 @@
       ]
     },
     {
+      "api_level_below_or_equal": 33,
+      "api_level_greater_or_equal": 24,
+      "emulate_interface": {
+        "java.util.Collection": "j$.util.Collection"
+      },
+      "dont_rewrite": [
+        "boolean java.util.Collection#removeIf(java.util.function.Predicate)",
+        "java.util.Spliterator java.util.Collection#spliterator()",
+        "java.util.stream.Stream java.util.Collection#parallelStream()",
+        "java.util.stream.Stream java.util.Collection#stream()",
+        "void java.util.Collection#forEach(java.util.function.Consumer)"
+      ]
+    },
+    {
       "api_level_below_or_equal": 25,
       "rewrite_prefix": {
         "java.io.DesugarFile": "j$.io.DesugarFile",
@@ -306,6 +320,12 @@
   ],
   "program_flags": [
     {
+      "api_level_below_or_equal": 33,
+      "amend_library_method": [
+        "public java.lang.Object[] java.util.Collection#toArray(java.util.function.IntFunction)"
+      ]
+    },
+    {
       "api_level_below_or_equal": 32,
       "api_level_greater_or_equal": 26,
       "covariant_retarget_method": {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index ab044e3..751b635 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -359,10 +359,7 @@
     workaroundAbstractMethodOnNonAbstractClassVerificationBug(executor);
     DexApplication application = appView.appInfo().app();
     D8MethodProcessor methodProcessor = new D8MethodProcessor(this, executor);
-    InterfaceProcessor interfaceProcessor =
-        appView.options().isInterfaceMethodDesugaringEnabled()
-            ? new InterfaceProcessor(appView)
-            : null;
+    InterfaceProcessor interfaceProcessor = InterfaceProcessor.create(appView);
 
     timing.begin("IR conversion");
 
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 aa8ca78..7905c6c 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
@@ -93,17 +93,15 @@
     if (appView.options().enableTryWithResourcesDesugaring()) {
       desugarings.add(new TwrInstructionDesugaring(appView));
     }
-    if (appView.options().isInterfaceMethodDesugaringEnabled()) {
-      interfaceMethodRewriter =
-          new InterfaceMethodRewriter(
-              appView,
-              SetUtils.newImmutableSetExcludingNullItems(
-                  alwaysThrowingInstructionDesugaring,
-                  backportedMethodRewriter,
-                  desugaredLibraryRetargeter));
+    interfaceMethodRewriter =
+        InterfaceMethodRewriter.create(
+            appView,
+            SetUtils.newImmutableSetExcludingNullItems(
+                alwaysThrowingInstructionDesugaring,
+                backportedMethodRewriter,
+                desugaredLibraryRetargeter));
+    if (interfaceMethodRewriter != null) {
       desugarings.add(interfaceMethodRewriter);
-    } else {
-      interfaceMethodRewriter = null;
     }
     desugaredLibraryAPIConverter =
         appView.typeRewriter.isRewriting()
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/EmulatedInterfaceDescriptor.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/EmulatedInterfaceDescriptor.java
index fb96fe6..fee2962 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/EmulatedInterfaceDescriptor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/EmulatedInterfaceDescriptor.java
@@ -9,6 +9,13 @@
 import java.util.Map;
 import java.util.Objects;
 
+/**
+ * An EmulatedInterfaceDescriptor describes how emulated interfaces are desugared. The
+ * emulatedMethods encode the emulated dispatch logic for default methods. Note that there is an
+ * implicit decision here: If interface method desugaring is enabled (< 24), the static methods in
+ * the emulated interface are going to be desugared, else they are left in place. This means static
+ * methods need to be manually retargeted when interface method desugaring is not enabled.
+ */
 public class EmulatedInterfaceDescriptor implements SpecificationDescriptor {
   private final DexType rewrittenType;
   private final Map<DexMethod, EmulatedDispatchMethodDescriptor> emulatedMethods;
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
index 567cc79..c6ea5b0 100644
--- 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
@@ -28,6 +28,8 @@
       levelType = app.dexItemFactory.createType("Ljava/util/concurrent/Flow;");
     } else if (requiredCompilationAPILevel.isEqualTo(AndroidApiLevel.N)) {
       levelType = app.dexItemFactory.createType("Ljava/util/function/Supplier;");
+    } else if (requiredCompilationAPILevel.isEqualTo(AndroidApiLevel.T)) {
+      levelType = app.dexItemFactory.createType("Ljava/lang/invoke/VarHandle;");
     } else {
       app.options.reporter.warning(
           "Unsupported requiredCompilationAPILevel: " + requiredCompilationAPILevel);
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 1682151..eb710e9 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
@@ -4,6 +4,8 @@
 
 package com.android.tools.r8.ir.desugar.itf;
 
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode.EMULATED_INTERFACE_ONLY;
+
 import com.android.tools.r8.cf.code.CfInvoke;
 import com.android.tools.r8.cf.code.CfNew;
 import com.android.tools.r8.cf.code.CfStackInstruction;
@@ -29,6 +31,7 @@
 import com.android.tools.r8.graph.MethodResolutionResult;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.DerivedMethod;
+import com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode;
 import com.android.tools.r8.position.MethodPosition;
 import com.android.tools.r8.utils.BooleanBox;
 import com.android.tools.r8.utils.BooleanUtils;
@@ -374,7 +377,12 @@
   private final Map<DexProgramClass, List<ClassTypeSignature>> newExtraInterfaceSignatures =
       new ConcurrentHashMap<>();
 
-  ClassProcessor(AppView<?> appView, Predicate<ProgramMethod> isLiveMethod) {
+  private final InterfaceMethodDesugaringMode desugaringMode;
+
+  ClassProcessor(
+      AppView<?> appView,
+      Predicate<ProgramMethod> isLiveMethod,
+      InterfaceMethodDesugaringMode desugaringMode) {
     this.appView = appView;
     this.dexItemFactory = appView.dexItemFactory();
     this.helper = new InterfaceDesugaringSyntheticHelper(appView);
@@ -382,6 +390,7 @@
         !appView.options().canUseDefaultAndStaticInterfaceMethods()
             && !appView.options().machineDesugaredLibrarySpecification.isEmpty();
     this.isLiveMethod = isLiveMethod;
+    this.desugaringMode = desugaringMode;
   }
 
   private boolean isLiveMethod(DexClassAndMethod method) {
@@ -440,6 +449,9 @@
     assert iface.isInterface();
     assert iface.superType == dexItemFactory.objectType;
     assert !helper.isEmulatedInterface(iface.type);
+    if (desugaringMode == EMULATED_INTERFACE_ONLY) {
+      return SignaturesInfo.EMPTY;
+    }
     // Add non-library default methods as well as those for desugared library classes.
     if (!iface.isLibraryClass() || (needsLibraryInfo() && helper.isInDesugaredLibrary(iface))) {
       MethodSignatures signatures = getDefaultMethods(iface);
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 eda530c..4ac2b73 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
@@ -72,6 +72,23 @@
     this.shouldIgnoreFromReportsPredicate = getShouldIgnoreFromReportsPredicate(appView);
   }
 
+  public enum InterfaceMethodDesugaringMode {
+    ALL,
+    EMULATED_INTERFACE_ONLY,
+    NONE
+  }
+
+  public static InterfaceMethodDesugaringMode getInterfaceMethodDesugaringMode(
+      InternalOptions options) {
+    if (options.isInterfaceMethodDesugaringEnabled()) {
+      return InterfaceMethodDesugaringMode.ALL;
+    }
+    if (options.machineDesugaredLibrarySpecification.getEmulatedInterfaces().isEmpty()) {
+      return InterfaceMethodDesugaringMode.NONE;
+    }
+    return InterfaceMethodDesugaringMode.EMULATED_INTERFACE_ONLY;
+  }
+
   boolean isEmulatedInterface(DexType itf) {
     return appView
         .options()
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodProcessorFacade.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodProcessorFacade.java
index 434238a..a5ec16a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodProcessorFacade.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodProcessorFacade.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.desugar.CfPostProcessingDesugaring;
 import com.android.tools.r8.ir.desugar.CfPostProcessingDesugaringEventConsumer;
+import com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode;
 import com.android.tools.r8.ir.desugar.itf.InterfaceMethodRewriter.Flavor;
 import com.android.tools.r8.utils.ThreadUtils;
 import com.google.common.collect.Iterables;
@@ -28,11 +29,13 @@
       AppView<?> appView,
       Flavor flavour,
       Predicate<ProgramMethod> isLiveMethod,
-      InterfaceProcessor interfaceProcessor) {
+      InterfaceProcessor interfaceProcessor,
+      InterfaceMethodDesugaringMode desugaringMode) {
     this.appView = appView;
     this.flavour = flavour;
+    assert interfaceProcessor != null;
     this.interfaceProcessor = interfaceProcessor;
-    this.classProcessor = new ClassProcessor(appView, isLiveMethod);
+    this.classProcessor = new ClassProcessor(appView, isLiveMethod, desugaringMode);
   }
 
   private boolean shouldProcess(DexProgramClass clazz, Flavor flavour) {
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 955183a..e91925d 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
@@ -4,6 +4,11 @@
 
 package com.android.tools.r8.ir.desugar.itf;
 
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode.ALL;
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode.EMULATED_INTERFACE_ONLY;
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode.NONE;
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.getInterfaceMethodDesugaringMode;
+
 import com.android.tools.r8.DesugarGraphConsumer;
 import com.android.tools.r8.cf.CfVersion;
 import com.android.tools.r8.cf.code.CfInstruction;
@@ -38,6 +43,7 @@
 import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.DerivedMethod;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
 import com.android.tools.r8.ir.desugar.icce.AlwaysThrowingInstructionDesugaring;
+import com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode;
 import com.android.tools.r8.ir.desugar.lambda.LambdaInstructionDesugaring;
 import com.android.tools.r8.ir.desugar.stringconcat.StringConcatInstructionDesugaring;
 import com.android.tools.r8.ir.synthetic.ForwardMethodBuilder;
@@ -87,6 +93,9 @@
   private final AppView<?> appView;
   private final InternalOptions options;
   final DexItemFactory factory;
+  // If this is true, this will desugar only default methods from emulated interfaces present in
+  // the emulated interface descriptor.
+  private final InterfaceMethodDesugaringMode desugaringMode;
   private final InterfaceDesugaringSyntheticHelper helper;
   // The emulatedMethod set is there to avoid doing the emulated look-up too often.
   private final Set<DexString> emulatedMethods = Sets.newIdentityHashSet();
@@ -108,12 +117,28 @@
     ExcludeDexResources
   }
 
-  public InterfaceMethodRewriter(
+  public static InterfaceMethodRewriter create(
       AppView<?> appView, Set<CfInstructionDesugaring> precedingDesugarings) {
+    InterfaceMethodDesugaringMode desugaringMode =
+        getInterfaceMethodDesugaringMode(appView.options());
+    if (desugaringMode == NONE) {
+      return null;
+    }
+    return new InterfaceMethodRewriter(appView, precedingDesugarings, desugaringMode);
+  }
+
+  public InterfaceMethodRewriter(
+      AppView<?> appView,
+      Set<CfInstructionDesugaring> precedingDesugarings,
+      InterfaceMethodDesugaringMode desugaringMode) {
     this.appView = appView;
     this.precedingDesugarings = precedingDesugarings;
     this.options = appView.options();
     this.factory = appView.dexItemFactory();
+    assert desugaringMode == EMULATED_INTERFACE_ONLY || desugaringMode == ALL;
+    this.desugaringMode = desugaringMode;
+    assert desugaringMode == EMULATED_INTERFACE_ONLY
+        || appView.options().isInterfaceMethodDesugaringEnabled();
     this.helper = new InterfaceDesugaringSyntheticHelper(appView);
     initializeEmulatedInterfaceVariables();
   }
@@ -274,15 +299,18 @@
           .build();
     }
     // Continue with invoke type logic.
+    if (invoke.isInvokeVirtual() || invoke.isInvokeInterface()) {
+      return computeInvokeVirtualDispatch(holder, invoke, context);
+    }
+    if (desugaringMode == EMULATED_INTERFACE_ONLY) {
+      return DesugarDescription.nothing();
+    }
     if (invoke.isInvokeStatic()) {
       return computeInvokeStatic(holder, invoke, context);
     }
     if (invoke.isInvokeSpecial()) {
       return computeInvokeSpecial(holder, invoke, context);
     }
-    if (invoke.isInvokeVirtual() || invoke.isInvokeInterface()) {
-      return computeInvokeVirtualDispatch(holder, invoke, context);
-    }
     return DesugarDescription.nothing();
   }
 
@@ -839,14 +867,16 @@
 
   public InterfaceMethodProcessorFacade getPostProcessingDesugaringD8(
       Flavor flavour, InterfaceProcessor interfaceProcessor) {
-    return new InterfaceMethodProcessorFacade(appView, flavour, m -> true, interfaceProcessor);
+    return new InterfaceMethodProcessorFacade(
+        appView, flavour, m -> true, interfaceProcessor, desugaringMode);
   }
 
   public InterfaceMethodProcessorFacade getPostProcessingDesugaringR8(
       Flavor flavour,
       Predicate<ProgramMethod> isLiveMethod,
       InterfaceProcessor interfaceProcessor) {
-    return new InterfaceMethodProcessorFacade(appView, flavour, isLiveMethod, interfaceProcessor);
+    return new InterfaceMethodProcessorFacade(
+        appView, flavour, isLiveMethod, interfaceProcessor, desugaringMode);
   }
 
   private Origin getMethodOrigin(DexMethod method) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
index 59dcd83..8d2c8c6 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
@@ -4,6 +4,10 @@
 
 package com.android.tools.r8.ir.desugar.itf;
 
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode.EMULATED_INTERFACE_ONLY;
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode.NONE;
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.getInterfaceMethodDesugaringMode;
+
 import com.android.tools.r8.cf.code.CfInstruction;
 import com.android.tools.r8.cf.code.CfInvoke;
 import com.android.tools.r8.dex.code.DexInstruction;
@@ -25,6 +29,8 @@
 import com.android.tools.r8.graph.MethodCollection;
 import com.android.tools.r8.graph.NestedGraphLens;
 import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.EmulatedDispatchMethodDescriptor;
+import com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode;
 import com.android.tools.r8.synthesis.SyntheticMethodBuilder;
 import com.android.tools.r8.utils.Pair;
 import com.android.tools.r8.utils.collections.BidirectionalManyToManyRepresentativeMap;
@@ -56,10 +62,21 @@
   private final InterfaceDesugaringSyntheticHelper helper;
   private final Map<DexProgramClass, PostProcessingInterfaceInfo> postProcessingInterfaceInfos =
       new ConcurrentHashMap<>();
+  private final InterfaceMethodDesugaringMode desugaringMode;
 
-  public InterfaceProcessor(AppView<?> appView) {
+  public static InterfaceProcessor create(AppView<?> appView) {
+    InterfaceMethodDesugaringMode desugaringMode =
+        getInterfaceMethodDesugaringMode(appView.options());
+    if (desugaringMode == NONE) {
+      return null;
+    }
+    return new InterfaceProcessor(appView, desugaringMode);
+  }
+
+  public InterfaceProcessor(AppView<?> appView, InterfaceMethodDesugaringMode desugaringMode) {
     this.appView = appView;
     helper = new InterfaceDesugaringSyntheticHelper(appView);
+    this.desugaringMode = desugaringMode;
   }
 
   public InterfaceDesugaringSyntheticHelper getHelper() {
@@ -72,6 +89,10 @@
     if (!method.getHolder().isInterface()) {
       return;
     }
+    if (desugaringMode == EMULATED_INTERFACE_ONLY) {
+      processEmulatedInterfaceOnly(method);
+      return;
+    }
     if (method.getDefinition().belongsToDirectPool()) {
       processDirectInterfaceMethod(method, eventConsumer);
     } else {
@@ -83,6 +104,25 @@
     }
   }
 
+  private void processEmulatedInterfaceOnly(ProgramMethod method) {
+    if (!appView.options().isDesugaredLibraryCompilation()) {
+      return;
+    }
+    if (method.getDefinition().belongsToDirectPool()) {
+      return;
+    }
+    if (helper.isEmulatedInterface(method.getHolderType())) {
+      EmulatedDispatchMethodDescriptor emulatedDispatchDescriptor =
+          helper.getEmulatedDispatchDescriptor(method.getHolder(), method);
+      if (emulatedDispatchDescriptor != null) {
+        processVirtualInterfaceMethod(method);
+        if (!interfaceMethodRemovalChangesApi(method)) {
+          getPostProcessingInterfaceInfo(method.getHolder()).setHasBridgesToRemove();
+        }
+      }
+    }
+  }
+
   static ProgramMethod ensureCompanionMethod(
       DexProgramClass iface,
       DexString methodName,
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 74202d3..1b77e82 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -510,7 +510,7 @@
     liveFields = new LiveFieldsSet(graphReporter::registerField);
     if (mode.isInitialTreeShaking()) {
       desugaring = CfInstructionDesugaringCollection.create(appView, appView.apiLevelCompute());
-      interfaceProcessor = new InterfaceProcessor(appView);
+      interfaceProcessor = InterfaceProcessor.create(appView);
     } else {
       desugaring = CfInstructionDesugaringCollection.empty();
       interfaceProcessor = null;
@@ -4055,6 +4055,7 @@
 
     // Move the pending methods and mark them live and ready for tracing.
     for (ProgramMethod method : pendingMethodMove) {
+      assert interfaceProcessor != null;
       ProgramMethod companion =
           interfaceProcessor
               .getHelper()
diff --git a/src/test/examplesJava11/collectiontoarray/Main.java b/src/test/examplesJava11/collectiontoarray/Main.java
new file mode 100644
index 0000000..91bbd8b
--- /dev/null
+++ b/src/test/examplesJava11/collectiontoarray/Main.java
@@ -0,0 +1,20 @@
+// 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 collectiontoarray;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class Main {
+  public static void main(String[] args) {
+    List<String> list = new ArrayList<>();
+    list.add("one");
+    list.add("two");
+    // This default method was added in Android T.
+    String[] toArray = list.toArray(String[]::new);
+    System.out.println(Arrays.toString(toArray));
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/CollectionToArrayTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/CollectionToArrayTest.java
new file mode 100644
index 0000000..d3d901a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/CollectionToArrayTest.java
@@ -0,0 +1,63 @@
+// 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.desugar.desugaredlibrary.jdk11;
+
+import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.DEFAULT_SPECIFICATIONS;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11_PATH;
+
+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.desugar.desugaredlibrary.test.CompilationSpecification;
+import com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class CollectionToArrayTest extends DesugaredLibraryTestBase {
+
+  private final TestParameters parameters;
+  private final LibraryDesugaringSpecification libraryDesugaringSpecification;
+  private final CompilationSpecification compilationSpecification;
+
+  private static final Path INPUT_JAR =
+      Paths.get(ToolHelper.EXAMPLES_JAVA11_JAR_DIR + "collectiontoarray.jar");
+  private static final String EXPECTED_OUTPUT = StringUtils.lines("[one, two]");
+  private static final String MAIN_CLASS = "collectiontoarray.Main";
+
+  @Parameters(name = "{0}, spec: {1}, {2}")
+  public static List<Object[]> data() {
+    return buildParameters(
+        getTestParameters().withDexRuntimes().withAllApiLevels().build(),
+        ImmutableList.of(JDK11, JDK11_PATH),
+        DEFAULT_SPECIFICATIONS);
+  }
+
+  public CollectionToArrayTest(
+      TestParameters parameters,
+      LibraryDesugaringSpecification libraryDesugaringSpecification,
+      CompilationSpecification compilationSpecification) {
+    this.parameters = parameters;
+    this.libraryDesugaringSpecification = libraryDesugaringSpecification;
+    this.compilationSpecification = compilationSpecification;
+  }
+
+  @Test
+  public void test() throws Throwable {
+    testForDesugaredLibrary(parameters, libraryDesugaringSpecification, compilationSpecification)
+        .addProgramFiles(INPUT_JAR)
+        .addKeepMainRule(MAIN_CLASS)
+        .run(parameters.getRuntime(), MAIN_CLASS)
+        .assertSuccessWithOutput(EXPECTED_OUTPUT);
+  }
+}