Merge commit '9f651b6c4bddddc1cb687e4e803f3393e5a1b8c0' into dev-release
diff --git a/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriteDescription.java b/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriteDescription.java
index 52d878b..089a293 100644
--- a/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriteDescription.java
+++ b/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriteDescription.java
@@ -12,7 +12,6 @@
 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 =
diff --git a/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriter.java b/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriter.java
index c20de96..0848c09 100644
--- a/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriter.java
+++ b/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriter.java
@@ -6,7 +6,6 @@
 
 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;
@@ -133,51 +132,46 @@
     @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;
-        }
+      if (opcode == INVOKESTATIC && name.equals(WRAP_CONVERT)) {
+        convertInvoke(opcode, owner, descriptor, isInterface);
+        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);
+    private String extractFirstArg(String descriptor) {
+      assert descriptor.startsWith("(L");
+      int end = descriptor.indexOf(';');
+      assert end > 2;
+      return descriptor.substring(2, end);
+    }
+
+    private void convertInvoke(int opcode, String owner, String descriptor, boolean isInterface) {
+      String firstArg = extractFirstArg(descriptor);
+      assert sameBaseName(firstArg, owner);
+      if (!javaWrapConvertOwnerMap.containsKey(owner)
+          || !j$WrapConvertOwnerMap.containsKey(owner)
+          || !(firstArg.startsWith("java") || firstArg.startsWith("j$"))) {
+        throw new RuntimeException(
+            "Cannot transform wrap_convert method for " + firstArg + " (owner: " + owner + ")");
       }
-      if (owner.startsWith("java")) {
-        String newOwner = j$Map.get(owner);
+      if (firstArg.startsWith("java")) {
+        String newOwner = javaWrapConvertOwnerMap.get(owner);
         super.visitMethodInsn(opcode, newOwner, CONVERT, descriptor, isInterface);
         return;
       }
-      assert owner.startsWith("j$");
-      String newOwner = javaMap.get(owner);
+      assert firstArg.startsWith("j$");
+      String newOwner = j$WrapConvertOwnerMap.get(owner);
       super.visitMethodInsn(opcode, newOwner, CONVERT, descriptor, isInterface);
     }
+
+    private boolean sameBaseName(String firstArg, String owner) {
+      assert owner.startsWith("j$");
+      if (firstArg.equals(owner)) {
+        return true;
+      }
+      String javaName = owner.replace("j$", "java");
+      return firstArg.equals(javaName);
+    }
   }
 }
diff --git a/compatibility-faq.md b/compatibility-faq.md
index 8ca09d5..5614f6f 100644
--- a/compatibility-faq.md
+++ b/compatibility-faq.md
@@ -25,7 +25,8 @@
 - Default methods are not implicitly kept as abstract methods.
 - Attributes (such as `Signature`) and annotations are only kept for classes,
 methods and fields which are matched by keep rules even when `-keepattributes`
-is specified.
+is specified. The weakest rule that will keep annotations and attributes is 
+`-keep[classmembers],allowshrinking,allowoptimization,allowobfuscation,allowaccessmodification class-specification`
 Additionally, for attributes describing a relationship such as `InnerClass` and
 `EnclosingMethod`, non-compat mode requires both endpoints being kept.
 
