Add container property to aconfig_declarations.

Bug: 311155208
Test: Unit test
Change-Id: I7b187138856d0144203961e82b6dad5e2f8eed9d
This commit is contained in:
Yu Liu
2023-11-16 17:05:47 -08:00
parent 62093cf7fc
commit eae7b36699
26 changed files with 750 additions and 146 deletions

View File

@@ -8,6 +8,8 @@ bootstrap_go_package {
deps: [
"blueprint",
"soong",
"soong-aconfig",
"soong-aconfig-codegen",
"soong-android",
"soong-bazel",
"soong-bpf",

View File

@@ -24,6 +24,7 @@ import (
"sort"
"strings"
"android/soong/aconfig"
"android/soong/bazel/cquery"
"github.com/google/blueprint"
@@ -482,6 +483,8 @@ type apexBundle struct {
nativeApisUsedByModuleFile android.ModuleOutPath
nativeApisBackedByModuleFile android.ModuleOutPath
javaApisUsedByModuleFile android.ModuleOutPath
aconfigFiles []android.Path
}
// apexFileClass represents a type of file that can be included in APEX.
@@ -2008,6 +2011,8 @@ type visitorContext struct {
// visitor skips these from this list of module names
unwantedTransitiveDeps []string
aconfigFiles []android.Path
}
func (vctx *visitorContext) normalizeFileInfo(mctx android.ModuleContext) {
@@ -2067,6 +2072,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext,
fi := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs)
fi.isJniLib = isJniLib
vctx.filesInfo = append(vctx.filesInfo, fi)
addAconfigFiles(vctx, ctx, child)
// Collect the list of stub-providing libs except:
// - VNDK libs are only for vendors
// - bootstrap bionic libs are treated as provided by system
@@ -2090,6 +2096,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext,
switch ch := child.(type) {
case *cc.Module:
vctx.filesInfo = append(vctx.filesInfo, apexFileForExecutable(ctx, ch))
addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
case *rust.Module:
vctx.filesInfo = append(vctx.filesInfo, apexFileForRustExecutable(ctx, ch))
@@ -2132,6 +2139,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext,
return false
}
vctx.filesInfo = append(vctx.filesInfo, af)
addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
default:
ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child))
@@ -2140,6 +2148,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext,
switch ap := child.(type) {
case *java.AndroidApp:
vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
case *java.AndroidAppImport:
vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
@@ -2298,6 +2307,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext,
}
vctx.filesInfo = append(vctx.filesInfo, af)
addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
} else if rm, ok := child.(*rust.Module); ok {
af := apexFileForRustLibrary(ctx, rm)
@@ -2378,6 +2388,13 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext,
return false
}
func addAconfigFiles(vctx *visitorContext, ctx android.ModuleContext, module blueprint.Module) {
dep := ctx.OtherModuleProvider(module, aconfig.TransitiveDeclarationsInfoProvider).(aconfig.TransitiveDeclarationsInfo)
if len(dep.AconfigFiles) > 0 && dep.AconfigFiles[ctx.ModuleName()] != nil {
vctx.aconfigFiles = append(vctx.aconfigFiles, dep.AconfigFiles[ctx.ModuleName()].ToList()...)
}
}
func (a *apexBundle) shouldCheckDuplicate(ctx android.ModuleContext) bool {
// TODO(b/263308293) remove this
if a.properties.IsCoverageVariant {
@@ -2459,6 +2476,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// 3) some fields in apexBundle struct are configured
a.installDir = android.PathForModuleInstall(ctx, "apex")
a.filesInfo = vctx.filesInfo
a.aconfigFiles = android.FirstUniquePaths(vctx.aconfigFiles)
a.setPayloadFsType(ctx)
a.setSystemLibLink(ctx)

View File

@@ -25,6 +25,7 @@ import (
"strings"
"testing"
"android/soong/aconfig/codegen"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -151,6 +152,7 @@ var prepareForApexTest = android.GroupFixturePreparers(
prebuilt_etc.PrepareForTestWithPrebuiltEtc,
rust.PrepareForTestWithRustDefaultModules,
sh.PrepareForTestWithShBuildComponents,
codegen.PrepareForTestWithAconfigBuildComponents,
PrepareForTestWithApexBuildComponents,
@@ -10756,3 +10758,437 @@ func TestFileSystemShouldSkipApexLibraries(t *testing.T) {
inputs.Strings(),
"out/soong/.intermediates/libbar/android_arm64_armv8-a_shared/libbar.so")
}
var apex_default_bp = `
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
filegroup {
name: "myapex.manifest",
srcs: ["apex_manifest.json"],
}
filegroup {
name: "myapex.androidmanifest",
srcs: ["AndroidManifest.xml"],
}
`
func TestAconfigFilesJavaDeps(t *testing.T) {
ctx := testApex(t, apex_default_bp+`
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
java_libs: [
"my_java_library_foo",
"my_java_library_bar",
],
updatable: false,
}
java_library {
name: "my_java_library_foo",
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
static_libs: ["my_java_aconfig_library_foo"],
// TODO: remove //apex_available:platform
apex_available: [
"//apex_available:platform",
"myapex",
],
}
java_library {
name: "my_java_library_bar",
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
static_libs: ["my_java_aconfig_library_bar"],
// TODO: remove //apex_available:platform
apex_available: [
"//apex_available:platform",
"myapex",
],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "myapex",
srcs: ["foo.aconfig"],
}
java_aconfig_library {
name: "my_java_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
// TODO: remove //apex_available:platform
apex_available: [
"//apex_available:platform",
"myapex",
],
}
aconfig_declarations {
name: "my_aconfig_declarations_bar",
package: "com.example.package",
container: "myapex",
srcs: ["bar.aconfig"],
}
java_aconfig_library {
name: "my_java_aconfig_library_bar",
aconfig_declarations: "my_aconfig_declarations_bar",
// TODO: remove //apex_available:platform
apex_available: [
"//apex_available:platform",
"myapex",
],
}
`)
mod := ctx.ModuleForTests("myapex", "android_common_myapex")
s := mod.Rule("apexRule").Args["copy_commands"]
copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
if len(copyCmds) != 5 {
t.Fatalf("Expected 5 commands, got %d in:\n%s", len(copyCmds), s)
}
ensureMatches(t, copyCmds[4], "^cp -f .*/aconfig_flags.pb .*/image.apex$")
combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
s = " " + combineAconfigRule.Args["cache_files"]
aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
if len(aconfigArgs) != 2 {
t.Fatalf("Expected 2 commands, got %d in:\n%s", len(aconfigArgs), s)
}
android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_bar/intermediate.pb")
buildParams := combineAconfigRule.BuildParams
android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_bar/intermediate.pb")
ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
}
func TestAconfigFilesJavaAndCcDeps(t *testing.T) {
ctx := testApex(t, apex_default_bp+`
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
java_libs: [
"my_java_library_foo",
],
native_shared_libs: [
"my_cc_library_bar",
],
binaries: [
"my_cc_binary_baz",
],
updatable: false,
}
java_library {
name: "my_java_library_foo",
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
static_libs: ["my_java_aconfig_library_foo"],
// TODO: remove //apex_available:platform
apex_available: [
"//apex_available:platform",
"myapex",
],
}
cc_library {
name: "my_cc_library_bar",
srcs: ["foo/bar/MyClass.cc"],
static_libs: ["my_cc_aconfig_library_bar"],
// TODO: remove //apex_available:platform
apex_available: [
"//apex_available:platform",
"myapex",
],
}
cc_binary {
name: "my_cc_binary_baz",
srcs: ["foo/bar/MyClass.cc"],
static_libs: ["my_cc_aconfig_library_baz"],
// TODO: remove //apex_available:platform
apex_available: [
"//apex_available:platform",
"myapex",
],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "myapex",
srcs: ["foo.aconfig"],
}
java_aconfig_library {
name: "my_java_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
// TODO: remove //apex_available:platform
apex_available: [
"//apex_available:platform",
"myapex",
],
}
aconfig_declarations {
name: "my_aconfig_declarations_bar",
package: "com.example.package",
container: "myapex",
srcs: ["bar.aconfig"],
}
cc_aconfig_library {
name: "my_cc_aconfig_library_bar",
aconfig_declarations: "my_aconfig_declarations_bar",
// TODO: remove //apex_available:platform
apex_available: [
"//apex_available:platform",
"myapex",
],
}
aconfig_declarations {
name: "my_aconfig_declarations_baz",
package: "com.example.package",
container: "myapex",
srcs: ["baz.aconfig"],
}
cc_aconfig_library {
name: "my_cc_aconfig_library_baz",
aconfig_declarations: "my_aconfig_declarations_baz",
// TODO: remove //apex_available:platform
apex_available: [
"//apex_available:platform",
"myapex",
],
}
cc_library {
name: "server_configurable_flags",
srcs: ["server_configurable_flags.cc"],
}
`)
mod := ctx.ModuleForTests("myapex", "android_common_myapex")
s := mod.Rule("apexRule").Args["copy_commands"]
copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
if len(copyCmds) != 9 {
t.Fatalf("Expected 9 commands, got %d in:\n%s", len(copyCmds), s)
}
ensureMatches(t, copyCmds[8], "^cp -f .*/aconfig_flags.pb .*/image.apex$")
combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
s = " " + combineAconfigRule.Args["cache_files"]
aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
if len(aconfigArgs) != 3 {
t.Fatalf("Expected 3 commands, got %d in:\n%s", len(aconfigArgs), s)
}
android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_bar/intermediate.pb")
android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_baz/intermediate.pb")
buildParams := combineAconfigRule.BuildParams
if len(buildParams.Inputs) != 3 {
t.Fatalf("Expected 3 input, got %d", len(buildParams.Inputs))
}
android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_bar/intermediate.pb")
android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_baz/intermediate.pb")
ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
}
func TestAconfigFilesOnlyMatchCurrentApex(t *testing.T) {
ctx := testApex(t, apex_default_bp+`
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
java_libs: [
"my_java_library_foo",
"other_java_library_bar",
],
updatable: false,
}
java_library {
name: "my_java_library_foo",
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
static_libs: ["my_java_aconfig_library_foo"],
// TODO: remove //apex_available:platform
apex_available: [
"//apex_available:platform",
"myapex",
],
}
java_library {
name: "other_java_library_bar",
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
static_libs: ["other_java_aconfig_library_bar"],
// TODO: remove //apex_available:platform
apex_available: [
"//apex_available:platform",
"myapex",
],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "myapex",
srcs: ["foo.aconfig"],
}
java_aconfig_library {
name: "my_java_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
// TODO: remove //apex_available:platform
apex_available: [
"//apex_available:platform",
"myapex",
],
}
aconfig_declarations {
name: "other_aconfig_declarations_bar",
package: "com.example.package",
container: "otherapex",
srcs: ["bar.aconfig"],
}
java_aconfig_library {
name: "other_java_aconfig_library_bar",
aconfig_declarations: "other_aconfig_declarations_bar",
// TODO: remove //apex_available:platform
apex_available: [
"//apex_available:platform",
"myapex",
],
}
`)
mod := ctx.ModuleForTests("myapex", "android_common_myapex")
combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
s := " " + combineAconfigRule.Args["cache_files"]
aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
if len(aconfigArgs) != 1 {
t.Fatalf("Expected 1 commands, got %d in:\n%s", len(aconfigArgs), s)
}
android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
buildParams := combineAconfigRule.BuildParams
if len(buildParams.Inputs) != 1 {
t.Fatalf("Expected 1 input, got %d", len(buildParams.Inputs))
}
android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
}
func TestAconfigFilesRemoveDuplicates(t *testing.T) {
ctx := testApex(t, apex_default_bp+`
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
java_libs: [
"my_java_library_foo",
"my_java_library_bar",
],
updatable: false,
}
java_library {
name: "my_java_library_foo",
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
static_libs: ["my_java_aconfig_library_foo"],
// TODO: remove //apex_available:platform
apex_available: [
"//apex_available:platform",
"myapex",
],
}
java_library {
name: "my_java_library_bar",
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
static_libs: ["my_java_aconfig_library_bar"],
// TODO: remove //apex_available:platform
apex_available: [
"//apex_available:platform",
"myapex",
],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "myapex",
srcs: ["foo.aconfig"],
}
java_aconfig_library {
name: "my_java_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
// TODO: remove //apex_available:platform
apex_available: [
"//apex_available:platform",
"myapex",
],
}
java_aconfig_library {
name: "my_java_aconfig_library_bar",
aconfig_declarations: "my_aconfig_declarations_foo",
// TODO: remove //apex_available:platform
apex_available: [
"//apex_available:platform",
"myapex",
],
}
`)
mod := ctx.ModuleForTests("myapex", "android_common_myapex")
combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
s := " " + combineAconfigRule.Args["cache_files"]
aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
if len(aconfigArgs) != 1 {
t.Fatalf("Expected 1 commands, got %d in:\n%s", len(aconfigArgs), s)
}
android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
buildParams := combineAconfigRule.BuildParams
if len(buildParams.Inputs) != 1 {
t.Fatalf("Expected 1 input, got %d", len(buildParams.Inputs))
}
android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
}

View File

@@ -24,6 +24,7 @@ import (
"strconv"
"strings"
"android/soong/aconfig"
"android/soong/android"
"android/soong/java"
@@ -36,6 +37,7 @@ var (
)
func init() {
pctx.Import("android/soong/aconfig")
pctx.Import("android/soong/android")
pctx.Import("android/soong/cc/config")
pctx.Import("android/soong/java")
@@ -80,6 +82,7 @@ func init() {
pctx.HostBinToolVariable("conv_linker_config", "conv_linker_config")
pctx.HostBinToolVariable("assemble_vintf", "assemble_vintf")
pctx.HostBinToolVariable("apex_elf_checker", "apex_elf_checker")
pctx.HostBinToolVariable("aconfig", "aconfig")
}
var (
@@ -574,6 +577,7 @@ func (a *apexBundle) buildApex(ctx android.ModuleContext) {
installMapSet[installMapPath.String()+":"+fi.installDir+"/"+fi.builtFile.Base()] = true
}
implicitInputs = append(implicitInputs, a.manifestPbOut)
if len(installMapSet) > 0 {
@@ -628,10 +632,28 @@ func (a *apexBundle) buildApex(ctx android.ModuleContext) {
outHostBinDir := ctx.Config().HostToolPath(ctx, "").String()
prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin")
defaultReadOnlyFiles := []string{"apex_manifest.json", "apex_manifest.pb"}
if len(a.aconfigFiles) > 0 {
apexAconfigFile := android.PathForModuleOut(ctx, "aconfig_flags.pb")
ctx.Build(pctx, android.BuildParams{
Rule: aconfig.AllDeclarationsRule,
Inputs: a.aconfigFiles,
Output: apexAconfigFile,
Description: "combine_aconfig_declarations",
Args: map[string]string{
"cache_files": android.JoinPathsWithPrefix(a.aconfigFiles, "--cache "),
},
})
copyCommands = append(copyCommands, "cp -f "+apexAconfigFile.String()+" "+imageDir.String())
implicitInputs = append(implicitInputs, apexAconfigFile)
defaultReadOnlyFiles = append(defaultReadOnlyFiles, apexAconfigFile.Base())
}
////////////////////////////////////////////////////////////////////////////////////
// Step 2: create canned_fs_config which encodes filemode,uid,gid of each files
// in this APEX. The file will be used by apexer in later steps.
cannedFsConfig := a.buildCannedFsConfig(ctx)
cannedFsConfig := a.buildCannedFsConfig(ctx, defaultReadOnlyFiles)
implicitInputs = append(implicitInputs, cannedFsConfig)
////////////////////////////////////////////////////////////////////////////////////
@@ -1082,8 +1104,8 @@ func (a *apexBundle) buildLintReports(ctx android.ModuleContext) {
a.lintReports = java.BuildModuleLintReportZips(ctx, depSetsBuilder.Build())
}
func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext) android.OutputPath {
var readOnlyPaths = []string{"apex_manifest.json", "apex_manifest.pb"}
func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext, defaultReadOnlyFiles []string) android.OutputPath {
var readOnlyPaths = defaultReadOnlyFiles
var executablePaths []string // this also includes dirs
var appSetDirs []string
appSetFiles := make(map[string]android.Path)