Fix Wrappers for Flow classes

Bug: b/247232304
Change-Id: Ia54ca812559908fb437c9c0ee6c92d043b70a450
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs.json b/src/library_desugar/jdk11/desugar_jdk_libs.json
index 609f920..8cb9509 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.0",
+  "identifier": "com.tools.android:desugar_jdk_libs_configuration:2.0.1",
   "configuration_format_version": 100,
   "required_compilation_api_level": 30,
   "synthesized_library_classes_package_prefix": "j$.",
@@ -38,7 +38,12 @@
       "api_level_below_or_equal": 29,
       "rewrite_prefix": {
         "java.util.concurrent.Flow": "j$.util.concurrent.Flow"
-      }
+      },
+      "wrapper_conversion": [
+        "java.util.concurrent.Flow$Publisher",
+        "java.util.concurrent.Flow$Subscriber",
+        "java.util.concurrent.Flow$Subscription"
+      ]
     },
     {
       "api_level_below_or_equal": 23,
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_legacy.json b/src/library_desugar/jdk11/desugar_jdk_libs_legacy.json
index 7d17a1d..c29c213 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_legacy.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_legacy.json
@@ -2,7 +2,7 @@
   "configuration_format_version": 5,
   "group_id" : "com.tools.android",
   "artifact_id" : "desugar_jdk_libs",
-  "version": "1.2.2",
+  "version": "1.2.3",
   "required_compilation_api_level": 30,
   "synthesized_library_classes_package_prefix": "j$.",
   "support_all_callbacks_from_library": true,
@@ -37,7 +37,12 @@
       "api_level_below_or_equal": 29,
       "rewrite_prefix": {
         "java.util.concurrent.Flow": "j$.util.concurrent.Flow"
-      }
+      },
+      "wrapper_conversion": [
+        "java.util.concurrent.Flow$Publisher",
+        "java.util.concurrent.Flow$Subscriber",
+        "java.util.concurrent.Flow$Subscription"
+      ]
     },
     {
       "api_level_below_or_equal": 23,
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_minimal.json b/src/library_desugar/jdk11/desugar_jdk_libs_minimal.json
index d13b947..119b674 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.0",
+  "identifier": "com.tools.android:desugar_jdk_libs_configuration_minimal:2.0.1",
   "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 e2f74e8..0b7d6cf 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.0",
+  "identifier": "com.tools.android:desugar_jdk_libs_configuration_nio:2.0.1",
   "configuration_format_version": 100,
   "required_compilation_api_level": 30,
   "synthesized_library_classes_package_prefix": "j$.",
@@ -52,7 +52,12 @@
       "api_level_below_or_equal": 29,
       "rewrite_prefix": {
         "java.util.concurrent.Flow": "j$.util.concurrent.Flow"
-      }
+      },
+      "wrapper_conversion": [
+        "java.util.concurrent.Flow$Publisher",
+        "java.util.concurrent.Flow$Subscriber",
+        "java.util.concurrent.Flow$Subscription"
+      ]
     },
     {
       "api_level_below_or_equal": 25,
diff --git a/src/test/examplesJava9/flow/FlowExample.java b/src/test/examplesJava9/flow/FlowExample.java
index 4b02fca..caa0c24 100644
--- a/src/test/examplesJava9/flow/FlowExample.java
+++ b/src/test/examplesJava9/flow/FlowExample.java
@@ -21,7 +21,7 @@
     oneShotPublisher.awaitPublishing();
   }
 
