Reland "Use local FileSystem through conversions on high API devices"

This reverts commit 688b2c24f7630758c232801c9cff51d2f78886a6.

Change-Id: Ic07720fd208164a213872a0b40b2a2098326fa84
diff --git a/src/library_desugar/java/j$/nio/file/FileSystem.java b/src/library_desugar/java/j$/nio/file/FileSystem.java
new file mode 100644
index 0000000..a7a49a2
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/FileSystem.java
@@ -0,0 +1,13 @@
+// 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 j$.nio.file;
+
+import j$.nio.file.spi.FileSystemProvider;
+
+public class FileSystem {
+  public FileSystemProvider provider() {
+    return null;
+  }
+}
diff --git a/src/library_desugar/java/j$/nio/file/FileSystems.java b/src/library_desugar/java/j$/nio/file/FileSystems.java
new file mode 100644
index 0000000..d7214ca
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/FileSystems.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 j$.nio.file;
+
+public class FileSystems {
+  public static FileSystem getDefault() {
+    return null;
+  }
+}
diff --git a/src/library_desugar/java/j$/nio/file/Files.java b/src/library_desugar/java/j$/nio/file/Files.java
index 2825d24..f34593b 100644
--- a/src/library_desugar/java/j$/nio/file/Files.java
+++ b/src/library_desugar/java/j$/nio/file/Files.java
@@ -5,10 +5,9 @@
 package j$.nio.file;
 
 import java.io.IOException;
