Backwards compatible desugared library configuration.

Bug: 158645207
Change-Id: I6d298723aecd6693b3614527d9fd1dd3b524ed78
diff --git a/.gitignore b/.gitignore
index e184eb8..aa4c9ae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -135,6 +135,8 @@
 third_party/protobuf-lite/
 third_party/r8
 third_party/r8.tar.gz
+third_party/r8-releases/2.0.74
+third_party/r8-releases/2.0.74.tar.gz
 third_party/r8mappings
 third_party/r8mappings.tar.gz
 third_party/remapper
diff --git a/build.gradle b/build.gradle
index 909d605..4428f58 100644
--- a/build.gradle
+++ b/build.gradle
@@ -335,6 +335,7 @@
                 "proguard/proguard5.2.1",
                 "proguard/proguard6.0.1",
                 "r8",
+                "r8-releases/2.0.74",
                 "r8mappings",
                 "tachiyomi"
         ],
diff --git a/src/library_desugar/desugar_jdk_libs.json b/src/library_desugar/desugar_jdk_libs.json
index 6477eff..5bdc91e 100644
--- a/src/library_desugar/desugar_jdk_libs.json
+++ b/src/library_desugar/desugar_jdk_libs.json
@@ -1,51 +1,19 @@
 {
-  "configuration_format_version": 5,
+  "configuration_format_version": 3,
   "group_id" : "com.tools.android",
   "artifact_id" : "desugar_jdk_libs",
-  "version": "1.0.7",
+  "version": "1.0.9",
   "required_compilation_api_level": 26,
   "synthesized_library_classes_package_prefix": "j$.",
   "common_flags": [
     {
       "api_level_below_or_equal": 25,
-      "custom_conversion": {
-        "java.time.ZonedDateTime": "java.time.TimeConversions",
-        "java.time.LocalDate": "java.time.TimeConversions",
-        "java.time.Duration": "java.time.TimeConversions",
-        "java.time.ZoneId": "java.time.TimeConversions",
-        "java.time.MonthDay": "java.time.TimeConversions",
-        "java.time.Instant": "java.time.TimeConversions"
-      },
       "wrapper_conversion": [
         "java.time.Clock"
       ]
     },
     {
       "api_level_below_or_equal": 23,
-      "dont_rewrite": [
-        "java.util.Iterator#remove"
-      ],
-      "emulate_interface": {
-        "java.lang.Iterable": "j$.lang.Iterable",
-        "java.util.Map$Entry": "j$.util.Map$Entry",
-        "java.util.Collection": "j$.util.Collection",
-        "java.util.Map": "j$.util.Map",
-        "java.util.Iterator": "j$.util.Iterator",
-        "java.util.Comparator": "j$.util.Comparator",
-        "java.util.List": "j$.util.List",
-        "java.util.SortedSet": "j$.util.SortedSet",
-        "java.util.Set": "j$.util.Set",
-        "java.util.concurrent.ConcurrentMap": "j$.util.concurrent.ConcurrentMap"
-      },
-      "custom_conversion": {
-        "java.util.Optional": "java.util.OptionalConversions",
-        "java.util.OptionalDouble": "java.util.OptionalConversions",
-        "java.util.OptionalInt": "java.util.OptionalConversions",
-        "java.util.OptionalLong": "java.util.OptionalConversions",
-        "java.util.LongSummaryStatistics": "java.util.LongSummaryStatisticsConversions",
-        "java.util.IntSummaryStatistics": "java.util.IntSummaryStatisticsConversions",
-        "java.util.DoubleSummaryStatistics": "java.util.DoubleSummaryStatisticsConversions"
-      },
       "wrapper_conversion": [
         "java.util.PrimitiveIterator$OfDouble",
         "java.util.PrimitiveIterator$OfInt",
@@ -117,6 +85,14 @@
       "retarget_lib_member": {
         "java.util.Date#toInstant": "java.util.DesugarDate",
         "java.util.GregorianCalendar#toZonedDateTime": "java.util.DesugarGregorianCalendar"
+      },
+      "custom_conversion": {
+        "java.time.ZonedDateTime": "java.time.TimeConversions",
+        "java.time.LocalDate": "java.time.TimeConversions",
+        "java.time.Duration": "java.time.TimeConversions",
+        "java.time.ZoneId": "java.time.TimeConversions",
+        "java.time.MonthDay": "java.time.TimeConversions",
+        "java.time.Instant": "java.time.TimeConversions"
       }
     },
     {
@@ -148,6 +124,30 @@
         "java.util.Arrays#stream": "java.util.DesugarArrays",
         "java.util.Arrays#spliterator": "java.util.DesugarArrays",
         "java.util.LinkedHashSet#spliterator": "java.util.DesugarLinkedHashSet"
+      },
+      "dont_rewrite": [
+        "java.util.Iterator#remove"
+      ],
+      "emulate_interface": {
+        "java.lang.Iterable": "j$.lang.Iterable",
+        "java.util.Map$Entry": "j$.util.Map$Entry",
+        "java.util.Collection": "j$.util.Collection",
+        "java.util.Map": "j$.util.Map",
+        "java.util.Iterator": "j$.util.Iterator",
+        "java.util.Comparator": "j$.util.Comparator",
+        "java.util.List": "j$.util.List",
+        "java.util.SortedSet": "j$.util.SortedSet",
+        "java.util.Set": "j$.util.Set",
+        "java.util.concurrent.ConcurrentMap": "j$.util.concurrent.ConcurrentMap"
+      },
+      "custom_conversion": {
+        "java.util.Optional": "java.util.OptionalConversions",
+        "java.util.OptionalDouble": "java.util.OptionalConversions",
+        "java.util.OptionalInt": "java.util.OptionalConversions",
+        "java.util.OptionalLong": "java.util.OptionalConversions",
+        "java.util.LongSummaryStatistics": "java.util.LongSummaryStatisticsConversions",
+        "java.util.IntSummaryStatistics": "java.util.IntSummaryStatisticsConversions",
+        "java.util.DoubleSummaryStatistics": "java.util.DoubleSummaryStatisticsConversions"
       }
     }
   ],
@@ -164,6 +164,14 @@
         "java.util.Date#toInstant": "java.util.DesugarDate",
         "java.util.GregorianCalendar#from": "java.util.DesugarGregorianCalendar",
         "java.util.GregorianCalendar#toZonedDateTime": "java.util.DesugarGregorianCalendar"
+      },
+      "custom_conversion": {
+        "java.time.ZonedDateTime": "java.time.TimeConversions",
+        "java.time.LocalDate": "java.time.TimeConversions",
+        "java.time.Duration": "java.time.TimeConversions",
+        "java.time.ZoneId": "java.time.TimeConversions",
+        "java.time.MonthDay": "java.time.TimeConversions",
+        "java.time.Instant": "java.time.TimeConversions"
       }
     },
     {
@@ -200,6 +208,30 @@
         "java.util.concurrent.atomic.AtomicReference#accumulateAndGet": "java.util.concurrent.atomic.DesugarAtomicReference",
         "java.util.Collections#synchronizedMap": "java.util.DesugarCollections",
         "java.util.Collections#synchronizedSortedMap": "java.util.DesugarCollections"
+      },
+      "dont_rewrite": [
+        "java.util.Iterator#remove"
+      ],
+      "emulate_interface": {
+        "java.lang.Iterable": "j$.lang.Iterable",
+        "java.util.Map$Entry": "j$.util.Map$Entry",
+        "java.util.Collection": "j$.util.Collection",
+        "java.util.Map": "j$.util.Map",
+        "java.util.Iterator": "j$.util.Iterator",
+        "java.util.Comparator": "j$.util.Comparator",
+        "java.util.List": "j$.util.List",
+        "java.util.SortedSet": "j$.util.SortedSet",
+        "java.util.Set": "j$.util.Set",
+        "java.util.concurrent.ConcurrentMap": "j$.util.concurrent.ConcurrentMap"
+      },
+      "custom_conversion": {
+        "java.util.Optional": "java.util.OptionalConversions",
+        "java.util.OptionalDouble": "java.util.OptionalConversions",
+        "java.util.OptionalInt": "java.util.OptionalConversions",
+        "java.util.OptionalLong": "java.util.OptionalConversions",
+        "java.util.LongSummaryStatistics": "java.util.LongSummaryStatisticsConversions",
+        "java.util.IntSummaryStatistics": "java.util.IntSummaryStatisticsConversions",
+        "java.util.DoubleSummaryStatistics": "java.util.DoubleSummaryStatisticsConversions"
       }
     }
   ],
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfigurationParser.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfigurationParser.java
index 5b57033..a1af388 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfigurationParser.java
@@ -21,10 +21,15 @@
 
 public class DesugaredLibraryConfigurationParser {
 
-  public static final int MAX_SUPPORTED_VERSION = 5;
-  private static final int MIN_SUPPORTED_VERSION = 5;
+  public static final int MAX_SUPPORTED_VERSION = 4;
 
-  private static final String MIN_DESUGARED_LIBRARY_WITH_SUPPORTED_VERSION = "1.0.7";
+  private static final String MIN_DESUGARED_LIBRARY_WITH_COMMON_FLAGS = "1.0.9";
+
+  private static final String UNSUPPORTED_MESSAGE =
+      "Unsupported desugared library version, please upgrade the"
+          + " desugared library to at least version "
+          + MIN_DESUGARED_LIBRARY_WITH_COMMON_FLAGS
+          + ".";
 
   static final String CONFIGURATION_FORMAT_VERSION_KEY = "configuration_format_version";
   static final String VERSION_KEY = "version";
@@ -61,7 +66,6 @@
       Reporter reporter,
       boolean libraryCompilation,
       int minAPILevel) {
-    assert MIN_SUPPORTED_VERSION <= MAX_SUPPORTED_VERSION;
     this.dexItemFactory = dexItemFactory;
     this.reporter = reporter;
     this.minAPILevel = minAPILevel;
@@ -69,11 +73,15 @@
   }
 
   private JsonElement required(JsonObject json, String key) {
+    return required(
+        json,
+        key,
+        "Invalid desugared library configuration. " + "Expected required key '" + key + "'");
+  }
+
+  private JsonElement required(JsonObject json, String key, String message) {
     if (!json.has(key)) {
-      throw reporter.fatalError(
-          new StringDiagnostic(
-              "Invalid desugared library configuration. " + "Expected required key '" + key + "'",
-              origin));
+      throw reporter.fatalError(new StringDiagnostic(message, origin));
     }
     return json.get(key);
   }
@@ -105,15 +113,6 @@
                   + " compiler.",
               origin));
     }
-    if (formatVersion < MIN_SUPPORTED_VERSION) {
-      throw reporter.fatalError(
-          new StringDiagnostic(
-              "Unsupported desugared library version, please upgrade the"
-                  + " desugared library to at least version "
-                  + MIN_DESUGARED_LIBRARY_WITH_SUPPORTED_VERSION
-                  + ".",
-              origin));
-    }
 
     String version = required(jsonConfig, VERSION_KEY).getAsString();
     String groupID = required(jsonConfig, GROUP_ID_KEY).getAsString();
@@ -127,7 +126,7 @@
         required(jsonConfig, REQUIRED_COMPILATION_API_LEVEL_KEY).getAsInt();
     configurationBuilder.setRequiredCompilationAPILevel(
         AndroidApiLevel.getAndroidApiLevel(required_compilation_api_level));
-    JsonElement commonFlags = required(jsonConfig, COMMON_FLAGS_KEY);
+    JsonElement commonFlags = required(jsonConfig, COMMON_FLAGS_KEY, UNSUPPORTED_MESSAGE);
     JsonElement libraryFlags = required(jsonConfig, LIBRARY_FLAGS_KEY);
     JsonElement programFlags = required(jsonConfig, PROGRAM_FLAGS_KEY);
     parseFlagsList(commonFlags.getAsJsonArray());
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BackwardsCompatibleSpecificationTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BackwardsCompatibleSpecificationTest.java
new file mode 100644
index 0000000..54f3acb
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BackwardsCompatibleSpecificationTest.java
@@ -0,0 +1,55 @@
+// Copyright (c) 2020, 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;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestRuntime.NoneRuntime;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.ProcessResult;
+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;
+
+@RunWith(Parameterized.class)
+public class BackwardsCompatibleSpecificationTest extends TestBase {
+
+  private static final List<String> RELEASES = ImmutableList.of("2.0.74");
+
+  @Parameterized.Parameters(name = "{1}")
+  public static List<Object[]> data() {
+    return buildParameters(getTestParameters().withNoneRuntime().build(), RELEASES);
+  }
+
+  private final Path desugaredLib = ToolHelper.getDesugarJDKLibs();
+  private final Path desugaredSpec = ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING;
+  private final String release;
+
+  public BackwardsCompatibleSpecificationTest(TestParameters parameters, String release) {
+    assertEquals(NoneRuntime.getInstance(), parameters.getRuntime());
+    this.release = release;
+  }
+
+  private Path getReleaseJar() {
+    return Paths.get(ToolHelper.THIRD_PARTY_DIR, "r8-releases", release, "r8lib.jar");
+  }
+
+  @Test
+  public void test() throws Exception {
+    ProcessResult result =
+        ToolHelper.runJava(
+            getReleaseJar(),
+            "com.android.tools.r8.L8",
+            "--desugared-lib",
+            desugaredSpec.toString(),
+            desugaredLib.toString());
+    assertEquals(result.toString(), 0, result.exitCode);
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryConfigurationParsingTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryConfigurationParsingTest.java
index 5860d0d..92fc7be 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryConfigurationParsingTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryConfigurationParsingTest.java
@@ -141,7 +141,6 @@
             "version",
             "required_compilation_api_level",
             "synthesized_library_classes_package_prefix",
-            "common_flags",
             "program_flags",
             "library_flags");
     for (String key : requiredKeys) {
@@ -159,9 +158,9 @@
   }
 
   @Test
-  public void testUnsupportedBelow() {
+  public void testUnsupportedFormatMissingFlags() {
     LinkedHashMap<String, Object> data = template();
-    data.put("configuration_format_version", 4);
+    data.remove("common_flags");
     runFailing(
         toJson(data),
         diagnostics ->
diff --git a/third_party/r8-releases/2.0.74.tar.gz.sha1 b/third_party/r8-releases/2.0.74.tar.gz.sha1
new file mode 100644
index 0000000..7359e6d
--- /dev/null
+++ b/third_party/r8-releases/2.0.74.tar.gz.sha1
@@ -0,0 +1 @@
+6903a4fb98ef23da4d40e1b08998a390578dd0ef
\ No newline at end of file