java_sdk_library: Control API surfaces generated
Adds a per scope set of properties that allows explicit control over
the API surfaces generated.
Previously, the term active was used to determine whether it was
generated but that was a little abstract and unclear so has been
replaced by generated.
Test: m nothing
Bug: 155164730
Change-Id: I7539d89618b61f6b9d1a4b60cc3f9614b157f0d9
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 39c118d..3ce1583 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -70,6 +70,18 @@
// The api scope that this scope extends.
extends *apiScope
+ // The legacy enabled status for a specific scope can be dependent on other
+ // properties that have been specified on the library so it is provided by
+ // a function that can determine the status by examining those properties.
+ legacyEnabledStatus func(module *SdkLibrary) bool
+
+ // The default enabled status for non-legacy behavior, which is triggered by
+ // explicitly enabling at least one api scope.
+ defaultEnabledStatus bool
+
+ // Gets a pointer to the scope specific properties.
+ scopeSpecificProperties func(module *SdkLibrary) *ApiScopeProperties
+
// The name of the field in the dynamically created structure.
fieldName string
@@ -120,6 +132,10 @@
return baseName + sdkStubsSourceSuffix + scope.moduleSuffix
}
+func (scope *apiScope) String() string {
+ return scope.name
+}
+
type apiScopes []*apiScope
func (scopes apiScopes) Strings(accessor func(*apiScope) string) []string {
@@ -132,20 +148,38 @@
var (
apiScopePublic = initApiScope(&apiScope{
- name: "public",
+ name: "public",
+
+ // Public scope is enabled by default for both legacy and non-legacy modes.
+ legacyEnabledStatus: func(module *SdkLibrary) bool {
+ return true
+ },
+ defaultEnabledStatus: true,
+
+ scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
+ return &module.sdkLibraryProperties.Public
+ },
sdkVersion: "current",
})
apiScopeSystem = initApiScope(&apiScope{
- name: "system",
- extends: apiScopePublic,
+ name: "system",
+ extends: apiScopePublic,
+ legacyEnabledStatus: (*SdkLibrary).generateTestAndSystemScopesByDefault,
+ scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
+ return &module.sdkLibraryProperties.System
+ },
apiFilePrefix: "system-",
moduleSuffix: sdkSystemApiSuffix,
sdkVersion: "system_current",
droidstubsArgs: []string{"-showAnnotation android.annotation.SystemApi"},
})
apiScopeTest = initApiScope(&apiScope{
- name: "test",
- extends: apiScopePublic,
+ name: "test",
+ extends: apiScopePublic,
+ legacyEnabledStatus: (*SdkLibrary).generateTestAndSystemScopesByDefault,
+ scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
+ return &module.sdkLibraryProperties.Test
+ },
apiFilePrefix: "test-",
moduleSuffix: sdkTestApiSuffix,
sdkVersion: "test_current",
@@ -190,6 +224,18 @@
ctx.RegisterModuleType("java_sdk_library_import", sdkLibraryImportFactory)
}
+// Properties associated with each api scope.
+type ApiScopeProperties struct {
+ // Indicates whether the api surface is generated.
+ //
+ // If this is set for any scope then all scopes must explicitly specify if they
+ // are enabled. This is to prevent new usages from depending on legacy behavior.
+ //
+ // Otherwise, if this is not set for any scope then the default behavior is
+ // scope specific so please refer to the scope specific property documentation.
+ Enabled *bool
+}
+
type sdkLibraryProperties struct {
// List of Java libraries that will be in the classpath when building stubs
Stub_only_libs []string `android:"arch_variant"`
@@ -232,8 +278,30 @@
// don't create dist rules.
No_dist *bool `blueprint:"mutated"`
- // indicates whether system and test apis should be managed.
- Has_system_and_test_apis bool `blueprint:"mutated"`
+ // indicates whether system and test apis should be generated.
+ Generate_system_and_test_apis bool `blueprint:"mutated"`
+
+ // The properties specific to the public api scope
+ //
+ // Unless explicitly specified by using public.enabled the public api scope is
+ // enabled by default in both legacy and non-legacy mode.
+ Public ApiScopeProperties
+
+ // The properties specific to the system api scope
+ //
+ // In legacy mode the system api scope is enabled by default when sdk_version
+ // is set to something other than "none".
+ //
+ // In non-legacy mode the system api scope is disabled by default.
+ System ApiScopeProperties
+
+ // The properties specific to the test api scope
+ //
+ // In legacy mode the test api scope is enabled by default when sdk_version
+ // is set to something other than "none".
+ //
+ // In non-legacy mode the test api scope is disabled by default.
+ Test ApiScopeProperties
// TODO: determines whether to create HTML doc or not
//Html_doc *bool
@@ -270,18 +338,65 @@
sdkLibraryProperties sdkLibraryProperties
+ // Map from api scope to the scope specific property structure.
+ scopeToProperties map[*apiScope]*ApiScopeProperties
+
commonToSdkLibraryAndImport
}
var _ Dependency = (*SdkLibrary)(nil)
var _ SdkLibraryDependency = (*SdkLibrary)(nil)
-func (module *SdkLibrary) getActiveApiScopes() apiScopes {
- if module.sdkLibraryProperties.Has_system_and_test_apis {
- return allApiScopes
- } else {
- return apiScopes{apiScopePublic}
+func (module *SdkLibrary) generateTestAndSystemScopesByDefault() bool {
+ return module.sdkLibraryProperties.Generate_system_and_test_apis
+}
+
+func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext) apiScopes {
+ // Check to see if any scopes have been explicitly enabled. If any have then all
+ // must be.
+ anyScopesExplicitlyEnabled := false
+ for _, scope := range allApiScopes {
+ scopeProperties := module.scopeToProperties[scope]
+ if scopeProperties.Enabled != nil {
+ anyScopesExplicitlyEnabled = true
+ break
+ }
}
+
+ var generatedScopes apiScopes
+ enabledScopes := make(map[*apiScope]struct{})
+ for _, scope := range allApiScopes {
+ scopeProperties := module.scopeToProperties[scope]
+ // If any scopes are explicitly enabled then ignore the legacy enabled status.
+ // This is to ensure that any new usages of this module type do not rely on legacy
+ // behaviour.
+ defaultEnabledStatus := false
+ if anyScopesExplicitlyEnabled {
+ defaultEnabledStatus = scope.defaultEnabledStatus
+ } else {
+ defaultEnabledStatus = scope.legacyEnabledStatus(module)
+ }
+ enabled := proptools.BoolDefault(scopeProperties.Enabled, defaultEnabledStatus)
+ if enabled {
+ enabledScopes[scope] = struct{}{}
+ generatedScopes = append(generatedScopes, scope)
+ }
+ }
+
+ // Now check to make sure that any scope that is extended by an enabled scope is also
+ // enabled.
+ for _, scope := range allApiScopes {
+ if _, ok := enabledScopes[scope]; ok {
+ extends := scope.extends
+ if extends != nil {
+ if _, ok := enabledScopes[extends]; !ok {
+ ctx.ModuleErrorf("enabled api scope %q depends on disabled scope %q", scope, extends)
+ }
+ }
+ }
+ }
+
+ return generatedScopes
}
var xmlPermissionsFileTag = dependencyTag{name: "xml-permissions-file"}
@@ -294,7 +409,7 @@
}
func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
- for _, apiScope := range module.getActiveApiScopes() {
+ for _, apiScope := range module.getGeneratedApiScopes(ctx) {
// Add dependencies to the stubs library
ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsName(apiScope))
@@ -734,15 +849,15 @@
// also assume it does not contribute to the dist build.
sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
hasSystemAndTestApis := sdkDep.hasStandardLibs()
- module.sdkLibraryProperties.Has_system_and_test_apis = hasSystemAndTestApis
+ module.sdkLibraryProperties.Generate_system_and_test_apis = hasSystemAndTestApis
module.sdkLibraryProperties.No_dist = proptools.BoolPtr(!hasSystemAndTestApis)
missing_current_api := false
- activeScopes := module.getActiveApiScopes()
+ generatedScopes := module.getGeneratedApiScopes(mctx)
apiDir := module.getApiDir()
- for _, scope := range activeScopes {
+ for _, scope := range generatedScopes {
for _, api := range []string{"current.txt", "removed.txt"} {
path := path.Join(mctx.ModuleDir(), apiDir, scope.apiFilePrefix+api)
p := android.ExistentPathForSource(mctx, path)
@@ -765,11 +880,11 @@
"You can update them by:\n"+
"%s %q %s && m update-api",
script, filepath.Join(mctx.ModuleDir(), apiDir),
- strings.Join(activeScopes.Strings(func(s *apiScope) string { return s.apiFilePrefix }), " "))
+ strings.Join(generatedScopes.Strings(func(s *apiScope) string { return s.apiFilePrefix }), " "))
return
}
- for _, scope := range activeScopes {
+ for _, scope := range generatedScopes {
module.createStubsLibrary(mctx, scope)
module.createStubsSources(mctx, scope)
}
@@ -809,6 +924,14 @@
module.InitSdkLibraryProperties()
android.InitApexModule(module)
InitJavaModule(module, android.HostAndDeviceSupported)
+
+ // Initialize the map from scope to scope specific properties.
+ scopeToProperties := make(map[*apiScope]*ApiScopeProperties)
+ for _, scope := range allApiScopes {
+ scopeToProperties[scope] = scope.scopeSpecificProperties(module)
+ }
+ module.scopeToProperties = scopeToProperties
+
module.SetDefaultableHook(func(ctx android.DefaultableHookContext) { module.CreateInternalModules(ctx) })
return module
}