Don't duplicate emulated interface

When input has already been library desugared the emulated interface is
already implemented.

Bug: 171867367
Bug: 172433489
Change-Id: I9bdde7ccd430b9a24ab680b84a1eabd8ecb65208
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
index 758830d..2a4225f 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
@@ -429,6 +429,26 @@
       extraInterfaceSignatures.add(
           new GenericSignature.ClassTypeSignature(rewriter.getEmulatedInterface(extraInterface)));
     }
+    // The emulated interface might already be implemented if the input class has gone through
+    // library desugaring already.
+    clazz
+        .getInterfaces()
+        .forEach(
+            iface -> {
+              for (int i = 0; i < extraInterfaceSignatures.size(); i++) {
+                if (extraInterfaceSignatures.get(i).type() == iface) {
+                  if (!appView.options().desugarSpecificOptions().allowDesugaredInput) {
+                    throw new CompilationError(
+                        "Code has already been library desugared. Interface "
+                            + iface.getDescriptor()
+                            + " is already implemented by "
+                            + clazz.getType().getDescriptor());
+                  }
+                  extraInterfaceSignatures.remove(i);
+                  break;
+                }
+              }
+            });
     clazz.asProgramClass().addExtraInterfaces(extraInterfaceSignatures);
   }
 
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 c74ed38..bb54770 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -1176,6 +1176,8 @@
     // b/172508621
     public boolean sortMethodsOnCfOutput =
         System.getProperty("com.android.tools.r8.sortMethodsOnCfWriting") != null;
+    public boolean allowDesugaredInput =
+        System.getProperty("com.android.tools.r8.allowDesugaredInput") != null;
   }
 
   public static class CallSiteOptimizationOptions {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IteratorTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IteratorTest.java
index 1146f66..70da258 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IteratorTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IteratorTest.java
@@ -4,9 +4,14 @@
 
 package com.android.tools.r8.desugar.desugaredlibrary;
 
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
 import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
+import static org.hamcrest.CoreMatchers.containsString;
 
+import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.StringUtils;
@@ -93,9 +98,34 @@
         canUseDefaultAndStaticInterfaceMethods ? 1 : 2,
         info.getMethodNames().stream().filter(name -> name.equals("forEachRemaining")).count());
 
+    AndroidApiLevel apiLevelNotRequiringDesugaring = AndroidApiLevel.N;
+    if (parameters.getApiLevel().isLessThan(apiLevelNotRequiringDesugaring)) {
+      try {
+        // Use D8 to desugar with Java classfile output.
+        testForD8(Backend.CF)
+            .setMinApi(parameters.getApiLevel())
+            .addProgramFiles(firstJar)
+            .enableCoreLibraryDesugaring(parameters.getApiLevel(), new AbsentKeepRuleConsumer())
+            .compileWithExpectedDiagnostics(
+                diagnostics ->
+                    diagnostics.assertErrorsMatch(
+                        diagnosticMessage(
+                            containsString(
+                                "Code has already been library desugared. "
+                                    + "Interface Lj$/util/Iterator; is already implemented"))));
+        fail("Expected failure");
+      } catch (CompilationFailedException e) {
+        // Expected.
+      }
+    }
+
     // Use D8 to desugar with Java classfile output.
     Path secondJar =
         testForD8(Backend.CF)
+            .addOptionsModification(
+                options ->
+                    options.desugarSpecificOptions().allowDesugaredInput =
+                        parameters.getApiLevel().isLessThan(apiLevelNotRequiringDesugaring))
             .setMinApi(parameters.getApiLevel())
             .addProgramFiles(firstJar)
             .enableCoreLibraryDesugaring(parameters.getApiLevel(), new AbsentKeepRuleConsumer())
@@ -108,9 +138,8 @@
     assertEquals(
         MyIterator.class.getTypeName(),
         DescriptorUtils.getJavaTypeFromBinaryName(info.getClassBinaryName()));
-    // TODO(b/171867367): This should only be 1.
     assertEquals(
-        canUseDefaultAndStaticInterfaceMethods ? 0 : 2,
+        canUseDefaultAndStaticInterfaceMethods ? 0 : 1,
         info.getInterfaces().stream().filter(name -> name.equals("j$/util/Iterator")).count());
     // TODO(b/171867367): This should only be 2.
     assertEquals(