From 64e61997569dde18f70abac001942ee677bccab0 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Fri, 15 May 2020 10:20:31 +0100 Subject: [PATCH 1/2] Retry: "Improve tracking of exported sdk libraries" The build tracks the java_sdk_library/_import modules that are referenced by libraries so that it can ensure that any Android app that includes code that depends on one of those modules has the appropriate entry in their manifest. Unfortunately, there were a couple of issues with that: 1) It only tracks direct references to the java_sdk_library module itself, e.g. android.test.mock. Direct references to the stubs module, e.g. android.test.mock.stubs were not tracked. Making it possible for Android apps to reference libraries which would not be available at runtime. 2) The logic for determining whether something was a java_sdk_library was repeated in a number of places making it difficult to allow java_sdk_library/_import instances to determine whether they should be treated as an Android shared library. 3) It tracks (and could use) even those java_sdk_library instances which do not represent a shared library, e.g. the ones that set api_only: true. While this change will simplifty fixing that the actual issue will be fixed in a follow up change. Changes: * Added EmbeddableSdkLibraryComponent and embedded it into java_sdk_library/_import, java_library and java_import. It provides the common code to minimize duplication. It contains an SdkLibraryToImplicitlyTrack field that if set will cause any references to the containing module to add the SdkLibraryParent to the list of implicit sdk libraries being tracked. * Changed code that assumed that anything that implemented SdkLibraryDependency required tracking to use the OptionalImplicitSdkLibrary() method to get the optional name of the sdk library to track. That will allow a follow up change to return nil from that method to exclude an sdk library from being tracked. * Moved SdkLibraryDependency from java.go to sdk_library.go as that is a better place for it to be. * Changed the stubs java_library/java_import creation code to initialize the SdkLibraryToImplicitlyTrack field with the name of the creating module. * Initialized the SdkLibraryToImplicitlyTrack field in the java_sdk_library/_import so that direct references to them will be tracked too. * Added tests to verify that direct access to the .stubs child of both java_sdk_library and java_sdk_library_import are tracked properly. Test: atest CtsProviderTestCases - which relies on android.test.mock being implicitly tracked to verify that I had not broken anything. Used aapt2 dump badging to read the manifest. m nothing - to run the new tests which failed before fixing the code. Bug: 156723295 (cherry picked from commit 859fe961b015259368e9994969b569eb34f54ddc) Change-Id: I760a9ac72856e3a07a497ce40db70c7e70106837 --- java/aar.go | 7 +++- java/app_test.go | 24 ++++++++++++ java/java.go | 33 +++++++++++++--- java/java_test.go | 22 +++++++++-- java/sdk_library.go | 94 ++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 166 insertions(+), 14 deletions(-) diff --git a/java/aar.go b/java/aar.go index 0e103f248..c8daf835b 100644 --- a/java/aar.go +++ b/java/aar.go @@ -379,8 +379,11 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati sharedLibs = append(sharedLibs, exportPackage) } - if _, ok := module.(SdkLibraryDependency); ok { - sdkLibraries = append(sdkLibraries, ctx.OtherModuleName(module)) + // If the module is (or possibly could be) a component of a java_sdk_library + // (including the java_sdk_library) itself then append any implicit sdk library + // names to the list of sdk libraries to be added to the manifest. + if component, ok := module.(SdkLibraryComponentDependency); ok { + sdkLibraries = append(sdkLibraries, component.OptionalImplicitSdkLibrary()...) } case frameworkResTag: diff --git a/java/app_test.go b/java/app_test.go index c731a1713..12b935ed3 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -2382,6 +2382,20 @@ func TestUsesLibraries(t *testing.T) { sdk_version: "current", } + java_sdk_library { + name: "qux", + srcs: ["a.java"], + api_packages: ["qux"], + sdk_version: "current", + } + + java_sdk_library { + name: "quuz", + srcs: ["a.java"], + api_packages: ["quuz"], + sdk_version: "current", + } + java_sdk_library { name: "bar", srcs: ["a.java"], @@ -2392,6 +2406,7 @@ func TestUsesLibraries(t *testing.T) { android_app { name: "app", srcs: ["a.java"], + libs: ["qux", "quuz.stubs"], uses_libs: ["foo"], sdk_version: "current", optional_uses_libs: [ @@ -2422,6 +2437,15 @@ func TestUsesLibraries(t *testing.T) { app := ctx.ModuleForTests("app", "android_common") prebuilt := ctx.ModuleForTests("prebuilt", "android_common") + // Test that implicit dependencies on java_sdk_library instances are passed to the manifest. + manifestFixerArgs := app.Output("manifest_fixer/AndroidManifest.xml").Args["args"] + if w := "--uses-library qux"; !strings.Contains(manifestFixerArgs, w) { + t.Errorf("unexpected manifest_fixer args: wanted %q in %q", w, manifestFixerArgs) + } + if w := "--uses-library quuz"; !strings.Contains(manifestFixerArgs, w) { + t.Errorf("unexpected manifest_fixer args: wanted %q in %q", w, manifestFixerArgs) + } + // Test that all libraries are verified cmd := app.Rule("verify_uses_libraries").RuleParams.Command if w := "--uses-library foo"; !strings.Contains(cmd, w) { diff --git a/java/java.go b/java/java.go index da9bd3dfe..00b11f77a 100644 --- a/java/java.go +++ b/java/java.go @@ -355,7 +355,17 @@ func (me *CompilerDeviceProperties) EffectiveOptimizeEnabled() bool { } // Functionality common to Module and Import +// +// It is embedded in Module so its functionality can be used by methods in Module +// but it is currently only initialized by Import and Library. type embeddableInModuleAndImport struct { + + // Functionality related to this being used as a component of a java_sdk_library. + EmbeddableSdkLibraryComponent +} + +func (e *embeddableInModuleAndImport) initModuleAndImport(moduleBase *android.ModuleBase) { + e.initSdkLibraryComponent(moduleBase) } // Module/Import's DepIsInSameApex(...) delegates to this method. @@ -496,11 +506,6 @@ type Dependency interface { JacocoReportClassesFile() android.Path } -type SdkLibraryDependency interface { - SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths - SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths -} - type xref interface { XrefJavaFiles() android.Paths } @@ -930,6 +935,12 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { } } + // If this is a component library (stubs, etc.) for a java_sdk_library then + // add the name of that java_sdk_library to the exported sdk libs to make sure + // that, if necessary, a element for that java_sdk_library is + // added to the Android manifest. + j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...) + ctx.VisitDirectDeps(func(module android.Module) { otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) @@ -949,7 +960,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { case libTag: deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...) // names of sdk libs that are directly depended are exported - j.exportedSdkLibs = append(j.exportedSdkLibs, otherName) + j.exportedSdkLibs = append(j.exportedSdkLibs, dep.OptionalImplicitSdkLibrary()...) case staticLibTag: ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName) } @@ -1990,6 +2001,8 @@ func LibraryFactory() android.Module { &module.Module.protoProperties, &module.libraryProperties) + module.initModuleAndImport(&module.ModuleBase) + android.InitApexModule(module) android.InitSdkAwareModule(module) InitJavaModule(module, android.HostAndDeviceSupported) @@ -2451,6 +2464,12 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { } j.combinedClasspathFile = outputFile + // If this is a component library (impl, stubs, etc.) for a java_sdk_library then + // add the name of that java_sdk_library to the exported sdk libs to make sure + // that, if necessary, a element for that java_sdk_library is + // added to the Android manifest. + j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...) + ctx.VisitDirectDeps(func(module android.Module) { otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) @@ -2567,6 +2586,8 @@ func ImportFactory() android.Module { module.AddProperties(&module.properties) + module.initModuleAndImport(&module.ModuleBase) + android.InitPrebuiltModule(module, &module.properties.Jars) android.InitApexModule(module) android.InitSdkAwareModule(module) diff --git a/java/java_test.go b/java/java_test.go index 4f3a803ff..4c085cf0f 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -19,6 +19,7 @@ import ( "os" "path/filepath" "reflect" + "sort" "strconv" "strings" "testing" @@ -1153,13 +1154,25 @@ func TestJavaSdkLibrary(t *testing.T) { java_library { name: "baz", srcs: ["c.java"], - libs: ["foo", "bar"], + libs: ["foo", "bar.stubs"], sdk_version: "system_current", } + java_sdk_library_import { + name: "quuz", + public: { + jars: ["c.jar"], + }, + } + java_sdk_library_import { + name: "fred", + public: { + jars: ["b.jar"], + }, + } java_library { name: "qux", srcs: ["c.java"], - libs: ["baz"], + libs: ["baz", "fred", "quuz.stubs"], sdk_version: "system_current", } java_library { @@ -1224,8 +1237,9 @@ func TestJavaSdkLibrary(t *testing.T) { qux := ctx.ModuleForTests("qux", "android_common") if quxLib, ok := qux.Module().(*Library); ok { sdkLibs := quxLib.ExportedSdkLibs() - if len(sdkLibs) != 2 || !android.InList("foo", sdkLibs) || !android.InList("bar", sdkLibs) { - t.Errorf("qux should export \"foo\" and \"bar\" but exports %v", sdkLibs) + sort.Strings(sdkLibs) + if w := []string{"bar", "foo", "fred", "quuz"}; !reflect.DeepEqual(w, sdkLibs) { + t.Errorf("qux should export %q but exports %q", w, sdkLibs) } } } diff --git a/java/sdk_library.go b/java/sdk_library.go index b215a76f7..de30635b4 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -543,12 +543,18 @@ type commonToSdkLibraryAndImport struct { namingScheme sdkLibraryComponentNamingScheme commonProperties commonToSdkLibraryAndImportProperties + + // Functionality related to this being used as a component of a java_sdk_library. + EmbeddableSdkLibraryComponent } func (c *commonToSdkLibraryAndImport) initCommon(moduleBase *android.ModuleBase) { c.moduleBase = moduleBase moduleBase.AddProperties(&c.commonProperties) + + // Initialize this as an sdk library component. + c.initSdkLibraryComponent(moduleBase) } func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android.DefaultableHookContext) bool { @@ -563,6 +569,9 @@ func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android return false } + // Use the name specified in the module definition as the owner. + c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.moduleBase.BaseModuleName()) + return true } @@ -728,6 +737,84 @@ func (c *commonToSdkLibraryAndImport) selectHeaderJarsForSdkVersion(ctx android. return paths.stubsHeaderPath } +func (c *commonToSdkLibraryAndImport) sdkComponentPropertiesForChildLibrary() interface{} { + componentProps := &struct { + SdkLibraryToImplicitlyTrack *string + }{ + // Mark the stubs library as being components of this java_sdk_library so that + // any app that includes code which depends (directly or indirectly) on the stubs + // library will have the appropriate invocation inserted into its + // manifest if necessary. + SdkLibraryToImplicitlyTrack: proptools.StringPtr(c.moduleBase.BaseModuleName()), + } + + return componentProps +} + +// Properties related to the use of a module as an component of a java_sdk_library. +type SdkLibraryComponentProperties struct { + + // The name of the java_sdk_library/_import to add to a entry + // in the AndroidManifest.xml of any Android app that includes code that references + // this module. If not set then no java_sdk_library/_import is tracked. + SdkLibraryToImplicitlyTrack *string `blueprint:"mutated"` +} + +// Structure to be embedded in a module struct that needs to support the +// SdkLibraryComponentDependency interface. +type EmbeddableSdkLibraryComponent struct { + sdkLibraryComponentProperties SdkLibraryComponentProperties +} + +func (e *EmbeddableSdkLibraryComponent) initSdkLibraryComponent(moduleBase *android.ModuleBase) { + moduleBase.AddProperties(&e.sdkLibraryComponentProperties) +} + +// to satisfy SdkLibraryComponentDependency +func (e *EmbeddableSdkLibraryComponent) OptionalImplicitSdkLibrary() []string { + if e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack != nil { + return []string{*e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack} + } + return nil +} + +// Implemented by modules that are (or possibly could be) a component of a java_sdk_library +// (including the java_sdk_library) itself. +type SdkLibraryComponentDependency interface { + // The optional name of the sdk library that should be implicitly added to the + // AndroidManifest of an app that contains code which references the sdk library. + // + // Returns an array containing 0 or 1 items rather than a *string to make it easier + // to append this to the list of exported sdk libraries. + OptionalImplicitSdkLibrary() []string +} + +// Make sure that all the module types that are components of java_sdk_library/_import +// and which can be referenced (directly or indirectly) from an android app implement +// the SdkLibraryComponentDependency interface. +var _ SdkLibraryComponentDependency = (*Library)(nil) +var _ SdkLibraryComponentDependency = (*Import)(nil) +var _ SdkLibraryComponentDependency = (*SdkLibrary)(nil) +var _ SdkLibraryComponentDependency = (*sdkLibraryImport)(nil) + +// Provides access to sdk_version related header and implentation jars. +type SdkLibraryDependency interface { + SdkLibraryComponentDependency + + // Get the header jars appropriate for the supplied sdk_version. + // + // These are turbine generated jars so they only change if the externals of the + // class changes but it does not contain and implementation or JavaDoc. + SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths + + // Get the implementation jars appropriate for the supplied sdk version. + // + // These are either the implementation jar for the whole sdk library or the implementation + // jars for the stubs. The latter should only be needed when generating JavaDoc as otherwise + // they are identical to the corresponding header jars. + SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths +} + type SdkLibrary struct { Library @@ -981,7 +1068,7 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext props.Dist.Tag = proptools.StringPtr(".jar") } - mctx.CreateModule(LibraryFactory, &props) + mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) } // Creates a droidstubs module that creates stubs source files from the given full source @@ -1326,6 +1413,8 @@ func (module *SdkLibrary) InitSdkLibraryProperties() { &module.protoProperties, ) + module.initSdkLibraryComponent(&module.ModuleBase) + module.properties.Installable = proptools.BoolPtr(true) module.deviceProperties.IsSDKLibrary = true } @@ -1574,7 +1663,8 @@ func (module *sdkLibraryImport) createJavaImportForStubs(mctx android.Defaultabl // The imports are preferred if the java_sdk_library_import is preferred. props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer()) - mctx.CreateModule(ImportFactory, &props) + + mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary()) } func (module *sdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) { From d11e78e641dfbe235d9edbd11f4ed26189ffd74d Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Fri, 15 May 2020 20:37:11 +0100 Subject: [PATCH 2/2] Retry: "java_sdk_library: Control shared library use" Previously, all java_sdk_library instances were assumed to be usable as shared libraries, i.e. referenced from in Android manifest. However, that was not true for any instances that specified api_only: true and will not be true for many of the new Android modules. One consequence of this assumption is that use of one of the api_only instances could (but fortunately does not appear to) have lead to an invalid library being referenced in an app's manifest which would prevent the app from loading. That would have been done automatically by the implicit sdk library tracking and manifest fixing mechanism and there would have been nothing a developer could have done about it. Changes: 1) Prevents api_only instances from participating in the automatic tracking which will prevent them from being added to Android manifests and breaking apps. 2) Add a new shared_library property that can have the same effect as api_only while still creating a runtime implementation library. 3) Renamed commonProperties to commonSdkLibraryProperties to disambiguate it from the ModuleBase.commonProperties field. 4) Extracts requiresRuntimeImplementationLibrary() to remove duplicate code accessing the Api_only property. 5) Tests for the api_only and shared_library behaviours. Test: m nothing - added tests, tests broke, fixed code, tests passed. Bug: 156723295 (cherry picked from commit dfa131e67358e6346a49e9b14be0da41d88d76ab) Change-Id: I06b3444ced00fd7b54068352187684171024c679 --- java/java_test.go | 19 ++++++++++- java/sdk_library.go | 82 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 80 insertions(+), 21 deletions(-) diff --git a/java/java_test.go b/java/java_test.go index 4c085cf0f..0ab541a3e 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -1157,6 +1157,16 @@ func TestJavaSdkLibrary(t *testing.T) { libs: ["foo", "bar.stubs"], sdk_version: "system_current", } + java_sdk_library { + name: "barney", + srcs: ["c.java"], + api_only: true, + } + java_sdk_library { + name: "betty", + srcs: ["c.java"], + shared_library: false, + } java_sdk_library_import { name: "quuz", public: { @@ -1169,10 +1179,17 @@ func TestJavaSdkLibrary(t *testing.T) { jars: ["b.jar"], }, } + java_sdk_library_import { + name: "wilma", + public: { + jars: ["b.jar"], + }, + shared_library: false, + } java_library { name: "qux", srcs: ["c.java"], - libs: ["baz", "fred", "quuz.stubs"], + libs: ["baz", "fred", "quuz.stubs", "wilma", "barney", "betty"], sdk_version: "system_current", } java_library { diff --git a/java/sdk_library.go b/java/sdk_library.go index de30635b4..f503e13bc 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -372,7 +372,10 @@ type sdkLibraryProperties struct { // Defaults to "api". Api_dir *string - // If set to true there is no runtime library. + // Determines whether a runtime implementation library is built; defaults to false. + // + // If true then it also prevents the module from being used as a shared module, i.e. + // it is as is shared_library: false, was set. Api_only *bool // local files that are used within user customized droiddoc options. @@ -532,6 +535,13 @@ type commonToSdkLibraryAndImportProperties struct { // // TODO(b/155480189) - Remove once naming inconsistencies have been resolved. Naming_scheme *string + + // Specifies whether this module can be used as an Android shared library; defaults + // to true. + // + // An Android shared library is one that can be referenced in a element + // in an AndroidManifest.xml. + Shared_library *bool } // Common code between sdk library and sdk library import @@ -542,7 +552,7 @@ type commonToSdkLibraryAndImport struct { namingScheme sdkLibraryComponentNamingScheme - commonProperties commonToSdkLibraryAndImportProperties + commonSdkLibraryProperties commonToSdkLibraryAndImportProperties // Functionality related to this being used as a component of a java_sdk_library. EmbeddableSdkLibraryComponent @@ -551,14 +561,14 @@ type commonToSdkLibraryAndImport struct { func (c *commonToSdkLibraryAndImport) initCommon(moduleBase *android.ModuleBase) { c.moduleBase = moduleBase - moduleBase.AddProperties(&c.commonProperties) + moduleBase.AddProperties(&c.commonSdkLibraryProperties) // Initialize this as an sdk library component. c.initSdkLibraryComponent(moduleBase) } func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android.DefaultableHookContext) bool { - schemeProperty := proptools.StringDefault(c.commonProperties.Naming_scheme, "default") + schemeProperty := proptools.StringDefault(c.commonSdkLibraryProperties.Naming_scheme, "default") switch schemeProperty { case "default": c.namingScheme = &defaultNamingScheme{} @@ -569,8 +579,11 @@ func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android return false } - // Use the name specified in the module definition as the owner. - c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.moduleBase.BaseModuleName()) + // Only track this sdk library if this can be used as a shared library. + if c.sharedLibrary() { + // Use the name specified in the module definition as the owner. + c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.moduleBase.BaseModuleName()) + } return true } @@ -740,17 +753,24 @@ func (c *commonToSdkLibraryAndImport) selectHeaderJarsForSdkVersion(ctx android. func (c *commonToSdkLibraryAndImport) sdkComponentPropertiesForChildLibrary() interface{} { componentProps := &struct { SdkLibraryToImplicitlyTrack *string - }{ + }{} + + if c.sharedLibrary() { // Mark the stubs library as being components of this java_sdk_library so that // any app that includes code which depends (directly or indirectly) on the stubs // library will have the appropriate invocation inserted into its // manifest if necessary. - SdkLibraryToImplicitlyTrack: proptools.StringPtr(c.moduleBase.BaseModuleName()), + componentProps.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.moduleBase.BaseModuleName()) } return componentProps } +// Check if this can be used as a shared library. +func (c *commonToSdkLibraryAndImport) sharedLibrary() bool { + return proptools.BoolDefault(c.commonSdkLibraryProperties.Shared_library, true) +} + // Properties related to the use of a module as an component of a java_sdk_library. type SdkLibraryComponentProperties struct { @@ -907,12 +927,15 @@ func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { } } - if !proptools.Bool(module.sdkLibraryProperties.Api_only) { - // Add dependency to the rule for generating the xml permissions file - ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlFileName()) - } + if module.requiresRuntimeImplementationLibrary() { + if module.sharedLibrary() { + // Add dependency to the rule for generating the xml permissions file + ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlFileName()) + } - module.Library.deps(ctx) + // Only add the deps for the library if it is actually going to be built. + module.Library.deps(ctx) + } } func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) { @@ -925,8 +948,8 @@ func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) { } func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { - // Don't build an implementation library if this is api only. - if !proptools.Bool(module.sdkLibraryProperties.Api_only) { + // Only build an implementation library if required. + if module.requiresRuntimeImplementationLibrary() { module.Library.GenerateAndroidBuildActions(ctx) } @@ -949,7 +972,7 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) } func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries { - if proptools.Bool(module.sdkLibraryProperties.Api_only) { + if !module.requiresRuntimeImplementationLibrary() { return nil } entriesList := module.Library.AndroidMkEntries() @@ -1392,9 +1415,12 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont module.createStubsLibrary(mctx, scope) } - if !proptools.Bool(module.sdkLibraryProperties.Api_only) { - // for runtime - module.createXmlFile(mctx) + if module.requiresRuntimeImplementationLibrary() { + // Only create an XML permissions file that declares the library as being usable + // as a shared library if required. + if module.sharedLibrary() { + module.createXmlFile(mctx) + } // record java_sdk_library modules so that they are exported to make javaSdkLibraries := javaSdkLibraries(mctx.Config()) @@ -1419,6 +1445,10 @@ func (module *SdkLibrary) InitSdkLibraryProperties() { module.deviceProperties.IsSDKLibrary = true } +func (module *SdkLibrary) requiresRuntimeImplementationLibrary() bool { + return !proptools.Bool(module.sdkLibraryProperties.Api_only) +} + // Defines how to name the individual component modules the sdk library creates. type sdkLibraryComponentNamingScheme interface { stubsLibraryModuleName(scope *apiScope, baseName string) string @@ -1497,6 +1527,18 @@ func SdkLibraryFactory() android.Module { android.AddVisibilityProperty(module, "stubs_source_visibility", &module.sdkLibraryProperties.Stubs_source_visibility) module.SetDefaultableHook(func(ctx android.DefaultableHookContext) { + // If no implementation is required then it cannot be used as a shared library + // either. + if !module.requiresRuntimeImplementationLibrary() { + // If shared_library has been explicitly set to true then it is incompatible + // with api_only: true. + if proptools.Bool(module.commonSdkLibraryProperties.Shared_library) { + ctx.PropertyErrorf("api_only/shared_library", "inconsistent settings, shared_library and api_only cannot both be true") + } + // Set shared_library: false. + module.commonSdkLibraryProperties.Shared_library = proptools.BoolPtr(false) + } + if module.initCommonAfterDefaultsApplied(ctx) { module.CreateInternalModules(ctx) } @@ -1921,7 +1963,7 @@ func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMembe } s.Libs = sdk.properties.Libs - s.Naming_scheme = sdk.commonProperties.Naming_scheme + s.Naming_scheme = sdk.commonSdkLibraryProperties.Naming_scheme } func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {