Reland "Desugared library: Prefix all synthesized classes"

Reintroduces the 2 fixes in the CL.

Change-Id: I1086c807602879658894ed129e744deb44b10cfa
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index 92f194a..9673bc2 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -68,6 +68,7 @@
     private boolean intermediate = false;
     private DesugarGraphConsumer desugarGraphConsumer = null;
     private StringConsumer desugaredLibraryKeepRuleConsumer = null;
+    private String synthesizedClassPrefix = "";
 
     private Builder() {
       this(new DefaultD8DiagnosticsHandler());
@@ -168,6 +169,11 @@
       return CompilationMode.DEBUG;
     }
 
+    Builder setSynthesizedClassesPrefix(String prefix) {
+      synthesizedClassPrefix = prefix;
+      return self();
+    }
+
     @Override
     void validate() {
       Reporter reporter = getReporter();
@@ -227,6 +233,7 @@
           libraryConfiguration,
           getAssertionsConfiguration(),
           getOutputInspections(),
+          synthesizedClassPrefix,
           getThreadCount(),
           factory);
     }
@@ -238,6 +245,7 @@
   private final DesugarGraphConsumer desugarGraphConsumer;
   private final StringConsumer desugaredLibraryKeepRuleConsumer;
   private final DesugaredLibraryConfiguration libraryConfiguration;
+  private final String synthesizedClassPrefix;
   private final DexItemFactory factory;
 
   public static Builder builder() {
@@ -297,6 +305,7 @@
       DesugaredLibraryConfiguration libraryConfiguration,
       List<AssertionsConfiguration> assertionsConfiguration,
       List<Consumer<Inspector>> outputInspections,
+      String synthesizedClassPrefix,
       int threadCount,
       DexItemFactory factory) {
     super(
@@ -317,6 +326,7 @@
     this.desugarGraphConsumer = desugarGraphConsumer;
     this.desugaredLibraryKeepRuleConsumer = desugaredLibraryKeepRuleConsumer;
     this.libraryConfiguration = libraryConfiguration;
+    this.synthesizedClassPrefix = synthesizedClassPrefix;
     this.factory = factory;
   }
 
@@ -326,6 +336,7 @@
     desugarGraphConsumer = null;
     desugaredLibraryKeepRuleConsumer = null;
     libraryConfiguration = null;
+    synthesizedClassPrefix = null;
     factory = null;
   }
 
@@ -372,8 +383,8 @@
     internal.dexClassChecksumFilter = getDexClassChecksumFilter();
     internal.enableInheritanceClassInDexDistributor = isOptimizeMultidexForLinearAlloc();
 
-    // TODO(134732760): This is still work in progress.
     internal.desugaredLibraryConfiguration = libraryConfiguration;
+    internal.synthesizedClassPrefix = synthesizedClassPrefix;
     internal.desugaredLibraryKeepRuleConsumer = desugaredLibraryKeepRuleConsumer;
 
     // Default is to remove all javac generated assertion code when generating dex.
diff --git a/src/main/java/com/android/tools/r8/L8Command.java b/src/main/java/com/android/tools/r8/L8Command.java
index c32fbb7..7741651 100644
--- a/src/main/java/com/android/tools/r8/L8Command.java
+++ b/src/main/java/com/android/tools/r8/L8Command.java
@@ -178,8 +178,10 @@
     assert internal.enableInheritanceClassInDexDistributor;
     internal.enableInheritanceClassInDexDistributor = false;
 
-    // TODO(134732760): This is still work in progress.
+    assert libraryConfiguration != null;
     internal.desugaredLibraryConfiguration = libraryConfiguration;
+    internal.synthesizedClassPrefix =
+        libraryConfiguration.getSynthesizedLibraryClassesPackagePrefix();
 
     // Default is to remove all javac generated assertion code when generating dex.
     assert internal.assertionsConfiguration == null;
@@ -289,6 +291,8 @@
         R8Command.Builder r8Builder =
             R8Command.builder(getReporter())
                 .addProgramResourceProvider(desugaredLibrary)