diff --git a/src/library_desugar/java/j$/nio/file/spi/FileSystemProvider.java b/src/library_desugar/java/j$/nio/file/spi/FileSystemProvider.java
index 8db22b3..510d621 100644
--- a/src/library_desugar/java/j$/nio/file/spi/FileSystemProvider.java
+++ b/src/library_desugar/java/j$/nio/file/spi/FileSystemProvider.java
@@ -5,7 +5,7 @@
 package j$.nio.file.spi;
 
 public class FileSystemProvider {
-  public static java.nio.file.spi.FileSystemProvider inverted_wrap_convert(
+  public static java.nio.file.spi.FileSystemProvider wrap_convert(
       j$.nio.file.spi.FileSystemProvider provider) {
     // Rewritten in ASM to the wrapper method.
     return null;
diff --git a/src/library_desugar/java/j$/util/stream/Stream.java b/src/library_desugar/java/j$/util/stream/Stream.java
index dc5861d..7e06e4a 100644
--- a/src/library_desugar/java/j$/util/stream/Stream.java
+++ b/src/library_desugar/java/j$/util/stream/Stream.java
@@ -6,14 +6,6 @@
 
 public class Stream<T> {
 
-  public static java.util.stream.Stream<?> inverted_wrap_convert(j$.util.stream.Stream<?> stream) {
-    return null;
-  }
-
-  public static j$.util.stream.Stream<?> inverted_wrap_convert(java.util.stream.Stream<?> stream) {
-    return null;
-  }
-
   public static java.util.stream.Stream<?> wrap_convert(j$.util.stream.Stream<?> stream) {
     return null;
   }
diff --git a/src/library_desugar/java/java/adapter/HybridFileSystemProvider.java b/src/library_desugar/java/java/adapter/HybridFileSystemProvider.java
index 5be05a8..e34e571 100644
--- a/src/library_desugar/java/java/adapter/HybridFileSystemProvider.java
+++ b/src/library_desugar/java/java/adapter/HybridFileSystemProvider.java
@@ -29,7 +29,7 @@
       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.inverted_wrap_convert(provider);
+      return j$.nio.file.spi.FileSystemProvider.wrap_convert(provider);
     } catch (ClassNotFoundException ignored) {
       // We reach this path is API < 26.
     }
diff --git a/src/library_desugar/java/java/util/stream/FlatMapApiFlips.java b/src/library_desugar/java/java/util/stream/FlatMapApiFlips.java
index b9e1b9e..ac81093 100644
--- a/src/library_desugar/java/java/util/stream/FlatMapApiFlips.java
+++ b/src/library_desugar/java/java/util/stream/FlatMapApiFlips.java
@@ -37,6 +37,7 @@
       this.function = function;
     }
 
+    @SuppressWarnings("unchecked")
     private R flipStream(R maybeStream) {
       if (maybeStream == null) {
         return null;
@@ -89,6 +90,7 @@
       this.function = function;
     }
 
+    @SuppressWarnings("unchecked")
     private R flipStream(R maybeStream) {
       if (maybeStream == null) {
         return null;
@@ -115,6 +117,7 @@
       this.function = function;
     }
 
+    @SuppressWarnings("unchecked")
     private R flipStream(R maybeStream) {
       if (maybeStream == null) {
         return null;
@@ -143,6 +146,7 @@
       this.function = function;
     }
 
+    @SuppressWarnings("unchecked")
     private R flipStream(R maybeStream) {
       if (maybeStream == null) {
         return null;
diff --git a/src/library_desugar/java/java/util/stream/StackWalkerApiFlips.java b/src/library_desugar/java/java/util/stream/StackWalkerApiFlips.java
index 300c5ad..0951704 100644
--- a/src/library_desugar/java/java/util/stream/StackWalkerApiFlips.java
+++ b/src/library_desugar/java/java/util/stream/StackWalkerApiFlips.java
@@ -22,17 +22,16 @@
       this.function = function;
     }
 
+    @SuppressWarnings("unchecked")
     private T flipStream(T maybeStream) {
       if (maybeStream == null) {
         return null;
       }
       if (maybeStream instanceof java.util.stream.Stream<?>) {
-        return (T)
-            j$.util.stream.Stream.inverted_wrap_convert((java.util.stream.Stream<?>) maybeStream);
+        return (T) j$.util.stream.Stream.wrap_convert((java.util.stream.Stream<?>) maybeStream);
       }
       if (maybeStream instanceof j$.util.stream.Stream<?>) {
-        return (T)
-            j$.util.stream.Stream.inverted_wrap_convert((j$.util.stream.Stream<?>) maybeStream);
+        return (T) j$.util.stream.Stream.wrap_convert((j$.util.stream.Stream<?>) maybeStream);
       }
       throw exception("java.util.stream.Stream", maybeStream.getClass());
     }
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs.json b/src/library_desugar/jdk11/desugar_jdk_libs.json
index 9332de7..9cc01cc 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs.json
@@ -22,7 +22,85 @@
       ]
     },
     {
+      "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": 32,
+      "api_level_greater_or_equal": 24,
+      "emulate_interface": {
+        "java.util.Collection": "j$.util.Collection"
+      },
+      "dont_rewrite": [
+        "boolean java.util.Collection#removeIf(java.util.function.Predicate)",
+        "java.util.Spliterator java.util.Collection#spliterator()",
+        "java.util.stream.Stream java.util.Collection#parallelStream()",
+        "java.util.stream.Stream java.util.Collection#stream()",
+        "void java.util.Collection#forEach(java.util.function.Consumer)"
+      ],
+      "rewrite_prefix": {
+        "java.util.stream.DesugarCollectors": "j$.util.stream.DesugarCollectors"
+      },
+      "retarget_method": {
+        "java.util.stream.Collector java.util.stream.Collectors#filtering(java.util.function.Predicate, java.util.stream.Collector)": "java.util.stream.DesugarCollectors",
+        "java.util.stream.Collector java.util.stream.Collectors#flatMapping(java.util.function.Function, java.util.stream.Collector)": "java.util.stream.DesugarCollectors",
+        "java.util.stream.Collector java.util.stream.Collectors#toUnmodifiableList()": "java.util.stream.DesugarCollectors",
+        "java.util.stream.Collector java.util.stream.Collectors#toUnmodifiableMap(java.util.function.Function, java.util.function.Function)": "java.util.stream.DesugarCollectors",
+        "java.util.stream.Collector java.util.stream.Collectors#toUnmodifiableMap(java.util.function.Function, java.util.function.Function, java.util.function.BinaryOperator)": "java.util.stream.DesugarCollectors",
+        "java.util.stream.Collector java.util.stream.Collectors#toUnmodifiableSet()": "java.util.stream.DesugarCollectors"
+      },
+      "amend_library_method": [
+        "public static java.util.stream.Collector java.util.stream.Collectors#filtering(java.util.function.Predicate, java.util.stream.Collector)",
+        "public static java.util.stream.Collector java.util.stream.Collectors#flatMapping(java.util.function.Function, java.util.stream.Collector)",
+        "public static java.util.stream.Collector java.util.stream.Collectors#toUnmodifiableList()",
+        "public static java.util.stream.Collector java.util.stream.Collectors#toUnmodifiableMap(java.util.function.Function, java.util.function.Function)",
+        "public static java.util.stream.Collector java.util.stream.Collectors#toUnmodifiableMap(java.util.function.Function, java.util.function.Function, java.util.function.BinaryOperator)",
+        "public static java.util.stream.Collector java.util.stream.Collectors#toUnmodifiableSet()"
+      ]
+    },
+    {
       "api_level_below_or_equal": 30,
+      "api_level_greater_or_equal": 26,
+      "rewrite_prefix": {
+        "java.time.DesugarDuration": "j$.time.DesugarDuration",
+        "java.time.DesugarLocalTime": "j$.time.DesugarLocalTime"
+      },
+      "retarget_method": {
+        "long java.time.Duration#dividedBy(java.time.Duration)": "java.time.DesugarDuration",
+        "long java.time.Duration#toDaysPart()": "java.time.DesugarDuration",
+        "int java.time.Duration#toHoursPart()": "java.time.DesugarDuration",
+        "int java.time.Duration#toMillisPart()": "java.time.DesugarDuration",
+        "int java.time.Duration#toMinutesPart()": "java.time.DesugarDuration",
+        "int java.time.Duration#toNanosPart()": "java.time.DesugarDuration",
+        "long java.time.Duration#toSeconds()": "java.time.DesugarDuration",
+        "int java.time.Duration#toSecondsPart()": "java.time.DesugarDuration",
+        "java.time.Duration java.time.Duration#truncatedTo(java.time.temporal.TemporalUnit)": "java.time.DesugarDuration",
+        "java.time.LocalTime java.time.LocalTime#ofInstant(java.time.Instant, java.time.ZoneId)": "java.time.DesugarLocalTime",
+        "long java.time.LocalTime#toEpochSecond(java.time.LocalDate, java.time.ZoneOffset)": "java.time.DesugarLocalTime"
+      },
+      "amend_library_method": [
+        "public long java.time.Duration#dividedBy(java.time.Duration)",
+        "public long java.time.Duration#toDaysPart()",
+        "public int java.time.Duration#toHoursPart()",
+        "public int java.time.Duration#toMillisPart()",
+        "public int java.time.Duration#toMinutesPart()",
+        "public int java.time.Duration#toNanosPart()",
+        "public long java.time.Duration#toSeconds()",
+        "public int java.time.Duration#toSecondsPart()",
+        "public java.time.Duration java.time.Duration#truncatedTo(java.time.temporal.TemporalUnit)",
+        "public static java.time.LocalTime java.time.LocalTime#ofInstant(java.time.Instant, java.time.ZoneId)",
+        "public long java.time.LocalTime#toEpochSecond(java.time.LocalDate, java.time.ZoneOffset)"
+      ]
+    },
+    {
+      "api_level_below_or_equal": 25,
       "rewrite_prefix": {
         "java.time.": "j$.time.",
         "java.util.Desugar": "j$.util.Desugar"
@@ -50,31 +128,6 @@
       }
     },
     {
-      "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": 32,
-      "api_level_greater_or_equal": 24,
-      "emulate_interface": {
-        "java.util.Collection": "j$.util.Collection"
-      },
-      "dont_rewrite": [
-        "boolean java.util.Collection#removeIf(java.util.function.Predicate)",
-        "java.util.Spliterator java.util.Collection#spliterator()",
-        "java.util.stream.Stream java.util.Collection#parallelStream()",
-        "java.util.stream.Stream java.util.Collection#stream()",
-        "void java.util.Collection#forEach(java.util.function.Consumer)"
-      ]
-    },
-    {
       "api_level_below_or_equal": 23,
       "rewrite_prefix": {
         "java.io.DesugarBufferedReader": "j$.io.DesugarBufferedReader",
@@ -192,7 +245,7 @@
       ]
     },
     {
-      "api_level_below_or_equal": 30,
+      "api_level_below_or_equal": 25,
       "retarget_method": {
         "java.time.Instant java.util.Calendar#toInstant()": "java.util.DesugarCalendar",
         "java.util.Date java.util.Date#from(java.time.Instant)": "java.util.DesugarDate",
@@ -229,9 +282,6 @@
         "sun.misc.Desugar": "j$.sun.misc.Desugar"
       },
       "rewrite_derived_prefix": {
-        "java.time.": {
-          "j$.time.": "java.time."
-        },
         "sun.misc.DesugarUnsafe": {
           "jdk.internal.misc.Unsafe": "j$.sun.misc.DesugarUnsafe"
         }
@@ -250,8 +300,13 @@
       },
       "amend_library_method": [
         "private static boolean java.util.Arrays#deepEquals0(java.lang.Object, java.lang.Object)"
-      ]
-    },
+      ],
+      "rewrite_derived_prefix": {
+        "java.time.": {
+          "j$.time.": "java.time."
+        }
+      }
+      },
     {
       "api_level_below_or_equal": 23,
       "rewrite_prefix": {
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_legacy.json b/src/library_desugar/jdk11/desugar_jdk_libs_legacy.json
index c29c213..91f9a56 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_legacy.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_legacy.json
@@ -1,8 +1,8 @@
 {
   "configuration_format_version": 5,
-  "group_id" : "com.tools.android",
-  "artifact_id" : "desugar_jdk_libs",
-  "version": "1.2.3",
+  "group_id": "com.tools.android",
+  "artifact_id": "desugar_jdk_libs",
+  "version": "1.2.4",
   "required_compilation_api_level": 30,
   "synthesized_library_classes_package_prefix": "j$.",
   "support_all_callbacks_from_library": true,
@@ -47,29 +47,9 @@
     {
       "api_level_below_or_equal": 23,
       "rewrite_prefix": {
-        "java.util.concurrent.atomic.DesugarAtomic": "j$.util.concurrent.atomic.DesugarAtomic"
-      }
-    },
-    {
-      "api_level_below_or_equal": 23,
-      "rewrite_prefix": {
+        "java.util.concurrent.atomic.DesugarAtomic": "j$.util.concurrent.atomic.DesugarAtomic",
         "java.util.function.": "j$.util.function."
-      },
-      "emulate_interface": {
-        "java.lang.Iterable": "j$.lang.Iterable",
-        "java.util.Collection": "j$.util.Collection",
-        "java.util.Comparator": "j$.util.Comparator",
-        "java.util.Iterator": "j$.util.Iterator",
-        "java.util.List": "j$.util.List",
-        "java.util.Map": "j$.util.Map",
-        "java.util.Map$Entry": "j$.util.Map$Entry",
-        "java.util.Set": "j$.util.Set",
-        "java.util.SortedSet": "j$.util.SortedSet",
-        "java.util.concurrent.ConcurrentMap": "j$.util.concurrent.ConcurrentMap"
-      },
-      "dont_rewrite": [
-        "java.util.Iterator#remove"
-      ]
+      }
     },
     {
       "api_level_below_or_equal": 10000,
@@ -90,6 +70,21 @@
         "java.util.Arrays#stream": "java.util.DesugarArrays",
         "java.util.LinkedHashSet#spliterator": "java.util.DesugarLinkedHashSet"
       },
+      "emulate_interface": {
+        "java.lang.Iterable": "j$.lang.Iterable",
+        "java.util.Collection": "j$.util.Collection",
+        "java.util.Comparator": "j$.util.Comparator",
+        "java.util.Iterator": "j$.util.Iterator",
+        "java.util.List": "j$.util.List",
+        "java.util.Map": "j$.util.Map",
+        "java.util.Map$Entry": "j$.util.Map$Entry",
+        "java.util.Set": "j$.util.Set",
+        "java.util.SortedSet": "j$.util.SortedSet",
+        "java.util.concurrent.ConcurrentMap": "j$.util.concurrent.ConcurrentMap"
+      },
+      "dont_rewrite": [
+        "java.util.Iterator#remove"
+      ],
       "wrapper_conversion": [
         "java.util.Spliterator",
         "java.util.function.IntUnaryOperator",
@@ -234,4 +229,4 @@
     "-dontwarn sun.misc.Unsafe",
     "-dontwarn wrapper.**"
   ]
-}
\ No newline at end of file
+}
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_nio.json b/src/library_desugar/jdk11/desugar_jdk_libs_nio.json
index 5a1d513..c62cb34 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_nio.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_nio.json
@@ -29,7 +29,85 @@
       ]
     },
     {
+      "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": 32,
+      "api_level_greater_or_equal": 24,
+      "emulate_interface": {
+        "java.util.Collection": "j$.util.Collection"
+      },
+      "dont_rewrite": [
+        "boolean java.util.Collection#removeIf(java.util.function.Predicate)",
+        "java.util.Spliterator java.util.Collection#spliterator()",
+        "java.util.stream.Stream java.util.Collection#parallelStream()",
+        "java.util.stream.Stream java.util.Collection#stream()",
+        "void java.util.Collection#forEach(java.util.function.Consumer)"
+      ],
+      "rewrite_prefix": {
+        "java.util.stream.DesugarCollectors": "j$.util.stream.DesugarCollectors"
+      },
+      "retarget_method": {
+        "java.util.stream.Collector java.util.stream.Collectors#filtering(java.util.function.Predicate, java.util.stream.Collector)": "java.util.stream.DesugarCollectors",
+        "java.util.stream.Collector java.util.stream.Collectors#flatMapping(java.util.function.Function, java.util.stream.Collector)": "java.util.stream.DesugarCollectors",
+        "java.util.stream.Collector java.util.stream.Collectors#toUnmodifiableList()": "java.util.stream.DesugarCollectors",
+        "java.util.stream.Collector java.util.stream.Collectors#toUnmodifiableMap(java.util.function.Function, java.util.function.Function)": "java.util.stream.DesugarCollectors",
+        "java.util.stream.Collector java.util.stream.Collectors#toUnmodifiableMap(java.util.function.Function, java.util.function.Function, java.util.function.BinaryOperator)": "java.util.stream.DesugarCollectors",
+        "java.util.stream.Collector java.util.stream.Collectors#toUnmodifiableSet()": "java.util.stream.DesugarCollectors"
+      },
+      "amend_library_method": [
+        "public static java.util.stream.Collector java.util.stream.Collectors#filtering(java.util.function.Predicate, java.util.stream.Collector)",
+        "public static java.util.stream.Collector java.util.stream.Collectors#flatMapping(java.util.function.Function, java.util.stream.Collector)",
+        "public static java.util.stream.Collector java.util.stream.Collectors#toUnmodifiableList()",
+        "public static java.util.stream.Collector java.util.stream.Collectors#toUnmodifiableMap(java.util.function.Function, java.util.function.Function)",
+        "public static java.util.stream.Collector java.util.stream.Collectors#toUnmodifiableMap(java.util.function.Function, java.util.function.Function, java.util.function.BinaryOperator)",
+        "public static java.util.stream.Collector java.util.stream.Collectors#toUnmodifiableSet()"
+      ]
+    },
+    {
       "api_level_below_or_equal": 30,
+      "api_level_greater_or_equal": 26,
+      "rewrite_prefix": {
+        "java.time.DesugarDuration": "j$.time.DesugarDuration",
+        "java.time.DesugarLocalTime": "j$.time.DesugarLocalTime"
+      },
+      "retarget_method": {
+        "long java.time.Duration#dividedBy(java.time.Duration)": "java.time.DesugarDuration",
+        "long java.time.Duration#toDaysPart()": "java.time.DesugarDuration",
+        "int java.time.Duration#toHoursPart()": "java.time.DesugarDuration",
+        "int java.time.Duration#toMillisPart()": "java.time.DesugarDuration",
+        "int java.time.Duration#toMinutesPart()": "java.time.DesugarDuration",
+        "int java.time.Duration#toNanosPart()": "java.time.DesugarDuration",
+        "long java.time.Duration#toSeconds()": "java.time.DesugarDuration",
+        "int java.time.Duration#toSecondsPart()": "java.time.DesugarDuration",
+        "java.time.Duration java.time.Duration#truncatedTo(java.time.temporal.TemporalUnit)": "java.time.DesugarDuration",
+        "java.time.LocalTime java.time.LocalTime#ofInstant(java.time.Instant, java.time.ZoneId)": "java.time.DesugarLocalTime",
+        "long java.time.LocalTime#toEpochSecond(java.time.LocalDate, java.time.ZoneOffset)": "java.time.DesugarLocalTime"
+      },
+      "amend_library_method": [
+        "public long java.time.Duration#dividedBy(java.time.Duration)",
+        "public long java.time.Duration#toDaysPart()",
+        "public int java.time.Duration#toHoursPart()",
+        "public int java.time.Duration#toMillisPart()",
+        "public int java.time.Duration#toMinutesPart()",
+        "public int java.time.Duration#toNanosPart()",
+        "public long java.time.Duration#toSeconds()",
+        "public int java.time.Duration#toSecondsPart()",
+        "public java.time.Duration java.time.Duration#truncatedTo(java.time.temporal.TemporalUnit)",
+        "public static java.time.LocalTime java.time.LocalTime#ofInstant(java.time.Instant, java.time.ZoneId)",
+        "public long java.time.LocalTime#toEpochSecond(java.time.LocalDate, java.time.ZoneOffset)"
+      ]
+    },
+    {
+      "api_level_below_or_equal": 25,
       "rewrite_prefix": {
         "java.time.": "j$.time.",
         "java.util.Desugar": "j$.util.Desugar"
@@ -57,31 +135,6 @@
       }
     },
     {
-      "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": 32,
-      "api_level_greater_or_equal": 24,
-      "emulate_interface": {
-        "java.util.Collection": "j$.util.Collection"
-      },
-      "dont_rewrite": [
-        "boolean java.util.Collection#removeIf(java.util.function.Predicate)",
-        "java.util.Spliterator java.util.Collection#spliterator()",
-        "java.util.stream.Stream java.util.Collection#parallelStream()",
-        "java.util.stream.Stream java.util.Collection#stream()",
-        "void java.util.Collection#forEach(java.util.function.Consumer)"
-      ]
-    },
-    {
       "api_level_below_or_equal": 25,
       "rewrite_prefix": {
         "java.io.DesugarFile": "j$.io.DesugarFile",
@@ -193,13 +246,6 @@
       }
     },
     {
-      "api_level_below_or_equal": 32,
-      "api_level_greater_or_equal": 24,
-      "rewrite_prefix": {
-        "java.util.stream.Collectors": "j$.util.stream.Collectors"
-      }
-    },
-    {
       "api_level_below_or_equal": 23,
       "rewrite_prefix": {
         "java.io.DesugarBufferedReader": "j$.io.DesugarBufferedReader",
@@ -344,7 +390,7 @@
       ]
     },
     {
-      "api_level_below_or_equal": 30,
+      "api_level_below_or_equal": 25,
       "retarget_method": {
         "java.time.Instant java.util.Calendar#toInstant()": "java.util.DesugarCalendar",
         "java.util.Date java.util.Date#from(java.time.Instant)": "java.util.DesugarDate",
@@ -390,19 +436,10 @@
       "rewrite_prefix": {
         "desugar.": "j$.desugar.",
         "libcore.": "j$.libcore.",
-        "java.lang.Desugar": "j$.lang.Desugar",
         "sun.security.action.": "j$.sun.security.action."
       }
     },
     {
-      "api_level_below_or_equal": 30,
-      "rewrite_derived_prefix": {
-        "java.time.": {
-          "j$.time.": "java.time."
-        }
-      }
-    },
-    {
       "api_level_below_or_equal": 25,
       "rewrite_prefix": {
         "java.nio.channels.Desugar": "j$.nio.channels.Desugar",
@@ -450,6 +487,12 @@
         },
         "java.nio.file.Path": {
           "j$.nio.file.Path": "java.nio.file.Path"
+        },
+        "java.time.": {
+          "j$.time.": "java.time."
+        },
+        "java.nio.file.WatchEvent": {
+          "j$.nio.file.WatchEvent": "java.nio.file.WatchEvent"
         }
       },
       "retarget_method": {
@@ -510,6 +553,9 @@
     },
     {
       "api_level_below_or_equal": 18,
+      "rewrite_prefix": {
+        "java.lang.DesugarCharacter": "j$.lang.DesugarCharacter"
+      },
       "retarget_static_field": {
         "sun.nio.cs.US_ASCII sun.nio.cs.US_ASCII#INSTANCE": "java.nio.charset.Charset java.nio.charset.StandardCharsets#US_ASCII",
         "sun.nio.cs.ISO_8859_1 sun.nio.cs.ISO_8859_1#INSTANCE": "java.nio.charset.Charset java.nio.charset.StandardCharsets#ISO_8859_1",
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java
index 021a904..8c90b56 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java
@@ -15,6 +15,7 @@
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
 import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.ThreadUtils;
 import com.android.tools.r8.utils.Timing;
 import com.android.tools.r8.utils.Timing.TimingMerger;
@@ -145,6 +146,8 @@
       fileTiming.end();
       timings.add(fileTiming);
     }
+    updateStringIdsSizeAndOffset(dexOutputBuffer, sections);
+
     merger.add(timings);
     merger.end();
 
@@ -162,6 +165,39 @@
     }
   }
 
