Merge "Remove macros that the Linux host no longer needs." 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 4b8d346..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,12 +108,15 @@
},
})
- // Mark our generated code as possibly needing jarjar repackaging
- // TODO: Maybe control this with a property?
- module.AddJarJarRenameRule(declarations.Package+".Flags", "")
- module.AddJarJarRenameRule(declarations.Package+".FeatureFlags", "")
- module.AddJarJarRenameRule(declarations.Package+".FeatureFlagsImpl", "")
- module.AddJarJarRenameRule(declarations.Package+".FakeFeatureFlagsImpl", "")
+ 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 1444e7d..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
}
diff --git a/android/config.go b/android/config.go
index f2dedad..f9cb842 100644
--- a/android/config.go
+++ b/android/config.go
@@ -210,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")
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/rule_builder.go b/android/rule_builder.go
index e8dbd48..85e29bd 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -1157,11 +1157,15 @@
// OutputDir adds the output directory to the command line. This is only available when used with RuleBuilder.Sbox,
// and will be the temporary output directory managed by sbox, not the final one.
-func (c *RuleBuilderCommand) OutputDir() *RuleBuilderCommand {
+func (c *RuleBuilderCommand) OutputDir(subPathComponents ...string) *RuleBuilderCommand {
if !c.rule.sbox {
panic("OutputDir only valid with Sbox")
}
- return c.Text(sboxOutDir)
+ path := sboxOutDir
+ if len(subPathComponents) > 0 {
+ path = filepath.Join(append([]string{sboxOutDir}, subPathComponents...)...)
+ }
+ return c.Text(path)
}
// DepFile adds the specified depfile path to the paths returned by RuleBuilder.DepFiles and adds it to the command
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/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/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/cc/afdo.go b/cc/afdo.go
index 79fbae1..6cc1746 100644
--- a/cc/afdo.go
+++ b/cc/afdo.go
@@ -68,6 +68,10 @@
}
func (afdo *afdo) flags(ctx ModuleContext, flags Flags) Flags {
+ if ctx.Host() {
+ return flags
+ }
+
if afdo.Properties.Afdo {
// We use `-funique-internal-linkage-names` to associate profiles to the right internal
// functions. This option should be used before generating a profile. Because a profile
@@ -147,6 +151,10 @@
// Propagate afdo requirements down from binaries and shared libraries
func afdoDepsMutator(mctx android.TopDownMutatorContext) {
+ if mctx.Host() {
+ return
+ }
+
if m, ok := mctx.Module().(*Module); ok && m.afdo.afdoEnabled() {
path := m.afdo.Properties.FdoProfilePath
mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
@@ -181,6 +189,10 @@
// Create afdo variants for modules that need them
func afdoMutator(mctx android.BottomUpMutatorContext) {
+ if mctx.Host() {
+ return
+ }
+
if m, ok := mctx.Module().(*Module); ok && m.afdo != nil {
if !m.static() && m.afdo.Properties.Afdo {
mctx.SetDependencyVariation(encodeTarget(m.Name()))
diff --git a/cc/afdo_test.go b/cc/afdo_test.go
index b250ad1..3eab039 100644
--- a/cc/afdo_test.go
+++ b/cc/afdo_test.go
@@ -42,19 +42,25 @@
bp := `
cc_library_shared {
name: "libTest",
+ host_supported: true,
srcs: ["test.c"],
static_libs: ["libFoo"],
afdo: true,
+ lto: {
+ thin: true,
+ },
}
cc_library_static {
name: "libFoo",
+ host_supported: true,
srcs: ["foo.c"],
static_libs: ["libBar"],
}
cc_library_static {
name: "libBar",
+ host_supported: true,
srcs: ["bar.c"],
}
`
@@ -72,13 +78,20 @@
"afdo_profiles_package/Android.bp": []byte(`
fdo_profile {
name: "libTest_afdo",
- profile: "libTest.afdo",
+ arch: {
+ arm64: {
+ profile: "libTest.afdo",
+ },
+ },
}
`),
}.AddToFixture(),
).RunTestWithBp(t, bp)
- expectedCFlag := "-fprofile-sample-use=afdo_profiles_package/libTest.afdo"
+ profileSampleCFlag := "-fprofile-sample-use=afdo_profiles_package/libTest.afdo"
+ uniqueInternalLinkageNamesCFlag := "-funique-internal-linkage-names"
+ afdoLtoLdFlag := "-Wl,-plugin-opt,-import-instr-limit=40"
+ noAfdoLtoLdFlag := "-Wl,-plugin-opt,-import-instr-limit=5"
libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
libFooAfdoVariant := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
@@ -86,18 +99,32 @@
// Check cFlags of afdo-enabled module and the afdo-variant of its static deps
cFlags := libTest.Rule("cc").Args["cFlags"]
- if !strings.Contains(cFlags, expectedCFlag) {
- t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", expectedCFlag, cFlags)
+ if !strings.Contains(cFlags, profileSampleCFlag) {
+ t.Errorf("Expected 'libTest' to enable afdo profile, but did not find %q in cflags %q", profileSampleCFlag, cFlags)
+ }
+ if !strings.Contains(cFlags, uniqueInternalLinkageNamesCFlag) {
+ t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", profileSampleCFlag, cFlags)
+ }
+
+ ldFlags := libTest.Rule("ld").Args["ldFlags"]
+ if !strings.Contains(ldFlags, afdoLtoLdFlag) {
+ t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in ldflags %q", afdoLtoLdFlag, ldFlags)
}
cFlags = libFooAfdoVariant.Rule("cc").Args["cFlags"]
- if !strings.Contains(cFlags, expectedCFlag) {
- t.Errorf("Expected 'libFooAfdoVariant' to enable afdo, but did not find %q in cflags %q", expectedCFlag, cFlags)
+ if !strings.Contains(cFlags, profileSampleCFlag) {
+ t.Errorf("Expected 'libFooAfdoVariant' to enable afdo profile, but did not find %q in cflags %q", profileSampleCFlag, cFlags)
+ }
+ if !strings.Contains(cFlags, uniqueInternalLinkageNamesCFlag) {
+ t.Errorf("Expected 'libFooAfdoVariant' to enable afdo, but did not find %q in cflags %q", profileSampleCFlag, cFlags)
}
cFlags = libBarAfdoVariant.Rule("cc").Args["cFlags"]
- if !strings.Contains(cFlags, expectedCFlag) {
- t.Errorf("Expected 'libBarAfdoVariant' to enable afdo, but did not find %q in cflags %q", expectedCFlag, cFlags)
+ if !strings.Contains(cFlags, profileSampleCFlag) {
+ t.Errorf("Expected 'libBarAfdoVariant' to enable afdo profile, but did not find %q in cflags %q", profileSampleCFlag, cFlags)
+ }
+ if !strings.Contains(cFlags, uniqueInternalLinkageNamesCFlag) {
+ t.Errorf("Expected 'libBarAfdoVariant' to enable afdo, but did not find %q in cflags %q", profileSampleCFlag, cFlags)
}
// Check dependency edge from afdo-enabled module to static deps
@@ -114,12 +141,18 @@
libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
cFlags = libFoo.Rule("cc").Args["cFlags"]
- if strings.Contains(cFlags, expectedCFlag) {
- t.Errorf("Expected 'libFoo' to not enable afdo, but found %q in cflags %q", expectedCFlag, cFlags)
+ if strings.Contains(cFlags, profileSampleCFlag) {
+ t.Errorf("Expected 'libFoo' to not enable afdo profile, but found %q in cflags %q", profileSampleCFlag, cFlags)
+ }
+ if strings.Contains(cFlags, uniqueInternalLinkageNamesCFlag) {
+ t.Errorf("Expected 'libFoo' to not enable afdo, but found %q in cflags %q", profileSampleCFlag, cFlags)
}
cFlags = libBar.Rule("cc").Args["cFlags"]
- if strings.Contains(cFlags, expectedCFlag) {
- t.Errorf("Expected 'libBar' to not enable afdo, but found %q in cflags %q", expectedCFlag, cFlags)
+ if strings.Contains(cFlags, profileSampleCFlag) {
+ t.Errorf("Expected 'libBar' to not enable afdo profile, but found %q in cflags %q", profileSampleCFlag, cFlags)
+ }
+ if strings.Contains(cFlags, uniqueInternalLinkageNamesCFlag) {
+ t.Errorf("Expected 'libBar' to not enable afdo, but found %q in cflags %q", profileSampleCFlag, cFlags)
}
// Check dependency edges of static deps
@@ -130,6 +163,102 @@
if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
t.Errorf("libFoo missing dependency on non-afdo variant of libBar")
}
+
+ // Verify that the arm variant does not have FDO since the fdo_profile module only has a profile for arm64
+ libTest32 := result.ModuleForTests("libTest", "android_arm_armv7-a-neon_shared")
+ libFooAfdoVariant32 := result.ModuleForTests("libFoo", "android_arm_armv7-a-neon_static_afdo-libTest_lto-thin")
+ libBarAfdoVariant32 := result.ModuleForTests("libBar", "android_arm_armv7-a-neon_static_afdo-libTest_lto-thin")
+
+ cFlags = libTest32.Rule("cc").Args["cFlags"]
+ if strings.Contains(cFlags, profileSampleCFlag) {
+ t.Errorf("Expected arm32 'libTest' not to enable afdo, but found %q in cflags %q", profileSampleCFlag, cFlags)
+ }
+
+ // TODO(b/324141705): when the fdo_profile module doesn't provide a source file the dependencies don't get
+ // -funique-internal-linkage-names but the module does.
+ if !strings.Contains(cFlags, uniqueInternalLinkageNamesCFlag) {
+ t.Errorf("Expected arm32 'libTest' to enable -funique-internal-linkage-names but did not find %q in cflags %q",
+ uniqueInternalLinkageNamesCFlag, cFlags)
+ }
+
+ ldFlags = libTest32.Rule("ld").Args["ldFlags"]
+ if !strings.Contains(ldFlags, noAfdoLtoLdFlag) {
+ t.Errorf("Expected arm32 'libTest' to not enable afdo, but did not find %q in ldflags %q", noAfdoLtoLdFlag, ldFlags)
+ }
+ if strings.Contains(ldFlags, afdoLtoLdFlag) {
+ t.Errorf("Expected arm32 'libTest' to not enable afdo, but found %q in ldflags %q", afdoLtoLdFlag, ldFlags)
+ }
+
+ // Check dependency edge from afdo-enabled module to static deps
+ if !hasDirectDep(result, libTest32.Module(), libFooAfdoVariant32.Module()) {
+ t.Errorf("arm32 libTest missing dependency on afdo variant of libFoo")
+ }
+
+ if !hasDirectDep(result, libFooAfdoVariant32.Module(), libBarAfdoVariant32.Module()) {
+ t.Errorf("arm32 libTest missing dependency on afdo variant of libBar")
+ }
+
+ cFlags = libFooAfdoVariant32.Rule("cc").Args["cFlags"]
+ if strings.Contains(cFlags, profileSampleCFlag) {
+ t.Errorf("Expected arm32 'libFoo' to not enable afdo profile, but found %q in cflags %q", uniqueInternalLinkageNamesCFlag, cFlags)
+ }
+ if !strings.Contains(cFlags, uniqueInternalLinkageNamesCFlag) {
+ t.Errorf("Expected arm32 'libFoo' to enable afdo, but did not find %q in cflags %q", uniqueInternalLinkageNamesCFlag, cFlags)
+ }
+ cFlags = libBarAfdoVariant32.Rule("cc").Args["cFlags"]
+ if strings.Contains(cFlags, profileSampleCFlag) {
+ t.Errorf("Expected arm32 'libBar' to not enable afdo profile, but found %q in cflags %q", uniqueInternalLinkageNamesCFlag, cFlags)
+ }
+ if !strings.Contains(cFlags, uniqueInternalLinkageNamesCFlag) {
+ t.Errorf("Expected arm32 'libBar' to enable afdo, but did not find %q in cflags %q", uniqueInternalLinkageNamesCFlag, cFlags)
+ }
+
+ // Verify that the host variants don't enable afdo
+ libTestHost := result.ModuleForTests("libTest", result.Config.BuildOSTarget.String()+"_shared")
+ libFooHost := result.ModuleForTests("libFoo", result.Config.BuildOSTarget.String()+"_static_lto-thin")
+ libBarHost := result.ModuleForTests("libBar", result.Config.BuildOSTarget.String()+"_static_lto-thin")
+
+ cFlags = libTestHost.Rule("cc").Args["cFlags"]
+ if strings.Contains(cFlags, profileSampleCFlag) {
+ t.Errorf("Expected host 'libTest' to not enable afdo profile, but found %q in cflags %q", profileSampleCFlag, cFlags)
+ }
+
+ if strings.Contains(cFlags, uniqueInternalLinkageNamesCFlag) {
+ t.Errorf("Expected host 'libTest' to not enable afdo but found %q in cflags %q",
+ uniqueInternalLinkageNamesCFlag, cFlags)
+ }
+
+ ldFlags = libTestHost.Rule("ld").Args["ldFlags"]
+ if !strings.Contains(ldFlags, noAfdoLtoLdFlag) {
+ t.Errorf("Expected host 'libTest' to not enable afdo, but did not find %q in ldflags %q", noAfdoLtoLdFlag, ldFlags)
+ }
+ if strings.Contains(ldFlags, afdoLtoLdFlag) {
+ t.Errorf("Expected host 'libTest' to not enable afdo, but found %q in ldflags %q", afdoLtoLdFlag, ldFlags)
+ }
+
+ // Check dependency edge from afdo-enabled module to static deps
+ if !hasDirectDep(result, libTestHost.Module(), libFooHost.Module()) {
+ t.Errorf("host libTest missing dependency on non-afdo variant of libFoo")
+ }
+
+ if !hasDirectDep(result, libFooHost.Module(), libBarHost.Module()) {
+ t.Errorf("host libTest missing dependency on non-afdo variant of libBar")
+ }
+
+ cFlags = libFooHost.Rule("cc").Args["cFlags"]
+ if strings.Contains(cFlags, profileSampleCFlag) {
+ t.Errorf("Expected host 'libFoo' to not enable afdo profile, but found %q in cflags %q", uniqueInternalLinkageNamesCFlag, cFlags)
+ }
+ if strings.Contains(cFlags, uniqueInternalLinkageNamesCFlag) {
+ t.Errorf("Expected host 'libFoo' to not enable afdo, but found %q in cflags %q", uniqueInternalLinkageNamesCFlag, cFlags)
+ }
+ cFlags = libBarHost.Rule("cc").Args["cFlags"]
+ if strings.Contains(cFlags, profileSampleCFlag) {
+ t.Errorf("Expected host 'libBar' to not enable afdo profile, but found %q in cflags %q", uniqueInternalLinkageNamesCFlag, cFlags)
+ }
+ if strings.Contains(cFlags, uniqueInternalLinkageNamesCFlag) {
+ t.Errorf("Expected host 'libBar' to not enable afdo, but found %q in cflags %q", uniqueInternalLinkageNamesCFlag, cFlags)
+ }
}
func TestAfdoEnabledOnStaticDepNoAfdo(t *testing.T) {
@@ -174,11 +303,11 @@
libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static").Module()
if !hasDirectDep(result, libTest, libFoo.Module()) {
- t.Errorf("libTest missing dependency on afdo variant of libFoo")
+ t.Errorf("libTest missing dependency on non-afdo variant of libFoo")
}
if !hasDirectDep(result, libFoo.Module(), libBar) {
- t.Errorf("libFoo missing dependency on afdo variant of libBar")
+ t.Errorf("libFoo missing dependency on non-afdo variant of libBar")
}
fooVariants := result.ModuleVariantsForTests("foo")
diff --git a/cc/config/global.go b/cc/config/global.go
index c562614..613641f 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -254,7 +254,7 @@
"-Wno-pointer-to-int-cast",
"-Werror=fortify-source",
// http://b/315246135 temporarily disabled
- "-Wno-error=unused-variable",
+ "-Wno-unused-variable",
// http://b/315250603 temporarily disabled
"-Wno-error=format",
// Disabled because it produces many false positives. http://b/323050926
@@ -302,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{}
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/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/base.go b/java/base.go
index 284ec99..4e2366f 100644
--- a/java/base.go
+++ b/java/base.go
@@ -2441,6 +2441,9 @@
// 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 {
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/droidstubs.go b/java/droidstubs.go
index 56ae427..51503f2 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -744,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{
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/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/python/scripts/precompile_python.py b/python/scripts/precompile_python.py
index 80e7c76..aa1a5df 100644
--- a/python/scripts/precompile_python.py
+++ b/python/scripts/precompile_python.py
@@ -24,7 +24,12 @@
# This file needs to support both python 2 and 3.
-def process_one_file(info, infile, outzip):
+def process_one_file(name, infile, outzip):
+ # Create a ZipInfo instance with a fixed date to ensure a deterministic output.
+ # Date was chosen to be the same as
+ # https://cs.android.com/android/platform/superproject/main/+/main:build/soong/jar/jar.go;l=36;drc=2863e4535eb65e15f955dc8ed48fa99b1d2a1db5
+ info = zipfile.ZipInfo(filename=name, date_time=(2008, 1, 1, 0, 0, 0))
+
if not info.filename.endswith('.py'):
outzip.writestr(info, infile.read())
return
@@ -37,17 +42,15 @@
with tempfile.NamedTemporaryFile(prefix="Soong_precompile_", delete=False) as tmp:
out_name = tmp.name
try:
- # Ensure deterministic pyc by using the hash rather than timestamp.
- # This is required to improve caching in accelerated builds.
- # Only works on Python 3.7+ (see https://docs.python.org/3/library/py_compile.html#py_compile.PycInvalidationMode)
- # which should cover most updated branches and developer machines.
+ # Ensure a deterministic .pyc output by using the hash rather than the timestamp.
+ # Only works on Python 3.7+
+ # See https://docs.python.org/3/library/py_compile.html#py_compile.PycInvalidationMode
if sys.version_info >= (3, 7):
py_compile.compile(in_name, out_name, info.filename, doraise=True, invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH)
else:
py_compile.compile(in_name, out_name, info.filename, doraise=True)
with open(out_name, 'rb') as f:
info.filename = info.filename + 'c'
- # Use ZipInfo rather than str to reuse timestamps for deterministic zip files.
outzip.writestr(info, f.read())
finally:
os.remove(in_name)
@@ -62,9 +65,9 @@
with open(args.dst_zip, 'wb') as outf, open(args.src_zip, 'rb') as inf:
with zipfile.ZipFile(outf, mode='w') as outzip, zipfile.ZipFile(inf, mode='r') as inzip:
- for info in inzip.infolist():
- with inzip.open(info.filename, mode='r') as inzipf:
- process_one_file(info, inzipf, outzip)
+ for name in inzip.namelist():
+ with inzip.open(name, mode='r') as inzipf:
+ process_one_file(name, inzipf, outzip)
if __name__ == "__main__":
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 9aeaf9d..e7896ab 100644
--- a/ui/build/androidmk_denylist.go
+++ b/ui/build/androidmk_denylist.go
@@ -30,7 +30,8 @@
"libcore/",
"libnativehelper/",
"pdk/",
- "toolchain/",
+ // Add back toolchain/ once defensive Android.mk files are removed
+ //"toolchain/",
}
func blockAndroidMks(ctx Context, androidMks []string) {