Migrate android providers to use BuiltinProvider instead of NativeProvider

RELNOTES: None.
PiperOrigin-RevId: 200096226
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index ca706fc..f69a2c8 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -975,6 +975,19 @@
   }
 
   /**
+   * Returns the declared provider (native and Skylark) for the specified constructor under the
+   * specified attribute of this target in the BUILD file. May return null if there is no
+   * TransitiveInfoCollection under the specified attribute.
+   */
+  @Nullable
+  public <T extends Info> T getPrerequisite(
+      String attributeName, Mode mode, final BuiltinProvider<T> skylarkKey) {
+    TransitiveInfoCollection prerequisite = getPrerequisite(attributeName, mode);
+    return prerequisite == null ? null : prerequisite.get(skylarkKey);
+  }
+
+
+  /**
    * Returns all the providers of the specified type that are listed under the specified attribute
    * of this target in the BUILD file, and that contain the specified provider.
    */
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
index ec2aafa..ed94e47 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
@@ -309,15 +309,15 @@
           builder.addRuleDefinition(new AndroidHostServiceFixtureRule());
 
           builder.addSkylarkAccessibleTopLevels("android_common", new AndroidSkylarkCommon());
-          builder.addSkylarkAccessibleTopLevels(ApkInfo.PROVIDER.getName(), ApkInfo.PROVIDER);
+          builder.addSkylarkAccessibleTopLevels(ApkInfo.NAME, ApkInfo.PROVIDER);
           builder.addSkylarkAccessibleTopLevels(
-              AndroidInstrumentationInfo.PROVIDER.getName(), AndroidInstrumentationInfo.PROVIDER);
+              AndroidInstrumentationInfo.NAME, AndroidInstrumentationInfo.PROVIDER);
           builder.addSkylarkAccessibleTopLevels(
-              AndroidDeviceBrokerInfo.PROVIDER.getName(), AndroidDeviceBrokerInfo.PROVIDER);
+              AndroidDeviceBrokerInfo.NAME, AndroidDeviceBrokerInfo.PROVIDER);
           builder.addSkylarkAccessibleTopLevels(
-              AndroidResourcesInfo.PROVIDER.getName(), AndroidResourcesInfo.PROVIDER);
+              AndroidResourcesInfo.NAME, AndroidResourcesInfo.PROVIDER);
           builder.addSkylarkAccessibleTopLevels(
-              AndroidNativeLibsInfo.PROVIDER.getName(), AndroidNativeLibsInfo.PROVIDER);
+              AndroidNativeLibsInfo.NAME, AndroidNativeLibsInfo.PROVIDER);
 
           try {
             builder.addWorkspaceFilePrefix(
diff --git a/src/main/java/com/google/devtools/build/lib/packages/BuiltinProvider.java b/src/main/java/com/google/devtools/build/lib/packages/BuiltinProvider.java
index bb12ae3..b880c97 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/BuiltinProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/BuiltinProvider.java
@@ -17,6 +17,7 @@
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.packages.NativeProvider.NativeKey;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
+import com.google.devtools.build.lib.syntax.EvalException;
 import javax.annotation.Nullable;
 
 /**
@@ -88,4 +89,13 @@
   public void repr(SkylarkPrinter printer) {
     printer.append("<function " + getPrintableName() + ">");
   }
+
+  /**
+   * Convenience method for subclasses of this class to throw a consistent error when
+   * a provider is unable to be constructed from skylark.
+   */
+  protected T throwUnsupportedConstructorException(Location loc) throws EvalException {
+    throw new EvalException(
+        loc, String.format("'%s' cannot be constructed from Skylark", getPrintableName()));
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDeviceBrokerInfo.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDeviceBrokerInfo.java
index ac8c3c9..8e0d089 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDeviceBrokerInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDeviceBrokerInfo.java
@@ -13,15 +13,11 @@
 // limitations under the License.
 package com.google.devtools.build.lib.rules.android;
 
-import com.google.common.collect.ImmutableList;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
-import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.packages.BuiltinProvider;
 import com.google.devtools.build.lib.packages.NativeInfo;
-import com.google.devtools.build.lib.packages.NativeProvider;
 import com.google.devtools.build.lib.skylarkbuildapi.android.AndroidDeviceBrokerInfoApi;
-import com.google.devtools.build.lib.syntax.Environment;
-import com.google.devtools.build.lib.syntax.FunctionSignature;
-import com.google.devtools.build.lib.syntax.SkylarkType;
+import com.google.devtools.build.lib.syntax.EvalException;
 
 /** Supplies the device broker type string, passed to the Android test runtime. */
 @Immutable
@@ -29,26 +25,12 @@
     implements AndroidDeviceBrokerInfoApi {
 
   private static final String SKYLARK_NAME = "AndroidDeviceBrokerInfo";
-  private static final FunctionSignature.WithValues<Object, SkylarkType> SIGNATURE =
-      FunctionSignature.WithValues.create(
-          FunctionSignature.of(
-              /*numMandatoryPositionals=*/ 0,
-              /*numOptionalPositionals=*/ 0,
-              /*numMandatoryNamedOnly=*/ 1,
-              /*starArg=*/ false,
-              /*kwArg=*/ false,
-              "type"),
-          /*defaultValues=*/ null,
-          /*types=*/ ImmutableList.of(SkylarkType.of(String.class))); // instrumentation_apk
-  public static final NativeProvider<AndroidDeviceBrokerInfo> PROVIDER =
-      new NativeProvider<AndroidDeviceBrokerInfo>(
-          AndroidDeviceBrokerInfo.class, SKYLARK_NAME, SIGNATURE) {
-        @Override
-        protected AndroidDeviceBrokerInfo createInstanceFromSkylark(
-            Object[] args, Environment env, Location loc) {
-          return new AndroidDeviceBrokerInfo(/*deviceBrokerType=*/ (String) args[0]);
-        }
-      };
+
+  /**
+   * Provider instance for {@link AndroidDeviceBrokerInfo}.
+   */
+  public static final AndroidDeviceBrokerInfoProvider PROVIDER =
+      new AndroidDeviceBrokerInfoProvider();
 
   private final String deviceBrokerType;
 
@@ -64,4 +46,20 @@
   public String getDeviceBrokerType() {
     return deviceBrokerType;
   }
+
+  /** Provider for {@link AndroidDeviceBrokerInfo}. */
+  public static class AndroidDeviceBrokerInfoProvider
+      extends BuiltinProvider<AndroidDeviceBrokerInfo>
+      implements AndroidDeviceBrokerInfoApiProvider {
+
+    private AndroidDeviceBrokerInfoProvider() {
+      super(SKYLARK_NAME, AndroidDeviceBrokerInfo.class);
+    }
+
+    @Override
+    public AndroidDeviceBrokerInfo createInfo(String type)
+        throws EvalException {
+      return new AndroidDeviceBrokerInfo(type);
+    }
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidInstrumentationInfo.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidInstrumentationInfo.java
index 00c3ed9..5b0e9b8 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidInstrumentationInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidInstrumentationInfo.java
@@ -13,16 +13,12 @@
 // limitations under the License.
 package com.google.devtools.build.lib.rules.android;
 
-import com.google.common.collect.ImmutableList;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
-import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.packages.BuiltinProvider;
 import com.google.devtools.build.lib.packages.NativeInfo;
-import com.google.devtools.build.lib.packages.NativeProvider;
 import com.google.devtools.build.lib.skylarkbuildapi.android.AndroidInstrumentationInfoApi;
-import com.google.devtools.build.lib.syntax.Environment;
-import com.google.devtools.build.lib.syntax.FunctionSignature;
-import com.google.devtools.build.lib.syntax.SkylarkType;
+import com.google.devtools.build.lib.syntax.EvalException;
 
 /**
  * A provider for targets that create Android instrumentations. Consumed by Android testing rules.
@@ -32,30 +28,9 @@
     implements AndroidInstrumentationInfoApi<Artifact> {
 
   private static final String SKYLARK_NAME = "AndroidInstrumentationInfo";
-  private static final FunctionSignature.WithValues<Object, SkylarkType> SIGNATURE =
-      FunctionSignature.WithValues.create(
-          FunctionSignature.of(
-              /*numMandatoryPositionals=*/ 0,
-              /*numOptionalPositionals=*/ 0,
-              /*numMandatoryNamedOnly*/ 2,
-              /*starArg=*/ false,
-              /*kwArg=*/ false,
-              "target_apk",
-              "instrumentation_apk"),
-          /*defaultValues=*/ null,
-          /*types=*/ ImmutableList.of(
-              SkylarkType.of(Artifact.class), // target_apk
-              SkylarkType.of(Artifact.class))); // instrumentation_apk
-  public static final NativeProvider<AndroidInstrumentationInfo> PROVIDER =
-      new NativeProvider<AndroidInstrumentationInfo>(
-          AndroidInstrumentationInfo.class, SKYLARK_NAME, SIGNATURE) {
-        @Override
-        protected AndroidInstrumentationInfo createInstanceFromSkylark(
-            Object[] args, Environment env, Location loc) {
-          return new AndroidInstrumentationInfo(
-              /*targetApk=*/ (Artifact) args[0], /*instrumentationApk=*/ (Artifact) args[1]);
-        }
-      };
+
+  public static final AndroidInstrumentationInfoProvider PROVIDER =
+      new AndroidInstrumentationInfoProvider();
 
   private final Artifact targetApk;
   private final Artifact instrumentationApk;
@@ -75,4 +50,20 @@
   public Artifact getInstrumentationApk() {
     return instrumentationApk;
   }
+
+  /** Provider for {@link AndroidInstrumentationInfo}. */
+  public static class AndroidInstrumentationInfoProvider
+      extends BuiltinProvider<AndroidInstrumentationInfo>
+      implements AndroidInstrumentationInfoApiProvider<Artifact> {
+
+    private AndroidInstrumentationInfoProvider() {
+      super(SKYLARK_NAME, AndroidInstrumentationInfo.class);
+    }
+
+    @Override
+    public AndroidInstrumentationInfoApi<Artifact> createInfo(
+        Artifact targetApk, Artifact instrumentationApk) throws EvalException {
+      return new AndroidInstrumentationInfo(targetApk, instrumentationApk);
+    }
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidInstrumentationTestRule.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidInstrumentationTestRule.java
index a9f6fe4..ff88d5d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidInstrumentationTestRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidInstrumentationTestRule.java
@@ -23,6 +23,7 @@
 import com.google.devtools.build.lib.analysis.config.HostTransition;
 import com.google.devtools.build.lib.packages.RuleClass;
 import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
+import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier;
 import com.google.devtools.build.lib.util.FileTypeSet;
 
 /** Rule definition for the {@code android_instrumentation_test} rule. */
@@ -54,7 +55,8 @@
                 .exec()
                 .cfg(HostTransition.INSTANCE)
                 .allowedFileTypes(FileTypeSet.NO_FILE)
-                .mandatoryProviders(AndroidDeviceBrokerInfo.PROVIDER.id()))
+                .mandatoryProviders(
+                    SkylarkProviderIdentifier.forKey(AndroidDeviceBrokerInfo.PROVIDER.getKey())))
         /* <!-- #BLAZE_RULE(android_instrumentation_test).ATTRIBUTE(support_apks) -->
         Other APKs to install on the device before the instrumentation test starts.
         <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNativeLibsInfo.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNativeLibsInfo.java
index d73d302..aa189a4 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNativeLibsInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNativeLibsInfo.java
@@ -13,18 +13,14 @@
 // limitations under the License.
 package com.google.devtools.build.lib.rules.android;
 
-import com.google.common.collect.ImmutableList;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
-import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.packages.BuiltinProvider;
 import com.google.devtools.build.lib.packages.NativeInfo;
-import com.google.devtools.build.lib.packages.NativeProvider;
 import com.google.devtools.build.lib.skylarkbuildapi.android.AndroidNativeLibsInfoApi;
-import com.google.devtools.build.lib.syntax.Environment;
-import com.google.devtools.build.lib.syntax.FunctionSignature;
+import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
-import com.google.devtools.build.lib.syntax.SkylarkType;
 
 /**
  * Provider of transitively available ZIPs of native libs that should be directly copied into the
@@ -35,27 +31,9 @@
     implements AndroidNativeLibsInfoApi<Artifact> {
 
   private static final String SKYLARK_NAME = "AndroidNativeLibsInfo";
-  private static final FunctionSignature.WithValues<Object, SkylarkType> SIGNATURE =
-      FunctionSignature.WithValues.create(
-          FunctionSignature.of(
-              /*numMandatoryPositionals=*/ 0,
-              /*numOptionalPositionals=*/ 0,
-              /*numMandatoryNamedOnly=*/ 1,
-              /*starArg=*/ false,
-              /*kwArg=*/ false,
-              "native_libs"),
-          /*defaultValues=*/ null,
-          /*types=*/ ImmutableList.of(SkylarkType.of(SkylarkNestedSet.class)));
-  public static final NativeProvider<AndroidNativeLibsInfo> PROVIDER =
-      new NativeProvider<AndroidNativeLibsInfo>(
-          AndroidNativeLibsInfo.class, SKYLARK_NAME, SIGNATURE) {
-        @Override
-        protected AndroidNativeLibsInfo createInstanceFromSkylark(
-            Object[] args, Environment env, Location loc) {
-          return new AndroidNativeLibsInfo(
-              /*nativeLibs=*/ ((SkylarkNestedSet) args[0]).getSet(Artifact.class));
-        }
-      };
+
+  public static final AndroidNativeLibsInfoProvider PROVIDER =
+      new AndroidNativeLibsInfoProvider();
 
   private final NestedSet<Artifact> nativeLibs;
 