+  private void updateStringIdsSizeAndOffset(
+      DexOutputBuffer dexOutputBuffer, List<DexContainerSection> sections) {
+    // The last section has the shared string_ids table. Now it is written the final size and
+    // offset is known and the remaining sections can be updated to point to the shared table.
+    // This updates both the size and offset in the header and in the map.
+    DexContainerSection lastSection = ListUtils.last(sections);
+    int stringIdsSize = lastSection.getFileWriter().getMixedSectionOffsets().getStringData().size();
+    int stringIdsOffset = lastSection.getLayout().stringIdsOffset;
+    for (DexContainerSection section : sections) {
+      if (section != lastSection) {
+        dexOutputBuffer.moveTo(section.getLayout().headerOffset + Constants.STRING_IDS_SIZE_OFFSET);
+        dexOutputBuffer.putInt(stringIdsSize);
+        dexOutputBuffer.putInt(stringIdsOffset);
+        dexOutputBuffer.moveTo(section.getLayout().getMapOffset());
+        // Skip size.
+        dexOutputBuffer.getInt();
+        while (dexOutputBuffer.position() < section.getLayout().getEndOfFile()) {
+          int sectionType = dexOutputBuffer.getShort();
+          dexOutputBuffer.getShort(); // Skip unused.
+          if (sectionType == Constants.TYPE_STRING_ID_ITEM) {
+            dexOutputBuffer.putInt(stringIdsSize);
+            dexOutputBuffer.putInt(stringIdsOffset);
+            break;
+          } else {
+            // Skip size and offset for this type.
+            dexOutputBuffer.getInt();
+            dexOutputBuffer.getInt();
+          }
+        }
+      }
+    }
+  }
+
   private DexContainerSection writeVirtualFileSection(
       VirtualFile virtualFile,
       Timing timing,
diff --git a/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java b/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java
index e552456..d9cabaa 100644
--- a/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java
+++ b/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java
@@ -126,6 +126,14 @@
     byteBuffer.putInt(anInteger);
   }
 
+  public short getShort() {
+    return byteBuffer.getShort();
+  }
+
+  public int getInt() {
+    return byteBuffer.getInt();
+  }
+
   public boolean assertZero() {
     int pos = byteBuffer.position();
     int i = byteBuffer.getInt();
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
index d05ea55..0db5825 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
@@ -131,7 +131,8 @@
           field -> {
             FieldAccessInfo accessInfo = fieldAccessInfos.get(field.getReference());
             KeepFieldInfo keepInfo = appView.getKeepInfo(field);
-            if (keepInfo.isPinned(appView.options()) || accessInfo.isWrittenFromMethodHandle()) {
+            if (keepInfo.isPinned(appView.options())
+                || (accessInfo != null && accessInfo.isWrittenFromMethodHandle())) {
               fieldStates.put(field.getDefinition(), FieldState.unknown());
             }
           });
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryAmender.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryAmender.java
index f83ab04..167b91d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryAmender.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryAmender.java
@@ -6,6 +6,7 @@
 
 import com.android.tools.r8.androidapi.ComputedApiLevel;
 import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.ClassResolutionResult;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexDefinitionSupplier;
 import com.android.tools.r8.graph.DexEncodedField;
@@ -107,7 +108,18 @@
   private DexLibraryClass getLibraryClass(DexReference reference) {
     DexClass dexClass = definitions.contextIndependentDefinitionFor(reference.getContextType());
     if (dexClass == null || !dexClass.isLibraryClass()) {
-      // Consider just throwing an error.
+      // We can end up in situation where a class is rewritten at some API level but is used as
+      // a library class with a different min API level. We check here if there is a multiple
+      // resolution result.
+      ClassResolutionResult result =
+          definitions.contextIndependentDefinitionForWithResolutionResult(
+              reference.getContextType());
+      if (result.isMultipleClassResolutionResult()) {
+        DexClass alternativeClass = result.toAlternativeClass();
+        if (alternativeClass != null && alternativeClass.isLibraryClass()) {
+          return alternativeClass.asLibraryClass();
+        }
+      }
       reporter.warning(
           "Desugared library: Cannot amend library reference "
               + reference
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
index eb710e9..91da4d9 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
@@ -1,10 +1,11 @@
 // Copyright (c) 2021, 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.ir.desugar.itf;
 
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode.ALL;
 import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode.EMULATED_INTERFACE_ONLY;
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode.NONE;
 
 import com.android.tools.r8.cf.code.CfInvoke;
 import com.android.tools.r8.cf.code.CfNew;
@@ -386,9 +387,10 @@
     this.appView = appView;
     this.dexItemFactory = appView.dexItemFactory();
     this.helper = new InterfaceDesugaringSyntheticHelper(appView);
-    needsLibraryInfo =
-        !appView.options().canUseDefaultAndStaticInterfaceMethods()
-            && !appView.options().machineDesugaredLibrarySpecification.isEmpty();
+    assert desugaringMode != NONE;
+    assert desugaringMode == ALL
+        || !appView.options().machineDesugaredLibrarySpecification.isEmpty();
+    needsLibraryInfo = !appView.options().machineDesugaredLibrarySpecification.isEmpty();
     this.isLiveMethod = isLiveMethod;
     this.desugaringMode = desugaringMode;
   }
@@ -454,7 +456,7 @@
     }
     // Add non-library default methods as well as those for desugared library classes.
     if (!iface.isLibraryClass() || (needsLibraryInfo() && helper.isInDesugaredLibrary(iface))) {
-      MethodSignatures signatures = getDefaultMethods(iface);
+      MethodSignatures signatures = getDefaultMethodsMatching(iface, m -> true);
       interfaceInfo = interfaceInfo.withSignatures(signatures);
     }
     return interfaceInfo;
@@ -466,18 +468,29 @@
     assert iface.superType == dexItemFactory.objectType;
     assert helper.isEmulatedInterface(iface.type);
     assert needsLibraryInfo();
-    MethodSignatures signatures = getDefaultMethods(iface);
+    MethodSignatures signatures =
+        getDefaultMethodsMatching(
+            iface,
+            m ->
+                appView
+                        .options()
+                        .machineDesugaredLibrarySpecification
+                        .getEmulatedInterfaceEmulatedDispatchMethodDescriptor(m)
+                    != null);
     EmulatedInterfaceInfo emulatedInterfaceInfo =
         new EmulatedInterfaceInfo(signatures, new EmulatedInterfaces(iface.type));
     return interfaceInfo.withEmulatedInterfaceInfo(emulatedInterfaceInfo);
   }
 
-  private MethodSignatures getDefaultMethods(DexClass iface) {
+  private MethodSignatures getDefaultMethodsMatching(
+      DexClass iface, Predicate<DexMethod> predicate) {
     assert iface.isInterface();
     Set<Wrapper<DexMethod>> defaultMethods =
         new HashSet<>(iface.getMethodCollection().numberOfVirtualMethods());
     for (DexEncodedMethod method : iface.virtualMethods(DexEncodedMethod::isDefaultMethod)) {
-      defaultMethods.add(equivalence.wrap(method.getReference()));
+      if (predicate.test(method.getReference())) {
+        defaultMethods.add(equivalence.wrap(method.getReference()));
+      }
     }
     return MethodSignatures.create(defaultMethods);
   }
@@ -653,6 +666,7 @@
           });
     }
   }