-import java.nio.file.Path;
 
 public class Files {
-  public static String probeContentType(Path path) throws IOException {
+  public static String probeContentType(j$.nio.file.Path path) throws IOException {
     return null;
   }
 }
diff --git a/src/library_desugar/java/j$/nio/file/LinkOption.java b/src/library_desugar/java/j$/nio/file/LinkOption.java
new file mode 100644
index 0000000..b8cf168
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/LinkOption.java
@@ -0,0 +1,15 @@
+// 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 j$.nio.file;
+
+public class LinkOption extends OpenOption {
+  public static java.nio.file.LinkOption wrap_convert(j$.nio.file.LinkOption option) {
+    return null;
+  }
+
+  public static j$.nio.file.LinkOption wrap_convert(java.nio.file.LinkOption option) {
+    return null;
+  }
+}
diff --git a/src/library_desugar/java/j$/nio/file/OpenOption.java b/src/library_desugar/java/j$/nio/file/OpenOption.java
new file mode 100644
index 0000000..8b063d1
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/OpenOption.java
@@ -0,0 +1,7 @@
+// 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 j$.nio.file;
+
+public class OpenOption {}
diff --git a/src/library_desugar/java/j$/nio/file/Path.java b/src/library_desugar/java/j$/nio/file/Path.java
new file mode 100644
index 0000000..781ab5f
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/Path.java
@@ -0,0 +1,12 @@
+// 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 j$.nio.file;
+
+public class Path {
+
+  public static j$.nio.file.Path wrap_convert(java.nio.file.Path path) {
+    return null;
+  }
+}
diff --git a/src/library_desugar/java/j$/nio/file/StandardOpenOption.java b/src/library_desugar/java/j$/nio/file/StandardOpenOption.java
new file mode 100644
index 0000000..a65da37
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/StandardOpenOption.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 j$.nio.file;
+
+public class StandardOpenOption extends OpenOption {
+
+  public static java.nio.file.StandardOpenOption wrap_convert(
+      j$.nio.file.StandardOpenOption option) {
+    return null;
+  }
+
+  public static j$.nio.file.StandardOpenOption wrap_convert(
+      java.nio.file.StandardOpenOption option) {
+    return null;
+  }
+}
diff --git a/src/library_desugar/java/j$/nio/file/WatchEvent.java b/src/library_desugar/java/j$/nio/file/WatchEvent.java
new file mode 100644
index 0000000..fd977e9
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/WatchEvent.java
@@ -0,0 +1,16 @@
+// 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 j$.nio.file;
+
+public class WatchEvent<T> {
+
+  public static java.nio.file.WatchEvent<?> wrap_convert(j$.nio.file.WatchEvent<?> option) {
+    return null;
+  }
+
+  public static j$.nio.file.WatchEvent<?> wrap_convert(java.nio.file.WatchEvent<?> option) {
+    return null;
+  }
+}
diff --git a/src/library_desugar/java/j$/nio/file/attribute/BasicFileAttributeView.java b/src/library_desugar/java/j$/nio/file/attribute/BasicFileAttributeView.java
new file mode 100644
index 0000000..774cf2c
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/attribute/BasicFileAttributeView.java
@@ -0,0 +1,17 @@
+// 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 j$.nio.file.attribute;
+
+public class BasicFileAttributeView extends FileAttributeView {
+  public static java.nio.file.attribute.BasicFileAttributeView wrap_convert(
+      j$.nio.file.attribute.BasicFileAttributeView fileAttributeView) {
+    return null;
+  }
+
+  public static j$.nio.file.attribute.BasicFileAttributeView wrap_convert(
+      java.nio.file.attribute.BasicFileAttributeView fileAttributeView) {
+    return null;
+  }
+}
diff --git a/src/library_desugar/java/j$/nio/file/attribute/BasicFileAttributes.java b/src/library_desugar/java/j$/nio/file/attribute/BasicFileAttributes.java
new file mode 100644
index 0000000..dd91a95
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/attribute/BasicFileAttributes.java
@@ -0,0 +1,17 @@
+// 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 j$.nio.file.attribute;
+
+public class BasicFileAttributes {
+  public static java.nio.file.attribute.BasicFileAttributes wrap_convert(
+      j$.nio.file.attribute.BasicFileAttributes fileAttributes) {
+    return null;
+  }
+
+  public static j$.nio.file.attribute.BasicFileAttributes wrap_convert(
+      java.nio.file.attribute.BasicFileAttributes fileAttributes) {
+    return null;
+  }
+}
diff --git a/src/library_desugar/java/j$/nio/file/attribute/FileAttributeView.java b/src/library_desugar/java/j$/nio/file/attribute/FileAttributeView.java
new file mode 100644
index 0000000..34046eb3
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/attribute/FileAttributeView.java
@@ -0,0 +1,17 @@
+// 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 j$.nio.file.attribute;
+
+public class FileAttributeView {
+  public static java.nio.file.attribute.FileAttributeView wrap_convert(
+      j$.nio.file.attribute.FileAttributeView fileAttributeView) {
+    return null;
+  }
+
+  public static j$.nio.file.attribute.FileAttributeView wrap_convert(
+      java.nio.file.attribute.FileAttributeView fileAttributeView) {
+    return null;
+  }
+}
diff --git a/src/library_desugar/java/j$/nio/file/attribute/FileOwnerAttributeView.java b/src/library_desugar/java/j$/nio/file/attribute/FileOwnerAttributeView.java
new file mode 100644
index 0000000..34a637d
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/attribute/FileOwnerAttributeView.java
@@ -0,0 +1,17 @@
+// 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 j$.nio.file.attribute;
+
+public class FileOwnerAttributeView extends FileAttributeView {
+  public static java.nio.file.attribute.FileOwnerAttributeView wrap_convert(
+      j$.nio.file.attribute.FileOwnerAttributeView fileAttributeView) {
+    return null;
+  }
+
+  public static j$.nio.file.attribute.FileOwnerAttributeView wrap_convert(
+      java.nio.file.attribute.FileOwnerAttributeView fileAttributeView) {
+    return null;
+  }
+}
diff --git a/src/library_desugar/java/j$/nio/file/attribute/PosixFileAttributeView.java b/src/library_desugar/java/j$/nio/file/attribute/PosixFileAttributeView.java
new file mode 100644
index 0000000..bb24cb7
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/attribute/PosixFileAttributeView.java
@@ -0,0 +1,17 @@
+// 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 j$.nio.file.attribute;
+
+public class PosixFileAttributeView extends FileAttributeView {
+  public static java.nio.file.attribute.PosixFileAttributeView wrap_convert(
+      j$.nio.file.attribute.PosixFileAttributeView fileAttributeView) {
+    return null;
+  }
+
+  public static j$.nio.file.attribute.PosixFileAttributeView wrap_convert(
+      java.nio.file.attribute.PosixFileAttributeView fileAttributeView) {
+    return null;
+  }
+}
diff --git a/src/library_desugar/java/j$/nio/file/attribute/PosixFileAttributes.java b/src/library_desugar/java/j$/nio/file/attribute/PosixFileAttributes.java
new file mode 100644
index 0000000..5e61814
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/attribute/PosixFileAttributes.java
@@ -0,0 +1,17 @@
+// 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 j$.nio.file.attribute;
+
+public class PosixFileAttributes extends BasicFileAttributes {
+  public static java.nio.file.attribute.PosixFileAttributes wrap_convert(
+      j$.nio.file.attribute.PosixFileAttributes fileAttributes) {
+    return null;
+  }
+
+  public static j$.nio.file.attribute.PosixFileAttributes wrap_convert(
+      java.nio.file.attribute.PosixFileAttributes fileAttributes) {
+    return null;
+  }
+}
diff --git a/src/library_desugar/java/j$/nio/file/attribute/PosixFilePermission.java b/src/library_desugar/java/j$/nio/file/attribute/PosixFilePermission.java
new file mode 100644
index 0000000..94dbcbf
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/attribute/PosixFilePermission.java
@@ -0,0 +1,17 @@
+// 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 j$.nio.file.attribute;
+
+public class PosixFilePermission {
+  public static java.nio.file.attribute.PosixFilePermission wrap_convert(
+      j$.nio.file.attribute.PosixFilePermission permission) {
+    return null;
+  }
+
+  public static j$.nio.file.attribute.PosixFilePermission wrap_convert(
+      java.nio.file.attribute.PosixFilePermission permission) {
+    return null;
+  }
+}
diff --git a/src/library_desugar/java/j$/nio/file/spi/FileSystemProvider.java b/src/library_desugar/java/j$/nio/file/spi/FileSystemProvider.java
new file mode 100644
index 0000000..38152b3
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/spi/FileSystemProvider.java
@@ -0,0 +1,12 @@
+// 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 j$.nio.file.spi;
+
+public class FileSystemProvider {
+  public static java.nio.file.spi.FileSystemProvider wrap_convert(FileSystemProvider provider) {
+    // Rewritten in ASM to the wrapper method.
+    return null;
+  }
+}
diff --git a/src/library_desugar/java/java/adapter/HybridFileSystemProvider.java b/src/library_desugar/java/java/adapter/HybridFileSystemProvider.java
index 658c351..d02344d 100644
--- a/src/library_desugar/java/java/adapter/HybridFileSystemProvider.java
+++ b/src/library_desugar/java/java/adapter/HybridFileSystemProvider.java
@@ -4,13 +4,12 @@
 
 package java.adapter;
 
-import android.os.Build.VERSION;
 import android.os.StrictMode;
 import android.os.StrictMode.ThreadPolicy;
 import desugar.sun.nio.fs.DesugarDefaultFileSystemProvider;
+import j$.nio.file.FileSystems;
 import java.net.URI;
 import java.nio.file.FileSystem;
-import java.nio.file.FileSystems;
 import java.nio.file.spi.FileSystemProvider;
 
 /**
@@ -23,20 +22,26 @@
       INSTANCE.getFileSystem(URI.create("file:///"));
 
   private static FileSystemProvider getFileSystemProvider() {
-    if (VERSION.SDK_INT >= 26) {
-      return FileSystems.getDefault().provider();
-    } else {
-      try {
-        // In headless, android.os is absent so the following line will throw.
-        // We cannot set the ThreadPolicy in headless and it is irrelevant.
-        // If we are not in headless, the class will be found and we can set the thread policy.
-        Class.forName("android.os.Build");
-        setThreadPolicy();
-      } catch (ClassNotFoundException ignored) {
-        // Headless mode.
-      }
-      return DesugarDefaultFileSystemProvider.instance();
+    try {
+      // On API 26 and above, FileSystems is present.
+      Class.forName("java.nio.file.FileSystems");
+      j$.nio.file.FileSystem fileSystem = FileSystems.getDefault();
+      j$.nio.file.spi.FileSystemProvider provider = fileSystem.provider();
+      return j$.nio.file.spi.FileSystemProvider.wrap_convert(provider);
+    } catch (ClassNotFoundException ignored) {
+      // We reach this path is API < 26.
     }
+    // The DesugarDefaultFileSystemProvider requires the ThreadPolicy to be set to work correctly.
+    // We cannot set the ThreadPolicy in headless and it should not matter.
+    // In headless, android.os is absent so the following line will throw.
+    // In headfull, android.os is present and we set the thread policy.
+    try {
+      Class.forName("android.os.Build");
+      setThreadPolicy();
+    } catch (ClassNotFoundException ignored) {
+      // Headless mode.
+    }
+    return DesugarDefaultFileSystemProvider.instance();
   }
 
   private static void setThreadPolicy() {
diff --git a/src/library_desugar/java/java/adapter/HybridFileTypeDetector.java b/src/library_desugar/java/java/adapter/HybridFileTypeDetector.java
index 1caf2f1..da93736 100644
--- a/src/library_desugar/java/java/adapter/HybridFileTypeDetector.java
+++ b/src/library_desugar/java/java/adapter/HybridFileTypeDetector.java
@@ -4,7 +4,6 @@
 
 package java.adapter;
 
-import android.os.Build.VERSION;
 import desugar.sun.nio.fs.DesugarDefaultFileTypeDetector;
 import java.io.IOException;
 import java.nio.file.Path;
@@ -18,18 +17,19 @@
   private HybridFileTypeDetector() {}
 
   public static FileTypeDetector create() {
-    if (VERSION.SDK_INT >= 26) {
+    try {
+      // On API 26 and above, java.nio.file.Files is present.
+      Class.forName("java.nio.file.Files");
       return new PlatformFileTypeDetector();
-    } else {
+    } catch (ClassNotFoundException ignored) {
       return DesugarDefaultFileTypeDetector.create();
     }
   }
 
-  static class PlatformFileTypeDetector extends java.nio.file.spi.FileTypeDetector {
+  static class PlatformFileTypeDetector extends FileTypeDetector {
     @Override
     public String probeContentType(Path path) throws IOException {
-      // Relies at runtime on java.nio.file.Files.
-      return j$.nio.file.Files.probeContentType(path);
+      return j$.nio.file.Files.probeContentType(j$.nio.file.Path.wrap_convert(path));
     }
   }
 }
diff --git a/src/library_desugar/java/java/nio/file/FileApiFlips.java b/src/library_desugar/java/java/nio/file/FileApiFlips.java
new file mode 100644
index 0000000..fae6648
--- /dev/null
+++ b/src/library_desugar/java/java/nio/file/FileApiFlips.java
@@ -0,0 +1,170 @@
+// 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 java.nio.file;
+
+import static java.util.ConversionRuntimeException.exception;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class FileApiFlips {
+
+  public static Class<?> flipFileAttributes(Class<?> attributesClass) {
+    if (attributesClass == null) {
+      return null;
+    }
+    if (attributesClass == j$.nio.file.attribute.BasicFileAttributes.class) {
+      return java.nio.file.attribute.BasicFileAttributes.class;
+    }
+    if (attributesClass == j$.nio.file.attribute.PosixFileAttributes.class) {
+      return java.nio.file.attribute.PosixFileAttributes.class;
+    }
+    if (attributesClass == java.nio.file.attribute.BasicFileAttributes.class) {
+      return j$.nio.file.attribute.BasicFileAttributes.class;
+    }
+    if (attributesClass == java.nio.file.attribute.PosixFileAttributes.class) {
+      return j$.nio.file.attribute.PosixFileAttributes.class;
+    }
+    throw exception("java.nio.file.attribute.BasicFileAttributes", attributesClass);
+  }
+
+  public static Class<?> flipFileAttributeView(Class<?> attributeView) {
+    if (attributeView == null) {
+      return null;
+    }
+    if (attributeView == j$.nio.file.attribute.BasicFileAttributeView.class) {
+      return java.nio.file.attribute.BasicFileAttributeView.class;
+    }
+    if (attributeView == j$.nio.file.attribute.PosixFileAttributeView.class) {
+      return java.nio.file.attribute.PosixFileAttributeView.class;
+    }
+    if (attributeView == j$.nio.file.attribute.FileOwnerAttributeView.class) {
+      return java.nio.file.attribute.FileOwnerAttributeView.class;
+    }
+    if (attributeView == java.nio.file.attribute.BasicFileAttributeView.class) {
+      return j$.nio.file.attribute.BasicFileAttributeView.class;
+    }
+    if (attributeView == java.nio.file.attribute.PosixFileAttributeView.class) {
+      return j$.nio.file.attribute.PosixFileAttributeView.class;
+    }
+    if (attributeView == java.nio.file.attribute.FileOwnerAttributeView.class) {
+      return j$.nio.file.attribute.FileOwnerAttributeView.class;
+    }
+    throw exception("java.nio.file.attribute.FileAttributeView", attributeView);
+  }
+
+  public static RuntimeException exceptionOpenOption(Object suffix) {
+    throw exception("java.nio.file.OpenOption", suffix);
+  }
+
+  public static Set<?> flipOpenOptionSet(Set<?> openOptionSet) {
+    if (openOptionSet == null || openOptionSet.isEmpty()) {
+      return openOptionSet;
+    }
+    HashSet<Object> convertedSet = new HashSet<>();
+    Object guineaPig = openOptionSet.iterator().next();
+    if (guineaPig instanceof java.nio.file.OpenOption) {
+      for (Object item : openOptionSet) {
+        java.nio.file.OpenOption option;
+        try {
+          option = (java.nio.file.OpenOption) item;
+        } catch (ClassCastException cce) {
+          throw exceptionOpenOption(cce);
+        }
+        convertedSet.add(OpenOptionConversions.convert(option));
+      }
+      return convertedSet;
+    }
+    if (guineaPig instanceof j$.nio.file.OpenOption) {
+      for (Object item : openOptionSet) {
+        j$.nio.file.OpenOption option;
+        try {
+          option = (j$.nio.file.OpenOption) item;
+        } catch (ClassCastException cce) {
+          throw exceptionOpenOption(cce);
+        }
+        convertedSet.add(OpenOptionConversions.convert(option));
+      }
+      return convertedSet;
+    }
+    throw exceptionOpenOption(guineaPig.getClass());
+  }
+
+  public static RuntimeException exceptionPosixPermission(Object suffix) {
+    throw exception("java.nio.file.attribute.PosixFilePermission", suffix);
+  }
+
+  public static Set<?> flipPosixPermissionSet(Set<?> posixPermissions) {
+    if (posixPermissions == null || posixPermissions.isEmpty()) {
+      return posixPermissions;
+    }
+    HashSet<Object> convertedSet = new HashSet<>();
+    Object guineaPig = posixPermissions.iterator().next();
+    if (guineaPig instanceof java.nio.file.attribute.PosixFilePermission) {
+      for (Object item : posixPermissions) {
+        java.nio.file.attribute.PosixFilePermission permission;
+        try {
+          permission = (java.nio.file.attribute.PosixFilePermission) item;
+        } catch (ClassCastException cce) {
+          throw exceptionPosixPermission(cce);
+        }
+        convertedSet.add(j$.nio.file.attribute.PosixFilePermission.wrap_convert(permission));
+      }
+      return convertedSet;
+    }
+    if (guineaPig instanceof j$.nio.file.attribute.PosixFilePermission) {
+      for (Object item : posixPermissions) {
+        j$.nio.file.attribute.PosixFilePermission permission;
+        try {
+          permission = (j$.nio.file.attribute.PosixFilePermission) item;
+        } catch (ClassCastException cce) {
+          throw exceptionPosixPermission(cce);
+        }
+        convertedSet.add(j$.nio.file.attribute.PosixFilePermission.wrap_convert(permission));
+      }
+      return convertedSet;
+    }
+    throw exceptionPosixPermission(guineaPig.getClass());
+  }
+
+  public static RuntimeException exceptionWatchEvent(Object suffix) {
+    throw exception("java.nio.file.WatchEvent", suffix);
+  }
+
+  public static List<?> flipWatchEventList(List<?> watchEventList) {
+    if (watchEventList == null || watchEventList.isEmpty()) {
+      return watchEventList;
+    }
+    List<Object> convertedList = new ArrayList<>();
+    Object guineaPig = watchEventList.get(0);
+    if (guineaPig instanceof java.nio.file.WatchEvent) {
+      for (Object item : watchEventList) {
+        java.nio.file.WatchEvent<?> watchEvent;
+        try {
+          watchEvent = (java.nio.file.WatchEvent<?>) item;
+        } catch (ClassCastException cce) {
+          throw exceptionWatchEvent(cce);
+        }
+        convertedList.add(j$.nio.file.WatchEvent.wrap_convert(watchEvent));
+      }
+      return convertedList;
+    }
+    if (guineaPig instanceof j$.nio.file.WatchEvent) {
+      for (Object item : watchEventList) {
+        j$.nio.file.WatchEvent<?> watchEvent;
+        try {
+          watchEvent = (j$.nio.file.WatchEvent<?>) item;
+        } catch (ClassCastException cce) {
+          throw exceptionWatchEvent(cce);
+        }
+        convertedList.add(j$.nio.file.WatchEvent.wrap_convert(watchEvent));
+      }
+      return convertedList;
+    }
+    throw exceptionWatchEvent(guineaPig.getClass());
+  }
+}
diff --git a/src/library_desugar/java/java/nio/file/OpenOptionConversions.java b/src/library_desugar/java/java/nio/file/OpenOptionConversions.java
new file mode 100644
index 0000000..bfe4968
--- /dev/null
+++ b/src/library_desugar/java/java/nio/file/OpenOptionConversions.java
@@ -0,0 +1,35 @@
+// 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 java.nio.file;
+
+import static java.util.ConversionRuntimeException.exception;
+
+public class OpenOptionConversions {
+  public static java.nio.file.OpenOption convert(j$.nio.file.OpenOption option) {
+    if (option == null) {
+      return null;
+    }
+    if (option instanceof j$.nio.file.StandardOpenOption) {
+      return j$.nio.file.StandardOpenOption.wrap_convert((j$.nio.file.StandardOpenOption) option);
+    }
+    if (option instanceof j$.nio.file.LinkOption) {
+      return j$.nio.file.LinkOption.wrap_convert((j$.nio.file.LinkOption) option);
+    }
+    throw exception("java.nio.file.OpenOption", option);
+  }
+
+  public static j$.nio.file.OpenOption convert(java.nio.file.OpenOption option) {
+    if (option == null) {
+      return null;
+    }
+    if (option instanceof java.nio.file.StandardOpenOption) {
+      return j$.nio.file.StandardOpenOption.wrap_convert((java.nio.file.StandardOpenOption) option);
+    }
+    if (option instanceof java.nio.file.LinkOption) {
+      return j$.nio.file.LinkOption.wrap_convert((java.nio.file.LinkOption) option);
+    }
+    throw exception("java.nio.file.OpenOption", option);
+  }
+}
diff --git a/src/library_desugar/java/java/nio/file/attribute/FileAttributeConversions.java b/src/library_desugar/java/java/nio/file/attribute/FileAttributeConversions.java
index f4c4beb..332c89b 100644
--- a/src/library_desugar/java/java/nio/file/attribute/FileAttributeConversions.java
+++ b/src/library_desugar/java/java/nio/file/attribute/FileAttributeConversions.java
@@ -4,7 +4,10 @@
 
 package java.nio.file.attribute;
 
+import static java.util.ConversionRuntimeException.exception;
+
 public class FileAttributeConversions {
+
   public static java.nio.file.attribute.FileTime convert(j$.nio.file.attribute.FileTime fileTime) {
     if (fileTime == null) {
       return null;
@@ -18,4 +21,68 @@
     }
     return j$.nio.file.attribute.FileTime.fromMillis(fileTime.toMillis());
   }
+
+  public static java.nio.file.attribute.FileAttributeView convert(
+      j$.nio.file.attribute.FileAttributeView fileAttributeView) {
+    if (fileAttributeView == null) {
+      return null;
+    }
+    if (fileAttributeView instanceof j$.nio.file.attribute.PosixFileAttributeView) {
+      return j$.nio.file.attribute.PosixFileAttributeView.wrap_convert(
+          (j$.nio.file.attribute.PosixFileAttributeView) fileAttributeView);
+    }
+    if (fileAttributeView instanceof j$.nio.file.attribute.FileOwnerAttributeView) {
+      return j$.nio.file.attribute.FileOwnerAttributeView.wrap_convert(
+          (j$.nio.file.attribute.FileOwnerAttributeView) fileAttributeView);
+    }
+    if (fileAttributeView instanceof j$.nio.file.attribute.BasicFileAttributeView) {
+      return j$.nio.file.attribute.BasicFileAttributeView.wrap_convert(
+          (j$.nio.file.attribute.BasicFileAttributeView) fileAttributeView);
+    }
+    throw exception("java.nio.file.attribute.FileAttributeView", fileAttributeView);
+  }
+
+  public static j$.nio.file.attribute.FileAttributeView convert(
+      java.nio.file.attribute.FileAttributeView fileAttributeView) {
+    if (fileAttributeView == null) {
+      return null;
+    }
+    if (fileAttributeView instanceof java.nio.file.attribute.PosixFileAttributeView) {
+      return j$.nio.file.attribute.PosixFileAttributeView.wrap_convert(
+          (java.nio.file.attribute.PosixFileAttributeView) fileAttributeView);
+    }
+    if (fileAttributeView instanceof java.nio.file.attribute.FileOwnerAttributeView) {
+      return j$.nio.file.attribute.FileOwnerAttributeView.wrap_convert(
+          (java.nio.file.attribute.FileOwnerAttributeView) fileAttributeView);
+    }
+    if (fileAttributeView instanceof java.nio.file.attribute.BasicFileAttributeView) {
+      return j$.nio.file.attribute.BasicFileAttributeView.wrap_convert(
+          (java.nio.file.attribute.BasicFileAttributeView) fileAttributeView);
+    }
+    throw exception("java.nio.file.attribute.FileAttributeView", fileAttributeView);
+  }
+
+  public static java.nio.file.attribute.BasicFileAttributes convert(
+      j$.nio.file.attribute.BasicFileAttributes fileAttributes) {
+    if (fileAttributes == null) {
+      return null;
+    }
+    if (fileAttributes instanceof j$.nio.file.attribute.PosixFileAttributes) {
+      return j$.nio.file.attribute.PosixFileAttributes.wrap_convert(
+          (j$.nio.file.attribute.PosixFileAttributes) fileAttributes);
+    }
+    return j$.nio.file.attribute.BasicFileAttributes.wrap_convert(fileAttributes);
+  }
+
+  public static j$.nio.file.attribute.BasicFileAttributes convert(
+      java.nio.file.attribute.BasicFileAttributes fileAttributes) {
+    if (fileAttributes == null) {
+      return null;
+    }
+    if (fileAttributes instanceof java.nio.file.attribute.PosixFileAttributes) {
+      return j$.nio.file.attribute.PosixFileAttributes.wrap_convert(
+          (java.nio.file.attribute.PosixFileAttributes) fileAttributes);
+    }
+    return j$.nio.file.attribute.BasicFileAttributes.wrap_convert(fileAttributes);
+  }
 }
diff --git a/src/library_desugar/java/java/util/ConversionRuntimeException.java b/src/library_desugar/java/java/util/ConversionRuntimeException.java
new file mode 100644
index 0000000..896be1e
--- /dev/null
+++ b/src/library_desugar/java/java/util/ConversionRuntimeException.java
@@ -0,0 +1,16 @@
+// 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 java.util;
+
+public class ConversionRuntimeException extends RuntimeException {
+
+  public ConversionRuntimeException(String message) {
+    super(message);
+  }
+
+  public static RuntimeException exception(String type, Object suffix) {
+    throw new ConversionRuntimeException("Unsupported " + type + " :" + suffix);
+  }
+}
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_path.json b/src/library_desugar/jdk11/desugar_jdk_libs_path.json
index 4f0ec65..038efba 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_path.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_path.json
@@ -105,11 +105,15 @@
       "retarget_method_with_emulated_dispatch": {
         "java.nio.file.Path java.io.File#toPath()": "java.io.DesugarFile"
       },
-      "api_conversion_collection": {
-        "java.nio.channels.AsynchronousFileChannel java.nio.file.spi.FileSystemProvider#newAsynchronousFileChannel(java.nio.file.Path, java.util.Set, java.util.concurrent.ExecutorService, java.nio.file.attribute.FileAttribute[])" : [1, "OpenOption"],
-        "java.nio.channels.SeekableByteChannel java.nio.file.spi.FileSystemProvider#newByteChannel(java.nio.file.Path, java.util.Set, java.nio.file.attribute.FileAttribute[])" : [1, "OpenOption"],
-        "java.nio.channels.FileChannel java.nio.file.spi.FileSystemProvider#newFileChannel(java.nio.file.Path, java.util.Set, java.nio.file.attribute.FileAttribute[])" : [1, "OpenOption"],
-        "java.util.List java.nio.file.WatchKey#pollEvents()": [-1, "java.nio.file.WatchEvent"]
+      "api_generic_types_conversion": {
+        "java.nio.channels.AsynchronousFileChannel java.nio.file.spi.FileSystemProvider#newAsynchronousFileChannel(java.nio.file.Path, java.util.Set, java.util.concurrent.ExecutorService, java.nio.file.attribute.FileAttribute[])" : [1, "java.util.Set java.nio.file.FileApiFlips#flipOpenOptionSet(java.util.Set)"],
+        "java.nio.channels.SeekableByteChannel java.nio.file.spi.FileSystemProvider#newByteChannel(java.nio.file.Path, java.util.Set, java.nio.file.attribute.FileAttribute[])" : [1, "java.util.Set java.nio.file.FileApiFlips#flipOpenOptionSet(java.util.Set)"],
+        "java.nio.channels.FileChannel java.nio.file.spi.FileSystemProvider#newFileChannel(java.nio.file.Path, java.util.Set, java.nio.file.attribute.FileAttribute[])" : [1, "java.util.Set java.nio.file.FileApiFlips#flipOpenOptionSet(java.util.Set)"],
+        "java.util.List java.nio.file.WatchKey#pollEvents()": [-1, "java.util.List java.nio.file.FileApiFlips#flipWatchEventList(java.util.List)"],
+        "java.nio.file.attribute.FileAttributeView java.nio.file.spi.FileSystemProvider#getFileAttributeView(java.nio.file.Path, java.lang.Class, java.nio.file.LinkOption[])": [1, "java.lang.Class java.nio.file.FileApiFlips#flipFileAttributeView(java.lang.Class)"],
+        "java.nio.file.attribute.BasicFileAttributes java.nio.file.spi.FileSystemProvider#readAttributes(java.nio.file.Path, java.lang.Class, java.nio.file.LinkOption[])": [1, "java.lang.Class java.nio.file.FileApiFlips#flipFileAttributes(java.lang.Class)"],
+        "java.util.Set java.nio.file.attribute.PosixFileAttributes#permissions()": [-1, "java.util.Set java.nio.file.FileApiFlips#flipPosixPermissionSet(java.util.Set)"],
+        "void java.nio.file.attribute.PosixFileAttributeView#setPermissions(java.util.Set)": [0, "java.util.Set java.nio.file.FileApiFlips#flipPosixPermissionSet(java.util.Set)"]
       },
       "wrapper_conversion": [
         "java.nio.channels.AsynchronousChannel",
@@ -117,6 +121,7 @@
         "java.nio.file.Path",
         "java.nio.file.FileSystem",
         "java.nio.file.WatchService",
+        "java.nio.file.WatchEvent",
         "java.nio.file.WatchEvent$Kind",
         "java.nio.file.WatchKey",
         "java.nio.file.Watchable",
@@ -124,19 +129,24 @@
         "java.nio.file.WatchEvent$Modifier",
         "java.nio.file.attribute.UserPrincipalLookupService",
         "java.nio.file.spi.FileSystemProvider",
+        "java.nio.file.spi.FileTypeDetector",
         "java.nio.file.AccessMode",
+        "java.nio.file.StandardOpenOption",
         "java.nio.file.LinkOption",
         "java.nio.file.CopyOption",
         "java.nio.file.attribute.GroupPrincipal",
         "java.nio.file.attribute.FileAttribute",
-        "java.nio.file.attribute.FileAttributeView",
         "java.nio.file.attribute.UserPrincipal",
         "java.nio.file.FileStore",
         "java.nio.file.attribute.FileStoreAttributeView",
         "java.nio.file.DirectoryStream$Filter",
         "java.nio.file.DirectoryStream",
-        "java.nio.file.OpenOption",
-        "java.nio.file.attribute.BasicFileAttributes"
+        "java.nio.file.attribute.PosixFilePermission",
+        "java.nio.file.attribute.BasicFileAttributes",
+        "java.nio.file.attribute.PosixFileAttributes",
+        "java.nio.file.attribute.FileOwnerAttributeView",
+        "java.nio.file.attribute.PosixFileAttributeView",
+        "java.nio.file.attribute.BasicFileAttributeView"
       ],
       "wrapper_conversion_excluding": {
         "java.nio.channels.AsynchronousFileChannel": [
@@ -146,7 +156,10 @@
         ]
       },
       "custom_conversion": {
-        "java.nio.file.attribute.FileTime": "java.nio.file.attribute.FileAttributeConversions"
+        "java.nio.file.OpenOption": "java.nio.file.OpenOptionConversions",
+        "java.nio.file.attribute.FileTime": "java.nio.file.attribute.FileAttributeConversions",
+        "java.nio.file.attribute.BasicFileAttributes": "java.nio.file.attribute.FileAttributeConversions",
+        "java.nio.file.attribute.FileAttributeView": "java.nio.file.attribute.FileAttributeConversions"
       }
     },
     {
@@ -395,14 +408,33 @@
         "sun.nio.fs.BasicFileAttributesHolder": "j$.sun.nio.fs.BasicFileAttributesHolder",
         "sun.nio.fs.DynamicFileAttributeView": "j$.sun.nio.fs.DynamicFileAttributeView",
         "sun.util.PreHashedMap": "j$.sun.util.PreHashedMap",
-        "java.adapter" : "j$.adapter"
+        "java.adapter" : "j$.adapter",
+        "java.util.ConversionRuntimeException": "j$.util.ConversionRuntimeException"
       },
       "rewrite_derived_prefix": {
-        "java.nio.file.attribute.FileTime": {
-          "j$.nio.file.attribute.FileTime": "java.nio.file.attribute.FileTime"
+        "java.nio.file.attribute.": {
+          "j$.nio.file.attribute.": "java.nio.file.attribute."
+        },
+        "java.nio.file.OpenOption": {
+          "j$.nio.file.OpenOption": "java.nio.file.OpenOption"
+        },
+        "java.nio.file.StandardOpenOption": {
+          "j$.nio.file.StandardOpenOption": "java.nio.file.StandardOpenOption"
+        },
+        "java.nio.file.LinkOption": {
+          "j$.nio.file.LinkOption": "java.nio.file.LinkOption"
         },
         "java.nio.file.Files": {
           "j$.nio.file.Files": "java.nio.file.Files"
+        },
+        "java.nio.file.FileSystem": {
+          "j$.nio.file.FileSystem": "java.nio.file.FileSystem"
+        },
+        "java.nio.file.spi.FileSystemProvider": {
+          "j$.nio.file.spi.FileSystemProvider": "java.nio.file.spi.FileSystemProvider"
+        },
+        "java.nio.file.Path": {
+          "j$.nio.file.Path": "java.nio.file.Path"
         }
       },
       "retarget_method": {