Create (API) bp2build converters for droidstubs
- The converter runs for api_bp2build, not bp2build workspace
- Since droidstubs is an internal module created by java_sdk_library,
the conversion encompasses the latter as well
- Since droidstubs do not have an api_surface attribute, this conversion
uses naming convention to infer the api_surface represented by the api
file e.g. *stubs.source -> publicapi, *stubs.source.system -> systemapi)
- Also adds an SdkIntraCore enum to represent the API surface provided
by one core module to another
There is also ongoing work to check in java_api_contribution modules in
Soong. Once we have that, we can update this converter to operate on
that module type instead
Test: go test ./bp2build
Change-Id: Ia85828e04c738d9ffcc524856d7c3034ee29bbf9
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 5777b18..2ad2969 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -18,11 +18,13 @@
"fmt"
"path/filepath"
"regexp"
+ "sort"
"strings"
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/bazel"
"android/soong/java/config"
"android/soong/remoteexec"
)
@@ -834,6 +836,74 @@
}
}
+var _ android.ApiProvider = (*Droidstubs)(nil)
+
+type bazelJavaApiContributionAttributes struct {
+ Api bazel.LabelAttribute
+ Api_surface *string
+}
+
+func (d *Droidstubs) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "java_api_contribution",
+ Bzl_load_location: "//build/bazel/rules/apis:java_api_contribution.bzl",
+ }
+ apiFile := d.properties.Check_api.Current.Api_file
+ // Do not generate a target if check_api is not set
+ if apiFile == nil {
+ return
+ }
+ attrs := &bazelJavaApiContributionAttributes{
+ Api: *bazel.MakeLabelAttribute(
+ android.BazelLabelForModuleSrcSingle(ctx, proptools.String(apiFile)).Label,
+ ),
+ Api_surface: proptools.StringPtr(bazelApiSurfaceName(d.Name())),
+ }
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{
+ Name: android.ApiContributionTargetName(ctx.ModuleName()),
+ }, attrs)
+}
+
+// TODO (b/262014796): Export the API contributions of CorePlatformApi
+// A map to populate the api surface of a droidstub from a substring appearing in its name
+// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
+// use a strict naming convention
+var (
+ droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
+ //public is commented out since the core libraries use public in their java_sdk_library names
+ "intracore": android.SdkIntraCore,
+ "intra.core": android.SdkIntraCore,
+ "system_server": android.SdkSystemServer,
+ "system-server": android.SdkSystemServer,
+ "system": android.SdkSystem,
+ "module_lib": android.SdkModule,
+ "module-lib": android.SdkModule,
+ "test": android.SdkTest,
+ }
+)
+
+// A helper function that returns the api surface of the corresponding java_api_contribution Bazel target
+// The api_surface is populated using the naming convention of the droidstubs module.
+func bazelApiSurfaceName(name string) string {
+ // Sort the keys so that longer strings appear first
+ // Otherwise substrings like system will match both system and system_server
+ sortedKeys := make([]string, 0)
+ for key := range droidstubsModuleNamingToSdkKind {
+ sortedKeys = append(sortedKeys, key)
+ }
+ sort.Slice(sortedKeys, func(i, j int) bool {
+ return len(sortedKeys[i]) > len(sortedKeys[j])
+ })
+ for _, sortedKey := range sortedKeys {
+ if strings.Contains(name, sortedKey) {
+ sdkKind := droidstubsModuleNamingToSdkKind[sortedKey]
+ return sdkKind.String() + "api"
+ }
+ }
+ // Default is publicapi
+ return android.SdkPublic.String() + "api"
+}
+
func StubsDefaultsFactory() android.Module {
module := &DocDefaults{}
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index 25f8c86..ef2e6dc 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -304,3 +304,45 @@
android.AssertStringDoesContain(t, "sdk-extensions-root present", cmdline, "--sdk-extensions-root sdk/extensions")
android.AssertStringDoesContain(t, "sdk-extensions-info present", cmdline, "--sdk-extensions-info sdk/extensions/info.txt")
}
+
+func TestApiSurfaceFromDroidStubsName(t *testing.T) {
+ testCases := []struct {
+ desc string
+ name string
+ expectedApiSurface string
+ }{
+ {
+ desc: "Default is publicapi",
+ name: "mydroidstubs",
+ expectedApiSurface: "publicapi",
+ },
+ {
+ desc: "name contains system substring",
+ name: "mydroidstubs.system.suffix",
+ expectedApiSurface: "systemapi",
+ },
+ {
+ desc: "name contains system_server substring",
+ name: "mydroidstubs.system_server.suffix",
+ expectedApiSurface: "system-serverapi",
+ },
+ {
+ desc: "name contains module_lib substring",
+ name: "mydroidstubs.module_lib.suffix",
+ expectedApiSurface: "module-libapi",
+ },
+ {
+ desc: "name contains test substring",
+ name: "mydroidstubs.test.suffix",
+ expectedApiSurface: "testapi",
+ },
+ {
+ desc: "name contains intra.core substring",
+ name: "mydroidstubs.intra.core.suffix",
+ expectedApiSurface: "intracoreapi",
+ },
+ }
+ for _, tc := range testCases {
+ android.AssertStringEquals(t, tc.desc, tc.expectedApiSurface, bazelApiSurfaceName(tc.name))
+ }
+}