+
   // If any of the signature would lead to a different behavior than the default method on the
   // emulated interface, we need to resolve the forwarding methods.
   private boolean shouldResolveForwardingMethodsForEmulatedInterfaces(
@@ -803,7 +817,6 @@
   }
 
   // Construction of actual forwarding methods.
-
   private void addSyntheticMethod(DexProgramClass clazz, DexEncodedMethod method) {
     newSyntheticMethods
         .computeIfAbsent(clazz, key -> ProgramMethodSet.create())
@@ -893,7 +906,6 @@
   }
 
   // Topological order traversal and its helpers.
-
   private DexClass definitionOrNull(DexType type, ReportingContext context) {
     // No forwards at the top of the class hierarchy (assuming java.lang.Object is never amended).
     if (type == null || type == dexItemFactory.objectType) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/EmulatedInterfaceApplicationRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/EmulatedInterfaceApplicationRewriter.java
index c764377..fd607ee 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/EmulatedInterfaceApplicationRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/EmulatedInterfaceApplicationRewriter.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.graph.GenericSignature;
 import com.android.tools.r8.graph.GenericSignature.ClassSignature;
 import com.android.tools.r8.graph.MethodCollection.MethodCollectionFactory;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.utils.IterableUtils;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -59,9 +60,8 @@
     }
     DexType newType = emulatedInterfaces.get(emulatedInterface.type);
     assert newType != null;
-    DexEncodedMethod[] newVirtualMethods =
-        renameHolder(emulatedInterface.virtualMethods(), newType);
-    DexEncodedMethod[] newDirectMethods = renameHolder(emulatedInterface.directMethods(), newType);
+    DexEncodedMethod[] newVirtualMethods = computeNewVirtualMethods(emulatedInterface, newType);
+    DexEncodedMethod[] newDirectMethods = DexEncodedMethod.EMPTY_ARRAY;
     assert emulatedInterface.getSuperType() == appView.dexItemFactory().objectType;
     assert !emulatedInterface.hasFields();
     assert emulatedInterface.getNestHost() == null;
@@ -116,11 +116,24 @@
     return newInterfaces;
   }
 
-  private DexEncodedMethod[] renameHolder(Iterable<DexEncodedMethod> methods, DexType newName) {
-    List<DexEncodedMethod> methodArray = IterableUtils.toNewArrayList(methods);
+  private DexEncodedMethod[] computeNewVirtualMethods(
+      DexProgramClass emulatedInterface, DexType newName) {
+    Iterable<ProgramMethod> emulatedMethods =
+        emulatedInterface.virtualProgramMethods(
+            m ->
+                appView
+                        .options()
+                        .machineDesugaredLibrarySpecification
+                        .getEmulatedInterfaceEmulatedDispatchMethodDescriptor(m.getReference())
+                    != null);
+    List<ProgramMethod> methodArray = IterableUtils.toNewArrayList(emulatedMethods);
     DexEncodedMethod[] newMethods = new DexEncodedMethod[methodArray.size()];
     for (int i = 0; i < newMethods.length; i++) {
-      newMethods[i] = methodArray.get(i).toRenamedHolderMethod(newName, appView.dexItemFactory());
+      newMethods[i] =
+          methodArray
+              .get(i)
+              .getDefinition()
+              .toRenamedHolderMethod(newName, appView.dexItemFactory());
     }
     return newMethods;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 4d31397..6099074 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -1980,8 +1980,13 @@
       Map<BasicBlock, LinkedHashMap<Value, Instruction>> addConstantInBlock,
       Predicate<Instruction> selector) {
     InstructionListIterator iterator = block.listIterator(code);
+    boolean seenCompareExit = false;
     while (iterator.hasNext()) {
       Instruction instruction = iterator.next();
+      if (options.canHaveCmpIfFloatBug() && instruction.isCmp()) {
+        seenCompareExit = true;
+      }
+
       if (instruction.hasUnusedOutValue() || instruction.outValue().hasLocalInfo()) {
         continue;
       }
@@ -2008,6 +2013,7 @@
         Instruction uniqueUse = instruction.outValue().singleUniqueUser();
         Instruction next = iterator.next();
         if (uniqueUse == next) {
+          iterator.previous();
           continue;
         }
         if (next.hasOutValue()
@@ -2017,6 +2023,7 @@
           Instruction nextNext = iterator.peekNext();
           Instruction uniqueUseNext = next.outValue().singleUniqueUser();
           if (uniqueUse == nextNext && uniqueUseNext == nextNext) {
+            iterator.previous();
             continue;
           }
         }
@@ -2053,6 +2060,14 @@
         }
       }
 
+      // If the dominator block has a potential compare exit we will chose that as the insertion
+      // point. Uniquely for instructions having invalues this can be before the definition of them.
+      // Bail-out when this is the case. See b/251015885 for more information.
+      if (seenCompareExit
+          && Iterables.any(instruction.inValues(), x -> x.getBlock() == dominator)) {
+        continue;
+      }
+
       Instruction copy;
       switch (instruction.opcode()) {
         case CONST_CLASS:
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java
index 0184def..ea58acd 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java
@@ -221,11 +221,13 @@
       this.retraceMethodResult = retraceMethodResult;
       this.methodReference = methodReference;
       this.mapping = mapping;
-      assert mapping != null;
     }
 
     @Override
     public boolean isCompilerSynthesized() {
+      if (mapping == null) {
+        return false;
+      }
       if (mapping.getMemberNaming() != null) {
         return mapping.getMemberNaming().isCompilerSynthesized();
       } else {
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 09c87e2..30a8723 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -2226,6 +2226,19 @@
       return;
     }
 
+    if (!clazz.isInterface()) {
+      throw appView
+          .reporter()
+          .fatalError(
+              "The class "
+                  + implementer
+                  + " implements the interface "
+                  + type
+                  + " but "
+                  + type
+                  + " is not an interface.");
+    }
+
     if (!appView.options().enableUnusedInterfaceRemoval
         || rootSet.noUnusedInterfaceRemoval.contains(type)
         || mode.isMainDexTracing()) {
diff --git a/src/test/examplesJava10/collectors/Main.java b/src/test/examplesJava10/collectors/Main.java
new file mode 100644
index 0000000..a1b3d71
--- /dev/null
+++ b/src/test/examplesJava10/collectors/Main.java
@@ -0,0 +1,38 @@
+// 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 collectors;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class Main {
+
+  public static void main(String[] args) {
+    Collector<Object, ?, List<Object>> filtering =
+        Collectors.filtering(Objects::nonNull, Collectors.toList());
+    System.out.println(Stream.of(null, 1).collect(filtering).get(0));
+
+    Collector<List<?>, ?, List<Object>> collector =
+        Collectors.flatMapping(Collection::stream, Collectors.toList());
+    System.out.println(Stream.of(List.of(1)).collect(collector).get(0));
+
+    Collector<Object, ?, List<Object>> toList = Collectors.toUnmodifiableList();
+    System.out.println(Stream.of(1).collect(toList).get(0));
+    Collector<Object, ?, Set<Object>> toSet = Collectors.toUnmodifiableSet();
+    System.out.println(Stream.of(1).collect(toSet).iterator().next());
+    Collector<Object, ?, Map<String, Integer>> toMap1 =
+        Collectors.toUnmodifiableMap(Object::toString, Object::hashCode);
+    System.out.println(Stream.of(1).collect(toMap1).keySet().iterator().next());
+    Collector<Object, ?, Map<String, Integer>> toMap2 =
+        Collectors.toUnmodifiableMap(Object::toString, Object::hashCode, (x, y) -> x);
+    System.out.println(Stream.of(1).collect(toMap2).keySet().iterator().next());
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelMockDalvikVerifyErrorTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelMockDalvikVerifyErrorTest.java
new file mode 100644
index 0000000..50edd76
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelMockDalvikVerifyErrorTest.java
@@ -0,0 +1,139 @@
+// 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.apimodel;
+
+import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForClass;
+import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForDefaultInstanceInitializer;
+import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForMethod;
+import static com.android.tools.r8.apimodel.ApiModelingTestHelper.verifyThat;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.SingleTestRunResult;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestCompilerBuilder;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.testing.AndroidBuildVersion;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+/** This is a regression test for b/252558440. */
+@RunWith(Parameterized.class)
+public class ApiModelMockDalvikVerifyErrorTest extends TestBase {
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  private final AndroidApiLevel mockLevel = AndroidApiLevel.M;
+
+  private boolean isGreaterOrEqualToMockLevel() {
+    return parameters.isDexRuntime() && parameters.getApiLevel().isGreaterThanOrEqualTo(mockLevel);
+  }
+
+  private void setupTestBuilder(TestCompilerBuilder<?, ?, ?, ?, ?> testBuilder) throws Exception {
+    testBuilder
+        .addProgramClasses(Main.class)
+        .addLibraryClasses(LibraryClass.class, LibrarySub.class)
+        .addDefaultRuntimeLibrary(parameters)
+        .setMinApi(parameters.getApiLevel())
+        .addAndroidBuildVersion()
+        .apply(ApiModelingTestHelper::enableStubbingOfClasses)
+        .apply(setMockApiLevelForClass(LibraryClass.class, mockLevel))
+        .apply(setMockApiLevelForDefaultInstanceInitializer(LibraryClass.class, mockLevel))
+        .apply(setMockApiLevelForMethod(LibraryClass.class.getDeclaredMethod("foo"), mockLevel));
+  }
+
+  private boolean addToBootClasspath() {
+    return parameters.isCfRuntime()
+        || parameters.getRuntime().maxSupportedApiLevel().isGreaterThanOrEqualTo(mockLevel);
+  }
+
+  @Test
+  public void testD8Debug() throws Exception {
+    assumeTrue(parameters.isDexRuntime());
+    testForD8()
+        .setMode(CompilationMode.DEBUG)
+        .apply(this::setupTestBuilder)
+        .compile()
+        .applyIf(addToBootClasspath(), b -> b.addBootClasspathClasses(LibraryClass.class))
+        .inspect(this::inspect)
+        .run(parameters.getRuntime(), Main.class)
+        .apply(this::checkOutput);
+  }
+
+  @Test
+  public void testD8Release() throws Exception {
+    assumeTrue(parameters.isDexRuntime());
+    testForD8()
+        .setMode(CompilationMode.RELEASE)
+        .apply(this::setupTestBuilder)
+        .compile()
+        .applyIf(addToBootClasspath(), b -> b.addBootClasspathClasses(LibraryClass.class))
+        .inspect(this::inspect)
+        .run(parameters.getRuntime(), Main.class)
+        .apply(this::checkOutput);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .apply(this::setupTestBuilder)
+        .addKeepMainRule(Main.class)
+        .compile()
+        .inspect(this::inspect)
+        .applyIf(
+            addToBootClasspath(),
+            b -> b.addBootClasspathClasses(LibraryClass.class, LibrarySub.class))
+        .run(parameters.getRuntime(), Main.class)
+        .apply(this::checkOutput);
+  }
+
+  private void checkOutput(SingleTestRunResult<?> runResult) {
+    if (isGreaterOrEqualToMockLevel()) {
+      runResult.assertFailureWithErrorThatThrows(ClassCastException.class);
+    } else {
+      runResult.assertSuccessWithOutputLines("Hello World!");
+    }
+  }
+
+  private void inspect(CodeInspector inspector) {
+    verifyThat(inspector, parameters, LibraryClass.class).stubbedUntil(mockLevel);
+  }
+
+  public abstract static class LibraryClass {
+
+    public abstract void foo();
+  }
+
+  public static class LibrarySub extends LibraryClass {
+
+    @Override
+    public void foo() {
+      System.out.println("LibrarySub::foo");
+    }
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      if (AndroidBuildVersion.VERSION >= 23) {
+        LibraryClass librarySub = (LibraryClass) new Object();
+        librarySub.foo();
+      } else {
+        System.out.println("Hello World!");
+      }
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionTest.java
index 872ca85..df80365 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionTest.java
@@ -5,16 +5,20 @@
 package com.android.tools.r8.desugar.desugaredlibrary;
 
 import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.SPECIFICATIONS_WITH_CF2CF;
-import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.getJdk8Jdk11;
+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.JDK8;
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification;
 import com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification;
+import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject.JumboStringMode;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import com.google.common.collect.ImmutableList;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -22,6 +26,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.SortedSet;
+import java.util.function.Predicate;
 import java.util.stream.Stream;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -39,7 +44,7 @@
   public static List<Object[]> data() {
     return buildParameters(
         getTestParameters().withDexRuntimes().withAllApiLevels().build(),
-        getJdk8Jdk11(),
+        ImmutableList.of(JDK8, JDK11, JDK11_LEGACY),
         SPECIFICATIONS_WITH_CF2CF);
   }
 
@@ -82,16 +87,17 @@
     }
     MethodSubject direct =
         inspector.clazz(Executor.class).uniqueMethodWithOriginalName("directTypes");
+    Predicate<InstructionSubject> matcher =
+        parameters.getApiLevel().isLessThan(AndroidApiLevel.N)
+            ? (instr ->
+                instr.toString().contains("$-EL")
+                    || instr.toString().contains("Comparator$-CC")
+                    || instr.toString().contains("Stream$-CC"))
+            : (instr ->
+                instr.toString().contains("$-EL") || instr.toString().contains("Comparator"));
     if (libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters)) {
       assertTrue(
-          direct
-              .streamInstructions()
-              .filter(InstructionSubject::isInvokeStatic)
-              .allMatch(
-                  instr ->
-                      instr.toString().contains("$-EL")
-                          || instr.toString().contains("Comparator$-CC")
-                          || instr.toString().contains("Stream$-CC")));
+          direct.streamInstructions().filter(InstructionSubject::isInvokeStatic).allMatch(matcher));
     } else {
       assertTrue(direct.streamInstructions().noneMatch(instr -> instr.toString().contains("$-EL")));
     }
@@ -106,11 +112,7 @@
         inherited
             .streamInstructions()
             .filter(InstructionSubject::isInvokeStatic)
-            .allMatch(
-                instr ->
-                    instr.toString().contains("$-EL")
-                        || instr.toString().contains("Comparator$-CC")
-                        || instr.toString().contains("Stream$-CC")));
+            .allMatch(matcher));
     inherited.streamInstructions().forEach(this::assertInheritedDispatchCorrect);
   }
 
@@ -118,16 +120,15 @@
     if (!instructionSubject.isConstString(JumboStringMode.ALLOW)) {
       for (String s : new String[] {">stream", "spliterator", "sort"}) {
         if (instructionSubject.toString().contains(s)) {
-            assertTrue(instructionSubject.isInvokeStatic());
-            assertTrue(
-                instructionSubject.toString().contains("$-EL")
-                    || instructionSubject.toString().contains("Comparator$-CC"));
+          assertTrue(instructionSubject.isInvokeStatic());
+          assertTrue(
+              instructionSubject.toString().contains("$-EL")
+                  || instructionSubject.toString().contains("Comparator$-CC"));
         }
       }
     }
   }
 
-
   static class Executor {
 
     // In directTypes() the collections use directly their type which implements a j$ interface
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryContentTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryContentTest.java
index 2838f2c..76bd656 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryContentTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryContentTest.java
@@ -15,20 +15,39 @@
 import static org.hamcrest.core.StringContains.containsString;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification;
 import com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification;
+import com.android.tools.r8.dex.ApplicationReader;
+import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DirectMappedDexApplication;
+import com.android.tools.r8.graph.MethodResolutionResult;
+import com.android.tools.r8.synthesis.SyntheticItems.GlobalSyntheticsStrategy;
 import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.Pair;
+import com.android.tools.r8.utils.Timing;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
 import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import java.io.IOException;
 import java.nio.file.Path;
 import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import org.hamcrest.CoreMatchers;
 import org.junit.Assume;
 import org.junit.Test;
@@ -39,6 +58,30 @@
 @RunWith(Parameterized.class)
 public class DesugaredLibraryContentTest extends DesugaredLibraryTestBase {
 
+  // The class sun.misc.Unsafe is runnable on Android despite not being in android.jar.
+  private static final Set<String> ALLOWED_MISSING_HOLDER = ImmutableSet.of("sun.misc.Unsafe");
+  private static final Set<String> ALLOWED_MISSING_METHOD =
+      ImmutableSet.of(
+          // The takeWhile/dropWhile methods are present in the wrappers but not yet present on
+          // android.jar
+          // leading to NoSuchMethod errors, yet, we keep them for subsequent android versions.
+          "java.util.stream.IntStream"
+              + " java.util.stream.IntStream.dropWhile(java.util.function.IntPredicate)",
+          "java.util.stream.Stream java.util.stream.Stream.takeWhile(java.util.function.Predicate)",
+          "java.util.stream.LongStream"
+              + " java.util.stream.LongStream.dropWhile(java.util.function.LongPredicate)",
+          "java.util.stream.DoubleStream"
+              + " java.util.stream.DoubleStream.takeWhile(java.util.function.DoublePredicate)",
+          "java.util.stream.IntStream"
+              + " java.util.stream.IntStream.takeWhile(java.util.function.IntPredicate)",
+          "java.util.stream.Stream java.util.stream.Stream.dropWhile(java.util.function.Predicate)",
+          "java.util.stream.LongStream"
+              + " java.util.stream.LongStream.takeWhile(java.util.function.LongPredicate)",
+          "java.util.stream.DoubleStream"
+              + " java.util.stream.DoubleStream.dropWhile(java.util.function.DoublePredicate)",
+          // FileStore.getBlockSize() was added in 33 which confuses the required library (30).
+          "long java.nio.file.FileStore.getBlockSize()");
+
   private final TestParameters parameters;
   private final CompilationSpecification compilationSpecification;
   private final LibraryDesugaringSpecification libraryDesugaringSpecification;
@@ -67,7 +110,63 @@
         .apply(libraryDesugaringSpecification::configureL8TestBuilder)
         .compile()
         .assertNoMessages()
-        .inspect(this::assertCorrect);
+        .inspect(this::assertCorrect)
+        .inspect(this::assertAllInvokeResolve);
+  }
+
+  private void assertAllInvokeResolve(CodeInspector inspector) throws IOException {
+    AndroidApp build =
+        AndroidApp.builder()
+            .addLibraryFiles(libraryDesugaringSpecification.getLibraryFiles())
+            .build();
+    DirectMappedDexApplication libHolder =
+        new ApplicationReader(build, inspector.getApplication().options, Timing.empty())
+            .read()
+            .toDirect();
+    DirectMappedDexApplication finalApp =
+        inspector
+            .getApplication()
+            .toDirect()
+            .builder()
+            .replaceLibraryClasses(libHolder.libraryClasses())
+            .build();
+    AppInfoWithClassHierarchy appInfo =
+        AppView.createForD8(
+                AppInfo.createInitialAppInfo(
+                    finalApp, GlobalSyntheticsStrategy.forNonSynthesizing()))
+            .appInfoForDesugaring();
+    Map<DexMethod, Object> failures = new IdentityHashMap<>();
+    for (FoundClassSubject clazz : inspector.allClasses()) {
+      for (FoundMethodSubject method : clazz.allMethods()) {
+        if (method.hasCode()) {
+          for (InstructionSubject instruction : method.instructions(InstructionSubject::isInvoke)) {
+            assertInvokeResolution(instruction, appInfo, method, failures);
+          }
+        }
+      }
+    }
+    for (DexMethod dexMethod : new HashSet<>(failures.keySet())) {
+      if (ALLOWED_MISSING_HOLDER.contains(dexMethod.getHolderType().toString())) {
+        failures.remove(dexMethod);
+      } else if (ALLOWED_MISSING_METHOD.contains(dexMethod.toString())) {
+        failures.remove(dexMethod);
+      }
+    }
+    assertTrue(failures.isEmpty());
+  }
+
+  private void assertInvokeResolution(
+      InstructionSubject instruction,
+      AppInfoWithClassHierarchy appInfo,
+      FoundMethodSubject context,
+      Map<DexMethod, Object> failures) {
+    DexMethod method = instruction.getMethod();
+    assert method != null;
+    MethodResolutionResult methodResolutionResult =
+        appInfo.unsafeResolveMethodDueToDexFormatLegacy(method);
+    if (methodResolutionResult.isFailedResolution()) {
+      failures.put(method, new Pair(context, methodResolutionResult));
+    }
   }
 
   @Test
@@ -110,7 +209,7 @@
                 assertThat(
                     clazz.getOriginalName(),
                     CoreMatchers.anyOf(startsWith("j$."), startsWith("java."))));