@@ -68,4 +46,19 @@
   public NestedSet<Artifact> getNativeLibs() {
     return nativeLibs;
   }
+
+  /** Provider for {@link AndroidNativeLibsInfo}. */
+  public static class AndroidNativeLibsInfoProvider extends BuiltinProvider<AndroidNativeLibsInfo>
+      implements AndroidNativeLibsInfoApiProvider {
+
+    private AndroidNativeLibsInfoProvider() {
+      super(SKYLARK_NAME, AndroidNativeLibsInfo.class);
+    }
+
+    @Override
+    public AndroidNativeLibsInfo createInfo(SkylarkNestedSet nativeLibs)
+        throws EvalException {
+      return new AndroidNativeLibsInfo(nativeLibs.getSet(Artifact.class));
+    }
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesInfo.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesInfo.java
index 13502e6..a2afaa6 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesInfo.java
@@ -17,17 +17,24 @@
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.packages.BuiltinProvider;
 import com.google.devtools.build.lib.packages.NativeInfo;
-import com.google.devtools.build.lib.packages.NativeProvider;
 import com.google.devtools.build.lib.skylarkbuildapi.android.AndroidResourcesInfoApi;
+import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.SkylarkDict;
 
 /** A provider that supplies ResourceContainers from its transitive closure. */
 @Immutable
 public class AndroidResourcesInfo extends NativeInfo implements AndroidResourcesInfoApi {
 
   private static final String SKYLARK_NAME = "AndroidResourcesInfo";
-  public static final NativeProvider<AndroidResourcesInfo> PROVIDER =
-      new NativeProvider<AndroidResourcesInfo>(AndroidResourcesInfo.class, SKYLARK_NAME) {};
+
+  /**
+   * Provider instance for {@link AndroidResourcesInfo}.
+   */
+  public static final AndroidResourcesInfoProvider PROVIDER =
+      new AndroidResourcesInfoProvider();
 
   /*
    * Local information about the target that produced this provider, for tooling. These values will
@@ -147,4 +154,19 @@
   public NestedSet<Artifact> getTransitiveRTxt() {
     return transitiveRTxt;
   }
+
+  /** Provider for {@link AndroidResourcesInfo}. */
+  public static class AndroidResourcesInfoProvider extends BuiltinProvider<AndroidResourcesInfo>
+      implements AndroidResourcesInfoApiProvider {
+
+    private AndroidResourcesInfoProvider() {
+      super(SKYLARK_NAME, AndroidResourcesInfo.class);
+    }
+
+    @Override
+    public AndroidResourcesInfo createInfo(SkylarkDict<?, ?> kwargs, Location loc)
+        throws EvalException {
+      return throwUnsupportedConstructorException(loc);
+    }
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
index a9264b0..d06c9b2 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
@@ -563,8 +563,10 @@
               attr(DataBinding.DATABINDING_ANNOTATION_PROCESSOR_ATTR, LABEL)
                   .cfg(HostTransition.INSTANCE)
                   .value(env.getToolsLabel("//tools/android:databinding_annotation_processor")))
-          .advertiseSkylarkProvider(AndroidResourcesInfo.PROVIDER.id())
-          .advertiseSkylarkProvider(AndroidNativeLibsInfo.PROVIDER.id())
+          .advertiseSkylarkProvider(
+              SkylarkProviderIdentifier.forKey(AndroidResourcesInfo.PROVIDER.getKey()))
+          .advertiseSkylarkProvider(
+              SkylarkProviderIdentifier.forKey(AndroidNativeLibsInfo.PROVIDER.getKey()))
           .build();
     }
 
@@ -1030,7 +1032,7 @@
                   .exec()
                   .value(env.getToolsLabel("//tools/android:zip_filter")))
           .removeAttribute("data")