+                .setSynthesizedClassesPrefix(
+                    libraryConfiguration.getSynthesizedLibraryClassesPackagePrefix())
                 .setMinApiLevel(getMinApiLevel())
                 .setMode(getMode())
                 .setProgramConsumer(getProgramConsumer());
@@ -307,6 +311,8 @@
         D8Command.Builder d8Builder =
             D8Command.builder(getReporter())
                 .addProgramResourceProvider(desugaredLibrary)
+                .setSynthesizedClassesPrefix(
+                    libraryConfiguration.getSynthesizedLibraryClassesPackagePrefix())
                 .setMinApiLevel(getMinApiLevel())
                 .setMode(getMode())
                 .setProgramConsumer(getProgramConsumer());
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 611bc7a..fea04c7 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -104,6 +104,7 @@
     private GraphConsumer mainDexKeptGraphConsumer = null;
     private BiFunction<String, Long, Boolean> dexClassChecksumFilter = (name, checksum) -> true;
     private final List<FeatureSplit> featureSplits = new ArrayList<>();
+    private String synthesizedClassPrefix = "";
 
     private boolean allowPartiallyImplementedProguardOptions = false;
     private boolean allowTestProguardOptions =
@@ -146,6 +147,11 @@
       return CompilationMode.RELEASE;
     }
 
