Differentiate dexing and desugaring artifacts based on the minsdk

PiperOrigin-RevId: 454746208
Change-Id: I3118ec2bc345ac2a2b1b12bc7e35ab9eed9448c1
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/DexArchiveAspect.java b/src/main/java/com/google/devtools/build/lib/rules/android/DexArchiveAspect.java
index 2c837a8..1578a06 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/DexArchiveAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/DexArchiveAspect.java
@@ -272,15 +272,19 @@
     if (runtimeJars != null) {
       boolean basenameClash = checkBasenameClash(runtimeJars);
       Set<Set<String>> aspectDexopts = aspectDexopts(ruleContext);
+      String minSdkFilenamePart = minSdkVersion > 0 ? "--min_sdk_version=" + minSdkVersion : "";
       for (Artifact jar : runtimeJars) {
         for (Set<String> incrementalDexopts : aspectDexopts) {
           // Since we're potentially dexing the same jar multiple times with different flags, we
           // need to write unique artifacts for each flag combination. Here, it is convenient to
           // distinguish them by putting the flags that were used for creating the artifacts into
-          // their filenames.
+          // their filenames. Since min_sdk_version is a parameter to the aspect from the
+          // android_binary target that the aspect originates from, it's handled separately so that
+          // the correct min sdk value is used.
           String uniqueFilename =
               (basenameClash ? jar.getRootRelativePathString() : jar.getFilename())
                   + Joiner.on("").join(incrementalDexopts)
+                  + minSdkFilenamePart
                   + ".dex.zip";
           Artifact dexArchive =
               createDexArchiveAction(
@@ -486,6 +490,8 @@
       NestedSet<Artifact> bootclasspath,
       NestedSet<Artifact> compileTimeClasspath,
       int minSdkVersion) {
+
+    String minSdkFilenamePart = minSdkVersion > 0 ? "_minsdk=" + minSdkVersion : "";
     return createDesugarAction(
         ruleContext,
         ASPECT_DESUGAR_PREREQ,
@@ -496,6 +502,7 @@
         AndroidBinary.getDxArtifact(
             ruleContext,
             (disambiguateBasenames ? jar.getRootRelativePathString() : jar.getFilename())
+                + minSdkFilenamePart
                 + "_desugared.jar"));
   }
 
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java
index f0f6b3c..d6e3ba1 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java
@@ -14,6 +14,7 @@
 package com.google.devtools.build.lib.rules.android;
 
 import static com.google.common.collect.ImmutableList.toImmutableList;
+import static com.google.common.collect.ImmutableMap.toImmutableMap;
 import static com.google.common.collect.Iterables.getOnlyElement;
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
@@ -37,6 +38,7 @@
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.FailAction;
 import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
+import com.google.devtools.build.lib.analysis.AnalysisResult;
 import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.FileProvider;
@@ -74,6 +76,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
+import java.util.function.Function;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -784,6 +787,71 @@
     assertThat(args).contains("28");
   }
 
+  @Test
+  public void testSimpleAndroidBinary_multipleMinSdkVersionOnSameLibrary() throws Exception {
+    scratch.overwriteFile(
+        "java/android/BUILD",
+        "android_binary(name = 'app1',",
+        "               srcs = ['A.java'],",
+        "               deps = ['lib'],",
+        "               manifest = 'AndroidManifest.xml',",
+        "               resource_files = glob(['res/**']),",
+        "              )",
+        "android_binary(name = 'app2',",
+        "               srcs = ['B.java'],",
+        "               deps = ['lib'],",
+        "               manifest = 'AndroidManifest.xml',",
+        "               resource_files = glob(['res/**']),",
+        "               min_sdk_version = 28,",
+        "              )",
+        "android_library(name = 'lib',",
+        "                srcs = ['C.java'])");
+    AnalysisResult result =
+        update(
+            ImmutableList.of("//java/android:app1", "//java/android:app2"),
+            /* keepGoing= */ true,
+            /* loadingPhaseThreads= */ 1,
+            /* doAnalysis= */ true,
+            eventBus);
+
+    ImmutableMap<String, ConfiguredTarget> targets =
+        result.getTargetsToBuild().stream()
+            .collect(toImmutableMap(ct -> ct.getLabel().toString(), Function.identity()));
+
+    ConfiguredTarget app1 = targets.get("//java/android:app1");
+    ConfiguredTarget app2 = targets.get("//java/android:app2");
+
+    // The "lib" target is built twice: once with the default minsdk from app1, and again with
+    // min_sdk_version = 28 from app2.
+
+    List<String> libDesugarNoMinSdkArgs =
+        getGeneratingSpawnActionArgs(
+            ActionsTestUtil.getFirstArtifactEndingWith(
+                actionsTestUtil().artifactClosureOf(getFilesToBuild(app1)),
+                "/liblib.jar_desugared.jar"));
+    assertThat(libDesugarNoMinSdkArgs).doesNotContain("--min_sdk_version");
+
+    List<String> libDexNoMinSdkArgs =
+        getGeneratingSpawnActionArgs(
+            ActionsTestUtil.getFirstArtifactEndingWith(
+                actionsTestUtil().artifactClosureOf(getFilesToBuild(app1)), "/liblib.jar.dex.zip"));
+    assertThat(libDexNoMinSdkArgs).doesNotContain("--min_sdk_version");
+
+    List<String> libDesugarWithMinSdkArgs =
+        getGeneratingSpawnActionArgs(
+            ActionsTestUtil.getFirstArtifactEndingWith(
+                actionsTestUtil().artifactClosureOf(getFilesToBuild(app2)),
+                "/liblib.jar_minsdk=28_desugared.jar"));
+    assertThat(libDesugarWithMinSdkArgs).containsAtLeast("--min_sdk_version", "28").inOrder();
+
+    List<String> libDexWithMinSdkArgs =
+        getGeneratingSpawnActionArgs(
+            ActionsTestUtil.getFirstArtifactEndingWith(
+                actionsTestUtil().artifactClosureOf(getFilesToBuild(app2)),
+                "liblib.jar--min_sdk_version=28.dex.zip"));
+    assertThat(libDexWithMinSdkArgs).containsAtLeast("--min_sdk_version", "28").inOrder();
+  }
+
   // regression test for #3169099
   @Test
   public void testBinarySrcs() throws Exception {