-          .advertiseSkylarkProvider(ApkInfo.PROVIDER.id())
+          .advertiseSkylarkProvider(SkylarkProviderIdentifier.forKey(ApkInfo.PROVIDER.getKey()))
           .advertiseSkylarkProvider(SkylarkProviderIdentifier.forKey(JavaInfo.PROVIDER.getKey()))
           .build();
     }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java
index 97f1b81..b60d9d1 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java
@@ -25,6 +25,7 @@
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
 import com.google.devtools.build.lib.collect.nestedset.Order;
 import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.packages.BuiltinProvider;
 import com.google.devtools.build.lib.packages.NativeInfo;
 import com.google.devtools.build.lib.packages.NativeProvider;
 import com.google.devtools.build.lib.packages.Provider;
@@ -754,6 +755,16 @@
             .collect(ImmutableList.toImmutableList()));
   }
 
+  protected static <T extends NativeInfo> SkylarkList<T> getProviders(
+      SkylarkList<ConfiguredTarget> targets, BuiltinProvider<T> provider) {
+    return SkylarkList.createImmutable(
+        targets
+            .stream()
+            .map(target -> target.get(provider))
+            .filter(Objects::nonNull)
+            .collect(ImmutableList.toImmutableList()));
+  }
+
   private static <T> SkylarkList<T> listFromNoneableOrEmpty(Object object, Class<T> clazz)
       throws EvalException {
     List<T> value = listFromNoneable(object, clazz);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ApkInfo.java b/src/main/java/com/google/devtools/build/lib/rules/android/ApkInfo.java
index de7841d..18b07e8 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ApkInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ApkInfo.java
@@ -15,9 +15,12 @@
 
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.packages.BuiltinProvider;
 import com.google.devtools.build.lib.packages.NativeInfo;
-import com.google.devtools.build.lib.packages.NativeProvider;
 import com.google.devtools.build.lib.skylarkbuildapi.android.ApkInfoApi;
+import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.SkylarkDict;
 import javax.annotation.Nullable;
 
 /** A provider for targets that produce an apk file. */
@@ -25,8 +28,11 @@
 public class ApkInfo extends NativeInfo implements ApkInfoApi<Artifact> {
 
   private static final String SKYLARK_NAME = "ApkInfo";
-  public static final NativeProvider<ApkInfo> PROVIDER =
-      new NativeProvider<ApkInfo>(ApkInfo.class, SKYLARK_NAME) {};
+
+  /**
+   * Provider instance for {@link ApkInfo}.
+   */
+  public static final ApkInfoProvider PROVIDER = new ApkInfoProvider();
 
   private final Artifact apk;
   private final Artifact unsignedApk;
@@ -74,4 +80,19 @@
   public Artifact getKeystore() {
     return keystore;
   }
+
+  /** Provider for {@link ApkInfo}. */
+  public static class ApkInfoProvider extends BuiltinProvider<ApkInfo>
+      implements ApkInfoApiProvider {
+
+    private ApkInfoProvider() {
+      super(SKYLARK_NAME, ApkInfo.class);
+    }
+
+    @Override
+    public ApkInfoApi<?> createInfo(SkylarkDict<?, ?> kwargs, Location loc)
+        throws EvalException {
+      return throwUnsupportedConstructorException(loc);
+    }
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidDeviceBrokerInfoApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidDeviceBrokerInfoApi.java
index 51c2272..733334a 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidDeviceBrokerInfoApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidDeviceBrokerInfoApi.java
@@ -13,9 +13,40 @@
 // limitations under the License.
 package com.google.devtools.build.lib.skylarkbuildapi.android;
 
+import com.google.devtools.build.lib.skylarkbuildapi.ProviderApi;
 import com.google.devtools.build.lib.skylarkbuildapi.StructApi;
+import com.google.devtools.build.lib.skylarkinterface.Param;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkConstructor;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
+import com.google.devtools.build.lib.syntax.EvalException;
 
 /** Supplies the device broker type string, passed to the Android test runtime. */
 @SkylarkModule(name = "AndroidDeviceBrokerInfo", doc = "", documented = false)
-public interface AndroidDeviceBrokerInfoApi extends StructApi {}
+public interface AndroidDeviceBrokerInfoApi extends StructApi {
+
+  /**
+   * Name of this info object.
+   */
+  public static String NAME = "AndroidDeviceBrokerInfo";
+
+  /** Provider for {@link AndroidDeviceBrokerInfoApi}. */
+  @SkylarkModule(name = "Provider", doc = "", documented = false)
+  public interface AndroidDeviceBrokerInfoApiProvider extends ProviderApi {
+
+    @SkylarkCallable(
+        name = "AndroidDeviceBrokerInfo",
+        doc = "The <code>AndroidDeviceBrokerInfo</code> constructor.",
+        parameters = {
+            @Param(
+                name = "type",
+                type = String.class,
+                named = true,
+                doc = "The type of device broker that is appropriate to use to interact with "
+                    + "devices"
+            )},
+        selfCall = true)
+    @SkylarkConstructor(objectType = AndroidDeviceBrokerInfoApi.class)
+    public AndroidDeviceBrokerInfoApi createInfo(String type) throws EvalException;
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidInstrumentationInfoApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidInstrumentationInfoApi.java
index 2022024..4c70937 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidInstrumentationInfoApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidInstrumentationInfoApi.java
@@ -14,10 +14,14 @@
 package com.google.devtools.build.lib.skylarkbuildapi.android;
 
 import com.google.devtools.build.lib.skylarkbuildapi.FileApi;
+import com.google.devtools.build.lib.skylarkbuildapi.ProviderApi;
 import com.google.devtools.build.lib.skylarkbuildapi.StructApi;
+import com.google.devtools.build.lib.skylarkinterface.Param;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkConstructor;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
+import com.google.devtools.build.lib.syntax.EvalException;
 
 /**
  * A provider for targets that create Android instrumentations. Consumed by Android testing rules.
@@ -28,6 +32,11 @@
     category = SkylarkModuleCategory.PROVIDER)
 public interface AndroidInstrumentationInfoApi<FileT extends FileApi> extends StructApi {
 
+  /**
+   * Name of this info object.
+   */
+  public static String NAME = "AndroidInstrumentationInfo";
+
   @SkylarkCallable(
       name = "target_apk",
       doc = "Returns the target APK of the instrumentation test.",
@@ -39,4 +48,31 @@
       doc = "Returns the instrumentation APK that should be executed.",
       structField = true)
   FileT getInstrumentationApk();
+
+  /** Provider for {@link AndroidInstrumentationInfoApi}. */
+  @SkylarkModule(name = "Provider", doc = "", documented = false)
+  public interface AndroidInstrumentationInfoApiProvider<FileT extends FileApi>
+      extends ProviderApi {
+
+    @SkylarkCallable(
+        name = "AndroidInstrumentationInfo",
+        doc = "The <code>AndroidInstrumentationInfo</code> constructor.",
+        parameters = {
+            @Param(
+                name = "target_apk",
+                type = FileApi.class,
+                named = true,
+                doc = "The target APK of the instrumentation test."
+            ),
+            @Param(
+                name = "instrumentation_apk",
+                type = FileApi.class,
+                named = true,
+                doc = "The instrumentation APK that should be executed."
+            )},
+        selfCall = true)
+    @SkylarkConstructor(objectType = AndroidInstrumentationInfoApi.class)
+    public AndroidInstrumentationInfoApi<FileT> createInfo(
+        FileT targetApk, FileT instrumentationApk) throws EvalException;
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidNativeLibsInfoApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidNativeLibsInfoApi.java
index 6e1c154..cf69fee 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidNativeLibsInfoApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidNativeLibsInfoApi.java
@@ -15,9 +15,13 @@
 
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.skylarkbuildapi.FileApi;
+import com.google.devtools.build.lib.skylarkbuildapi.ProviderApi;
 import com.google.devtools.build.lib.skylarkbuildapi.StructApi;
+import com.google.devtools.build.lib.skylarkinterface.Param;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
+import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
 
 /**
  * Provider of transitively available ZIPs of native libs that should be directly copied into the
@@ -26,9 +30,34 @@
 @SkylarkModule(name = "AndroidNativeLibsInfo", doc = "", documented = false)
 public interface AndroidNativeLibsInfoApi<FileT extends FileApi> extends StructApi {
 
+  /**
+   * Name of this info object.
+   */
+  public static String NAME = "AndroidNativeLibsInfo";
+
   @SkylarkCallable(
       name = "native_libs",
       doc = "Returns the native libraries produced by the rule.",
       structField = true)
   NestedSet<FileT> getNativeLibs();
+
+  /** Provider for {@link AndroidNativeLibsInfoApi}. */
+  @SkylarkModule(name = "Provider", doc = "", documented = false)
+  public interface AndroidNativeLibsInfoApiProvider extends ProviderApi {
+
+    @SkylarkCallable(
+        name = "AndroidNativeLibsInfo",
+        doc = "The <code>AndroidNativeLibsInfo</code> constructor.",
+        parameters = {
+            @Param(
+                name = "native_libs",
+                type = SkylarkNestedSet.class,
+                generic1 = FileApi.class,
+                named = true,
+                doc = "The native libraries produced by the rule."
+            ),
+        },
+        selfCall = true)
+    public AndroidNativeLibsInfoApi<?> createInfo(SkylarkNestedSet nativeLibs) throws EvalException;
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidResourcesInfoApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidResourcesInfoApi.java
index 92caa64..e9c6788 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidResourcesInfoApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/AndroidResourcesInfoApi.java
@@ -13,11 +13,16 @@
 // limitations under the License.
 package com.google.devtools.build.lib.skylarkbuildapi.android;
 
+import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.skylarkbuildapi.FileApi;
+import com.google.devtools.build.lib.skylarkbuildapi.ProviderApi;
 import com.google.devtools.build.lib.skylarkbuildapi.StructApi;
+import com.google.devtools.build.lib.skylarkinterface.Param;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
+import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.SkylarkDict;
 
 /** A provider that supplies resource information from its transitive closure. */
 @SkylarkModule(
@@ -26,6 +31,11 @@
     category = SkylarkModuleCategory.PROVIDER)
 public interface AndroidResourcesInfoApi extends StructApi {
 
+  /**
+   * Name of this info object.
+   */
+  public static String NAME = "AndroidResourcesInfo";
+
   /** Returns the compiletime r.txt file for the target. */
   @SkylarkCallable(
       name = "compiletime_r_txt",
@@ -35,4 +45,19 @@
               + " dependencies, or used at runtime.",
       structField = true)
   FileApi getRTxt();
+
+  /** Provider for {@link AndroidResourcesInfoApi}. */
+  @SkylarkModule(name = "Provider", doc = "", documented = false)
+  public interface AndroidResourcesInfoApiProvider extends ProviderApi {
+
+    @SkylarkCallable(
+        name = "AndroidResourcesInfo",
+        // This is left undocumented as it throws a "not-implemented in Skylark" error when invoked.
+        documented = false,
+        extraKeywords = @Param(name = "kwargs"),
+        useLocation = true,
+        selfCall = true)
+    public AndroidResourcesInfoApi createInfo(
+        SkylarkDict<?, ?> kwargs, Location loc) throws EvalException;
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/ApkInfoApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/ApkInfoApi.java
index b279e87..b3cd96e 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/ApkInfoApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/android/ApkInfoApi.java
@@ -13,11 +13,16 @@
 // limitations under the License.
 package com.google.devtools.build.lib.skylarkbuildapi.android;
 
+import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.skylarkbuildapi.FileApi;
+import com.google.devtools.build.lib.skylarkbuildapi.ProviderApi;
 import com.google.devtools.build.lib.skylarkbuildapi.StructApi;
+import com.google.devtools.build.lib.skylarkinterface.Param;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
+import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.SkylarkDict;
 
 /** A provider for targets that produce an apk file. */
 @SkylarkModule(
@@ -25,10 +30,30 @@
     doc = "APKs provided by a rule",
     category = SkylarkModuleCategory.PROVIDER)
 public interface ApkInfoApi<FileT extends FileApi> extends StructApi {
+
+  /**
+   * Name of this info object.
+   */
+  public static String NAME = "ApkInfo";
+
   /** Returns the APK file built in the transitive closure. */
   @SkylarkCallable(
       name = "signed_apk",
       doc = "Returns a signed APK built from the target.",
       structField = true)
   FileT getApk();
+
+  /** Provider for {@link ApkInfoApi}. */
+  @SkylarkModule(name = "Provider", doc = "", documented = false)
+  public interface ApkInfoApiProvider extends ProviderApi {
+
+    @SkylarkCallable(
+        name = "ApkInfo",
+        // This is left undocumented as it throws a "not-implemented in Skylark" error when invoked.
+        documented = false,
+        extraKeywords = @Param(name = "kwargs"),
+        useLocation = true,
+        selfCall = true)
+    public ApkInfoApi<?> createInfo(SkylarkDict<?, ?> kwargs, Location loc) throws EvalException;
+  }
 }