Merge "Allow specifying sub-dir in sbox output" into main
diff --git a/README.md b/README.md
index f471c47..93260e6 100644
--- a/README.md
+++ b/README.md
@@ -314,6 +314,9 @@
* `["//visibility:override"]`: Discards any rules inherited from defaults or a
creating module. Can only be used at the beginning of a list of visibility
rules.
+* `["//visibility:any_partition"]`: Any modules of type android_filesystem
+or android_system_image can use this module. Intended for modules that no one
+should link against, but should still be included in soong-built partitions.
* `["//some/package:__pkg__", "//other/package:__pkg__"]`: Only modules in
`some/package` and `other/package` (defined in `some/package/*.bp` and
`other/package/*.bp`) have access to this module. Note that sub-packages do not
diff --git a/aconfig/aconfig_declarations.go b/aconfig/aconfig_declarations.go
index 78f506a..392e819 100644
--- a/aconfig/aconfig_declarations.go
+++ b/aconfig/aconfig_declarations.go
@@ -40,6 +40,9 @@
// Container(system/vendor/apex) that this module belongs to
Container string
+
+ // The flags will only be repackaged if this prop is true.
+ Exportable bool
}
intermediatePath android.WritablePath
@@ -159,6 +162,7 @@
android.SetProvider(ctx, android.AconfigDeclarationsProviderKey, android.AconfigDeclarationsProviderData{
Package: module.properties.Package,
Container: module.properties.Container,
+ Exportable: module.properties.Exportable,
IntermediateCacheOutputPath: intermediateCacheFilePath,
IntermediateDumpOutputPath: intermediateDumpFilePath,
})
diff --git a/aconfig/aconfig_declarations_test.go b/aconfig/aconfig_declarations_test.go
index d508af7..1fe3c86 100644
--- a/aconfig/aconfig_declarations_test.go
+++ b/aconfig/aconfig_declarations_test.go
@@ -27,6 +27,7 @@
name: "module_name",
package: "com.example.package",
container: "com.android.foo",
+ exportable: true,
srcs: [
"foo.aconfig",
"bar.aconfig",
@@ -41,6 +42,7 @@
depData, _ := android.SingletonModuleProvider(result, module, android.AconfigDeclarationsProviderKey)
android.AssertStringEquals(t, "package", depData.Package, "com.example.package")
android.AssertStringEquals(t, "container", depData.Container, "com.android.foo")
+ android.AssertBoolEquals(t, "exportable", depData.Exportable, true)
if !strings.HasSuffix(depData.IntermediateCacheOutputPath.String(), "/intermediate.pb") {
t.Errorf("Missing intermediates proto path in provider: %s", depData.IntermediateCacheOutputPath.String())
}
@@ -48,3 +50,22 @@
t.Errorf("Missing intermediates text path in provider: %s", depData.IntermediateDumpOutputPath.String())
}
}
+
+func TestAconfigDeclarationsWithExportableUnset(t *testing.T) {
+ bp := `
+ aconfig_declarations {
+ name: "module_name",
+ package: "com.example.package",
+ container: "com.android.foo",
+ srcs: [
+ "foo.aconfig",
+ "bar.aconfig",
+ ],
+ }
+ `
+ result := runTest(t, android.FixtureExpectsNoErrors, bp)
+
+ module := result.ModuleForTests("module_name", "").Module().(*DeclarationsModule)
+ depData, _ := android.SingletonModuleProvider(result, module, android.AconfigDeclarationsProviderKey)
+ android.AssertBoolEquals(t, "exportable", depData.Exportable, false)
+}
diff --git a/aconfig/codegen/java_aconfig_library.go b/aconfig/codegen/java_aconfig_library.go
index e6817e0..d4c6da5 100644
--- a/aconfig/codegen/java_aconfig_library.go
+++ b/aconfig/codegen/java_aconfig_library.go
@@ -91,6 +91,12 @@
if !isModeSupported(mode) {
ctx.PropertyErrorf("mode", "%q is not a supported mode", mode)
}
+ // TODO: uncomment this part after internal clean up
+ //if mode == "exported" && !declarations.Exportable {
+ // // if mode is exported, the corresponding aconfig_declaration must mark its
+ // // exportable property true
+ // ctx.PropertyErrorf("mode", "exported mode requires its aconfig_declaration has exportable prop true")
+ //}
ctx.Build(pctx, android.BuildParams{
Rule: javaRule,
@@ -102,6 +108,16 @@
},
})
+ if declarations.Exportable {
+ // Mark our generated code as possibly needing jarjar repackaging
+ // The repackaging only happens when the corresponding aconfig_declaration
+ // has property exportable true
+ module.AddJarJarRenameRule(declarations.Package+".Flags", "")
+ module.AddJarJarRenameRule(declarations.Package+".FeatureFlags", "")
+ module.AddJarJarRenameRule(declarations.Package+".FeatureFlagsImpl", "")
+ module.AddJarJarRenameRule(declarations.Package+".FakeFeatureFlagsImpl", "")
+ }
+
return srcJarPath
}
diff --git a/aconfig/codegen/java_aconfig_library_test.go b/aconfig/codegen/java_aconfig_library_test.go
index 85d2675..de45b5c 100644
--- a/aconfig/codegen/java_aconfig_library_test.go
+++ b/aconfig/codegen/java_aconfig_library_test.go
@@ -176,6 +176,7 @@
name: "my_aconfig_declarations",
package: "com.example.package",
srcs: ["foo.aconfig"],
+ exportable: true,
}
java_aconfig_library {
diff --git a/aconfig/init.go b/aconfig/init.go
index 3e9d297..77f5ed3 100644
--- a/aconfig/init.go
+++ b/aconfig/init.go
@@ -43,7 +43,7 @@
// For create-device-config-sysprops: Generate aconfig flag value map text file
aconfigTextRule = pctx.AndroidStaticRule("aconfig_text",
blueprint.RuleParams{
- Command: `${aconfig} dump-cache --format='{fully_qualified_name}={state:bool}'` +
+ Command: `${aconfig} dump-cache --dedup --format='{fully_qualified_name}={state:bool}'` +
` --cache ${in}` +
` --out ${out}.tmp` +
` && ( if cmp -s ${out}.tmp ${out} ; then rm ${out}.tmp ; else mv ${out}.tmp ${out} ; fi )`,
@@ -56,7 +56,7 @@
// For all_aconfig_declarations: Combine all parsed_flags proto files
AllDeclarationsRule = pctx.AndroidStaticRule("All_aconfig_declarations_dump",
blueprint.RuleParams{
- Command: `${aconfig} dump-cache --format protobuf --out ${out} ${cache_files}`,
+ Command: `${aconfig} dump-cache --dedup --format protobuf --out ${out} ${cache_files}`,
CommandDeps: []string{
"${aconfig}",
},
@@ -73,7 +73,7 @@
blueprint.RuleParams{
Command: `rm -rf ${out}.tmp` +
`&& for cache in ${cache_files}; do ` +
- ` if [ -n "$$(${aconfig} dump-cache --cache $$cache --filter=is_exported:true --format='{fully_qualified_name}')" ]; then ` +
+ ` if [ -n "$$(${aconfig} dump-cache --dedup --cache $$cache --filter=is_exported:true --format='{fully_qualified_name}')" ]; then ` +
` ${aconfig} create-java-lib --cache $$cache --mode=exported --out ${out}.tmp; ` +
` fi ` +
`done` +
diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go
index be9beb1..74c1a5e 100644
--- a/android/aconfig_providers.go
+++ b/android/aconfig_providers.go
@@ -35,6 +35,7 @@
type AconfigDeclarationsProviderData struct {
Package string
Container string
+ Exportable bool
IntermediateCacheOutputPath WritablePath
IntermediateDumpOutputPath WritablePath
}
@@ -171,7 +172,7 @@
}
func mergeAconfigFiles(ctx ModuleContext, container string, inputs Paths, generateRule bool) Paths {
- inputs = LastUniquePaths(inputs)
+ inputs = SortedUniquePaths(inputs)
if len(inputs) == 1 {
return Paths{inputs[0]}
}
diff --git a/android/all_teams.go b/android/all_teams.go
index 6c3a219..dd7d2db 100644
--- a/android/all_teams.go
+++ b/android/all_teams.go
@@ -118,8 +118,8 @@
// either the declared team data for that module or the package default team data for that module.
func (this *allTeamsSingleton) lookupTeamForAllModules() *team_proto.AllTeams {
teamsProto := make([]*team_proto.Team, len(this.teams_for_mods))
- i := 0
- for moduleName, m := range this.teams_for_mods {
+ for i, moduleName := range SortedKeys(this.teams_for_mods) {
+ m, _ := this.teams_for_mods[moduleName]
teamName := m.teamName
var teamProperties teamProperties
found := false
@@ -152,7 +152,6 @@
}
}
teamsProto[i] = teamData
- i++
}
return &team_proto.AllTeams{Teams: teamsProto}
}
diff --git a/android/arch.go b/android/arch.go
index c39db02..4fe4345 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -426,6 +426,7 @@
// filters out non-Soong modules. Now that we've handled them, create a
// normal android.BottomUpMutatorContext.
mctx := bottomUpMutatorContextFactory(bpctx, module, false)
+ defer bottomUpMutatorContextPool.Put(mctx)
base := module.base()
@@ -572,6 +573,7 @@
// filters out non-Soong modules. Now that we've handled them, create a
// normal android.BottomUpMutatorContext.
mctx := bottomUpMutatorContextFactory(bpctx, module, false)
+ defer bottomUpMutatorContextPool.Put(mctx)
base := module.base()
@@ -1058,9 +1060,7 @@
// order checks the `android:"variant_prepend"` tag to handle properties where the
// arch-specific value needs to come before the generic value, for example for lists of
// include directories.
- order := func(property string,
- dstField, srcField reflect.StructField,
- dstValue, srcValue interface{}) (proptools.Order, error) {
+ order := func(dstField, srcField reflect.StructField) (proptools.Order, error) {
if proptools.HasTag(dstField, "android", "variant_prepend") {
return proptools.Prepend, nil
} else {
diff --git a/android/config.go b/android/config.go
index d94a86f..f9cb842 100644
--- a/android/config.go
+++ b/android/config.go
@@ -28,6 +28,7 @@
"strconv"
"strings"
"sync"
+ "unicode"
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
@@ -209,6 +210,12 @@
Bool(c.config.productVariables.ReleaseDefaultModuleBuildFromSource)
}
+// Enables flagged apis annotated with READ_WRITE aconfig flags to be included in the stubs
+// and hiddenapi flags so that they are accessible at runtime
+func (c Config) ReleaseExportRuntimeApis() bool {
+ return c.config.productVariables.GetBuildFlagBool("RELEASE_EXPORT_RUNTIME_APIS")
+}
+
// Enables ABI monitoring of NDK libraries
func (c Config) ReleaseNdkAbiMonitored() bool {
return c.config.productVariables.GetBuildFlagBool("RELEASE_NDK_ABI_MONITORED")
@@ -320,6 +327,18 @@
return loadFromConfigFile(&config.productVariables, absolutePath(config.ProductVariablesFileName))
}
+// Checks if the string is a valid go identifier. This is equivalent to blueprint's definition
+// of an identifier, so it will match the same identifiers as those that can be used in bp files.
+func isGoIdentifier(ident string) bool {
+ for i, r := range ident {
+ valid := r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r) && i > 0
+ if !valid {
+ return false
+ }
+ }
+ return len(ident) > 0
+}
+
// loadFromConfigFile loads and decodes configuration options from a JSON file
// in the current working directory.
func loadFromConfigFile(configurable *ProductVariables, filename string) error {
@@ -355,6 +374,20 @@
Bool(configurable.GcovCoverage) ||
Bool(configurable.ClangCoverage))
+ // The go scanner's definition of identifiers is c-style identifiers, but allowing unicode's
+ // definition of letters and digits. This is the same scanner that blueprint uses, so it
+ // will allow the same identifiers as are valid in bp files.
+ for namespace := range configurable.VendorVars {
+ if !isGoIdentifier(namespace) {
+ return fmt.Errorf("soong config namespaces must be valid identifiers: %q", namespace)
+ }
+ for variable := range configurable.VendorVars[namespace] {
+ if !isGoIdentifier(variable) {
+ return fmt.Errorf("soong config variables must be valid identifiers: %q", variable)
+ }
+ }
+ }
+
// when Platform_sdk_final is true (or PLATFORM_VERSION_CODENAME is REL), use Platform_sdk_version;
// if false (pre-released version, for example), use Platform_sdk_codename.
if Bool(configurable.Platform_sdk_final) {
diff --git a/android/deapexer.go b/android/deapexer.go
index 2704b3e..61ae64e 100644
--- a/android/deapexer.go
+++ b/android/deapexer.go
@@ -83,6 +83,10 @@
// name of the java libraries exported from the apex
// e.g. core-libart
exportedModuleNames []string
+
+ // name of the java libraries exported from the apex that should be dexpreopt'd with the .prof
+ // file embedded in the apex
+ dexpreoptProfileGuidedExportedModuleNames []string
}
// ApexModuleName returns the name of the APEX module that provided the info.
@@ -121,6 +125,14 @@
}
}
+func (i *DeapexerInfo) GetDexpreoptProfileGuidedExportedModuleNames() []string {
+ return i.dexpreoptProfileGuidedExportedModuleNames
+}
+
+func (i *DeapexerInfo) AddDexpreoptProfileGuidedExportedModuleNames(names ...string) {
+ i.dexpreoptProfileGuidedExportedModuleNames = append(i.dexpreoptProfileGuidedExportedModuleNames, names...)
+}
+
type deapexerTagStruct struct {
blueprint.BaseDependencyTag
}
@@ -143,6 +155,9 @@
// the path to the extracted file will be stored in the DeapexerInfo using the APEX relative file
// path as the key, The path can then be retrieved using the PrebuiltExportPath(key) method.
RequiredFilesFromPrebuiltApex(ctx BaseModuleContext) []string
+
+ // Returns true if a transitive dependency of an apex should use a .prof file to guide dexpreopt
+ UseProfileGuidedDexpreopt() bool
}
// Marker interface that identifies dependencies on modules that may require files from a prebuilt
diff --git a/android/defaults_test.go b/android/defaults_test.go
index a7542ab..0ad0fb8 100644
--- a/android/defaults_test.go
+++ b/android/defaults_test.go
@@ -16,10 +16,13 @@
import (
"testing"
+
+ "github.com/google/blueprint"
)
type defaultsTestProperties struct {
- Foo []string
+ Foo []string
+ Path_prop []string `android:"path"`
}
type defaultsTestModule struct {
@@ -130,3 +133,40 @@
// TODO: missing transitive defaults is currently not handled
_ = missingTransitiveDefaults
}
+
+func TestDefaultsPathProperties(t *testing.T) {
+ bp := `
+ defaults {
+ name: "defaults",
+ path_prop: [":gen"],
+ }
+
+ test {
+ name: "foo",
+ defaults: ["defaults"],
+ }
+
+ test {
+ name: "gen",
+ }
+ `
+
+ result := GroupFixturePreparers(
+ prepareForDefaultsTest,
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
+
+ collectDeps := func(m Module) []string {
+ var deps []string
+ result.VisitDirectDeps(m, func(dep blueprint.Module) {
+ deps = append(deps, result.ModuleName(dep))
+ })
+ return deps
+ }
+
+ foo := result.Module("foo", "")
+ defaults := result.Module("defaults", "")
+
+ AssertStringListContains(t, "foo should depend on gen", collectDeps(foo), "gen")
+ AssertStringListDoesNotContain(t, "defaults should not depend on gen", collectDeps(defaults), "gen")
+}
diff --git a/android/module.go b/android/module.go
index 5c7bbbf..b615ff5 100644
--- a/android/module.go
+++ b/android/module.go
@@ -34,6 +34,7 @@
var (
DeviceSharedLibrary = "shared_library"
DeviceStaticLibrary = "static_library"
+ jarJarPrefixHandler func(ctx ModuleContext)
)
type Module interface {
@@ -1772,6 +1773,13 @@
return
}
+ if jarJarPrefixHandler != nil {
+ jarJarPrefixHandler(ctx)
+ if ctx.Failed() {
+ return
+ }
+ }
+
m.module.GenerateAndroidBuildActions(ctx)
if ctx.Failed() {
return
@@ -1865,6 +1873,13 @@
m.variables = ctx.variables
}
+func SetJarJarPrefixHandler(handler func(ModuleContext)) {
+ if jarJarPrefixHandler != nil {
+ panic("jarJarPrefixHandler already set")
+ }
+ jarJarPrefixHandler = handler
+}
+
func (m *ModuleBase) moduleInfoRegisterName(ctx ModuleContext, subName string) string {
name := m.BaseModuleName()
diff --git a/android/mutator.go b/android/mutator.go
index 22e9160..0ff4f48 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -15,6 +15,8 @@
package android
import (
+ "sync"
+
"github.com/google/blueprint"
)
@@ -328,29 +330,52 @@
SetVariationProvider(module blueprint.Module, provider blueprint.AnyProviderKey, value interface{})
}
+// An outgoingTransitionContextImpl and incomingTransitionContextImpl is created for every dependency of every module
+// for each transition mutator. bottomUpMutatorContext and topDownMutatorContext are created once for every module
+// for every BottomUp or TopDown mutator. Use a global pool for each to avoid reallocating every time.
+var (
+ outgoingTransitionContextPool = sync.Pool{
+ New: func() any { return &outgoingTransitionContextImpl{} },
+ }
+ incomingTransitionContextPool = sync.Pool{
+ New: func() any { return &incomingTransitionContextImpl{} },
+ }
+ bottomUpMutatorContextPool = sync.Pool{
+ New: func() any { return &bottomUpMutatorContext{} },
+ }
+
+ topDownMutatorContextPool = sync.Pool{
+ New: func() any { return &topDownMutatorContext{} },
+ }
+)
+
type bottomUpMutatorContext struct {
bp blueprint.BottomUpMutatorContext
baseModuleContext
finalPhase bool
}
+// callers must immediately follow the call to this function with defer bottomUpMutatorContextPool.Put(mctx).
func bottomUpMutatorContextFactory(ctx blueprint.BottomUpMutatorContext, a Module,
finalPhase bool) BottomUpMutatorContext {
moduleContext := a.base().baseModuleContextFactory(ctx)
-
- return &bottomUpMutatorContext{
+ mctx := bottomUpMutatorContextPool.Get().(*bottomUpMutatorContext)
+ *mctx = bottomUpMutatorContext{
bp: ctx,
baseModuleContext: moduleContext,
finalPhase: finalPhase,
}
+ return mctx
}
func (x *registerMutatorsContext) BottomUp(name string, m BottomUpMutator) MutatorHandle {
finalPhase := x.finalPhase
f := func(ctx blueprint.BottomUpMutatorContext) {
if a, ok := ctx.Module().(Module); ok {
- m(bottomUpMutatorContextFactory(ctx, a, finalPhase))
+ mctx := bottomUpMutatorContextFactory(ctx, a, finalPhase)
+ defer bottomUpMutatorContextPool.Put(mctx)
+ m(mctx)
}
}
mutator := &mutator{name: x.mutatorName(name), bottomUpMutator: f}
@@ -514,7 +539,9 @@
func (a *androidTransitionMutator) OutgoingTransition(bpctx blueprint.OutgoingTransitionContext, sourceVariation string) string {
if m, ok := bpctx.Module().(Module); ok {
- ctx := &outgoingTransitionContextImpl{
+ ctx := outgoingTransitionContextPool.Get().(*outgoingTransitionContextImpl)
+ defer outgoingTransitionContextPool.Put(ctx)
+ *ctx = outgoingTransitionContextImpl{
archModuleContext: m.base().archModuleContextFactory(bpctx),
bp: bpctx,
}
@@ -543,7 +570,9 @@
func (a *androidTransitionMutator) IncomingTransition(bpctx blueprint.IncomingTransitionContext, incomingVariation string) string {
if m, ok := bpctx.Module().(Module); ok {
- ctx := &incomingTransitionContextImpl{
+ ctx := incomingTransitionContextPool.Get().(*incomingTransitionContextImpl)
+ defer incomingTransitionContextPool.Put(ctx)
+ *ctx = incomingTransitionContextImpl{
archModuleContext: m.base().archModuleContextFactory(bpctx),
bp: bpctx,
}
@@ -555,7 +584,9 @@
func (a *androidTransitionMutator) Mutate(ctx blueprint.BottomUpMutatorContext, variation string) {
if am, ok := ctx.Module().(Module); ok {
- a.mutator.Mutate(bottomUpMutatorContextFactory(ctx, am, a.finalPhase), variation)
+ mctx := bottomUpMutatorContextFactory(ctx, am, a.finalPhase)
+ defer bottomUpMutatorContextPool.Put(mctx)
+ a.mutator.Mutate(mctx, variation)
}
}
@@ -578,7 +609,9 @@
f := func(ctx blueprint.TopDownMutatorContext) {
if a, ok := ctx.Module().(Module); ok {
moduleContext := a.base().baseModuleContextFactory(ctx)
- actx := &topDownMutatorContext{
+ actx := topDownMutatorContextPool.Get().(*topDownMutatorContext)
+ defer topDownMutatorContextPool.Put(actx)
+ *actx = topDownMutatorContext{
bp: ctx,
baseModuleContext: moduleContext,
}
diff --git a/android/packaging.go b/android/packaging.go
index 8873540..a8fb28d 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -85,6 +85,7 @@
// GatherPackagingSpecs gathers PackagingSpecs of transitive dependencies.
GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec
+ GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec
// CopyDepsToZip zips the built artifacts of the dependencies into the given zip file and
// returns zip entries in it. This is expected to be called in GenerateAndroidBuildActions,
@@ -221,14 +222,18 @@
}
}
-// See PackageModule.GatherPackagingSpecs
-func (p *PackagingBase) GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec {
+func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec {
m := make(map[string]PackagingSpec)
ctx.VisitDirectDeps(func(child Module) {
if pi, ok := ctx.OtherModuleDependencyTag(child).(PackagingItem); !ok || !pi.IsPackagingItem() {
return
}
for _, ps := range child.TransitivePackagingSpecs() {
+ if filter != nil {
+ if !filter(ps) {
+ continue
+ }
+ }
if _, ok := m[ps.relPathInPackage]; !ok {
m[ps.relPathInPackage] = ps
}
@@ -237,6 +242,11 @@
return m
}
+// See PackageModule.GatherPackagingSpecs
+func (p *PackagingBase) GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec {
+ return p.GatherPackagingSpecsWithFilter(ctx, nil)
+}
+
// CopySpecsToDir is a helper that will add commands to the rule builder to copy the PackagingSpec
// entries into the specified directory.
func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir WritablePath) (entries []string) {
diff --git a/android/path_properties.go b/android/path_properties.go
index fdc4d91..bbfaa8c 100644
--- a/android/path_properties.go
+++ b/android/path_properties.go
@@ -33,6 +33,11 @@
// The pathDepsMutator automatically adds dependencies on any module that is listed with the
// ":module" module reference syntax in a property that is tagged with `android:"path"`.
func pathDepsMutator(ctx BottomUpMutatorContext) {
+ if _, ok := ctx.Module().(DefaultsModule); ok {
+ // Defaults modules shouldn't have dependencies added for path properties, they have already been
+ // squashed into the real modules.
+ return
+ }
props := ctx.Module().base().GetProperties()
addPathDepsForProps(ctx, props)
}
diff --git a/android/paths.go b/android/paths.go
index 95f53ea..61c1258 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1661,6 +1661,8 @@
// makePath indicates whether this path is for Soong (false) or Make (true).
makePath bool
+
+ fullPath string
}
// Will panic if called from outside a test environment.
@@ -1673,7 +1675,12 @@
func (p InstallPath) RelativeToTop() Path {
ensureTestOnly()
- p.soongOutDir = OutSoongDir
+ if p.makePath {
+ p.soongOutDir = OutDir
+ } else {
+ p.soongOutDir = OutSoongDir
+ }
+ p.fullPath = filepath.Join(p.soongOutDir, p.path)
return p
}
@@ -1691,12 +1698,7 @@
func (p InstallPath) writablePath() {}
func (p InstallPath) String() string {
- if p.makePath {
- // Make path starts with out/ instead of out/soong.
- return filepath.Join(p.soongOutDir, "../", p.path)
- } else {
- return filepath.Join(p.soongOutDir, p.path)
- }
+ return p.fullPath
}
// PartitionDir returns the path to the partition where the install path is rooted at. It is
@@ -1726,6 +1728,7 @@
func (p InstallPath) withRel(rel string) InstallPath {
p.basePath = p.basePath.withRel(rel)
+ p.fullPath = filepath.Join(p.fullPath, rel)
return p
}
@@ -1769,6 +1772,25 @@
return os, arch
}
+func pathForPartitionInstallDir(ctx PathContext, partition, partitionPath string, makePath bool) InstallPath {
+ fullPath := ctx.Config().SoongOutDir()
+ if makePath {
+ // Make path starts with out/ instead of out/soong.
+ fullPath = filepath.Join(fullPath, "../", partitionPath)
+ } else {
+ fullPath = filepath.Join(fullPath, partitionPath)
+ }
+
+ return InstallPath{
+ basePath: basePath{partitionPath, ""},
+ soongOutDir: ctx.Config().soongOutDir,
+ partitionDir: partitionPath,
+ partition: partition,
+ makePath: makePath,
+ fullPath: fullPath,
+ }
+}
+
func pathForInstall(ctx PathContext, os OsType, arch ArchType, partition string,
pathComponents ...string) InstallPath {
@@ -1805,27 +1827,12 @@
reportPathError(ctx, err)
}
- base := InstallPath{
- basePath: basePath{partitionPath, ""},
- soongOutDir: ctx.Config().soongOutDir,
- partitionDir: partitionPath,
- partition: partition,
- }
-
- if ctx.Config().KatiEnabled() {
- base.makePath = true
- }
-
+ base := pathForPartitionInstallDir(ctx, partition, partitionPath, ctx.Config().KatiEnabled())
return base.Join(ctx, pathComponents...)
}
func pathForNdkOrSdkInstall(ctx PathContext, prefix string, paths []string) InstallPath {
- base := InstallPath{
- basePath: basePath{prefix, ""},
- soongOutDir: ctx.Config().soongOutDir,
- partitionDir: prefix,
- makePath: false,
- }
+ base := pathForPartitionInstallDir(ctx, "", prefix, false)
return base.Join(ctx, paths...)
}
diff --git a/android/prebuilt.go b/android/prebuilt.go
index a94f5b7..13cda9d 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -518,7 +518,7 @@
// query all_apex_contributions to see if any module in this family has been selected
for _, moduleInFamily := range allModulesInFamily {
// validate that are no duplicates
- if psi.IsSelected(moduleInFamily.Name()) {
+ if isSelected(psi, moduleInFamily) {
if selectedModuleInFamily == nil {
// Store this so we can validate that there are no duplicates
selectedModuleInFamily = moduleInFamily
@@ -547,13 +547,29 @@
if p := GetEmbeddedPrebuilt(m); p != nil {
bmn, _ := m.(baseModuleName)
name := bmn.BaseModuleName()
+ psi := PrebuiltSelectionInfoMap{}
+ ctx.VisitDirectDepsWithTag(acDepTag, func(am Module) {
+ psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider)
+ })
+
if p.properties.UsePrebuilt {
if p.properties.SourceExists {
ctx.ReplaceDependenciesIf(name, func(from blueprint.Module, tag blueprint.DependencyTag, to blueprint.Module) bool {
+ if sdkLibrary, ok := m.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil {
+ // Do not replace deps to the top-level prebuilt java_sdk_library hook.
+ // This hook has been special-cased in #isSelected to be _always_ active, even in next builds
+ // for dexpreopt and hiddenapi processing.
+ // If we do not special-case this here, rdeps referring to a java_sdk_library in next builds via libs
+ // will get prebuilt stubs
+ // TODO (b/308187268): Remove this after the apexes have been added to apex_contributions
+ if psi.IsSelected(*sdkLibrary.SdkLibraryName()) {
+ return false
+ }
+ }
+
if t, ok := tag.(ReplaceSourceWithPrebuilt); ok {
return t.ReplaceSourceWithPrebuilt()
}
-
return true
})
}
@@ -582,15 +598,20 @@
func isSelected(psi PrebuiltSelectionInfoMap, m Module) bool {
if sdkLibrary, ok := m.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil {
sln := proptools.String(sdkLibrary.SdkLibraryName())
+
// This is the top-level library
// Do not supersede the existing prebuilts vs source selection mechanisms
- if sln == m.base().BaseModuleName() {
+ // TODO (b/308187268): Remove this after the apexes have been added to apex_contributions
+ if bmn, ok := m.(baseModuleName); ok && sln == bmn.BaseModuleName() {
return false
}
// Stub library created by java_sdk_library_import
- if p := GetEmbeddedPrebuilt(m); p != nil {
- return psi.IsSelected(PrebuiltNameFromSource(sln))
+ // java_sdk_library creates several child modules (java_import + prebuilt_stubs_sources) dynamically.
+ // This code block ensures that these child modules are selected if the top-level java_sdk_library_import is listed
+ // in the selected apex_contributions.
+ if javaImport, ok := m.(createdByJavaSdkLibraryName); ok && javaImport.CreatedByJavaSdkLibraryName() != nil {
+ return psi.IsSelected(PrebuiltNameFromSource(proptools.String(javaImport.CreatedByJavaSdkLibraryName())))
}
// Stub library created by java_sdk_library
@@ -599,6 +620,11 @@
return psi.IsSelected(m.Name())
}
+// implemented by child modules of java_sdk_library_import
+type createdByJavaSdkLibraryName interface {
+ CreatedByJavaSdkLibraryName() *string
+}
+
// usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt
// will be used if it is marked "prefer" or if the source module is disabled.
func (p *Prebuilt) usePrebuilt(ctx BaseMutatorContext, source Module, prebuilt Module) bool {
diff --git a/android/sdk_version.go b/android/sdk_version.go
index 9355667..b2ff960 100644
--- a/android/sdk_version.go
+++ b/android/sdk_version.go
@@ -393,6 +393,7 @@
// Export the name of the soong modules representing the various Java API surfaces.
func javaSdkMakeVars(ctx MakeVarsContext) {
ctx.Strict("ANDROID_PUBLIC_STUBS", SdkPublic.DefaultJavaLibraryName())
+ ctx.Strict("ANDROID_PUBLIC_EXPORTABLE_STUBS", SdkPublic.DefaultExportableJavaLibraryName())
ctx.Strict("ANDROID_SYSTEM_STUBS", SdkSystem.DefaultJavaLibraryName())
ctx.Strict("ANDROID_TEST_STUBS", SdkTest.DefaultJavaLibraryName())
ctx.Strict("ANDROID_MODULE_LIB_STUBS", SdkModule.DefaultJavaLibraryName())
diff --git a/android/singleton.go b/android/singleton.go
index e0e552e..ccddeaf 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -250,8 +250,8 @@
}
func (s *singletonContextAdaptor) ModuleVariantsFromName(referer Module, name string) []Module {
- // get qualified module name for visibility enforcement
- qualified := createQualifiedModuleName(s.ModuleName(referer), s.ModuleDir(referer))
+ // get module reference for visibility enforcement
+ qualified := createVisibilityModuleReference(s.ModuleName(referer), s.ModuleDir(referer), s.ModuleType(referer))
modules := s.SingletonContext.ModuleVariantsFromName(referer, name)
result := make([]Module, 0, len(modules))
@@ -262,7 +262,7 @@
depDir := s.ModuleDir(module)
depQualified := qualifiedModuleName{depDir, depName}
// Targets are always visible to other targets in their own package.
- if depQualified.pkg != qualified.pkg {
+ if depQualified.pkg != qualified.name.pkg {
rule := effectiveVisibilityRules(s.Config(), depQualified)
if !rule.matches(qualified) {
s.ModuleErrorf(referer, "module %q references %q which is not visible to this module\nYou may need to add %q to its visibility",
diff --git a/android/test_suites.go b/android/test_suites.go
index 9ded998..adcc15a 100644
--- a/android/test_suites.go
+++ b/android/test_suites.go
@@ -24,6 +24,7 @@
type testSuiteFiles struct {
robolectric WritablePath
+ ravenwood WritablePath
}
type TestSuiteModule interface {
@@ -47,12 +48,15 @@
})
t.robolectric = robolectricTestSuite(ctx, files["robolectric-tests"])
-
ctx.Phony("robolectric-tests", t.robolectric)
+
+ t.ravenwood = ravenwoodTestSuite(ctx, files["ravenwood-tests"])
+ ctx.Phony("ravenwood-tests", t.ravenwood)
}
func (t *testSuiteFiles) MakeVars(ctx MakeVarsContext) {
ctx.DistForGoal("robolectric-tests", t.robolectric)
+ ctx.DistForGoal("ravenwood-tests", t.ravenwood)
}
func robolectricTestSuite(ctx SingletonContext, files map[string]InstallPaths) WritablePath {
@@ -74,3 +78,23 @@
return outputFile
}
+
+func ravenwoodTestSuite(ctx SingletonContext, files map[string]InstallPaths) WritablePath {
+ var installedPaths InstallPaths
+ for _, module := range SortedKeys(files) {
+ installedPaths = append(installedPaths, files[module]...)
+ }
+ testCasesDir := pathForInstall(ctx, ctx.Config().BuildOS, X86, "testcases")
+
+ outputFile := PathForOutput(ctx, "packaging", "ravenwood-tests.zip")
+ rule := NewRuleBuilder(pctx, ctx)
+ rule.Command().BuiltTool("soong_zip").
+ FlagWithOutput("-o ", outputFile).
+ FlagWithArg("-P ", "host/testcases").
+ FlagWithArg("-C ", testCasesDir.String()).
+ FlagWithRspFileInputList("-r ", outputFile.ReplaceExtension(ctx, "rsp"), installedPaths.Paths()).
+ Flag("-sha256")
+ rule.Build("ravenwood_tests_zip", "ravenwood-tests.zip")
+
+ return outputFile
+}
diff --git a/android/util.go b/android/util.go
index 51313ce..363b31c 100644
--- a/android/util.go
+++ b/android/util.go
@@ -15,6 +15,7 @@
package android
import (
+ "cmp"
"fmt"
"path/filepath"
"reflect"
@@ -106,15 +107,8 @@
return SortedKeys(m)
}
-type Ordered interface {
- ~string |
- ~float32 | ~float64 |
- ~int | ~int8 | ~int16 | ~int32 | ~int64 |
- ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
-}
-
// SortedKeys returns the keys of the given map in the ascending order.
-func SortedKeys[T Ordered, V any](m map[T]V) []T {
+func SortedKeys[T cmp.Ordered, V any](m map[T]V) []T {
if len(m) == 0 {
return nil
}
diff --git a/android/util_test.go b/android/util_test.go
index 699135b..8e73d83 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -15,6 +15,7 @@
package android
import (
+ "cmp"
"fmt"
"reflect"
"strconv"
@@ -650,7 +651,7 @@
}
}
-func testSortedKeysHelper[K Ordered, V any](t *testing.T, name string, input map[K]V, expected []K) {
+func testSortedKeysHelper[K cmp.Ordered, V any](t *testing.T, name string, input map[K]V, expected []K) {
t.Helper()
t.Run(name, func(t *testing.T) {
actual := SortedKeys(input)
diff --git a/android/visibility.go b/android/visibility.go
index 3130135..b387562 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -57,12 +57,29 @@
var visibilityRuleRegexp = regexp.MustCompile(visibilityRulePattern)
+type visibilityModuleReference struct {
+ name qualifiedModuleName
+ isPartitionModule bool
+}
+
+func createVisibilityModuleReference(name, dir, typ string) visibilityModuleReference {
+ isPartitionModule := false
+ switch typ {
+ case "android_filesystem", "android_system_image":
+ isPartitionModule = true
+ }
+ return visibilityModuleReference{
+ name: createQualifiedModuleName(name, dir),
+ isPartitionModule: isPartitionModule,
+ }
+}
+
// A visibility rule is associated with a module and determines which other modules it is visible
// to, i.e. which other modules can depend on the rule's module.
type visibilityRule interface {
// Check to see whether this rules matches m.
// Returns true if it does, false otherwise.
- matches(m qualifiedModuleName) bool
+ matches(m visibilityModuleReference) bool
String() string
}
@@ -108,8 +125,10 @@
// ["//visibility:private"].
type compositeRule []visibilityRule
+var _ visibilityRule = compositeRule{}
+
// A compositeRule matches if and only if any of its rules matches.
-func (c compositeRule) matches(m qualifiedModuleName) bool {
+func (c compositeRule) matches(m visibilityModuleReference) bool {
for _, r := range c {
if r.matches(m) {
return true
@@ -135,8 +154,10 @@
pkg string
}
-func (r packageRule) matches(m qualifiedModuleName) bool {
- return m.pkg == r.pkg
+var _ visibilityRule = packageRule{}
+
+func (r packageRule) matches(m visibilityModuleReference) bool {
+ return m.name.pkg == r.pkg
}
func (r packageRule) String() string {
@@ -149,8 +170,10 @@
pkgPrefix string
}
-func (r subpackagesRule) matches(m qualifiedModuleName) bool {
- return isAncestor(r.pkgPrefix, m.pkg)
+var _ visibilityRule = subpackagesRule{}
+
+func (r subpackagesRule) matches(m visibilityModuleReference) bool {
+ return isAncestor(r.pkgPrefix, m.name.pkg)
}
func isAncestor(p1 string, p2 string) bool {
@@ -168,7 +191,9 @@
// visibilityRule for //visibility:public
type publicRule struct{}
-func (r publicRule) matches(_ qualifiedModuleName) bool {
+var _ visibilityRule = publicRule{}
+
+func (r publicRule) matches(_ visibilityModuleReference) bool {
return true
}
@@ -179,7 +204,9 @@
// visibilityRule for //visibility:private
type privateRule struct{}
-func (r privateRule) matches(_ qualifiedModuleName) bool {
+var _ visibilityRule = privateRule{}
+
+func (r privateRule) matches(_ visibilityModuleReference) bool {
return false
}
@@ -187,6 +214,19 @@
return "//visibility:private"
}
+// visibilityRule for //visibility:any_partition
+type anyPartitionRule struct{}
+
+var _ visibilityRule = anyPartitionRule{}
+
+func (r anyPartitionRule) matches(m visibilityModuleReference) bool {
+ return m.isPartitionModule
+}
+
+func (r anyPartitionRule) String() string {
+ return "//visibility:any_partition"
+}
+
var visibilityRuleMap = NewOnceKey("visibilityRuleMap")
// The map from qualifiedModuleName to visibilityRule.
@@ -237,13 +277,10 @@
// Checks the per-module visibility rule lists before defaults expansion.
func visibilityRuleChecker(ctx BottomUpMutatorContext) {
- qualified := createQualifiedModuleName(ctx.ModuleName(), ctx.ModuleDir())
- if m, ok := ctx.Module().(Module); ok {
- visibilityProperties := m.visibilityProperties()
- for _, p := range visibilityProperties {
- if visibility := p.getStrings(); visibility != nil {
- checkRules(ctx, qualified.pkg, p.getName(), visibility)
- }
+ visibilityProperties := ctx.Module().visibilityProperties()
+ for _, p := range visibilityProperties {
+ if visibility := p.getStrings(); visibility != nil {
+ checkRules(ctx, ctx.ModuleDir(), p.getName(), visibility)
}
}
}
@@ -266,7 +303,7 @@
if pkg == "visibility" {
switch name {
- case "private", "public":
+ case "private", "public", "any_partition":
case "legacy_public":
ctx.PropertyErrorf(property, "//visibility:legacy_public must not be used")
continue
@@ -305,10 +342,7 @@
//
// See ../README.md#Visibility for information on the format of the visibility rules.
func visibilityRuleGatherer(ctx BottomUpMutatorContext) {
- m, ok := ctx.Module().(Module)
- if !ok {
- return
- }
+ m := ctx.Module()
qualifiedModuleId := m.qualifiedModuleId(ctx)
currentPkg := qualifiedModuleId.pkg
@@ -355,6 +389,8 @@
hasNonPrivateRule = false
// This does not actually create a rule so continue onto the next rule.
continue
+ case "any_partition":
+ r = anyPartitionRule{}
}
} else {
switch name {
@@ -395,10 +431,7 @@
func isAllowedFromOutsideVendor(pkg string, name string) bool {
if pkg == "vendor" {
- if name == "__subpackages__" {
- return true
- }
- return false
+ return name == "__subpackages__"
}
return !isAncestor("vendor", pkg)
@@ -434,11 +467,7 @@
}
func visibilityRuleEnforcer(ctx TopDownMutatorContext) {
- if _, ok := ctx.Module().(Module); !ok {
- return
- }
-
- qualified := createQualifiedModuleName(ctx.ModuleName(), ctx.ModuleDir())
+ qualified := createVisibilityModuleReference(ctx.ModuleName(), ctx.ModuleDir(), ctx.ModuleType())
// Visit all the dependencies making sure that this module has access to them all.
ctx.VisitDirectDeps(func(dep Module) {
@@ -453,7 +482,7 @@
depQualified := qualifiedModuleName{depDir, depName}
// Targets are always visible to other targets in their own package.
- if depQualified.pkg == qualified.pkg {
+ if depQualified.pkg == qualified.name.pkg {
return
}
@@ -478,7 +507,7 @@
if ok {
rule = value.(compositeRule)
} else {
- rule = packageDefaultVisibility(config, qualified)
+ rule = packageDefaultVisibility(moduleToVisibilityRule, qualified)
}
// If no rule is specified then return the default visibility rule to avoid
@@ -494,8 +523,7 @@
return qualified
}
-func packageDefaultVisibility(config Config, moduleId qualifiedModuleName) compositeRule {
- moduleToVisibilityRule := moduleToVisibilityRuleMap(config)
+func packageDefaultVisibility(moduleToVisibilityRule *sync.Map, moduleId qualifiedModuleName) compositeRule {
packageQualifiedId := moduleId.getContainingPackageId()
for {
value, ok := moduleToVisibilityRule.Load(packageQualifiedId)
@@ -574,10 +602,12 @@
rule := effectiveVisibilityRules(ctx.Config(), qualified)
+ currentModule := createVisibilityModuleReference(moduleName, dir, ctx.OtherModuleType(module))
+
// Modules are implicitly visible to other modules in the same package,
// without checking the visibility rules. Here we need to add that visibility
// explicitly.
- if !rule.matches(qualified) {
+ if !rule.matches(currentModule) {
if len(rule) == 1 {
if _, ok := rule[0].(privateRule); ok {
// If the rule is //visibility:private we can't append another
diff --git a/android/visibility_test.go b/android/visibility_test.go
index a66f0b6..d4add7d 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -1904,6 +1904,38 @@
}`),
},
},
+ {
+ name: "any_partition visibility works",
+ fs: MockFS{
+ "top/Android.bp": []byte(`
+ android_filesystem {
+ name: "foo",
+ deps: ["bar"],
+ }`),
+ "top/nested/Android.bp": []byte(`
+ package(default_visibility=["//visibility:private"])
+ mock_library {
+ name: "bar",
+ visibility: ["//visibility:any_partition"],
+ }`),
+ },
+ },
+ {
+ name: "any_partition visibility doesn't work for non-partitions",
+ fs: MockFS{
+ "top/Android.bp": []byte(`
+ mock_library {
+ name: "foo",
+ deps: ["bar"],
+ }`),
+ "top/nested/Android.bp": []byte(`
+ mock_library {
+ name: "bar",
+ visibility: ["//visibility:any_partition"],
+ }`),
+ },
+ expectedErrors: []string{`module "foo" variant "android_common": depends on //top/nested:bar which is not visible to this module`},
+ },
}
func TestVisibility(t *testing.T) {
@@ -1925,6 +1957,8 @@
ctx.RegisterModuleType("mock_library", newMockLibraryModule)
ctx.RegisterModuleType("mock_parent", newMockParentFactory)
ctx.RegisterModuleType("mock_defaults", defaultsFactory)
+ // For testing //visibility:any_partition. The module type doesn't matter, just that it's registered under the name "android_filesystem"
+ ctx.RegisterModuleType("android_filesystem", newMockLibraryModule)
}),
prepareForTestWithFakePrebuiltModules,
// Add additional files to the mock filesystem
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 7e67c0f..d3959ec 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -1455,6 +1455,7 @@
name: "libc",
no_libcrt: true,
nocrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
stubs: { versions: ["1"] },
@@ -1469,6 +1470,7 @@
name: "libclang_rt.hwasan",
no_libcrt: true,
nocrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
srcs: [""],
@@ -1511,6 +1513,7 @@
name: "libc",
no_libcrt: true,
nocrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
stubs: { versions: ["1"] },
@@ -1521,6 +1524,7 @@
name: "libclang_rt.hwasan",
no_libcrt: true,
nocrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
srcs: [""],
@@ -3768,13 +3772,6 @@
"lib64/libvndk.so",
"lib64/libvndksp.so"),
},
- {
- vndkVersion: "",
- expectedFiles: append(commonFiles,
- // Legacy VNDK APEX contains only VNDK-SP files (of core variant)
- "lib/libvndksp.so",
- "lib64/libvndksp.so"),
- },
}
for _, tc := range testCases {
t.Run("VNDK.current with DeviceVndkVersion="+tc.vndkVersion, func(t *testing.T) {
diff --git a/apex/builder.go b/apex/builder.go
index 3078863..40ccd2c 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -910,7 +910,7 @@
var validations android.Paths
validations = append(validations, runApexLinkerconfigValidation(ctx, unsignedOutputFile.OutputPath, imageDir.OutputPath))
// TODO(b/279688635) deapexer supports [ext4]
- if suffix == imageApexSuffix && ext4 == a.payloadFsType {
+ if !a.testApex && suffix == imageApexSuffix && ext4 == a.payloadFsType {
validations = append(validations, runApexSepolicyTests(ctx, unsignedOutputFile.OutputPath))
}
if !a.testApex && len(a.properties.Unwanted_transitive_deps) > 0 {
diff --git a/apex/deapexer.go b/apex/deapexer.go
index 5ff622c..a673108 100644
--- a/apex/deapexer.go
+++ b/apex/deapexer.go
@@ -53,6 +53,10 @@
// all architectures, e.g. java.
CommonModules []string
+ // List of modules that use an embedded .prof to guide optimization of the equivalent dexpreopt artifact
+ // This is a subset of CommonModules
+ DexpreoptProfileGuidedModules []string
+
// List of files exported from the .apex file by this module
//
// Each entry is a path from the apex root, e.g. javalib/core-libart.jar.
@@ -128,6 +132,7 @@
if len(exports) > 0 {
// Make the information available for other modules.
di := android.NewDeapexerInfo(apexModuleName(ctx.ModuleName()), exports, p.properties.CommonModules)
+ di.AddDexpreoptProfileGuidedExportedModuleNames(p.properties.DexpreoptProfileGuidedModules...)
android.SetProvider(ctx, android.DeapexerProvider, di)
// Create a sorted list of the files that this exports.
diff --git a/apex/dexpreopt_bootjars_test.go b/apex/dexpreopt_bootjars_test.go
index d9ab8fa..7a17f50 100644
--- a/apex/dexpreopt_bootjars_test.go
+++ b/apex/dexpreopt_bootjars_test.go
@@ -164,6 +164,7 @@
"out/soong/dexpreopt_arm64/dex_bootjars_input/baz.jar",
"out/soong/.intermediates/art-bootclasspath-fragment/android_common_apex10000/art-bootclasspath-fragment/boot.prof",
"out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof",
+ "out/soong/dexpreopt/uffd_gc_flag.txt",
}
expectedOutputs := []string{
@@ -201,6 +202,7 @@
"out/soong/dexpreopt_arm64/dex_bootjars_input/baz.jar",
"out/soong/.intermediates/prebuilt_com.android.art.deapexer/android_common/deapexer/etc/boot-image.prof",
"out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof",
+ "out/soong/dexpreopt/uffd_gc_flag.txt",
}
expectedOutputs := []string{
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 551942d..cebbae9 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -629,6 +629,7 @@
// Compute the deapexer properties from the transitive dependencies of this module.
commonModules := []string{}
+ dexpreoptProfileGuidedModules := []string{}
exportedFiles := []string{}
ctx.WalkDeps(func(child, parent android.Module) bool {
tag := ctx.OtherModuleDependencyTag(child)
@@ -638,13 +639,18 @@
return false
}
- name := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child))
+ name := java.ModuleStemForDeapexing(child)
if _, ok := tag.(android.RequiresFilesFromPrebuiltApexTag); ok {
commonModules = append(commonModules, name)
- requiredFiles := child.(android.RequiredFilesFromPrebuiltApex).RequiredFilesFromPrebuiltApex(ctx)
+ extract := child.(android.RequiredFilesFromPrebuiltApex)
+ requiredFiles := extract.RequiredFilesFromPrebuiltApex(ctx)
exportedFiles = append(exportedFiles, requiredFiles...)
+ if extract.UseProfileGuidedDexpreopt() {
+ dexpreoptProfileGuidedModules = append(dexpreoptProfileGuidedModules, name)
+ }
+
// Visit the dependencies of this module just in case they also require files from the
// prebuilt apex.
return true
@@ -657,7 +663,8 @@
deapexerProperties := &DeapexerProperties{
// Remove any duplicates from the common modules lists as a module may be included via a direct
// dependency as well as transitive ones.
- CommonModules: android.SortedUniqueStrings(commonModules),
+ CommonModules: android.SortedUniqueStrings(commonModules),
+ DexpreoptProfileGuidedModules: android.SortedUniqueStrings(dexpreoptProfileGuidedModules),
}
// Populate the exported files property in a fixed order.
diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go
index 6b2c397..f6c53b2 100644
--- a/apex/systemserver_classpath_fragment_test.go
+++ b/apex/systemserver_classpath_fragment_test.go
@@ -221,8 +221,6 @@
}
func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) {
- // TODO(spandandas): Fix the rules for profile guided dexpreopt of deapexed prebuilt jars
- t.Skip()
result := android.GroupFixturePreparers(
prepareForTestWithSystemserverclasspathFragment,
prepareForTestWithMyapex,
@@ -294,8 +292,8 @@
"javalib/bar.jar.prof",
})
- assertProfileGuided(t, ctx, "foo", "android_common_myapex", false)
- assertProfileGuided(t, ctx, "bar", "android_common_myapex", true)
+ assertProfileGuidedPrebuilt(t, ctx, "myapex", "foo", false)
+ assertProfileGuidedPrebuilt(t, ctx, "myapex", "bar", true)
}
func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) {
@@ -381,8 +379,6 @@
}
func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) {
- // TODO(spandandas): Fix the rules for profile guided dexpreopt of deapexed prebuilt jars
- t.Skip()
result := android.GroupFixturePreparers(
prepareForTestWithSystemserverclasspathFragment,
prepareForTestWithMyapex,
@@ -447,8 +443,8 @@
"javalib/bar.jar.prof",
})
- assertProfileGuided(t, ctx, "foo", "android_common_myapex", false)
- assertProfileGuided(t, ctx, "bar", "android_common_myapex", true)
+ assertProfileGuidedPrebuilt(t, ctx, "myapex", "foo", false)
+ assertProfileGuidedPrebuilt(t, ctx, "myapex", "bar", true)
}
func assertProfileGuided(t *testing.T, ctx *android.TestContext, moduleName string, variant string, expected bool) {
@@ -458,3 +454,11 @@
t.Fatalf("Expected profile-guided to be %v, got %v", expected, actual)
}
}
+
+func assertProfileGuidedPrebuilt(t *testing.T, ctx *android.TestContext, apexName string, moduleName string, expected bool) {
+ dexpreopt := ctx.ModuleForTests(apexName, "android_common_"+apexName).Rule("dexpreopt." + moduleName)
+ actual := strings.Contains(dexpreopt.RuleParams.Command, "--profile-file=")
+ if expected != actual {
+ t.Fatalf("Expected profile-guided to be %v, got %v", expected, actual)
+ }
+}
diff --git a/apex/vndk_test.go b/apex/vndk_test.go
index e2aee96..894aece 100644
--- a/apex/vndk_test.go
+++ b/apex/vndk_test.go
@@ -8,66 +8,6 @@
"android/soong/android"
)
-func TestVndkApexForVndkLite(t *testing.T) {
- ctx := testApex(t, `
- apex_vndk {
- name: "com.android.vndk.current",
- key: "com.android.vndk.current.key",
- updatable: false,
- }
-
- apex_key {
- name: "com.android.vndk.current.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_library {
- name: "libvndk",
- srcs: ["mylib.cpp"],
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- system_shared_libs: [],
- stl: "none",
- apex_available: [ "com.android.vndk.current" ],
- }
-
- cc_library {
- name: "libvndksp",
- srcs: ["mylib.cpp"],
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- system_shared_libs: [],
- stl: "none",
- apex_available: [ "com.android.vndk.current" ],
- }
- `+vndkLibrariesTxtFiles("current"),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.DeviceVndkVersion = proptools.StringPtr("")
- variables.KeepVndk = proptools.BoolPtr(true)
- }),
- )
- // VNDK-Lite contains only core variants of VNDK-Sp libraries
- ensureExactContents(t, ctx, "com.android.vndk.current", "android_common", []string{
- "lib/libvndksp.so",
- "lib/libc++.so",
- "lib64/libvndksp.so",
- "lib64/libc++.so",
- "etc/llndk.libraries.29.txt",
- "etc/vndkcore.libraries.29.txt",
- "etc/vndksp.libraries.29.txt",
- "etc/vndkprivate.libraries.29.txt",
- "etc/vndkproduct.libraries.29.txt",
- })
-}
-
func TestVndkApexUsesVendorVariant(t *testing.T) {
bp := `
apex_vndk {
diff --git a/bin/soongdbg b/bin/soongdbg
new file mode 100755
index 0000000..132a0f0
--- /dev/null
+++ b/bin/soongdbg
@@ -0,0 +1,313 @@
+#!/usr/bin/env python3
+
+import argparse
+import fnmatch
+import json
+import os
+import pathlib
+import types
+import sys
+
+
+class Graph:
+ def __init__(self, modules):
+ def get_or_make_node(dictionary, id, module):
+ node = dictionary.get(id)
+ if node:
+ if module and not node.module:
+ node.module = module
+ return node
+ node = Node(id, module)
+ dictionary[id] = node
+ return node
+ self.nodes = dict()
+ for module in modules.values():
+ node = get_or_make_node(self.nodes, module.id, module)
+ for d in module.deps:
+ dep = get_or_make_node(self.nodes, d.id, None)
+ node.deps.add(dep)
+ dep.rdeps.add(node)
+
+ def find_paths(self, id1, id2):
+ # Throws KeyError if one of the names isn't found
+ def recurse(node1, node2, visited):
+ result = set()
+ for dep in node1.rdeps:
+ if dep == node2:
+ result.add(node2)
+ if dep not in visited:
+ visited.add(dep)
+ found = recurse(dep, node2, visited)
+ if found:
+ result |= found
+ result.add(dep)
+ return result
+ node1 = self.nodes[id1]
+ node2 = self.nodes[id2]
+ # Take either direction
+ p = recurse(node1, node2, set())
+ if p:
+ p.add(node1)
+ return p
+ p = recurse(node2, node1, set())
+ p.add(node2)
+ return p
+
+
+class Node:
+ def __init__(self, id, module):
+ self.id = id
+ self.module = module
+ self.deps = set()
+ self.rdeps = set()
+
+
+PROVIDERS = [
+ "android/soong/java.JarJarProviderData",
+ "android/soong/java.BaseJarJarProviderData",
+]
+
+
+def format_node_label(node):
+ if not node.module:
+ return node.id
+ if node.module.debug:
+ module_debug = f"<tr><td>{node.module.debug}</td></tr>"
+ else:
+ module_debug = ""
+
+ result = (f"<<table border=\"0\" cellborder=\"0\" cellspacing=\"0\" cellpadding=\"0\">"
+ + f"<tr><td><b>{node.module.name}</b></td></tr>"
+ + module_debug
+ + f"<tr><td>{node.module.type}</td></tr>")
+ for p in node.module.providers:
+ if p.type in PROVIDERS:
+ result += "<tr><td><font color=\"#666666\">" + format_provider(p) + "</font></td></tr>"
+ result += "</table>>"
+ return result
+
+
+def format_source_pos(file, lineno):
+ result = file
+ if lineno:
+ result += f":{lineno}"
+ return result
+
+
+STRIP_TYPE_PREFIXES = [
+ "android/soong/",
+ "github.com/google/",
+]
+
+
+def format_provider(provider):
+ result = ""
+ for prefix in STRIP_TYPE_PREFIXES:
+ if provider.type.startswith(prefix):
+ result = provider.type[len(prefix):]
+ break
+ if not result:
+ result = provider.type
+ if True and provider.debug:
+ result += " (" + provider.debug + ")"
+ return result
+
+
+def load_soong_debug():
+ # Read the json
+ try:
+ with open(SOONG_DEBUG_DATA_FILENAME) as f:
+ info = json.load(f, object_hook=lambda d: types.SimpleNamespace(**d))
+ except IOError:
+ sys.stderr.write(f"error: Unable to open {SOONG_DEBUG_DATA_FILENAME}. Make sure you have"
+ + " built with GENERATE_SOONG_DEBUG.\n")
+ sys.exit(1)
+
+ # Construct IDs, which are name + variant if the
+ name_counts = dict()
+ for m in info.modules:
+ name_counts[m.name] = name_counts.get(m.name, 0) + 1
+ def get_id(m):
+ result = m.name
+ if name_counts[m.name] > 1 and m.variant:
+ result += "@@" + m.variant
+ return result
+ for m in info.modules:
+ m.id = get_id(m)
+ for dep in m.deps:
+ dep.id = get_id(dep)
+
+ return info
+
+
+def load_modules():
+ info = load_soong_debug()
+
+ # Filter out unnamed modules
+ modules = dict()
+ for m in info.modules:
+ if not m.name:
+ continue
+ modules[m.id] = m
+
+ return modules
+
+
+def load_graph():
+ modules=load_modules()
+ return Graph(modules)
+
+
+def module_selection_args(parser):
+ parser.add_argument("modules", nargs="*",
+ help="Modules to match. Can be glob-style wildcards.")
+ parser.add_argument("--provider", nargs="+",
+ help="Match the given providers.")
+ parser.add_argument("--dep", nargs="+",
+ help="Match the given providers.")
+
+
+def load_and_filter_modules(args):
+ # Which modules are printed
+ matchers = []
+ if args.modules:
+ matchers.append(lambda m: [True for pattern in args.modules
+ if fnmatch.fnmatchcase(m.name, pattern)])
+ if args.provider:
+ matchers.append(lambda m: [True for pattern in args.provider
+ if [True for p in m.providers if p.type.endswith(pattern)]])
+ if args.dep:
+ matchers.append(lambda m: [True for pattern in args.dep
+ if [True for d in m.deps if d.id == pattern]])
+
+ if not matchers:
+ sys.stderr.write("error: At least one module matcher must be supplied\n")
+ sys.exit(1)
+
+ info = load_soong_debug()
+ for m in sorted(info.modules, key=lambda m: (m.name, m.variant)):
+ if len([matcher for matcher in matchers if matcher(m)]) == len(matchers):
+ yield m
+
+
+def print_nodes(nodes):
+ print("digraph {")
+ for node in nodes:
+ print(f"\"{node.id}\"[label={format_node_label(node)}];")
+ for dep in node.deps:
+ if dep in nodes:
+ print(f"\"{node.id}\" -> \"{dep.id}\";")
+ print("}")
+
+
+def get_deps(nodes, root):
+ if root in nodes:
+ return
+ nodes.add(root)
+ for dep in root.deps:
+ get_deps(nodes, dep)
+
+
+class BetweenCommand:
+ help = "Print the module graph between two nodes."
+
+ def args(self, parser):
+ parser.add_argument("module", nargs=2,
+ help="The two modules")
+
+ def run(self, args):
+ graph = load_graph()
+ print_nodes(graph.find_paths(args.module[0], args.module[1]))
+
+
+class DepsCommand:
+ help = "Print the module graph of dependencies of one or more modules"
+
+ def args(self, parser):
+ parser.add_argument("module", nargs="+",
+ help="Module to print dependencies of")
+
+ def run(self, args):
+ graph = load_graph()
+ nodes = set()
+ err = False
+ for id in sys.argv[3:]:
+ root = graph.nodes.get(id)
+ if not root:
+ sys.stderr.write(f"error: Can't find root: {id}\n")
+ err = True
+ continue
+ get_deps(nodes, root)
+ if err:
+ sys.exit(1)
+ print_nodes(nodes)
+
+
+class IdCommand:
+ help = "Print the id (name + variant) of matching modules"
+
+ def args(self, parser):
+ module_selection_args(parser)
+
+ def run(self, args):
+ for m in load_and_filter_modules(args):
+ print(m.id)
+
+
+class QueryCommand:
+ help = "Query details about modules"
+
+ def args(self, parser):
+ module_selection_args(parser)
+
+ def run(self, args):
+ for m in load_and_filter_modules(args):
+ print(m.id)
+ print(f" type: {m.type}")
+ print(f" location: {format_source_pos(m.source_file, m.source_line)}")
+ for p in m.providers:
+ print(f" provider: {format_provider(p)}")
+ for d in m.deps:
+ print(f" dep: {d.id}")
+
+
+COMMANDS = {
+ "between": BetweenCommand(),
+ "deps": DepsCommand(),
+ "id": IdCommand(),
+ "query": QueryCommand(),
+}
+
+
+def assert_env(name):
+ val = os.getenv(name)
+ if not val:
+ sys.stderr.write(f"{name} not set. please make sure you've run lunch.")
+ return val
+
+ANDROID_BUILD_TOP = assert_env("ANDROID_BUILD_TOP")
+
+TARGET_PRODUCT = assert_env("TARGET_PRODUCT")
+OUT_DIR = os.getenv("OUT_DIR")
+if not OUT_DIR:
+ OUT_DIR = "out"
+if OUT_DIR[0] != "/":
+ OUT_DIR = pathlib.Path(ANDROID_BUILD_TOP).joinpath(OUT_DIR)
+SOONG_DEBUG_DATA_FILENAME = pathlib.Path(OUT_DIR).joinpath("soong/soong-debug-info.json")
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ subparsers = parser.add_subparsers(required=True, dest="command")
+ for name in sorted(COMMANDS.keys()):
+ command = COMMANDS[name]
+ subparser = subparsers.add_parser(name, help=command.help)
+ command.args(subparser)
+ args = parser.parse_args()
+ COMMANDS[args.command].run(args)
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
+
diff --git a/cc/androidmk.go b/cc/androidmk.go
index c39668c..20673e8 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -107,7 +107,6 @@
}
entries.SetString("LOCAL_SOONG_LINK_TYPE", c.makeLinkType)
if c.InVendorOrProduct() {
- entries.SetBool("LOCAL_USE_VNDK", true)
if c.IsVndk() && !c.static() {
entries.SetString("LOCAL_SOONG_VNDK_VERSION", c.VndkVersion())
// VNDK libraries available to vendor are not installed because
@@ -117,6 +116,11 @@
}
}
}
+ if c.InVendor() {
+ entries.SetBool("LOCAL_IN_VENDOR", true)
+ } else if c.InProduct() {
+ entries.SetBool("LOCAL_IN_PRODUCT", true)
+ }
if c.Properties.IsSdkVariant && c.Properties.SdkAndPlatformVariantVisibleToMake {
// Make the SDK variant uninstallable so that there are not two rules to install
// to the same location.
diff --git a/cc/compiler.go b/cc/compiler.go
index c57b72c..de1ae71 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -116,6 +116,10 @@
// if set to false, use -std=c++* instead of -std=gnu++*
Gnu_extensions *bool
+ // cc Build rules targeting BPF must set this to true. The correct fix is to
+ // ban targeting bpf in cc rules instead use bpf_rules. (b/323415017)
+ Bpf_target *bool
+
Yacc *YaccProperties
Lex *LexProperties
@@ -483,6 +487,11 @@
}
}
+ // bpf targets don't need the default target triple. b/308826679
+ if proptools.Bool(compiler.Properties.Bpf_target) {
+ target = "--target=bpf"
+ }
+
flags.Global.CFlags = append(flags.Global.CFlags, target)
flags.Global.AsFlags = append(flags.Global.AsFlags, target)
flags.Global.LdFlags = append(flags.Global.LdFlags, target)
@@ -498,8 +507,12 @@
flags.Global.AsFlags = append(flags.Global.AsFlags, tc.Asflags())
flags.Global.CppFlags = append([]string{"${config.CommonGlobalCppflags}"}, flags.Global.CppFlags...)
+
+ // bpf targets don't need the target specific toolchain cflags. b/308826679
+ if !proptools.Bool(compiler.Properties.Bpf_target) {
+ flags.Global.CommonFlags = append(flags.Global.CommonFlags, tc.Cflags())
+ }
flags.Global.CommonFlags = append(flags.Global.CommonFlags,
- tc.Cflags(),
"${config.CommonGlobalCflags}",
fmt.Sprintf("${config.%sGlobalCflags}", hod))
@@ -521,7 +534,11 @@
flags.Global.YasmFlags = append(flags.Global.YasmFlags, tc.YasmFlags())
- flags.Global.CommonFlags = append(flags.Global.CommonFlags, tc.ToolchainCflags())
+ // bpf targets don't need the target specific toolchain cflags. b/308826679
+ if !proptools.Bool(compiler.Properties.Bpf_target) {
+ flags.Global.CommonFlags = append(flags.Global.CommonFlags, tc.ToolchainCflags())
+ }
+
cStd := parseCStd(compiler.Properties.C_std)
cppStd := parseCppStd(compiler.Properties.Cpp_std)
diff --git a/cc/config/bionic.go b/cc/config/bionic.go
index a1e3851..ed724f5 100644
--- a/cc/config/bionic.go
+++ b/cc/config/bionic.go
@@ -24,6 +24,7 @@
bionicCrtBeginStaticBinary, bionicCrtEndStaticBinary = []string{"crtbegin_static"}, []string{"crtend_android"}
bionicCrtBeginSharedBinary, bionicCrtEndSharedBinary = []string{"crtbegin_dynamic"}, []string{"crtend_android"}
bionicCrtBeginSharedLibrary, bionicCrtEndSharedLibrary = []string{"crtbegin_so"}, []string{"crtend_so"}
+ bionicCrtPadSegmentSharedLibrary = []string{"crt_pad_segment"}
)
func (toolchainBionic) Bionic() bool { return true }
@@ -36,9 +37,10 @@
func (toolchainBionic) AvailableLibraries() []string { return nil }
-func (toolchainBionic) CrtBeginStaticBinary() []string { return bionicCrtBeginStaticBinary }
-func (toolchainBionic) CrtBeginSharedBinary() []string { return bionicCrtBeginSharedBinary }
-func (toolchainBionic) CrtBeginSharedLibrary() []string { return bionicCrtBeginSharedLibrary }
-func (toolchainBionic) CrtEndStaticBinary() []string { return bionicCrtEndStaticBinary }
-func (toolchainBionic) CrtEndSharedBinary() []string { return bionicCrtEndSharedBinary }
-func (toolchainBionic) CrtEndSharedLibrary() []string { return bionicCrtEndSharedLibrary }
+func (toolchainBionic) CrtBeginStaticBinary() []string { return bionicCrtBeginStaticBinary }
+func (toolchainBionic) CrtBeginSharedBinary() []string { return bionicCrtBeginSharedBinary }
+func (toolchainBionic) CrtBeginSharedLibrary() []string { return bionicCrtBeginSharedLibrary }
+func (toolchainBionic) CrtEndStaticBinary() []string { return bionicCrtEndStaticBinary }
+func (toolchainBionic) CrtEndSharedBinary() []string { return bionicCrtEndSharedBinary }
+func (toolchainBionic) CrtEndSharedLibrary() []string { return bionicCrtEndSharedLibrary }
+func (toolchainBionic) CrtPadSegmentSharedLibrary() []string { return bionicCrtPadSegmentSharedLibrary }
diff --git a/cc/config/darwin_host.go b/cc/config/darwin_host.go
index b789590..47c61b0 100644
--- a/cc/config/darwin_host.go
+++ b/cc/config/darwin_host.go
@@ -29,11 +29,6 @@
"-fPIC",
"-funwind-tables",
- // Workaround differences in inttypes.h between host and target.
- //See bug 12708004.
- "-D__STDC_FORMAT_MACROS",
- "-D__STDC_CONSTANT_MACROS",
-
"-isysroot ${macSdkRoot}",
"-mmacosx-version-min=${macMinVersion}",
"-DMACOSX_DEPLOYMENT_TARGET=${macMinVersion}",
diff --git a/cc/config/global.go b/cc/config/global.go
index 5fed7f1..613641f 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -253,6 +253,14 @@
// http://b/161386391 for -Wno-pointer-to-int-cast
"-Wno-pointer-to-int-cast",
"-Werror=fortify-source",
+ // http://b/315246135 temporarily disabled
+ "-Wno-unused-variable",
+ // http://b/315250603 temporarily disabled
+ "-Wno-error=format",
+ // Disabled because it produces many false positives. http://b/323050926
+ "-Wno-missing-field-initializers",
+ // http://b/323050889
+ "-Wno-packed-non-pod",
"-Werror=address-of-temporary",
"-Werror=incompatible-function-pointer-types",
@@ -294,6 +302,8 @@
// until then because it causes warnings in the _callers_, not the
// project itself.
"-Wno-deprecated-dynamic-exception-spec",
+ // http://b/324323434
+ "-Wno-ambiguous-reversed-operator",
}
noOverride64GlobalCflags = []string{}
@@ -351,11 +361,16 @@
// enabling since it's a cosmetic issue.
"-Wno-bitwise-instead-of-logical",
- "-Wno-unused-but-set-variable",
+ "-Wno-unused",
+ "-Wno-unused-parameter",
"-Wno-unused-but-set-parameter",
"-Wno-unqualified-std-cast-call",
"-Wno-array-parameter",
"-Wno-gnu-offsetof-extensions",
+ // TODO: Enable this warning http://b/315245071
+ "-Wno-fortify-source",
+ "-Wno-tautological-negation-compare",
+ "-Wno-tautological-undefined-compare",
}
llvmNextExtraCommonGlobalCflags = []string{
@@ -375,8 +390,8 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r498229b"
- ClangDefaultShortVersion = "17"
+ ClangDefaultVersion = "clang-r510928"
+ ClangDefaultShortVersion = "18"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index 62f75d1..71e98fe 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -100,6 +100,7 @@
CrtEndStaticBinary() []string
CrtEndSharedBinary() []string
CrtEndSharedLibrary() []string
+ CrtPadSegmentSharedLibrary() []string
// DefaultSharedLibraries returns the list of shared libraries that will be added to all
// targets unless they explicitly specify system_shared_libs.
@@ -155,12 +156,13 @@
type toolchainNoCrt struct{}
-func (toolchainNoCrt) CrtBeginStaticBinary() []string { return nil }
-func (toolchainNoCrt) CrtBeginSharedBinary() []string { return nil }
-func (toolchainNoCrt) CrtBeginSharedLibrary() []string { return nil }
-func (toolchainNoCrt) CrtEndStaticBinary() []string { return nil }
-func (toolchainNoCrt) CrtEndSharedBinary() []string { return nil }
-func (toolchainNoCrt) CrtEndSharedLibrary() []string { return nil }
+func (toolchainNoCrt) CrtBeginStaticBinary() []string { return nil }
+func (toolchainNoCrt) CrtBeginSharedBinary() []string { return nil }
+func (toolchainNoCrt) CrtBeginSharedLibrary() []string { return nil }
+func (toolchainNoCrt) CrtEndStaticBinary() []string { return nil }
+func (toolchainNoCrt) CrtEndSharedBinary() []string { return nil }
+func (toolchainNoCrt) CrtEndSharedLibrary() []string { return nil }
+func (toolchainNoCrt) CrtPadSegmentSharedLibrary() []string { return nil }
func (toolchainBase) DefaultSharedLibraries() []string {
return nil
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index f95da0b..f497bf9 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -328,12 +328,13 @@
func (toolchainMusl) Musl() bool { return true }
-func (toolchainMusl) CrtBeginStaticBinary() []string { return muslCrtBeginStaticBinary }
-func (toolchainMusl) CrtBeginSharedBinary() []string { return muslCrtBeginSharedBinary }
-func (toolchainMusl) CrtBeginSharedLibrary() []string { return muslCrtBeginSharedLibrary }
-func (toolchainMusl) CrtEndStaticBinary() []string { return muslCrtEndStaticBinary }
-func (toolchainMusl) CrtEndSharedBinary() []string { return muslCrtEndSharedBinary }
-func (toolchainMusl) CrtEndSharedLibrary() []string { return muslCrtEndSharedLibrary }
+func (toolchainMusl) CrtBeginStaticBinary() []string { return muslCrtBeginStaticBinary }
+func (toolchainMusl) CrtBeginSharedBinary() []string { return muslCrtBeginSharedBinary }
+func (toolchainMusl) CrtBeginSharedLibrary() []string { return muslCrtBeginSharedLibrary }
+func (toolchainMusl) CrtEndStaticBinary() []string { return muslCrtEndStaticBinary }
+func (toolchainMusl) CrtEndSharedBinary() []string { return muslCrtEndSharedBinary }
+func (toolchainMusl) CrtEndSharedLibrary() []string { return muslCrtEndSharedLibrary }
+func (toolchainMusl) CrtPadSegmentSharedLibrary() []string { return nil }
func (toolchainMusl) DefaultSharedLibraries() []string { return MuslDefaultSharedLibraries }
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index 561c500..1e61b01 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -27,9 +27,8 @@
"-DWIN32_LEAN_AND_MEAN",
"-Wno-unused-parameter",
- // Workaround differences in inttypes.h between host and target.
- //See bug 12708004.
- "-D__STDC_FORMAT_MACROS",
+ // Workaround differences in <stdint.h> between host and target.
+ // Context: http://b/12708004
"-D__STDC_CONSTANT_MACROS",
// Use C99-compliant printf functions (%zd).
diff --git a/cc/library.go b/cc/library.go
index ff30d40..4684d32 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -974,6 +974,10 @@
if library.baseLinker.Properties.crt() {
deps.CrtBegin = append(deps.CrtBegin, ctx.toolchain().CrtBeginSharedLibrary()...)
deps.CrtEnd = append(deps.CrtEnd, ctx.toolchain().CrtEndSharedLibrary()...)
+
+ }
+ if library.baseLinker.Properties.crtPadSegment() {
+ deps.CrtEnd = append(deps.CrtEnd, ctx.toolchain().CrtPadSegmentSharedLibrary()...)
}
deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.SharedProperties.Shared.Whole_static_libs...)
deps.StaticLibs = append(deps.StaticLibs, library.SharedProperties.Shared.Static_libs...)
@@ -1350,10 +1354,12 @@
fileName+".lsdump")
}
-func getRefAbiDumpDir(isNdk bool) string {
+func getRefAbiDumpDir(isNdk, isLlndk bool) string {
var dirName string
if isNdk {
dirName = "ndk"
+ } else if isLlndk {
+ dirName = "vndk"
} else {
dirName = "platform"
}
@@ -1474,9 +1480,11 @@
headerAbiChecker.Exclude_symbol_tags,
currVersion)
- addLsdumpPath(classifySourceAbiDump(ctx) + ":" + library.sAbiOutputFile.String())
+ for _, tag := range classifySourceAbiDump(ctx) {
+ addLsdumpPath(tag + ":" + library.sAbiOutputFile.String())
+ }
- dumpDir := getRefAbiDumpDir(isNdk)
+ dumpDir := getRefAbiDumpDir(isNdk, isLlndk)
binderBitness := ctx.DeviceConfig().BinderBitness()
// Check against the previous version.
prevVersionInt := prevRefAbiDumpVersion(ctx, dumpDir)
diff --git a/cc/linker.go b/cc/linker.go
index 85c128e..2c50db2 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -91,6 +91,10 @@
// compiling crt or libc.
Nocrt *bool `android:"arch_variant"`
+ // don't link in crt_pad_segment. This flag is currently only used internal to
+ // soong for testing and for vndk prebuilt shared libraries.
+ No_crt_pad_segment *bool `android:"arch_variant"`
+
// deprecated and ignored because lld makes it unnecessary. See b/189475744.
Group_static_libs *bool `android:"arch_variant"`
@@ -253,6 +257,10 @@
return blp.No_libcrt == nil || !*blp.No_libcrt
}
+func (blp *BaseLinkerProperties) crtPadSegment() bool {
+ return blp.No_crt_pad_segment == nil || !*blp.No_crt_pad_segment
+}
+
func NewBaseLinker(sanitize *sanitize) *baseLinker {
return &baseLinker{sanitize: sanitize}
}
diff --git a/cc/sabi.go b/cc/sabi.go
index 9f5781f..4ca9f5c 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -97,36 +97,34 @@
return sabi != nil && sabi.Properties.ShouldCreateSourceAbiDump
}
-// Returns a string that represents the class of the ABI dump.
-// Returns an empty string if ABI check is disabled for this library.
-func classifySourceAbiDump(ctx android.BaseModuleContext) string {
+// Returns a slice of strings that represent the ABI dumps generated for this module.
+func classifySourceAbiDump(ctx android.BaseModuleContext) []string {
+ result := []string{}
m := ctx.Module().(*Module)
headerAbiChecker := m.library.getHeaderAbiCheckerProperties(ctx)
if headerAbiChecker.explicitlyDisabled() {
- return ""
+ return result
}
if !m.InProduct() && !m.InVendor() {
- // Return NDK if the library is both NDK and LLNDK.
- if m.IsNdk(ctx.Config()) {
- return "NDK"
- }
if m.isImplementationForLLNDKPublic() {
- return "LLNDK"
+ result = append(result, "LLNDK")
}
- if m.library.hasStubsVariants() {
- return "PLATFORM"
+ // Return NDK if the library is both NDK and APEX.
+ // TODO(b/309880485): Split NDK and APEX ABI.
+ if m.IsNdk(ctx.Config()) {
+ result = append(result, "NDK")
+ } else if m.library.hasStubsVariants() || headerAbiChecker.enabled() {
+ result = append(result, "PLATFORM")
}
- }
- if headerAbiChecker.enabled() {
+ } else if headerAbiChecker.enabled() {
if m.InProduct() {
- return "PRODUCT"
+ result = append(result, "PRODUCT")
}
if m.InVendor() {
- return "VENDOR"
+ result = append(result, "VENDOR")
}
- return "PLATFORM"
}
- return ""
+ return result
}
// Called from sabiDepsMutator to check whether ABI dumps should be created for this module.
@@ -195,7 +193,7 @@
return false
}
}
- return classifySourceAbiDump(ctx) != ""
+ return len(classifySourceAbiDump(ctx)) > 0
}
// Mark the direct and transitive dependencies of libraries that need ABI check, so that ABI dumps
diff --git a/cc/testing.go b/cc/testing.go
index bac41e7..9c2900c 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -77,6 +77,7 @@
no_libcrt: true,
sdk_version: "minimum",
nocrt: true,
+ no_crt_pad_segment: true,
system_shared_libs: [],
stl: "none",
check_elf_files: false,
@@ -385,6 +386,11 @@
}
cc_object {
+ name: "crt_pad_segment",
+ defaults: ["crt_defaults"],
+ }
+
+ cc_object {
name: "crtbrand",
defaults: ["crt_defaults"],
srcs: ["crtbrand.c"],
diff --git a/cc/vendor_snapshot_test.go b/cc/vendor_snapshot_test.go
index 890a533..0a55431 100644
--- a/cc/vendor_snapshot_test.go
+++ b/cc/vendor_snapshot_test.go
@@ -341,6 +341,7 @@
vendor: true,
nocrt: true,
no_libcrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
compile_multilib: "64",
@@ -458,6 +459,7 @@
vendor: true,
nocrt: true,
no_libcrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
}
@@ -467,6 +469,7 @@
vendor: true,
nocrt: true,
no_libcrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
shared_libs: ["libvndk", "libvendor_available", "libllndk"],
@@ -487,6 +490,7 @@
vendor: true,
nocrt: true,
no_libcrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
static_libs: ["libvendor"],
@@ -501,6 +505,7 @@
vendor: true,
nocrt: true,
no_libcrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
vndk: {
@@ -597,6 +602,7 @@
target_arch: "arm64",
compile_multilib: "both",
vendor: true,
+ no_crt_pad_segment: true,
shared_libs: [
"libvendor_without_snapshot",
"libvendor_available",
@@ -620,6 +626,7 @@
target_arch: "arm64",
compile_multilib: "both",
vendor: true,
+ no_crt_pad_segment: true,
overrides: ["libvendor"],
shared_libs: [
"libvendor_without_snapshot",
@@ -657,6 +664,7 @@
target_arch: "arm64",
compile_multilib: "32",
vendor: true,
+ no_crt_pad_segment: true,
arch: {
arm: {
src: "lib32.so",
@@ -683,6 +691,7 @@
target_arch: "arm64",
compile_multilib: "64",
vendor: true,
+ no_crt_pad_segment: true,
arch: {
arm64: {
src: "lib64.so",
@@ -722,6 +731,7 @@
target_arch: "arm64",
compile_multilib: "both",
vendor: true,
+ no_crt_pad_segment: true,
arch: {
arm64: {
src: "libvendor_available.so",
diff --git a/cc/vndk.go b/cc/vndk.go
index 0e0dba9..2b2ea64 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -377,22 +377,17 @@
return false
}
- // ignore prebuilt vndk modules that are newer than or equal to the platform vndk version
- platformVndkApiLevel := android.ApiLevelOrPanic(mctx, mctx.DeviceConfig().PlatformVndkVersion())
- if platformVndkApiLevel.LessThanOrEqualTo(android.ApiLevelOrPanic(mctx, p.Version())) {
- return false
+ platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
+ if platformVndkVersion != "" {
+ // ignore prebuilt vndk modules that are newer than or equal to the platform vndk version
+ platformVndkApiLevel := android.ApiLevelOrPanic(mctx, platformVndkVersion)
+ if platformVndkApiLevel.LessThanOrEqualTo(android.ApiLevelOrPanic(mctx, p.Version())) {
+ return false
+ }
}
}
if lib, ok := m.linker.(libraryInterface); ok {
- // VNDK APEX for VNDK-Lite devices will have VNDK-SP libraries from core variants
- if mctx.DeviceConfig().VndkVersion() == "" {
- // b/73296261: filter out libz.so because it is considered as LLNDK for VNDK-lite devices
- if mctx.ModuleName() == "libz" {
- return false
- }
- return m.ImageVariation().Variation == android.CoreVariation && lib.shared() && m.IsVndkSp() && !m.IsVndkExt()
- }
// VNDK APEX doesn't need stub variants
if lib.buildStubs() {
return false
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index eb1790f..43030b8 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -131,11 +131,14 @@
func (p *vndkPrebuiltLibraryDecorator) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
- platformVndkApiLevel := android.ApiLevelOrPanic(ctx, ctx.DeviceConfig().PlatformVndkVersion())
- if platformVndkApiLevel.LessThanOrEqualTo(android.ApiLevelOrPanic(ctx, p.Version())) {
- // This prebuilt VNDK module is not required for the current build
- ctx.Module().HideFromMake()
- return nil
+ platformVndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
+ if platformVndkVersion != "" {
+ platformVndkApiLevel := android.ApiLevelOrPanic(ctx, platformVndkVersion)
+ if platformVndkApiLevel.LessThanOrEqualTo(android.ApiLevelOrPanic(ctx, p.Version())) {
+ // This prebuilt VNDK module is not required for the current build
+ ctx.Module().HideFromMake()
+ return nil
+ }
}
if !p.MatchesWithDevice(ctx.DeviceConfig()) {
@@ -232,6 +235,7 @@
prebuilt.properties.Check_elf_files = BoolPtr(false)
prebuilt.baseLinker.Properties.No_libcrt = BoolPtr(true)
prebuilt.baseLinker.Properties.Nocrt = BoolPtr(true)
+ prebuilt.baseLinker.Properties.No_crt_pad_segment = BoolPtr(true)
// Prevent default system libs (libc, libm, and libdl) from being linked
if prebuilt.baseLinker.Properties.System_shared_libs == nil {
@@ -246,14 +250,6 @@
&prebuilt.properties,
)
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- // empty BOARD_VNDK_VERSION implies that the device won't support
- // system only OTA. In this case, VNDK snapshots aren't needed.
- if ctx.DeviceConfig().VndkVersion() == "" {
- ctx.Module().Disable()
- }
- })
-
return module
}
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 4727566..673f305 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -79,6 +79,7 @@
flag.BoolVar(&cmdlineArgs.MultitreeBuild, "multitree-build", false, "this is a multitree build")
flag.BoolVar(&cmdlineArgs.BuildFromSourceStub, "build-from-source-stub", false, "build Java stubs from source files instead of API text files")
flag.BoolVar(&cmdlineArgs.EnsureAllowlistIntegrity, "ensure-allowlist-integrity", false, "verify that allowlisted modules are mixed-built")
+ flag.StringVar(&cmdlineArgs.ModuleDebugFile, "soong_module_debug", "", "soong module debug info file to write")
// Flags that probably shouldn't be flags of soong_build, but we haven't found
// the time to remove them yet
flag.BoolVar(&cmdlineArgs.RunGoTests, "t", false, "build and run go tests during bootstrap")
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 6163952..fe6317c 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -98,7 +98,9 @@
// measure, as it masks real errors and affects performance.
RelaxUsesLibraryCheck bool
- EnableUffdGc bool // preopt with the assumption that userfaultfd GC will be used on device.
+ // "true" to force preopt with CMC GC (a.k.a., UFFD GC); "false" to force preopt with CC GC;
+ // "default" to determine the GC type based on the kernel version file.
+ EnableUffdGc string
}
var allPlatformSystemServerJarsKey = android.NewOnceKey("allPlatformSystemServerJars")
@@ -154,6 +156,7 @@
Zip2zip android.Path
ManifestCheck android.Path
ConstructContext android.Path
+ UffdGcFlag android.WritablePath
}
type ModuleConfig struct {
@@ -537,6 +540,7 @@
Zip2zip: ctx.Config().HostToolPath(ctx, "zip2zip"),
ManifestCheck: ctx.Config().HostToolPath(ctx, "manifest_check"),
ConstructContext: ctx.Config().HostToolPath(ctx, "construct_context"),
+ UffdGcFlag: getUffdGcFlagPath(ctx),
}
}
@@ -588,6 +592,7 @@
Zip2zip string
ManifestCheck string
ConstructContext string
+ UffdGcFlag string
}
// ParseGlobalSoongConfig parses the given data assumed to be read from the
@@ -609,6 +614,7 @@
Zip2zip: constructPath(ctx, jc.Zip2zip),
ManifestCheck: constructPath(ctx, jc.ManifestCheck),
ConstructContext: constructPath(ctx, jc.ConstructContext),
+ UffdGcFlag: constructWritablePath(ctx, jc.UffdGcFlag),
}
return config, nil
@@ -633,12 +639,15 @@
}
func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) {
- checkBootJarsConfigConsistency(ctx, GetGlobalConfig(ctx), ctx.Config())
+ global := GetGlobalConfig(ctx)
+ checkBootJarsConfigConsistency(ctx, global, ctx.Config())
- if GetGlobalConfig(ctx).DisablePreopt {
+ if global.DisablePreopt {
return
}
+ buildUffdGcFlag(ctx, global)
+
config := GetCachedGlobalSoongConfig(ctx)
if config == nil {
// No module has enabled dexpreopting, so we assume there will be no calls
@@ -654,6 +663,7 @@
Zip2zip: config.Zip2zip.String(),
ManifestCheck: config.ManifestCheck.String(),
ConstructContext: config.ConstructContext.String(),
+ UffdGcFlag: config.UffdGcFlag.String(),
}
data, err := json.Marshal(jc)
@@ -684,9 +694,32 @@
config.Zip2zip.String(),
config.ManifestCheck.String(),
config.ConstructContext.String(),
+ config.UffdGcFlag.String(),
}, " "))
}
+func buildUffdGcFlag(ctx android.BuilderContext, global *GlobalConfig) {
+ uffdGcFlag := getUffdGcFlagPath(ctx)
+
+ if global.EnableUffdGc == "true" {
+ android.WriteFileRuleVerbatim(ctx, uffdGcFlag, "--runtime-arg -Xgc:CMC")
+ } else if global.EnableUffdGc == "false" {
+ android.WriteFileRuleVerbatim(ctx, uffdGcFlag, "")
+ } else if global.EnableUffdGc == "default" {
+ // Generated by `build/make/core/Makefile`.
+ kernelVersionFile := android.PathForOutput(ctx, "dexpreopt/kernel_version_for_uffd_gc.txt")
+ // Determine the UFFD GC flag by the kernel version file.
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Command().
+ Tool(ctx.Config().HostToolPath(ctx, "construct_uffd_gc_flag")).
+ Input(kernelVersionFile).
+ Output(uffdGcFlag)
+ rule.Restat().Build("dexpreopt_uffd_gc_flag", "dexpreopt_uffd_gc_flag")
+ } else {
+ panic(fmt.Sprintf("Unknown value of PRODUCT_ENABLE_UFFD_GC: %s", global.EnableUffdGc))
+ }
+}
+
func GlobalConfigForTests(ctx android.PathContext) *GlobalConfig {
return &GlobalConfig{
DisablePreopt: false,
@@ -731,7 +764,7 @@
}
}
-func globalSoongConfigForTests() *GlobalSoongConfig {
+func globalSoongConfigForTests(ctx android.BuilderContext) *GlobalSoongConfig {
return &GlobalSoongConfig{
Profman: android.PathForTesting("profman"),
Dex2oat: android.PathForTesting("dex2oat"),
@@ -740,5 +773,19 @@
Zip2zip: android.PathForTesting("zip2zip"),
ManifestCheck: android.PathForTesting("manifest_check"),
ConstructContext: android.PathForTesting("construct_context"),
+ UffdGcFlag: android.PathForOutput(ctx, "dexpreopt_test", "uffd_gc_flag.txt"),
}
}
+
+func GetDexpreoptDirName(ctx android.PathContext) string {
+ prefix := "dexpreopt_"
+ targets := ctx.Config().Targets[android.Android]
+ if len(targets) > 0 {
+ return prefix + targets[0].Arch.ArchType.String()
+ }
+ return prefix + "unknown_target"
+}
+
+func getUffdGcFlagPath(ctx android.PathContext) android.WritablePath {
+ return android.PathForOutput(ctx, "dexpreopt/uffd_gc_flag.txt")
+}
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 94707ba..04bc61d 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -390,7 +390,8 @@
Flag("--generate-build-id").
Flag("--abort-on-hard-verifier-error").
Flag("--force-determinism").
- FlagWithArg("--no-inline-from=", "core-oj.jar")
+ FlagWithArg("--no-inline-from=", "core-oj.jar").
+ Text("$(cat").Input(globalSoong.UffdGcFlag).Text(")")
var preoptFlags []string
if len(module.PreoptFlags) > 0 {
@@ -506,10 +507,6 @@
cmd.FlagWithInput("--profile-file=", profile)
}
- if global.EnableUffdGc {
- cmd.Flag("--runtime-arg").Flag("-Xgc:CMC")
- }
-
rule.Install(odexPath, odexInstallPath)
rule.Install(vdexPath, vdexInstallPath)
}
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 230fbb4..7071f3e 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -96,7 +96,7 @@
func TestDexPreopt(t *testing.T) {
config := android.TestConfig("out", nil, "", nil)
ctx := android.BuilderContextForTesting(config)
- globalSoong := globalSoongConfigForTests()
+ globalSoong := globalSoongConfigForTests(ctx)
global := GlobalConfigForTests(ctx)
module := testSystemModuleConfig(ctx, "test")
productPackages := android.PathForTesting("product_packages.txt")
@@ -114,12 +114,15 @@
if rule.Installs().String() != wantInstalls.String() {
t.Errorf("\nwant installs:\n %v\ngot:\n %v", wantInstalls, rule.Installs())
}
+
+ android.AssertStringListContains(t, "", rule.Inputs().RelativeToTop().Strings(),
+ "out/soong/dexpreopt_test/uffd_gc_flag.txt")
}
func TestDexPreoptSystemOther(t *testing.T) {
config := android.TestConfig("out", nil, "", nil)
ctx := android.BuilderContextForTesting(config)
- globalSoong := globalSoongConfigForTests()
+ globalSoong := globalSoongConfigForTests(ctx)
global := GlobalConfigForTests(ctx)
systemModule := testSystemModuleConfig(ctx, "Stest")
systemProductModule := testSystemProductModuleConfig(ctx, "SPtest")
@@ -180,7 +183,7 @@
func TestDexPreoptApexSystemServerJars(t *testing.T) {
config := android.TestConfig("out", nil, "", nil)
ctx := android.BuilderContextForTesting(config)
- globalSoong := globalSoongConfigForTests()
+ globalSoong := globalSoongConfigForTests(ctx)
global := GlobalConfigForTests(ctx)
module := testApexModuleConfig(ctx, "service-A", "com.android.apex1")
productPackages := android.PathForTesting("product_packages.txt")
@@ -204,7 +207,7 @@
func TestDexPreoptStandaloneSystemServerJars(t *testing.T) {
config := android.TestConfig("out", nil, "", nil)
ctx := android.BuilderContextForTesting(config)
- globalSoong := globalSoongConfigForTests()
+ globalSoong := globalSoongConfigForTests(ctx)
global := GlobalConfigForTests(ctx)
module := testPlatformSystemServerModuleConfig(ctx, "service-A")
productPackages := android.PathForTesting("product_packages.txt")
@@ -228,7 +231,7 @@
func TestDexPreoptSystemExtSystemServerJars(t *testing.T) {
config := android.TestConfig("out", nil, "", nil)
ctx := android.BuilderContextForTesting(config)
- globalSoong := globalSoongConfigForTests()
+ globalSoong := globalSoongConfigForTests(ctx)
global := GlobalConfigForTests(ctx)
module := testSystemExtSystemServerModuleConfig(ctx, "service-A")
productPackages := android.PathForTesting("product_packages.txt")
@@ -252,7 +255,7 @@
func TestDexPreoptApexStandaloneSystemServerJars(t *testing.T) {
config := android.TestConfig("out", nil, "", nil)
ctx := android.BuilderContextForTesting(config)
- globalSoong := globalSoongConfigForTests()
+ globalSoong := globalSoongConfigForTests(ctx)
global := GlobalConfigForTests(ctx)
module := testApexModuleConfig(ctx, "service-A", "com.android.apex1")
productPackages := android.PathForTesting("product_packages.txt")
@@ -276,7 +279,7 @@
func TestDexPreoptProfile(t *testing.T) {
config := android.TestConfig("out", nil, "", nil)
ctx := android.BuilderContextForTesting(config)
- globalSoong := globalSoongConfigForTests()
+ globalSoong := globalSoongConfigForTests(ctx)
global := GlobalConfigForTests(ctx)
module := testSystemModuleConfig(ctx, "test")
productPackages := android.PathForTesting("product_packages.txt")
@@ -316,3 +319,55 @@
after := fmt.Sprintf("%v", parsed)
android.AssertStringEquals(t, "The result must be the same as the original after marshalling and unmarshalling it.", before, after)
}
+
+func TestUffdGcFlagForce(t *testing.T) {
+ for _, enableUffdGc := range []string{"true", "false"} {
+ t.Run(enableUffdGc, func(t *testing.T) {
+ preparers := android.GroupFixturePreparers(
+ PrepareForTestWithFakeDex2oatd,
+ PrepareForTestWithDexpreoptConfig,
+ FixtureSetEnableUffdGc(enableUffdGc),
+ )
+
+ result := preparers.RunTest(t)
+ ctx := result.TestContext
+
+ ctx.SingletonForTests("dexpreopt-soong-config").Output("out/soong/dexpreopt/uffd_gc_flag.txt")
+ })
+ }
+}
+
+func TestUffdGcFlagDefault(t *testing.T) {
+ preparers := android.GroupFixturePreparers(
+ PrepareForTestWithFakeDex2oatd,
+ PrepareForTestWithDexpreoptConfig,
+ FixtureSetEnableUffdGc("default"),
+ )
+
+ result := preparers.RunTest(t)
+ ctx := result.TestContext
+ config := ctx.Config()
+
+ rule := ctx.SingletonForTests("dexpreopt-soong-config").Rule("dexpreopt_uffd_gc_flag")
+
+ android.AssertStringDoesContain(t, "", rule.RuleParams.Command, "construct_uffd_gc_flag")
+ android.AssertStringPathsRelativeToTopEquals(t, "", config, []string{
+ "out/soong/dexpreopt/uffd_gc_flag.txt",
+ }, rule.AllOutputs())
+ android.AssertPathsRelativeToTopEquals(t, "", []string{
+ "out/soong/dexpreopt/kernel_version_for_uffd_gc.txt",
+ }, rule.Implicits)
+}
+
+func TestUffdGcFlagBogus(t *testing.T) {
+ preparers := android.GroupFixturePreparers(
+ PrepareForTestWithFakeDex2oatd,
+ PrepareForTestWithDexpreoptConfig,
+ FixtureSetEnableUffdGc("bogus"),
+ )
+
+ preparers.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ "Unknown value of PRODUCT_ENABLE_UFFD_GC: bogus")).
+ RunTest(t)
+}
diff --git a/dexpreopt/testing.go b/dexpreopt/testing.go
index 147a562..b1fbef5 100644
--- a/dexpreopt/testing.go
+++ b/dexpreopt/testing.go
@@ -88,6 +88,15 @@
FixtureModifyGlobalConfig(func(android.PathContext, *GlobalConfig) {}),
)
+var PrepareForTestWithDexpreoptConfig = android.GroupFixturePreparers(
+ android.PrepareForTestWithAndroidBuildComponents,
+ android.FixtureModifyContext(func(ctx *android.TestContext) {
+ ctx.RegisterParallelSingletonType("dexpreopt-soong-config", func() android.Singleton {
+ return &globalSoongConfigSingleton{}
+ })
+ }),
+)
+
// FixtureModifyGlobalConfig enables dexpreopt (unless modified by the mutator) and modifies the
// configuration.
func FixtureModifyGlobalConfig(configModifier func(ctx android.PathContext, dexpreoptConfig *GlobalConfig)) android.FixturePreparer {
@@ -195,3 +204,10 @@
dexpreoptConfig.DisablePreopt = disable
})
}
+
+// FixtureSetEnableUffdGc sets the EnableUffdGc property in the global config.
+func FixtureSetEnableUffdGc(value string) android.FixturePreparer {
+ return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) {
+ dexpreoptConfig.EnableUffdGc = value
+ })
+}
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 2f6476c..6612a6f 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -50,8 +50,8 @@
// Function that builds extra files under the root directory and returns the files
buildExtraFiles func(ctx android.ModuleContext, root android.OutputPath) android.OutputPaths
- // Function that filters PackagingSpecs returned by PackagingBase.GatherPackagingSpecs()
- filterPackagingSpecs func(specs map[string]android.PackagingSpec)
+ // Function that filters PackagingSpec in PackagingBase.GatherPackagingSpecs()
+ filterPackagingSpec func(spec android.PackagingSpec) bool
output android.OutputPath
installDir android.InstallPath
@@ -493,10 +493,7 @@
// Note that "apex" module installs its contents to "apex"(fake partition) as well
// for symbol lookup by imitating "activated" paths.
func (f *filesystem) gatherFilteredPackagingSpecs(ctx android.ModuleContext) map[string]android.PackagingSpec {
- specs := f.PackagingBase.GatherPackagingSpecs(ctx)
- if f.filterPackagingSpecs != nil {
- f.filterPackagingSpecs(specs)
- }
+ specs := f.PackagingBase.GatherPackagingSpecsWithFilter(ctx, f.filterPackagingSpec)
return specs
}
diff --git a/filesystem/system_image.go b/filesystem/system_image.go
index 75abf70..34f4ffb 100644
--- a/filesystem/system_image.go
+++ b/filesystem/system_image.go
@@ -37,7 +37,7 @@
module := &systemImage{}
module.AddProperties(&module.properties)
module.filesystem.buildExtraFiles = module.buildExtraFiles
- module.filesystem.filterPackagingSpecs = module.filterPackagingSpecs
+ module.filesystem.filterPackagingSpec = module.filterPackagingSpec
initFilesystemModule(&module.filesystem)
return module
}
@@ -73,10 +73,6 @@
// Filter the result of GatherPackagingSpecs to discard items targeting outside "system" partition.
// Note that "apex" module installs its contents to "apex"(fake partition) as well
// for symbol lookup by imitating "activated" paths.
-func (s *systemImage) filterPackagingSpecs(specs map[string]android.PackagingSpec) {
- for k, ps := range specs {
- if ps.Partition() != "system" {
- delete(specs, k)
- }
- }
+func (s *systemImage) filterPackagingSpec(ps android.PackagingSpec) bool {
+ return ps.Partition() == "system"
}
diff --git a/java/Android.bp b/java/Android.bp
index 2585cd2..54b36ab 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -67,6 +67,7 @@
"plugin.go",
"prebuilt_apis.go",
"proto.go",
+ "ravenwood.go",
"robolectric.go",
"rro.go",
"sdk.go",
@@ -107,6 +108,7 @@
"plugin_test.go",
"prebuilt_apis_test.go",
"proto_test.go",
+ "ravenwood_test.go",
"rro_test.go",
"sdk_library_test.go",
"sdk_test.go",
diff --git a/java/androidmk.go b/java/androidmk.go
index c86dcf4..b7df9bf 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -209,9 +209,10 @@
return []android.AndroidMkEntries{}
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
- Class: "JAVA_LIBRARIES",
- OutputFile: android.OptionalPathForPath(prebuilt.combinedClasspathFile),
- Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
+ Class: "JAVA_LIBRARIES",
+ OverrideName: prebuilt.BaseModuleName(),
+ OutputFile: android.OptionalPathForPath(prebuilt.combinedClasspathFile),
+ Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !Bool(prebuilt.properties.Installable))
@@ -548,8 +549,8 @@
if BoolDefault(jd.properties.Installable, true) {
entries.SetPath("LOCAL_DROIDDOC_DOC_ZIP", jd.docZip)
}
- if jd.stubsSrcJar != nil {
- entries.SetPath("LOCAL_DROIDDOC_STUBS_SRCJAR", jd.stubsSrcJar)
+ if jd.exportableStubsSrcJar != nil {
+ entries.SetPath("LOCAL_DROIDDOC_STUBS_SRCJAR", jd.exportableStubsSrcJar)
}
},
},
@@ -595,17 +596,17 @@
Include: "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- if dstubs.Javadoc.stubsSrcJar != nil {
- entries.SetPath("LOCAL_DROIDDOC_STUBS_SRCJAR", dstubs.Javadoc.stubsSrcJar)
+ if dstubs.Javadoc.exportableStubsSrcJar != nil {
+ entries.SetPath("LOCAL_DROIDDOC_STUBS_SRCJAR", dstubs.Javadoc.exportableStubsSrcJar)
}
if dstubs.everythingArtifacts.apiVersionsXml != nil {
- entries.SetPath("LOCAL_DROIDDOC_API_VERSIONS_XML", dstubs.everythingArtifacts.apiVersionsXml)
+ entries.SetPath("LOCAL_DROIDDOC_API_VERSIONS_XML", dstubs.exportableArtifacts.apiVersionsXml)
}
if dstubs.everythingArtifacts.annotationsZip != nil {
- entries.SetPath("LOCAL_DROIDDOC_ANNOTATIONS_ZIP", dstubs.everythingArtifacts.annotationsZip)
+ entries.SetPath("LOCAL_DROIDDOC_ANNOTATIONS_ZIP", dstubs.exportableArtifacts.annotationsZip)
}
if dstubs.everythingArtifacts.metadataZip != nil {
- entries.SetPath("LOCAL_DROIDDOC_METADATA_ZIP", dstubs.everythingArtifacts.metadataZip)
+ entries.SetPath("LOCAL_DROIDDOC_METADATA_ZIP", dstubs.exportableArtifacts.metadataZip)
}
},
},
diff --git a/java/base.go b/java/base.go
index e52cedd..4e2366f 100644
--- a/java/base.go
+++ b/java/base.go
@@ -17,6 +17,8 @@
import (
"fmt"
"path/filepath"
+ "reflect"
+ "slices"
"strconv"
"strings"
@@ -89,6 +91,9 @@
// if not blank, run jarjar using the specified rules file
Jarjar_rules *string `android:"path,arch_variant"`
+ // if not blank, used as prefix to generate repackage rule
+ Jarjar_prefix *string
+
// If not blank, set the java version passed to javac as -source and -target
Java_version *string
@@ -425,6 +430,8 @@
// inserting into the bootclasspath/classpath of another compile
headerJarFile android.Path
+ repackagedHeaderJarFile android.Path
+
// jar file containing implementation classes including static library dependencies but no
// resources
implementationJarFile android.Path
@@ -489,6 +496,9 @@
// expanded Jarjar_rules
expandJarjarRules android.Path
+ // jarjar rule for inherited jarjar rules
+ repackageJarjarRules android.Path
+
// Extra files generated by the module type to be added as java resources.
extraResources android.Paths
@@ -518,6 +528,10 @@
// Single aconfig "cache file" merged from this module and all dependencies.
mergedAconfigFiles map[string]android.Paths
+
+ // Values that will be set in the JarJarProvider data for jarjar repackaging,
+ // and merged with our dependencies' rules.
+ jarjarRenameRules map[string]string
}
func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error {
@@ -1072,6 +1086,19 @@
}
func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspathJars, extraCombinedJars android.Paths) {
+
+ // Auto-propagating jarjar rules
+ jarjarProviderData := j.collectJarJarRules(ctx)
+ if jarjarProviderData != nil {
+ android.SetProvider(ctx, JarJarProvider, *jarjarProviderData)
+ text := getJarJarRuleText(jarjarProviderData)
+ if text != "" {
+ ruleTextFile := android.PathForModuleOut(ctx, "repackaged-jarjar", "repackaging.txt")
+ android.WriteFileRule(ctx, ruleTextFile, text)
+ j.repackageJarjarRules = ruleTextFile
+ }
+ }
+
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)
deps := j.collectDeps(ctx)
@@ -1170,7 +1197,7 @@
ctx.ModuleErrorf("headers_only is enabled but Turbine is disabled.")
}
- _, j.headerJarFile =
+ _, j.headerJarFile, _ =
j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName,
extraCombinedJars)
if ctx.Failed() {
@@ -1285,7 +1312,7 @@
// with sharding enabled. See: b/77284273.
}
extraJars := append(android.CopyOf(extraCombinedJars), kotlinHeaderJars...)
- headerJarFileWithoutDepsOrJarjar, j.headerJarFile =
+ headerJarFileWithoutDepsOrJarjar, j.headerJarFile, j.repackagedHeaderJarFile =
j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, extraJars)
if ctx.Failed() {
return
@@ -1509,6 +1536,16 @@
}
}
+ // Automatic jarjar rules propagation
+ if j.repackageJarjarRules != nil {
+ repackagedJarjarFile := android.PathForModuleOut(ctx, "repackaged-jarjar", jarName).OutputPath
+ TransformJarJar(ctx, repackagedJarjarFile, outputFile, j.repackageJarjarRules)
+ outputFile = repackagedJarjarFile
+ if ctx.Failed() {
+ return
+ }
+ }
+
// Check package restrictions if necessary.
if len(j.properties.Permitted_packages) > 0 {
// Time stamp file created by the package check rule.
@@ -1678,6 +1715,7 @@
android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
HeaderJars: android.PathsIfNonNil(j.headerJarFile),
+ RepackagedHeaderJars: android.PathsIfNonNil(j.repackagedHeaderJarFile),
TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
ImplementationAndResourcesJars: android.PathsIfNonNil(j.implementationAndResourcesJar),
@@ -1813,7 +1851,7 @@
func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars android.Paths,
deps deps, flags javaBuilderFlags, jarName string,
- extraJars android.Paths) (headerJar, jarjarAndDepsHeaderJar android.Path) {
+ extraJars android.Paths) (headerJar, jarjarAndDepsHeaderJar, jarjarAndDepsRepackagedHeaderJar android.Path) {
var jars android.Paths
if len(srcFiles) > 0 || len(srcJars) > 0 {
@@ -1821,7 +1859,7 @@
turbineJar := android.PathForModuleOut(ctx, "turbine", jarName)
TransformJavaToHeaderClasses(ctx, turbineJar, srcFiles, srcJars, flags)
if ctx.Failed() {
- return nil, nil
+ return nil, nil, nil
}
jars = append(jars, turbineJar)
headerJar = turbineJar
@@ -1846,11 +1884,22 @@
TransformJarJar(ctx, jarjarFile, jarjarAndDepsHeaderJar, j.expandJarjarRules)
jarjarAndDepsHeaderJar = jarjarFile
if ctx.Failed() {
- return nil, nil
+ return nil, nil, nil
}
}
- return headerJar, jarjarAndDepsHeaderJar
+ if j.repackageJarjarRules != nil {
+ repackagedJarjarFile := android.PathForModuleOut(ctx, "repackaged-turbine-jarjar", jarName)
+ TransformJarJar(ctx, repackagedJarjarFile, jarjarAndDepsHeaderJar, j.repackageJarjarRules)
+ jarjarAndDepsRepackagedHeaderJar = repackagedJarjarFile
+ if ctx.Failed() {
+ return nil, nil, nil
+ }
+ } else {
+ jarjarAndDepsRepackagedHeaderJar = jarjarAndDepsHeaderJar
+ }
+
+ return headerJar, jarjarAndDepsHeaderJar, jarjarAndDepsRepackagedHeaderJar
}
func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
@@ -2207,6 +2256,10 @@
}
deps.classpath = append(deps.classpath, dep.HeaderJars...)
deps.dexClasspath = append(deps.dexClasspath, dep.HeaderJars...)
+ if len(dep.RepackagedHeaderJars) == 1 && !slices.Contains(dep.HeaderJars, dep.RepackagedHeaderJars[0]) {
+ deps.classpath = append(deps.classpath, dep.RepackagedHeaderJars...)
+ deps.dexClasspath = append(deps.dexClasspath, dep.RepackagedHeaderJars...)
+ }
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...)
addPlugins(&deps, dep.ExportedPlugins, dep.ExportedPluginClasses...)
deps.disableTurbine = deps.disableTurbine || dep.ExportedPluginDisableTurbine
@@ -2311,6 +2364,190 @@
return deps
}
+// Provider for jarjar renaming rules.
+//
+// Modules can set their jarjar renaming rules with addJarJarRenameRule, and those renamings will be
+// passed to all rdeps. The typical way that these renamings will NOT be inherited is when a module
+// links against stubs -- these are not passed through stubs. The classes will remain unrenamed on
+// classes until a module with jarjar_prefix is reached, and all as yet unrenamed classes will then
+// be renamed from that module.
+// TODO: Add another property to suppress the forwarding of
+type JarJarProviderData struct {
+ // Mapping of class names: original --> renamed. If the value is "", the class will be
+ // renamed by the next rdep that has the jarjar_prefix attribute (or this module if it has
+ // attribute). Rdeps of that module will inherit the renaming.
+ Rename map[string]string
+}
+
+func (this JarJarProviderData) GetDebugString() string {
+ result := ""
+ for k, v := range this.Rename {
+ if strings.Contains(k, "android.companion.virtual.flags.FakeFeatureFlagsImpl") {
+ result += k + "-->" + v + ";"
+ }
+ }
+ return result
+}
+
+var JarJarProvider = blueprint.NewProvider[JarJarProviderData]()
+
+var overridableJarJarPrefix = "com.android.internal.hidden_from_bootclasspath"
+
+func init() {
+ android.SetJarJarPrefixHandler(mergeJarJarPrefixes)
+}
+
+// BaseJarJarProviderData contains information that will propagate across dependencies regardless of
+// whether they are java modules or not.
+type BaseJarJarProviderData struct {
+ JarJarProviderData JarJarProviderData
+}
+
+func (this BaseJarJarProviderData) GetDebugString() string {
+ return this.JarJarProviderData.GetDebugString()
+}
+
+var BaseJarJarProvider = blueprint.NewProvider[BaseJarJarProviderData]()
+
+// mergeJarJarPrefixes is called immediately before module.GenerateAndroidBuildActions is called.
+// Since there won't be a JarJarProvider, we create the BaseJarJarProvider if any of our deps have
+// either JarJarProvider or BaseJarJarProvider.
+func mergeJarJarPrefixes(ctx android.ModuleContext) {
+ mod := ctx.Module()
+ // Explicitly avoid propagating into some module types.
+ switch reflect.TypeOf(mod).String() {
+ case "*java.Droidstubs":
+ return
+ }
+ jarJarData := collectDirectDepsProviders(ctx)
+ if jarJarData != nil {
+ providerData := BaseJarJarProviderData{
+ JarJarProviderData: *jarJarData,
+ }
+ android.SetProvider(ctx, BaseJarJarProvider, providerData)
+ }
+
+}
+
+// Add a jarjar renaming rule to this module, to be inherited to all dependent modules.
+func (module *Module) addJarJarRenameRule(original string, renamed string) {
+ if module.jarjarRenameRules == nil {
+ module.jarjarRenameRules = make(map[string]string)
+ }
+ module.jarjarRenameRules[original] = renamed
+}
+
+func collectDirectDepsProviders(ctx android.ModuleContext) (result *JarJarProviderData) {
+ // Gather repackage information from deps
+ // If the dep jas a JarJarProvider, it is used. Otherwise, any BaseJarJarProvider is used.
+ ctx.VisitDirectDepsIgnoreBlueprint(func(m android.Module) {
+ if ctx.OtherModuleDependencyTag(m) == proguardRaiseTag {
+ return
+ }
+ merge := func(theirs *JarJarProviderData) {
+ for orig, renamed := range theirs.Rename {
+ if result == nil {
+ result = &JarJarProviderData{
+ Rename: make(map[string]string),
+ }
+ }
+ if preexisting, exists := (*result).Rename[orig]; !exists || preexisting == "" {
+ result.Rename[orig] = renamed
+ } else if preexisting != "" && renamed != "" && preexisting != renamed {
+ if strings.HasPrefix(preexisting, overridableJarJarPrefix) {
+ result.Rename[orig] = renamed
+ } else if !strings.HasPrefix(renamed, overridableJarJarPrefix) {
+ ctx.ModuleErrorf("1. Conflicting jarjar rules inherited for class: %s (%s and %s)", orig, renamed, preexisting, ctx.ModuleName(), m.Name())
+ continue
+ }
+ }
+ }
+ }
+ if theirs, ok := android.OtherModuleProvider(ctx, m, JarJarProvider); ok {
+ merge(&theirs)
+ } else if theirs, ok := android.OtherModuleProvider(ctx, m, BaseJarJarProvider); ok {
+ // TODO: if every java.Module should have a JarJarProvider, and we find only the
+ // BaseJarJarProvider, then there is a bug. Consider seeing if m can be cast
+ // to java.Module.
+ merge(&theirs.JarJarProviderData)
+ }
+ })
+ return
+}
+
+func (this Module) GetDebugString() string {
+ return "sdk_version=" + proptools.String(this.deviceProperties.Sdk_version)
+}
+
+// Merge the jarjar rules we inherit from our dependencies, any that have been added directly to
+// us, and if it's been set, apply the jarjar_prefix property to rename them.
+func (module *Module) collectJarJarRules(ctx android.ModuleContext) *JarJarProviderData {
+ // Gather repackage information from deps
+ result := collectDirectDepsProviders(ctx)
+
+ // Update that with entries we've stored for ourself
+ for orig, renamed := range module.jarjarRenameRules {
+ if result == nil {
+ result = &JarJarProviderData{
+ Rename: make(map[string]string),
+ }
+ }
+ if renamed != "" {
+ if preexisting, exists := (*result).Rename[orig]; exists && preexisting != renamed {
+ ctx.ModuleErrorf("Conflicting jarjar rules inherited for class: %s (%s and %s)", orig, renamed, preexisting)
+ continue
+ }
+ }
+ (*result).Rename[orig] = renamed
+ }
+
+ // If there are no renamings, then jarjar_prefix does nothing, so skip the extra work.
+ if result == nil {
+ return nil
+ }
+
+ // If they've given us a jarjar_prefix property, then we will use that to rename any classes
+ // that have not yet been renamed.
+ prefix := proptools.String(module.properties.Jarjar_prefix)
+ if prefix != "" {
+ if prefix[0] == '.' {
+ ctx.PropertyErrorf("jarjar_prefix", "jarjar_prefix can not start with '.'")
+ return nil
+ }
+ if prefix[len(prefix)-1] == '.' {
+ ctx.PropertyErrorf("jarjar_prefix", "jarjar_prefix can not end with '.'")
+ return nil
+ }
+
+ var updated map[string]string
+ for orig, renamed := range (*result).Rename {
+ if renamed == "" {
+ if updated == nil {
+ updated = make(map[string]string)
+ }
+ updated[orig] = prefix + "." + orig
+ }
+ }
+ for orig, renamed := range updated {
+ (*result).Rename[orig] = renamed
+ }
+ }
+
+ return result
+}
+
+// Get the jarjar rule text for a given provider for the fully resolved rules. Classes that map
+// to "" won't be in this list because they shouldn't be renamed yet.
+func getJarJarRuleText(provider *JarJarProviderData) string {
+ result := ""
+ for orig, renamed := range provider.Rename {
+ if renamed != "" {
+ result += "rule " + orig + " " + renamed + "\n"
+ }
+ }
+ return result
+}
+
func addPlugins(deps *deps, pluginJars android.Paths, pluginClasses ...string) {
deps.processorPath = append(deps.processorPath, pluginJars...)
deps.processorClasses = append(deps.processorClasses, pluginClasses...)
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 2c13d99..7c45d30 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -1105,6 +1105,10 @@
return nil
}
+func (module *PrebuiltBootclasspathFragmentModule) UseProfileGuidedDexpreopt() bool {
+ return false
+}
+
var _ android.RequiredFilesFromPrebuiltApex = (*PrebuiltBootclasspathFragmentModule)(nil)
func prebuiltBootclasspathFragmentFactory() android.Module {
diff --git a/java/builder.go b/java/builder.go
index 085e7a1..74a05f2 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -277,7 +277,7 @@
gatherReleasedFlaggedApisRule = pctx.AndroidStaticRule("gatherReleasedFlaggedApisRule",
blueprint.RuleParams{
- Command: `${aconfig} dump-cache --format='{fully_qualified_name}={state:bool}' ` +
+ Command: `${aconfig} dump-cache --dedup --format='{fully_qualified_name}={state:bool}' ` +
`--out ${out} ` +
`${flags_path} ` +
`${filter_args} `,
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
index 2017801..0ebab4d 100644
--- a/java/classpath_fragment.go
+++ b/java/classpath_fragment.go
@@ -103,8 +103,8 @@
func gatherPossibleApexModuleNamesAndStems(ctx android.ModuleContext, contents []string, tag blueprint.DependencyTag) []string {
set := map[string]struct{}{}
for _, name := range contents {
- dep := ctx.GetDirectDepWithTag(name, tag)
- set[name] = struct{}{}
+ dep, _ := ctx.GetDirectDepWithTag(name, tag).(android.Module)
+ set[ModuleStemForDeapexing(dep)] = struct{}{}
if m, ok := dep.(ModuleWithStem); ok {
set[m.Stem()] = struct{}{}
} else {
diff --git a/java/dex.go b/java/dex.go
index cdae0a2..4474c63 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -262,7 +262,7 @@
var proguardRaiseDeps classpath
ctx.VisitDirectDepsWithTag(proguardRaiseTag, func(m android.Module) {
dep, _ := android.OtherModuleProvider(ctx, m, JavaInfoProvider)
- proguardRaiseDeps = append(proguardRaiseDeps, dep.HeaderJars...)
+ proguardRaiseDeps = append(proguardRaiseDeps, dep.RepackagedHeaderJars...)
})
r8Flags = append(r8Flags, proguardRaiseDeps.FormJavaClassPath("-libraryjars"))
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 4c0a0a1..9db9b1b 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -282,6 +282,17 @@
d.installPath = android.PathForModuleInPartitionInstall(ctx, "", strings.TrimPrefix(dexpreopt.GetSystemServerDexLocation(ctx, dc, libraryName), "/"))
// generate the rules for creating the .odex and .vdex files for this system server jar
dexJarFile := di.PrebuiltExportPath(ApexRootRelativePathToJavaLib(libraryName))
+
+ d.inputProfilePathOnHost = nil // reset: TODO(spandandas): Make dexpreopter stateless
+ if android.InList(libraryName, di.GetDexpreoptProfileGuidedExportedModuleNames()) {
+ // Set the profile path to guide optimization
+ prof := di.PrebuiltExportPath(ApexRootRelativePathToJavaLib(libraryName) + ".prof")
+ if prof == nil {
+ ctx.ModuleErrorf("Could not find a .prof file in this prebuilt apex")
+ }
+ d.inputProfilePathOnHost = prof
+ }
+
d.dexpreopt(ctx, libraryName, dexJarFile)
}
@@ -354,6 +365,7 @@
var profileClassListing android.OptionalPath
var profileBootListing android.OptionalPath
profileIsTextListing := false
+
if d.inputProfilePathOnHost != nil {
profileClassListing = android.OptionalPathForPath(d.inputProfilePathOnHost)
} else if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) && !forPrebuiltApex(ctx) {
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index ec8b4c8..f7e3cb9 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -617,7 +617,8 @@
// GenerateSingletonBuildActions generates build rules for the dexpreopt config for Make.
func (d *dexpreoptBootJars) GenerateSingletonBuildActions(ctx android.SingletonContext) {
- d.dexpreoptConfigForMake = android.PathForOutput(ctx, getDexpreoptDirName(ctx), "dexpreopt.config")
+ d.dexpreoptConfigForMake =
+ android.PathForOutput(ctx, dexpreopt.GetDexpreoptDirName(ctx), "dexpreopt.config")
writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake)
}
@@ -725,13 +726,19 @@
return nil, false
}
+// Returns the stem of an artifact inside a prebuilt apex
+func ModuleStemForDeapexing(m android.Module) string {
+ bmn, _ := m.(interface{ BaseModuleName() string })
+ return bmn.BaseModuleName()
+}
+
// Returns the java libraries exported by the apex for hiddenapi and dexpreopt
// This information can come from two mechanisms
// 1. New: Direct deps to _selected_ apexes. The apexes return a ApexExportsInfo
// 2. Legacy: An edge to java_library or java_import (java_sdk_library) module. For prebuilt apexes, this serves as a hook and is populated by deapexers of prebuilt apxes
// TODO: b/308174306 - Once all mainline modules have been flagged, drop (2)
func getDexJarForApex(ctx android.ModuleContext, pair apexJarModulePair, apexNameToApexExportsInfoMap apexNameToApexExportsInfoMap) android.Path {
- if dex, found := apexNameToApexExportsInfoMap.javaLibraryDexPathOnHost(ctx, pair.apex, android.RemoveOptionalPrebuiltPrefix(pair.jarModule.Name())); found {
+ if dex, found := apexNameToApexExportsInfoMap.javaLibraryDexPathOnHost(ctx, pair.apex, ModuleStemForDeapexing(pair.jarModule)); found {
return dex
}
// TODO: b/308174306 - Remove the legacy mechanism
@@ -1066,8 +1073,8 @@
cmd.FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch])
}
- if global.EnableUffdGc && image.target.Os == android.Android {
- cmd.Flag("--runtime-arg").Flag("-Xgc:CMC")
+ if image.target.Os == android.Android {
+ cmd.Text("$(cat").Input(globalSoong.UffdGcFlag).Text(")")
}
if global.BootFlags != "" {
@@ -1235,7 +1242,7 @@
func dumpOatRules(ctx android.ModuleContext, image *bootImageConfig) {
var allPhonies android.Paths
name := image.name
- global := dexpreopt.GetGlobalConfig(ctx)
+ globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
for _, image := range image.variants {
arch := image.target.Arch.ArchType
suffix := arch.String()
@@ -1247,6 +1254,7 @@
output := android.PathForOutput(ctx, name+"."+suffix+".oatdump.txt")
rule := android.NewRuleBuilder(pctx, ctx)
imageLocationsOnHost, _ := image.imageLocations()
+
cmd := rule.Command().
BuiltTool("oatdump").
FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
@@ -1254,8 +1262,8 @@
FlagWithArg("--image=", strings.Join(imageLocationsOnHost, ":")).Implicits(image.imagesDeps.Paths()).
FlagWithOutput("--output=", output).
FlagWithArg("--instruction-set=", arch.String())
- if global.EnableUffdGc && image.target.Os == android.Android {
- cmd.Flag("--runtime-arg").Flag("-Xgc:CMC")
+ if image.target.Os == android.Android {
+ cmd.Text("$(cat").Input(globalSoong.UffdGcFlag).Text(")")
}
rule.Build("dump-oat-"+name+"-"+suffix, "dump oat "+name+" "+arch.String())
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 254b2c1..dc0973c 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -115,7 +115,7 @@
func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig {
return ctx.Config().Once(bootImageConfigKey, func() interface{} {
targets := dexpreoptTargets(ctx)
- deviceDir := android.PathForOutput(ctx, getDexpreoptDirName(ctx))
+ deviceDir := android.PathForOutput(ctx, dexpreopt.GetDexpreoptDirName(ctx))
configs := genBootImageConfigRaw(ctx)
@@ -234,12 +234,3 @@
func dexpreoptConfigMakevars(ctx android.MakeVarsContext) {
ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules.CopyOfApexJarPairs(), ":"))
}
-
-func getDexpreoptDirName(ctx android.PathContext) string {
- prefix := "dexpreopt_"
- targets := ctx.Config().Targets[android.Android]
- if len(targets) > 0 {
- return prefix + targets[0].Arch.ArchType.String()
- }
- return prefix + "unknown_target"
-}
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 6ef2afe..51503f2 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -333,66 +333,89 @@
}
}
-func (d *Droidstubs) AnnotationsZip(stubsType StubsType) (android.Path, error) {
+func (d *Droidstubs) AnnotationsZip(stubsType StubsType) (ret android.Path, err error) {
switch stubsType {
case Everything:
- return d.everythingArtifacts.annotationsZip, nil
+ ret, err = d.everythingArtifacts.annotationsZip, nil
case Exportable:
- return d.exportableArtifacts.annotationsZip, nil
+ ret, err = d.exportableArtifacts.annotationsZip, nil
default:
- return nil, fmt.Errorf("annotations zip not supported for the stub type %s", stubsType.String())
+ ret, err = nil, fmt.Errorf("annotations zip not supported for the stub type %s", stubsType.String())
}
+ return ret, err
}
-func (d *Droidstubs) ApiFilePath(stubsType StubsType) (android.Path, error) {
+func (d *Droidstubs) ApiFilePath(stubsType StubsType) (ret android.Path, err error) {
switch stubsType {
case Everything:
- return d.apiFile, nil
+ ret, err = d.apiFile, nil
case Exportable:
- return d.exportableApiFile, nil
+ ret, err = d.exportableApiFile, nil
default:
- return nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
+ ret, err = nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
}
+ if ret == nil && err == nil {
+ err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
+ }
+ return ret, err
}
-func (d *Droidstubs) ApiVersionsXmlFilePath(stubsType StubsType) (android.Path, error) {
+func (d *Droidstubs) ApiVersionsXmlFilePath(stubsType StubsType) (ret android.Path, err error) {
switch stubsType {
case Everything:
- return d.everythingArtifacts.apiVersionsXml, nil
- default:
- return nil, fmt.Errorf("api versions xml file path not supported for the stub type %s", stubsType.String())
- }
-}
-
-func (d *Droidstubs) DocZip(stubsType StubsType) (android.Path, error) {
- switch stubsType {
- case Everything:
- return d.docZip, nil
- default:
- return nil, fmt.Errorf("docs zip not supported for the stub type %s", stubsType.String())
- }
-}
-
-func (d *Droidstubs) RemovedApiFilePath(stubsType StubsType) (android.Path, error) {
- switch stubsType {
- case Everything:
- return d.removedApiFile, nil
+ ret, err = d.everythingArtifacts.apiVersionsXml, nil
case Exportable:
- return d.exportableRemovedApiFile, nil
+ ret, err = d.exportableArtifacts.apiVersionsXml, nil
default:
- return nil, fmt.Errorf("removed api file path not supported for the stub type %s", stubsType.String())
+ ret, err = nil, fmt.Errorf("api versions xml file path not supported for the stub type %s", stubsType.String())
}
+ if ret == nil && err == nil {
+ err = fmt.Errorf("api versions xml file is null for the stub type %s", stubsType.String())
+ }
+ return ret, err
}
-func (d *Droidstubs) StubsSrcJar(stubsType StubsType) (android.Path, error) {
+func (d *Droidstubs) DocZip(stubsType StubsType) (ret android.Path, err error) {
switch stubsType {
case Everything:
- return d.stubsSrcJar, nil
- case Exportable:
- return d.exportableStubsSrcJar, nil
+ ret, err = d.docZip, nil
default:
- return nil, fmt.Errorf("stubs srcjar not supported for the stub type %s", stubsType.String())
+ ret, err = nil, fmt.Errorf("docs zip not supported for the stub type %s", stubsType.String())
}
+ if ret == nil && err == nil {
+ err = fmt.Errorf("docs zip is null for the stub type %s", stubsType.String())
+ }
+ return ret, err
+}
+
+func (d *Droidstubs) RemovedApiFilePath(stubsType StubsType) (ret android.Path, err error) {
+ switch stubsType {
+ case Everything:
+ ret, err = d.removedApiFile, nil
+ case Exportable:
+ ret, err = d.exportableRemovedApiFile, nil
+ default:
+ ret, err = nil, fmt.Errorf("removed api file path not supported for the stub type %s", stubsType.String())
+ }
+ if ret == nil && err == nil {
+ err = fmt.Errorf("removed api file is null for the stub type %s", stubsType.String())
+ }
+ return ret, err
+}
+
+func (d *Droidstubs) StubsSrcJar(stubsType StubsType) (ret android.Path, err error) {
+ switch stubsType {
+ case Everything:
+ ret, err = d.stubsSrcJar, nil
+ case Exportable:
+ ret, err = d.exportableStubsSrcJar, nil
+ default:
+ ret, err = nil, fmt.Errorf("stubs srcjar not supported for the stub type %s", stubsType.String())
+ }
+ if ret == nil && err == nil {
+ err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
+ }
+ return ret, err
}
func (d *Droidstubs) CurrentApiTimestamp() android.Path {
@@ -537,11 +560,17 @@
var apiVersions android.Path
if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
- apiVersions = d.everythingArtifacts.apiVersionsXml
+ apiVersions = apiVersionsXml
} else {
ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
if s, ok := m.(*Droidstubs); ok {
- apiVersions = s.everythingArtifacts.apiVersionsXml
+ if stubsType == Everything {
+ apiVersions = s.everythingArtifacts.apiVersionsXml
+ } else if stubsType == Exportable {
+ apiVersions = s.exportableArtifacts.apiVersionsXml
+ } else {
+ ctx.ModuleErrorf("%s stubs type does not generate api-versions.xml file", stubsType.String())
+ }
} else {
ctx.PropertyErrorf("api_levels_module",
"module %q is not a droidstubs module", ctx.OtherModuleName(m))
@@ -715,8 +744,14 @@
filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
case Exportable:
- filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
-
+ // When the build flag RELEASE_EXPORT_RUNTIME_APIS is set to true, apis marked with
+ // the flagged apis that have read_write permissions are exposed on top of the enabled
+ // and read_only apis. This is to support local override of flag values at runtime.
+ if ctx.Config().ReleaseExportRuntimeApis() {
+ filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
+ } else {
+ filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
+ }
}
ctx.Build(pctx, android.BuildParams{
@@ -976,8 +1011,11 @@
stubConfig: params,
}
- d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
- optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
+ if params.generateStubs {
+ d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
+ optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
+ }
+
if params.writeSdkValues {
d.exportableArtifacts.metadataZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-metadata.zip")
d.exportableArtifacts.metadataDir = android.PathForModuleOut(ctx, params.stubsType.String(), "metadata")
@@ -1288,6 +1326,24 @@
type PrebuiltStubsSourcesProperties struct {
Srcs []string `android:"path"`
+
+ // Name of the source soong module that gets shadowed by this prebuilt
+ // If unspecified, follows the naming convention that the source module of
+ // the prebuilt is Name() without "prebuilt_" prefix
+ Source_module_name *string
+
+ // Non-nil if this prebuilt stub srcs module was dynamically created by a java_sdk_library_import
+ // The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
+ // (without any prebuilt_ prefix)
+ Created_by_java_sdk_library_name *string `blueprint:"mutated"`
+}
+
+func (j *PrebuiltStubsSources) BaseModuleName() string {
+ return proptools.StringDefault(j.properties.Source_module_name, j.ModuleBase.Name())
+}
+
+func (j *PrebuiltStubsSources) CreatedByJavaSdkLibraryName() *string {
+ return j.properties.Created_by_java_sdk_library_name
}
type PrebuiltStubsSources struct {
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index 52cd1c5..caa8345 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -412,3 +412,48 @@
android.AssertStringDoesContain(t, "foo generates exportable stubs jar",
strings.Join(m.AllOutputs(), ""), "exportable/foo-stubs.srcjar")
}
+
+func TestReleaseExportRuntimeApis(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ "RELEASE_EXPORT_RUNTIME_APIS": "true",
+ }
+ }),
+ android.FixtureMergeMockFs(map[string][]byte{
+ "a/A.java": nil,
+ "a/current.txt": nil,
+ "a/removed.txt": nil,
+ }),
+ ).RunTestWithBp(t, `
+ aconfig_declarations {
+ name: "bar",
+ package: "com.example.package",
+ srcs: [
+ "bar.aconfig",
+ ],
+ }
+ droidstubs {
+ name: "foo",
+ srcs: ["a/A.java"],
+ api_surface: "public",
+ check_api: {
+ current: {
+ api_file: "a/current.txt",
+ removed_api_file: "a/removed.txt",
+ }
+ },
+ aconfig_declarations: [
+ "bar",
+ ],
+ }
+ `)
+
+ m := result.ModuleForTests("foo", "android_common")
+
+ rule := m.Output("released-flagged-apis-exportable.txt")
+ exposeWritableApisFilter := "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
+ android.AssertStringEquals(t, "Filter argument expected to contain READ_WRITE permissions", exposeWritableApisFilter, rule.Args["filter_args"])
+}
diff --git a/java/generated_java_library.go b/java/generated_java_library.go
index 40f780c..e8316cc 100644
--- a/java/generated_java_library.go
+++ b/java/generated_java_library.go
@@ -107,3 +107,8 @@
module.Library.properties.Generated_srcjars = append(module.Library.properties.Generated_srcjars, srcJarPath)
module.Library.GenerateAndroidBuildActions(ctx)
}
+
+// Add a rule to the jarjar renaming rules. See RepackageProviderData.
+func (module *GeneratedJavaLibraryModule) AddJarJarRenameRule(original string, renamed string) {
+ module.addJarJarRenameRule(original, renamed)
+}
diff --git a/java/java.go b/java/java.go
index d536ca1..d7d271c 100644
--- a/java/java.go
+++ b/java/java.go
@@ -248,6 +248,8 @@
// against this module. If empty, ImplementationJars should be used instead.
HeaderJars android.Paths
+ RepackagedHeaderJars android.Paths
+
// set of header jars for all transitive libs deps
TransitiveLibsHeaderJars *android.DepSet[android.Path]
@@ -1837,6 +1839,7 @@
func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
apiContributions := al.properties.Api_contributions
addValidations := !ctx.Config().IsEnvTrue("DISABLE_STUB_VALIDATION") &&
+ !ctx.Config().IsEnvTrue("WITHOUT_CHECK_API") &&
proptools.BoolDefault(al.properties.Enable_validation, true)
for _, apiContributionName := range apiContributions {
ctx.AddDependency(ctx.Module(), javaApiContributionTag, apiContributionName)
@@ -2089,6 +2092,16 @@
// that depend on this module, as well as to aidl for this module.
Export_include_dirs []string
}
+
+ // Name of the source soong module that gets shadowed by this prebuilt
+ // If unspecified, follows the naming convention that the source module of
+ // the prebuilt is Name() without "prebuilt_" prefix
+ Source_module_name *string
+
+ // Non-nil if this java_import module was dynamically created by a java_sdk_library_import
+ // The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
+ // (without any prebuilt_ prefix)
+ Created_by_java_sdk_library_name *string `blueprint:"mutated"`
}
type Import struct {
@@ -2162,12 +2175,20 @@
return j.properties.Jars
}
+func (j *Import) BaseModuleName() string {
+ return proptools.StringDefault(j.properties.Source_module_name, j.ModuleBase.Name())
+}
+
func (j *Import) Name() string {
return j.prebuilt.Name(j.ModuleBase.Name())
}
func (j *Import) Stem() string {
- return proptools.StringDefault(j.properties.Stem, j.ModuleBase.Name())
+ return proptools.StringDefault(j.properties.Stem, j.BaseModuleName())
+}
+
+func (j *Import) CreatedByJavaSdkLibraryName() *string {
+ return j.properties.Created_by_java_sdk_library_name
}
func (a *Import) JacocoReportClassesFile() android.Path {
@@ -2453,6 +2474,10 @@
return requiredFilesFromPrebuiltApexForImport(name, &j.dexpreopter)
}
+func (j *Import) UseProfileGuidedDexpreopt() bool {
+ return proptools.Bool(j.importDexpreoptProperties.Dex_preopt.Profile_guided)
+}
+
// Add compile time check for interface implementation
var _ android.IDEInfo = (*Import)(nil)
var _ android.IDECustomizedModuleName = (*Import)(nil)
@@ -2817,7 +2842,20 @@
type JavaApiContributionImport struct {
JavaApiContribution
- prebuilt android.Prebuilt
+ prebuilt android.Prebuilt
+ prebuiltProperties javaApiContributionImportProperties
+}
+
+type javaApiContributionImportProperties struct {
+ // Name of the source soong module that gets shadowed by this prebuilt
+ // If unspecified, follows the naming convention that the source module of
+ // the prebuilt is Name() without "prebuilt_" prefix
+ Source_module_name *string
+
+ // Non-nil if this java_import module was dynamically created by a java_sdk_library_import
+ // The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
+ // (without any prebuilt_ prefix)
+ Created_by_java_sdk_library_name *string `blueprint:"mutated"`
}
func ApiContributionImportFactory() android.Module {
@@ -2825,7 +2863,7 @@
android.InitAndroidModule(module)
android.InitDefaultableModule(module)
android.InitPrebuiltModule(module, &[]string{""})
- module.AddProperties(&module.properties)
+ module.AddProperties(&module.properties, &module.prebuiltProperties)
module.AddProperties(&module.sdkLibraryComponentProperties)
return module
}
@@ -2838,6 +2876,14 @@
return module.prebuilt.Name(module.ModuleBase.Name())
}
+func (j *JavaApiContributionImport) BaseModuleName() string {
+ return proptools.StringDefault(j.prebuiltProperties.Source_module_name, j.ModuleBase.Name())
+}
+
+func (j *JavaApiContributionImport) CreatedByJavaSdkLibraryName() *string {
+ return j.prebuiltProperties.Created_by_java_sdk_library_name
+}
+
func (ap *JavaApiContributionImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
ap.JavaApiContribution.GenerateAndroidBuildActions(ctx)
}
diff --git a/java/java_test.go b/java/java_test.go
index 0891ab6..42301d8 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -24,6 +24,7 @@
"strings"
"testing"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/aconfig"
@@ -2521,3 +2522,105 @@
apiScopePublic.stubsLibraryModuleName("foo"), "android_common",
apiScopePublic.apiLibraryModuleName("foo")))
}
+
+func TestMultiplePrebuilts(t *testing.T) {
+ bp := `
+ // an rdep
+ java_library {
+ name: "foo",
+ libs: ["bar"],
+ }
+
+ // multiple variations of dep
+ // source
+ java_library {
+ name: "bar",
+ srcs: ["bar.java"],
+ }
+ // prebuilt "v1"
+ java_import {
+ name: "bar",
+ jars: ["bar.jar"],
+ }
+ // prebuilt "v2"
+ java_import {
+ name: "bar.v2",
+ source_module_name: "bar",
+ jars: ["bar.v1.jar"],
+ }
+
+ // selectors
+ apex_contributions {
+ name: "myapex_contributions",
+ contents: ["%v"],
+ }
+ `
+ hasDep := func(ctx *android.TestResult, m android.Module, wantDep android.Module) bool {
+ t.Helper()
+ var found bool
+ ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
+ if dep == wantDep {
+ found = true
+ }
+ })
+ return found
+ }
+
+ hasFileWithStem := func(m android.TestingModule, stem string) bool {
+ t.Helper()
+ for _, o := range m.AllOutputs() {
+ _, file := filepath.Split(o)
+ if file == stem+".jar" {
+ return true
+ }
+ }
+ return false
+ }
+
+ testCases := []struct {
+ desc string
+ selectedDependencyName string
+ expectedDependencyName string
+ }{
+ {
+ desc: "Source library is selected using apex_contributions",
+ selectedDependencyName: "bar",
+ expectedDependencyName: "bar",
+ },
+ {
+ desc: "Prebuilt library v1 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_bar",
+ expectedDependencyName: "prebuilt_bar",
+ },
+ {
+ desc: "Prebuilt library v2 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_bar.v2",
+ expectedDependencyName: "prebuilt_bar.v2",
+ },
+ }
+
+ for _, tc := range testCases {
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
+ }
+ }),
+ ).RunTestWithBp(t, fmt.Sprintf(bp, tc.selectedDependencyName))
+
+ // check that rdep gets the correct variation of dep
+ foo := ctx.ModuleForTests("foo", "android_common")
+ expectedDependency := ctx.ModuleForTests(tc.expectedDependencyName, "android_common")
+ android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", foo.Module().Name(), tc.expectedDependencyName), true, hasDep(ctx, foo.Module(), expectedDependency.Module()))
+
+ // check that output file of dep is always bar.jar
+ // The filename should be agnostic to source/prebuilt/prebuilt_version
+ android.AssertBoolEquals(t, fmt.Sprintf("could not find bar.jar in outputs of %s. All Outputs %v\n", tc.expectedDependencyName, expectedDependency.AllOutputs()), true, hasFileWithStem(expectedDependency, "bar"))
+
+ // check LOCAL_MODULE of the selected module name
+ // the prebuilt should have the same LOCAL_MODULE when exported to make
+ entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, expectedDependency.Module())[0]
+ android.AssertStringEquals(t, "unexpected LOCAL_MODULE", "bar", entries.EntryMap["LOCAL_MODULE"][0])
+ }
+}
diff --git a/java/lint.go b/java/lint.go
index c3d723b..31e7f35 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -370,6 +370,12 @@
return
}
+ for _, flag := range l.properties.Lint.Flags {
+ if strings.Contains(flag, "--disable") || strings.Contains(flag, "--enable") || strings.Contains(flag, "--check") {
+ ctx.PropertyErrorf("lint.flags", "Don't use --disable, --enable, or --check in the flags field, instead use the dedicated disabled_checks, warning_checks, error_checks, or fatal_checks fields")
+ }
+ }
+
if l.minSdkVersion.CompareTo(l.compileSdkVersion) == -1 {
l.extraMainlineLintErrors = append(l.extraMainlineLintErrors, updatabilityChecks...)
// Skip lint warning checks for NewApi warnings for libcore where they come from source
diff --git a/java/lint_test.go b/java/lint_test.go
index b7e6aad..751b139 100644
--- a/java/lint_test.go
+++ b/java/lint_test.go
@@ -260,3 +260,22 @@
}
}
}
+
+func TestCantControlCheckSeverityWithFlags(t *testing.T) {
+ bp := `
+ java_library {
+ name: "foo",
+ srcs: [
+ "a.java",
+ ],
+ min_sdk_version: "29",
+ sdk_version: "current",
+ lint: {
+ flags: ["--disabled", "NewApi"],
+ },
+ }
+ `
+ PrepareForTestWithJavaDefaultModules.
+ ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("Don't use --disable, --enable, or --check in the flags field, instead use the dedicated disabled_checks, warning_checks, error_checks, or fatal_checks fields")).
+ RunTestWithBp(t, bp)
+}
diff --git a/java/ravenwood.go b/java/ravenwood.go
new file mode 100644
index 0000000..dcb5c8b
--- /dev/null
+++ b/java/ravenwood.go
@@ -0,0 +1,228 @@
+// Copyright 2023 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 java
+
+import (
+ "android/soong/android"
+ "android/soong/tradefed"
+
+ "github.com/google/blueprint/proptools"
+)
+
+func init() {
+ RegisterRavenwoodBuildComponents(android.InitRegistrationContext)
+}
+
+func RegisterRavenwoodBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("android_ravenwood_test", ravenwoodTestFactory)
+ ctx.RegisterModuleType("android_ravenwood_libgroup", ravenwoodLibgroupFactory)
+}
+
+var ravenwoodTag = dependencyTag{name: "ravenwood"}
+var ravenwoodJniTag = dependencyTag{name: "ravenwood-jni"}
+
+const ravenwoodUtilsName = "ravenwood-utils"
+const ravenwoodRuntimeName = "ravenwood-runtime"
+
+func getLibPath(archType android.ArchType) string {
+ if archType.Multilib == "lib64" {
+ return "lib64"
+ }
+ return "lib"
+}
+
+type ravenwoodTestProperties struct {
+ Jni_libs []string
+}
+
+type ravenwoodTest struct {
+ Library
+
+ ravenwoodTestProperties ravenwoodTestProperties
+
+ testProperties testProperties
+ testConfig android.Path
+
+ forceOSType android.OsType
+ forceArchType android.ArchType
+}
+
+func ravenwoodTestFactory() android.Module {
+ module := &ravenwoodTest{}
+
+ module.addHostAndDeviceProperties()
+ module.AddProperties(&module.testProperties, &module.ravenwoodTestProperties)
+
+ module.Module.dexpreopter.isTest = true
+ module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
+
+ module.testProperties.Test_suites = []string{
+ "general-tests",
+ "ravenwood-tests",
+ }
+ module.testProperties.Test_options.Unit_test = proptools.BoolPtr(false)
+
+ InitJavaModule(module, android.DeviceSupported)
+ android.InitDefaultableModule(module)
+
+ return module
+}
+
+func (r *ravenwoodTest) InstallInTestcases() bool { return true }
+func (r *ravenwoodTest) InstallForceOS() (*android.OsType, *android.ArchType) {
+ return &r.forceOSType, &r.forceArchType
+}
+func (r *ravenwoodTest) TestSuites() []string {
+ return r.testProperties.Test_suites
+}
+
+func (r *ravenwoodTest) DepsMutator(ctx android.BottomUpMutatorContext) {
+ r.Library.DepsMutator(ctx)
+
+ // Generically depend on the runtime so that it's installed together with us
+ ctx.AddVariationDependencies(nil, ravenwoodTag, ravenwoodRuntimeName)
+
+ // Directly depend on any utils so that we link against them
+ utils := ctx.AddVariationDependencies(nil, ravenwoodTag, ravenwoodUtilsName)[0]
+ if utils != nil {
+ for _, lib := range utils.(*ravenwoodLibgroup).ravenwoodLibgroupProperties.Libs {
+ ctx.AddVariationDependencies(nil, libTag, lib)
+ }
+ }
+
+ // Add jni libs
+ for _, lib := range r.ravenwoodTestProperties.Jni_libs {
+ ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), ravenwoodJniTag, lib)
+ }
+}
+
+func (r *ravenwoodTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ r.forceOSType = ctx.Config().BuildOS
+ r.forceArchType = ctx.Config().BuildArch
+
+ r.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
+ TestConfigProp: r.testProperties.Test_config,
+ TestConfigTemplateProp: r.testProperties.Test_config_template,
+ TestSuites: r.testProperties.Test_suites,
+ AutoGenConfig: r.testProperties.Auto_gen_config,
+ DeviceTemplate: "${RavenwoodTestConfigTemplate}",
+ HostTemplate: "${RavenwoodTestConfigTemplate}",
+ })
+
+ r.Library.GenerateAndroidBuildActions(ctx)
+
+ // Start by depending on all files installed by dependancies
+ var installDeps android.InstallPaths
+ for _, dep := range ctx.GetDirectDepsWithTag(ravenwoodTag) {
+ for _, installFile := range dep.FilesToInstall() {
+ installDeps = append(installDeps, installFile)
+ }
+ }
+
+ // Also depend on our config
+ installPath := android.PathForModuleInstall(ctx, r.BaseModuleName())
+ installConfig := ctx.InstallFile(installPath, ctx.ModuleName()+".config", r.testConfig)
+ installDeps = append(installDeps, installConfig)
+
+ // Depend on the JNI libraries.
+ soInstallPath := installPath.Join(ctx, getLibPath(r.forceArchType))
+ for _, dep := range ctx.GetDirectDepsWithTag(ravenwoodJniTag) {
+ file := android.OutputFileForModule(ctx, dep, "")
+ installJni := ctx.InstallFile(soInstallPath, file.Base(), file)
+ installDeps = append(installDeps, installJni)
+ }
+
+ // Install our JAR with all dependencies
+ ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.outputFile, installDeps...)
+}
+
+func (r *ravenwoodTest) AndroidMkEntries() []android.AndroidMkEntries {
+ entriesList := r.Library.AndroidMkEntries()
+ entries := &entriesList[0]
+ entries.ExtraEntries = append(entries.ExtraEntries,
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
+ entries.AddStrings("LOCAL_COMPATIBILITY_SUITE",
+ "general-tests", "ravenwood-tests")
+ if r.testConfig != nil {
+ entries.SetPath("LOCAL_FULL_TEST_CONFIG", r.testConfig)
+ }
+ })
+ return entriesList
+}
+
+type ravenwoodLibgroupProperties struct {
+ Libs []string
+
+ Jni_libs []string
+}
+
+type ravenwoodLibgroup struct {
+ android.ModuleBase
+
+ ravenwoodLibgroupProperties ravenwoodLibgroupProperties
+
+ forceOSType android.OsType
+ forceArchType android.ArchType
+}
+
+func ravenwoodLibgroupFactory() android.Module {
+ module := &ravenwoodLibgroup{}
+ module.AddProperties(&module.ravenwoodLibgroupProperties)
+
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ return module
+}
+
+func (r *ravenwoodLibgroup) InstallInTestcases() bool { return true }
+func (r *ravenwoodLibgroup) InstallForceOS() (*android.OsType, *android.ArchType) {
+ return &r.forceOSType, &r.forceArchType
+}
+func (r *ravenwoodLibgroup) TestSuites() []string {
+ return []string{
+ "general-tests",
+ "ravenwood-tests",
+ }
+}
+
+func (r *ravenwoodLibgroup) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // Always depends on our underlying libs
+ for _, lib := range r.ravenwoodLibgroupProperties.Libs {
+ ctx.AddVariationDependencies(nil, ravenwoodTag, lib)
+ }
+ for _, lib := range r.ravenwoodLibgroupProperties.Jni_libs {
+ ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), ravenwoodJniTag, lib)
+ }
+}
+
+func (r *ravenwoodLibgroup) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ r.forceOSType = ctx.Config().BuildOS
+ r.forceArchType = ctx.Config().BuildArch
+
+ // Install our runtime into expected location for packaging
+ installPath := android.PathForModuleInstall(ctx, r.BaseModuleName())
+ for _, lib := range r.ravenwoodLibgroupProperties.Libs {
+ libModule := ctx.GetDirectDepWithTag(lib, ravenwoodTag)
+ libJar := android.OutputFileForModule(ctx, libModule, "")
+ ctx.InstallFile(installPath, lib+".jar", libJar)
+ }
+ soInstallPath := android.PathForModuleInstall(ctx, r.BaseModuleName()).Join(ctx, getLibPath(r.forceArchType))
+ for _, dep := range ctx.GetDirectDepsWithTag(ravenwoodJniTag) {
+ file := android.OutputFileForModule(ctx, dep, "")
+ ctx.InstallFile(soInstallPath, file.Base(), file)
+ }
+
+ // Normal build should perform install steps
+ ctx.Phony(r.BaseModuleName(), android.PathForPhony(ctx, r.BaseModuleName()+"-install"))
+}
diff --git a/java/ravenwood_test.go b/java/ravenwood_test.go
new file mode 100644
index 0000000..a71391c
--- /dev/null
+++ b/java/ravenwood_test.go
@@ -0,0 +1,154 @@
+// Copyright 2022 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 java
+
+import (
+ "runtime"
+ "testing"
+
+ "android/soong/android"
+)
+
+var prepareRavenwoodRuntime = android.GroupFixturePreparers(
+ android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ RegisterRavenwoodBuildComponents(ctx)
+ }),
+ android.FixtureAddTextFile("ravenwood/Android.bp", `
+ cc_library_shared {
+ name: "ravenwood-runtime-jni",
+ host_supported: true,
+ srcs: ["jni.cpp"],
+ }
+ cc_library_shared {
+ name: "ravenwood-runtime-jni2",
+ host_supported: true,
+ srcs: ["jni.cpp"],
+ stem: "libred",
+ }
+ java_library_static {
+ name: "framework-minus-apex.ravenwood",
+ srcs: ["Framework.java"],
+ }
+ java_library_static {
+ name: "framework-services.ravenwood",
+ srcs: ["Services.java"],
+ }
+ java_library_static {
+ name: "framework-rules.ravenwood",
+ srcs: ["Rules.java"],
+ }
+ android_ravenwood_libgroup {
+ name: "ravenwood-runtime",
+ libs: [
+ "framework-minus-apex.ravenwood",
+ "framework-services.ravenwood",
+ ],
+ jni_libs: ["ravenwood-runtime-jni", "ravenwood-runtime-jni2"],
+ }
+ android_ravenwood_libgroup {
+ name: "ravenwood-utils",
+ libs: [
+ "framework-rules.ravenwood",
+ ],
+ }
+ `),
+)
+
+var installPathPrefix = "out/soong/host/linux-x86/testcases"
+
+func TestRavenwoodRuntime(t *testing.T) {
+ if runtime.GOOS != "linux" {
+ t.Skip("requires linux")
+ }
+
+ ctx := android.GroupFixturePreparers(
+ PrepareForIntegrationTestWithJava,
+ prepareRavenwoodRuntime,
+ ).RunTest(t)
+
+ // Verify that our runtime depends on underlying libs
+ CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-runtime", "android_common", "framework-minus-apex.ravenwood")
+ CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-runtime", "android_common", "framework-services.ravenwood")
+ CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-runtime", "android_common", "ravenwood-runtime-jni")
+ CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-utils", "android_common", "framework-rules.ravenwood")
+
+ // Verify that we've emitted artifacts in expected location
+ runtime := ctx.ModuleForTests("ravenwood-runtime", "android_common")
+ runtime.Output(installPathPrefix + "/ravenwood-runtime/framework-minus-apex.ravenwood.jar")
+ runtime.Output(installPathPrefix + "/ravenwood-runtime/framework-services.ravenwood.jar")
+ runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/ravenwood-runtime-jni.so")
+ runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/libred.so")
+ utils := ctx.ModuleForTests("ravenwood-utils", "android_common")
+ utils.Output(installPathPrefix + "/ravenwood-utils/framework-rules.ravenwood.jar")
+}
+
+func TestRavenwoodTest(t *testing.T) {
+ if runtime.GOOS != "linux" {
+ t.Skip("requires linux")
+ }
+
+ ctx := android.GroupFixturePreparers(
+ PrepareForIntegrationTestWithJava,
+ prepareRavenwoodRuntime,
+ ).RunTestWithBp(t, `
+ cc_library_shared {
+ name: "jni-lib",
+ host_supported: true,
+ srcs: ["jni.cpp"],
+ }
+ cc_library_shared {
+ name: "jni-lib2",
+ host_supported: true,
+ srcs: ["jni.cpp"],
+ stem: "libblue",
+ }
+ android_ravenwood_test {
+ name: "ravenwood-test",
+ srcs: ["Test.java"],
+ jni_libs: ["jni-lib", "jni-lib2"],
+ sdk_version: "test_current",
+ }
+ `)
+
+ // Verify that our test depends on underlying libs
+ CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-test", "android_common", "ravenwood-buildtime")
+ CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-test", "android_common", "ravenwood-utils")
+ CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-test", "android_common", "jni-lib")
+
+ module := ctx.ModuleForTests("ravenwood-test", "android_common")
+ classpath := module.Rule("javac").Args["classpath"]
+
+ // Verify that we're linking against test_current
+ android.AssertStringDoesContain(t, "classpath", classpath, "android_test_stubs_current.jar")
+ // Verify that we're linking against utils
+ android.AssertStringDoesContain(t, "classpath", classpath, "framework-rules.ravenwood.jar")
+ // Verify that we're *NOT* linking against runtime
+ android.AssertStringDoesNotContain(t, "classpath", classpath, "framework-minus-apex.ravenwood.jar")
+ android.AssertStringDoesNotContain(t, "classpath", classpath, "framework-services.ravenwood.jar")
+
+ // Verify that we've emitted test artifacts in expected location
+ outputJar := module.Output(installPathPrefix + "/ravenwood-test/ravenwood-test.jar")
+ module.Output(installPathPrefix + "/ravenwood-test/ravenwood-test.config")
+ module.Output(installPathPrefix + "/ravenwood-test/lib64/jni-lib.so")
+ module.Output(installPathPrefix + "/ravenwood-test/lib64/libblue.so")
+
+ // Verify that we're going to install underlying libs
+ orderOnly := outputJar.OrderOnly.Strings()
+ android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/framework-minus-apex.ravenwood.jar")
+ android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/framework-services.ravenwood.jar")
+ android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/lib64/ravenwood-runtime-jni.so")
+ android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/lib64/libred.so")
+ android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-utils/framework-rules.ravenwood.jar")
+}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 2bf6644..fbde042 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -907,7 +907,30 @@
type commonSdkLibraryAndImportModule interface {
android.Module
- BaseModuleName() string
+ // Returns the name of the root java_sdk_library that creates the child stub libraries
+ // This is the `name` as it appears in Android.bp, and not the name in Soong's build graph
+ // (with the prebuilt_ prefix)
+ //
+ // e.g. in the following java_sdk_library_import
+ // java_sdk_library_import {
+ // name: "framework-foo.v1",
+ // source_module_name: "framework-foo",
+ // }
+ // the values returned by
+ // 1. Name(): prebuilt_framework-foo.v1 # unique
+ // 2. BaseModuleName(): framework-foo # the source
+ // 3. RootLibraryName: framework-foo.v1 # the undecordated `name` from Android.bp
+ RootLibraryName() string
+}
+
+func (m *SdkLibrary) RootLibraryName() string {
+ return m.BaseModuleName()
+}
+
+func (m *SdkLibraryImport) RootLibraryName() string {
+ // m.BaseModuleName refers to the source of the import
+ // use moduleBase.Name to get the name of the module as it appears in the .bp file
+ return m.ModuleBase.Name()
}
// Common code between sdk library and sdk library import
@@ -946,7 +969,7 @@
return false
}
- namePtr := proptools.StringPtr(c.module.BaseModuleName())
+ namePtr := proptools.StringPtr(c.module.RootLibraryName())
c.sdkLibraryComponentProperties.SdkLibraryName = namePtr
// Only track this sdk library if this can be used as a shared library.
@@ -973,51 +996,51 @@
// Module name of the runtime implementation library
func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string {
- return c.module.BaseModuleName() + ".impl"
+ return c.module.RootLibraryName() + ".impl"
}
// Module name of the XML file for the lib
func (c *commonToSdkLibraryAndImport) xmlPermissionsModuleName() string {
- return c.module.BaseModuleName() + sdkXmlFileSuffix
+ return c.module.RootLibraryName() + sdkXmlFileSuffix
}
// Name of the java_library module that compiles the stubs source.
func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string {
- baseName := c.module.BaseModuleName()
+ baseName := c.module.RootLibraryName()
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()
+ baseName := c.module.RootLibraryName()
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 {
- baseName := c.module.BaseModuleName()
+ baseName := c.module.RootLibraryName()
return c.namingScheme.stubsSourceModuleName(apiScope, baseName)
}
// Name of the java_api_library module that generates the from-text stubs source
// and compiles to a jar file.
func (c *commonToSdkLibraryAndImport) apiLibraryModuleName(apiScope *apiScope) string {
- baseName := c.module.BaseModuleName()
+ baseName := c.module.RootLibraryName()
return c.namingScheme.apiLibraryModuleName(apiScope, baseName)
}
// Name of the java_library module that compiles the stubs
// generated from source Java files.
func (c *commonToSdkLibraryAndImport) sourceStubsLibraryModuleName(apiScope *apiScope) string {
- baseName := c.module.BaseModuleName()
+ baseName := c.module.RootLibraryName()
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()
+ baseName := c.module.RootLibraryName()
return c.namingScheme.exportableSourceStubsLibraryModuleName(apiScope, baseName)
}
@@ -1067,7 +1090,7 @@
if scope, ok := scopeByName[scopeName]; ok {
paths := c.findScopePaths(scope)
if paths == nil {
- return nil, fmt.Errorf("%q does not provide api scope %s", c.module.BaseModuleName(), scopeName)
+ return nil, fmt.Errorf("%q does not provide api scope %s", c.module.RootLibraryName(), scopeName)
}
switch component {
@@ -1103,7 +1126,7 @@
if c.doctagPaths != nil {
return c.doctagPaths, nil
} else {
- return nil, fmt.Errorf("no doctag_files specified on %s", c.module.BaseModuleName())
+ return nil, fmt.Errorf("no doctag_files specified on %s", c.module.RootLibraryName())
}
}
return nil, nil
@@ -1149,7 +1172,7 @@
// If a specific numeric version has been requested then use prebuilt versions of the sdk.
if !sdkVersion.ApiLevel.IsPreview() {
- return PrebuiltJars(ctx, c.module.BaseModuleName(), sdkVersion)
+ return PrebuiltJars(ctx, c.module.RootLibraryName(), sdkVersion)
}
paths := c.selectScopePaths(ctx, sdkVersion.Kind)
@@ -1176,7 +1199,7 @@
scopes = append(scopes, s.name)
}
}
- ctx.ModuleErrorf("requires api scope %s from %s but it only has %q available", apiScope.name, c.module.BaseModuleName(), scopes)
+ ctx.ModuleErrorf("requires api scope %s from %s but it only has %q available", apiScope.name, c.module.RootLibraryName(), scopes)
return nil
}
@@ -1238,7 +1261,7 @@
SdkLibraryToImplicitlyTrack *string
}{}
- namePtr := proptools.StringPtr(c.module.BaseModuleName())
+ namePtr := proptools.StringPtr(c.module.RootLibraryName())
componentProps.SdkLibraryName = namePtr
if c.sharedLibrary() {
@@ -2525,6 +2548,11 @@
// If not empty, classes are restricted to the specified packages and their sub-packages.
Permitted_packages []string
+
+ // Name of the source soong module that gets shadowed by this prebuilt
+ // If unspecified, follows the naming convention that the source module of
+ // the prebuilt is Name() without "prebuilt_" prefix
+ Source_module_name *string
}
type SdkLibraryImport struct {
@@ -2638,6 +2666,10 @@
return module.prebuilt.Name(module.ModuleBase.Name())
}
+func (module *SdkLibraryImport) BaseModuleName() string {
+ return proptools.StringDefault(module.properties.Source_module_name, module.ModuleBase.Name())
+}
+
func (module *SdkLibraryImport) createInternalModules(mctx android.DefaultableHookContext) {
// If the build is configured to use prebuilts then force this to be preferred.
@@ -2670,15 +2702,19 @@
func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
// Creates a java import for the jar with ".stubs" suffix
props := struct {
- Name *string
- Sdk_version *string
- Libs []string
- Jars []string
- Compile_dex *bool
+ Name *string
+ Source_module_name *string
+ Created_by_java_sdk_library_name *string
+ Sdk_version *string
+ Libs []string
+ Jars []string
+ Compile_dex *bool
android.UserSuppliedPrebuiltProperties
}{}
props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
+ props.Source_module_name = proptools.StringPtr(apiScope.stubsLibraryModuleName(module.BaseModuleName()))
+ props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
props.Sdk_version = scopeProperties.Sdk_version
// Prepend any of the libs from the legacy public properties to the libs for each of the
// scopes to avoid having to duplicate them in each scope.
@@ -2700,12 +2736,16 @@
func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
props := struct {
- Name *string
- Srcs []string
+ Name *string
+ Source_module_name *string
+ Created_by_java_sdk_library_name *string
+ Srcs []string
android.UserSuppliedPrebuiltProperties
}{}
props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope))
+ props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()))
+ props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
props.Srcs = scopeProperties.Stub_srcs
// The stubs source is preferred if the java_sdk_library_import is preferred.
@@ -2719,13 +2759,17 @@
api_surface := &apiScope.name
props := struct {
- Name *string
- Api_surface *string
- Api_file *string
- Visibility []string
+ Name *string
+ Source_module_name *string
+ Created_by_java_sdk_library_name *string
+ Api_surface *string
+ Api_file *string
+ Visibility []string
}{}
props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope) + ".api.contribution")
+ props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()) + ".api.contribution")
+ props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
props.Api_surface = api_surface
props.Api_file = api_file
props.Visibility = []string{"//visibility:override", "//visibility:public"}
@@ -3019,6 +3063,10 @@
return requiredFilesFromPrebuiltApexForImport(name, &module.dexpreopter)
}
+func (j *SdkLibraryImport) UseProfileGuidedDexpreopt() bool {
+ return proptools.Bool(j.importDexpreoptProperties.Dex_preopt.Profile_guided)
+}
+
// java_sdk_library_xml
type sdkLibraryXml struct {
android.ModuleBase
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 3326ec5..93ef408 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -1772,3 +1772,151 @@
"top level exportable stubs library", []string{exportableSourceStubsLibraryModuleName},
topLevelModule.Module().(*Library).properties.Static_libs)
}
+
+// For java libraries depending on java_sdk_library(_import) via libs, assert that
+// rdep gets stubs of source if source is listed in apex_contributions and prebuilt has prefer (legacy mechanism)
+func TestStubResolutionOfJavaSdkLibraryInLibs(t *testing.T) {
+ bp := `
+ apex_contributions {
+ name: "my_mainline_module_contributions",
+ api_domain: "my_mainline_module",
+ contents: ["sdklib"], // source is selected using apex_contributions, but prebuilt is selected using prefer
+ }
+ java_sdk_library {
+ name: "sdklib",
+ srcs: ["a.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ public: {
+ enabled: true,
+ },
+ }
+ java_sdk_library_import {
+ name: "sdklib",
+ public: {
+ jars: ["a.jar"],
+ stub_srcs: ["a.java"],
+ current_api: "current.txt",
+ removed_api: "removed.txt",
+ annotations: "annotations.zip",
+ },
+ prefer: true, // Set prefer explicitly on the prebuilt. We will assert that rdep gets source in a test case.
+ }
+ // rdeps
+ java_library {
+ name: "mymodule",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ libs: ["sdklib",], // this should be dynamically resolved to sdklib.stubs (source) or prebuilt_sdklib.stubs (prebuilt)
+ }
+ `
+
+ fixture := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("sdklib"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ // We can use any of the apex contribution build flags from build/soong/android/config.go#mainlineApexContributionBuildFlags here
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_mainline_module_contributions",
+ }
+ }),
+ )
+
+ result := fixture.RunTestWithBp(t, bp)
+ // Make sure that rdeps get the correct source vs prebuilt based on mainline_module_contributions
+ public := result.ModuleForTests("mymodule", "android_common")
+ rule := public.Output("javac/mymodule.jar")
+ inputs := rule.Implicits.Strings()
+ android.AssertStringListContains(t, "Could not find the expected stub on classpath", inputs, "out/soong/.intermediates/sdklib.stubs/android_common/turbine-combined/sdklib.stubs.jar")
+}
+
+// test that rdep gets resolved to the correct version of a java_sdk_library (source or a specific prebuilt)
+func TestMultipleSdkLibraryPrebuilts(t *testing.T) {
+ bp := `
+ apex_contributions {
+ name: "my_mainline_module_contributions",
+ api_domain: "my_mainline_module",
+ contents: ["%s"],
+ }
+ java_sdk_library {
+ name: "sdklib",
+ srcs: ["a.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ public: {
+ enabled: true,
+ },
+ }
+ java_sdk_library_import {
+ name: "sdklib.v1", //prebuilt
+ source_module_name: "sdklib",
+ public: {
+ jars: ["a.jar"],
+ stub_srcs: ["a.java"],
+ current_api: "current.txt",
+ removed_api: "removed.txt",
+ annotations: "annotations.zip",
+ },
+ }
+ java_sdk_library_import {
+ name: "sdklib.v2", //prebuilt
+ source_module_name: "sdklib",
+ public: {
+ jars: ["a.jar"],
+ stub_srcs: ["a.java"],
+ current_api: "current.txt",
+ removed_api: "removed.txt",
+ annotations: "annotations.zip",
+ },
+ }
+ // rdeps
+ java_library {
+ name: "mymodule",
+ srcs: ["a.java"],
+ libs: ["sdklib.stubs",],
+ }
+ `
+ testCases := []struct {
+ desc string
+ selectedDependencyName string
+ expectedStubPath string
+ }{
+ {
+ desc: "Source library is selected using apex_contributions",
+ selectedDependencyName: "sdklib",
+ expectedStubPath: "out/soong/.intermediates/sdklib.stubs/android_common/turbine-combined/sdklib.stubs.jar",
+ },
+ {
+ desc: "Prebuilt library v1 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_sdklib.v1",
+ expectedStubPath: "out/soong/.intermediates/prebuilt_sdklib.v1.stubs/android_common/combined/sdklib.stubs.jar",
+ },
+ {
+ desc: "Prebuilt library v2 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_sdklib.v2",
+ expectedStubPath: "out/soong/.intermediates/prebuilt_sdklib.v2.stubs/android_common/combined/sdklib.stubs.jar",
+ },
+ }
+
+ fixture := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("sdklib", "sdklib.v1", "sdklib.v2"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_mainline_module_contributions",
+ }
+ }),
+ )
+
+ for _, tc := range testCases {
+ result := fixture.RunTestWithBp(t, fmt.Sprintf(bp, tc.selectedDependencyName))
+
+ // Make sure that rdeps get the correct source vs prebuilt based on mainline_module_contributions
+ public := result.ModuleForTests("mymodule", "android_common")
+ rule := public.Output("javac/mymodule.jar")
+ inputs := rule.Implicits.Strings()
+ android.AssertStringListContains(t, "Could not find the expected stub on classpath", inputs, tc.expectedStubPath)
+ }
+}
diff --git a/java/system_modules.go b/java/system_modules.go
index f344648..92e31cd 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -19,6 +19,7 @@
"strings"
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
"android/soong/android"
)
@@ -210,7 +211,7 @@
// type and the one to use is selected at runtime.
func systemModulesImportFactory() android.Module {
module := &systemModulesImport{}
- module.AddProperties(&module.properties)
+ module.AddProperties(&module.properties, &module.prebuiltProperties)
android.InitPrebuiltModule(module, &module.properties.Libs)
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
@@ -219,13 +220,39 @@
type systemModulesImport struct {
SystemModules
- prebuilt android.Prebuilt
+ prebuilt android.Prebuilt
+ prebuiltProperties prebuiltSystemModulesProperties
+}
+
+type prebuiltSystemModulesProperties struct {
+ // Name of the source soong module that gets shadowed by this prebuilt
+ // If unspecified, follows the naming convention that the source module of
+ // the prebuilt is Name() without "prebuilt_" prefix
+ Source_module_name *string
}
func (system *systemModulesImport) Name() string {
return system.prebuilt.Name(system.ModuleBase.Name())
}
+// BaseModuleName returns the source module that will get shadowed by this prebuilt
+// e.g.
+//
+// java_system_modules_import {
+// name: "my_system_modules.v1",
+// source_module_name: "my_system_modules",
+// }
+//
+// java_system_modules_import {
+// name: "my_system_modules.v2",
+// source_module_name: "my_system_modules",
+// }
+//
+// `BaseModuleName` for both will return `my_system_modules`
+func (system *systemModulesImport) BaseModuleName() string {
+ return proptools.StringDefault(system.prebuiltProperties.Source_module_name, system.ModuleBase.Name())
+}
+
func (system *systemModulesImport) Prebuilt() *android.Prebuilt {
return &system.prebuilt
}
diff --git a/java/system_modules_test.go b/java/system_modules_test.go
index 2ceca5d..336dd21 100644
--- a/java/system_modules_test.go
+++ b/java/system_modules_test.go
@@ -15,6 +15,7 @@
package java
import (
+ "fmt"
"testing"
"android/soong/android"
@@ -111,3 +112,85 @@
expectedPrebuiltPaths := getModuleHeaderJarsAsRelativeToTopPaths(result, "prebuilt_system-module1", "prebuilt_system-module2")
android.AssertArrayString(t, "prebuilt system modules inputs", expectedPrebuiltPaths, prebuiltInputs.RelativeToTop().Strings())
}
+
+func TestMultipleSystemModulesPrebuilts(t *testing.T) {
+ bp := `
+ // an rdep
+ java_library {
+ name: "foo",
+ sdk_version: "none",
+ system_modules: "my_system_modules",
+ }
+
+ // multiple variations of java_system_modules
+ // source
+ java_system_modules {
+ name: "my_system_modules",
+ libs: ["bar"],
+ }
+ java_library {
+ name: "bar",
+ srcs: ["bar.java"],
+ }
+ // prebuilt "v1"
+ java_system_modules_import {
+ name: "my_system_modules.v1",
+ source_module_name: "my_system_modules",
+ libs: ["bar.v1"],
+ }
+ java_import {
+ name: "bar.v1",
+ source_module_name: "bar",
+ jars: ["bar.v1.jar"],
+ }
+ // prebuilt "v2"
+ java_system_modules_import {
+ name: "my_system_modules.v2",
+ source_module_name: "my_system_modules",
+ libs: ["bar.v2"],
+ }
+ java_import {
+ name: "bar.v2",
+ source_module_name: "bar",
+ jars: ["bar.v2.jar"],
+ }
+
+ // selectors
+ apex_contributions {
+ name: "myapex_contributions",
+ contents: ["%v"],
+ }
+ `
+ testCases := []struct {
+ desc string
+ selectedDependencyName string
+ }{
+ {
+ desc: "Source system_modules is selected using apex_contributions",
+ selectedDependencyName: "my_system_modules",
+ },
+ {
+ desc: "Prebuilt system_modules v1 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_my_system_modules.v1",
+ },
+ {
+ desc: "Prebuilt system_modules v2 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_my_system_modules.v2",
+ },
+ }
+
+ for _, tc := range testCases {
+ res := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
+ }
+ }),
+ ).RunTestWithBp(t, fmt.Sprintf(bp, tc.selectedDependencyName))
+
+ // check that rdep gets the correct variation of system_modules
+ hasDep := CheckModuleHasDependency(t, res.TestContext, "foo", "android_common", tc.selectedDependencyName)
+ android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from foo to %s\n", tc.selectedDependencyName), true, hasDep)
+ }
+}
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index 30dd55f..59c5466 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -313,6 +313,10 @@
return nil
}
+func (module *prebuiltSystemServerClasspathModule) UseProfileGuidedDexpreopt() bool {
+ return false
+}
+
var _ android.RequiredFilesFromPrebuiltApex = (*prebuiltSystemServerClasspathModule)(nil)
func prebuiltSystemServerClasspathModuleFactory() android.Module {
diff --git a/python/test.go b/python/test.go
index 7eb9136..826f353 100644
--- a/python/test.go
+++ b/python/test.go
@@ -158,35 +158,25 @@
}
runner := proptools.StringDefault(p.testProperties.Test_options.Runner, "tradefed")
- if runner == "tradefed" {
- p.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
- TestConfigProp: p.testProperties.Test_config,
- TestConfigTemplateProp: p.testProperties.Test_config_template,
- TestSuites: p.binaryProperties.Test_suites,
- OptionsForAutogenerated: configs,
- AutoGenConfig: p.binaryProperties.Auto_gen_config,
- DeviceTemplate: "${PythonBinaryHostTestConfigTemplate}",
- HostTemplate: "${PythonBinaryHostTestConfigTemplate}",
- })
- } else if runner == "mobly" {
- if p.testProperties.Test_config != nil || p.testProperties.Test_config_template != nil || p.binaryProperties.Auto_gen_config != nil {
- panic(fmt.Errorf("cannot set test_config, test_config_template or auto_gen_config for mobly test"))
+ template := "${PythonBinaryHostTestConfigTemplate}"
+ if runner == "mobly" {
+ // Add tag to enable Atest mobly runner
+ if !android.InList("mobly", p.testProperties.Test_options.Tags) {
+ p.testProperties.Test_options.Tags = append(p.testProperties.Test_options.Tags, "mobly")
}
-
- for _, testSuite := range p.binaryProperties.Test_suites {
- if testSuite == "cts" {
- configs = append(configs, tradefed.Option{Name: "test-suite-tag", Value: "cts"})
- break
- }
- }
- p.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
- OptionsForAutogenerated: configs,
- DeviceTemplate: "${PythonBinaryHostMoblyTestConfigTemplate}",
- HostTemplate: "${PythonBinaryHostMoblyTestConfigTemplate}",
- })
- } else {
+ template = "${PythonBinaryHostMoblyTestConfigTemplate}"
+ } else if runner != "tradefed" {
panic(fmt.Errorf("unknown python test runner '%s', should be 'tradefed' or 'mobly'", runner))
}
+ p.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
+ TestConfigProp: p.testProperties.Test_config,
+ TestConfigTemplateProp: p.testProperties.Test_config_template,
+ TestSuites: p.binaryProperties.Test_suites,
+ OptionsForAutogenerated: configs,
+ AutoGenConfig: p.binaryProperties.Auto_gen_config,
+ DeviceTemplate: template,
+ HostTemplate: template,
+ })
for _, dataSrcPath := range android.PathsForModuleSrc(ctx, p.testProperties.Data) {
p.data = append(p.data, android.DataPath{SrcPath: dataSrcPath})
@@ -228,6 +218,12 @@
entries.SetString("LOCAL_FULL_TEST_CONFIG", p.testConfig.String())
}
+ // ATS 2.0 is the test harness for mobly tests and the test config is for ATS 2.0.
+ // Add "v2" suffix to test config name to distinguish it from the config for TF.
+ if proptools.String(p.testProperties.Test_options.Runner) == "mobly" {
+ entries.SetString("LOCAL_TEST_CONFIG_SUFFIX", "v2")
+ }
+
entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !BoolDefault(p.binaryProperties.Auto_gen_config, true))
android.SetAconfigFileMkEntries(&p.ModuleBase, entries, p.mergedAconfigFiles)
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 17fd2d8..e0cb3ce 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -63,8 +63,10 @@
entries.AddStrings("LOCAL_SHARED_LIBRARIES", mod.transitiveAndroidMkSharedLibs.ToList()...)
entries.AddStrings("LOCAL_STATIC_LIBRARIES", mod.Properties.AndroidMkStaticLibs...)
entries.AddStrings("LOCAL_SOONG_LINK_TYPE", mod.makeLinkType)
- if mod.UseVndk() {
- entries.SetBool("LOCAL_USE_VNDK", true)
+ if mod.InVendor() {
+ entries.SetBool("LOCAL_IN_VENDOR", true)
+ } else if mod.InProduct() {
+ entries.SetBool("LOCAL_IN_PRODUCT", true)
}
android.SetAconfigFileMkEntries(mod.AndroidModuleBase(), entries, mod.mergedAconfigFiles)
},
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 77ba277..85cc220 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -29,7 +29,7 @@
defaultBindgenFlags = []string{""}
// bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
- bindgenClangVersion = "clang-r498229b"
+ bindgenClangVersion = "clang-r510928"
_ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string {
if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" {
diff --git a/rust/vendor_snapshot_test.go b/rust/vendor_snapshot_test.go
index 4f45799..7ebe66b 100644
--- a/rust/vendor_snapshot_test.go
+++ b/rust/vendor_snapshot_test.go
@@ -553,6 +553,7 @@
vendor: true,
nocrt: true,
no_libcrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
}
@@ -857,6 +858,7 @@
target_arch: "arm64",
compile_multilib: "32",
vendor: true,
+ no_crt_pad_segment: true,
arch: {
arm: {
src: "lib32.so",
@@ -870,6 +872,7 @@
target_arch: "arm64",
compile_multilib: "64",
vendor: true,
+ no_crt_pad_segment: true,
arch: {
arm64: {
src: "lib64.so",
@@ -882,6 +885,7 @@
target_arch: "arm64",
compile_multilib: "64",
vendor: true,
+ no_crt_pad_segment: true,
arch: {
arm64: {
src: "liblog.so",
@@ -913,6 +917,7 @@
target_arch: "arm64",
compile_multilib: "both",
vendor: true,
+ no_crt_pad_segment: true,
arch: {
arm64: {
src: "libvendor_available.so",
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 7baaadb..e2fd59f 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -143,6 +143,39 @@
}
python_library_host {
+ name: "uffd_gc_utils",
+ srcs: [
+ "uffd_gc_utils.py",
+ ],
+ visibility: [
+ "//build/make/tools:__subpackages__",
+ ],
+}
+
+python_test_host {
+ name: "uffd_gc_utils_test",
+ main: "uffd_gc_utils_test.py",
+ srcs: [
+ "uffd_gc_utils_test.py",
+ ],
+ libs: [
+ "uffd_gc_utils",
+ ],
+ test_suites: ["general-tests"],
+}
+
+python_binary_host {
+ name: "construct_uffd_gc_flag",
+ main: "construct_uffd_gc_flag.py",
+ srcs: [
+ "construct_uffd_gc_flag.py",
+ ],
+ libs: [
+ "uffd_gc_utils",
+ ],
+}
+
+python_library_host {
name: "ninja_rsp",
srcs: ["ninja_rsp.py"],
}
diff --git a/scripts/construct_uffd_gc_flag.py b/scripts/construct_uffd_gc_flag.py
new file mode 100644
index 0000000..f437961
--- /dev/null
+++ b/scripts/construct_uffd_gc_flag.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2024 The Android Open Source Project
+#
+# 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.
+#
+"""A tool for constructing UFFD GC flag."""
+
+import argparse
+import os
+
+from uffd_gc_utils import should_enable_uffd_gc
+
+
+def parse_args():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('kernel_version_file')
+ parser.add_argument('output')
+ return parser.parse_args()
+
+def main():
+ args = parse_args()
+ enable_uffd_gc = should_enable_uffd_gc(args.kernel_version_file)
+ flag = '--runtime-arg -Xgc:CMC' if enable_uffd_gc else ''
+ # Prevent the file's mtime from being changed if the contents don't change.
+ # This avoids unnecessary dexpreopt reruns.
+ if os.path.isfile(args.output):
+ with open(args.output, 'r') as f:
+ if f.read() == flag:
+ return
+ with open(args.output, 'w') as f:
+ f.write(flag)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/uffd_gc_utils.py b/scripts/uffd_gc_utils.py
new file mode 100644
index 0000000..2d35494
--- /dev/null
+++ b/scripts/uffd_gc_utils.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2024 The Android Open Source Project
+#
+# 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.
+#
+"""Utils to determine whether to enable UFFD GC."""
+
+import re
+import sys
+
+
+def should_enable_uffd_gc(kernel_version_file):
+ with open(kernel_version_file, 'r') as f:
+ kernel_version = f.read().strip()
+ return should_enable_uffd_gc_impl(kernel_version)
+
+def should_enable_uffd_gc_impl(kernel_version):
+ # See https://source.android.com/docs/core/architecture/kernel/gki-versioning#determine-release
+ p = r"^(?P<w>\d+)[.](?P<x>\d+)[.](?P<y>\d+)(-android(?P<z>\d+)-(?P<k>\d+).*$)?"
+ m = re.match(p, kernel_version)
+ if m is not None:
+ if m.group('z') is not None:
+ android_release = int(m.group('z'))
+ # No need to check w, x, y because all Android 12 kernels have backports.
+ return android_release >= 12
+ else:
+ # Old kernel or non-GKI kernel.
+ version = int(m.group('w'))
+ patch_level = int(m.group('x'))
+ if version < 5:
+ # Old kernel.
+ return False
+ elif (version == 5 and patch_level >= 7) or version >= 6:
+ # New non-GKI kernel. 5.7 supports MREMAP_DONTUNMAP without the need for
+ # backports.
+ return True
+ else:
+ # Non-GKI kernel between 5 and 5.6. It may have backports.
+ raise exit_with_error(kernel_version)
+ elif kernel_version == '<unknown-kernel>':
+ # The kernel information isn't available to the build system, probably
+ # because PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS is set to false. We
+ # assume that the kernel supports UFFD GC because it is the case for most of
+ # the products today and it is the future.
+ return True
+ else:
+ # Unrecognizable non-GKI kernel.
+ raise exit_with_error(kernel_version)
+
+def exit_with_error(kernel_version):
+ sys.exit(f"""
+Unable to determine UFFD GC flag for kernel version "{kernel_version}".
+You can fix this by explicitly setting PRODUCT_ENABLE_UFFD_GC to "true" or
+"false" based on the kernel version.
+1. Set PRODUCT_ENABLE_UFFD_GC to "true" if the kernel supports userfaultfd(2)
+ and MREMAP_DONTUNMAP.
+2. Set PRODUCT_ENABLE_UFFD_GC to "false" otherwise.""")
diff --git a/scripts/uffd_gc_utils_test.py b/scripts/uffd_gc_utils_test.py
new file mode 100644
index 0000000..c86ab4b
--- /dev/null
+++ b/scripts/uffd_gc_utils_test.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2024 The Android Open Source Project
+#
+# 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.
+#
+"""Unit tests for uffd_gc_utils.py."""
+
+import unittest
+
+from uffd_gc_utils import should_enable_uffd_gc_impl
+
+
+class UffdGcUtilsTest(unittest.TestCase):
+ def test_should_enable_uffd_gc_impl(self):
+ # GKI kernels in new format.
+ self.assertTrue(should_enable_uffd_gc_impl(
+ "6.1.25-android14-11-g34fde9ec08a3-ab10675345"))
+ self.assertTrue(should_enable_uffd_gc_impl(
+ "5.4.42-android12-0-something"))
+ self.assertFalse(should_enable_uffd_gc_impl(
+ "5.4.42-android11-0-something"))
+ # GKI kernels in old format.
+ self.assertFalse(should_enable_uffd_gc_impl(
+ "4.19.282-g4b749a433956-ab10893502"))
+ # Non GKI kernels.
+ self.assertTrue(should_enable_uffd_gc_impl(
+ "6.1.25-foo"))
+ self.assertTrue(should_enable_uffd_gc_impl(
+ "6.1.25"))
+ self.assertTrue(should_enable_uffd_gc_impl(
+ "5.10.19-foo"))
+ self.assertTrue(should_enable_uffd_gc_impl(
+ "5.10.19"))
+ with self.assertRaises(SystemExit):
+ should_enable_uffd_gc_impl("5.4.42-foo")
+ with self.assertRaises(SystemExit):
+ should_enable_uffd_gc_impl("5.4.42")
+ self.assertFalse(should_enable_uffd_gc_impl(
+ "4.19.282-foo"))
+ self.assertFalse(should_enable_uffd_gc_impl(
+ "4.19.282"))
+ with self.assertRaises(SystemExit):
+ should_enable_uffd_gc_impl("foo")
+ # No kernel.
+ self.assertTrue(should_enable_uffd_gc_impl(
+ "<unknown-kernel>"))
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/tradefed/config.go b/tradefed/config.go
index 326a006..b015034 100644
--- a/tradefed/config.go
+++ b/tradefed/config.go
@@ -33,6 +33,7 @@
pctx.SourcePathVariable("NativeTestConfigTemplate", "build/make/core/native_test_config_template.xml")
pctx.SourcePathVariable("PythonBinaryHostMoblyTestConfigTemplate", "build/make/core/python_binary_host_mobly_test_config_template.xml")
pctx.SourcePathVariable("PythonBinaryHostTestConfigTemplate", "build/make/core/python_binary_host_test_config_template.xml")
+ pctx.SourcePathVariable("RavenwoodTestConfigTemplate", "build/make/core/ravenwood_test_config_template.xml")
pctx.SourcePathVariable("RustDeviceTestConfigTemplate", "build/make/core/rust_device_test_config_template.xml")
pctx.SourcePathVariable("RustHostTestConfigTemplate", "build/make/core/rust_host_test_config_template.xml")
pctx.SourcePathVariable("RustDeviceBenchmarkConfigTemplate", "build/make/core/rust_device_benchmark_config_template.xml")
diff --git a/ui/build/androidmk_denylist.go b/ui/build/androidmk_denylist.go
index e004cdc..e7896ab 100644
--- a/ui/build/androidmk_denylist.go
+++ b/ui/build/androidmk_denylist.go
@@ -16,8 +16,6 @@
import (
"strings"
-
- "android/soong/android"
)
var androidmk_denylist []string = []string{
@@ -32,16 +30,17 @@
"libcore/",
"libnativehelper/",
"pdk/",
- "toolchain/",
+ // Add back toolchain/ once defensive Android.mk files are removed
+ //"toolchain/",
}
-func blockAndroidMks(androidMks []string) []string {
- return android.FilterListPred(androidMks, func(s string) bool {
+func blockAndroidMks(ctx Context, androidMks []string) {
+ for _, mkFile := range androidMks {
for _, d := range androidmk_denylist {
- if strings.HasPrefix(s, d) {
- return false
+ if strings.HasPrefix(mkFile, d) {
+ ctx.Fatalf("Found blocked Android.mk file: %s. "+
+ "Please see androidmk_denylist.go for the blocked directories and contact build system team if the file should not be blocked.", mkFile)
}
}
- return true
- })
+ }
}
diff --git a/ui/build/config.go b/ui/build/config.go
index 5085c68..e29d239 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -115,6 +115,11 @@
// Data source to write ninja weight list
ninjaWeightListSource NinjaWeightListSource
+
+ // This file is a detailed dump of all soong-defined modules for debugging purposes.
+ // There's quite a bit of overlap with module-info.json and soong module graph. We
+ // could consider merging them.
+ moduleDebugFile string
}
type NinjaWeightListSource uint
@@ -273,6 +278,10 @@
ret.sandboxConfig.SetSrcDirIsRO(srcDirIsWritable == "false")
}
+ if os.Getenv("GENERATE_SOONG_DEBUG") == "true" {
+ ret.moduleDebugFile, _ = filepath.Abs(shared.JoinPath(ret.SoongOutDir(), "soong-debug-info.json"))
+ }
+
ret.environ.Unset(
// We're already using it
"USE_SOONG_UI",
@@ -325,6 +334,9 @@
"ANDROID_DEV_SCRIPTS",
"ANDROID_EMULATOR_PREBUILTS",
"ANDROID_PRE_BUILD_PATHS",
+
+ // We read it here already, don't let others share in the fun
+ "GENERATE_SOONG_DEBUG",
)
if ret.UseGoma() || ret.ForceUseGoma() {
diff --git a/ui/build/finder.go b/ui/build/finder.go
index a114079..573df21 100644
--- a/ui/build/finder.go
+++ b/ui/build/finder.go
@@ -128,7 +128,7 @@
// Stop searching a subdirectory recursively after finding an Android.mk.
androidMks := f.FindFirstNamedAt(".", "Android.mk")
- androidMks = blockAndroidMks(androidMks)
+ blockAndroidMks(ctx, androidMks)
err := dumpListToFile(ctx, config, androidMks, filepath.Join(dumpDir, "Android.mk.list"))
if err != nil {
ctx.Fatalf("Could not export module list: %v", err)
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index 65e2c8e..2f25a8c 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -93,6 +93,7 @@
"fuser": Allowed,
"gcert": Allowed,
"gcertstatus": Allowed,
+ "gcloud": Allowed,
"getopt": Allowed,
"git": Allowed,
"hexdump": Allowed,
@@ -101,7 +102,6 @@
"javap": Allowed,
"lsof": Allowed,
"openssl": Allowed,
- "prodcertstatus": Allowed,
"pstree": Allowed,
"rsync": Allowed,
"sh": Allowed,
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 90c3bfc..a201ac5 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -204,6 +204,11 @@
commonArgs = append(commonArgs, "--build-from-source-stub")
}
+ if pb.config.moduleDebugFile != "" {
+ commonArgs = append(commonArgs, "--soong_module_debug")
+ commonArgs = append(commonArgs, pb.config.moduleDebugFile)
+ }
+
commonArgs = append(commonArgs, "-l", filepath.Join(pb.config.FileListDir(), "Android.bp.list"))
invocationEnv := make(map[string]string)
if pb.debugPort != "" {