Add aconfig_declarations property to droidstubs and java_sdk_library
In consideration of the incremental build performance, this change let
droidstubs and java_sdk_library (which generates droidstubs per api
scope) modules to specify `aconfig_declaration` modules where the
dependent flags are defined in via the "aconfig_declarations" property,
opposed to passing uniform "all_aconfig_declaration"-generated flag
arguments to metalava.
When "aconfig_declarations" property is defined for java_sdk_library
modules, the property is passed to the generated droidstubs modules.
When "aconfig_declarations" property is defined for droidstubs modules,
the all aconfig_declaration modules listed in the property are listed as
deps, all cache protobuf files are gathered and metalava-consumable
flags are generated in "revert-annotations.txt".
Although this change introduces scalable implementation to easily
support generation of the "runtime" stubs corresponding flags, actual
support of the runtime flags/stubs will be done in future changes. This
change mostly focuses on the generation of the "exportable" flags.
Utilization of the generated "exportable" flags will be done in future
changes.
Test: go test ./java
Bug: 315485740
Change-Id: I37becd1b9dd9069d7ac4abed130906df30b3fdf4
diff --git a/java/builder.go b/java/builder.go
index d03c8e5..6919236 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -274,11 +274,29 @@
` cat $$f; ` +
`done > $out`,
})
+
+ gatherReleasedFlaggedApisRule = pctx.AndroidStaticRule("gatherReleasedFlaggedApisRule",
+ blueprint.RuleParams{
+ Command: `${aconfig} dump --format bool ` +
+ `--out ${out} ` +
+ `${flags_path} ` +
+ `${filter_args} `,
+ CommandDeps: []string{"${aconfig}"},
+ Description: "aconfig_bool",
+ }, "flags_path", "filter_args")
+
+ generateMetalavaRevertAnnotationsRule = pctx.AndroidStaticRule("generateMetalavaRevertAnnotationsRule",
+ blueprint.RuleParams{
+ Command: `${keep-flagged-apis} ${in} > ${out}`,
+ })
)
func init() {
pctx.Import("android/soong/android")
pctx.Import("android/soong/java/config")
+
+ pctx.HostBinToolVariable("aconfig", "aconfig")
+ pctx.HostBinToolVariable("keep-flagged-apis", "keep-flagged-apis")
}
type javaBuilderFlags struct {
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 138c9c3..e05f230 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -397,6 +397,15 @@
sm := module.(SystemModulesProvider)
outputDir, outputDeps := sm.OutputDirAndDeps()
deps.systemModules = &systemModules{outputDir, outputDeps}
+ case aconfigDeclarationTag:
+ if dep, ok := android.OtherModuleProvider(ctx, module, android.AconfigDeclarationsProviderKey); ok {
+ deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPath)
+ } else {
+ ctx.ModuleErrorf("Only aconfig_declarations module type is allowed for "+
+ "flags_packages property, but %s is not aconfig_declarations module type",
+ module.Name(),
+ )
+ }
}
})
// do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs
diff --git a/java/droidstubs.go b/java/droidstubs.go
index e7ccc1b..c839dba 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -30,6 +30,27 @@
// The values allowed for Droidstubs' Api_levels_sdk_type
var allowedApiLevelSdkTypes = []string{"public", "system", "module-lib", "system-server"}
+type StubsType int
+
+const (
+ Everything StubsType = iota
+ Runtime
+ Exportable
+)
+
+func (s StubsType) String() string {
+ switch s {
+ case Everything:
+ return "everything"
+ case Runtime:
+ return "runtime"
+ case Exportable:
+ return "exportable"
+ default:
+ return ""
+ }
+}
+
func init() {
RegisterStubsBuildComponents(android.InitRegistrationContext)
}
@@ -151,6 +172,10 @@
// API surface of this module. If set, the module contributes to an API surface.
// For the full list of available API surfaces, refer to soong/android/sdk_version.go
Api_surface *string
+
+ // a list of aconfig_declarations module names that the stubs generated in this module
+ // depend on.
+ Aconfig_declarations []string
}
// Used by xsd_config
@@ -274,6 +299,12 @@
}
}
+ if len(d.properties.Aconfig_declarations) != 0 {
+ for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
+ ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
+ }
+ }
+
if d.properties.Api_levels_module != nil {
ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
}
@@ -538,11 +569,59 @@
return cmd
}
+// Generate flagged apis related flags. Apply transformations and only revert the flagged apis
+// that are not enabled via release configurations and are not specified in aconfig_declarations
+func (d *Droidstubs) generateRevertAnnotationArgs(ctx android.ModuleContext, stubsType StubsType, aconfigFlagsPaths android.Paths) {
+
+ releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
+ revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
+
+ var filterArgs string
+ switch stubsType {
+ // No flagged apis specific flags need to be passed to metalava when generating
+ // everything stubs
+ case Everything:
+ return
+
+ case Runtime:
+ filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
+
+ case Exportable:
+ filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
+
+ }
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: gatherReleasedFlaggedApisRule,
+ Inputs: aconfigFlagsPaths,
+ Output: releasedFlaggedApisFile,
+ Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
+ Args: map[string]string{
+ "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
+ "filter_args": filterArgs,
+ },
+ })
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: generateMetalavaRevertAnnotationsRule,
+ Input: releasedFlaggedApisFile,
+ Output: revertAnnotationsFile,
+ Description: fmt.Sprintf("%s revert annotations", stubsType),
+ })
+}
+
func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
deps := d.Javadoc.collectDeps(ctx)
javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
+ // If the module specifies aconfig_declarations property, "exportable" (and "runtime" eventually) stubs are generated
+ if len(deps.aconfigProtoFiles) > 0 {
+ // Files required to generate "exportable" stubs
+ stubsType := Exportable
+ d.generateRevertAnnotationArgs(ctx, stubsType, deps.aconfigProtoFiles)
+ }
+
// Create rule for metalava
srcJarDir := android.PathForModuleOut(ctx, "metalava", "srcjars")
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index 7bcaca1..5544890 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -395,3 +395,46 @@
cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command)
android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "--revert-annotation android.annotation.FlaggedApi")
}
+
+func TestAconfigDeclarations(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ }),
+ android.FixtureMergeMockFs(map[string][]byte{
+ "a/A.java": nil,
+ "a/current.txt": nil,
+ "a/removed.txt": nil,
+ }),
+ ).RunTestWithBp(t, `
+ aconfig_declarations {
+ name: "bar",
+ package: "com.example.package",
+ srcs: [
+ "bar.aconfig",
+ ],
+ }
+ droidstubs {
+ name: "foo",
+ srcs: ["a/A.java"],
+ api_surface: "public",
+ check_api: {
+ current: {
+ api_file: "a/current.txt",
+ removed_api_file: "a/removed.txt",
+ }
+ },
+ aconfig_declarations: [
+ "bar",
+ ],
+ }
+ `)
+
+ // Check that droidstubs depend on aconfig_declarations
+ android.AssertBoolEquals(t, "foo expected to depend on bar",
+ CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"), true)
+
+ m := result.ModuleForTests("foo", "android_common")
+ android.AssertStringDoesContain(t, "foo generates revert annotations file",
+ strings.Join(m.AllOutputs(), ""), "revert-annotations-exportable.txt")
+}
diff --git a/java/java.go b/java/java.go
index 2a4fafa..4227d36 100644
--- a/java/java.go
+++ b/java/java.go
@@ -26,6 +26,7 @@
"android/soong/remoteexec"
"android/soong/testing"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -519,6 +520,7 @@
kotlinStdlib android.Paths
kotlinAnnotations android.Paths
kotlinPlugins android.Paths
+ aconfigProtoFiles android.Paths
disableTurbine bool
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index ef34fb6..6998bd2 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -628,6 +628,10 @@
// Defaults to false.
Contribute_to_android_api *bool
+ // a list of aconfig_declarations module names that the stubs generated in this module
+ // depend on.
+ Aconfig_declarations []string
+
// TODO: determines whether to create HTML doc or not
// Html_doc *bool
}
@@ -1698,6 +1702,7 @@
Merge_inclusion_annotations_dirs []string
Generate_stubs *bool
Previous_api *string
+ Aconfig_declarations []string
Check_api struct {
Current ApiToCheck
Last_released ApiToCheck
@@ -1742,6 +1747,7 @@
props.Annotations_enabled = module.sdkLibraryProperties.Annotations_enabled
props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs
props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs
+ props.Aconfig_declarations = module.sdkLibraryProperties.Aconfig_declarations
droidstubsArgs := []string{}
if len(module.sdkLibraryProperties.Api_packages) != 0 {