diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp index 8ffe5113c2..ab72e8b6d0 100644 --- a/java/core-libraries/Android.bp +++ b/java/core-libraries/Android.bp @@ -64,6 +64,7 @@ java_api_library { "stub-annotations", ], enable_validation: false, + stubs_type: "everything", } java_library { @@ -248,6 +249,7 @@ java_api_library { "stub-annotations", ], visibility: ["//visibility:private"], + stubs_type: "everything", } // Produces a dist file that is used by the @@ -358,6 +360,7 @@ java_api_library { libs: [ "stub-annotations", ], + stubs_type: "everything", } java_library { @@ -446,6 +449,7 @@ java_api_library { libs: [ "stub-annotations", ], + stubs_type: "everything", } java_library { diff --git a/java/droidstubs.go b/java/droidstubs.go index b1126146ca..f4bcaca15f 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -52,6 +52,19 @@ func (s StubsType) String() string { } } +func StringToStubsType(s string) StubsType { + switch strings.ToLower(s) { + case Everything.String(): + return Everything + case Runtime.String(): + return Runtime + case Exportable.String(): + return Exportable + default: + return Unavailable + } +} + func init() { RegisterStubsBuildComponents(android.InitRegistrationContext) } @@ -731,7 +744,7 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi // defined for a module, simply revert all flagged apis annotations. If aconfig_declarations // property is defined, 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, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) { +func generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) { if len(aconfigFlagsPaths) == 0 { cmd.Flag("--revert-annotation android.annotation.FlaggedApi") @@ -1106,7 +1119,7 @@ func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsComm cmd := d.commonMetalavaStubCmd(ctx, rule, params) - d.generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles) + generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles) if params.stubConfig.doApiLint { // Pass the lint baseline file as an input to resolve the lint errors. diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go index ca34e0ef13..c86e8bf0fd 100644 --- a/java/droidstubs_test.go +++ b/java/droidstubs_test.go @@ -337,6 +337,7 @@ func TestGeneratedApiContributionVisibilityTest(t *testing.T) { name: "bar", api_surface: "public", api_contributions: ["foo.api.contribution"], + stubs_type: "everything", } ` ctx, _ := testJavaWithFS(t, ` diff --git a/java/java.go b/java/java.go index af4c3be3b7..794020dc5b 100644 --- a/java/java.go +++ b/java/java.go @@ -24,6 +24,7 @@ import ( "sort" "strings" + "android/soong/aconfig" "android/soong/remoteexec" "android/soong/testing" @@ -1863,6 +1864,10 @@ type ApiLibrary struct { dexJarFile OptionalDexJarPath validationPaths android.Paths + + stubsType StubsType + + aconfigProtoFiles android.Paths } type JavaApiLibraryProperties struct { @@ -1904,6 +1909,20 @@ type JavaApiLibraryProperties struct { // in sync with the source Java files. However, the environment variable // DISABLE_STUB_VALIDATION has precedence over this property. Enable_validation *bool + + // Type of stubs the module should generate. Must be one of "everything", "runtime" or + // "exportable". Defaults to "everything". + // - "everything" stubs include all non-flagged apis and flagged apis, regardless of the state + // of the flag. + // - "runtime" stubs include all non-flagged apis and flagged apis that are ENABLED or + // READ_WRITE, and all other flagged apis are stripped. + // - "exportable" stubs include all non-flagged apis and flagged apis that are ENABLED and + // READ_ONLY, and all other flagged apis are stripped. + Stubs_type *string + + // List of aconfig_declarations module names that the stubs generated in this module + // depend on. + Aconfig_declarations []string } func ApiLibraryFactory() android.Module { @@ -2067,6 +2086,9 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { if al.properties.System_modules != nil { ctx.AddVariationDependencies(nil, systemModulesTag, String(al.properties.System_modules)) } + for _, aconfigDeclarationsName := range al.properties.Aconfig_declarations { + ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationsName) + } } // Map where key is the api scope name and value is the int value @@ -2087,7 +2109,23 @@ func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFiles return srcFilesInfo } +var validstubsType = []StubsType{Everything, Runtime, Exportable} + +func (al *ApiLibrary) validateProperties(ctx android.ModuleContext) { + if al.properties.Stubs_type == nil { + ctx.ModuleErrorf("java_api_library module type must specify stubs_type property.") + } else { + al.stubsType = StringToStubsType(proptools.String(al.properties.Stubs_type)) + } + + if !android.InList(al.stubsType, validstubsType) { + ctx.PropertyErrorf("stubs_type", "%s is not a valid stubs_type property value. "+ + "Must be one of %s.", proptools.String(al.properties.Stubs_type), validstubsType) + } +} + func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { + al.validateProperties(ctx) rule := android.NewRuleBuilder(pctx, ctx) @@ -2131,6 +2169,18 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { if currentApiTimestampProvider, ok := dep.(currentApiTimestampProvider); ok { al.validationPaths = append(al.validationPaths, currentApiTimestampProvider.CurrentApiTimestamp()) } + case aconfigDeclarationTag: + if provider, ok := android.OtherModuleProvider(ctx, dep, android.AconfigDeclarationsProviderKey); ok { + al.aconfigProtoFiles = append(al.aconfigProtoFiles, provider.IntermediateCacheOutputPath) + } else if provider, ok := android.OtherModuleProvider(ctx, dep, aconfig.CodegenInfoProvider); ok { + al.aconfigProtoFiles = append(al.aconfigProtoFiles, provider.IntermediateCacheOutputPaths...) + } else { + ctx.ModuleErrorf("Only aconfig_declarations and aconfig_declarations_group "+ + "module type is allowed for flags_packages property, but %s is neither "+ + "of these supported module types", + dep.Name(), + ) + } } }) @@ -2156,6 +2206,8 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { al.addValidation(ctx, cmd, al.validationPaths) + generateRevertAnnotationArgs(ctx, cmd, al.stubsType, al.aconfigProtoFiles) + al.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar") al.stubsJarWithoutStaticLibs = android.PathForModuleOut(ctx, "metalava", "stubs.jar") al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), fmt.Sprintf("%s.jar", ctx.ModuleName())) diff --git a/java/java_test.go b/java/java_test.go index 42301d866e..2f3ccb98df 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -1756,6 +1756,7 @@ func TestJavaApiContributionEmptyApiFile(t *testing.T) { name: "bar", api_surface: "public", api_contributions: ["foo"], + stubs_type: "everything", } `) } @@ -1792,12 +1793,14 @@ func TestJavaApiLibraryAndProviderLink(t *testing.T) { name: "bar1", api_surface: "public", api_contributions: ["foo1"], + stubs_type: "everything", } java_api_library { name: "bar2", api_surface: "system", api_contributions: ["foo1", "foo2"], + stubs_type: "everything", } `) @@ -1885,12 +1888,14 @@ func TestJavaApiLibraryAndDefaultsLink(t *testing.T) { name: "bar1", api_surface: "public", api_contributions: ["foo1"], + stubs_type: "everything", } java_api_library { name: "bar2", api_surface: "public", defaults:["baz1"], + stubs_type: "everything", } java_api_library { @@ -1898,6 +1903,7 @@ func TestJavaApiLibraryAndDefaultsLink(t *testing.T) { api_surface: "system", defaults:["baz1", "baz2"], api_contributions: ["foo4"], + stubs_type: "everything", } `) @@ -1962,12 +1968,14 @@ func TestJavaApiLibraryJarGeneration(t *testing.T) { name: "bar1", api_surface: "public", api_contributions: ["foo1"], + stubs_type: "everything", } java_api_library { name: "bar2", api_surface: "system", api_contributions: ["foo1", "foo2"], + stubs_type: "everything", } `) @@ -2044,6 +2052,7 @@ func TestJavaApiLibraryLibsLink(t *testing.T) { api_surface: "public", api_contributions: ["foo1"], libs: ["lib1"], + stubs_type: "everything", } java_api_library { @@ -2051,6 +2060,7 @@ func TestJavaApiLibraryLibsLink(t *testing.T) { api_surface: "system", api_contributions: ["foo1", "foo2"], libs: ["lib1", "lib2", "bar1"], + stubs_type: "everything", } `) @@ -2130,6 +2140,7 @@ func TestJavaApiLibraryStaticLibsLink(t *testing.T) { api_surface: "public", api_contributions: ["foo1"], static_libs: ["lib1"], + stubs_type: "everything", } java_api_library { @@ -2137,6 +2148,7 @@ func TestJavaApiLibraryStaticLibsLink(t *testing.T) { api_surface: "system", api_contributions: ["foo1", "foo2"], static_libs: ["lib1", "lib2", "bar1"], + stubs_type: "everything", } `) @@ -2184,6 +2196,7 @@ func TestJavaApiLibraryFullApiSurfaceStub(t *testing.T) { name: "lib1", api_surface: "public", api_contributions: ["foo1", "foo2"], + stubs_type: "everything", } ` @@ -2207,6 +2220,7 @@ func TestJavaApiLibraryFullApiSurfaceStub(t *testing.T) { api_surface: "public", api_contributions: ["foo1"], full_api_surface_stub: "lib1", + stubs_type: "everything", } `) @@ -2368,6 +2382,7 @@ func TestJavaApiContributionImport(t *testing.T) { java_api_library { name: "foo", api_contributions: ["bar"], + stubs_type: "everything", } java_api_contribution_import { name: "bar", @@ -2394,6 +2409,7 @@ func TestJavaApiLibraryApiFilesSorting(t *testing.T) { "module-lib-api-stubs-docs-non-updatable.api.contribution", "api-stubs-docs-non-updatable.api.contribution", ], + stubs_type: "everything", } `) m := ctx.ModuleForTests("foo", "android_common") @@ -2466,6 +2482,7 @@ func TestApiLibraryDroidstubsDependency(t *testing.T) { "api-stubs-docs-non-updatable.api.contribution", ], enable_validation: true, + stubs_type: "everything", } java_api_library { name: "bar", @@ -2473,6 +2490,7 @@ func TestApiLibraryDroidstubsDependency(t *testing.T) { "api-stubs-docs-non-updatable.api.contribution", ], enable_validation: false, + stubs_type: "everything", } `) @@ -2624,3 +2642,54 @@ func TestMultiplePrebuilts(t *testing.T) { android.AssertStringEquals(t, "unexpected LOCAL_MODULE", "bar", entries.EntryMap["LOCAL_MODULE"][0]) } } + +func TestApiLibraryAconfigDeclarations(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", + ], + } + java_api_contribution { + name: "baz", + api_file: "a/current.txt", + api_surface: "public", + } + java_api_library { + name: "foo", + api_surface: "public", + api_contributions: [ + "baz", + ], + aconfig_declarations: [ + "bar", + ], + stubs_type: "exportable", + enable_validation: false, + } + `) + + // Check if java_api_library depends 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") + + // revert-annotations.txt passed to exportable stubs generation metalava command + manifest := m.Output("metalava.sbox.textproto") + cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command) + android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "revert-annotations-exportable.txt") +} diff --git a/java/sdk_library.go b/java/sdk_library.go index d532aaa00b..cdd04483d4 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -2024,6 +2024,7 @@ func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, Full_api_surface_stub *string System_modules *string Enable_validation *bool + Stubs_type *string }{} props.Name = proptools.StringPtr(module.apiLibraryModuleName(apiScope)) @@ -2073,6 +2074,7 @@ func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, props.System_modules = module.deviceProperties.System_modules props.Enable_validation = proptools.BoolPtr(true) + props.Stubs_type = proptools.StringPtr("everything") mctx.CreateModule(ApiLibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) } diff --git a/java/testing.go b/java/testing.go index 04e8c734ec..631d51662c 100644 --- a/java/testing.go +++ b/java/testing.go @@ -523,10 +523,11 @@ func gatherRequiredDepsForTest() string { for libName, droidstubs := range extraApiLibraryModules { bp += fmt.Sprintf(` - java_api_library { - name: "%s", - api_contributions: ["%s"], - } + java_api_library { + name: "%s", + api_contributions: ["%s"], + stubs_type: "everything", + } `, libName, droidstubs.name+".api.contribution") }