Custom conversion rewrites as gradle tasks

Bug: 222647019
Change-Id: Ifdddc41a608ec11044c50923843b126672925372
diff --git a/build.gradle b/build.gradle
index b2e669c..50fda5f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,6 +4,7 @@
 
 import dx.DexMergerTask
 import dx.DxTask
+import desugaredlibrary.CustomConversionAsmRewriterTask
 import net.ltgt.gradle.errorprone.CheckSeverity
 import org.gradle.internal.os.OperatingSystem
 import smali.SmaliTask
@@ -31,7 +32,7 @@
 
 ext {
     androidSupportVersion = '25.4.0'
-    asmVersion = '9.3'  // When updating update tools/asmifier.py and Toolhelper as well.
+    asmVersion = '9.3'  // When updating update tools/asmifier.py, build.src and Toolhelper as well.
     espressoVersion = '3.0.0'
     fastutilVersion = '7.2.0'
     guavaVersion = '30.1.1-jre'
@@ -1007,11 +1008,16 @@
     }
 }
 
-task buildLibraryDesugarConversions(type: Zip, dependsOn: downloadDeps) {
+task rawBuildLibraryDesugarConversions(type: Zip, dependsOn: downloadDeps) {
     from sourceSets.libraryDesugarConversions.output
     include "java/**/*.class"
-    baseName 'library_desugar_conversions'
-    destinationDir file('build/libs')
+    baseName 'library_desugar_conversions_raw'
+    destinationDir file('build/tmp/desugaredlibrary')
+}
+
+task buildLibraryDesugarConversions(type: CustomConversionAsmRewriterTask, dependsOn: rawBuildLibraryDesugarConversions) {
+    rawJar = file("tmp/library_desugar_conversions_raw.zip")
+    outputDirectory = file("build/libs")
 }
 
 task testJarSources(type: Jar, dependsOn: [testClasses, buildLibraryDesugarConversions]) {
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
index 74c5cfd..81527b4 100644
--- a/buildSrc/build.gradle
+++ b/buildSrc/build.gradle
@@ -7,10 +7,18 @@
 repositories {
     mavenCentral()
 }
+ext {
+    asmVersion = '9.3'
+}
 
 dependencies {
     compile group: 'com.google.guava', name: 'guava', version: '19.0'
     compile group: 'org.smali', name: 'smali', version: '2.2b4'
+    compile group: 'org.ow2.asm', name: 'asm', version: asmVersion
+    compile group: 'org.ow2.asm', name: 'asm-commons', version: asmVersion
+    compile group: 'org.ow2.asm', name: 'asm-tree', version: asmVersion
+    compile group: 'org.ow2.asm', name: 'asm-analysis', version: asmVersion
+    compile group: 'org.ow2.asm', name: 'asm-util', version: asmVersion
 }
 
 sourceCompatibility = JavaVersion.VERSION_1_8
diff --git a/buildSrc/src/main/java/desugaredlibrary/AsmRewriter.java b/buildSrc/src/main/java/desugaredlibrary/AsmRewriter.java
new file mode 100644
index 0000000..cc1fcf2
--- /dev/null
+++ b/buildSrc/src/main/java/desugaredlibrary/AsmRewriter.java
@@ -0,0 +1,53 @@
+// 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 desugaredlibrary;
+
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+public abstract class AsmRewriter {
+
+  public static int ASM_VERSION = Opcodes.ASM9;
+
+  public static byte[] transformInvoke(byte[] bytes, MethodTransformer transformer) {
+    ClassReader reader = new ClassReader(bytes);
+    ClassWriter writer = new ClassWriter(reader, 0);
+    ClassVisitor subvisitor = new InvokeTransformer(writer, transformer);
+    reader.accept(subvisitor, 0);
+    return writer.toByteArray();
+  }
+
+  public static class InvokeTransformer extends ClassVisitor {
+
+    private final MethodTransformer transformer;
+
+    InvokeTransformer(ClassWriter writer, MethodTransformer transformer) {
+      super(ASM_VERSION, writer);
+      this.transformer = transformer;
+    }
+
+    @Override
+    public MethodVisitor visitMethod(
+        int access, String name, String descriptor, String signature, String[] exceptions) {
+      MethodVisitor sub = super.visitMethod(access, name, descriptor, signature, exceptions);
+      transformer.setMv(sub);
+      return transformer;
+    }
+  }
+
+  public static class MethodTransformer extends MethodVisitor {
+
+    protected MethodTransformer(int api) {
+      super(api);
+    }
+
+    public void setMv(MethodVisitor visitor) {
+      this.mv = visitor;
+    }
+  }
+}
diff --git a/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriteDescription.java b/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriteDescription.java
new file mode 100644
index 0000000..137ac12
--- /dev/null
+++ b/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriteDescription.java
@@ -0,0 +1,54 @@
+// 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 desugaredlibrary;
+
+import com.google.common.collect.ImmutableSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class CustomConversionAsmRewriteDescription {
+
+  static final String WRAP_CONVERT = "wrap_convert";
+  static final String INVERTED_WRAP_CONVERT = "inverted_wrap_convert";
+  static final String CONVERT = "convert";
+
+  private static final Set<String> ENUM_WRAP_CONVERT_OWNER =
+      ImmutableSet.of(
+          "j$/nio/file/StandardOpenOption",
+          "j$/nio/file/LinkOption",
+          "j$/nio/file/attribute/PosixFilePermission",
+          "j$/util/stream/Collector$Characteristics");
+  private static final Set<String> WRAP_CONVERT_OWNER =
+      ImmutableSet.of(
+          "j$/nio/file/spi/FileSystemProvider",
+          "j$/nio/file/spi/FileTypeDetector",
+          "j$/nio/file/Path",
+          "j$/nio/file/WatchEvent",
+          "j$/nio/file/attribute/BasicFileAttributes",
+          "j$/nio/file/attribute/BasicFileAttributeView",
+          "j$/nio/file/attribute/FileOwnerAttributeView",
+          "j$/nio/file/attribute/PosixFileAttributes",
+          "j$/nio/file/attribute/PosixFileAttributeView");
+
+  static Map<String, String> getJavaWrapConvertOwnerMap() {
+    return computeConvertOwnerMap("$VivifiedWrapper");
+  }
+
+  static Map<String, String> getJ$WrapConvertOwnerMap() {
+    return computeConvertOwnerMap("$Wrapper");
+  }
+
+  private static HashMap<String, String> computeConvertOwnerMap(String suffix) {
+    HashMap<String, String> map = new HashMap<>();
+    for (String theEnum : ENUM_WRAP_CONVERT_OWNER) {
+      map.put(theEnum, theEnum + "$EnumConversion");
+    }
+    for (String owner : WRAP_CONVERT_OWNER) {
+      map.put(owner, owner + suffix);
+    }
+    return map;
+  }
+}
diff --git a/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriter.java b/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriter.java
new file mode 100644
index 0000000..6107e67
--- /dev/null
+++ b/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriter.java
@@ -0,0 +1,183 @@
+// 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 desugaredlibrary;
+
+import static desugaredlibrary.AsmRewriter.ASM_VERSION;
+import static desugaredlibrary.CustomConversionAsmRewriteDescription.CONVERT;
+import static desugaredlibrary.CustomConversionAsmRewriteDescription.INVERTED_WRAP_CONVERT;
+import static desugaredlibrary.CustomConversionAsmRewriteDescription.WRAP_CONVERT;
+import static desugaredlibrary.CustomConversionAsmRewriter.CustomConversionVersion.LEGACY;
+import static org.objectweb.asm.Opcodes.INVOKESTATIC;
+
+import com.google.common.io.ByteStreams;
+import desugaredlibrary.AsmRewriter.MethodTransformer;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.OpenOption;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.zip.CRC32;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+public class CustomConversionAsmRewriter {
+
+  public enum CustomConversionVersion {
+    LEGACY,
+    LATEST
+  }
+
+  public CustomConversionAsmRewriter(CustomConversionVersion legacy) {
+    this.legacy = legacy;
+  }
+
+  private final CustomConversionVersion legacy;
+  private final Map<String, String> javaWrapConvertOwnerMap =
+      CustomConversionAsmRewriteDescription.getJavaWrapConvertOwnerMap();
+  private final Map<String, String> j$WrapConvertOwnerMap =
+      CustomConversionAsmRewriteDescription.getJ$WrapConvertOwnerMap();
+
+  public static void generateJars(Path jar, Path outputDirectory) throws IOException {
+    for (CustomConversionVersion version : CustomConversionVersion.values()) {
+      new CustomConversionAsmRewriter(version).convert(jar, outputDirectory);
+    }
+  }
+
+  private void convert(Path jar, Path outputDirectory) throws IOException {
+    String fileName = jar.getFileName().toString();
+    String newFileName =
+        fileName.substring(0, fileName.length() - "_raw.jar".length())
+            + (legacy == LEGACY ? "_legacy" : "")
+            + ".jar";
+    Path convertedJar = outputDirectory.resolve(newFileName);
+    internalConvert(jar, convertedJar);
+  }
+
+  private void internalConvert(Path jar, Path convertedJar) throws IOException {
+    OpenOption[] options =
+        new OpenOption[] {StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING};
+    try (ZipOutputStream out =
+        new ZipOutputStream(
+            new BufferedOutputStream(Files.newOutputStream(convertedJar, options)))) {
+      new CustomConversionAsmRewriter(legacy).convert(jar, out, legacy);
+    }
+  }
+
+  private void convert(
+      Path desugaredLibraryFiles, ZipOutputStream out, CustomConversionVersion legacy)
+      throws IOException {
+    try (ZipFile zipFile = new ZipFile(desugaredLibraryFiles.toFile(), StandardCharsets.UTF_8)) {
+      final Enumeration<? extends ZipEntry> entries = zipFile.entries();
+      while (entries.hasMoreElements()) {
+        ZipEntry entry = entries.nextElement();
+        try (InputStream entryStream = zipFile.getInputStream(entry)) {
+          handleFile(entry, entryStream, out, legacy);
+        }
+      }
+    }
+  }
+
+  private void handleFile(
+      ZipEntry entry, InputStream input, ZipOutputStream out, CustomConversionVersion legacy)
+      throws IOException {
+    if (!entry.getName().endsWith(".class")) {
+      return;
+    }
+    if (legacy == LEGACY
+        && (entry.getName().contains("java.nio.file")
+            || entry.getName().contains("ApiFlips")
+            || entry.getName().contains("java.adapter"))) {
+      return;
+    }
+    final byte[] bytes = ByteStreams.toByteArray(input);
+    input.close();
+    final byte[] rewrittenBytes = transformInvoke(bytes);
+    writeToZipStream(out, entry.getName(), rewrittenBytes, ZipEntry.STORED);
+  }
+
+  public static void writeToZipStream(
+      ZipOutputStream stream, String entry, byte[] content, int compressionMethod)
+      throws IOException {
+    int offset = 0;
+    int length = content.length;
+    CRC32 crc = new CRC32();
+    crc.update(content, offset, length);
+    ZipEntry zipEntry = new ZipEntry(entry);
+    zipEntry.setMethod(compressionMethod);
+    zipEntry.setSize(length);
+    zipEntry.setCrc(crc.getValue());
+    zipEntry.setTime(0);
+    stream.putNextEntry(zipEntry);
+    stream.write(content, offset, length);
+    stream.closeEntry();
+  }
+
+  private byte[] transformInvoke(byte[] bytes) {
+    return AsmRewriter.transformInvoke(bytes, new CustomConversionRewriter(ASM_VERSION));
+  }
+
+  class CustomConversionRewriter extends MethodTransformer {
+
+    protected CustomConversionRewriter(int api) {
+      super(api);
+    }
+
+    @Override
+    public void visitMethodInsn(
+        int opcode, String owner, String name, String descriptor, boolean isInterface) {
+      if (opcode == INVOKESTATIC) {
+        if (name.equals(WRAP_CONVERT)) {
+          convertInvoke(
+              opcode,
+              owner,
+              descriptor,
+              isInterface,
+              javaWrapConvertOwnerMap,
+              j$WrapConvertOwnerMap);
+          return;
+        }
+        if (name.equals(INVERTED_WRAP_CONVERT)) {
+          convertInvoke(
+              opcode,
+              owner,
+              descriptor,
+              isInterface,
+              j$WrapConvertOwnerMap,
+              javaWrapConvertOwnerMap);
+          return;
+        }
+      }
+      super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+    }
+
+    private void convertInvoke(
+        int opcode,
+        String owner,
+        String descriptor,
+        boolean isInterface,
+        Map<String, String> javaMap,
+        Map<String, String> j$Map) {
+      if (!javaMap.containsKey(owner)
+          || !j$Map.containsKey(owner)
+          || !(owner.startsWith("java") || owner.startsWith("j$"))) {
+        throw new RuntimeException("Cannot transform wrap_convert method for " + owner);
+      }
+      if (owner.startsWith("java")) {
+        String newOwner = j$Map.get(owner);
+        super.visitMethodInsn(opcode, newOwner, CONVERT, descriptor, isInterface);
+        return;
+      }
+      assert owner.startsWith("j$");
+      String newOwner = javaMap.get(owner);
+      super.visitMethodInsn(opcode, newOwner, CONVERT, descriptor, isInterface);
+    }
+  }
+}
diff --git a/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriterTask.java b/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriterTask.java
new file mode 100644
index 0000000..bae3c1c
--- /dev/null
+++ b/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriterTask.java
@@ -0,0 +1,78 @@
+// 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 desugaredlibrary;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import javax.inject.Inject;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.tasks.InputFile;
+import org.gradle.api.tasks.OutputDirectory;
+import org.gradle.api.tasks.TaskAction;
+import org.gradle.workers.IsolationMode;
+import org.gradle.workers.WorkerExecutor;
+
+public class CustomConversionAsmRewriterTask extends DefaultTask {
+
+  private final WorkerExecutor workerExecutor;
+
+  private File rawJar;
+  private File outputDirectory;
+
+  @Inject
+  public CustomConversionAsmRewriterTask(WorkerExecutor workerExecutor) {
+    this.workerExecutor = workerExecutor;
+  }
+
+  @InputFile
+  public File getRawJar() {
+    return rawJar;
+  }
+
+  public void setRawJar(File rawJar) {
+    this.rawJar = rawJar;
+  }
+
+  @OutputDirectory
+  public File getOutputDirectory() {
+    return outputDirectory;
+  }
+
+  public void setOutputDirectory(File outputDirectory) {
+    this.outputDirectory = outputDirectory;
+  }
+
+  @TaskAction
+  void exec() {
+    workerExecutor.submit(
+        Run.class,
+        config -> {
+          config.setIsolationMode(IsolationMode.NONE);
+          config.params(rawJar, outputDirectory);
+        });
+  }
+
+  public static class Run implements Runnable {
+
+    private final File rawJar;
+    private final File outputDirectory;
+
+    @Inject
+    public Run(File rawJar, File outputDirectory) {
+      this.rawJar = rawJar;
+      this.outputDirectory = outputDirectory;
+    }
+
+    @Override
+    public void run() {
+      try {
+        CustomConversionAsmRewriter.generateJars(rawJar.toPath(), outputDirectory.toPath());
+      } catch (IOException e) {
+        throw new UncheckedIOException(e);
+      }
+    }
+  }
+}
diff --git a/src/library_desugar/java/j$/nio/file/Path.java b/src/library_desugar/java/j$/nio/file/Path.java
index 781ab5f..cb01ec0 100644
--- a/src/library_desugar/java/j$/nio/file/Path.java
+++ b/src/library_desugar/java/j$/nio/file/Path.java
@@ -6,7 +6,7 @@
 
 public class Path {
 
-  public static j$.nio.file.Path wrap_convert(java.nio.file.Path path) {
+  public static j$.nio.file.Path inverted_wrap_convert(java.nio.file.Path path) {
     return null;
   }
 }
diff --git a/src/library_desugar/java/java/adapter/HybridFileTypeDetector.java b/src/library_desugar/java/java/adapter/HybridFileTypeDetector.java
index da93736..af2c8f7 100644
--- a/src/library_desugar/java/java/adapter/HybridFileTypeDetector.java
+++ b/src/library_desugar/java/java/adapter/HybridFileTypeDetector.java
@@ -29,7 +29,7 @@
   static class PlatformFileTypeDetector extends FileTypeDetector {
     @Override
     public String probeContentType(Path path) throws IOException {
-      return j$.nio.file.Files.probeContentType(j$.nio.file.Path.wrap_convert(path));
+      return j$.nio.file.Files.probeContentType(j$.nio.file.Path.inverted_wrap_convert(path));
     }
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index b9e0912..69f2167 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -15,7 +15,6 @@
 import com.android.tools.r8.TestRuntime.CfRuntime;
 import com.android.tools.r8.ToolHelper.DexVm.Kind;
 import com.android.tools.r8.benchmarks.BenchmarkResults;
-import com.android.tools.r8.desugar.desugaredlibrary.jdk11.ConversionConverter;
 import com.android.tools.r8.desugar.desugaredlibrary.jdk11.DesugaredLibraryJDK11Undesugarer;
 import com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.CustomConversionVersion;
 import com.android.tools.r8.dex.ApplicationReader;
@@ -180,8 +179,6 @@
   public static final Path DEPS = Paths.get(LIBS_DIR, "deps_all.jar");
   public static final Path R8_RETRACE_JAR = Paths.get(LIBS_DIR, "r8retrace.jar");
 
-  public static final Path DESUGAR_LIB_CONVERSIONS =
-      Paths.get(LIBS_DIR, "library_desugar_conversions.zip");
   public static final String DESUGARED_LIB_RELEASES_DIR =
       OPEN_JDK_DIR + "desugar_jdk_libs_releases/";
   public static final Path DESUGARED_JDK_8_LIB_JAR =
@@ -189,8 +186,10 @@
   public static final Path DESUGARED_JDK_11_LIB_JAR =
       Paths.get(OPEN_JDK_DIR + "desugar_jdk_libs_11/desugar_jdk_libs.jar");
 
-  public static Path getConvertedDesugaredLibConversions(CustomConversionVersion legacy) {
-    return ConversionConverter.convertJar(DESUGAR_LIB_CONVERSIONS, legacy);
+  public static Path getDesugarLibConversions(CustomConversionVersion legacy) {
+    return legacy == CustomConversionVersion.LEGACY
+        ? Paths.get(LIBS_DIR, "library_desugar_conversions_legacy.jar")
+        : Paths.get(LIBS_DIR, "library_desugar_conversions.jar");
   }
 
   public static Path getUndesugaredJdk11LibJarForTesting() {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java
index efee088..5a05e80 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java
@@ -54,7 +54,7 @@
             "JDK8_CL",
             ImmutableSet.of(
                 DESUGARED_JDK_8_LIB_JAR,
-                ToolHelper.getConvertedDesugaredLibConversions(LEGACY),
+                ToolHelper.getDesugarLibConversions(LEGACY),
                 ToolHelper.getCoreLambdaStubs()),
             JDK8.getSpecification(),
             ImmutableSet.of(ToolHelper.getAndroidJar(AndroidApiLevel.O)),
@@ -65,7 +65,7 @@
             "JDK11_CL",
             ImmutableSet.of(
                 ToolHelper.getUndesugaredJdk11LibJarForTesting(),
-                ToolHelper.getConvertedDesugaredLibConversions(LATEST),
+                ToolHelper.getDesugarLibConversions(LATEST),
                 ToolHelper.getCoreLambdaStubs()),
             JDK11.getSpecification(),
             ImmutableSet.of(ToolHelper.getAndroidJar(AndroidApiLevel.R)),
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/ConversionConverter.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/ConversionConverter.java
deleted file mode 100644
index 746a1d2..0000000
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/ConversionConverter.java
+++ /dev/null
@@ -1,179 +0,0 @@
-// 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.LibraryDesugaringSpecification.CustomConversionVersion.LEGACY;
-
-import com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.CustomConversionVersion;
-import com.android.tools.r8.references.Reference;
-import com.android.tools.r8.transformers.ClassFileTransformer;
-import com.android.tools.r8.transformers.MethodTransformer;
-import com.android.tools.r8.utils.StreamUtils;
-import com.android.tools.r8.utils.ZipUtils;
-import java.io.BufferedOutputStream;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.OpenOption;
-import java.nio.file.Path;
-import java.nio.file.StandardOpenOption;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipOutputStream;
-import org.objectweb.asm.Opcodes;
-
-public class ConversionConverter {
-
-  private static final Map<String, String> JAVA_WRAP_CONVERT_OWNER = new HashMap<>();
-  private static final Map<String, String> J$_WRAP_CONVERT_OWNER = new HashMap<>();
-
-  static {
-    JAVA_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/spi/FileSystemProvider",
-        "java/nio/file/spi/FileSystemProvider$VivifiedWrapper");
-    JAVA_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/spi/FileTypeDetector", "java/nio/file/spi/FileTypeDetector$VivifiedWrapper");
-    JAVA_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/StandardOpenOption", "java/nio/file/StandardOpenOption$EnumConversion");
-    JAVA_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/LinkOption", "java/nio/file/LinkOption$EnumConversion");
-    JAVA_WRAP_CONVERT_OWNER.put("j$/nio/file/Path", "java/nio/file/Path$Wrapper");
-    JAVA_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/WatchEvent", "java/nio/file/WatchEvent$VivifiedWrapper");
-    JAVA_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/attribute/BasicFileAttributes",
-        "java/nio/file/attribute/BasicFileAttributes$VivifiedWrapper");
-    JAVA_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/attribute/BasicFileAttributeView",
-        "java/nio/file/attribute/BasicFileAttributeView$VivifiedWrapper");
-    JAVA_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/attribute/FileOwnerAttributeView",
-        "java/nio/file/attribute/FileOwnerAttributeView$VivifiedWrapper");
-    JAVA_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/attribute/PosixFileAttributes",
-        "java/nio/file/attribute/PosixFileAttributes$VivifiedWrapper");
-    JAVA_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/attribute/PosixFileAttributeView",
-        "java/nio/file/attribute/PosixFileAttributeView$VivifiedWrapper");
-    JAVA_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/attribute/PosixFilePermission",
-        "java/nio/file/attribute/PosixFilePermission$EnumConversion");
-    JAVA_WRAP_CONVERT_OWNER.put(
-        "j$/util/stream/Collector$Characteristics",
-        "java/util/stream/Collector$Characteristics$EnumConversion");
-
-    J$_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/spi/FileSystemProvider", "java/nio/file/spi/FileSystemProvider$Wrapper");
-    J$_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/spi/FileTypeDetector", "java/nio/file/spi/FileTypeDetector$Wrapper");
-    J$_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/StandardOpenOption", "java/nio/file/StandardOpenOption$EnumConversion");
-    J$_WRAP_CONVERT_OWNER.put("j$/nio/file/LinkOption", "java/nio/file/LinkOption$EnumConversion");
-    J$_WRAP_CONVERT_OWNER.put("j$/nio/file/Path", "java/nio/file/Path$VivifiedWrapper");
-    J$_WRAP_CONVERT_OWNER.put("j$/nio/file/WatchEvent", "java/nio/file/WatchEvent$Wrapper");
-    J$_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/attribute/BasicFileAttributes",
-        "java/nio/file/attribute/BasicFileAttributes$Wrapper");
-    J$_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/attribute/BasicFileAttributeView",
-        "java/nio/file/attribute/BasicFileAttributeView$Wrapper");
-    J$_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/attribute/FileOwnerAttributeView",
-        "java/nio/file/attribute/FileOwnerAttributeView$Wrapper");
-    J$_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/attribute/PosixFileAttributes",
-        "java/nio/file/attribute/PosixFileAttributes$Wrapper");
-    J$_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/attribute/PosixFileAttributeView",
-        "java/nio/file/attribute/PosixFileAttributeView$Wrapper");
-    J$_WRAP_CONVERT_OWNER.put(
-        "j$/nio/file/attribute/PosixFilePermission",
-        "java/nio/file/attribute/PosixFilePermission$EnumConversion");
-    J$_WRAP_CONVERT_OWNER.put(
-        "j$/util/stream/Collector$Characteristics",
-        "java/util/stream/Collector$Characteristics$EnumConversion");
-  }
-
-  public static Path convertJar(Path jar, CustomConversionVersion legacy) {
-    String fileName = jar.getFileName().toString();
-    String newFileName =
-        fileName.substring(0, fileName.length() - ".jar".length())
-            + (legacy == LEGACY ? "_legacy" : "")
-            + "_converted.jar";
-    Path convertedJar = jar.getParent().resolve(newFileName);
-    return internalConvert(jar, convertedJar, legacy);
-  }
-
-  private static synchronized Path internalConvert(
-      Path jar, Path convertedJar, CustomConversionVersion legacy) {
-    if (Files.exists(convertedJar)) {
-      return convertedJar;
-    }
-
-    OpenOption[] options =
-        new OpenOption[] {StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING};
-    try (ZipOutputStream out =
-        new ZipOutputStream(
-            new BufferedOutputStream(Files.newOutputStream(convertedJar, options)))) {
-      new ConversionConverter().convert(jar, out, legacy);
-    } catch (IOException e) {
-      throw new RuntimeException(e);
-    }
-    return convertedJar;
-  }
-
-  private void convert(
-      Path desugaredLibraryFiles, ZipOutputStream out, CustomConversionVersion legacy)
-      throws IOException {
-    ZipUtils.iter(
-        desugaredLibraryFiles,
-        ((entry, input) -> {
-          if (!entry.getName().endsWith(".class")) {
-            return;
-          }
-          if (legacy == LEGACY
-              && (entry.getName().contains("nio.file") || entry.getName().contains("ApiFlips"))) {
-            return;
-          }
-          final byte[] bytes = StreamUtils.streamToByteArrayClose(input);
-          final byte[] rewrittenBytes =
-              transformInvoke(entry.getName().substring(0, entry.getName().length() - 6), bytes);
-          ZipUtils.writeToZipStream(out, entry.getName(), rewrittenBytes, ZipEntry.STORED);
-        }));
-  }
-
-  private byte[] transformInvoke(String descriptor, byte[] bytes) {
-    return ClassFileTransformer.create(bytes, Reference.classFromDescriptor(descriptor))
-        .addMethodTransformer(getMethodTransformer())
-        .transform();
-  }
-
-  private MethodTransformer getMethodTransformer() {
-    return new MethodTransformer() {
-      @Override
-      public void visitMethodInsn(
-          int opcode, String owner, String name, String descriptor, boolean isInterface) {
-        if (opcode == Opcodes.INVOKESTATIC && name.equals("wrap_convert")) {
-          if (!JAVA_WRAP_CONVERT_OWNER.containsKey(owner)
-              || !J$_WRAP_CONVERT_OWNER.containsKey(owner)) {
-            throw new RuntimeException("Cannot transform wrap_convert method for " + owner);
-          }
-          if (owner.startsWith("java")) {
-            String newOwner = J$_WRAP_CONVERT_OWNER.get(owner);
-            super.visitMethodInsn(opcode, newOwner, "convert", descriptor, isInterface);
-            return;
-          } else if (owner.startsWith("j$")) {
-            String newOwner = JAVA_WRAP_CONVERT_OWNER.get(owner);
-            super.visitMethodInsn(opcode, newOwner, "convert", descriptor, isInterface);
-            return;
-          } else {
-            throw new RuntimeException("Cannot transform wrap_convert method for " + owner);
-          }
-        }
-        super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
-      }
-    };
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/LibraryDesugaringSpecification.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/LibraryDesugaringSpecification.java
index 143a52d..b3cc9ab 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/LibraryDesugaringSpecification.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/LibraryDesugaringSpecification.java
@@ -168,7 +168,7 @@
       CustomConversionVersion legacy) {
     this(
         name,
-        ImmutableSet.of(desugarJdkLibs, ToolHelper.getConvertedDesugaredLibConversions(legacy)),
+        ImmutableSet.of(desugarJdkLibs, ToolHelper.getDesugarLibConversions(legacy)),
         Paths.get("src/library_desugar/" + specificationPath),
         ImmutableSet.of(ToolHelper.getAndroidJar(androidJarLevel)),
         descriptor,