+    Builder setSynthesizedClassesPrefix(String prefix) {
+      synthesizedClassPrefix = prefix;
+      return self();
+    }
+
     /**
      * Disable tree shaking.
      *
@@ -572,6 +578,7 @@
               featureSplitConfiguration,
               getAssertionsConfiguration(),
               getOutputInspections(),
+              synthesizedClassPrefix,
               getThreadCount());
 
       return command;
@@ -654,6 +661,7 @@
   private final StringConsumer desugaredLibraryKeepRuleConsumer;
   private final DesugaredLibraryConfiguration libraryConfiguration;
   private final FeatureSplitConfiguration featureSplitConfiguration;
+  private final String synthesizedClassPrefix;
 
   /** Get a new {@link R8Command.Builder}. */
   public static Builder builder() {
@@ -731,6 +739,7 @@
       FeatureSplitConfiguration featureSplitConfiguration,
       List<AssertionsConfiguration> assertionsConfiguration,
       List<Consumer<Inspector>> outputInspections,
+      String synthesizedClassPrefix,
       int threadCount) {
     super(
         inputApp,
@@ -764,6 +773,7 @@
     this.desugaredLibraryKeepRuleConsumer = desugaredLibraryKeepRuleConsumer;
     this.libraryConfiguration = libraryConfiguration;
     this.featureSplitConfiguration = featureSplitConfiguration;
+    this.synthesizedClassPrefix = synthesizedClassPrefix;
   }
 
   private R8Command(boolean printHelp, boolean printVersion) {
@@ -784,6 +794,7 @@
     desugaredLibraryKeepRuleConsumer = null;
     libraryConfiguration = null;
     featureSplitConfiguration = null;
+    synthesizedClassPrefix = null;
   }
 
   /** Get the enable-tree-shaking state. */
@@ -910,8 +921,8 @@
 
     internal.enableInheritanceClassInDexDistributor = isOptimizeMultidexForLinearAlloc();
 
-    // TODO(134732760): This is still work in progress.
     internal.desugaredLibraryConfiguration = libraryConfiguration;
+    internal.synthesizedClassPrefix = synthesizedClassPrefix;
     internal.desugaredLibraryKeepRuleConsumer = desugaredLibraryKeepRuleConsumer;
 
     assert internal.threadCount == ThreadUtils.NOT_SPECIFIED;
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 a0934cd..4ac8995 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
@@ -974,12 +974,7 @@
   private DexType computeOutlineClassType() {
     DexType result;
     int count = 0;
-    String tempPrefix =
-        appView
-            .options()
-            .desugaredLibraryConfiguration
-            .getSynthesizedLibraryClassesPackagePrefix(appView);
-    String prefix = tempPrefix.replace('/', '.');
+    String prefix = appView.options().synthesizedClassPrefix.replace('/', '.');
     do {
       String name =
           prefix + OutlineOptions.CLASS_NAME + (count == 0 ? "" : Integer.toString(count));
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index fd0e452..962170d 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
@@ -489,11 +489,11 @@
   }
 
   private static DexType dispatchTypeFor(AppView<?> appView, DexMethod method, String suffix) {
-    String desugaredLibPrefix =
+    String prefix =
         appView.options().desugaredLibraryConfiguration.getSynthesizedLibraryClassesPackagePrefix();
     String descriptor =
         "L"
-            + desugaredLibPrefix
+            + prefix
             + UTILITY_CLASS_NAME_PREFIX
             + '$'
             + method.holder.getName()
@@ -552,38 +552,47 @@
     private final Set<DexMethod> emulatedDispatchMethods = Sets.newHashSet();
 
     RewritableMethods(InternalOptions options, AppView<?> appView) {
-      DexItemFactory factory = options.itemFactory;
+      if (options.shouldBackportMethods()) {
+        DexItemFactory factory = options.itemFactory;
+        if (options.minApiLevel < AndroidApiLevel.K.getLevel()) {
+          initializeAndroidKMethodProviders(factory);
+        }
+        if (options.minApiLevel < AndroidApiLevel.N.getLevel()) {
+          initializeAndroidNMethodProviders(factory);
+        }
+        if (options.minApiLevel < AndroidApiLevel.O.getLevel()) {
+          initializeAndroidOMethodProviders(factory);
+        }
 
-      if (options.minApiLevel < AndroidApiLevel.K.getLevel()) {
-        initializeAndroidKMethodProviders(factory);
-      }
-      if (options.minApiLevel < AndroidApiLevel.N.getLevel()) {
-        initializeAndroidNMethodProviders(factory);
-      }
-      if (options.minApiLevel < AndroidApiLevel.O.getLevel()) {
-        initializeAndroidOMethodProviders(factory);
+        // The following providers are currently not implemented at any API level in Android.
+        // They however require the Optional/Stream class to be present, either through desugared
+        // libraries or natively. If Optional/Stream class is not present, we do not desugar to
+        // avoid confusion in error messages.
+        if (appView.rewritePrefix.hasRewrittenType(factory.optionalType, appView)
+            || options.minApiLevel >= AndroidApiLevel.N.getLevel()) {
+          initializeJava9OptionalMethodProviders(factory);
+          initializeJava10OptionalMethodProviders(factory);
+          initializeJava11OptionalMethodProviders(factory);
+        }
+        if (appView.rewritePrefix.hasRewrittenType(factory.streamType, appView)
+            || options.minApiLevel >= AndroidApiLevel.N.getLevel()) {
+          initializeStreamMethodProviders(factory);
+        }
+
+        // These are currently not implemented at any API level in Android.
+        initializeJava9MethodProviders(factory);
+        initializeJava10MethodProviders(factory);
+        initializeJava11MethodProviders(factory);
       }
 
-      // The following providers are currently not implemented at any API level in Android.
-      // They however require the Optional/Stream class to be present, either through
-      // desugared libraries or natively. If Optional/Stream class is not present,
-      // we do not desugar to avoid confusion in error messages.
-      if (appView.rewritePrefix.hasRewrittenType(factory.optionalType, appView)
-          || options.minApiLevel >= AndroidApiLevel.N.getLevel()) {
+      if (options.testing.forceLibBackportsInL8CfToCf) {
+        DexItemFactory factory = options.itemFactory;
         initializeJava9OptionalMethodProviders(factory);
         initializeJava10OptionalMethodProviders(factory);
         initializeJava11OptionalMethodProviders(factory);
-      }
-      if (appView.rewritePrefix.hasRewrittenType(factory.streamType, appView)
-          || options.minApiLevel >= AndroidApiLevel.N.getLevel()) {
         initializeStreamMethodProviders(factory);
       }
 
-      // These are currently not implemented at any API level in Android.
-      initializeJava9MethodProviders(factory);
-      initializeJava10MethodProviders(factory);
-      initializeJava11MethodProviders(factory);
-
       if (!options.desugaredLibraryConfiguration.getRetargetCoreLibMember().isEmpty()) {
         initializeRetargetCoreLibraryMembers(appView);
       }
@@ -1896,14 +1905,9 @@
       DexItemFactory factory = appView.dexItemFactory();
       String unqualifiedName = method.holder.getName();
       // Avoid duplicate class names between core lib dex file and program dex files.
-      String desugaredLibPrefix =
-          appView
-              .options()
-              .desugaredLibraryConfiguration
-              .getSynthesizedLibraryClassesPackagePrefix(appView);
       String descriptor =
           "L"
-              + desugaredLibPrefix
+              + appView.options().synthesizedClassPrefix
               + UTILITY_CLASS_NAME_PREFIX
               + '$'
               + unqualifiedName
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
index 3527f62..946077d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
@@ -144,14 +144,9 @@
   }
 
   private DexType createWrapperType(DexType type, String suffix) {
-    String desugaredLibPrefix =
-        appView
-            .options()
-            .desugaredLibraryConfiguration
-            .getSynthesizedLibraryClassesPackagePrefix(appView);
     return factory.createType(
         "L"
-            + desugaredLibPrefix
+            + appView.options().synthesizedClassPrefix
             + WRAPPER_PREFIX
             + type.toString().replace('.', '$')
             + suffix
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 37b38e9..b8f02fe 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -287,6 +287,8 @@
 
   public boolean enablePcDebugInfoOutput = false;
 
+  public String synthesizedClassPrefix = "";
+
   // Number of threads to use while processing the dex files.
   public int threadCount = DETERMINISTIC_DEBUGGING ? 1 : ThreadUtils.NOT_SPECIFIED;
   // Print smali disassembly.
@@ -360,6 +362,10 @@
     return desugaredLibraryConfiguration.isLibraryCompilation();
   }
 
+  public boolean shouldBackportMethods() {
+    return !hasConsumer() || isGeneratingDex();
+  }
+
   public boolean shouldKeepStackMapTable() {
     return isDesugaredLibraryCompilation()
         || getProguardConfiguration().getKeepAttributes().stackMapTable;
@@ -1091,6 +1097,7 @@
     public PrintStream whyAreYouNotInliningConsumer = System.out;
     public boolean trackDesugaredAPIConversions =
         System.getProperty("com.android.tools.r8.trackDesugaredAPIConversions") != null;
+    public boolean forceLibBackportsInL8CfToCf = false;
 
     // TODO(b/144781417): This is disabled by default as some test apps appear to have such classes.
     public boolean allowNonAbstractClassesWithAbstractMethods = true;
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 628fbfe..b68997a 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
@@ -82,7 +82,7 @@
       // If we compile extended library here, it means we use TestNG.
       // TestNG requires annotations, hence we disable AnnotationRemoval.
       // This implies that extra warning are generated if this is set.
-      boolean disableL8AnnotationRemovalForTesting = !additionalProgramFiles.isEmpty();
+      boolean extraFiles = !additionalProgramFiles.isEmpty();
       ArrayList<Path> extraPaths = new ArrayList<>(additionalProgramFiles);
       TestDiagnosticMessagesImpl diagnosticsHandler = new TestDiagnosticMessagesImpl();
       Path desugaredLib = temp.newFolder().toPath().resolve("desugar_jdk_libs_dex.zip");
@@ -104,11 +104,12 @@
       ToolHelper.runL8(
           l8Builder.build(),
           options -> {
-            if (disableL8AnnotationRemovalForTesting) {
+            if (extraFiles) {
               options.testing.disableL8AnnotationRemoval = true;
+              options.testing.forceLibBackportsInL8CfToCf = true;
             }
           });
-      if (!disableL8AnnotationRemovalForTesting) {
+      if (!extraFiles) {
         assertTrue(
             diagnosticsHandler.getInfos().stream()
                 .noneMatch(