Fix interface removal in tree pruner

Bug: b/259204069
Change-Id: I2133c3fcb970e6d368c618044dc06bfe5ff31e9e
diff --git a/src/library_desugar/java/java/adapter/AndroidVersionTest.java b/src/library_desugar/java/java/adapter/AndroidVersionTest.java
index 6425791..065761e 100644
--- a/src/library_desugar/java/java/adapter/AndroidVersionTest.java
+++ b/src/library_desugar/java/java/adapter/AndroidVersionTest.java
@@ -6,6 +6,7 @@
 
 public class AndroidVersionTest {
 
+  public static final boolean is24OrAbove = setUp("java.util.StringJoiner");
   public static final boolean is26OrAbove = setUp("java.nio.file.FileSystems");
   public static final boolean isHeadfull = setUp("android.os.Build");
 
diff --git a/src/library_desugar/java/java/nio/channels/DesugarChannels.java b/src/library_desugar/java/java/nio/channels/DesugarChannels.java
index 6380268..4ca851d 100644
--- a/src/library_desugar/java/java/nio/channels/DesugarChannels.java
+++ b/src/library_desugar/java/java/nio/channels/DesugarChannels.java
@@ -39,10 +39,10 @@
     if (raw == null) {
       return null;
     }
-    if (raw instanceof SeekableByteChannel) {
+    if (AndroidVersionTest.is24OrAbove) {
       return raw;
     }
-    return new WrappedFileChannel(raw);
+    return WrappedFileChannel.wrap(raw);
   }
 
   /**
@@ -63,12 +63,15 @@
 
     final FileChannel delegate;
 
-    private WrappedFileChannel(FileChannel delegate) {
-      this.delegate = delegate;
+    public static FileChannel wrap(FileChannel channel) {
+      if (channel instanceof WrappedFileChannel) {
+        return channel;
+      }
+      return new WrappedFileChannel(channel);
     }
 
-    FileChannel convert(FileChannel raw) {
-      return new WrappedFileChannel(raw);
+    private WrappedFileChannel(FileChannel delegate) {
+      this.delegate = delegate;
     }
 
     @Override
@@ -98,7 +101,7 @@
 
     @Override
     public FileChannel position(long newPosition) throws IOException {
-      return convert(delegate.position(newPosition));
+      return WrappedFileChannel.wrap(delegate.position(newPosition));
     }
 
     @Override
@@ -108,7 +111,7 @@
 
     @Override
     public FileChannel truncate(long size) throws IOException {
-      return convert(delegate.truncate(size));
+      return WrappedFileChannel.wrap(delegate.truncate(size));
     }
 
     @Override
diff --git a/src/main/java/com/android/tools/r8/shaking/TreePruner.java b/src/main/java/com/android/tools/r8/shaking/TreePruner.java
index 7170817..57726f6 100644
--- a/src/main/java/com/android/tools/r8/shaking/TreePruner.java
+++ b/src/main/java/com/android/tools/r8/shaking/TreePruner.java
@@ -156,6 +156,11 @@
     if (clazz == null) {
       return;
     }
+    if (clazz.isLibraryClass()) {
+      // TODO(b/259204069): Mitigation of invalid interface removal.
+      // It would be nice to integrate this with the api database.
+      return;
+    }
     for (DexType itf : clazz.interfaces) {
       if (interfaces.remove(itf) && interfaces.isEmpty()) {
         return;
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/FileChannelTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/FileChannelTest.java
index c39147d..6c5c149 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/FileChannelTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/FileChannelTest.java
@@ -18,8 +18,10 @@
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;
+import java.nio.channels.SeekableByteChannel;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.OpenOption;
@@ -38,6 +40,10 @@
 
   private static final String EXPECTED_RESULT =
       StringUtils.lines(
+          "true",
+          "true",
+          "true",
+          "true",
           "Hello World! ",
           "Hello World! ",
           "Bye bye. ",
@@ -89,11 +95,28 @@
   public static class TestClass {
 
     public static void main(String[] args) throws IOException {
+      instanceTest();
       fisTest();
       fosTest();
       fileChannelOpen();
     }
 
+    /**
+     * These check look obvious but they are not on low Api level due to the interface injection.
+     */
+    @SuppressWarnings("all")
+    private static void instanceTest() throws IOException {
+      Path tmp = Files.createTempFile("tmp", ".txt");
+      System.out.println(
+          new FileInputStream(tmp.toFile()).getChannel() instanceof SeekableByteChannel);
+      System.out.println(
+          new FileOutputStream(tmp.toFile()).getChannel() instanceof SeekableByteChannel);
+      System.out.println(
+          new RandomAccessFile(tmp.toFile(), "rw").getChannel() instanceof SeekableByteChannel);
+      System.out.println(
+          Files.newByteChannel(tmp, StandardOpenOption.READ) instanceof SeekableByteChannel);
+    }
+
     private static void fosTest() throws IOException {
       String toWrite = "The monkey eats...";
       Path tmp = Files.createTempFile("fos", ".txt");