Introduce desugared library amender

Bug: 184026720
Change-Id: I2dd577b9f3ab20b803332c7a365847a18b4fb07e
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index 8bb087e..851b677 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -24,6 +24,7 @@
 import com.android.tools.r8.inspector.internal.InspectorImpl;
 import com.android.tools.r8.ir.conversion.IRConverter;
 import com.android.tools.r8.ir.desugar.TypeRewriter;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibraryAmender;
 import com.android.tools.r8.ir.optimize.AssertionsRewriter;
 import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
 import com.android.tools.r8.jar.CfApplicationWriter;
@@ -195,6 +196,7 @@
       assert forTesting(options, () -> !options.testing.testEnableTestAssertions);
 
       AppView<AppInfo> appView = readApp(inputApp, options, executor, timing);
+      DesugaredLibraryAmender.run(appView);
       SyntheticItems.collectSyntheticInputs(appView);
 
       final CfgPrinter printer = options.printCfg ? new CfgPrinter() : null;
diff --git a/src/main/java/com/android/tools/r8/L8.java b/src/main/java/com/android/tools/r8/L8.java
index 7c0a805..0c8f9ea 100644
--- a/src/main/java/com/android/tools/r8/L8.java
+++ b/src/main/java/com/android/tools/r8/L8.java
@@ -14,6 +14,7 @@
 import com.android.tools.r8.graph.LazyLoadedDexApplication;
 import com.android.tools.r8.ir.conversion.IRConverter;
 import com.android.tools.r8.ir.desugar.TypeRewriter;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibraryAmender;
 import com.android.tools.r8.jar.CfApplicationWriter;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.naming.PrefixRewritingNamingLens;
@@ -134,6 +135,7 @@
       options.enableLoadStoreOptimization = false;
 
       AppView<AppInfo> appView = readApp(inputApp, options, executor, timing);
