diff --git a/android/config.go b/android/config.go index e7f1044e2..40a73d6e7 100644 --- a/android/config.go +++ b/android/config.go @@ -1979,6 +1979,17 @@ func (c *config) SetBuildFromTextStub(b bool) { c.productVariables.Build_from_text_stub = boolPtr(b) } +func (c *config) SetApiLibraries(libs []string) { + c.apiLibraries = make(map[string]struct{}) + for _, lib := range libs { + c.apiLibraries[lib] = struct{}{} + } +} + +func (c *config) GetApiLibraries() map[string]struct{} { + return c.apiLibraries +} + func (c *deviceConfig) CheckVendorSeappViolations() bool { return Bool(c.config.productVariables.CheckVendorSeappViolations) } diff --git a/apex/apex_test.go b/apex/apex_test.go index a59526f45..cdf16ddce 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -10016,6 +10016,9 @@ func TestApexLintBcpFragmentSdkLibDeps(t *testing.T) { java.PrepareForTestWithJavaSdkLibraryFiles, java.PrepareForTestWithJacocoInstrumentation, java.FixtureWithLastReleaseApis("foo"), + android.FixtureModifyConfig(func(config android.Config) { + config.SetApiLibraries([]string{"foo"}) + }), android.FixtureMergeMockFs(fs), ).RunTestWithBp(t, bp) @@ -11487,6 +11490,9 @@ func TestAconfifDeclarationsValidation(t *testing.T) { prepareForApexTest, java.PrepareForTestWithJavaSdkLibraryFiles, java.FixtureWithLastReleaseApis("foo"), + android.FixtureModifyConfig(func(config android.Config) { + config.SetApiLibraries([]string{"foo"}) + }), ).RunTestWithBp(t, ` java_library { name: "baz-java-lib", diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp index cee7a192e..ab72e8b6d 100644 --- a/java/core-libraries/Android.bp +++ b/java/core-libraries/Android.bp @@ -41,7 +41,7 @@ java_defaults { } java_library { - name: "core.current.stubs", + name: "core.current.stubs.from-source", defaults: [ "core.current.stubs.defaults", ], @@ -52,12 +52,8 @@ java_library { ], } -// Used for bootstrapping ART system modules java_api_library { name: "core.current.stubs.from-text", - defaults: [ - "core.current.stubs.defaults", - ], api_surface: "core", api_contributions: [ "art.module.public.api.stubs.source.api.contribution", @@ -72,7 +68,27 @@ java_api_library { } java_library { - name: "core.current.stubs.exportable", + name: "core.current.stubs", + defaults: [ + "core.current.stubs.defaults", + ], + static_libs: [ + "core.current.stubs.from-source", + ], + product_variables: { + build_from_text_stub: { + static_libs: [ + "core.current.stubs.from-text", + ], + exclude_static_libs: [ + "core.current.stubs.from-source", + ], + }, + }, +} + +java_library { + name: "core.current.stubs.exportable.from-source", defaults: [ "core.current.stubs.defaults", ], @@ -87,6 +103,16 @@ java_library { }, } +java_library { + name: "core.current.stubs.exportable", + defaults: [ + "core.current.stubs.defaults", + ], + static_libs: [ + "core.current.stubs.exportable.from-source", + ], +} + // Distributed with the SDK for turning into system modules to compile apps // against. // @@ -174,6 +200,26 @@ java_library { defaults: [ "core.module_lib.stubs.defaults", ], + static_libs: [ + "core.module_lib.stubs.from-source", + ], + product_variables: { + build_from_text_stub: { + static_libs: [ + "core.module_lib.stubs.from-text", + ], + exclude_static_libs: [ + "core.module_lib.stubs.from-source", + ], + }, + }, +} + +java_library { + name: "core.module_lib.stubs.from-source", + defaults: [ + "core.module_lib.stubs.defaults", + ], static_libs: [ "art.module.public.api.stubs.module_lib", @@ -185,6 +231,27 @@ java_library { ], } +java_api_library { + name: "core.module_lib.stubs.from-text", + api_surface: "module-lib", + api_contributions: [ + "art.module.public.api.stubs.source.api.contribution", + "art.module.public.api.stubs.source.system.api.contribution", + "art.module.public.api.stubs.source.module_lib.api.contribution", + + // Add the module-lib correspondence when Conscrypt or i18N module + // provides @SystemApi(MODULE_LIBRARIES). Currently, assume that only ART module provides + // @SystemApi(MODULE_LIBRARIES). + "conscrypt.module.public.api.stubs.source.api.contribution", + "i18n.module.public.api.stubs.source.api.contribution", + ], + libs: [ + "stub-annotations", + ], + visibility: ["//visibility:private"], + stubs_type: "everything", +} + // Produces a dist file that is used by the // prebuilts/sdk/update_prebuilts.py script to update the prebuilts/sdk // directory. @@ -244,7 +311,7 @@ core_platform_visibility = ["//visibility:public"] // API annotations are available to the dex tools that enable enforcement of runtime // accessibility. b/119068555 java_library { - name: "legacy.core.platform.api.stubs", + name: "legacy.core.platform.api.stubs.from-source", visibility: core_platform_visibility, defaults: [ "core.platform.api.stubs.defaults", @@ -257,7 +324,7 @@ java_library { } java_library { - name: "legacy.core.platform.api.stubs.exportable", + name: "legacy.core.platform.api.stubs.exportable.from-source", visibility: core_platform_visibility, defaults: [ "core.platform.api.stubs.defaults", @@ -281,6 +348,53 @@ java_defaults { ], } +java_api_library { + name: "legacy.core.platform.api.stubs.from-text", + api_surface: "core_platform", + defaults: [ + "android_core_platform_stubs_current_contributions", + ], + api_contributions: [ + "legacy.i18n.module.platform.api.stubs.source.api.contribution", + ], + libs: [ + "stub-annotations", + ], + stubs_type: "everything", +} + +java_library { + name: "legacy.core.platform.api.stubs", + visibility: core_platform_visibility, + defaults: [ + "core.platform.api.stubs.defaults", + ], + static_libs: [ + "legacy.core.platform.api.stubs.from-source", + ], + product_variables: { + build_from_text_stub: { + static_libs: [ + "legacy.core.platform.api.stubs.from-text", + ], + exclude_static_libs: [ + "legacy.core.platform.api.stubs.from-source", + ], + }, + }, +} + +java_library { + name: "legacy.core.platform.api.stubs.exportable", + visibility: core_platform_visibility, + defaults: [ + "core.platform.api.stubs.defaults", + ], + static_libs: [ + "legacy.core.platform.api.stubs.exportable.from-source", + ], +} + java_defaults { name: "core.platform.api.stubs.defaults", hostdex: true, @@ -310,7 +424,7 @@ java_library { } java_library { - name: "stable.core.platform.api.stubs", + name: "stable.core.platform.api.stubs.from-source", visibility: core_platform_visibility, defaults: [ "core.platform.api.stubs.defaults", @@ -323,6 +437,42 @@ java_library { ], } +java_api_library { + name: "stable.core.platform.api.stubs.from-text", + api_surface: "core_platform", + defaults: [ + "android_core_platform_stubs_current_contributions", + ], + api_contributions: [ + "stable.i18n.module.platform.api.stubs.source.api.contribution", + ], + libs: [ + "stub-annotations", + ], + stubs_type: "everything", +} + +java_library { + name: "stable.core.platform.api.stubs", + visibility: core_platform_visibility, + defaults: [ + "core.platform.api.stubs.defaults", + ], + static_libs: [ + "stable.core.platform.api.stubs.from-source", + ], + product_variables: { + build_from_text_stub: { + static_libs: [ + "stable.core.platform.api.stubs.from-text", + ], + exclude_static_libs: [ + "stable.core.platform.api.stubs.from-source", + ], + }, + }, +} + // Same as stable.core.platform.api.stubs, but android annotations are // stripped. This is used by the Java toolchain, while the annotated stub is to // be used by Kotlin one. diff --git a/java/java.go b/java/java.go index ccb348fbb..b320732cd 100644 --- a/java/java.go +++ b/java/java.go @@ -432,6 +432,7 @@ var ( r8LibraryJarTag = dependencyTag{name: "r8-libraryjar", runtimeLinked: true} syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"} javaApiContributionTag = dependencyTag{name: "java-api-contribution"} + depApiSrcsTag = dependencyTag{name: "dep-api-srcs"} aconfigDeclarationTag = dependencyTag{name: "aconfig-declaration"} jniInstallTag = dependencyTag{name: "jni install", runtimeLinked: true, installable: true} binaryInstallTag = dependencyTag{name: "binary install", runtimeLinked: true, installable: true} @@ -2004,6 +2005,12 @@ type JavaApiLibraryProperties struct { // merge zipped after metalava invocation Static_libs []string + // Java Api library to provide the full API surface stub jar file. + // If this property is set, the stub jar of this module is created by + // extracting the compiled class files provided by the + // full_api_surface_stub module. + Full_api_surface_stub *string + // Version of previously released API file for compatibility check. Previous_api *string `android:"path"` @@ -2036,15 +2043,6 @@ type JavaApiLibraryProperties struct { // List of hard coded filegroups containing Metalava config files that are passed to every // Metalava invocation that this module performs. See addMetalavaConfigFilesToCmd. ConfigFiles []string `android:"path" blueprint:"mutated"` - - // If not blank, set to the version of the sdk to compile against. - // Defaults to an empty string, which compiles the module against the private platform APIs. - // Values are of one of the following forms: - // 1) numerical API level, "current", "none", or "core_platform" - // 2) An SDK kind with an API level: "_" - // See build/soong/android/sdk_version.go for the complete and up to date list of SDK kinds. - // If the SDK kind is empty, it will be set to public. - Sdk_version *string } func ApiLibraryFactory() android.Module { @@ -2143,6 +2141,40 @@ func (al *ApiLibrary) addValidation(ctx android.ModuleContext, cmd *android.Rule } } +// This method extracts the stub class files from the stub jar file provided +// from full_api_surface_stub module instead of compiling the srcjar generated from invoking metalava. +// This method is used because metalava can generate compilable from-text stubs only when +// the codebase encompasses all classes listed in the input API text file, and a class can extend +// a class that is not within the same API domain. +func (al *ApiLibrary) extractApiSrcs(ctx android.ModuleContext, rule *android.RuleBuilder, stubsDir android.OptionalPath, fullApiSurfaceStubJar android.Path) { + classFilesList := android.PathForModuleOut(ctx, "metalava", "classes.txt") + unzippedSrcJarDir := android.PathForModuleOut(ctx, "metalava", "unzipDir") + + rule.Command(). + BuiltTool("list_files"). + Text(stubsDir.String()). + FlagWithOutput("--out ", classFilesList). + FlagWithArg("--extensions ", ".java"). + FlagWithArg("--root ", unzippedSrcJarDir.String()). + Flag("--classes") + + rule.Command(). + Text("unzip"). + Flag("-q"). + Input(fullApiSurfaceStubJar). + FlagWithArg("-d ", unzippedSrcJarDir.String()) + + rule.Command(). + BuiltTool("soong_zip"). + Flag("-jar"). + Flag("-write_if_changed"). + Flag("-ignore_missing_files"). + Flag("-quiet"). + FlagWithArg("-C ", unzippedSrcJarDir.String()). + FlagWithInput("-l ", classFilesList). + FlagWithOutput("-o ", al.stubsJarWithoutStaticLibs) +} + func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { apiContributions := al.properties.Api_contributions addValidations := !ctx.Config().IsEnvTrue("DISABLE_STUB_VALIDATION") && @@ -2169,18 +2201,14 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { } } } - if ctx.Device() { - sdkDep := decodeSdkDep(ctx, android.SdkContext(al)) - if sdkDep.useModule { - ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules) - ctx.AddVariationDependencies(nil, libTag, sdkDep.classpath...) - ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...) - - } - } ctx.AddVariationDependencies(nil, libTag, al.properties.Libs...) ctx.AddVariationDependencies(nil, staticLibTag, al.properties.Static_libs...) - + if al.properties.Full_api_surface_stub != nil { + ctx.AddVariationDependencies(nil, depApiSrcsTag, String(al.properties.Full_api_surface_stub)) + } + 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) } @@ -2236,8 +2264,8 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { var srcFilesInfo []JavaApiImportInfo var classPaths android.Paths - var bootclassPaths android.Paths var staticLibs android.Paths + var depApiSrcsStubsJar android.Path var systemModulesPaths android.Paths ctx.VisitDirectDeps(func(dep android.Module) { tag := ctx.OtherModuleDependencyTag(dep) @@ -2251,12 +2279,12 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { case libTag: provider, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider) classPaths = append(classPaths, provider.HeaderJars...) - case bootClasspathTag: - provider, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider) - bootclassPaths = append(bootclassPaths, provider.HeaderJars...) case staticLibTag: provider, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider) staticLibs = append(staticLibs, provider.HeaderJars...) + case depApiSrcsTag: + provider, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider) + depApiSrcsStubsJar = provider.HeaderJars[0] case systemModulesTag: module := dep.(SystemModulesProvider) systemModulesPaths = append(systemModulesPaths, module.HeaderJars()...) @@ -2291,10 +2319,7 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { configFiles := android.PathsForModuleSrc(ctx, al.properties.ConfigFiles) - combinedPaths := append(([]android.Path)(nil), systemModulesPaths...) - combinedPaths = append(combinedPaths, classPaths...) - combinedPaths = append(combinedPaths, bootclassPaths...) - cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir, combinedPaths, configFiles) + cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir, systemModulesPaths, configFiles) al.stubsFlags(ctx, cmd, stubsDir) @@ -2312,6 +2337,9 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { al.stubsJarWithoutStaticLibs = android.PathForModuleOut(ctx, "metalava", "stubs.jar") al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), fmt.Sprintf("%s.jar", ctx.ModuleName())) + if depApiSrcsStubsJar != nil { + al.extractApiSrcs(ctx, rule, stubsDir, depApiSrcsStubsJar) + } rule.Command(). BuiltTool("soong_zip"). Flag("-write_if_changed"). @@ -2322,18 +2350,19 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { rule.Build("metalava", "metalava merged text") - javacFlags := javaBuilderFlags{ - javaVersion: getStubsJavaVersion(), - javacFlags: strings.Join(al.properties.Javacflags, " "), - classpath: classpath(classPaths), - bootClasspath: classpath(append(systemModulesPaths, bootclassPaths...)), + if depApiSrcsStubsJar == nil { + var flags javaBuilderFlags + flags.javaVersion = getStubsJavaVersion() + flags.javacFlags = strings.Join(al.properties.Javacflags, " ") + flags.classpath = classpath(classPaths) + flags.bootClasspath = classpath(systemModulesPaths) + + annoSrcJar := android.PathForModuleOut(ctx, ctx.ModuleName(), "anno.srcjar") + + TransformJavaToClasses(ctx, al.stubsJarWithoutStaticLibs, 0, android.Paths{}, + android.Paths{al.stubsSrcJar}, annoSrcJar, flags, android.Paths{}) } - annoSrcJar := android.PathForModuleOut(ctx, ctx.ModuleName(), "anno.srcjar") - - TransformJavaToClasses(ctx, al.stubsJarWithoutStaticLibs, 0, android.Paths{}, - android.Paths{al.stubsSrcJar}, annoSrcJar, javacFlags, android.Paths{}) - builder := android.NewRuleBuilder(pctx, ctx) builder.Command(). BuiltTool("merge_zips"). @@ -2344,7 +2373,7 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { // compile stubs to .dex for hiddenapi processing dexParams := &compileDexParams{ - flags: javacFlags, + flags: javaBuilderFlags{}, sdkVersion: al.SdkVersion(ctx), minSdkVersion: al.MinSdkVersion(ctx), classesJar: al.stubsJar, @@ -2380,28 +2409,14 @@ func (al *ApiLibrary) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap { return nil } -// Most java_api_library constitues the sdk, but there are some java_api_library that -// does not contribute to the api surface. Such modules are allowed to set sdk_version -// other than "none" +// java_api_library constitutes the sdk, and does not build against one func (al *ApiLibrary) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { - return android.SdkSpecFrom(ctx, proptools.String(al.properties.Sdk_version)) + return android.SdkSpecNone } // java_api_library is always at "current". Return FutureApiLevel func (al *ApiLibrary) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { - return al.SdkVersion(ctx).ApiLevel -} - -func (al *ApiLibrary) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel { - return al.SdkVersion(ctx).ApiLevel -} - -func (al *ApiLibrary) SystemModules() string { - return proptools.String(al.properties.System_modules) -} - -func (al *ApiLibrary) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { - return al.SdkVersion(ctx).ApiLevel + return android.FutureApiLevel } func (al *ApiLibrary) IDEInfo(i *android.IdeInfo) { @@ -2419,6 +2434,9 @@ func (al *ApiLibrary) ideDeps() []string { if al.properties.System_modules != nil { ret = append(ret, proptools.String(al.properties.System_modules)) } + if al.properties.Full_api_surface_stub != nil { + ret = append(ret, proptools.String(al.properties.Full_api_surface_stub)) + } // Other non java_library dependencies like java_api_contribution are ignored for now. return ret } @@ -2426,7 +2444,6 @@ func (al *ApiLibrary) ideDeps() []string { // implement the following interfaces for hiddenapi processing var _ hiddenAPIModule = (*ApiLibrary)(nil) var _ UsesLibraryDependency = (*ApiLibrary)(nil) -var _ android.SdkContext = (*ApiLibrary)(nil) // implement the following interface for IDE completion. var _ android.IDEInfo = (*ApiLibrary)(nil) diff --git a/java/java_test.go b/java/java_test.go index 2d4fca240..33079f381 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -1342,12 +1342,12 @@ func TestJavaLibraryWithSystemModules(t *testing.T) { } `) - checkBootClasspathForLibWithSystemModule(t, ctx, "lib-with-source-system-modules", "/source-jar.jar") + checkBootClasspathForSystemModule(t, ctx, "lib-with-source-system-modules", "/source-jar.jar") - checkBootClasspathForLibWithSystemModule(t, ctx, "lib-with-prebuilt-system-modules", "/prebuilt-jar.jar") + checkBootClasspathForSystemModule(t, ctx, "lib-with-prebuilt-system-modules", "/prebuilt-jar.jar") } -func checkBootClasspathForLibWithSystemModule(t *testing.T, ctx *android.TestContext, moduleName string, expectedSuffix string) { +func checkBootClasspathForSystemModule(t *testing.T, ctx *android.TestContext, moduleName string, expectedSuffix string) { javacRule := ctx.ModuleForTests(moduleName, "android_common").Rule("javac") bootClasspath := javacRule.Args["bootClasspath"] if strings.HasPrefix(bootClasspath, "--system ") && strings.HasSuffix(bootClasspath, expectedSuffix) { @@ -2256,6 +2256,61 @@ func TestJavaApiLibraryStaticLibsLink(t *testing.T) { } } +func TestJavaApiLibraryFullApiSurfaceStub(t *testing.T) { + provider_bp_a := ` + java_api_contribution { + name: "foo1", + api_file: "current.txt", + api_surface: "public", + } + ` + provider_bp_b := ` + java_api_contribution { + name: "foo2", + api_file: "current.txt", + api_surface: "public", + } + ` + lib_bp_a := ` + java_api_library { + name: "lib1", + api_surface: "public", + api_contributions: ["foo1", "foo2"], + stubs_type: "everything", + } + ` + + ctx := android.GroupFixturePreparers( + prepareForJavaTest, + android.FixtureMergeMockFs( + map[string][]byte{ + "a/Android.bp": []byte(provider_bp_a), + "b/Android.bp": []byte(provider_bp_b), + "c/Android.bp": []byte(lib_bp_a), + }, + ), + android.FixtureMergeEnv( + map[string]string{ + "DISABLE_STUB_VALIDATION": "true", + }, + ), + ).RunTestWithBp(t, ` + java_api_library { + name: "bar1", + api_surface: "public", + api_contributions: ["foo1"], + full_api_surface_stub: "lib1", + stubs_type: "everything", + } + `) + + m := ctx.ModuleForTests("bar1", "android_common") + manifest := m.Output("metalava.sbox.textproto") + sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest) + manifestCommand := sboxProto.Commands[0].GetCommand() + android.AssertStringDoesContain(t, "Command expected to contain full_api_surface_stub output jar", manifestCommand, "lib1.jar") +} + func TestTransitiveSrcFiles(t *testing.T) { ctx, _ := testJava(t, ` java_library { @@ -2456,6 +2511,9 @@ func TestSdkLibraryProvidesSystemModulesToApiLibrary(t *testing.T) { prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, FixtureWithLastReleaseApis("foo"), + android.FixtureModifyConfig(func(config android.Config) { + config.SetApiLibraries([]string{"foo"}) + }), android.FixtureMergeMockFs( map[string][]byte{ "A.java": nil, @@ -2476,8 +2534,12 @@ func TestSdkLibraryProvidesSystemModulesToApiLibrary(t *testing.T) { system_modules: "baz", } `) - - checkBootClasspathForLibWithSystemModule(t, result.TestContext, apiScopePublic.apiLibraryModuleName("foo"), "/bar.jar") + m := result.ModuleForTests(apiScopePublic.apiLibraryModuleName("foo"), "android_common") + manifest := m.Output("metalava.sbox.textproto") + sboxProto := android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest) + manifestCommand := sboxProto.Commands[0].GetCommand() + classPathFlag := "--classpath __SBOX_SANDBOX_DIR__/out/soong/.intermediates/bar/android_common/turbine-combined/bar.jar" + android.AssertStringDoesContain(t, "command expected to contain classpath flag", manifestCommand, classPathFlag) } func TestApiLibraryDroidstubsDependency(t *testing.T) { @@ -2485,6 +2547,9 @@ func TestApiLibraryDroidstubsDependency(t *testing.T) { prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, FixtureWithLastReleaseApis("foo"), + android.FixtureModifyConfig(func(config android.Config) { + config.SetApiLibraries([]string{"foo"}) + }), android.FixtureMergeMockFs( map[string][]byte{ "A.java": nil, @@ -2533,6 +2598,7 @@ func TestDisableFromTextStubForCoverageBuild(t *testing.T) { PrepareForTestWithJacocoInstrumentation, FixtureWithLastReleaseApis("foo"), android.FixtureModifyConfig(func(config android.Config) { + config.SetApiLibraries([]string{"foo"}) config.SetBuildFromTextStub(true) }), android.FixtureModifyEnv(func(env map[string]string) { diff --git a/java/sdk_library.go b/java/sdk_library.go index b45341ab4..c5f7a1ce0 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -427,10 +427,22 @@ var ( apiScopeModuleLib, apiScopeSystemServer, } - apiLibraryAdditionalProperties = map[string]string{ - "legacy.i18n.module.platform.api": "i18n.module.public.api.stubs.source.api.contribution", - "stable.i18n.module.platform.api": "i18n.module.public.api.stubs.source.api.contribution", - "conscrypt.module.platform.api": "conscrypt.module.public.api.stubs.source.api.contribution", + apiLibraryAdditionalProperties = map[string]struct { + FullApiSurfaceStubLib string + AdditionalApiContribution string + }{ + "legacy.i18n.module.platform.api": { + FullApiSurfaceStubLib: "legacy.core.platform.api.stubs", + AdditionalApiContribution: "i18n.module.public.api.stubs.source.api.contribution", + }, + "stable.i18n.module.platform.api": { + FullApiSurfaceStubLib: "stable.core.platform.api.stubs", + AdditionalApiContribution: "i18n.module.public.api.stubs.source.api.contribution", + }, + "conscrypt.module.platform.api": { + FullApiSurfaceStubLib: "stable.core.platform.api.stubs", + AdditionalApiContribution: "conscrypt.module.public.api.stubs.source.api.contribution", + }, } ) @@ -638,6 +650,13 @@ type sdkLibraryProperties struct { Legacy_errors_allowed *bool } + // Determines if the module contributes to any api surfaces. + // This property should be set to true only if the module is listed under + // frameworks-base-api.bootclasspath in frameworks/base/api/Android.bp. + // Otherwise, this property should be set to false. + // 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 @@ -1732,13 +1751,30 @@ func (module *SdkLibrary) latestIncompatibilitiesModuleName(apiScope *apiScope) return latestPrebuiltApiModuleName(module.distStem()+"-incompatibilities", apiScope) } +func (module *SdkLibrary) contributesToApiSurface(c android.Config) bool { + _, exists := c.GetApiLibraries()[module.Name()] + return exists +} + +// The listed modules are the special java_sdk_libraries where apiScope.kind do not match the +// api surface that the module contribute to. For example, the public droidstubs and java_library +// do not contribute to the public api surface, but contributes to the core platform api surface. +// This method returns the full api surface stub lib that +// the generated java_api_library should depend on. +func (module *SdkLibrary) alternativeFullApiSurfaceStubLib() string { + if val, ok := apiLibraryAdditionalProperties[module.Name()]; ok { + return val.FullApiSurfaceStubLib + } + return "" +} + // The listed modules' stubs contents do not match the corresponding txt files, // but require additional api contributions to generate the full stubs. // This method returns the name of the additional api contribution module // for corresponding sdk_library modules. func (module *SdkLibrary) apiLibraryAdditionalApiContribution() string { if val, ok := apiLibraryAdditionalProperties[module.Name()]; ok { - return val + return val.AdditionalApiContribution } return "" } @@ -2033,18 +2069,17 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC mctx.CreateModule(DroidstubsFactory, &props, module.sdkComponentPropertiesForChildLibrary()).(*Droidstubs).CallHookIfAvailable(mctx) } -func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) { +func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope, alternativeFullApiSurfaceStub string) { props := struct { - Name *string - Visibility []string - Api_contributions []string - Libs []string - Static_libs []string - System_modules *string - Enable_validation *bool - Stubs_type *string - Sdk_version *string - Previous_api *string + Name *string + Visibility []string + Api_contributions []string + Libs []string + Static_libs []string + Full_api_surface_stub *string + System_modules *string + Enable_validation *bool + Stubs_type *string }{} props.Name = proptools.StringPtr(module.apiLibraryModuleName(apiScope)) @@ -2068,29 +2103,34 @@ func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, } props.Api_contributions = apiContributions - - // Ensure that stub-annotations is added to the classpath before any other libs - props.Libs = []string{"stub-annotations"} - props.Libs = append(props.Libs, module.properties.Libs...) - props.Libs = append(props.Libs, module.properties.Static_libs...) + props.Libs = module.properties.Libs props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...) props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...) + props.Libs = append(props.Libs, "stub-annotations") props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs + props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName()) + if alternativeFullApiSurfaceStub != "" { + props.Full_api_surface_stub = proptools.StringPtr(alternativeFullApiSurfaceStub) + } + + // android_module_lib_stubs_current.from-text only comprises api contributions from art, conscrypt and i18n. + // Thus, replace with android_module_lib_stubs_current_full.from-text, which comprises every api domains. + if apiScope.kind == android.SdkModule { + props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + "_full.from-text") + } + + // java_sdk_library modules that set sdk_version as none does not depend on other api + // domains. Therefore, java_api_library created from such modules should not depend on + // full_api_surface_stubs but create and compile stubs by the java_api_library module + // itself. + if module.SdkVersion(mctx).Kind == android.SdkNone { + props.Full_api_surface_stub = nil + } props.System_modules = module.deviceProperties.System_modules props.Enable_validation = proptools.BoolPtr(true) props.Stubs_type = proptools.StringPtr("everything") - if module.deviceProperties.Sdk_version != nil { - props.Sdk_version = module.deviceProperties.Sdk_version - } - - if module.compareAgainstLatestApi(apiScope) { - // check against the latest released API - latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope)) - props.Previous_api = latestApiFilegroupName - } - mctx.CreateModule(ApiLibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) } @@ -2121,7 +2161,7 @@ func (module *SdkLibrary) topLevelStubsLibraryProps(mctx android.DefaultableHook } func (module *SdkLibrary) createTopLevelStubsLibrary( - mctx android.DefaultableHookContext, apiScope *apiScope) { + mctx android.DefaultableHookContext, apiScope *apiScope, contributesToApiSurface bool) { // Dist the "everything" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is false doDist := !mctx.Config().ReleaseHiddenApiExportableStubs() @@ -2130,7 +2170,7 @@ func (module *SdkLibrary) createTopLevelStubsLibrary( // Add the stub compiling java_library/java_api_library as static lib based on build config staticLib := module.sourceStubsLibraryModuleName(apiScope) - if mctx.Config().BuildFromTextStub() && module.ModuleBuildFromTextStubs() { + if mctx.Config().BuildFromTextStub() && contributesToApiSurface { staticLib = module.apiLibraryModuleName(apiScope) } props.Static_libs = append(props.Static_libs, staticLib) @@ -2173,8 +2213,8 @@ func (module *SdkLibrary) UniqueApexVariations() bool { return module.uniqueApexVariations() } -func (module *SdkLibrary) ModuleBuildFromTextStubs() bool { - return proptools.BoolDefault(module.sdkLibraryProperties.Build_from_text_stub, true) +func (module *SdkLibrary) ContributeToApi() bool { + return proptools.BoolDefault(module.sdkLibraryProperties.Contribute_to_android_api, false) } // Creates the xml file that publicizes the runtime library @@ -2350,10 +2390,16 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont module.createStubsLibrary(mctx, scope) module.createExportableStubsLibrary(mctx, scope) - if mctx.Config().BuildFromTextStub() && module.ModuleBuildFromTextStubs() { - module.createApiLibrary(mctx, scope) + alternativeFullApiSurfaceStubLib := "" + if scope == apiScopePublic { + alternativeFullApiSurfaceStubLib = module.alternativeFullApiSurfaceStubLib() } - module.createTopLevelStubsLibrary(mctx, scope) + contributesToApiSurface := module.contributesToApiSurface(mctx.Config()) || alternativeFullApiSurfaceStubLib != "" + if contributesToApiSurface { + module.createApiLibrary(mctx, scope, alternativeFullApiSurfaceStubLib) + } + + module.createTopLevelStubsLibrary(mctx, scope, contributesToApiSurface) module.createTopLevelExportableStubsLibrary(mctx, scope) } diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go index f9c3dd5eb..a8a1494ee 100644 --- a/java/sdk_library_test.go +++ b/java/sdk_library_test.go @@ -35,6 +35,9 @@ func TestJavaSdkLibrary(t *testing.T) { "29": {"foo"}, "30": {"bar", "barney", "baz", "betty", "foo", "fred", "quuz", "wilma"}, }), + android.FixtureModifyConfig(func(config android.Config) { + config.SetApiLibraries([]string{"foo"}) + }), android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { variables.BuildFlags = map[string]string{ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true", @@ -1585,6 +1588,9 @@ func TestJavaSdkLibrary_ApiLibrary(t *testing.T) { prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, FixtureWithLastReleaseApis("foo"), + android.FixtureModifyConfig(func(config android.Config) { + config.SetApiLibraries([]string{"foo"}) + }), ).RunTestWithBp(t, ` java_sdk_library { name: "foo", @@ -1603,30 +1609,36 @@ func TestJavaSdkLibrary_ApiLibrary(t *testing.T) { `) testCases := []struct { - scope *apiScope - apiContributions []string + scope *apiScope + apiContributions []string + fullApiSurfaceStub string }{ { - scope: apiScopePublic, - apiContributions: []string{"foo.stubs.source.api.contribution"}, + scope: apiScopePublic, + apiContributions: []string{"foo.stubs.source.api.contribution"}, + fullApiSurfaceStub: "android_stubs_current", }, { - scope: apiScopeSystem, - apiContributions: []string{"foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"}, + scope: apiScopeSystem, + apiContributions: []string{"foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"}, + fullApiSurfaceStub: "android_system_stubs_current", }, { - scope: apiScopeTest, - apiContributions: []string{"foo.stubs.source.test.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"}, + scope: apiScopeTest, + apiContributions: []string{"foo.stubs.source.test.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"}, + fullApiSurfaceStub: "android_test_stubs_current", }, { - scope: apiScopeModuleLib, - apiContributions: []string{"foo.stubs.source.module_lib.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"}, + scope: apiScopeModuleLib, + apiContributions: []string{"foo.stubs.source.module_lib.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"}, + fullApiSurfaceStub: "android_module_lib_stubs_current_full.from-text", }, } for _, c := range testCases { m := result.ModuleForTests(c.scope.apiLibraryModuleName("foo"), "android_common").Module().(*ApiLibrary) android.AssertArrayString(t, "Module expected to contain api contributions", c.apiContributions, m.properties.Api_contributions) + android.AssertStringEquals(t, "Module expected to contain full api surface api library", c.fullApiSurfaceStub, *m.properties.Full_api_surface_stub) } } @@ -1696,6 +1708,9 @@ func TestSdkLibraryExportableStubsLibrary(t *testing.T) { prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, FixtureWithLastReleaseApis("foo"), + android.FixtureModifyConfig(func(config android.Config) { + config.SetApiLibraries([]string{"foo"}) + }), ).RunTestWithBp(t, ` aconfig_declarations { name: "bar", diff --git a/java/testing.go b/java/testing.go index a99baf8a2..7a42e4cce 100644 --- a/java/testing.go +++ b/java/testing.go @@ -486,17 +486,21 @@ func gatherRequiredDepsForTest() string { } extraApiLibraryModules := map[string]droidstubsStruct{ - "android_stubs_current.from-text": publicDroidstubs, - "android_system_stubs_current.from-text": systemDroidstubs, - "android_test_stubs_current.from-text": testDroidstubs, - "android_module_lib_stubs_current.from-text": moduleLibDroidstubs, - "android_module_lib_stubs_current_full.from-text": moduleLibDroidstubs, - "android_system_server_stubs_current.from-text": systemServerDroidstubs, - "core.current.stubs.from-text": publicDroidstubs, - "legacy.core.platform.api.stubs.from-text": publicDroidstubs, - "stable.core.platform.api.stubs.from-text": publicDroidstubs, - "core-lambda-stubs.from-text": publicDroidstubs, - "android-non-updatable.stubs.test_module_lib": moduleLibDroidstubs, + "android_stubs_current.from-text": publicDroidstubs, + "android_system_stubs_current.from-text": systemDroidstubs, + "android_test_stubs_current.from-text": testDroidstubs, + "android_module_lib_stubs_current.from-text": moduleLibDroidstubs, + "android_module_lib_stubs_current_full.from-text": moduleLibDroidstubs, + "android_system_server_stubs_current.from-text": systemServerDroidstubs, + "core.current.stubs.from-text": publicDroidstubs, + "legacy.core.platform.api.stubs.from-text": publicDroidstubs, + "stable.core.platform.api.stubs.from-text": publicDroidstubs, + "core-lambda-stubs.from-text": publicDroidstubs, + "android-non-updatable.stubs.from-text": publicDroidstubs, + "android-non-updatable.stubs.system.from-text": systemDroidstubs, + "android-non-updatable.stubs.test.from-text": testDroidstubs, + "android-non-updatable.stubs.module_lib.from-text": moduleLibDroidstubs, + "android-non-updatable.stubs.test_module_lib": moduleLibDroidstubs, } for _, droidstubs := range droidstubsStructs { @@ -525,8 +529,6 @@ func gatherRequiredDepsForTest() string { name: "%s", api_contributions: ["%s"], stubs_type: "everything", - sdk_version: "none", - system_modules: "none", } `, libName, droidstubs.name+".api.contribution") }