-  static class OneShotPublisher implements Publisher<Boolean> {
+  public static class OneShotPublisher implements Publisher<Boolean> {
 
     private final ForkJoinPool executor = new ForkJoinPool(); // daemon-based
 
diff --git a/src/test/examplesJava9/flow/FlowExample2.java b/src/test/examplesJava9/flow/FlowExample2.java
new file mode 100644
index 0000000..5a69730
--- /dev/null
+++ b/src/test/examplesJava9/flow/FlowExample2.java
@@ -0,0 +1,18 @@
+// 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 flow;
+
+import java.util.concurrent.Flow.Publisher;
+
+public class FlowExample2 extends flowlib.FlowLib {
+
+  public static void main(String[] args) {
+    System.out.println(new FlowExample2().getPublisher().getClass().getSimpleName());
+  }
+
+  public Publisher<?> getPublisher() {
+    return new FlowExample.OneShotPublisher();
+  }
+}
diff --git a/src/test/examplesJava9/flowlib/FlowLib.java b/src/test/examplesJava9/flowlib/FlowLib.java
new file mode 100644
index 0000000..f9fa74c
--- /dev/null
+++ b/src/test/examplesJava9/flowlib/FlowLib.java
@@ -0,0 +1,11 @@
+// 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 flowlib;
+
+import java.util.concurrent.Flow.Publisher;
+
+public abstract class FlowLib {
+  public abstract Publisher<?> getPublisher();
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ExtractWrapperTypesTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ExtractWrapperTypesTest.java
index bb51f2f..b5ca98b 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ExtractWrapperTypesTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ExtractWrapperTypesTest.java
@@ -131,6 +131,17 @@
               + " java.nio.file.spi.FileSystemProvider.newDirectoryStream(java.nio.file.Path,"
               + " java.nio.file.DirectoryStream$Filter)");
 
+  // TODO(b/238179854): Investigate how to fix these.
+  private static final Set<String> MISSING_GENERIC_TYPE_CONVERSION_FLOW =
+      ImmutableSet.of(
+          "int java.util.concurrent.SubmissionPublisher.offer(java.lang.Object,"
+              + " java.util.function.BiPredicate)",
+          "java.util.List java.util.concurrent.SubmissionPublisher.getSubscribers()",
+          "void java.util.concurrent.SubmissionPublisher.<init>(java.util.concurrent.Executor, int,"
+              + " java.util.function.BiConsumer)",
+          "int java.util.concurrent.SubmissionPublisher.offer(java.lang.Object, long,"
+              + " java.util.concurrent.TimeUnit, java.util.function.BiPredicate)");
+
   private final LibraryDesugaringSpecification libraryDesugaringSpecification;
 
   @Parameters(name = "{0}, spec: {1}")
@@ -158,6 +169,9 @@
     if (libraryDesugaringSpecification == JDK11_PATH) {
       missing.addAll(MISSING_GENERIC_TYPE_CONVERSION_PATH);
     }
+    if (libraryDesugaringSpecification != JDK8) {
+      missing.addAll(MISSING_GENERIC_TYPE_CONVERSION_FLOW);
+    }
     return missing;
   }
 
@@ -194,7 +208,9 @@
         || type.startsWith("java.security.")
         || type.startsWith("java.net.")
         || type.startsWith("java.awt.")
-        || type.startsWith("java.util.concurrent.")
+        || (type.startsWith("java.util.concurrent.")
+            && (!type.startsWith("java.util.concurrent.Flow")
+                || libraryDesugaringSpecification == JDK8))
         || (!libraryDesugaringSpecification.hasNioFileDesugaring(AndroidApiLevel.B)
             && type.startsWith("java.nio."));
   }
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/Flow2Test.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/Flow2Test.java
new file mode 100644
index 0000000..b0b4116
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/Flow2Test.java
@@ -0,0 +1,89 @@
+// 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.D8_L8DEBUG;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11_LEGACY;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11_PATH;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
+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.CustomLibrarySpecification;
+import com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
+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 Flow2Test extends DesugaredLibraryTestBase {
+
+  private final TestParameters parameters;
+  private final LibraryDesugaringSpecification libraryDesugaringSpecification;
+  private final CompilationSpecification compilationSpecification;
+
+  private static final AndroidApiLevel MIN_SUPPORTED = AndroidApiLevel.R;
+  private static final Path INPUT_JAR = Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR + "flow.jar");
+  private static final Path INPUT_LIB_JAR =
+      Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR + "flowlib.jar");
+  private static final String EXPECTED_OUTPUT = StringUtils.lines("OneShotPublisher");
+  private static final String MAIN_CLASS = "flow.FlowExample2";
+
+  @Parameters(name = "{0}, spec: {1}, {2}")
+  public static List<Object[]> data() {
+    return buildParameters(
+        getTestParameters()
+            // The actual min version is V11 but we don't have it.
+            .withDexRuntimesStartingFromIncluding(Version.V12_0_0)
+            .withApiLevelsEndingAtExcluding(MIN_SUPPORTED)
+            .build(),
+        ImmutableList.of(JDK11, JDK11_LEGACY, JDK11_PATH),
+        ImmutableList.of(D8_L8DEBUG));
+  }
+
+  public Flow2Test(
+      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)
+        .setCustomLibrarySpecification(
+            new CustomLibrarySpecification(INPUT_LIB_JAR, AndroidApiLevel.S))
+        .compile()
+        .inspect(this::assertWrapping)
+        .run(parameters.getRuntime(), MAIN_CLASS)
+        .assertSuccessWithOutput(EXPECTED_OUTPUT);
+  }
+
+  private void assertWrapping(CodeInspector inspector) {
+    List<FoundMethodSubject> getPublisherMethods =
+        inspector
+            .clazz("flow.FlowExample2")
+            .allMethods(m -> m.getMethod().getName().toString().equals("getPublisher"));
+    int numMethods = parameters.getApiLevel().isLessThanOrEqualTo(AndroidApiLevel.Q) ? 2 : 1;
+    assertEquals(numMethods, getPublisherMethods.size());
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/CustomLibrarySpecification.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/CustomLibrarySpecification.java
index cd4de6e..1c38f5a 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/CustomLibrarySpecification.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/CustomLibrarySpecification.java
@@ -4,29 +4,44 @@
 
 package com.android.tools.r8.desugar.desugaredlibrary.test;
 
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.D8TestBuilder;
+import com.android.tools.r8.D8TestCompileResult;
+import com.android.tools.r8.SingleTestRunResult;
+import com.android.tools.r8.TestCompilerBuilder;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.google.common.collect.ImmutableList;
+import java.nio.file.Path;
 import java.util.Collection;
 
 public class CustomLibrarySpecification {
 
+  private final Collection<Path> jars;
   private final Collection<Class<?>> classes;
   private final AndroidApiLevel minApi;
 
-  public CustomLibrarySpecification(Class<?> clazz, AndroidApiLevel minApi) {
-    this(ImmutableList.of(clazz), minApi);
+  public CustomLibrarySpecification(Path jar, AndroidApiLevel minApi) {
+    this(ImmutableList.of(jar), ImmutableList.of(), minApi);
   }
 
-  public CustomLibrarySpecification(Collection<Class<?>> classes, AndroidApiLevel minApi) {
+  public CustomLibrarySpecification(Class<?> clazz, AndroidApiLevel minApi) {
+    this(ImmutableList.of(), ImmutableList.of(clazz), minApi);
+  }
+
+  public CustomLibrarySpecification(
+      Collection<Path> jars, Collection<Class<?>> classes, AndroidApiLevel minApi) {
+    this.jars = jars;
     this.classes = classes;
     this.minApi = minApi;
   }
 
-  public Collection<Class<?>> getClasses() {
-    return classes;
+  public D8TestCompileResult compileCustomLibrary(D8TestBuilder builder)
+      throws CompilationFailedException {
+    return builder.addProgramClasses(classes).addProgramFiles(jars).setMinApi(minApi).compile();
   }
 
-  public AndroidApiLevel getMinApi() {
-    return minApi;
+  public void addLibraryClasses(
+      TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> builder) {
+    builder.addLibraryClasses(classes).addLibraryFiles(jars);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/DesugaredLibraryTestBuilder.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/DesugaredLibraryTestBuilder.java
index e68c8bc..b67d511 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/DesugaredLibraryTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/DesugaredLibraryTestBuilder.java
@@ -106,7 +106,7 @@
   public DesugaredLibraryTestBuilder<T> setCustomLibrarySpecification(
       CustomLibrarySpecification customLibrarySpecification) {
     this.customLibrarySpecification = customLibrarySpecification;
-    builder.addLibraryClasses(customLibrarySpecification.getClasses());
+    customLibrarySpecification.addLibraryClasses(builder);
     return this;
   }
 
@@ -376,10 +376,7 @@
     if (customLibrarySpecification == null) {
       return null;
     }
-    return test.testForD8(parameters.getBackend())
-        .addProgramClasses(customLibrarySpecification.getClasses())
-        .setMinApi(customLibrarySpecification.getMinApi())
-        .compile();
+    return customLibrarySpecification.compileCustomLibrary(test.testForD8(parameters.getBackend()));
   }
 
   private L8TestCompileResult compileDesugaredLibrary(