+      DesugaredLibraryAmender.run(appView);
 
       if (!options.disableL8AnnotationRemoval) {
         AnnotationRemover.clearAnnotations(appView);
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 8b93d23..ac01496 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -49,6 +49,7 @@
 import com.android.tools.r8.ir.desugar.BackportedMethodRewriter;
 import com.android.tools.r8.ir.desugar.CfClassSynthesizerDesugaringCollection;
 import com.android.tools.r8.ir.desugar.CfClassSynthesizerDesugaringEventConsumer;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibraryAmender;
 import com.android.tools.r8.ir.desugar.itf.InterfaceMethodRewriter;
 import com.android.tools.r8.ir.desugar.records.RecordDesugaring;
 import com.android.tools.r8.ir.desugar.records.RecordFieldValuesRewriter;
@@ -310,6 +311,7 @@
       if (!options.mainDexKeepRules.isEmpty()) {
         MainDexListBuilder.checkForAssumedLibraryTypes(appView.appInfo());
       }
+      DesugaredLibraryAmender.run(appView);
       InterfaceMethodRewriter.checkForAssumedLibraryTypes(appView.appInfo(), options);
       BackportedMethodRewriter.registerAssumedLibraryTypes(options);
       if (options.enableEnumUnboxing) {
diff --git a/src/main/java/com/android/tools/r8/graph/AccessFlags.java b/src/main/java/com/android/tools/r8/graph/AccessFlags.java
index cdf0ad1..1e6fb22 100644
--- a/src/main/java/com/android/tools/r8/graph/AccessFlags.java
+++ b/src/main/java/com/android/tools/r8/graph/AccessFlags.java
@@ -82,6 +82,18 @@
     return originalFlags;
   }
 
+  public ClassAccessFlags asClassAccessFlags() {
+    return null;
+  }
+
+  public MethodAccessFlags asMethodAccessFlags() {
+    return null;
+  }
+
+  public FieldAccessFlags asFieldAccessFlags() {
+    return null;
+  }
+
   @Override
   public boolean equals(Object object) {
     if (object instanceof AccessFlags) {
diff --git a/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java b/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java
index 19f0fdf..45d4be7 100644
--- a/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java
+++ b/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java
@@ -107,6 +107,11 @@
     return flags;
   }
 
+  @Override
+  public ClassAccessFlags asClassAccessFlags() {
+    return this;
+  }
+
   /**
    * Checks whether the constraints from
    * https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.1 are met.
diff --git a/src/main/java/com/android/tools/r8/graph/FieldAccessFlags.java b/src/main/java/com/android/tools/r8/graph/FieldAccessFlags.java
index 95b2a6f..cc2e10c 100644
--- a/src/main/java/com/android/tools/r8/graph/FieldAccessFlags.java
+++ b/src/main/java/com/android/tools/r8/graph/FieldAccessFlags.java
@@ -99,6 +99,11 @@
   }
 
   @Override
+  public FieldAccessFlags asFieldAccessFlags() {
+    return this;
+  }
+
+  @Override
   public int getAsCfAccessFlags() {
     return materialize();
   }
@@ -138,6 +143,11 @@
       super(FieldAccessFlags.fromSharedAccessFlags(0));
     }
 
+    public Builder set(int flag) {
+      flags.set(flag);
+      return this;
+    }
+
     @Override
     public Builder self() {
       return this;
diff --git a/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java b/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java
index cd5e8de..a20ab1d 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java
@@ -119,6 +119,11 @@
     return copy.materialize();
   }
 
+  @Override
+  public MethodAccessFlags asMethodAccessFlags() {
+    return this;
+  }
+
   public boolean isSynchronized() {
     return isSet(Constants.ACC_SYNCHRONIZED);
   }
@@ -249,6 +254,11 @@
       super(MethodAccessFlags.fromSharedAccessFlags(0, false));
     }
 
+    public Builder set(int flag) {
+      flags.set(flag);
+      return this;
+    }
+
     public Builder setBridge() {
       flags.setBridge();
       return this;
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
new file mode 100644
index 0000000..bd146e9
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryAmender.java
@@ -0,0 +1,68 @@
+// 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.ir.desugar.desugaredlibrary;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.MethodAccessFlags;
+import java.util.Map;
+
+/**
+ * The LibraryAmender is responsible in amending the library so that desugared library can be
+ * applied. For example, it can insert missing methods which are not present in the library but are
+ * supported in desugared library.
+ */
+public class DesugaredLibraryAmender {
+
+  private final AppView<?> appView;
+
+  public static void run(AppView<?> appView) {
+    run(appView, appView.options().machineDesugaredLibrarySpecification.getAmendLibraryMethods());
+  }
+
+  public static void run(AppView<?> appView, Map<DexMethod, MethodAccessFlags> amendLibrary) {
+    if (amendLibrary.isEmpty()) {
+      return;
+    }
+    new DesugaredLibraryAmender(appView).run(amendLibrary);
+  }
+
+  private DesugaredLibraryAmender(AppView<?> appView) {
+    this.appView = appView;
+  }
+
+  private void run(Map<DexMethod, MethodAccessFlags> amendLibrary) {
+    amendLibrary.forEach(this::amendLibraryMethod);
+  }
+
+  private void amendLibraryMethod(DexMethod method, MethodAccessFlags methodAccessFlags) {
+    DexClass dexClass = appView.contextIndependentDefinitionFor(method.getHolderType());
+    if (dexClass == null || !dexClass.isLibraryClass()) {
+      // Consider just throwing an error.
+      appView
+          .options()
+          .reporter
+          .warning(
+              "Desugared library: Cannot amend library method "
+                  + method
+                  + " because the holder is not a library class"
+                  + (dexClass == null ? "(null)." : "."));
+      return;
+    }
+    if (dexClass.lookupMethod(method) != null) {
+      return;
+    }
+    DexEncodedMethod encodedMethod =
+        DexEncodedMethod.syntheticBuilder()
+            .setMethod(method)
+            .setAccessFlags(methodAccessFlags)
+            .setCode(null)
+            .setApiLevelForDefinition(appView.computedMinApiLevel())
+            .build();
+    dexClass.getMethodCollection().addMethod(encodedMethod);
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/AbstractMethodParser.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/AbstractMethodParser.java
new file mode 100644
index 0000000..d63efb6
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/AbstractMethodParser.java
@@ -0,0 +1,81 @@
+// 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.ir.desugar.desugaredlibrary.humanspecification;
+
+import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.utils.DescriptorUtils;
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+
+/** Parse methods of the form: modifiers* returnType holder#name(arg0, ..., argN) */
+public abstract class AbstractMethodParser {
+
+  private static final String SEPARATORS = "\\s+|,\\s+|#|\\(|\\)";
+
+  private static final Map<String, Integer> modifiers =
+      ImmutableMap.<String, Integer>builder()
+          .put("public", Constants.ACC_PUBLIC)
+          .put("private", Constants.ACC_PRIVATE)
+          .put("protected", Constants.ACC_PROTECTED)
+          .put("final", Constants.ACC_FINAL)
+          .put("abstract", Constants.ACC_ABSTRACT)
+          .put("static", Constants.ACC_STATIC)
+          .build();
+
+  final DexItemFactory factory;
+
+  protected AbstractMethodParser(DexItemFactory factory) {
+    this.factory = factory;
+  }
+
+  // TODO(b/218755060): It would be nice to avoid the split regexp and use a nextToken()
+  //  method instead, then add a TraversalContinuation.
+  public void parseMethod(String signature) {
+    String[] tokens = signature.split(SEPARATORS);
+    if (tokens.length < 3) {
+      throw new CompilationError("Desugared library: cannot parse method " + signature);
+    }
+    methodStart();
+    int first = parseModifiers(tokens);
+    returnType(stringTypeToDexType(tokens[first]));
+    holderType(stringTypeToDexType(tokens[first + 1]));
+    methodName(factory.createString(tokens[first + 1 + 1]));
+    for (int i = first + 3; i < tokens.length; i++) {
+      argType(stringTypeToDexType(tokens[i]));
+    }
+    methodEnd();
+  }
+
+  private DexType stringTypeToDexType(String stringType) {
+    return factory.createType(DescriptorUtils.javaTypeToDescriptor(stringType));
+  }
+
+  private int parseModifiers(String[] split) {
+    int index = 0;
+    while (modifiers.containsKey(split[index])) {
+      modifier(modifiers.get(split[index]));
+      index++;
+    }
+    return index;
+  }
+
+  protected abstract void methodStart();
+
+  protected abstract void methodEnd();
+
+  protected abstract void returnType(DexType type);
+
+  protected abstract void argType(DexType type);
+
+  protected abstract void modifier(int access);
+
+  protected abstract void holderType(DexType type);
+
+  protected abstract void methodName(DexString name);
+}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecification.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecification.java
index 1e871b3..faa7e67 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecification.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecification.java
@@ -65,12 +65,12 @@
   }
 
   public Map<DexType, DexType> getEmulateLibraryInterface() {
-    return rewritingFlags.getEmulateLibraryInterface();
+    return rewritingFlags.getEmulatedInterfaces();
   }
 
   // If the method is retargeted, answers the retargeted method, else null.
   public DexMethod retargetMethod(DexEncodedMethod method, AppView<?> appView) {
-    Map<DexMethod, DexType> retargetCoreLibMember = rewritingFlags.getRetargetCoreLibMember();
+    Map<DexMethod, DexType> retargetCoreLibMember = rewritingFlags.getRetargetMethod();
     DexType dexType = retargetCoreLibMember.get(method.getReference());
     if (dexType != null) {
       return appView
@@ -88,11 +88,11 @@
   }
 
   public Map<DexMethod, DexType> getRetargetCoreLibMember() {
-    return rewritingFlags.getRetargetCoreLibMember();
+    return rewritingFlags.getRetargetMethod();
   }
 
   public Map<DexType, DexType> getBackportCoreLibraryMember() {
-    return rewritingFlags.getBackportCoreLibraryMember();
+    return rewritingFlags.getLegacyBackport();
   }
 
   public Map<DexType, DexType> getCustomConversions() {
@@ -108,7 +108,7 @@
   }
 
   public Set<DexType> getDontRetargetLibMember() {
-    return rewritingFlags.getDontRetargetLibMember();
+    return rewritingFlags.getDontRetarget();
   }
 
   public List<String> getExtraKeepRules() {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecificationParser.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecificationParser.java
index a612aea..85cf948 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecificationParser.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanDesugaredLibrarySpecificationParser.java
@@ -6,8 +6,11 @@
 
 import com.android.tools.r8.StringResource;
 import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.ExceptionDiagnostic;
 import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.StringDiagnostic;
@@ -36,16 +39,18 @@
   static final String WRAPPER_CONVERSION_KEY = "wrapper_conversion";
   static final String CUSTOM_CONVERSION_KEY = "custom_conversion";
   static final String REWRITE_PREFIX_KEY = "rewrite_prefix";
+  static final String RETARGET_METHOD_KEY = "retarget_method";
   static final String REWRITE_DERIVED_PREFIX_KEY = "rewrite_derived_prefix";
-  static final String RETARGET_LIB_MEMBER_KEY = "retarget_lib_member";
   static final String EMULATE_INTERFACE_KEY = "emulate_interface";
   static final String DONT_REWRITE_KEY = "dont_rewrite";
-  static final String DONT_RETARGET_LIB_MEMBER_KEY = "dont_retarget_lib_member";
+  static final String DONT_RETARGET_KEY = "dont_retarget";
   static final String BACKPORT_KEY = "backport";
+  static final String AMEND_LIBRARY_METHOD_KEY = "amend_library_method";
   static final String SHRINKER_CONFIG_KEY = "shrinker_config";
   static final String SUPPORT_ALL_CALLBACKS_FROM_LIBRARY_KEY = "support_all_callbacks_from_library";
 
   private final DexItemFactory dexItemFactory;
+  private final HumanMethodParser methodParser;
   private final Reporter reporter;
   private final boolean libraryCompilation;
   private final int minAPILevel;
@@ -59,6 +64,7 @@
       boolean libraryCompilation,
       int minAPILevel) {
     this.dexItemFactory = dexItemFactory;
+    this.methodParser = new HumanMethodParser(dexItemFactory);
     this.reporter = reporter;
     this.minAPILevel = minAPILevel;
     this.libraryCompilation = libraryCompilation;
@@ -129,8 +135,7 @@
   }
 
   private HumanRewritingFlags parseRewritingFlags() {
-    HumanRewritingFlags.Builder builder =
-        HumanRewritingFlags.builder(dexItemFactory, reporter, origin);
+    HumanRewritingFlags.Builder builder = HumanRewritingFlags.builder(reporter, origin);
     JsonElement commonFlags = required(jsonConfig, COMMON_FLAGS_KEY);
     JsonElement libraryFlags = required(jsonConfig, LIBRARY_FLAGS_KEY);
     JsonElement programFlags = required(jsonConfig, PROGRAM_FLAGS_KEY);
@@ -203,46 +208,70 @@
         }
       }
     }
-    if (jsonFlagSet.has(RETARGET_LIB_MEMBER_KEY)) {
+    if (jsonFlagSet.has(RETARGET_METHOD_KEY)) {
       for (Map.Entry<String, JsonElement> retarget :
-          jsonFlagSet.get(RETARGET_LIB_MEMBER_KEY).getAsJsonObject().entrySet()) {
-        builder.putRetargetCoreLibMember(retarget.getKey(), retarget.getValue().getAsString());
+          jsonFlagSet.get(RETARGET_METHOD_KEY).getAsJsonObject().entrySet()) {
+        builder.retargetMethod(
+            parseMethod(retarget.getKey()),
+            stringDescriptorToDexType(retarget.getValue().getAsString()));
       }
     }
     if (jsonFlagSet.has(BACKPORT_KEY)) {
       for (Map.Entry<String, JsonElement> backport :
           jsonFlagSet.get(BACKPORT_KEY).getAsJsonObject().entrySet()) {
-        builder.putBackportCoreLibraryMember(backport.getKey(), backport.getValue().getAsString());
+        builder.putLegacyBackport(
+            stringDescriptorToDexType(backport.getKey()),
+            stringDescriptorToDexType(backport.getValue().getAsString()));
       }
     }
     if (jsonFlagSet.has(EMULATE_INTERFACE_KEY)) {
       for (Map.Entry<String, JsonElement> itf :
           jsonFlagSet.get(EMULATE_INTERFACE_KEY).getAsJsonObject().entrySet()) {
-        builder.putEmulateLibraryInterface(itf.getKey(), itf.getValue().getAsString());
+        builder.putEmulatedInterface(
+            stringDescriptorToDexType(itf.getKey()),
+            stringDescriptorToDexType(itf.getValue().getAsString()));
       }
     }
     if (jsonFlagSet.has(CUSTOM_CONVERSION_KEY)) {
       for (Map.Entry<String, JsonElement> conversion :
           jsonFlagSet.get(CUSTOM_CONVERSION_KEY).getAsJsonObject().entrySet()) {
-        builder.putCustomConversion(conversion.getKey(), conversion.getValue().getAsString());
+        builder.putCustomConversion(
+            stringDescriptorToDexType(conversion.getKey()),
+            stringDescriptorToDexType(conversion.getValue().getAsString()));
       }
     }
     if (jsonFlagSet.has(WRAPPER_CONVERSION_KEY)) {
       for (JsonElement wrapper : jsonFlagSet.get(WRAPPER_CONVERSION_KEY).getAsJsonArray()) {
-        builder.addWrapperConversion(wrapper.getAsString());
+        builder.addWrapperConversion(stringDescriptorToDexType(wrapper.getAsString()));
       }
     }
     if (jsonFlagSet.has(DONT_REWRITE_KEY)) {
       JsonArray dontRewrite = jsonFlagSet.get(DONT_REWRITE_KEY).getAsJsonArray();
       for (JsonElement rewrite : dontRewrite) {
-        builder.addDontRewriteInvocation(rewrite.getAsString());
+        builder.addDontRewriteInvocation(parseMethod(rewrite.getAsString()));
       }
     }
-    if (jsonFlagSet.has(DONT_RETARGET_LIB_MEMBER_KEY)) {
-      JsonArray dontRetarget = jsonFlagSet.get(DONT_RETARGET_LIB_MEMBER_KEY).getAsJsonArray();
+    if (jsonFlagSet.has(DONT_RETARGET_KEY)) {
+      JsonArray dontRetarget = jsonFlagSet.get(DONT_RETARGET_KEY).getAsJsonArray();
       for (JsonElement rewrite : dontRetarget) {
-        builder.addDontRetargetLibMember(rewrite.getAsString());
+        builder.addDontRetargetLibMember(stringDescriptorToDexType(rewrite.getAsString()));
       }
     }
+    if (jsonFlagSet.has(AMEND_LIBRARY_METHOD_KEY)) {
+      JsonArray amendLibraryMember = jsonFlagSet.get(AMEND_LIBRARY_METHOD_KEY).getAsJsonArray();
+      for (JsonElement amend : amendLibraryMember) {
+        methodParser.parseMethod(amend.getAsString());
+        builder.amendLibraryMethod(methodParser.getMethod(), methodParser.getFlags());
+      }
+    }
+  }
+
+  private DexMethod parseMethod(String signature) {
+    methodParser.parseMethod(signature);
+    return methodParser.getMethod();
+  }
+
+  private DexType stringDescriptorToDexType(String stringClass) {
+    return dexItemFactory.createType(DescriptorUtils.javaTypeToDescriptor(stringClass));
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanMethodParser.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanMethodParser.java
new file mode 100644
index 0000000..b4bac60
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanMethodParser.java
@@ -0,0 +1,93 @@
+// 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.ir.desugar.desugaredlibrary.humanspecification;
+
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProto;
+import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodAccessFlags;
+import java.util.ArrayList;
+import java.util.List;
+
+public class HumanMethodParser extends AbstractMethodParser {
+
+  // Values accumulated while parsing.
+  private MethodAccessFlags.Builder flagBuilder;
+  private DexType returnType;
+  private DexType holder;
+  private DexString methodName;
+  private List<DexType> argTypes;
+  // Resulting values.
+  private DexMethod method;
+  private MethodAccessFlags flags;
+
+  protected HumanMethodParser(DexItemFactory factory) {
+    super(factory);
+  }
+
+  private boolean parsingFinished() {
+    return method != null;
+  }
+
+  public DexMethod getMethod() {
+    assert parsingFinished();
+    return method;
+  }
+
+  public MethodAccessFlags getFlags() {
+    assert parsingFinished();
+    return flags;
+  }
+
+  @Override
+  protected void modifier(int access) {
+    assert !parsingFinished();
+    flagBuilder.set(access);
+  }
+
+  @Override
+  protected void holderType(DexType type) {
+    assert !parsingFinished();
+    holder = type;
+  }
+
+  @Override
+  protected void methodName(DexString name) {
+    assert !parsingFinished();
+    methodName = name;
+  }
+
+  @Override
+  protected void methodStart() {
+    flagBuilder = MethodAccessFlags.builder();
+    returnType = null;
+    holder = null;
+    methodName = null;
+    argTypes = new ArrayList<>();
+    method = null;
+    flags = null;
+  }
+
+  @Override
+  protected void methodEnd() {
+    DexProto proto = factory.createProto(returnType, argTypes);
+    method = factory.createMethod(holder, proto, methodName);
+    flags = flagBuilder.build();
+  }
+
+  @Override
+  protected void returnType(DexType type) {
+    assert !parsingFinished();
+    returnType = type;
+  }
+
+  @Override
+  protected void argType(DexType type) {
+    assert !parsingFinished();
+    argTypes.add(type);
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanRewritingFlags.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanRewritingFlags.java
index 3faaf25..a37f18a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanRewritingFlags.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanRewritingFlags.java
@@ -4,13 +4,10 @@
 
 package com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification;
 
-import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexProto;
-import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.StringDiagnostic;
 import com.google.common.collect.ImmutableMap;
@@ -27,33 +24,36 @@
 
   private final Map<String, String> rewritePrefix;
   private final Map<String, Map<String, String>> rewriteDerivedPrefix;
-  private final Map<DexType, DexType> emulateLibraryInterface;
-  private final Map<DexMethod, DexType> retargetCoreLibMember;
-  private final Map<DexType, DexType> backportCoreLibraryMember;
+  private final Map<DexType, DexType> emulatedInterfaces;
+  private final Map<DexMethod, DexType> retargetMethod;
+  private final Map<DexType, DexType> legacyBackport;
   private final Map<DexType, DexType> customConversions;
   private final Set<DexMethod> dontRewriteInvocation;
-  private final Set<DexType> dontRetargetLibMember;
+  private final Set<DexType> dontRetarget;
   private final Set<DexType> wrapperConversions;
+  private final Map<DexMethod, MethodAccessFlags> amendLibraryMethod;
 
   HumanRewritingFlags(
       Map<String, String> rewritePrefix,
       Map<String, Map<String, String>> rewriteDerivedPrefix,
       Map<DexType, DexType> emulateLibraryInterface,
-      Map<DexMethod, DexType> retargetCoreLibMember,
-      Map<DexType, DexType> backportCoreLibraryMember,
-      Map<DexType, DexType> customConversions,
+      Map<DexMethod, DexType> retargetMethod,
+      Map<DexType, DexType> legacyBackport,
+      Map<DexType, DexType> customConversion,
       Set<DexMethod> dontRewriteInvocation,
-      Set<DexType> dontRetargetLibMember,
-      Set<DexType> wrapperConversions) {
+      Set<DexType> dontRetarget,
+      Set<DexType> wrapperConversion,
+      Map<DexMethod, MethodAccessFlags> amendLibraryMethod) {
     this.rewritePrefix = rewritePrefix;
     this.rewriteDerivedPrefix = rewriteDerivedPrefix;
-    this.emulateLibraryInterface = emulateLibraryInterface;
-    this.retargetCoreLibMember = retargetCoreLibMember;
-    this.backportCoreLibraryMember = backportCoreLibraryMember;
-    this.customConversions = customConversions;
+    this.emulatedInterfaces = emulateLibraryInterface;
+    this.retargetMethod = retargetMethod;
+    this.legacyBackport = legacyBackport;
+    this.customConversions = customConversion;
     this.dontRewriteInvocation = dontRewriteInvocation;
-    this.dontRetargetLibMember = dontRetargetLibMember;
-    this.wrapperConversions = wrapperConversions;
+    this.dontRetarget = dontRetarget;
+    this.wrapperConversions = wrapperConversion;
+    this.amendLibraryMethod = amendLibraryMethod;
   }
 
   public static HumanRewritingFlags empty() {
@@ -66,27 +66,28 @@
         ImmutableMap.of(),
         ImmutableSet.of(),
         ImmutableSet.of(),
-        ImmutableSet.of());
+        ImmutableSet.of(),
+        ImmutableMap.of());
   }
 
-  public static Builder builder(DexItemFactory dexItemFactory, Reporter reporter, Origin origin) {
-    return new Builder(dexItemFactory, reporter, origin);
+  public static Builder builder(Reporter reporter, Origin origin) {
+    return new Builder(reporter, origin);
   }
 
-  public Builder newBuilder(DexItemFactory dexItemFactory, Reporter reporter, Origin origin) {
+  public Builder newBuilder(Reporter reporter, Origin origin) {
     return new Builder(
-        dexItemFactory,
         reporter,
         origin,
         rewritePrefix,
         rewriteDerivedPrefix,
-        emulateLibraryInterface,
-        retargetCoreLibMember,
-        backportCoreLibraryMember,
+        emulatedInterfaces,
+        retargetMethod,
+        legacyBackport,
         customConversions,
         dontRewriteInvocation,
-        dontRetargetLibMember,
-        wrapperConversions);
+        dontRetarget,
+        wrapperConversions,
+        amendLibraryMethod);
   }
 
   public Map<String, String> getRewritePrefix() {
@@ -97,16 +98,16 @@
     return rewriteDerivedPrefix;
   }
 
-  public Map<DexType, DexType> getEmulateLibraryInterface() {
-    return emulateLibraryInterface;
+  public Map<DexType, DexType> getEmulatedInterfaces() {
+    return emulatedInterfaces;
   }
 
-  public Map<DexMethod, DexType> getRetargetCoreLibMember() {
-    return retargetCoreLibMember;
+  public Map<DexMethod, DexType> getRetargetMethod() {
+    return retargetMethod;
   }
 
-  public Map<DexType, DexType> getBackportCoreLibraryMember() {
-    return backportCoreLibraryMember;
+  public Map<DexType, DexType> getLegacyBackport() {
+    return legacyBackport;
   }
 
   public Map<DexType, DexType> getCustomConversions() {
@@ -117,35 +118,36 @@
     return dontRewriteInvocation;
   }
 
-  public Set<DexType> getDontRetargetLibMember() {
-    return dontRetargetLibMember;
+  public Set<DexType> getDontRetarget() {
+    return dontRetarget;
   }
 
   public Set<DexType> getWrapperConversions() {
     return wrapperConversions;
   }
 
+  public Map<DexMethod, MethodAccessFlags> getAmendLibraryMethod() {
+    return amendLibraryMethod;
+  }
+
   public static class Builder {
 
-    private static final String SEPARATORS = "\\s+|,\\s+|#|\\(|\\)";
-
-    private final DexItemFactory factory;
     private final Reporter reporter;
     private final Origin origin;
 
     private final Map<String, String> rewritePrefix;
-    Map<String, Map<String, String>> rewriteDerivedPrefix;
-    private final Map<DexType, DexType> emulateLibraryInterface;
-    private final Map<DexMethod, DexType> retargetCoreLibMember;
-    private final Map<DexType, DexType> backportCoreLibraryMember;
+    private final Map<String, Map<String, String>> rewriteDerivedPrefix;
+    private final Map<DexType, DexType> emulatedInterfaces;
+    private final Map<DexMethod, DexType> retargetMethod;
+    private final Map<DexType, DexType> legacyBackport;
     private final Map<DexType, DexType> customConversions;
     private final Set<DexMethod> dontRewriteInvocation;
-    private final Set<DexType> dontRetargetLibMember;
+    private final Set<DexType> dontRetarget;
     private final Set<DexType> wrapperConversions;
+    private final Map<DexMethod, MethodAccessFlags> amendLibraryMethod;
 
-    Builder(DexItemFactory factory, Reporter reporter, Origin origin) {
+    Builder(Reporter reporter, Origin origin) {
       this(
-          factory,
           reporter,
           origin,
           new HashMap<>(),
@@ -156,11 +158,11 @@
           new IdentityHashMap<>(),
           Sets.newIdentityHashSet(),
           Sets.newIdentityHashSet(),
-          Sets.newIdentityHashSet());
+          Sets.newIdentityHashSet(),
+          new IdentityHashMap<>());
     }
 
     Builder(
-        DexItemFactory factory,
         Reporter reporter,
         Origin origin,
         Map<String, String> rewritePrefix,
@@ -171,22 +173,23 @@
         Map<DexType, DexType> customConversions,
         Set<DexMethod> dontRewriteInvocation,
         Set<DexType> dontRetargetLibMember,
-        Set<DexType> wrapperConversions) {
-      this.factory = factory;
+        Set<DexType> wrapperConversions,
+        Map<DexMethod, MethodAccessFlags> amendLibrary) {
       this.reporter = reporter;
       this.origin = origin;
       this.rewritePrefix = new HashMap<>(rewritePrefix);
       this.rewriteDerivedPrefix = new HashMap<>(rewriteDerivedPrefix);
-      this.emulateLibraryInterface = new IdentityHashMap<>(emulateLibraryInterface);
-      this.retargetCoreLibMember = new IdentityHashMap<>(retargetCoreLibMember);
-      this.backportCoreLibraryMember = new IdentityHashMap<>(backportCoreLibraryMember);
+      this.emulatedInterfaces = new IdentityHashMap<>(emulateLibraryInterface);
+      this.retargetMethod = new IdentityHashMap<>(retargetCoreLibMember);
+      this.legacyBackport = new IdentityHashMap<>(backportCoreLibraryMember);
       this.customConversions = new IdentityHashMap<>(customConversions);
       this.dontRewriteInvocation = Sets.newIdentityHashSet();
       this.dontRewriteInvocation.addAll(dontRewriteInvocation);
-      this.dontRetargetLibMember = Sets.newIdentityHashSet();
-      this.dontRetargetLibMember.addAll(dontRetargetLibMember);
+      this.dontRetarget = Sets.newIdentityHashSet();
+      this.dontRetarget.addAll(dontRetargetLibMember);
       this.wrapperConversions = Sets.newIdentityHashSet();
       this.wrapperConversions.addAll(wrapperConversions);
+      this.amendLibraryMethod = new IdentityHashMap<>(amendLibrary);
     }
 
     // Utility to set values.
@@ -226,30 +229,15 @@
       return this;
     }
 
-    public Builder putEmulateLibraryInterface(
-        String emulateLibraryItf, String rewrittenEmulateLibraryItf) {
-      DexType interfaceType = stringClassToDexType(emulateLibraryItf);
-      DexType rewrittenType = stringClassToDexType(rewrittenEmulateLibraryItf);
-      putEmulateLibraryInterface(interfaceType, rewrittenType);
-      return this;
-    }
-
-    public Builder putEmulateLibraryInterface(DexType interfaceType, DexType rewrittenType) {
+    public Builder putEmulatedInterface(DexType interfaceType, DexType rewrittenType) {
       put(
-          emulateLibraryInterface,
+          emulatedInterfaces,
           interfaceType,
           rewrittenType,
           HumanDesugaredLibrarySpecificationParser.EMULATE_INTERFACE_KEY);
       return this;
     }
 
-    public Builder putCustomConversion(String type, String conversionHolder) {
-      DexType dexType = stringClassToDexType(type);
-      DexType conversionType = stringClassToDexType(conversionHolder);
-      putCustomConversion(dexType, conversionType);
-      return this;
-    }
-
     public Builder putCustomConversion(DexType dexType, DexType conversionType) {
       put(
           customConversions,
@@ -259,87 +247,42 @@
       return this;
     }
 
-    public Builder addWrapperConversion(String type) {
-      DexType dexType = stringClassToDexType(type);
-      addWrapperConversion(dexType);
-      return this;
-    }
-
     public Builder addWrapperConversion(DexType dexType) {
       wrapperConversions.add(dexType);
       return this;
     }
 
-    public Builder putRetargetCoreLibMember(String retarget, String rewrittenRetarget) {
-      DexMethod key = parseMethod(retarget);
-      DexType rewrittenType = stringClassToDexType(rewrittenRetarget);
-      putRetargetCoreLibMember(key, rewrittenType);
-      return this;
-    }
-
-    public Builder putRetargetCoreLibMember(DexMethod key, DexType rewrittenType) {
+    public Builder retargetMethod(DexMethod key, DexType rewrittenType) {
       put(
-          retargetCoreLibMember,
+          retargetMethod,
           key,
           rewrittenType,
-          HumanDesugaredLibrarySpecificationParser.RETARGET_LIB_MEMBER_KEY);
+          HumanDesugaredLibrarySpecificationParser.RETARGET_METHOD_KEY);
       return this;
     }
 
-    public Builder putBackportCoreLibraryMember(String backport, String rewrittenBackport) {
-      DexType backportType = stringClassToDexType(backport);
-      DexType rewrittenBackportType = stringClassToDexType(rewrittenBackport);
-      putBackportCoreLibraryMember(backportType, rewrittenBackportType);
-      return this;
-    }
-
-    public Builder putBackportCoreLibraryMember(
-        DexType backportType, DexType rewrittenBackportType) {
+    public Builder putLegacyBackport(DexType backportType, DexType rewrittenBackportType) {
       put(
-          backportCoreLibraryMember,
+          legacyBackport,
           backportType,
           rewrittenBackportType,
           HumanDesugaredLibrarySpecificationParser.BACKPORT_KEY);
       return this;
     }
 
-    public Builder addDontRewriteInvocation(String dontRewriteInvocation) {
-      DexMethod dontRewrite = parseMethod(dontRewriteInvocation);
-      addDontRewriteInvocation(dontRewrite);
-      return this;
-    }
-
     public Builder addDontRewriteInvocation(DexMethod dontRewrite) {
-      this.dontRewriteInvocation.add(dontRewrite);
-      return this;
-    }
-
-    public Builder addDontRetargetLibMember(String dontRetargetLibMember) {
-      addDontRetargetLibMember(stringClassToDexType(dontRetargetLibMember));
+      dontRewriteInvocation.add(dontRewrite);
       return this;
     }
 
     public Builder addDontRetargetLibMember(DexType dontRetargetLibMember) {
-      this.dontRetargetLibMember.add(dontRetargetLibMember);
+      dontRetarget.add(dontRetargetLibMember);
       return this;
     }
 
-    private DexMethod parseMethod(String signature) {
-      String[] split = signature.split(SEPARATORS);
-      assert split.length >= 3;
-      DexType returnType = factory.createType(DescriptorUtils.javaTypeToDescriptor(split[0]));
-      DexType holderType = factory.createType(DescriptorUtils.javaTypeToDescriptor(split[1]));
-      DexString name = factory.createString(split[2]);
-      DexType[] argTypes = new DexType[split.length - 3];
-      for (int i = 3; i < split.length; i++) {
-        argTypes[i - 3] = factory.createType(DescriptorUtils.javaTypeToDescriptor(split[i]));
-      }
-      DexProto proto = factory.createProto(returnType, argTypes);
-      return factory.createMethod(holderType, proto, name);
-    }
-
-    private DexType stringClassToDexType(String stringClass) {
-      return factory.createType(DescriptorUtils.javaTypeToDescriptor(stringClass));
+    public Builder amendLibraryMethod(DexMethod member, MethodAccessFlags flags) {
+      amendLibraryMethod.put(member, flags);
+      return this;
     }
 
     public HumanRewritingFlags build() {
@@ -347,13 +290,14 @@
       return new HumanRewritingFlags(
           ImmutableMap.copyOf(rewritePrefix),
           ImmutableMap.copyOf(rewriteDerivedPrefix),
-          ImmutableMap.copyOf(emulateLibraryInterface),
-          ImmutableMap.copyOf(retargetCoreLibMember),
-          ImmutableMap.copyOf(backportCoreLibraryMember),
+          ImmutableMap.copyOf(emulatedInterfaces),
+          ImmutableMap.copyOf(retargetMethod),
+          ImmutableMap.copyOf(legacyBackport),
           ImmutableMap.copyOf(customConversions),
           ImmutableSet.copyOf(dontRewriteInvocation),
-          ImmutableSet.copyOf(dontRetargetLibMember),
-          ImmutableSet.copyOf(wrapperConversions));
+          ImmutableSet.copyOf(dontRetarget),
+          ImmutableSet.copyOf(wrapperConversions),
+          ImmutableMap.copyOf(amendLibraryMethod));
     }
 
     private void validate() {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/MultiAPILevelHumanDesugaredLibrarySpecificationFlagDeduplicator.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/MultiAPILevelHumanDesugaredLibrarySpecificationFlagDeduplicator.java
index d79540c..4422b66 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/MultiAPILevelHumanDesugaredLibrarySpecificationFlagDeduplicator.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/MultiAPILevelHumanDesugaredLibrarySpecificationFlagDeduplicator.java
@@ -5,8 +5,9 @@
 package com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification;
 
 import com.android.tools.r8.graph.DexItem;
-import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.Reporter;
 import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
@@ -20,7 +21,6 @@
 
   public static void deduplicateFlags(
       MultiAPILevelHumanDesugaredLibrarySpecification specification,
-      DexItemFactory factory,
       Reporter reporter) {
 
     IntArraySet apis = new IntArraySet();
@@ -29,13 +29,12 @@
     apis.addAll(specification.getProgramFlags().keySet());
 
     for (Integer api : apis) {
-      deduplicateFlags(specification, factory, reporter, api);
+      deduplicateFlags(specification, reporter, api);
     }
   }
 
   private static void deduplicateFlags(
       MultiAPILevelHumanDesugaredLibrarySpecification specification,
-      DexItemFactory factory,
       Reporter reporter,
       int api) {
 
@@ -53,12 +52,10 @@
     Origin origin = specification.getOrigin();
     HumanRewritingFlags.Builder commonBuilder =
         commonFlags.get(api) == null
-            ? HumanRewritingFlags.builder(factory, reporter, origin)
-            : commonFlags.get(api).newBuilder(factory, reporter, origin);
-    HumanRewritingFlags.Builder libraryBuilder =
-        HumanRewritingFlags.builder(factory, reporter, origin);
-    HumanRewritingFlags.Builder programBuilder =
-        HumanRewritingFlags.builder(factory, reporter, origin);
+            ? HumanRewritingFlags.builder(reporter, origin)
+            : commonFlags.get(api).newBuilder(reporter, origin);
+    HumanRewritingFlags.Builder libraryBuilder = HumanRewritingFlags.builder(reporter, origin);
+    HumanRewritingFlags.Builder programBuilder = HumanRewritingFlags.builder(reporter, origin);
 
     // Iterate over all library/program flags, add them in common if also in the other, else add
     // them to library/program.
@@ -79,20 +76,20 @@
     deduplicateRewriteDifferentPrefix(flags, otherFlags, commonBuilder, builder);
 
     deduplicateFlags(
-        flags.getEmulateLibraryInterface(),
-        otherFlags.getEmulateLibraryInterface(),
-        commonBuilder::putEmulateLibraryInterface,
-        builder::putEmulateLibraryInterface);
+        flags.getEmulatedInterfaces(),
+        otherFlags.getEmulatedInterfaces(),
+        commonBuilder::putEmulatedInterface,
+        builder::putEmulatedInterface);
     deduplicateFlags(
-        flags.getRetargetCoreLibMember(),
-        otherFlags.getRetargetCoreLibMember(),
-        commonBuilder::putRetargetCoreLibMember,
-        builder::putRetargetCoreLibMember);
+        flags.getRetargetMethod(),
+        otherFlags.getRetargetMethod(),
+        commonBuilder::retargetMethod,
+        builder::retargetMethod);
     deduplicateFlags(
-        flags.getBackportCoreLibraryMember(),
-        otherFlags.getBackportCoreLibraryMember(),
-        commonBuilder::putBackportCoreLibraryMember,
-        builder::putBackportCoreLibraryMember);
+        flags.getLegacyBackport(),
+        otherFlags.getLegacyBackport(),
+        commonBuilder::putLegacyBackport,
+        builder::putLegacyBackport);
     deduplicateFlags(
         flags.getCustomConversions(),
         otherFlags.getCustomConversions(),
@@ -105,8 +102,8 @@
         commonBuilder::addDontRewriteInvocation,
         builder::addDontRewriteInvocation);
     deduplicateFlags(
-        flags.getDontRetargetLibMember(),
-        otherFlags.getDontRetargetLibMember(),
+        flags.getDontRetarget(),
+        otherFlags.getDontRetarget(),
         commonBuilder::addDontRetargetLibMember,
         builder::addDontRetargetLibMember);
     deduplicateFlags(
@@ -114,6 +111,26 @@
         otherFlags.getWrapperConversions(),
         commonBuilder::addWrapperConversion,
         builder::addWrapperConversion);
+
+    deduplicateAmendLibraryMemberFlags(flags, otherFlags, commonBuilder, builder);
+  }
+
+  private static void deduplicateAmendLibraryMemberFlags(
+      HumanRewritingFlags flags,
+      HumanRewritingFlags otherFlags,
+      HumanRewritingFlags.Builder commonBuilder,
+      HumanRewritingFlags.Builder builder) {
+    Map<DexMethod, MethodAccessFlags> other = otherFlags.getAmendLibraryMethod();
+    flags
+        .getAmendLibraryMethod()
+        .forEach(
+            (k, v) -> {
+              if (other.get(k) == v) {
+                commonBuilder.amendLibraryMethod(k, v);
+              } else {
+                builder.amendLibraryMethod(k, v);
+              }
+            });
   }
 
   private static void deduplicateRewriteDifferentPrefix(
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/MultiAPILevelHumanDesugaredLibrarySpecificationJsonExporter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/MultiAPILevelHumanDesugaredLibrarySpecificationJsonExporter.java
index dd22fe7..9fe9a04 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/MultiAPILevelHumanDesugaredLibrarySpecificationJsonExporter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/MultiAPILevelHumanDesugaredLibrarySpecificationJsonExporter.java
@@ -4,8 +4,25 @@
 
 package com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification;
 
-import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.*;
+import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.AMEND_LIBRARY_METHOD_KEY;
+import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.API_LEVEL_BELOW_OR_EQUAL_KEY;
+import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.BACKPORT_KEY;
+import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.COMMON_FLAGS_KEY;
+import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.CUSTOM_CONVERSION_KEY;
+import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.DONT_RETARGET_KEY;
+import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.DONT_REWRITE_KEY;
+import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.EMULATE_INTERFACE_KEY;
 import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.IDENTIFIER_KEY;
+import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.LIBRARY_FLAGS_KEY;
+import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.PROGRAM_FLAGS_KEY;
+import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.REQUIRED_COMPILATION_API_LEVEL_KEY;
+import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.RETARGET_METHOD_KEY;
+import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.REWRITE_DERIVED_PREFIX_KEY;
+import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.REWRITE_PREFIX_KEY;
+import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.SHRINKER_CONFIG_KEY;
+import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.SUPPORT_ALL_CALLBACKS_FROM_LIBRARY_KEY;
+import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.SYNTHESIZED_LIBRARY_CLASSES_PACKAGE_PREFIX_KEY;
+import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.WRAPPER_CONVERSION_KEY;
 
 import com.android.tools.r8.DiagnosticsHandler;
 import com.android.tools.r8.StringConsumer;
@@ -13,6 +30,7 @@
 import com.android.tools.r8.graph.DexItem;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodAccessFlags;
 import com.google.common.collect.Sets;
 import com.google.gson.Gson;
 import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
@@ -74,20 +92,20 @@
                 .forEach((k, v) -> rewriteDerivedPrefix.put(k, new TreeMap<>(v)));
             toJson.put(REWRITE_DERIVED_PREFIX_KEY, rewriteDerivedPrefix);
           }
-          if (!flags.getEmulateLibraryInterface().isEmpty()) {
-            toJson.put(EMULATE_INTERFACE_KEY, mapToString(flags.getEmulateLibraryInterface()));
+          if (!flags.getEmulatedInterfaces().isEmpty()) {
+            toJson.put(EMULATE_INTERFACE_KEY, mapToString(flags.getEmulatedInterfaces()));
           }
           if (!flags.getDontRewriteInvocation().isEmpty()) {
             toJson.put(DONT_REWRITE_KEY, setToString(flags.getDontRewriteInvocation()));
           }
-          if (!flags.getRetargetCoreLibMember().isEmpty()) {
-            toJson.put(RETARGET_LIB_MEMBER_KEY, mapToString(flags.getRetargetCoreLibMember()));
+          if (!flags.getRetargetMethod().isEmpty()) {
+            toJson.put(RETARGET_METHOD_KEY, mapToString(flags.getRetargetMethod()));
           }
-          if (!flags.getDontRetargetLibMember().isEmpty()) {
-            toJson.put(DONT_RETARGET_LIB_MEMBER_KEY, setToString(flags.getDontRetargetLibMember()));
+          if (!flags.getDontRetarget().isEmpty()) {
+            toJson.put(DONT_RETARGET_KEY, setToString(flags.getDontRetarget()));
           }
-          if (!flags.getBackportCoreLibraryMember().isEmpty()) {
-            toJson.put(BACKPORT_KEY, mapToString(flags.getBackportCoreLibraryMember()));
+          if (!flags.getLegacyBackport().isEmpty()) {
+            toJson.put(BACKPORT_KEY, mapToString(flags.getLegacyBackport()));
           }
           if (!flags.getWrapperConversions().isEmpty()) {
             toJson.put(WRAPPER_CONVERSION_KEY, setToString(flags.getWrapperConversions()));
@@ -95,11 +113,22 @@
           if (!flags.getCustomConversions().isEmpty()) {
             toJson.put(CUSTOM_CONVERSION_KEY, mapToString(flags.getCustomConversions()));
           }
+          if (!flags.getAmendLibraryMethod().isEmpty()) {
+            toJson.put(
+                AMEND_LIBRARY_METHOD_KEY, amendLibraryToString(flags.getAmendLibraryMethod()));
+          }
           list.add(toJson);
         });
     return list;
   }
 
+  private Set<String> amendLibraryToString(Map<DexMethod, MethodAccessFlags> amendLibraryMembers) {
+    Set<String> stringSet = Sets.newHashSet();
+    amendLibraryMembers.forEach(
+        (member, flags) -> stringSet.add(flags.toString() + " " + toString(member)));
+    return stringSet;
+  }
+
   private Set<String> setToString(Set<? extends DexItem> set) {
     Set<String> stringSet = Sets.newHashSet();
     set.forEach(e -> stringSet.add(toString(e)));
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/MultiAPILevelHumanDesugaredLibrarySpecificationParser.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/MultiAPILevelHumanDesugaredLibrarySpecificationParser.java
index 140609d..9f9fa81 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/MultiAPILevelHumanDesugaredLibrarySpecificationParser.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/MultiAPILevelHumanDesugaredLibrarySpecificationParser.java
@@ -43,10 +43,8 @@
       int api_level_below_or_equal = required(flag, API_LEVEL_BELOW_OR_EQUAL_KEY).getAsInt();
       HumanRewritingFlags.Builder builder =
           flags.containsKey(api_level_below_or_equal)
-              ? flags
-                  .get(api_level_below_or_equal)
-                  .newBuilder(dexItemFactory(), reporter(), getOrigin())
-              : HumanRewritingFlags.builder(dexItemFactory(), reporter(), getOrigin());
+              ? flags.get(api_level_below_or_equal).newBuilder(reporter(), getOrigin())
+              : HumanRewritingFlags.builder(reporter(), getOrigin());
       parseFlags(flag, builder);
       flags.put(api_level_below_or_equal, builder.build());
     }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java
index adc507f..520cc5f 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java
@@ -7,6 +7,7 @@
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexReference;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import java.util.List;
 import java.util.Map;
@@ -135,6 +136,10 @@
     return rewritingFlags.getCustomConversions();
   }
 
+  public Map<DexMethod, MethodAccessFlags> getAmendLibraryMethods() {
+    return rewritingFlags.getAmendLibraryMethod();
+  }
+
   public boolean hasRetargeting() {
     return rewritingFlags.hasRetargeting();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java
index f34634d..8dcffa4 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java
@@ -6,6 +6,7 @@
 
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodAccessFlags;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -33,7 +34,8 @@
       Map<DexType, List<DexMethod>> wrappers,
       Map<DexType, DexType> legacyBackport,
       Set<DexType> dontRetarget,
-      Map<DexType, CustomConversionDescriptor> customConversions) {
+      Map<DexType, CustomConversionDescriptor> customConversions,
+      Map<DexMethod, MethodAccessFlags> amendLibraryMethods) {
     this.rewriteType = rewriteType;
     this.rewriteDerivedTypeOnly = rewriteDerivedTypeOnly;
     this.staticRetarget = staticRetarget;
@@ -46,6 +48,7 @@
     this.legacyBackport = legacyBackport;
     this.dontRetarget = dontRetarget;
     this.customConversions = customConversions;
+    this.amendLibraryMethod = amendLibraryMethods;
   }
 
   // Rewrites all the references to the keys as well as synthetic types derived from any key.
@@ -79,6 +82,7 @@
   private final Map<DexType, DexType> legacyBackport;
   private final Set<DexType> dontRetarget;
   private final Map<DexType, CustomConversionDescriptor> customConversions;
+  private final Map<DexMethod, MethodAccessFlags> amendLibraryMethod;
 
   public Map<DexType, DexType> getRewriteType() {
     return rewriteType;
@@ -138,6 +142,10 @@
     return customConversions;
   }
 
+  public Map<DexMethod, MethodAccessFlags> getAmendLibraryMethod() {
+    return amendLibraryMethod;
+  }
+
   public boolean hasRetargeting() {
     return !staticRetarget.isEmpty()
         || !nonEmulatedVirtualRetarget.isEmpty()
@@ -182,6 +190,8 @@
     private final ImmutableSet.Builder<DexType> dontRetarget = ImmutableSet.builder();
     private final ImmutableMap.Builder<DexType, CustomConversionDescriptor> customConversions =
         ImmutableMap.builder();
+    private final ImmutableMap.Builder<DexMethod, MethodAccessFlags> amendLibraryMethod =
+        ImmutableMap.builder();
 
     public void rewriteType(DexType src, DexType target) {
       assert src != null;
@@ -231,6 +241,10 @@
       customConversions.put(src, descriptor);
     }
 
+    public void amendLibraryMethod(DexMethod missingReference, MethodAccessFlags flags) {
+      amendLibraryMethod.put(missingReference, flags);
+    }
+
     public DexType getRewrittenType(DexType type) {
       return rewriteType.get(type);
     }
@@ -247,7 +261,8 @@
           wrappers.build(),
           legacyBackport.build(),
           dontRetarget.build(),
-          customConversions.build());
+          customConversions.build(),
+          amendLibraryMethod.build());
     }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java
index 73dd908..a4b984f 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java
@@ -140,13 +140,11 @@
     AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
     MethodResolutionResult resolutionResult =
         appInfo.resolveMethod(invokedMethod, cfInvoke.isInterface());
-    // We are required to use the invokedMethod if it does not resolve due to the rewriting of
-    // private methods absent from the library.
-    DexMethod singleTarget =
-        resolutionResult.isSingleResolution()
-            ? resolutionResult.getSingleTarget().getReference()
-            : invokedMethod;
-    assert singleTarget != null;
+    if (!resolutionResult.isSingleResolution()) {
+      return NO_REWRITING;
+    }
+    assert resolutionResult.getSingleTarget() != null;
+    DexMethod singleTarget = resolutionResult.getSingleTarget().getReference();
     if (cfInvoke.isInvokeStatic()) {
       DexMethod retarget = staticRetarget.get(singleTarget);
       return retarget == null ? NO_REWRITING : ensureInvokeRetargetingResult(retarget);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineEmulatedInterfaceConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineEmulatedInterfaceConverter.java
index 4be8ef0..198fbc2 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineEmulatedInterfaceConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineEmulatedInterfaceConverter.java
@@ -43,7 +43,7 @@
       AppInfoWithClassHierarchy appInfo,
       MachineRewritingFlags.Builder builder,
       BiConsumer<String, Set<? extends DexReference>> warnConsumer) {
-    Map<DexType, DexType> emulateInterfaces = rewritingFlags.getEmulateLibraryInterface();
+    Map<DexType, DexType> emulateInterfaces = rewritingFlags.getEmulatedInterfaces();
     Set<DexMethod> dontRewriteInvocation = rewritingFlags.getDontRewriteInvocation();
     processEmulatedInterfaceHierarchy(appInfo, emulateInterfaces);
     for (DexType itf : emulateInterfaces.keySet()) {
@@ -73,7 +73,7 @@
         appInfo
             .dexItemFactory()
             .createMethod(
-                rewritingFlags.getEmulateLibraryInterface().get(method.getHolderType()),
+                rewritingFlags.getEmulatedInterfaces().get(method.getHolderType()),
                 method.getProto(),
                 method.getName());
     DerivedMethod interfaceMethod = new DerivedMethod(itfDexMethod);
@@ -93,7 +93,7 @@
     List<DexType> subInterfaces = emulatedInterfaceHierarchy.get(method.getHolderType());
     LinkedHashMap<DexType, DerivedMethod> extraDispatchCases = new LinkedHashMap<>();
     // Retarget core lib emulated dispatch handled as part of emulated interface dispatch.
-    Map<DexMethod, DexType> retargetCoreLibMember = rewritingFlags.getRetargetCoreLibMember();
+    Map<DexMethod, DexType> retargetCoreLibMember = rewritingFlags.getRetargetMethod();
     for (DexMethod retarget : retargetCoreLibMember.keySet()) {
       if (retarget.match(method)) {
         DexClass inClass = appInfo.definitionFor(retarget.getHolderType());
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java
index 0fc22f1..5dad42c 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java
@@ -43,10 +43,10 @@
   public void convertPrefixFlags(
       HumanRewritingFlags rewritingFlags, BiConsumer<String, Set<DexString>> warnConsumer) {
     rewriteClasses();
-    rewriteValues(rewritingFlags.getRetargetCoreLibMember());
+    rewriteValues(rewritingFlags.getRetargetMethod());
     rewriteValues(rewritingFlags.getCustomConversions());
-    rewriteEmulatedInterface(rewritingFlags.getEmulateLibraryInterface());
-    rewriteRetargetKeys(rewritingFlags.getRetargetCoreLibMember());
+    rewriteEmulatedInterface(rewritingFlags.getEmulatedInterfaces());
+    rewriteRetargetKeys(rewritingFlags.getRetargetMethod());
     warnIfUnusedPrefix(warnConsumer);
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java
index e153c70..8549488 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java
@@ -41,7 +41,7 @@
       MachineRewritingFlags.Builder builder,
       BiConsumer<String, Set<? extends DexReference>> warnConsumer) {
     rewritingFlags
-        .getRetargetCoreLibMember()
+        .getRetargetMethod()
         .forEach(
             (method, type) ->
                 convertRetargetCoreLibMemberFlag(builder, rewritingFlags, method, type));
@@ -55,12 +55,6 @@
       DexType type) {
     DexClass holder = appInfo.definitionFor(method.holder);
     DexEncodedMethod foundMethod = holder.lookupMethod(method);
-    if (foundMethod == null && method.getName().toString().equals("deepEquals0")) {
-      // TODO(b/184026720): Temporary work-around (the method is missing).
-      DexMethod dest = method.withHolder(type, appInfo.dexItemFactory());
-      builder.putStaticRetarget(method, dest);
-      return;
-    }
     if (foundMethod == null) {
       missingMethods.add(foundMethod.getReference());
       return;
@@ -127,8 +121,7 @@
       AppInfoWithClassHierarchy appInfo,
       HumanRewritingFlags humanRewritingFlags) {
     // Answers true if this method is already managed through emulated interface dispatch.
-    Map<DexType, DexType> emulateLibraryInterface =
-        humanRewritingFlags.getEmulateLibraryInterface();
+    Map<DexType, DexType> emulateLibraryInterface = humanRewritingFlags.getEmulatedInterfaces();
     if (emulateLibraryInterface.isEmpty()) {
       return false;
     }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java
index 1b5009a..fac9895 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java
@@ -16,6 +16,7 @@
 import com.android.tools.r8.graph.DexReference;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibraryAmender;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecification;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanRewritingFlags;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanTopLevelFlags;
@@ -100,6 +101,8 @@
       String synthesizedPrefix, HumanRewritingFlags rewritingFlags) {
     AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
     MachineRewritingFlags.Builder builder = MachineRewritingFlags.builder();
+    DesugaredLibraryAmender.run(appView, rewritingFlags.getAmendLibraryMethod());
+    rewritingFlags.getAmendLibraryMethod().forEach(builder::amendLibraryMethod);
     new HumanToMachineRetargetConverter(appInfo)
         .convertRetargetFlags(rewritingFlags, builder, this::warnMissingReferences);
     new HumanToMachineEmulatedInterfaceConverter(appInfo)
@@ -113,8 +116,8 @@
         .forEach(
             (type, conversionType) ->
                 convertCustomConversion(appInfo, builder, type, conversionType));
-    rewritingFlags.getDontRetargetLibMember().forEach(builder::addDontRetarget);
-    rewritingFlags.getBackportCoreLibraryMember().forEach(builder::putLegacyBackport);
+    rewritingFlags.getDontRetarget().forEach(builder::addDontRetarget);
+    rewritingFlags.getLegacyBackport().forEach(builder::putLegacyBackport);
     return builder.build();
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LegacyToHumanSpecificationConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LegacyToHumanSpecificationConverter.java
index fcdef84..d7bd243 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LegacyToHumanSpecificationConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LegacyToHumanSpecificationConverter.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.StringConsumer;
 import com.android.tools.r8.StringResource;
 import com.android.tools.r8.dex.ApplicationReader;
+import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexClassAndMethod;
@@ -16,6 +17,7 @@
 import com.android.tools.r8.graph.DexProto;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecification;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanRewritingFlags;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanTopLevelFlags;
@@ -60,7 +62,7 @@
     MultiAPILevelHumanDesugaredLibrarySpecification humanSpec =
         convertAllAPILevels(legacySpec, androidLib, options);
     MultiAPILevelHumanDesugaredLibrarySpecificationFlagDeduplicator.deduplicateFlags(
-        humanSpec, options.dexItemFactory(), options.reporter);
+        humanSpec, options.reporter);
     MultiAPILevelHumanDesugaredLibrarySpecificationJsonExporter.export(humanSpec, output);
   }
 
@@ -122,7 +124,7 @@
     if (options.getMinApiLevel().isLessThanOrEqualTo(legacyHackLevel)
         && legacySpec.isLibraryCompilation()) {
       HumanRewritingFlags.Builder builder =
-          humanRewritingFlags.newBuilder(app.dexItemFactory(), app.options.reporter, origin);
+          humanRewritingFlags.newBuilder(app.options.reporter, origin);
       legacyLibraryFlagHacks(app.dexItemFactory(), builder);
       humanRewritingFlags = builder.build();
     }
@@ -135,7 +137,7 @@
     int level = legacyHackLevel.getLevel();
     HumanRewritingFlags humanRewritingFlags = libraryFlags.get(level);
     HumanRewritingFlags.Builder builder =
-        humanRewritingFlags.newBuilder(app.dexItemFactory(), app.options.reporter, origin);
+        humanRewritingFlags.newBuilder(app.options.reporter, origin);
     legacyLibraryFlagHacks(app.dexItemFactory(), builder);
     libraryFlags.put(level, builder.build());
   }
@@ -152,7 +154,12 @@
     DexMethod source =
         itemFactory.createMethod(itemFactory.createType(itemFactory.arraysDescriptor), proto, name);
     DexType target = itemFactory.createType("Ljava/util/DesugarArrays;");
-    builder.putRetargetCoreLibMember(source, target);
+    builder.retargetMethod(source, target);
+
+    builder.amendLibraryMethod(
+        source,
+        MethodAccessFlags.fromSharedAccessFlags(
+            Constants.ACC_PRIVATE | Constants.ACC_STATIC, false));
 
     // TODO(b/181629049): This is only a workaround rewriting invokes of
     //  j.u.TimeZone.getTimeZone taking a java.time.ZoneId.
@@ -163,7 +170,7 @@
             itemFactory.createType("Ljava/time/ZoneId;"));
     source = itemFactory.createMethod(itemFactory.createType("Ljava/util/TimeZone;"), proto, name);
     target = itemFactory.createType("Ljava/util/DesugarTimeZone;");
-    builder.putRetargetCoreLibMember(source, target);
+    builder.retargetMethod(source, target);
   }
 
   private DexApplication readApp(AndroidApp inputApp, InternalOptions options) throws IOException {
@@ -181,14 +188,13 @@
 
   private HumanRewritingFlags convertRewritingFlags(
       LegacyRewritingFlags flags, DexApplication app, Origin origin) {
-    HumanRewritingFlags.Builder builder =
-        HumanRewritingFlags.builder(app.dexItemFactory(), app.options.reporter, origin);
+    HumanRewritingFlags.Builder builder = HumanRewritingFlags.builder(app.options.reporter, origin);
 
     flags
         .getRewritePrefix()
         .forEach((prefix, rewritten) -> rewritePrefix(builder, prefix, rewritten));
-    flags.getEmulateLibraryInterface().forEach(builder::putEmulateLibraryInterface);
-    flags.getBackportCoreLibraryMember().forEach(builder::putBackportCoreLibraryMember);
+    flags.getEmulateLibraryInterface().forEach(builder::putEmulatedInterface);
+    flags.getBackportCoreLibraryMember().forEach(builder::putLegacyBackport);
     flags.getCustomConversions().forEach(builder::putCustomConversion);
     flags.getDontRetargetLibMember().forEach(builder::addDontRetargetLibMember);
     flags.getWrapperConversions().forEach(builder::addWrapperConversion);
@@ -246,7 +252,7 @@
           assert dexClass != null;
           List<DexClassAndMethod> methodsWithName = findMethodsWithName(name, dexClass);
           for (DexClassAndMethod dexClassAndMethod : methodsWithName) {
-            builder.putRetargetCoreLibMember(dexClassAndMethod.getReference(), rewrittenType);
+            builder.retargetMethod(dexClassAndMethod.getReference(), rewrittenType);
           }
         });
   }
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/specification/ConvertExportReadTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/specification/ConvertExportReadTest.java
index 08dbd18..a972903 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/specification/ConvertExportReadTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/specification/ConvertExportReadTest.java
@@ -33,15 +33,13 @@
 @RunWith(Parameterized.class)
 public class ConvertExportReadTest extends TestBase {
 
-  private final TestParameters parameters;
-
   @Parameterized.Parameters(name = "{0}")
   public static TestParametersCollection data() {
     return getTestParameters().withNoneRuntime().build();
   }
 
   public ConvertExportReadTest(TestParameters parameters) {
-    this.parameters = parameters;
+    assert parameters.isNoneRuntime();
   }
 
   @Test
@@ -100,26 +98,25 @@
     assertEquals(
         humanRewritingFlags1.getRewriteDerivedPrefix(),
         humanRewritingFlags2.getRewriteDerivedPrefix());
+
     assertEquals(
-        humanRewritingFlags1.getBackportCoreLibraryMember(),
-        humanRewritingFlags2.getBackportCoreLibraryMember());
+        humanRewritingFlags1.getLegacyBackport(), humanRewritingFlags2.getLegacyBackport());
     assertEquals(
         humanRewritingFlags1.getCustomConversions(), humanRewritingFlags2.getCustomConversions());
     assertEquals(
-        humanRewritingFlags1.getEmulateLibraryInterface(),
-        humanRewritingFlags2.getEmulateLibraryInterface());
+        humanRewritingFlags1.getEmulatedInterfaces(), humanRewritingFlags2.getEmulatedInterfaces());
     assertEquals(
-        humanRewritingFlags1.getRetargetCoreLibMember(),
-        humanRewritingFlags2.getRetargetCoreLibMember());
+        humanRewritingFlags1.getRetargetMethod(), humanRewritingFlags2.getRetargetMethod());
 
-    assertEquals(
-        humanRewritingFlags1.getDontRetargetLibMember(),
-        humanRewritingFlags2.getDontRetargetLibMember());
+    assertEquals(humanRewritingFlags1.getDontRetarget(), humanRewritingFlags2.getDontRetarget());
     assertEquals(
         humanRewritingFlags1.getDontRewriteInvocation(),
         humanRewritingFlags2.getDontRewriteInvocation());
     assertEquals(
         humanRewritingFlags1.getWrapperConversions(), humanRewritingFlags2.getWrapperConversions());
+
+    assertEquals(
+        humanRewritingFlags1.getAmendLibraryMethod(), humanRewritingFlags2.getAmendLibraryMethod());
   }
 
   private void assertTopLevelFlagsEquals(