java_sdk_library - Allow it to be replaced by prebuilt

Previously, a java_sdk_library called "SDKLIB" would create a
prebuilt_etc module called "SDKLIB.xml" which installs the generated
XML permission file to /etc/permissions/SDKLIB.xml. That module
depended on the java_sdk_library "SDKLIB" to generate the XML file
as one of its outputs by specifying srcs: [":SDKLIB{.xml}"].

If the java_sdk_library is replaced by a prebuilt then the SDKLIB.xml
module expects the prebuilt to provide the XML permissions file which
it doesn't because that is an implementation detail and so the build
breaks.

A couple of alternative approaches were looked at to fix this. One was
to have the logic that replaced the source module with the prebuilt to
inform the source module that it was being replaced so it could disable
its created module. That lead to a dependency cycle where
    SDKLIB -> SDKLIB.xml -> SDKLIB{.xml}

Another solution was to mark dependency tags in such a way that the
prebuilt could automatically identify and disable the SDKLIB.xml
module. Similar to how the visibility code will ignore dependencies
that are tagged with ExcludeFromVisibilityEnforcementTag. That became
very convoluted.

Instead the java_sdk_library was changed so that it was not responsible
for creating the XML permissions file. Instead it created a genrule
called "gen-SDKLIB.xml" to create it and then "SDKLIB.xml" depended on
that. The java_sdk_library also depended on the genrule to make the XML
permissions file available for APEX and testing.

Some refactoring of the APEX code and tests was necessary because they
had knowledge of the internal implementation of java_sdk_library. The
refactoring insulates them a little better from those details.

Bug: 148080325
Test: m droid && TARGET_BUILD_APPS=Camera2 m
Change-Id: I597bccbb177b6b6320c3a3edeff467243230d384
This commit is contained in:
Paul Duffin 2020-02-06 13:51:46 +00:00
parent 9acd7c3d36
commit e74ac73bc9
3 changed files with 58 additions and 32 deletions

View File

@ -1342,12 +1342,12 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
filesInfo = append(filesInfo, af)
pf, _ := sdkLib.OutputFiles(".xml")
if len(pf) != 1 {
pf := sdkLib.XmlPermissionsFile()
if pf == nil {
ctx.PropertyErrorf("java_libs", "%q failed to generate permission XML", depName)
return false
}
filesInfo = append(filesInfo, newApexFile(ctx, pf[0], pf[0].Base(), "etc/permissions", etc, nil))
filesInfo = append(filesInfo, newApexFile(ctx, pf, pf.Base(), "etc/permissions", etc, nil))
return true // track transitive dependencies
} else {
ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child))

View File

