Fixes Android API level support in NDK crosstools.
NDK r19 crosstools incorrectly reported that it supports API level 29.
NDK r21 crosstools was missing API level 30.

Fixes #13421.

PiperOrigin-RevId: 380800055
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/AndroidNdkCrosstools.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/AndroidNdkCrosstools.java
index af96116..d6406d4 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/AndroidNdkCrosstools.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/AndroidNdkCrosstools.java
@@ -24,6 +24,8 @@
 import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r17.NdkMajorRevisionR17;
 import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r18.NdkMajorRevisionR18;
 import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r19.NdkMajorRevisionR19;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r20.NdkMajorRevisionR20;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r21.NdkMajorRevisionR21;
 import com.google.devtools.build.lib.util.OS;
 import java.util.Map;
 
@@ -52,8 +54,8 @@
           .put(17, new NdkMajorRevisionR17("6.0.2"))
           .put(18, new NdkMajorRevisionR18("7.0.2"))
           .put(19, new NdkMajorRevisionR19("8.0.2"))
-          .put(20, new NdkMajorRevisionR19("8.0.7")) // no changes relevant to Bazel
-          .put(21, new NdkMajorRevisionR19("9.0.8")) // no changes relevant to Bazel
+          .put(20, new NdkMajorRevisionR20("8.0.7"))
+          .put(21, new NdkMajorRevisionR21("9.0.8"))
           .build();
 
   public static final Map.Entry<Integer, NdkMajorRevision> LATEST_KNOWN_REVISION =
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/BUILD b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/BUILD
index ad27b68..06db24a 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/BUILD
@@ -15,6 +15,8 @@
         "//src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r17:srcs",
         "//src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r18:srcs",
         "//src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19:srcs",
+        "//src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r20:srcs",
+        "//src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r21:srcs",
     ],
     visibility = ["//src:__subpackages__"],
 )
@@ -35,6 +37,8 @@
         "//src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r17",
         "//src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r18",
         "//src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19",
+        "//src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r20",
+        "//src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r21",
         "//src/main/java/com/google/devtools/build/lib/util:os",
         "//third_party:guava",
     ],
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r18/NdkMajorRevisionR18.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r18/NdkMajorRevisionR18.java
index fe741e1..d2752ff 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r18/NdkMajorRevisionR18.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r18/NdkMajorRevisionR18.java
@@ -21,7 +21,7 @@
 import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CrosstoolRelease;
 
