diff --git a/java/droidstubs.go b/java/droidstubs.go index 5fbf6c063..bdbaf9281 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -1329,7 +1329,9 @@ type PrebuiltStubsSources struct { func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) { switch tag { - case "": + // prebuilt droidstubs does not output "exportable" stubs. + // Output the "everything" stubs srcjar file if the tag is ".exportable". + case "", ".exportable": return android.Paths{p.stubsSrcJar}, nil default: return nil, fmt.Errorf("unsupported module reference tag %q", tag) diff --git a/java/sdk_library.go b/java/sdk_library.go index 6998bd2c9..0df869edf 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -231,6 +231,10 @@ func (scope *apiScope) stubsLibraryModuleNameSuffix() string { return ".stubs" + scope.moduleSuffix } +func (scope *apiScope) exportableStubsLibraryModuleNameSuffix() string { + return ".stubs.exportable" + scope.moduleSuffix +} + func (scope *apiScope) apiLibraryModuleName(baseName string) string { return scope.stubsLibraryModuleName(baseName) + ".from-text" } @@ -239,10 +243,18 @@ func (scope *apiScope) sourceStubLibraryModuleName(baseName string) string { return scope.stubsLibraryModuleName(baseName) + ".from-source" } +func (scope *apiScope) exportableSourceStubsLibraryModuleName(baseName string) string { + return scope.exportableStubsLibraryModuleName(baseName) + ".from-source" +} + func (scope *apiScope) stubsLibraryModuleName(baseName string) string { return baseName + scope.stubsLibraryModuleNameSuffix() } +func (scope *apiScope) exportableStubsLibraryModuleName(baseName string) string { + return baseName + scope.exportableStubsLibraryModuleNameSuffix() +} + func (scope *apiScope) stubsSourceModuleName(baseName string) string { return baseName + ".stubs.source" + scope.moduleSuffix } @@ -895,6 +907,12 @@ func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) return c.namingScheme.stubsLibraryModuleName(apiScope, baseName) } +// Name of the java_library module that compiles the exportable stubs source. +func (c *commonToSdkLibraryAndImport) exportableStubsLibraryModuleName(apiScope *apiScope) string { + baseName := c.module.BaseModuleName() + return c.namingScheme.exportableStubsLibraryModuleName(apiScope, baseName) +} + // Name of the droidstubs module that generates the stubs source and may also // generate/check the API. func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope) string { @@ -911,9 +929,16 @@ func (c *commonToSdkLibraryAndImport) apiLibraryModuleName(apiScope *apiScope) s // Name of the java_library module that compiles the stubs // generated from source Java files. -func (c *commonToSdkLibraryAndImport) sourceStubLibraryModuleName(apiScope *apiScope) string { +func (c *commonToSdkLibraryAndImport) sourceStubsLibraryModuleName(apiScope *apiScope) string { baseName := c.module.BaseModuleName() - return c.namingScheme.sourceStubLibraryModuleName(apiScope, baseName) + return c.namingScheme.sourceStubsLibraryModuleName(apiScope, baseName) +} + +// Name of the java_library module that compiles the exportable stubs +// generated from source Java files. +func (c *commonToSdkLibraryAndImport) exportableSourceStubsLibraryModuleName(apiScope *apiScope) string { + baseName := c.module.BaseModuleName() + return c.namingScheme.exportableSourceStubsLibraryModuleName(apiScope, baseName) } // The component names for different outputs of the java_sdk_library. @@ -1629,36 +1654,34 @@ func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) mctx.CreateModule(LibraryFactory, properties...) } -// Creates a static java library that has API stubs -func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) { - props := struct { - Name *string - Visibility []string - Srcs []string - Installable *bool - Sdk_version *string - System_modules *string - Patch_module *string - Libs []string - Static_libs []string - Compile_dex *bool - Java_version *string - Openjdk9 struct { - Srcs []string - Javacflags []string - } - Dist struct { - Targets []string - Dest *string - Dir *string - Tag *string - } - }{} +type libraryProperties struct { + Name *string + Visibility []string + Srcs []string + Installable *bool + Sdk_version *string + System_modules *string + Patch_module *string + Libs []string + Static_libs []string + Compile_dex *bool + Java_version *string + Openjdk9 struct { + Srcs []string + Javacflags []string + } + Dist struct { + Targets []string + Dest *string + Dir *string + Tag *string + } +} - props.Name = proptools.StringPtr(module.sourceStubLibraryModuleName(apiScope)) +func (module *SdkLibrary) stubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope) libraryProperties { + props := libraryProperties{} props.Visibility = []string{"//visibility:override", "//visibility:private"} // sources are generated from the droiddoc - props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope)} sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope) props.Sdk_version = proptools.StringPtr(sdkVersion) props.System_modules = module.deviceProperties.System_modules @@ -1678,6 +1701,25 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext // interop with older developer tools that don't support 1.9. props.Java_version = proptools.StringPtr("1.8") + return props +} + +// Creates a static java library that has API stubs +func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) { + + props := module.stubsLibraryProps(mctx, apiScope) + props.Name = proptools.StringPtr(module.sourceStubsLibraryModuleName(apiScope)) + props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope)} + + mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) +} + +// Create a static java library that compiles the "exportable" stubs +func (module *SdkLibrary) createExportableStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) { + props := module.stubsLibraryProps(mctx, apiScope) + props.Name = proptools.StringPtr(module.exportableSourceStubsLibraryModuleName(apiScope)) + props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope) + "{.exportable}"} + mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) } @@ -1908,43 +1950,15 @@ func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, mctx.CreateModule(ApiLibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) } -func (module *SdkLibrary) createTopLevelStubsLibrary( - mctx android.DefaultableHookContext, apiScope *apiScope, contributesToApiSurface bool) { - props := struct { - Name *string - Visibility []string - Sdk_version *string - Static_libs []string - System_modules *string - Dist struct { - Targets []string - Dest *string - Dir *string - Tag *string - } - Compile_dex *bool - }{} - props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope)) +func (module *SdkLibrary) topLevelStubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope) libraryProperties { + props := libraryProperties{} + props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility) sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope) props.Sdk_version = proptools.StringPtr(sdkVersion) - // Add the stub compiling java_library/java_api_library as static lib based on build config - staticLib := module.sourceStubLibraryModuleName(apiScope) - if mctx.Config().BuildFromTextStub() && contributesToApiSurface { - staticLib = module.apiLibraryModuleName(apiScope) - } - props.Static_libs = append(props.Static_libs, staticLib) props.System_modules = module.deviceProperties.System_modules - // Dist the class jar artifact for sdk builds. - if !Bool(module.sdkLibraryProperties.No_dist) { - props.Dist.Targets = []string{"sdk", "win_sdk"} - props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem())) - props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope)) - props.Dist.Tag = proptools.StringPtr(".jar") - } - // The imports need to be compiled to dex if the java_sdk_library requests it. compileDex := module.dexProperties.Compile_dex if module.stubLibrariesCompiledForDex() { @@ -1952,6 +1966,43 @@ func (module *SdkLibrary) createTopLevelStubsLibrary( } props.Compile_dex = compileDex + return props +} + +func (module *SdkLibrary) createTopLevelStubsLibrary( + mctx android.DefaultableHookContext, apiScope *apiScope, contributesToApiSurface bool) { + + props := module.topLevelStubsLibraryProps(mctx, apiScope) + props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope)) + + // Add the stub compiling java_library/java_api_library as static lib based on build config + staticLib := module.sourceStubsLibraryModuleName(apiScope) + if mctx.Config().BuildFromTextStub() && contributesToApiSurface { + staticLib = module.apiLibraryModuleName(apiScope) + } + props.Static_libs = append(props.Static_libs, staticLib) + + mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) +} + +func (module *SdkLibrary) createTopLevelExportableStubsLibrary( + mctx android.DefaultableHookContext, apiScope *apiScope) { + + props := module.topLevelStubsLibraryProps(mctx, apiScope) + props.Name = proptools.StringPtr(module.exportableStubsLibraryModuleName(apiScope)) + + // Dist the class jar artifact for sdk builds. + // "exportable" stubs are copied to dist for sdk builds instead of the "everything" stubs. + if !Bool(module.sdkLibraryProperties.No_dist) { + props.Dist.Targets = []string{"sdk", "win_sdk"} + props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem())) + props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope)) + props.Dist.Tag = proptools.StringPtr(".jar") + } + + staticLib := module.exportableSourceStubsLibraryModuleName(apiScope) + props.Static_libs = append(props.Static_libs, staticLib) + mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) } @@ -2157,6 +2208,7 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont module.createStubsSourcesAndApi(mctx, scope, module.stubsSourceModuleName(scope), scope.droidstubsArgs) module.createStubsLibrary(mctx, scope) + module.createExportableStubsLibrary(mctx, scope) alternativeFullApiSurfaceStubLib := "" if scope == apiScopePublic { @@ -2168,6 +2220,7 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont } module.createTopLevelStubsLibrary(mctx, scope, contributesToApiSurface) + module.createTopLevelExportableStubsLibrary(mctx, scope) } if module.requiresRuntimeImplementationLibrary() { @@ -2223,7 +2276,11 @@ type sdkLibraryComponentNamingScheme interface { apiLibraryModuleName(scope *apiScope, baseName string) string - sourceStubLibraryModuleName(scope *apiScope, baseName string) string + sourceStubsLibraryModuleName(scope *apiScope, baseName string) string + + exportableStubsLibraryModuleName(scope *apiScope, baseName string) string + + exportableSourceStubsLibraryModuleName(scope *apiScope, baseName string) string } type defaultNamingScheme struct { @@ -2241,34 +2298,47 @@ func (s *defaultNamingScheme) apiLibraryModuleName(scope *apiScope, baseName str return scope.apiLibraryModuleName(baseName) } -func (s *defaultNamingScheme) sourceStubLibraryModuleName(scope *apiScope, baseName string) string { +func (s *defaultNamingScheme) sourceStubsLibraryModuleName(scope *apiScope, baseName string) string { return scope.sourceStubLibraryModuleName(baseName) } +func (s *defaultNamingScheme) exportableStubsLibraryModuleName(scope *apiScope, baseName string) string { + return scope.exportableStubsLibraryModuleName(baseName) +} + +func (s *defaultNamingScheme) exportableSourceStubsLibraryModuleName(scope *apiScope, baseName string) string { + return scope.exportableSourceStubsLibraryModuleName(baseName) +} + var _ sdkLibraryComponentNamingScheme = (*defaultNamingScheme)(nil) +func hasStubsLibrarySuffix(name string, apiScope *apiScope) bool { + return strings.HasSuffix(name, apiScope.stubsLibraryModuleNameSuffix()) || + strings.HasSuffix(name, apiScope.exportableStubsLibraryModuleNameSuffix()) +} + func moduleStubLinkType(name string) (stub bool, ret sdkLinkType) { name = strings.TrimSuffix(name, ".from-source") // This suffix-based approach is fragile and could potentially mis-trigger. // TODO(b/155164730): Clean this up when modules no longer reference sdk_lib stubs directly. - if strings.HasSuffix(name, apiScopePublic.stubsLibraryModuleNameSuffix()) { + if hasStubsLibrarySuffix(name, apiScopePublic) { if name == "hwbinder.stubs" || name == "libcore_private.stubs" { // Due to a previous bug, these modules were not considered stubs, so we retain that. return false, javaPlatform } return true, javaSdk } - if strings.HasSuffix(name, apiScopeSystem.stubsLibraryModuleNameSuffix()) { + if hasStubsLibrarySuffix(name, apiScopeSystem) { return true, javaSystem } - if strings.HasSuffix(name, apiScopeModuleLib.stubsLibraryModuleNameSuffix()) { + if hasStubsLibrarySuffix(name, apiScopeModuleLib) { return true, javaModule } - if strings.HasSuffix(name, apiScopeTest.stubsLibraryModuleNameSuffix()) { + if hasStubsLibrarySuffix(name, apiScopeTest) { return true, javaSystem } - if strings.HasSuffix(name, apiScopeSystemServer.stubsLibraryModuleNameSuffix()) { + if hasStubsLibrarySuffix(name, apiScopeSystemServer) { return true, javaSystemServer } return false, javaPlatform diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go index 63419d6b1..c14f3e611 100644 --- a/java/sdk_library_test.go +++ b/java/sdk_library_test.go @@ -1423,7 +1423,7 @@ func TestJavaSdkLibraryDist(t *testing.T) { for _, tt := range testCases { t.Run(tt.module, func(t *testing.T) { - m := result.ModuleForTests(tt.module+".stubs", "android_common").Module().(*Library) + m := result.ModuleForTests(apiScopePublic.exportableStubsLibraryModuleName(tt.module), "android_common").Module().(*Library) dists := m.Dists() if len(dists) != 1 { t.Fatalf("expected exactly 1 dist entry, got %d", len(dists)) @@ -1693,3 +1693,56 @@ func TestSdkLibraryDependency(t *testing.T) { android.AssertStringDoesContain(t, "bar.xml java_sdk_xml command", barPermissions.RuleParams.Command, `dependency=\"foo\"`) } + +func TestSdkLibraryExportableStubsLibrary(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForJavaTest, + PrepareForTestWithJavaSdkLibraryFiles, + FixtureWithLastReleaseApis("foo"), + android.FixtureModifyConfig(func(config android.Config) { + config.SetApiLibraries([]string{"foo"}) + }), + ).RunTestWithBp(t, ` + aconfig_declarations { + name: "bar", + package: "com.example.package", + srcs: [ + "bar.aconfig", + ], + } + java_sdk_library { + name: "foo", + srcs: ["a.java", "b.java"], + api_packages: ["foo"], + system: { + enabled: true, + }, + module_lib: { + enabled: true, + }, + test: { + enabled: true, + }, + aconfig_declarations: [ + "bar", + ], + } + `) + + exportableStubsLibraryModuleName := apiScopePublic.exportableStubsLibraryModuleName("foo") + exportableSourceStubsLibraryModuleName := apiScopePublic.exportableSourceStubsLibraryModuleName("foo") + + // Check modules generation + topLevelModule := result.ModuleForTests(exportableStubsLibraryModuleName, "android_common") + result.ModuleForTests(exportableSourceStubsLibraryModuleName, "android_common") + + // Check static lib dependency + android.AssertBoolEquals(t, "exportable top level stubs library module depends on the"+ + "exportable source stubs library module", true, + CheckModuleHasDependency(t, result.TestContext, exportableStubsLibraryModuleName, + "android_common", exportableSourceStubsLibraryModuleName), + ) + android.AssertArrayString(t, "exportable source stub library is a static lib of the"+ + "top level exportable stubs library", []string{exportableSourceStubsLibraryModuleName}, + topLevelModule.Module().(*Library).properties.Static_libs) +}