Expose the native libs of the android_binary rule to skylark.

RELNOTES: none
PiperOrigin-RevId: 153223511
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
index 52c1b52..7fbe3a2 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
@@ -799,7 +799,13 @@
         debugKeystore);
 
     androidCommon.addTransitiveInfoProviders(
-        builder, androidSemantics, null /* aar */, resourceApk, zipAlignedApk, apksUnderTest);
+        builder,
+        androidSemantics,
+        null /* aar */,
+        resourceApk,
+        zipAlignedApk,
+        apksUnderTest,
+        nativeLibs);
     androidSemantics.addTransitiveInfoProviders(builder, ruleContext, javaCommon, androidCommon);
 
     if (proguardOutput.getMapping() != null) {
@@ -909,7 +915,7 @@
     }
 
     if (ruleContext.getFragment(AndroidConfiguration.class).useIncrementalNativeLibs()) {
-      for (Map.Entry<String, Iterable<Artifact>> arch : nativeLibs.getMap().entrySet()) {
+      for (Map.Entry<String, NestedSet<Artifact>> arch : nativeLibs.getMap().entrySet()) {
         for (Artifact lib : arch.getValue()) {
           builder
               .addArgument("--native_lib")
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
index ab6878c..279f252 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
@@ -233,13 +233,15 @@
       Artifact aar,
       ResourceApk resourceApk,
       Artifact zipAlignedApk,
-      Iterable<Artifact> apksUnderTest) {
+      Iterable<Artifact> apksUnderTest,
+      NativeLibs nativeLibs) {
     AndroidIdeInfoProvider.Builder ideInfoProviderBuilder =
         new AndroidIdeInfoProvider.Builder()
             .setIdlClassJar(idlHelper.getIdlClassJar())
             .setIdlSourceJar(idlHelper.getIdlSourceJar())
             .setResourceJar(resourceJar)
             .setAar(aar)
+            .setNativeLibs(nativeLibs.getMap())
             .addIdlImportRoot(idlHelper.getIdlImportRoot())
             .addIdlParcelables(idlHelper.getIdlParcelables())
             .addIdlSrcs(idlHelper.getIdlSources())
@@ -703,7 +705,8 @@
       Artifact aar,
       ResourceApk resourceApk,
       Artifact zipAlignedApk,
-      Iterable<Artifact> apksUnderTest) {
+      Iterable<Artifact> apksUnderTest,
+      NativeLibs nativeLibs) {
 
     idlHelper.addTransitiveInfoProviders(builder, classJar, manifestProtoOutput);
 
@@ -757,7 +760,8 @@
                 aar,
                 resourceApk,
                 zipAlignedApk,
-                apksUnderTest))
+                apksUnderTest,
+                nativeLibs))
         .add(JavaCompilationArgsProvider.class, compilationArgsProvider)
         .addSkylarkTransitiveInfo(AndroidSkylarkApiProvider.NAME, new AndroidSkylarkApiProvider())
         .addOutputGroup(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidIdeInfoProvider.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidIdeInfoProvider.java
index c73eb96..cc5b9bb 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidIdeInfoProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidIdeInfoProvider.java
@@ -16,21 +16,22 @@
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableCollection;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.Root;
 import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.packages.AttributeMap;
 import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider.OutputJar;
 import com.google.devtools.build.lib.util.Preconditions;
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.util.Collection;
 import java.util.LinkedHashSet;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /**
@@ -140,6 +141,7 @@
     private final Set<Artifact> apksUnderTest = new LinkedHashSet<>();
     private boolean definesAndroidResources;
     private Artifact aar = null;
+    private Map<String, NestedSet<Artifact>> nativeLibs = null;
 
     public AndroidIdeInfoProvider build() {
       return new AndroidIdeInfoProvider(
@@ -158,7 +160,10 @@
           ImmutableList.copyOf(idlDirs),
           ImmutableList.copyOf(idlSrcs),
           ImmutableList.copyOf(idlGeneratedJavaFiles),
-          ImmutableList.copyOf(apksUnderTest));
+          ImmutableList.copyOf(apksUnderTest),
+          nativeLibs != null
+              ? ImmutableMap.copyOf(nativeLibs)
+              : ImmutableMap.<String, NestedSet<Artifact>>of());
     }
 
     public Builder setJavaPackage(String javaPackage) {
@@ -211,6 +216,12 @@
       return this;
     }
 
+    public Builder setNativeLibs(Map<String, NestedSet<Artifact>> nativeLibs) {
+      this.nativeLibs = nativeLibs;
+      return this;
+    }
+
+
     public Builder addIdlImportRoot(String idlImportRoot) {
       this.idlImportRoot = idlImportRoot;
       return this;
@@ -293,7 +304,6 @@
       Iterables.addAll(apksUnderTest, apks);
       return this;
     }
-
   }
 
   private final String javaPackage;
@@ -312,6 +322,7 @@
   private final ImmutableCollection<Artifact> idlSrcs;
   private final ImmutableCollection<Artifact> idlGeneratedJavaFiles;
   private final ImmutableCollection<Artifact> apksUnderTest;
+  private final ImmutableMap<String, NestedSet<Artifact>> nativeLibs;
 
   AndroidIdeInfoProvider(
       String javaPackage,
@@ -329,7 +340,8 @@
       ImmutableCollection<SourceDirectory> idlImports,
       ImmutableCollection<Artifact> idlSrcs,
       ImmutableCollection<Artifact> idlGeneratedJavaFiles,
-      ImmutableCollection<Artifact> apksUnderTest) {
+      ImmutableCollection<Artifact> apksUnderTest,
+      ImmutableMap<String, NestedSet<Artifact>> nativeLibs) {
     this.javaPackage = javaPackage;
     this.idlImportRoot = idlImportRoot;
     this.manifest = manifest;
@@ -346,6 +358,7 @@
     this.idlSrcs = idlSrcs;
     this.idlGeneratedJavaFiles = idlGeneratedJavaFiles;
     this.apksUnderTest = apksUnderTest;
+    this.nativeLibs = nativeLibs;
   }
 
   /** Returns java package for this target. */
@@ -433,4 +446,9 @@
   public ImmutableCollection<Artifact> getApksUnderTest() {
     return apksUnderTest;
   }
+
+  /** A map, keyed on architecture, of the native libs for the app, if any. */
+  public ImmutableMap<String, NestedSet<Artifact>> getNativeLibs() {
+    return nativeLibs;
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java
index 5f0da5f..0648e10 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java
@@ -195,8 +195,14 @@
       .build(ruleContext);
 
     RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(ruleContext);
-    androidCommon.addTransitiveInfoProviders(builder, androidSemantics, aarOut,
-        resourceApk, null, ImmutableList.<Artifact>of());
+    androidCommon.addTransitiveInfoProviders(
+        builder,
+        androidSemantics,
+        aarOut,
+        resourceApk,
+        null,
+        ImmutableList.<Artifact>of(),
+        NativeLibs.EMPTY);
     androidSemantics.addTransitiveInfoProviders(builder, ruleContext, javaCommon, androidCommon);
 
     NestedSetBuilder<Artifact> transitiveResourcesJars = collectTransitiveResourceJars(ruleContext);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkApiProvider.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkApiProvider.java
index 4ca0f5b..90d10291 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkApiProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkApiProvider.java
@@ -16,6 +16,7 @@
 import com.google.common.base.Function;
 import com.google.common.collect.ImmutableCollection;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
@@ -95,6 +96,18 @@
   }
 
   @SkylarkCallable(
+    name = "native_libs",
+    structField = true,
+    doc =
+        "Returns the native libraries as a map of the libraries' architecture as a String to a "
+            + "set of the native library artifacts, or the empty map if there are no native "
+            + "libraries."
+  )
+  public ImmutableMap<String, NestedSet<Artifact>> getNativeLibs() {
+    return getIdeInfoProvider().getNativeLibs();
+  }
+
+  @SkylarkCallable(
       name = "apks_under_test",
       structField = true,
       allowReturnNones = true,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ApkManifestAction.java b/src/main/java/com/google/devtools/build/lib/rules/android/ApkManifestAction.java
index e8753ce..4ab7f74 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ApkManifestAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ApkManifestAction.java
@@ -23,13 +23,13 @@
 import com.google.devtools.build.lib.analysis.FilesToRunProvider;
 import com.google.devtools.build.lib.analysis.actions.AbstractFileWriteAction;
 import com.google.devtools.build.lib.collect.CollectionUtils;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.rules.android.apkmanifest.ApkManifestOuterClass;
 import com.google.devtools.build.lib.rules.android.apkmanifest.ApkManifestOuterClass.ApkManifest;
 import com.google.devtools.build.lib.util.Fingerprint;
 import com.google.protobuf.ByteString;
 import com.google.protobuf.TextFormat;
-
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintStream;
@@ -59,7 +59,6 @@
         .add(sdk.getResourceExtractor().getExecutable())
         .add(sdk.getShrinkedAndroidJar())
         .add(sdk.getZipalign().getExecutable())
-        
         .addAll(jars)
         .add(resourceApk.getArtifact())
         .add(resourceApk.getManifest())
@@ -185,7 +184,7 @@
       manifestBuilder.setResourceApk(makeArtifactProto(resourceApk.getArtifact()));
       manifestBuilder.setAndroidManifest(makeArtifactProto(resourceApk.getManifest()));
 
-      for (Map.Entry<String, Iterable<Artifact>> nativeLib : nativeLibs.getMap().entrySet()) {
+      for (Map.Entry<String, NestedSet<Artifact>> nativeLib : nativeLibs.getMap().entrySet()) {
         if (!Iterables.isEmpty(nativeLib.getValue())) {
           manifestBuilder.addNativeLibBuilder()
               .setArch(nativeLib.getKey())
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java b/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java
index 48783e6..32a7c72 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java
@@ -28,6 +28,7 @@
 import com.google.devtools.build.lib.analysis.actions.SymlinkTreeAction;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.rules.cpp.CcLinkParams;
 import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider;
@@ -48,7 +49,7 @@
 @Immutable
 public final class NativeLibs {
   public static final NativeLibs EMPTY =
-      new NativeLibs(ImmutableMap.<String, Iterable<Artifact>>of(), null);
+      new NativeLibs(ImmutableMap.<String, NestedSet<Artifact>>of(), null);
 
   public static NativeLibs fromLinkedNativeDeps(
       RuleContext ruleContext,
@@ -57,7 +58,7 @@
       Map<String, CcToolchainProvider> toolchainMap,
       Map<String, BuildConfiguration> configurationMap)
       throws InterruptedException {
-    Map<String, Iterable<Artifact>> result = new LinkedHashMap<>();
+    Map<String, NestedSet<Artifact>> result = new LinkedHashMap<>();
     String nativeDepsLibraryBasename = null;
     for (Map.Entry<String, Collection<TransitiveInfoCollection>> entry :
         depsByArchitecture.asMap().entrySet()) {
@@ -74,14 +75,14 @@
               configurationMap.get(entry.getKey()),
               toolchainMap.get(entry.getKey()));
 
-      ImmutableList.Builder<Artifact> librariesBuilder = ImmutableList.builder();
+      NestedSetBuilder<Artifact> librariesBuilder = NestedSetBuilder.stableOrder();
       if (nativeDepsLibrary != null) {
         librariesBuilder.add(nativeDepsLibrary);
         nativeDepsLibraryBasename = nativeDepsLibrary.getExecPath().getBaseName();
       }
       librariesBuilder.addAll(
           filterUniqueSharedLibraries(ruleContext, nativeDepsLibrary, linkParams.getLibraries()));
-      ImmutableList<Artifact> libraries = librariesBuilder.build();
+      NestedSet<Artifact> libraries = librariesBuilder.build();
 
       if (!libraries.isEmpty()) {
         result.put(entry.getKey(), libraries);
@@ -106,21 +107,21 @@
   }
 
   // Map from architecture (CPU folder to place the library in) to libraries for that CPU
-  private final ImmutableMap<String, Iterable<Artifact>> nativeLibs;
+  private final ImmutableMap<String, NestedSet<Artifact>> nativeLibs;
   @Nullable private final Artifact nativeLibsName;
 
   @VisibleForTesting
-  NativeLibs(ImmutableMap<String, Iterable<Artifact>> nativeLibs,
-      @Nullable Artifact nativeLibsName) {
+  NativeLibs(
+      ImmutableMap<String, NestedSet<Artifact>> nativeLibs, @Nullable Artifact nativeLibsName) {
     this.nativeLibs = nativeLibs;
     this.nativeLibsName = nativeLibsName;
   }
 
   /**
    * Returns a map from the name of the architecture (CPU folder to place the library in) to the
-   * set of libraries for that architecture.
+   * nested set of libraries for that architecture.
    */
-  public Map<String, Iterable<Artifact>> getMap() {
+  public Map<String, NestedSet<Artifact>> getMap() {
     return nativeLibs;
   }
 
@@ -136,7 +137,7 @@
 
   public Pair<Artifact, Runfiles> createApkBuilderSymlinks(RuleContext ruleContext) {
     Map<PathFragment, Artifact> symlinks = new LinkedHashMap<>();
-    for (Map.Entry<String, Iterable<Artifact>> entry : nativeLibs.entrySet()) {
+    for (Map.Entry<String, NestedSet<Artifact>> entry : nativeLibs.entrySet()) {
       String arch = entry.getKey();
       for (Artifact lib : entry.getValue()) {
         symlinks.put(PathFragment.create(arch + "/" + lib.getExecPath().getBaseName()), lib);
@@ -216,7 +217,7 @@
                 + artifact.prettyPrint()
                 + " and "
                 + oldArtifact.prettyPrint()
-                + ((oldArtifact == linkedLibrary)
+                + ((oldArtifact.equals(linkedLibrary))
                     ? " (the library compiled for this target)"
                     : ""));
       }
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/ApkManifestActionTest.java b/src/test/java/com/google/devtools/build/lib/rules/android/ApkManifestActionTest.java
index 392c9e6..63d0589 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/android/ApkManifestActionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/ApkManifestActionTest.java
@@ -24,6 +24,8 @@
 import com.google.devtools.build.lib.analysis.FilesToRunProvider;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
 import com.google.devtools.build.lib.vfs.FileSystem;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.vfs.util.FileSystems;
@@ -87,11 +89,16 @@
         null, // mainDexProguardConfig
         false /* legacy */);
 
-    NativeLibs nativeLibs = new NativeLibs(
-        ImmutableMap.<String, Iterable<Artifact>>of(
-            "x86", ImmutableList.of(createArtifact("/workspace/java/test/x86.so")),
-            "arm", ImmutableList.of(createArtifact("/workspace/java/test/arm.so"))),
-        null /* nativeLibsName */);
+    NativeLibs nativeLibs =
+        new NativeLibs(
+            ImmutableMap.<String, NestedSet<Artifact>>of(
+                "x86", NestedSetBuilder.<Artifact>stableOrder()
+                    .add(createArtifact("/workspace/java/test/x86.so"))
+                    .build(),
+                "arm", NestedSetBuilder.<Artifact>stableOrder()
+                    .add(createArtifact("/workspace/java/test/arm.so"))
+                    .build()),
+            null /* nativeLibsName */);
 
     Artifact debugKeystore = createArtifact("/workspace/tools/android/debug_keystore");