-    if (parameters.getApiLevel().getLevel() <= AndroidApiLevel.R.getLevel()) {
+    if (parameters.getApiLevel().getLevel() < AndroidApiLevel.O.getLevel()) {
       assertThat(inspector.clazz("j$.time.Clock"), isPresent());
     }
     // Above N the following classes are removed instead of being desugared.
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/JavaTimeJDK11Test.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/JavaTimeJDK11Test.java
index cf2079e..09bb322 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/JavaTimeJDK11Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/JavaTimeJDK11Test.java
@@ -6,13 +6,20 @@
 
 import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.DEFAULT_SPECIFICATIONS;
 import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11_PATH;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.TestParameters;
 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.LibraryDesugaringSpecification;
 import com.android.tools.r8.transformers.MethodTransformer;
+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.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import java.io.IOException;
@@ -36,6 +43,21 @@
 @RunWith(Parameterized.class)
 public class JavaTimeJDK11Test extends DesugaredLibraryTestBase {
 
+  private static AndroidApiLevel INTRODUCTION_LEVEL = AndroidApiLevel.S;
+  private static Set<String> DURATION_VIRTUAL_INVOKES =
+      ImmutableSet.of(
+          "toDaysPart",
+          "toHoursPart",
+          "toMillisPart",
+          "toMinutesPart",
+          "toNanosPart",
+          "toSeconds",
+          "toSecondsPart",
+          "dividedBy",
+          "truncatedTo");
+  private static Set<String> LOCAL_TIME_VIRTUAL_INVOKES = ImmutableSet.of("toEpochSecond");
+  private static Set<String> LOCAL_TIME_STATIC_INVOKES = ImmutableSet.of("ofInstant");
+
   private final TestParameters parameters;
   private final LibraryDesugaringSpecification libraryDesugaringSpecification;
   private final CompilationSpecification compilationSpecification;
@@ -47,7 +69,7 @@
   public static List<Object[]> data() {
     return buildParameters(
         getTestParameters().withDexRuntimes().withAllApiLevels().build(),
-        ImmutableList.of(JDK11),
+        ImmutableList.of(JDK11, JDK11_PATH),
         DEFAULT_SPECIFICATIONS);
   }
 
@@ -61,26 +83,48 @@
   }
 
   @Test
-  public void test() throws Exception {
+  public void test() throws Throwable {
     testForDesugaredLibrary(parameters, libraryDesugaringSpecification, compilationSpecification)
         .addProgramClassFileData(getProgramClassFileData())
         .addKeepMainRule(TestClass.class)
+        .compile()
+        .inspect(this::assertCalls)
         .run(parameters.getRuntime(), TestClass.class)
         .assertSuccessWithOutput(EXPECTED_RESULT);
   }
 
+  private void assertCalls(CodeInspector inspector) {
+    MethodSubject mainMethod = inspector.clazz(TestClass.class).mainMethod();
+    assertTrue(mainMethod.isPresent());
+    mainMethod
+        .streamInstructions()
+        .forEach(
+            i -> {
+              if (i.isInvoke()) {
+                if (libraryDesugaringSpecification.hasTimeDesugaring(parameters)) {
+                  checkInvokeTime(i, "j$.time.Duration", "j$.time.LocalTime");
+                  return;
+                }
+                if (parameters.getApiLevel().isLessThan(INTRODUCTION_LEVEL)) {
+                  checkInvokeTime(i, "j$.time.DesugarDuration", "j$.time.DesugarLocalTime");
+                  return;
+                }
+                checkInvokeTime(i, "java.time.Duration", "java.time.LocalTime");
+              }
+            });
+  }
+
+  private void checkInvokeTime(InstructionSubject i, String duration, String localTime) {
+    String name = i.getMethod().getName().toString();
+    if (DURATION_VIRTUAL_INVOKES.contains(name)) {
+      assertEquals(duration, i.getMethod().getHolderType().toString());
+    }
+    if (LOCAL_TIME_STATIC_INVOKES.contains(name) || LOCAL_TIME_VIRTUAL_INVOKES.contains(name)) {
+      assertEquals(localTime, i.getMethod().getHolderType().toString());
+    }
+  }
+
   private Collection<byte[]> getProgramClassFileData() throws IOException {
-    Set<String> methodsToRewriteToDurationVirtualInvoke =
-        ImmutableSet.of(
-            "toDaysPart",
-            "toHoursPart",
-            "toMillisPart",
-            "toMinutesPart",
-            "toNanosPart",
-            "toSeconds",
-            "toSecondsPart",
-            "dividedBy",
-            "truncatedTo");
     return ImmutableList.of(
         transformer(TestClass.class)
             .addMethodTransformer(
@@ -92,29 +136,30 @@
                       String name,
                       String descriptor,
                       boolean isInterface) {
-                    if (opcode == Opcodes.INVOKESTATIC
-                        && methodsToRewriteToDurationVirtualInvoke.contains(name)) {
-                      super.visitMethodInsn(
-                          Opcodes.INVOKEVIRTUAL,
-                          "java/time/Duration",
-                          name,
-                          withoutFirstObjectArg(descriptor),
-                          isInterface);
-                      return;
-                    }
-                    if (opcode == Opcodes.INVOKESTATIC && name.equals("ofInstant")) {
-                      super.visitMethodInsn(
-                          opcode, "java/time/LocalTime", name, descriptor, isInterface);
-                      return;
-                    }
-                    if (opcode == Opcodes.INVOKESTATIC && name.equals("toEpochSecond")) {
-                      super.visitMethodInsn(
-                          Opcodes.INVOKEVIRTUAL,
-                          "java/time/LocalTime",
-                          name,
-                          withoutFirstObjectArg(descriptor),
-                          isInterface);
-                      return;
+                    if (opcode == Opcodes.INVOKESTATIC) {
+                      if (DURATION_VIRTUAL_INVOKES.contains(name)) {
+                        super.visitMethodInsn(
+                            Opcodes.INVOKEVIRTUAL,
+                            "java/time/Duration",
+                            name,
+                            withoutFirstObjectArg(descriptor),
+                            isInterface);
+                        return;
+                      }
+                      if (LOCAL_TIME_VIRTUAL_INVOKES.contains(name)) {
+                        super.visitMethodInsn(
+                            Opcodes.INVOKEVIRTUAL,
+                            "java/time/LocalTime",
+                            name,
+                            withoutFirstObjectArg(descriptor),
+                            isInterface);
+                        return;
+                      }
+                      if (LOCAL_TIME_STATIC_INVOKES.contains(name)) {
+                        super.visitMethodInsn(
+                            opcode, "java/time/LocalTime", name, descriptor, isInterface);
+                        return;
+                      }
                     }
                     super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
                   }
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/NewCollectorsTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/NewCollectorsTest.java
new file mode 100644
index 0000000..4c77e47
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/NewCollectorsTest.java
@@ -0,0 +1,102 @@
+// 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.DEFAULT_SPECIFICATIONS;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11_PATH;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+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.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.MethodSubject;
+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 NewCollectorsTest extends DesugaredLibraryTestBase {
+
+  private static final AndroidApiLevel NEW_COLLECTORS_LEVEL = AndroidApiLevel.T;
+
+  private final TestParameters parameters;
+  private final LibraryDesugaringSpecification libraryDesugaringSpecification;
+  private final CompilationSpecification compilationSpecification;
+
+  private static final Path INPUT_JAR =
+      Paths.get(ToolHelper.EXAMPLES_JAVA10_BUILD_DIR + "collectors.jar");
+  private static final String EXPECTED_OUTPUT = StringUtils.lines("1", "1", "1", "1", "1", "1");
+  private static final String MAIN_CLASS = "collectors.Main";
+
+  @Parameters(name = "{0}, spec: {1}, {2}")
+  public static List<Object[]> data() {
+    return buildParameters(
+        getTestParameters().withDexRuntimes().withAllApiLevels().build(),
+        ImmutableList.of(JDK11, JDK11_PATH),
+        DEFAULT_SPECIFICATIONS);
+  }
+
+  public NewCollectorsTest(
+      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)
+        .compile()
+        .inspect(this::assertCollectors)
+        .run(parameters.getRuntime(), MAIN_CLASS)
+        .assertSuccessWithOutput(EXPECTED_OUTPUT);
+  }
+
+  private void assertCollectors(CodeInspector inspector) {
+    MethodSubject methodSubject = inspector.clazz(MAIN_CLASS).mainMethod();
+    assertTrue(methodSubject.isPresent());
+    if (libraryDesugaringSpecification.hasEmulatedInterfaceDesugaring(parameters)) {
+      // Collectors is not present, all calls to the j$ version.
+      assertTrue(anyStaticInvokeToHolder(methodSubject, "j$.util.stream.Collectors"));
+      assertFalse(anyStaticInvokeToHolder(methodSubject, "j$.util.stream.DesugarCollectors"));
+      assertFalse(anyStaticInvokeToHolder(methodSubject, "java.util.stream.Collectors"));
+      return;
+    }
+    if (parameters.getApiLevel().isLessThan(NEW_COLLECTORS_LEVEL)) {
+      // Collectors is present, but partially, calls to java Collectors and DesugarCollectors.
+      assertFalse(anyStaticInvokeToHolder(methodSubject, "j$.util.stream.Collectors"));
+      assertTrue(anyStaticInvokeToHolder(methodSubject, "j$.util.stream.DesugarCollectors"));
+      assertTrue(anyStaticInvokeToHolder(methodSubject, "java.util.stream.Collectors"));
+      return;
+    }
+    // Collectors is fully present, all calls to java Collectors.
+    assertFalse(anyStaticInvokeToHolder(methodSubject, "j$.util.stream.Collectors"));
+    assertFalse(anyStaticInvokeToHolder(methodSubject, "j$.util.stream.DesugarCollectors"));
+    assertTrue(anyStaticInvokeToHolder(methodSubject, "java.util.stream.Collectors"));
+  }
+
+  private boolean anyStaticInvokeToHolder(MethodSubject methodSubject, String holder) {
+    return methodSubject
+        .streamInstructions()
+        .anyMatch(
+            i -> i.isInvokeStatic() && i.getMethod().getHolderType().toString().equals(holder));
+  }
+}
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 9ccafc8..8085bf6 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
@@ -34,12 +34,13 @@
 public class LibraryDesugaringSpecification {
 
   public static Descriptor JDK8_DESCRIPTOR = new Descriptor(24, 26, -1, 26, 24);
-  public static Descriptor JDK11_DESCRIPTOR = new Descriptor(24, 30, -1, 32, -1);
+  public static Descriptor JDK11_DESCRIPTOR = new Descriptor(24, 26, -1, 32, -1);
   public static Descriptor EMPTY_DESCRIPTOR_24 = new Descriptor(-1, -1, -1, 24, -1);
-  public static Descriptor JDK11_PATH_DESCRIPTOR = new Descriptor(24, 30, 26, 32, -1);
-  public static Descriptor JDK11_LEGACY_DESCRIPTOR = new Descriptor(24, 10000, -1, 10000, 24);
+  public static Descriptor JDK11_PATH_DESCRIPTOR = new Descriptor(24, 26, 26, 32, -1);
+  public static Descriptor JDK11_LEGACY_DESCRIPTOR = new Descriptor(10000, 10000, -1, 10000, 24);
 
   private static class Descriptor {
+
     // Above this level emulated interface are not *entirely* desugared.
     private final int emulatedInterfaceDesugaring;
     // Above this level java.time is not *entirely* desugared.
diff --git a/src/test/java/com/android/tools/r8/dex/container/DexContainerFormatBasicTest.java b/src/test/java/com/android/tools/r8/dex/container/DexContainerFormatBasicTest.java
index af1ee96..6f68f53 100644
--- a/src/test/java/com/android/tools/r8/dex/container/DexContainerFormatBasicTest.java
+++ b/src/test/java/com/android/tools/r8/dex/container/DexContainerFormatBasicTest.java
@@ -3,6 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.dex.container;
 
+import static com.android.tools.r8.dex.Constants.DATA_OFF_OFFSET;
+import static com.android.tools.r8.dex.Constants.DATA_SIZE_OFFSET;
+import static com.android.tools.r8.dex.Constants.MAP_OFF_OFFSET;
+import static com.android.tools.r8.dex.Constants.STRING_IDS_OFF_OFFSET;
+import static com.android.tools.r8.dex.Constants.STRING_IDS_SIZE_OFFSET;
+import static com.android.tools.r8.dex.Constants.TYPE_STRING_ID_ITEM;
 import static org.junit.Assert.assertEquals;
 
 import com.android.tools.r8.ByteDataView;
@@ -10,6 +16,9 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.dex.CompatByteBuffer;
+import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.maindexlist.MainDexListTests;
 import com.android.tools.r8.transformers.ClassTransformer;
 import com.android.tools.r8.utils.AndroidApiLevel;
@@ -17,7 +26,10 @@
 import com.android.tools.r8.utils.ZipUtils;
 import com.google.common.collect.ImmutableList;
 import com.google.common.io.ByteStreams;
+import it.unimi.dsi.fastutil.ints.IntArrayList;
+import it.unimi.dsi.fastutil.ints.IntList;
 import java.io.IOException;
+import java.nio.ByteOrder;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
@@ -91,8 +103,7 @@
                 options -> options.getTestingOptions().dexContainerExperiment = true)
             .compile()
             .writeToZip();
-    List<byte[]> dexFromDexing = unzipContent(outputFromDexing);
-    assertEquals(1, dexFromDexing.size());
+    validateSingleContainerDex(outputFromDexing);
   }
 
   @Test
@@ -105,7 +116,7 @@
                 options -> options.getTestingOptions().dexContainerExperiment = true)
             .compile()
             .writeToZip();
-    assertEquals(1, unzipContent(outputA).size());
+    validateSingleContainerDex(outputA);
 
     Path outputB =
         testForD8(Backend.DEX)
@@ -115,7 +126,84 @@
                 options -> options.getTestingOptions().dexContainerExperiment = true)
             .compile()
             .writeToZip();
-    assertEquals(1, unzipContent(outputB).size());
+    validateSingleContainerDex(outputB);
+  }
+
+  private void validateSingleContainerDex(Path output) throws IOException {
+    List<byte[]> dexes = unzipContent(output);
+    assertEquals(1, dexes.size());
+    validateStringIdsSizeAndOffsets(dexes.get(0));
+  }
+
+  private void validateStringIdsSizeAndOffsets(byte[] dex) {
+    CompatByteBuffer buffer = CompatByteBuffer.wrap(dex);
+    setByteOrder(buffer);
+
+    IntList sections = new IntArrayList();
+    int offset = 0;
+    while (offset < buffer.capacity()) {
+      sections.add(offset);
+      int dataSize = buffer.getInt(offset + DATA_SIZE_OFFSET);
+      int dataOffset = buffer.getInt(offset + DATA_OFF_OFFSET);
+      offset = dataOffset + dataSize;
+    }
+    assertEquals(buffer.capacity(), offset);
+
+    int lastOffset = sections.getInt(sections.size() - 1);
+    int stringIdsSize = buffer.getInt(lastOffset + STRING_IDS_SIZE_OFFSET);
+    int stringIdsOffset = buffer.getInt(lastOffset + STRING_IDS_OFF_OFFSET);
+
+    for (Integer sectionOffset : sections) {
+      assertEquals(stringIdsSize, buffer.getInt(sectionOffset + STRING_IDS_SIZE_OFFSET));
+      assertEquals(stringIdsOffset, buffer.getInt(sectionOffset + STRING_IDS_OFF_OFFSET));
+      assertEquals(stringIdsSize, getSizeFromMap(TYPE_STRING_ID_ITEM, buffer, sectionOffset));
+      assertEquals(stringIdsOffset, getOffsetFromMap(TYPE_STRING_ID_ITEM, buffer, sectionOffset));
+    }
+  }
+
+  private int getSizeFromMap(int type, CompatByteBuffer buffer, int offset) {
+    int mapOffset = buffer.getInt(offset + MAP_OFF_OFFSET);
+    buffer.position(mapOffset);
+    int mapSize = buffer.getInt();
+    for (int i = 0; i < mapSize; i++) {
+      int sectionType = buffer.getShort();
+      buffer.getShort(); // Skip unused.
+      int sectionSize = buffer.getInt();
+      buffer.getInt(); // Skip offset.
+      if (type == sectionType) {
+        return sectionSize;
+      }
+    }
+    throw new RuntimeException("Not found");
+  }
+
+  private int getOffsetFromMap(int type, CompatByteBuffer buffer, int offset) {
+    int mapOffset = buffer.getInt(offset + MAP_OFF_OFFSET);
+    buffer.position(mapOffset);
+    int mapSize = buffer.getInt();
+    for (int i = 0; i < mapSize; i++) {
+      int sectionType = buffer.getShort();
+      buffer.getShort(); // Skip unused.
+      buffer.getInt(); // SKip size.
+      int sectionOffset = buffer.getInt();
+      if (type == sectionType) {
+        return sectionOffset;
+      }
+    }
+    throw new RuntimeException("Not found");
+  }
+
+  private void setByteOrder(CompatByteBuffer buffer) {
+    // Make sure we set the right endian for reading.
+    buffer.order(ByteOrder.LITTLE_ENDIAN);
+    int endian = buffer.getInt(Constants.ENDIAN_TAG_OFFSET);
+    if (endian == Constants.REVERSE_ENDIAN_CONSTANT) {
+      buffer.order(ByteOrder.BIG_ENDIAN);
+    } else {
+      if (endian != Constants.ENDIAN_CONSTANT) {
+        throw new CompilationError("Unable to determine endianess for reading dex file.");
+      }
+    }
   }
 
   private List<byte[]> unzipContent(Path zip) throws IOException {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/InstanceGetOnCheckCastCompareLongTest.java b/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/InstanceGetOnCheckCastCompareLongTest.java
index c2721f1..f94bba3 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/InstanceGetOnCheckCastCompareLongTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/InstanceGetOnCheckCastCompareLongTest.java
@@ -4,16 +4,10 @@
 
 package com.android.tools.r8.ir.optimize.canonicalization;
 
-import static org.hamcrest.CoreMatchers.containsString;
-import static org.junit.Assert.assertThrows;
-
-import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.NeverInline;
-import com.android.tools.r8.R8FullTestBuilder;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.utils.AndroidApiLevel;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -49,29 +43,15 @@
     // For R8 we will try to shorten the live range and we have a bailout to find an insertion
     // point if we see a cmp instruction and the api is lower than 23. The receiver of the instance
     // get is not defined on the insertion point which is why this regression test was made.
-    R8FullTestBuilder r8FullTestBuilder =
-        testForR8(parameters.getBackend())
-            .addProgramClasses(I.class, Main.class)
-            .addProgramClassFileData(getTestClassWithRewrittenLongCompareToLCmp())
-            .addKeepMainRule(Main.class)
-            .addKeepClassRules(I.class)
-            .setMinApi(parameters.getApiLevel())
-            .enableInliningAnnotations();
-    if (parameters.getApiLevel().isLessThan(AndroidApiLevel.M)) {
-      // TODO(b/251015885). We should not fail compilation.
-      assertThrows(
-          CompilationFailedException.class,
-          () ->
-              r8FullTestBuilder.compileWithExpectedDiagnostics(
-                  diagnostics ->
-                      diagnostics.assertErrorMessageThatMatches(
-                          containsString("Unexpected values live at entry to first block"))));
-
-    } else {
-      r8FullTestBuilder
-          .run(parameters.getRuntime(), Main.class)
-          .assertSuccessWithOutputLines(EXPECTED);
-    }
+    testForR8(parameters.getBackend())
+        .addProgramClasses(I.class, Main.class)
+        .addProgramClassFileData(getTestClassWithRewrittenLongCompareToLCmp())
+        .addKeepMainRule(Main.class)
+        .addKeepClassRules(I.class)
+        .setMinApi(parameters.getApiLevel())
+        .enableInliningAnnotations()
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(EXPECTED);
   }
 
   private byte[] getTestClassWithRewrittenLongCompareToLCmp() throws Exception {
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageKeepClassMembersTest.java b/src/test/java/com/android/tools/r8/repackage/RepackageKeepClassMembersTest.java
index a49759f..57f650e 100644
--- a/src/test/java/com/android/tools/r8/repackage/RepackageKeepClassMembersTest.java
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageKeepClassMembersTest.java
@@ -6,15 +6,15 @@
 
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed;
-import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.NeverClassInline;
-import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.ProguardVersion;
 import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.repackage.testclasses.RepackageForKeepClassMembers;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import java.util.Objects;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -22,64 +22,57 @@
 @RunWith(Parameterized.class)
 public class RepackageKeepClassMembersTest extends RepackageTestBase {
 
+  private final String EXPECTED = "Could not find " + typeName(RepackageForKeepClassMembers.class);
+
   public RepackageKeepClassMembersTest(
       String flattenPackageHierarchyOrRepackageClasses, TestParameters parameters) {
     super(flattenPackageHierarchyOrRepackageClasses, parameters);
   }
 
   @Test
-  public void testR8() throws Exception {
-    testForR8(parameters.getBackend())
-        .addInnerClasses(getClass())
+  public void testPG() throws Exception {
+    assumeTrue(parameters.isOrSimulateNoneRuntime());
+    testForProguard(ProguardVersion.V7_0_0)
+        .addProgramClasses(RepackageForKeepClassMembers.class, Main.class)
         .setMinApi(parameters.getApiLevel())
         .apply(this::configureRepackaging)
         .addKeepRules(
-            "-keepclassmembers class * extends " + typeName(Base.class) + " { <fields>; }")
+            "-keepclassmembers class " + typeName(RepackageForKeepClassMembers.class) + " { *; }")
+        .addKeepMainRule(Main.class)
+        .addDontWarn(RepackageKeepClassMembersTest.class, NeverClassInline.class)
+        .run(parameters.getRuntime(), Main.class, typeName(RepackageForKeepClassMembers.class))
+        .inspect(this::inspect)
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(RepackageForKeepClassMembers.class, Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .apply(this::configureRepackaging)
+        .addKeepRules(
+            "-keepclassmembers class " + typeName(RepackageForKeepClassMembers.class) + " { *; }")
         .addKeepMainRule(Main.class)
         .enableNeverClassInliningAnnotations()
-        .enableInliningAnnotations()
-        .run(parameters.getRuntime(), Main.class, typeName(Sub.class))
+        .run(parameters.getRuntime(), Main.class, typeName(RepackageForKeepClassMembers.class))
         .inspect(this::inspect)
-        // TODOD(b/250671873): Should not repackage class.
-        .assertSuccessWithOutputLines("Could not find " + typeName(Sub.class));
+        .assertSuccessWithOutputLines(EXPECTED);
   }
 
   private void inspect(CodeInspector inspector) {
-    ClassSubject clazz = inspector.clazz(Sub.class);
+    ClassSubject clazz = inspector.clazz(RepackageForKeepClassMembers.class);
     assertThat(clazz, isPresent());
-    // TODOD(b/250671873): Should not repackage class.
-    assertThat(Sub.class, isRepackaged(inspector));
+    assertThat(RepackageForKeepClassMembers.class, isRepackaged(inspector));
     assertThat(clazz.uniqueFieldWithOriginalName("hashCodeCache"), isPresentAndNotRenamed());
-    assertThat(clazz.uniqueMethodWithOriginalName("calculateHashCode"), isPresentAndRenamed());
-  }
-
-  public static class Base {}
-
-  @NeverClassInline
-  public static class Sub extends Base {
-
-    public int hashCodeCache;
-
-    @NeverInline
-    public int calculateHashCode() {
-      if (hashCodeCache != -1) {
-        return hashCodeCache;
-      }
-      hashCodeCache = Objects.hash(Sub.class);
-      return hashCodeCache;
-    }
-
-    @Override
-    public int hashCode() {
-      return calculateHashCode();
-    }
+    assertThat(clazz.uniqueMethodWithOriginalName("calculateHashCode"), isPresentAndNotRenamed());
   }
 
   public static class Main {
 
     public static void main(String[] args) {
       if (System.currentTimeMillis() == 0) {
-        System.out.println(new Sub().hashCode());
+        System.out.println(new RepackageForKeepClassMembers().hashCode());
       }
       try {
         Class<?> subClass = Class.forName(args[0]);
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageProtectedInSamePackageTest.java b/src/test/java/com/android/tools/r8/repackage/RepackageProtectedInSamePackageTest.java
index a208857..a6c9ea3 100644
--- a/src/test/java/com/android/tools/r8/repackage/RepackageProtectedInSamePackageTest.java
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageProtectedInSamePackageTest.java
@@ -5,15 +5,18 @@
 package com.android.tools.r8.repackage;
 
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.NeverClassInline;
-import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.ProguardVersion;
 import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.repackage.testclasses.RepackageForKeepClassMembers;
+import com.android.tools.r8.transformers.ClassFileTransformer.FieldPredicate;
+import com.android.tools.r8.transformers.ClassFileTransformer.MethodPredicate;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import java.util.Objects;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -22,66 +25,82 @@
 @RunWith(Parameterized.class)
 public class RepackageProtectedInSamePackageTest extends RepackageTestBase {
 
+  private final String EXPECTED = "Hello World!";
+
   public RepackageProtectedInSamePackageTest(
       String flattenPackageHierarchyOrRepackageClasses, TestParameters parameters) {
     super(flattenPackageHierarchyOrRepackageClasses, parameters);
   }
 
   @Test
-  public void testR8() throws Exception {
-    testForR8(parameters.getBackend())
-        .addInnerClasses(getClass())
+  public void testPG() throws Exception {
+    assumeTrue(parameters.isOrSimulateNoneRuntime());
+    testForProguard(ProguardVersion.V7_0_0)
+        .addProgramClasses(Main.class)
+        .addProgramClassFileData(getRepackageForKeepClassMembersWithProtectedAccess())
         .setMinApi(parameters.getApiLevel())
         .apply(this::configureRepackaging)
         .addKeepRules(
-            "-keepclassmembers,allowobfuscation class * extends "
-                + typeName(Base.class)
-                + " { <fields>; }")
+            "-keepclassmembers class " + typeName(RepackageForKeepClassMembers.class) + " { *; }")
+        .addKeepMainRule(Main.class)
+        .addDontWarn(RepackageProtectedInSamePackageTest.class, NeverClassInline.class)
+        .run(parameters.getRuntime(), Main.class, typeName(RepackageForKeepClassMembers.class))
+        .inspect(inspector -> inspect(inspector, true))
+        .assertSuccessWithOutputLines(EXPECTED);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class)
+        .addProgramClassFileData(getRepackageForKeepClassMembersWithProtectedAccess())
+        .setMinApi(parameters.getApiLevel())
+        .apply(this::configureRepackaging)
+        .addKeepRules(
+            "-keepclassmembers class " + typeName(RepackageForKeepClassMembers.class) + " { *; }")
         .addKeepMainRule(Main.class)
         .enableNeverClassInliningAnnotations()
-        .enableInliningAnnotations()
         .run(parameters.getRuntime(), Main.class)
-        .inspect(this::inspect)
-        .assertSuccessWithOutputLines("Hello World!");
+        .inspect(inspector -> inspect(inspector, false))
+        .assertSuccessWithOutputLines(EXPECTED);
   }
 
-  private void inspect(CodeInspector inspector) {
+  private byte[] getRepackageForKeepClassMembersWithProtectedAccess() throws Exception {
+    return transformer(RepackageForKeepClassMembers.class)
+        .setAccessFlags(
+            MethodPredicate.onName("calculateHashCode"),
+            methodAccessFlags -> {
+              methodAccessFlags.unsetPublic();
+              methodAccessFlags.setProtected();
+            })
+        .setAccessFlags(
+            FieldPredicate.onName("hashCodeCache"),
+            fieldAccessFlags -> {
+              fieldAccessFlags.unsetPublic();
+              fieldAccessFlags.setProtected();
+            })
+        .transform();
+  }
+
+  private void inspect(CodeInspector inspector, boolean isProguard) {
+    ClassSubject clazz = inspector.clazz(RepackageForKeepClassMembers.class);
+    assertThat(clazz, isPresent());
     // TODO(b/250671873): We should be able to repackage the Sub class since the only reference
     //  to Sub.class is in the same package and we have allowobfuscation.
-    ClassSubject clazz = inspector.clazz(Sub.class);
-    assertThat(clazz, isPresent());
-    assertThat(Sub.class, isNotRepackaged(inspector));
-    assertThat(clazz.uniqueFieldWithOriginalName("hashCodeCache"), isPresentAndRenamed());
-    assertThat(clazz.uniqueMethodWithOriginalName("calculateHashCode"), isPresentAndRenamed());
-  }
-
-  public static class Base {}
-
-  @NeverClassInline
-  public static class Sub extends Base {
-
-    protected int hashCodeCache;
-
-    @NeverInline
-    protected int calculateHashCode() {
-      if (hashCodeCache != -1) {
-        return hashCodeCache;
-      }
-      hashCodeCache = Objects.hash(Sub.class);
-      return hashCodeCache;
+    if (isProguard) {
+      assertThat(RepackageForKeepClassMembers.class, isRepackaged(inspector));
+    } else {
+      assertThat(RepackageForKeepClassMembers.class, isNotRepackaged(inspector));
     }
-
-    @Override
-    public int hashCode() {
-      return calculateHashCode();
-    }
+    assertThat(clazz.uniqueFieldWithOriginalName("hashCodeCache"), isPresentAndNotRenamed());
+    assertThat(clazz.uniqueMethodWithOriginalName("calculateHashCode"), isPresentAndNotRenamed());
   }
 
   public static class Main {
 
     public static void main(String[] args) {
       if (System.currentTimeMillis() == 0) {
-        System.out.println(new Sub().hashCode());
+        System.out.println(new RepackageForKeepClassMembers().hashCode());
       }
       System.out.println("Hello World!");
     }
diff --git a/src/test/java/com/android/tools/r8/repackage/testclasses/RepackageForKeepClassMembers.java b/src/test/java/com/android/tools/r8/repackage/testclasses/RepackageForKeepClassMembers.java
new file mode 100644
index 0000000..48781e5
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/repackage/testclasses/RepackageForKeepClassMembers.java
@@ -0,0 +1,27 @@
+// 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.repackage.testclasses;
+
+import com.android.tools.r8.NeverClassInline;
+import java.util.Objects;
+
+@NeverClassInline
+public class RepackageForKeepClassMembers {
+
+  public int hashCodeCache;
+
+  public int calculateHashCode() {
+    if (hashCodeCache != -1) {
+      return hashCodeCache;
+    }
+    hashCodeCache = Objects.hash(RepackageForKeepClassMembers.class);
+    return hashCodeCache;
+  }
+
+  @Override
+  public int hashCode() {
+    return calculateHashCode();
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceNoProguardMapTest.java b/src/test/java/com/android/tools/r8/retrace/RetraceNoProguardMapTest.java
new file mode 100644
index 0000000..2deccf8
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceNoProguardMapTest.java
@@ -0,0 +1,45 @@
+// 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.retrace;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.references.MethodReference;
+import com.android.tools.r8.references.Reference;
+import java.util.Collections;
+import java.util.Optional;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class RetraceNoProguardMapTest extends TestBase {
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withNoneRuntime().build();
+  }
+
+  @Test
+  public void testNoLine() {
+    Retracer retracer =
+        Retracer.createDefault(ProguardMapProducer.fromString(""), new DiagnosticsHandler() {});
+    MethodReference methodReference =
+        Reference.method(Reference.classFromTypeName("a"), "foo", Collections.emptyList(), null);
+    Optional<RetraceMethodElement> first =
+        retracer.retraceMethod(methodReference).stream().findFirst();
+    assertTrue(first.isPresent());
+    assertEquals(methodReference, first.get().getRetracedMethod().asKnown().getMethodReference());
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java b/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
index 9dc6120..47c49fc 100644
--- a/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
+++ b/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
@@ -550,6 +550,14 @@
 
   private ClassFileTransformer setAccessFlags(
       FieldReference fieldReference, Consumer<FieldAccessFlags> setter) {
+    return setAccessFlags(
+        FieldPredicate.onNameAndDescriptor(
+            fieldReference.getFieldName(), fieldReference.getFieldType().getDescriptor()),
+        setter);
+  }
+
+  public ClassFileTransformer setAccessFlags(
+      FieldPredicate predicate, Consumer<FieldAccessFlags> setter) {
     return addClassTransformer(
         new ClassTransformer() {
 
@@ -557,8 +565,7 @@
           public FieldVisitor visitField(
               int access, String name, String descriptor, String signature, Object value) {
             FieldAccessFlags accessFlags = FieldAccessFlags.fromCfAccessFlags(access);
-            if (name.equals(fieldReference.getFieldName())
-                && descriptor.equals(fieldReference.getFieldType().getDescriptor())) {
+            if (predicate.test(access, name, descriptor, signature, value)) {
               setter.accept(accessFlags);
             }
             return super.visitField(
@@ -631,7 +638,7 @@
       return (access, name, descriptor, signature, value) -> true;
     }
 
-    static FieldPredicate onNameAndSignature(String name, String descriptor) {
+    static FieldPredicate onNameAndDescriptor(String name, String descriptor) {
       return (access, otherName, otherDescriptor, signature, value) ->
           name.equals(otherName) && descriptor.equals(otherDescriptor);
     }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
index aeb419e..b569a57 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
@@ -178,6 +178,10 @@
     }
   }
 
+  public DexApplication getApplication() {
+    return application;
+  }
+
   public DexItemFactory getFactory() {
     return dexItemFactory;
   }
diff --git a/third_party/openjdk/desugar_jdk_libs_11.tar.gz.sha1 b/third_party/openjdk/desugar_jdk_libs_11.tar.gz.sha1
index 6bb56ca..6a3c83d 100644
--- a/third_party/openjdk/desugar_jdk_libs_11.tar.gz.sha1
+++ b/third_party/openjdk/desugar_jdk_libs_11.tar.gz.sha1
@@ -1 +1 @@
-ed1a6a57d899d32cc749160872cad5c2130566b7
\ No newline at end of file
+9f148123a86ba0f40e58a71f9ad59c723ecb4607
\ No newline at end of file