-/** Logic specific to Android NDK R17. */
+/** Logic specific to Android NDK R18. */
 public class NdkMajorRevisionR18 implements NdkMajorRevision {
   private final String clangVersion;
 
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19/AndroidNdkCrosstoolsR19.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19/AndroidNdkCrosstoolsR19.java
index a653213..1d2fdc7 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19/AndroidNdkCrosstoolsR19.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19/AndroidNdkCrosstoolsR19.java
@@ -23,7 +23,7 @@
 import java.util.List;
 
 /** Generates a CrosstoolRelease proto for the Android NDK. */
-final class AndroidNdkCrosstoolsR19 {
+public final class AndroidNdkCrosstoolsR19 {
 
   /**
    * Creates a CrosstoolRelease proto for the Android NDK, given the API level to use and the
@@ -35,7 +35,7 @@
    *
    * @return A CrosstoolRelease for the Android NDK.
    */
-  static CrosstoolRelease create(
+  public static CrosstoolRelease create(
       NdkPaths ndkPaths, StlImpl stlImpl, String hostPlatform, String clangVersion) {
     return CrosstoolRelease.newBuilder()
         .setMajorVersion("android")
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19/ApiLevelR19.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19/ApiLevelR19.java
index a0d0f74..894b7d3 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19/ApiLevelR19.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19/ApiLevelR19.java
@@ -35,7 +35,6 @@
           .putAll("26", "arm", "x86", "arm64", "x86_64")
           .putAll("27", "arm", "x86", "arm64", "x86_64")
           .putAll("28", "arm", "x86", "arm64", "x86_64")
-          .putAll("29", "arm", "x86", "arm64", "x86_64")
           .build();
 
   /** This map fill in the gaps of {@code API_LEVEL_TO_ARCHITECTURES}. */
@@ -54,7 +53,6 @@
           .put("26", "26")
           .put("27", "27")
           .put("28", "28")
-          .put("29", "29")
           .build();
 
   ApiLevelR19(EventHandler eventHandler, String repositoryName, String apiLevel) {
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19/BUILD b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19/BUILD
index 8ad59d4..004f0a9 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19/BUILD
@@ -4,6 +4,8 @@
     default_visibility = ["//src:__subpackages__"],
 )
 
+licenses(["notice"])
+
 filegroup(
     name = "srcs",
     srcs = glob(["*"]),
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19/NdkMajorRevisionR19.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19/NdkMajorRevisionR19.java
index a9eae01..da404b7 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19/NdkMajorRevisionR19.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19/NdkMajorRevisionR19.java
@@ -21,7 +21,7 @@
 import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CrosstoolRelease;
 
-/** Logic specific to Android NDK R17. */
+/** Logic specific to Android NDK R19. */
 public class NdkMajorRevisionR19 implements NdkMajorRevision {
   private final String clangVersion;
 
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r20/ApiLevelR20.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r20/ApiLevelR20.java
new file mode 100644
index 0000000..bfbbac1
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r20/ApiLevelR20.java
@@ -0,0 +1,63 @@
+// Copyright 2021 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r20;
+
+import com.google.common.collect.ImmutableListMultimap;
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.ApiLevel;
+import com.google.devtools.build.lib.events.EventHandler;
+
+/** Class which encodes information from the Android NDK makefiles about API levels. */
+final class ApiLevelR20 extends ApiLevel {
+  /** This is the contents of {@code platforms/android-*} */
+  private static final ImmutableListMultimap<String, String> API_LEVEL_TO_ARCHITECTURES =
+      ImmutableListMultimap.<String, String>builder()
+          .putAll("16", "arm", "x86")
+          .putAll("17", "arm", "x86")
+          .putAll("18", "arm", "x86")
+          .putAll("19", "arm", "x86")
+          .putAll("21", "arm", "x86", "arm64", "x86_64")
+          .putAll("22", "arm", "x86", "arm64", "x86_64")
+          .putAll("23", "arm", "x86", "arm64", "x86_64")
+          .putAll("24", "arm", "x86", "arm64", "x86_64")
+          .putAll("26", "arm", "x86", "arm64", "x86_64")
+          .putAll("27", "arm", "x86", "arm64", "x86_64")
+          .putAll("28", "arm", "x86", "arm64", "x86_64")
+          .putAll("29", "arm", "x86", "arm64", "x86_64")
+          .build();
+
+  /** This map fill in the gaps of {@code API_LEVEL_TO_ARCHITECTURES}. */
+  private static final ImmutableMap<String, String> API_EQUIVALENCIES =
+      ImmutableMap.<String, String>builder()
+          .put("16", "16")
+          .put("17", "16")
+          .put("18", "18")
+          .put("19", "19")
+          .put("20", "19")
+          .put("21", "21")
+          .put("22", "22")
+          .put("23", "23")
+          .put("24", "24")
+          .put("25", "24")
+          .put("26", "26")
+          .put("27", "27")
+          .put("28", "28")
+          .put("29", "29")
+          .build();
+
+  ApiLevelR20(EventHandler eventHandler, String repositoryName, String apiLevel) {
+    super(API_LEVEL_TO_ARCHITECTURES, API_EQUIVALENCIES, eventHandler, repositoryName, apiLevel);
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r20/BUILD b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r20/BUILD
new file mode 100644
index 0000000..7bc15d4
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r20/BUILD
@@ -0,0 +1,25 @@
+load("@rules_java//java:defs.bzl", "java_library")
+
+package(
+    default_visibility = ["//src:__subpackages__"],
+)
+
+licenses(["notice"])
+
+filegroup(
+    name = "srcs",
+    srcs = glob(["*"]),
+    visibility = ["//src:__subpackages__"],
+)
+
+java_library(
+    name = "r20",
+    srcs = glob(["*.java"]),
+    deps = [
+        "//src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools",
+        "//src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19",
+        "//src/main/java/com/google/devtools/build/lib/events",
+        "//src/main/protobuf:crosstool_config_java_proto",
+        "//third_party:guava",
+    ],
+)
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r20/NdkMajorRevisionR20.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r20/NdkMajorRevisionR20.java
new file mode 100644
index 0000000..af3c617
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r20/NdkMajorRevisionR20.java
@@ -0,0 +1,44 @@
+// Copyright 2021 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r20;
+
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.ApiLevel;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.NdkMajorRevision;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.NdkPaths;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.StlImpl;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r19.AndroidNdkCrosstoolsR19;
+import com.google.devtools.build.lib.events.EventHandler;
+import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CrosstoolRelease;
+
+/** Logic specific to Android NDK R20. */
+public class NdkMajorRevisionR20 implements NdkMajorRevision {
+  private final String clangVersion;
+
+  public NdkMajorRevisionR20(String clangVersion) {
+    this.clangVersion = clangVersion;
+  }
+
+  @Override
+  public CrosstoolRelease crosstoolRelease(
+      NdkPaths ndkPaths, StlImpl stlImpl, String hostPlatform) {
+    // NDK r20 is the same as r19 for bazel, other than API level differences below.
+    return AndroidNdkCrosstoolsR19.create(ndkPaths, stlImpl, hostPlatform, clangVersion);
+  }
+
+  @Override
+  public ApiLevel apiLevel(EventHandler eventHandler, String name, String apiLevel) {
+    return new ApiLevelR20(eventHandler, name, apiLevel);
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r21/ApiLevelR21.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r21/ApiLevelR21.java
new file mode 100644
index 0000000..8dc34d6
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r21/ApiLevelR21.java
@@ -0,0 +1,65 @@
+// Copyright 2021 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r21;
+
+import com.google.common.collect.ImmutableListMultimap;
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.ApiLevel;
+import com.google.devtools.build.lib.events.EventHandler;
+
+/** Class which encodes information from the Android NDK makefiles about API levels. */
+final class ApiLevelR21 extends ApiLevel {
+  /** This is the contents of {@code platforms/android-*} */
+  private static final ImmutableListMultimap<String, String> API_LEVEL_TO_ARCHITECTURES =
+      ImmutableListMultimap.<String, String>builder()
+          .putAll("16", "arm", "x86")
+          .putAll("17", "arm", "x86")
+          .putAll("18", "arm", "x86")
+          .putAll("19", "arm", "x86")
+          .putAll("21", "arm", "x86", "arm64", "x86_64")
+          .putAll("22", "arm", "x86", "arm64", "x86_64")
+          .putAll("23", "arm", "x86", "arm64", "x86_64")
+          .putAll("24", "arm", "x86", "arm64", "x86_64")
+          .putAll("26", "arm", "x86", "arm64", "x86_64")
+          .putAll("27", "arm", "x86", "arm64", "x86_64")
+          .putAll("28", "arm", "x86", "arm64", "x86_64")
+          .putAll("29", "arm", "x86", "arm64", "x86_64")
+          .putAll("30", "arm", "x86", "arm64", "x86_64")
+          .build();
+
+  /** This map fill in the gaps of {@code API_LEVEL_TO_ARCHITECTURES}. */
+  private static final ImmutableMap<String, String> API_EQUIVALENCIES =
+      ImmutableMap.<String, String>builder()
+          .put("16", "16")
+          .put("17", "16")
+          .put("18", "18")
+          .put("19", "19")
+          .put("20", "19")
+          .put("21", "21")
+          .put("22", "22")
+          .put("23", "23")
+          .put("24", "24")
+          .put("25", "24")
+          .put("26", "26")
+          .put("27", "27")
+          .put("28", "28")
+          .put("29", "29")
+          .put("30", "30")
+          .build();
+
+  ApiLevelR21(EventHandler eventHandler, String repositoryName, String apiLevel) {
+    super(API_LEVEL_TO_ARCHITECTURES, API_EQUIVALENCIES, eventHandler, repositoryName, apiLevel);
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r21/BUILD b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r21/BUILD
new file mode 100644
index 0000000..6f0328a
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r21/BUILD
@@ -0,0 +1,25 @@
+load("@rules_java//java:defs.bzl", "java_library")
+
+package(
+    default_visibility = ["//src:__subpackages__"],
+)
+
+licenses(["notice"])
+
+filegroup(
+    name = "srcs",
+    srcs = glob(["*"]),
+    visibility = ["//src:__subpackages__"],
+)
+
+java_library(
+    name = "r21",
+    srcs = glob(["*.java"]),
+    deps = [
+        "//src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools",
+        "//src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r19",
+        "//src/main/java/com/google/devtools/build/lib/events",
+        "//src/main/protobuf:crosstool_config_java_proto",
+        "//third_party:guava",
+    ],
+)
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r21/NdkMajorRevisionR21.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r21/NdkMajorRevisionR21.java
new file mode 100644
index 0000000..b0560ce
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r21/NdkMajorRevisionR21.java
@@ -0,0 +1,44 @@
+// Copyright 2021 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r21;
+
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.ApiLevel;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.NdkMajorRevision;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.NdkPaths;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.StlImpl;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r19.AndroidNdkCrosstoolsR19;
+import com.google.devtools.build.lib.events.EventHandler;
+import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CrosstoolRelease;
+
+/** Logic specific to Android NDK R21. */
+public class NdkMajorRevisionR21 implements NdkMajorRevision {
+  private final String clangVersion;
+
+  public NdkMajorRevisionR21(String clangVersion) {
+    this.clangVersion = clangVersion;
+  }
+
+  @Override
+  public CrosstoolRelease crosstoolRelease(
+      NdkPaths ndkPaths, StlImpl stlImpl, String hostPlatform) {
+    // NDK r21 is the same as r19 for bazel, other than API level differences below.
+    return AndroidNdkCrosstoolsR19.create(ndkPaths, stlImpl, hostPlatform, clangVersion);
+  }
+
+  @Override
+  public ApiLevel apiLevel(EventHandler eventHandler, String name, String apiLevel) {
+    return new ApiLevelR21(eventHandler, name, apiLevel);
+  }
+}