@ -3470,8 +3470,9 @@ func TestJavaSDKLibrary(t *testing.T) {
"etc/permissions/foo.xml",
})
// Permission XML should point to the activated path of impl jar of java_sdk_library
xml := ctx.ModuleForTests("foo", "android_common_myapex").Output("foo.xml")
ensureContains(t, xml.Args["content"], `<library name="foo" file="/apex/myapex/javalib/foo.jar"`)
sdkLibrary := ctx.ModuleForTests("foo", "android_common_myapex").Module().(*java.SdkLibrary)
xml := sdkLibrary.XmlPermissionsFileContent()
ensureContains(t, xml, `<library name="foo" file="/apex/myapex/javalib/foo.jar"`)
}
func TestCompatConfig(t *testing.T) {

View File

@ -16,6 +16,7 @@ package java
import (
"android/soong/android"
"android/soong/genrule"
"fmt"
"io"
@ -264,6 +265,8 @@ func (module *SdkLibrary) getActiveApiScopes() apiScopes {
}
}
var xmlPermissionsFileTag = dependencyTag{name: "xml-permissions-file"}
func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
useBuiltStubs := !ctx.Config().UnbundledBuildUsePrebuiltSdks()
for _, apiScope := range module.getActiveApiScopes() {
@ -275,6 +278,11 @@ func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddVariationDependencies(nil, apiScope.apiFileTag, module.docsName(apiScope))
}
if !proptools.Bool(module.sdkLibraryProperties.Api_only) {
// Add dependency to the rule for generating the xml permissions file
ctx.AddDependency(module, xmlPermissionsFileTag, module.genXmlPermissionsFileName())
}
module.Library.deps(ctx)
}
@ -284,8 +292,6 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
module.Library.GenerateAndroidBuildActions(ctx)
}
module.buildPermissionsFile(ctx)
// Record the paths to the header jars of the library (stubs and impl).
// When this java_sdk_library is depended upon from others via "libs" property,
// the recorded paths will be returned depending on the link type of the caller.
@ -310,33 +316,21 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
ctx.ModuleErrorf("depends on module %q of unknown tag %q", otherName, tag)
}
}
if tag == xmlPermissionsFileTag {
if genRule, ok := to.(genrule.SourceFileGenerator); ok {
pf := genRule.GeneratedSourceFiles()
if len(pf) != 1 {
ctx.ModuleErrorf("%q failed to generate permission XML", otherName)
} else {
module.permissionsFile = pf[0]
}
} else {
ctx.ModuleErrorf("depends on module %q to generate xml permissions file but it does not provide any outputs", otherName)
}
}
})
}
func (module *SdkLibrary) buildPermissionsFile(ctx android.ModuleContext) {
xmlContent := fmt.Sprintf(permissionsTemplate, module.BaseModuleName(), module.implPath())
permissionsFile := android.PathForModuleOut(ctx, module.xmlFileName())
ctx.Build(pctx, android.BuildParams{
Rule: android.WriteFile,
Output: permissionsFile,
Description: "Generating " + module.BaseModuleName() + " permissions",
Args: map[string]string{
"content": xmlContent,
},
})
module.permissionsFile = permissionsFile
}
func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) {
switch tag {
case ".xml":
return android.Paths{module.permissionsFile}, nil
}
return module.Library.OutputFiles(tag)
}
func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
if proptools.Bool(module.sdkLibraryProperties.Api_only) {
return nil
@ -423,6 +417,11 @@ func (module *SdkLibrary) xmlFileName() string {
return module.BaseModuleName() + sdkXmlFileSuffix
}
// Module name of the rule for generating the XML permissions file
func (module *SdkLibrary) genXmlPermissionsFileName() string {
return "gen-" + module.BaseModuleName() + sdkXmlFileSuffix
}
// Get the sdk version for use when compiling the stubs library.
func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.LoadHookContext, apiScope *apiScope) string {
sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
@ -623,8 +622,34 @@ func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiSc
mctx.CreateModule(DroidstubsFactory, &props)
}
func (module *SdkLibrary) XmlPermissionsFile() android.Path {
return module.permissionsFile
}
func (module *SdkLibrary) XmlPermissionsFileContent() string {
return fmt.Sprintf(permissionsTemplate, module.BaseModuleName(), module.implPath())
}
// Creates the xml file that publicizes the runtime library
func (module *SdkLibrary) createXmlFile(mctx android.LoadHookContext) {
xmlContent := module.XmlPermissionsFileContent()
genRuleName := module.genXmlPermissionsFileName()
// Create a genrule module to create the XML permissions file.
genRuleProps := struct {
Name *string
Cmd *string
Out []string
}{
Name: proptools.StringPtr(genRuleName),
Cmd: proptools.StringPtr("echo -e '" + xmlContent + "' > '$(out)'"),
Out: []string{module.xmlFileName()},
}
mctx.CreateModule(genrule.GenRuleFactory, &genRuleProps)
// creates a prebuilt_etc module to actually place the xml file under
// <partition>/etc/permissions
etcProps := struct {
@ -637,7 +662,7 @@ func (module *SdkLibrary) createXmlFile(mctx android.LoadHookContext) {
System_ext_specific *bool
}{}
etcProps.Name = proptools.StringPtr(module.xmlFileName())
etcProps.Src = proptools.StringPtr(":" + module.BaseModuleName() + "{.xml}")
etcProps.Src = proptools.StringPtr(":" + genRuleName)
etcProps.Sub_dir = proptools.StringPtr("permissions")
if module.SocSpecific() {
etcProps.Soc_specific = proptools.BoolPtr(true)