Add Proguard-map ID to marker.

Bug: 70040153
Change-Id: I35c50c76d0761c5785f61a6a044ce991b378beda
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 186caee..64bdee0 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -169,10 +169,13 @@
     if (options.hasMarker()) {
       return options.getMarker();
     }
-    Marker marker = new Marker(Tool.R8)
-        .setVersion(Version.LABEL)
-        .setCompilationMode(options.debug ? CompilationMode.DEBUG : CompilationMode.RELEASE)
-        .setMinApi(options.minApiLevel);
+    Marker marker =
+        new Marker(Tool.R8)
+            .setVersion(Version.LABEL)
+            .setCompilationMode(options.debug ? CompilationMode.DEBUG : CompilationMode.RELEASE);
+    if (!options.isGeneratingClassFiles()) {
+      marker.setMinApi(options.minApiLevel);
+    }
     if (Version.isDev()) {
       marker.setSha1(VersionProperties.INSTANCE.getSha());
     }
@@ -191,6 +194,7 @@
       throws ExecutionException {
     try {
       Marker marker = getMarker(options);
+      assert marker != null;
       if (options.isGeneratingClassFiles()) {
         new CfApplicationWriter(
                 application,
@@ -206,7 +210,7 @@
         new ApplicationWriter(
                 application,
                 options,
-                marker == null ? null : Collections.singletonList(marker),
+                Collections.singletonList(marker),
                 deadCode,
                 graphLense,
                 namingLens,
@@ -632,8 +636,7 @@
               namingLens,
               options.lineNumberOptimization == LineNumberOptimization.OFF);
       timing.end();
-      proguardMapSupplier =
-          ProguardMapSupplier.fromClassNameMapper(classNameMapper, options.minApiLevel);
+      proguardMapSupplier = ProguardMapSupplier.fromClassNameMapper(classNameMapper, options);
 
       // If a method filter is present don't produce output since the application is likely partial.
       if (options.hasMethodsFilter()) {
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index 24e82a7..6ba7802 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -64,6 +64,7 @@
   public final NamingLens namingLens;
   public final String proguardSeedsData;
   public final InternalOptions options;
+  public List<Marker> markers;
   public List<DexString> markerStrings;
   public DexIndexedConsumer programConsumer;
   public final ProguardMapSupplier proguardMapSupplier;
@@ -160,12 +161,7 @@
     this.application = application;
     assert options != null;
     this.options = options;
-    if (markers != null && !markers.isEmpty()) {
-      this.markerStrings = new ArrayList<>();
-      for (Marker marker : markers) {
-        this.markerStrings.add(application.dexItemFactory.createString(marker.toString()));
-      }
-    }
+    this.markers = markers;
     this.deadCode = deadCode;
     this.graphLense = graphLense;
     this.namingLens = namingLens;
@@ -195,12 +191,29 @@
 
   public void write(ExecutorService executorService) throws IOException, ExecutionException {
     application.timing.begin("DexApplication.write");
+    ProguardMapSupplier.ProguardMapAndId proguardMapAndId = null;
+    if (proguardMapSupplier != null && options.proguardMapConsumer != null) {
+      proguardMapAndId = proguardMapSupplier.getProguardMapAndId();
+    }
+
+    // If we do have a map then we're called from R8. In that case we have exactly one marker.
+    assert proguardMapAndId == null || (markers != null && markers.size() == 1);
+
+    if (markers != null && !markers.isEmpty()) {
+      if (proguardMapAndId != null) {
+        markers.get(0).setPgMapId(proguardMapAndId.id);
+      }
+      markerStrings = new ArrayList<>(markers.size());
+      for (Marker marker : markers) {
+        markerStrings.add(application.dexItemFactory.createString(marker.toString()));
+      }
+    }
     try {
       insertAttributeAnnotations();
 
       application.dexItemFactory.sort(namingLens);
-      assert this.markerStrings == null
-          || this.markerStrings.isEmpty()
+      assert markers == null
+          || markers.isEmpty()
           || application.dexItemFactory.extractMarker() != null;
 
       SortAnnotations sortAnnotations = new SortAnnotations();
@@ -288,7 +301,7 @@
           namingLens,
           options,
           deadCode,
-          proguardMapSupplier,
+          proguardMapAndId == null ? null : proguardMapAndId.map,
           proguardSeedsData);
     } finally {
       application.timing.end();
@@ -301,7 +314,7 @@
       NamingLens namingLens,
       InternalOptions options,
       String deadCode,
-      ProguardMapSupplier proguardMapSupplier,
+      String proguardMapContent,
       String proguardSeedsData) {
     if (options.configurationConsumer != null) {
       ExceptionUtils.withConsumeResourceHandler(
@@ -312,15 +325,11 @@
       ExceptionUtils.withConsumeResourceHandler(
           options.reporter, options.usageInformationConsumer, deadCode);
     }
-    // Write the proguard map file after writing the dex files, as the map writer traverses
-    // the DexProgramClass structures, which are destructively updated during dex file writing.
-    if (proguardMapSupplier != null && options.proguardMapConsumer != null) {
-      String content = proguardMapSupplier.get();
-      if (content != null) {
-        ExceptionUtils.withConsumeResourceHandler(
-            options.reporter, options.proguardMapConsumer, content);
+    if (proguardMapContent != null) {
+      ExceptionUtils.withConsumeResourceHandler(
+          options.reporter, options.proguardMapConsumer, proguardMapContent);
       }
-    }
+
     if (options.proguardSeedsConsumer != null && proguardSeedsData != null) {
       ExceptionUtils.withConsumeResourceHandler(
           options.reporter, options.proguardSeedsConsumer, proguardSeedsData);
diff --git a/src/main/java/com/android/tools/r8/dex/Marker.java b/src/main/java/com/android/tools/r8/dex/Marker.java
index 3d977f6..66a2d463 100644
--- a/src/main/java/com/android/tools/r8/dex/Marker.java
+++ b/src/main/java/com/android/tools/r8/dex/Marker.java
@@ -21,6 +21,7 @@
   public static final String MIN_API = "min-api";
   public static final String SHA1 = "sha-1";
   public static final String COMPILATION_MODE = "compilation-mode";
+  public static final String PG_MAP_ID = "pg-map-id";
 
   public enum Tool {D8, R8}
 
@@ -93,6 +94,16 @@
     return this;
   }
 
+  public String getPgMapId() {
+    return jsonObject.get(PG_MAP_ID).getAsString();
+  }
+
+  public Marker setPgMapId(String pgMapId) {
+    assert !jsonObject.has(PG_MAP_ID);
+    jsonObject.addProperty(PG_MAP_ID, pgMapId);
+    return this;
+  }
+
   @Override
   public String toString() {
     // In order to make printing of markers deterministic we sort the entries by key.
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index 05120db..8d55a59 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -70,7 +70,7 @@
   private final GraphLense graphLense;
   private final NamingLens namingLens;
   private final InternalOptions options;
-  private final String markerString;
+  private final Marker marker;
 
   public final ProguardMapSupplier proguardMapSupplier;
   public final String deadCode;
@@ -89,7 +89,8 @@
     this.graphLense = graphLense;
     this.namingLens = namingLens;
     this.options = options;
-    this.markerString = marker == null ? null : marker.toString();
+    assert marker != null;
+    this.marker = marker;
     this.proguardMapSupplier = proguardMapSupplier;
     this.deadCode = deadCode;
     this.proguardSeedsData = proguardSeedsData;
@@ -106,9 +107,17 @@
 
   private void writeApplication(ClassFileConsumer consumer, ExecutorService executor)
       throws IOException {
+    ProguardMapSupplier.ProguardMapAndId proguardMapAndId = null;
+    if (proguardMapSupplier != null && options.proguardMapConsumer != null) {
+      proguardMapAndId = proguardMapSupplier.getProguardMapAndId();
+      if (proguardMapAndId != null) {
+        marker.setPgMapId(proguardMapAndId.id);
+      }
+    }
+    String markerString = marker.toString();
     for (DexProgramClass clazz : application.classes()) {
       if (clazz.getSynthesizedFrom().isEmpty()) {
-        writeClass(clazz, consumer);
+        writeClass(clazz, consumer, markerString);
       } else {
         throw new Unimplemented("No support for synthetics in the Java bytecode backend.");
       }
@@ -119,16 +128,14 @@
         namingLens,
         options,
         deadCode,
-        proguardMapSupplier,
+        proguardMapAndId == null ? null : proguardMapAndId.map,
         proguardSeedsData);
   }
 
-  private void writeClass(DexProgramClass clazz, ClassFileConsumer consumer) throws IOException {
+  private void writeClass(DexProgramClass clazz, ClassFileConsumer consumer, String markerString) {
     ClassWriter writer = new ClassWriter(0);
-    if (markerString != null) {
-      int index = writer.newConst(markerString);
-      assert index == MARKER_STRING_CONSTANT_POOL_INDEX;
-    }
+    int markerStringPoolIndex = writer.newConst(markerString);
+    assert markerStringPoolIndex == MARKER_STRING_CONSTANT_POOL_INDEX;
     writer.visitSource(clazz.sourceFile != null ? clazz.sourceFile.toString() : null, null);
     int version = getClassFileVersion(clazz);
     int access = clazz.accessFlags.getAsCfAccessFlags();
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapSupplier.java b/src/main/java/com/android/tools/r8/naming/ProguardMapSupplier.java
index 5ee5891..3b18383 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapSupplier.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapSupplier.java
@@ -5,7 +5,10 @@
 
 import com.android.tools.r8.Version;
 import com.android.tools.r8.graph.DexApplication;
+import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.VersionProperties;
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -18,66 +21,84 @@
   public static final String MARKER_KEY_COMPILER_VERSION = "compiler_version";
   public static final String MARKER_KEY_COMPILER_HASH = "compiler_hash";
   public static final String MARKER_KEY_MIN_API = "min_api";
+  public static final String MARKER_KEY_PG_MAP_ID = "pg_map_id";
+
+  public static int PG_MAP_ID_LENGTH = 7;
 
   public static ProguardMapSupplier fromClassNameMapper(
-      ClassNameMapper classNameMapper, int minApiLevel) {
-    return new ProguardMapSupplier(classNameMapper, minApiLevel);
+      ClassNameMapper classNameMapper, InternalOptions options) {
+    return new ProguardMapSupplier(true, classNameMapper, null, null, options);
   }
 
   public static ProguardMapSupplier fromNamingLens(
-      NamingLens namingLens, DexApplication dexApplication, int minApiLevel) {
-    return new ProguardMapSupplier(namingLens, dexApplication, minApiLevel);
+      NamingLens namingLens, DexApplication dexApplication, InternalOptions options) {
+    return new ProguardMapSupplier(false, null, namingLens, dexApplication, options);
   }
 
-  private ProguardMapSupplier(ClassNameMapper classNameMapper, int minApiLevel) {
-    this.useClassNameMapper = true;
+  public static class ProguardMapAndId {
+    public final String map;
+    public final String id;
+
+    ProguardMapAndId(String map, String id) {
+      assert map != null && id != null;
+      this.map = map;
+      this.id = id;
+    }
+  }
+
+  public ProguardMapSupplier(
+      boolean useClassNameMapper,
+      ClassNameMapper classNameMapper,
+      NamingLens namingLens,
+      DexApplication application,
+      InternalOptions options) {
+    this.useClassNameMapper = useClassNameMapper;
     this.classNameMapper = classNameMapper;
-    this.namingLens = null;
-    this.application = null;
-    this.minApiLevel = minApiLevel;
-  }
-
-  private ProguardMapSupplier(
-      NamingLens namingLens, DexApplication dexApplication, int minApiLevel) {
-    this.useClassNameMapper = false;
-    this.classNameMapper = null;
     this.namingLens = namingLens;
-    this.application = dexApplication;
-    this.minApiLevel = minApiLevel;
+    this.application = application;
+    this.minApiLevel = options.isGeneratingClassFiles() ? null : options.minApiLevel;
   }
 
   private final boolean useClassNameMapper;
   private final ClassNameMapper classNameMapper;
   private final NamingLens namingLens;
   private final DexApplication application;
-  private final int minApiLevel;
+  private final Integer minApiLevel;
 
-  public String get() {
+  public ProguardMapAndId getProguardMapAndId() {
     String body = getBody();
     if (body == null || body.trim().length() == 0) {
       return null;
     }
-    String shaLine = "";
-    if (Version.isDev()) {
-      shaLine = "# " + MARKER_KEY_COMPILER_HASH + ": " + VersionProperties.INSTANCE.getSha() + "\n";
+    // Algorithm:
+    // Hash of the non-whitespace codepoints of the input string.
+    Hasher hasher = Hashing.murmur3_32().newHasher();
+    body.codePoints().filter(c -> !Character.isWhitespace(c)).forEach(hasher::putInt);
+    String proguardMapId = hasher.hash().toString().substring(0, PG_MAP_ID_LENGTH);
+
+    StringBuilder builder = new StringBuilder();
+    builder.append(
+        "# "
+            + MARKER_KEY_COMPILER
+            + ": "
+            + MARKER_VALUE_COMPILER
+            + "\n"
+            + "# "
+            + MARKER_KEY_COMPILER_VERSION
+            + ": "
+            + Version.LABEL
+            + "\n");
+    if (minApiLevel != null) {
+      builder.append("# " + MARKER_KEY_MIN_API + ": " + minApiLevel + "\n");
     }
-    return "# "
-        + MARKER_KEY_COMPILER
-        + ": "
-        + MARKER_VALUE_COMPILER
-        + "\n"
-        + "# "
-        + MARKER_KEY_COMPILER_VERSION
-        + ": "
-        + Version.LABEL
-        + "\n"
-        + "# "
-        + MARKER_KEY_MIN_API
-        + ": "
-        + minApiLevel
-        + "\n"
-        + shaLine
-        + body;
+    if (Version.isDev()) {
+      builder.append(
+          "# " + MARKER_KEY_COMPILER_HASH + ": " + VersionProperties.INSTANCE.getSha() + "\n");
+    }
+    builder.append("# " + MARKER_KEY_PG_MAP_ID + ": " + proguardMapId + "\n");
+    builder.append(body);
+
+    return new ProguardMapAndId(builder.toString(), proguardMapId);
   }
 
   private String getBody() {
diff --git a/src/test/java/com/android/tools/r8/ExtractMarkerTest.java b/src/test/java/com/android/tools/r8/ExtractMarkerTest.java
index 6a47607..948ab96 100644
--- a/src/test/java/com/android/tools/r8/ExtractMarkerTest.java
+++ b/src/test/java/com/android/tools/r8/ExtractMarkerTest.java
@@ -14,14 +14,22 @@
 import org.junit.Test;
 
 public class ExtractMarkerTest {
+  private static final String CLASS_FILE =
+      ToolHelper.EXAMPLES_BUILD_DIR + "classes/trivial/Trivial.class";
+
+  private static void verifyMarker(Marker marker, Tool tool) {
+    assertEquals(tool, marker.getTool());
+    assertEquals(Version.LABEL, marker.getVersion());
+    assertEquals(CompilationMode.DEBUG.toString().toLowerCase(), marker.getCompilationMode());
+  }
 
   @Test
   public void extractMarkerTestDex() throws CompilationFailedException {
-    String classFile = ToolHelper.EXAMPLES_BUILD_DIR + "classes/trivial/Trivial.class";
     boolean[] testExecuted = {false};
+
     D8.run(
         D8Command.builder()
-            .addProgramFiles(Paths.get(classFile))
+            .addProgramFiles(Paths.get(CLASS_FILE))
             .setProgramConsumer(
                 new DexIndexedConsumer.ForwardingConsumer(null) {
                   @Override
@@ -39,11 +47,7 @@
                     } catch (Exception e) {
                       throw new RuntimeException(e);
                     }
-                    assertEquals(Tool.D8, marker.getTool());
-                    assertEquals(Version.LABEL, marker.getVersion());
-                    assertEquals(
-                        CompilationMode.DEBUG.toString().toLowerCase(),
-                        marker.getCompilationMode());
+                    verifyMarker(marker, Tool.D8);
                     testExecuted[0] = true;
                   }
                 })
@@ -53,11 +57,10 @@
 
   @Test
   public void extractMarkerTestCf() throws CompilationFailedException {
-    String classFile = ToolHelper.EXAMPLES_BUILD_DIR + "classes/trivial/Trivial.class";
     boolean[] testExecuted = {false};
     R8.run(
         R8Command.builder()
-            .addProgramFiles(Paths.get(classFile))
+            .addProgramFiles(Paths.get(CLASS_FILE))
             .addLibraryFiles(ToolHelper.getJava8RuntimeJar())
             .setMode(CompilationMode.DEBUG)
             .setDisableTreeShaking(true)
@@ -75,11 +78,7 @@
                     } catch (Exception e) {
                       throw new RuntimeException(e);
                     }
-                    assertEquals(Tool.R8, marker.getTool());
-                    assertEquals(Version.LABEL, marker.getVersion());
-                    assertEquals(
-                        CompilationMode.DEBUG.toString().toLowerCase(),
-                        marker.getCompilationMode());
+                    verifyMarker(marker, Tool.R8);
                     testExecuted[0] = true;
                   }
                 })
diff --git a/src/test/java/com/android/tools/r8/ProguardMapMarkerTest.java b/src/test/java/com/android/tools/r8/ProguardMapMarkerTest.java
index 6310054..c5961e8 100644
--- a/src/test/java/com/android/tools/r8/ProguardMapMarkerTest.java
+++ b/src/test/java/com/android/tools/r8/ProguardMapMarkerTest.java
@@ -6,55 +6,126 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.dex.Marker;
 import com.android.tools.r8.naming.ProguardMapSupplier;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.VersionProperties;
 import java.nio.file.Paths;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.Set;
 import org.junit.Test;
 
 public class ProguardMapMarkerTest {
+  private static final int EXPECTED_NUMBER_OF_KEYS_DEX = 5;
+  private static final int EXPECTED_NUMBER_OF_KEYS_CF = 4;
+  private static final String CLASS_FILE =
+      ToolHelper.EXAMPLES_BUILD_DIR + "classes/trivial/Trivial.class";
+
   @Test
   public void proguardMapMarkerTest24() throws CompilationFailedException {
-    proguardMapMarkerTest(AndroidApiLevel.N);
+    proguardMapMarkerTestDex(AndroidApiLevel.N);
   }
 
   @Test
   public void proguardMapMarkerTest26() throws CompilationFailedException {
-    proguardMapMarkerTest(AndroidApiLevel.O);
+    proguardMapMarkerTestDex(AndroidApiLevel.O);
   }
 
-  private void proguardMapMarkerTest(AndroidApiLevel minApiLevel) throws CompilationFailedException {
-    String classFile = ToolHelper.EXAMPLES_BUILD_DIR + "classes/trivial/Trivial.class";
+  private static class ProguardMapIds {
+    String fromProgram = null;
+    String fromMap = null;
+  }
+
+  private void proguardMapMarkerTestDex(AndroidApiLevel minApiLevel)
+      throws CompilationFailedException {
+    ProguardMapIds proguardMapIds = new ProguardMapIds();
     R8.run(
         R8Command.builder()
-            .addProgramFiles(Paths.get(classFile))
+            .addProgramFiles(Paths.get(CLASS_FILE))
+            .setDisableTreeShaking(true)
             .setProgramConsumer(
-                new DexIndexedConsumer() {
+                new DexIndexedConsumer.ForwardingConsumer(null) {
                   @Override
                   public void accept(
                       int fileIndex,
                       ByteDataView data,
                       Set<String> descriptors,
-                      DiagnosticsHandler handler) {}
-
-                  @Override
-                  public void finished(DiagnosticsHandler handler) {}
+                      DiagnosticsHandler handler) {
+                    Marker marker;
+                    try {
+                      Collection<Marker> markers =
+                          ExtractMarker.extractMarkerFromDexProgramData(data.copyByteData());
+                      assertEquals(1, markers.size());
+                      marker = markers.iterator().next();
+                    } catch (Exception e) {
+                      throw new RuntimeException(e);
+                    }
+                    proguardMapIds.fromProgram = marker.getPgMapId();
+                  }
                 })
             .addLibraryFiles(ToolHelper.getAndroidJar(minApiLevel))
             .setMinApiLevel(minApiLevel.getLevel())
             .setProguardMapConsumer(
                 (proguardMap, handler) -> {
-                  verifyMarkers(proguardMap, minApiLevel.getLevel());
+                  proguardMapIds.fromMap =
+                      verifyMarkersGetPgMapId(
+                          proguardMap, minApiLevel.getLevel(), EXPECTED_NUMBER_OF_KEYS_DEX);
                 })
             .build());
+    verifyProguardMapIds(proguardMapIds);
   }
 
-  private static void verifyMarkers(String proguardMap, int minApiLevel) {
+  private void verifyProguardMapIds(ProguardMapIds proguardMapIds) {
+    assertTrue(
+        proguardMapIds.fromProgram != null
+            && proguardMapIds.fromProgram.length() == ProguardMapSupplier.PG_MAP_ID_LENGTH);
+    assertTrue(proguardMapIds.fromMap != null);
+    assertEquals(proguardMapIds.fromMap, proguardMapIds.fromProgram);
+  }
+
+  @Test
+  public void proguardMapMarkerTestCf() throws CompilationFailedException {
+    ProguardMapIds buildIds = new ProguardMapIds();
+    R8.run(
+        R8Command.builder()
+            .addProgramFiles(Paths.get(CLASS_FILE))
+            .setDisableTreeShaking(true)
+            .setProgramConsumer(
+                new ClassFileConsumer.ForwardingConsumer(null) {
+                  @Override
+                  public void accept(
+                      ByteDataView data, String descriptor, DiagnosticsHandler handler) {
+                    Marker marker;
+                    try {
+                      Collection<Marker> markers =
+                          ExtractMarker.extractMarkerFromClassProgramData(data.copyByteData());
+                      assertEquals(1, markers.size());
+                      marker = markers.iterator().next();
+                    } catch (Exception e) {
+                      throw new RuntimeException(e);
+                    }
+                    buildIds.fromProgram = marker.getPgMapId();
+                  }
+                })
+            .addLibraryFiles(ToolHelper.getJava8RuntimeJar())
+            .setProguardMapConsumer(
+                (proguardMap, handler) -> {
+                  buildIds.fromMap =
+                      verifyMarkersGetPgMapId(proguardMap, null, EXPECTED_NUMBER_OF_KEYS_CF);
+                })
+            .build());
+    verifyProguardMapIds(buildIds);
+  }
+
+  private static String verifyMarkersGetPgMapId(
+      String proguardMap, Integer minApiLevel, int expectedNumberOfKeys) {
     String[] lines = proguardMap.split("\n");
     Set<String> keysFound = new HashSet<>();
+    String proguardMapId = null;
     for (String line : lines) {
       if (!line.startsWith("#")) {
         continue;
@@ -71,14 +142,19 @@
       } else if (key.equals(ProguardMapSupplier.MARKER_KEY_COMPILER_VERSION)) {
         assertEquals(Version.LABEL, value);
       } else if (key.equals(ProguardMapSupplier.MARKER_KEY_MIN_API)) {
-        assertEquals(minApiLevel, Integer.parseInt(value));
+        assertNotNull(minApiLevel);
+        assertEquals(minApiLevel.intValue(), Integer.parseInt(value));
       } else if (key.equals(ProguardMapSupplier.MARKER_KEY_COMPILER_HASH)) {
         assertEquals(VersionProperties.INSTANCE.getSha(), value);
+      } else if (key.equals(ProguardMapSupplier.MARKER_KEY_PG_MAP_ID)) {
+        proguardMapId = value;
       } else {
         continue;
       }
       assertFalse(keysFound.contains(key));
       keysFound.add(key);
     }
+    assertEquals(expectedNumberOfKeys, keysFound.size());
+    return proguardMapId;
   }
 }