Validate aconfig libs are built with the correct modes.

Bug: 323071835
Test: Unit tests and manual tests.
Change-Id: I32de90826c7c8bb4d8495608e959d554820ab9a2
This commit is contained in:
Yu Liu 2024-03-05 00:36:31 +00:00
parent eefca7373c
commit 67a28425a7
16 changed files with 696 additions and 32 deletions

View file

@ -15,9 +15,10 @@
package codegen
import (
"android/soong/aconfig"
"android/soong/android"
"fmt"
"maps"
"android/soong/android"
"github.com/google/blueprint"
)
@ -43,6 +44,7 @@ type AconfigDeclarationsGroup struct {
aconfigDeclarationNames []string
intermediateCacheOutputPaths android.Paths
javaSrcjars android.Paths
modeInfos map[string]android.ModeInfo
}
type AconfigDeclarationsGroupProperties struct {
@ -76,9 +78,10 @@ func (adg *AconfigDeclarationsGroup) DepsMutator(ctx android.BottomUpMutatorCont
}
func (adg *AconfigDeclarationsGroup) VisitDeps(ctx android.ModuleContext) {
adg.modeInfos = make(map[string]android.ModeInfo)
ctx.VisitDirectDeps(func(dep android.Module) {
tag := ctx.OtherModuleDependencyTag(dep)
if provider, ok := android.OtherModuleProvider(ctx, dep, aconfig.CodegenInfoProvider); ok {
if provider, ok := android.OtherModuleProvider(ctx, dep, android.CodegenInfoProvider); ok {
// aconfig declaration names and cache files are collected for all aconfig library dependencies
adg.aconfigDeclarationNames = append(adg.aconfigDeclarationNames, provider.AconfigDeclarations...)
@ -88,8 +91,14 @@ func (adg *AconfigDeclarationsGroup) VisitDeps(ctx android.ModuleContext) {
case aconfigDeclarationsGroupTag:
// Will retrieve outputs from another language codegen modules when support is added
adg.javaSrcjars = append(adg.javaSrcjars, provider.Srcjars...)
maps.Copy(adg.modeInfos, provider.ModeInfos)
case javaAconfigLibraryTag:
adg.javaSrcjars = append(adg.javaSrcjars, provider.Srcjars...)
maps.Copy(adg.modeInfos, provider.ModeInfos)
case ccAconfigLibraryTag:
maps.Copy(adg.modeInfos, provider.ModeInfos)
case rustAconfigLibraryTag:
maps.Copy(adg.modeInfos, provider.ModeInfos)
}
}
})
@ -100,10 +109,11 @@ func (adg *AconfigDeclarationsGroup) GenerateAndroidBuildActions(ctx android.Mod
adg.aconfigDeclarationNames = android.FirstUniqueStrings(adg.aconfigDeclarationNames)
adg.intermediateCacheOutputPaths = android.FirstUniquePaths(adg.intermediateCacheOutputPaths)
android.SetProvider(ctx, aconfig.CodegenInfoProvider, aconfig.CodegenInfo{
android.SetProvider(ctx, android.CodegenInfoProvider, android.CodegenInfo{
AconfigDeclarations: adg.aconfigDeclarationNames,
IntermediateCacheOutputPaths: adg.intermediateCacheOutputPaths,
Srcjars: adg.javaSrcjars,
ModeInfos: adg.modeInfos,
})
}

View file

@ -146,4 +146,12 @@ func (this *CcAconfigLibraryCallbacks) GeneratorBuildActions(ctx cc.ModuleContex
"mode": mode,
},
})
android.SetProvider(ctx, android.CodegenInfoProvider, android.CodegenInfo{
ModeInfos: map[string]android.ModeInfo{
ctx.ModuleName(): {
Container: declarations.Container,
Mode: mode,
}},
})
}

View file

@ -17,7 +17,6 @@ package codegen
import (
"fmt"
"android/soong/aconfig"
"android/soong/android"
"android/soong/java"
@ -119,10 +118,15 @@ func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuild
module.AddJarJarRenameRule(declarations.Package+".FakeFeatureFlagsImpl", "")
}
android.SetProvider(ctx, aconfig.CodegenInfoProvider, aconfig.CodegenInfo{
android.SetProvider(ctx, android.CodegenInfoProvider, android.CodegenInfo{
AconfigDeclarations: []string{declarationsModules[0].Name()},
IntermediateCacheOutputPaths: android.Paths{declarations.IntermediateCacheOutputPath},
Srcjars: android.Paths{srcJarPath},
ModeInfos: map[string]android.ModeInfo{
ctx.ModuleName(): {
Container: declarations.Container,
Mode: mode,
}},
})
return srcJarPath

View file

@ -85,6 +85,15 @@ func (a *aconfigDecorator) GenerateSource(ctx rust.ModuleContext, deps rust.Path
},
})
a.BaseSourceProvider.OutputFiles = android.Paths{generatedSource}
android.SetProvider(ctx, android.CodegenInfoProvider, android.CodegenInfo{
ModeInfos: map[string]android.ModeInfo{
ctx.ModuleName(): {
Container: declarations.Container,
Mode: mode,
}},
})
return generatedSource
}

View file

@ -20,20 +20,6 @@ import (
"github.com/google/blueprint"
)
type CodegenInfo struct {
// AconfigDeclarations is the name of the aconfig_declarations modules that
// the codegen module is associated with
AconfigDeclarations []string
// Paths to the cache files of the associated aconfig_declaration modules
IntermediateCacheOutputPaths android.Paths
// Paths to the srcjar files generated from the java_aconfig_library modules
Srcjars android.Paths
}
var CodegenInfoProvider = blueprint.NewProvider[CodegenInfo]()
var (
pctx = android.NewPackageContext("android/soong/aconfig")

View file

@ -17,6 +17,7 @@ package android
import (
"fmt"
"io"
"maps"
"reflect"
"github.com/google/blueprint"
@ -50,6 +51,35 @@ type AconfigTransitiveDeclarationsInfo struct {
var AconfigTransitiveDeclarationsInfoProvider = blueprint.NewProvider[AconfigTransitiveDeclarationsInfo]()
type ModeInfo struct {
Container string
Mode string
}
type CodegenInfo struct {
// AconfigDeclarations is the name of the aconfig_declarations modules that
// the codegen module is associated with
AconfigDeclarations []string
// Paths to the cache files of the associated aconfig_declaration modules
IntermediateCacheOutputPaths Paths
// Paths to the srcjar files generated from the java_aconfig_library modules
Srcjars Paths
ModeInfos map[string]ModeInfo
}
var CodegenInfoProvider = blueprint.NewProvider[CodegenInfo]()
func propagateModeInfos(ctx ModuleContext, module Module, to, from map[string]ModeInfo) {
if len(from) > 0 {
depTag := ctx.OtherModuleDependencyTag(module)
if tag, ok := depTag.(PropagateAconfigValidationDependencyTag); ok && tag.PropagateAconfigValidation() {
maps.Copy(to, from)
}
}
}
// CollectDependencyAconfigFiles is used by some module types to provide finer dependency graphing than
// we can do in ModuleBase.
func CollectDependencyAconfigFiles(ctx ModuleContext, mergedAconfigFiles *map[string]Paths) {
@ -90,13 +120,40 @@ func SetAconfigFileMkEntries(m *ModuleBase, entries *AndroidMkEntries, aconfigFi
type aconfigPropagatingDeclarationsInfo struct {
AconfigFiles map[string]Paths
ModeInfos map[string]ModeInfo
}
var aconfigPropagatingProviderKey = blueprint.NewProvider[aconfigPropagatingDeclarationsInfo]()
func VerifyAconfigBuildMode(ctx ModuleContext, container string, module blueprint.Module, asError bool) {
if dep, ok := OtherModuleProvider(ctx, module, aconfigPropagatingProviderKey); ok {
for k, v := range dep.ModeInfos {
msg := fmt.Sprintf("%s/%s depends on %s/%s/%s across containers\n",
module.Name(), container, k, v.Container, v.Mode)
if v.Container != container && v.Mode != "exported" && v.Mode != "force-read-only" {
if asError {
ctx.ModuleErrorf(msg)
} else {
fmt.Printf("WARNING: " + msg)
}
} else {
if !asError {
fmt.Printf("PASSED: " + msg)
}
}
}
}
}
func aconfigUpdateAndroidBuildActions(ctx ModuleContext) {
mergedAconfigFiles := make(map[string]Paths)
mergedModeInfos := make(map[string]ModeInfo)
ctx.VisitDirectDepsIgnoreBlueprint(func(module Module) {
if aconfig_dep, ok := OtherModuleProvider(ctx, module, CodegenInfoProvider); ok && len(aconfig_dep.ModeInfos) > 0 {
maps.Copy(mergedModeInfos, aconfig_dep.ModeInfos)
}
// If any of our dependencies have aconfig declarations (directly or propagated), then merge those and provide them.
if dep, ok := OtherModuleProvider(ctx, module, AconfigDeclarationsProviderKey); ok {
mergedAconfigFiles[dep.Container] = append(mergedAconfigFiles[dep.Container], dep.IntermediateCacheOutputPath)
@ -105,6 +162,7 @@ func aconfigUpdateAndroidBuildActions(ctx ModuleContext) {
for container, v := range dep.AconfigFiles {
mergedAconfigFiles[container] = append(mergedAconfigFiles[container], v...)
}
propagateModeInfos(ctx, module, mergedModeInfos, dep.ModeInfos)
}
if dep, ok := OtherModuleProvider(ctx, module, AconfigTransitiveDeclarationsInfoProvider); ok {
for container, v := range dep.AconfigFiles {
@ -120,6 +178,7 @@ func aconfigUpdateAndroidBuildActions(ctx ModuleContext) {
SetProvider(ctx, aconfigPropagatingProviderKey, aconfigPropagatingDeclarationsInfo{
AconfigFiles: mergedAconfigFiles,
ModeInfos: mergedModeInfos,
})
}
}

View file

@ -18,7 +18,6 @@ package android
// product variables necessary for soong_build's operation.
import (
"android/soong/shared"
"encoding/json"
"fmt"
"os"
@ -30,6 +29,8 @@ import (
"sync"
"unicode"
"android/soong/shared"
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/pathtools"
@ -1932,6 +1933,10 @@ func (c *deviceConfig) GenerateAidlNdkPlatformBackend() bool {
return c.config.productVariables.GenerateAidlNdkPlatformBackend
}
func (c *deviceConfig) AconfigContainerValidation() string {
return c.config.productVariables.AconfigContainerValidation
}
func (c *config) IgnorePrefer32OnDevice() bool {
return c.productVariables.IgnorePrefer32OnDevice
}

View file

@ -43,3 +43,15 @@ func IsInstallDepNeededTag(tag blueprint.DependencyTag) bool {
}
return false
}
type PropagateAconfigValidationDependencyTag interface {
PropagateAconfigValidation() bool
}
type AlwaysPropagateAconfigValidationDependencyTag struct{}
func (p AlwaysPropagateAconfigValidationDependencyTag) PropagateAconfigValidation() bool {
return true
}
var _ PropagateAconfigValidationDependencyTag = AlwaysPropagateAconfigValidationDependencyTag{}

View file

@ -15,7 +15,6 @@
package android
import (
"android/soong/bazel"
"crypto/md5"
"encoding/hex"
"encoding/json"
@ -27,6 +26,8 @@ import (
"sort"
"strings"
"android/soong/bazel"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@ -2087,6 +2088,7 @@ func isUnqualifiedModuleName(module string) bool {
// caused by prebuilt_ prefix, or fully qualified module names.
type sourceOrOutputDependencyTag struct {
blueprint.BaseDependencyTag
AlwaysPropagateAconfigValidationDependencyTag
// The name of the module.
moduleName string

View file

@ -500,6 +500,8 @@ type ProductVariables struct {
HiddenapiExportableStubs *bool `json:",omitempty"`
ExportRuntimeApis *bool `json:",omitempty"`
AconfigContainerValidation string `json:",omitempty"`
}
type PartitionQualifiedVariablesType struct {

550
apex/aconfig_test.go Normal file
View file

@ -0,0 +1,550 @@
// Copyright 2024 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package apex
import (
"testing"
"android/soong/aconfig/codegen"
"android/soong/android"
"android/soong/cc"
"android/soong/genrule"
"android/soong/java"
"android/soong/rust"
"github.com/google/blueprint/proptools"
)
var withAconfigValidationError = android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.AconfigContainerValidation = "error"
variables.BuildId = proptools.StringPtr("TEST.BUILD_ID")
})
func TestValidationAcrossContainersExportedPass(t *testing.T) {
testCases := []struct {
name string
bp string
}{
{
name: "Java lib passes for exported containers cross",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
java_libs: [
"my_java_library_foo",
],
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"],
apex_available: [
"myapex",
],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "otherapex",
srcs: ["foo.aconfig"],
exportable: true,
}
java_aconfig_library {
name: "my_java_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
mode: "exported",
apex_available: [
"myapex",
],
}`,
},
{
name: "Android app passes for exported containers cross",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
apps: [
"my_android_app_foo",
],
updatable: false,
}
android_app {
name: "my_android_app_foo",
srcs: ["foo/MyClass.java"],
sdk_version: "none",
system_modules: "none",
stl: "none",
static_libs: ["my_java_library_bar"],
apex_available: [ "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"],
apex_available: [
"myapex",
],
}
aconfig_declarations {
name: "my_aconfig_declarations_bar",
package: "com.example.package",
container: "otherapex",
srcs: ["bar.aconfig"],
exportable: true,
}
java_aconfig_library {
name: "my_java_aconfig_library_bar",
aconfig_declarations: "my_aconfig_declarations_bar",
mode: "exported",
apex_available: [
"myapex",
],
}`,
},
{
name: "Cc lib passes for exported containers cross",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
native_shared_libs: [
"my_cc_library_bar",
],
binaries: [
"my_cc_binary_baz",
],
updatable: false,
}
cc_library {
name: "my_cc_library_bar",
srcs: ["foo/bar/MyClass.cc"],
static_libs: [
"my_cc_aconfig_library_bar",
"my_cc_aconfig_library_baz",
],
apex_available: [
"myapex",
],
}
cc_binary {
name: "my_cc_binary_baz",
srcs: ["foo/bar/MyClass.cc"],
static_libs: ["my_cc_aconfig_library_baz"],
apex_available: [
"myapex",
],
}
cc_library {
name: "server_configurable_flags",
srcs: ["server_configurable_flags.cc"],
}
aconfig_declarations {
name: "my_aconfig_declarations_bar",
package: "com.example.package",
container: "otherapex",
srcs: ["bar.aconfig"],
exportable: true,
}
cc_aconfig_library {
name: "my_cc_aconfig_library_bar",
aconfig_declarations: "my_aconfig_declarations_bar",
apex_available: [
"myapex",
],
mode: "exported",
}
aconfig_declarations {
name: "my_aconfig_declarations_baz",
package: "com.example.package",
container: "otherapex",
srcs: ["baz.aconfig"],
exportable: true,
}
cc_aconfig_library {
name: "my_cc_aconfig_library_baz",
aconfig_declarations: "my_aconfig_declarations_baz",
apex_available: [
"myapex",
],
mode: "exported",
}`,
},
}
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
android.GroupFixturePreparers(
java.PrepareForTestWithJavaDefaultModules,
cc.PrepareForTestWithCcBuildComponents,
rust.PrepareForTestWithRustDefaultModules,
codegen.PrepareForTestWithAconfigBuildComponents,
PrepareForTestWithApexBuildComponents,
prepareForTestWithMyapex,
withAconfigValidationError,
).
RunTestWithBp(t, test.bp)
})
}
}
func TestValidationAcrossContainersNotExportedFail(t *testing.T) {
testCases := []struct {
name string
expectedError string
bp string
}{
{
name: "Java lib fails for non-exported containers cross",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
java_libs: [
"my_java_library_foo",
],
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"],
apex_available: [
"myapex",
],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "otherapex",
srcs: ["foo.aconfig"],
}
java_aconfig_library {
name: "my_java_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
apex_available: [
"myapex",
],
}`,
expectedError: `.*my_java_library_foo/myapex depends on my_java_aconfig_library_foo/otherapex/production across containers`,
},
{
name: "Android app fails for non-exported containers cross",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
apps: [
"my_android_app_foo",
],
updatable: false,
}
android_app {
name: "my_android_app_foo",
srcs: ["foo/MyClass.java"],
sdk_version: "none",
system_modules: "none",
stl: "none",
static_libs: ["my_java_library_foo"],
apex_available: [ "myapex" ],
}
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"],
apex_available: [
"myapex",
],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "otherapex",
srcs: ["bar.aconfig"],
}
java_aconfig_library {
name: "my_java_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
apex_available: [
"myapex",
],
}`,
expectedError: `.*my_android_app_foo/myapex depends on my_java_aconfig_library_foo/otherapex/production across containers`,
},
{
name: "Cc lib fails for non-exported containers cross",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
native_shared_libs: [
"my_cc_library_foo",
],
updatable: false,
}
cc_library {
name: "my_cc_library_foo",
srcs: ["foo/bar/MyClass.cc"],
shared_libs: [
"my_cc_aconfig_library_foo",
],
apex_available: [
"myapex",
],
}
cc_library {
name: "server_configurable_flags",
srcs: ["server_configurable_flags.cc"],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "otherapex",
srcs: ["foo.aconfig"],
}
cc_aconfig_library {
name: "my_cc_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
apex_available: [
"myapex",
],
}`,
expectedError: `.*my_cc_library_foo/myapex depends on my_cc_aconfig_library_foo/otherapex/production across containers`,
},
{
name: "Cc binary fails for non-exported containers cross",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
binaries: [
"my_cc_binary_foo",
],
updatable: false,
}
cc_library {
name: "my_cc_library_foo",
srcs: ["foo/bar/MyClass.cc"],
static_libs: [
"my_cc_aconfig_library_foo",
],
apex_available: [
"myapex",
],
}
cc_binary {
name: "my_cc_binary_foo",
srcs: ["foo/bar/MyClass.cc"],
static_libs: ["my_cc_library_foo"],
apex_available: [
"myapex",
],
}
cc_library {
name: "server_configurable_flags",
srcs: ["server_configurable_flags.cc"],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "otherapex",
srcs: ["foo.aconfig"],
}
cc_aconfig_library {
name: "my_cc_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
apex_available: [
"myapex",
],
}`,
expectedError: `.*my_cc_binary_foo/myapex depends on my_cc_aconfig_library_foo/otherapex/production across containers`,
},
{
name: "Aconfig validation propagate along sourceOrOutputDependencyTag",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
apps: [
"my_android_app_foo",
],
updatable: false,
}
android_app {
name: "my_android_app_foo",
srcs: ["foo/MyClass.java"],
sdk_version: "none",
system_modules: "none",
stl: "none",
static_libs: ["my_java_library_foo"],
apex_available: [ "myapex" ],
}
java_library {
name: "my_java_library_foo",
srcs: [":my_genrule_foo"],
sdk_version: "none",
system_modules: "none",
apex_available: [
"myapex",
],
}
aconfig_declarations_group {
name: "my_aconfig_declarations_group_foo",
java_aconfig_libraries: [
"my_java_aconfig_library_foo",
],
}
filegroup {
name: "my_filegroup_foo_srcjars",
srcs: [
":my_aconfig_declarations_group_foo{.srcjars}",
],
}
genrule {
name: "my_genrule_foo",
srcs: [":my_filegroup_foo_srcjars"],
cmd: "cp $(in) $(out)",
out: ["my_genrule_foo.srcjar"],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "otherapex",
srcs: ["bar.aconfig"],
}
java_aconfig_library {
name: "my_java_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
apex_available: [
"myapex",
],
}`,
expectedError: `.*my_android_app_foo/myapex depends on my_java_aconfig_library_foo/otherapex/production across containers`,
},
}
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
errorHandler := android.FixtureExpectsNoErrors
if test.expectedError != "" {
errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(test.expectedError)
}
android.GroupFixturePreparers(
java.PrepareForTestWithJavaDefaultModules,
cc.PrepareForTestWithCcBuildComponents,
rust.PrepareForTestWithRustDefaultModules,
codegen.PrepareForTestWithAconfigBuildComponents,
genrule.PrepareForIntegrationTestWithGenrule,
PrepareForTestWithApexBuildComponents,
prepareForTestWithMyapex,
withAconfigValidationError,
).
ExtendWithErrorHandler(errorHandler).
RunTestWithBp(t, test.bp)
})
}
}
func TestValidationNotPropagateAcrossShared(t *testing.T) {
testCases := []struct {
name string
bp string
}{
{
name: "Java shared lib not propagate aconfig validation",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
java_libs: [
"my_java_library_bar",
],
updatable: false,
}
java_library {
name: "my_java_library_bar",
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
libs: ["my_java_library_foo"],
apex_available: [
"myapex",
],
}
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"],
apex_available: [
"myapex",
],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "otherapex",
srcs: ["foo.aconfig"],
}
java_aconfig_library {
name: "my_java_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
apex_available: [
"myapex",
],
}`,
},
}
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
android.GroupFixturePreparers(
java.PrepareForTestWithJavaDefaultModules,
cc.PrepareForTestWithCcBuildComponents,
rust.PrepareForTestWithRustDefaultModules,
codegen.PrepareForTestWithAconfigBuildComponents,
PrepareForTestWithApexBuildComponents,
prepareForTestWithMyapex,
withAconfigValidationError,
).
RunTestWithBp(t, test.bp)
})
}
}

View file

@ -2321,9 +2321,15 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext,
}
func addAconfigFiles(vctx *visitorContext, ctx android.ModuleContext, module blueprint.Module) {
dep, _ := android.OtherModuleProvider(ctx, module, android.AconfigTransitiveDeclarationsInfoProvider)
if len(dep.AconfigFiles) > 0 && dep.AconfigFiles[ctx.ModuleName()] != nil {
vctx.aconfigFiles = append(vctx.aconfigFiles, dep.AconfigFiles[ctx.ModuleName()]...)
if dep, ok := android.OtherModuleProvider(ctx, module, android.AconfigTransitiveDeclarationsInfoProvider); ok {
if len(dep.AconfigFiles) > 0 && dep.AconfigFiles[ctx.ModuleName()] != nil {
vctx.aconfigFiles = append(vctx.aconfigFiles, dep.AconfigFiles[ctx.ModuleName()]...)
}
}
validationFlag := ctx.DeviceConfig().AconfigContainerValidation()
if validationFlag == "error" || validationFlag == "warning" {
android.VerifyAconfigBuildMode(ctx, ctx.ModuleName(), module, validationFlag == "error")
}
}

View file

@ -766,6 +766,12 @@ func (d libraryDependencyTag) InstallDepNeeded() bool {
var _ android.InstallNeededDependencyTag = libraryDependencyTag{}
func (d libraryDependencyTag) PropagateAconfigValidation() bool {
return d.static()
}
var _ android.PropagateAconfigValidationDependencyTag = libraryDependencyTag{}
// dependencyTag is used for tagging miscellaneous dependency types that don't fit into
// libraryDependencyTag. Each tag object is created globally and reused for multiple
// dependencies (although since the object contains no references, assigning a tag to a

View file

@ -26,7 +26,6 @@ import (
"github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
"android/soong/aconfig"
"android/soong/android"
"android/soong/dexpreopt"
"android/soong/java/config"
@ -2546,7 +2545,7 @@ func collectDirectDepsProviders(ctx android.ModuleContext) (result *JarJarProvid
default:
return RenameUseExclude, "srcfile"
}
} else if _, ok := android.OtherModuleProvider(ctx, m, aconfig.CodegenInfoProvider); ok {
} else if _, ok := android.OtherModuleProvider(ctx, m, android.CodegenInfoProvider); ok {
return RenameUseInclude, "aconfig_declarations_group"
} else {
switch tag {

View file

@ -21,7 +21,6 @@ import (
"github.com/google/blueprint/proptools"
"android/soong/aconfig"
"android/soong/android"
"android/soong/java/config"
)
@ -414,7 +413,7 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps {
case aconfigDeclarationTag:
if dep, ok := android.OtherModuleProvider(ctx, module, android.AconfigDeclarationsProviderKey); ok {
deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPath)
} else if dep, ok := android.OtherModuleProvider(ctx, module, aconfig.CodegenInfoProvider); ok {
} else if dep, ok := android.OtherModuleProvider(ctx, module, android.CodegenInfoProvider); ok {
deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPaths...)
} else {
ctx.ModuleErrorf("Only aconfig_declarations and aconfig_declarations_group "+

View file

@ -24,7 +24,6 @@ import (
"sort"
"strings"
"android/soong/aconfig"
"android/soong/remoteexec"
"android/soong/testing"
@ -346,6 +345,12 @@ func (j *Module) XrefJavaFiles() android.Paths {
return j.kytheFiles
}
func (d dependencyTag) PropagateAconfigValidation() bool {
return d.static
}
var _ android.PropagateAconfigValidationDependencyTag = dependencyTag{}
type dependencyTag struct {
blueprint.BaseDependencyTag
name string
@ -355,6 +360,8 @@ type dependencyTag struct {
// True if the dependency is a toolchain, for example an annotation processor.
toolchain bool
static bool
}
// installDependencyTag is a dependency tag that is annotated to cause the installed files of the
@ -400,7 +407,7 @@ func IsJniDepTag(depTag blueprint.DependencyTag) bool {
var (
dataNativeBinsTag = dependencyTag{name: "dataNativeBins"}
dataDeviceBinsTag = dependencyTag{name: "dataDeviceBins"}
staticLibTag = dependencyTag{name: "staticlib"}
staticLibTag = dependencyTag{name: "staticlib", static: true}
libTag = dependencyTag{name: "javalib", runtimeLinked: true}
sdkLibTag = dependencyTag{name: "sdklib", runtimeLinked: true}
java9LibTag = dependencyTag{name: "java9lib", runtimeLinked: true}
@ -2172,7 +2179,7 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
case aconfigDeclarationTag:
if provider, ok := android.OtherModuleProvider(ctx, dep, android.AconfigDeclarationsProviderKey); ok {
al.aconfigProtoFiles = append(al.aconfigProtoFiles, provider.IntermediateCacheOutputPath)
} else if provider, ok := android.OtherModuleProvider(ctx, dep, aconfig.CodegenInfoProvider); ok {
} else if provider, ok := android.OtherModuleProvider(ctx, dep, android.CodegenInfoProvider); ok {
al.aconfigProtoFiles = append(al.aconfigProtoFiles, provider.IntermediateCacheOutputPaths...)
} else {
ctx.ModuleErrorf("Only aconfig_declarations and aconfig_declarations_group "+