Merge "Add RELEASE_ACONFIG_REQUIRE_ALL_READ_ONLY build flag." into main
diff --git a/android/arch_test.go b/android/arch_test.go
index 57c9010..7914884 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -560,15 +560,7 @@
prepareForArchTest,
// Test specific preparer
OptionalFixturePreparer(tt.preparer),
- // Prepare for native bridge test
- FixtureModifyConfig(func(config Config) {
- config.Targets[Android] = []Target{
- {Android, Arch{ArchType: X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", "", false},
- {Android, Arch{ArchType: X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", "", false},
- {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeEnabled, "x86_64", "arm64", false},
- {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeEnabled, "x86", "arm", false},
- }
- }),
+ PrepareForNativeBridgeEnabled,
FixtureWithRootAndroidBp(bp),
).RunTest(t)
diff --git a/android/config.go b/android/config.go
index cb604a6..b811c55 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1519,6 +1519,13 @@
return "64"
}
+func (c *deviceConfig) RecoveryPath() string {
+ if c.config.productVariables.RecoveryPath != nil {
+ return *c.config.productVariables.RecoveryPath
+ }
+ return "recovery"
+}
+
func (c *deviceConfig) VendorPath() string {
if c.config.productVariables.VendorPath != nil {
return *c.config.productVariables.VendorPath
@@ -1614,6 +1621,10 @@
return proptools.Bool(c.config.productVariables.BuildingUserdataImage)
}
+func (c *deviceConfig) BuildingRecoveryImage() bool {
+ return proptools.Bool(c.config.productVariables.BuildingRecoveryImage)
+}
+
func (c *deviceConfig) BtConfigIncludeDir() string {
return String(c.config.productVariables.BtConfigIncludeDir)
}
diff --git a/android/hooks.go b/android/hooks.go
index 9f4e5b6..f8022d0 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -59,6 +59,16 @@
})
}
+func AddLoadHookWithPriority(m blueprint.Module, hook func(LoadHookContext), priority int) {
+ blueprint.AddLoadHookWithPriority(m, func(ctx blueprint.LoadHookContext) {
+ actx := &loadHookContext{
+ earlyModuleContext: m.(Module).base().earlyModuleContextFactory(ctx),
+ bp: ctx,
+ }
+ hook(actx)
+ }, priority)
+}
+
type loadHookContext struct {
earlyModuleContext
bp blueprint.LoadHookContext
diff --git a/android/module.go b/android/module.go
index 67dab4f..d703c19 100644
--- a/android/module.go
+++ b/android/module.go
@@ -338,6 +338,7 @@
}
Android struct {
Compile_multilib *string
+ Enabled *bool
}
}
@@ -1387,6 +1388,8 @@
partition = "ramdisk"
} else if m.InstallInVendorRamdisk() {
partition = "vendor_ramdisk"
+ } else if m.InstallInRecovery() {
+ partition = "recovery"
}
return partition
}
@@ -1866,6 +1869,7 @@
// The Target of artifacts that this module variant is responsible for creating.
CompileTarget Target
SkipAndroidMkProcessing bool
+ BaseModuleName string
}
var CommonModuleInfoKey = blueprint.NewProvider[CommonModuleInfo]()
@@ -2134,6 +2138,7 @@
ReplacedByPrebuilt: m.commonProperties.ReplacedByPrebuilt,
CompileTarget: m.commonProperties.CompileTarget,
SkipAndroidMkProcessing: shouldSkipAndroidMkProcessing(ctx, m),
+ BaseModuleName: m.BaseModuleName(),
}
if m.commonProperties.ForcedDisabled {
commonData.Enabled = false
diff --git a/android/neverallow.go b/android/neverallow.go
index 7f7ffa7..fdcbe1c 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -245,6 +245,11 @@
Without("name", "librecovery_ui_ext").
With("install_in_root", "true").
NotModuleType("prebuilt_root").
+ NotModuleType("prebuilt_vendor").
+ NotModuleType("prebuilt_sbin").
+ NotModuleType("prebuilt_system").
+ NotModuleType("prebuilt_first_stage_ramdisk").
+ NotModuleType("prebuilt_res").
Because("install_in_root is only for init_first_stage or librecovery_ui_ext."),
}
}
@@ -282,7 +287,7 @@
}
func createLimitDirgroupRule() []Rule {
- reason := "dirgroup module and dir_srcs property of genrule is allowed only to Trusty build rule."
+ reason := "dirgroup module and dir_srcs / keep_gendir property of genrule is allowed only to Trusty build rule."
return []Rule{
NeverAllow().
ModuleType("dirgroup").
@@ -297,6 +302,13 @@
Without("name", "trusty-x86_64.lk.elf.gen").
Without("name", "trusty-x86_64-test.lk.elf.gen").
WithMatcher("dir_srcs", isSetMatcherInstance).Because(reason),
+ NeverAllow().
+ ModuleType("genrule").
+ Without("name", "trusty-arm64.lk.elf.gen").
+ Without("name", "trusty-arm64-virt-test-debug.lk.elf.gen").
+ Without("name", "trusty-x86_64.lk.elf.gen").
+ Without("name", "trusty-x86_64-test.lk.elf.gen").
+ With("keep_gendir", "true").Because(reason),
}
}
@@ -333,7 +345,6 @@
"prebuilt_priv_app",
"prebuilt_rfs",
"prebuilt_framework",
- "prebuilt_res",
"prebuilt_wlc_upt",
"prebuilt_odm",
"prebuilt_vendor_dlkm",
@@ -341,6 +352,10 @@
"prebuilt_tvservice",
"prebuilt_optee",
"prebuilt_tvconfig",
+ "prebuilt_vendor",
+ "prebuilt_sbin",
+ "prebuilt_system",
+ "prebuilt_first_stage_ramdisk",
).
DefinedInBpFile().
Because("module type not allowed to be defined in bp file")
@@ -705,6 +720,9 @@
}
func (r *rule) appliesToModuleType(moduleType string) bool {
+ // Remove prefix for auto-generated modules
+ moduleType = strings.TrimSuffix(moduleType, "__loadHookModule")
+ moduleType = strings.TrimSuffix(moduleType, "__bottomUpMutatorModule")
return (len(r.moduleTypes) == 0 || InList(moduleType, r.moduleTypes)) && !InList(moduleType, r.unlessModuleTypes)
}
diff --git a/android/packaging.go b/android/packaging.go
index dcd8844..d96cccd 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -18,7 +18,6 @@
"fmt"
"path/filepath"
"sort"
- "strings"
"github.com/google/blueprint"
"github.com/google/blueprint/gobtools"
@@ -594,10 +593,6 @@
}
seenDir := make(map[string]bool)
- preparerPath := PathForModuleOut(ctx, "preparer.sh")
- cmd := builder.Command().Tool(preparerPath)
- var sb strings.Builder
- sb.WriteString("set -e\n")
dirs := make([]WritablePath, 0, len(dirsToSpecs))
for dir, _ := range dirsToSpecs {
@@ -616,22 +611,19 @@
entries = append(entries, ps.relPathInPackage)
if _, ok := seenDir[destDir]; !ok {
seenDir[destDir] = true
- sb.WriteString(fmt.Sprintf("mkdir -p %s\n", destDir))
+ builder.Command().Textf("mkdir -p %s", destDir)
}
if ps.symlinkTarget == "" {
- cmd.Implicit(ps.srcPath)
- sb.WriteString(fmt.Sprintf("cp %s %s\n", ps.srcPath, destPath))
+ builder.Command().Text("cp").Input(ps.srcPath).Text(destPath)
} else {
- sb.WriteString(fmt.Sprintf("ln -sf %s %s\n", ps.symlinkTarget, destPath))
+ builder.Command().Textf("ln -sf %s %s", ps.symlinkTarget, destPath)
}
if ps.executable {
- sb.WriteString(fmt.Sprintf("chmod a+x %s\n", destPath))
+ builder.Command().Textf("chmod a+x %s", destPath)
}
}
}
- WriteExecutableFileRuleVerbatim(ctx, preparerPath, sb.String())
-
return entries
}
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 83f8b99..db56c3f 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -63,6 +63,7 @@
missingDeps []string
args map[string]string
nsjail bool
+ nsjailKeepGendir bool
nsjailBasePath WritablePath
nsjailImplicits Paths
}
@@ -208,6 +209,18 @@
return r
}
+// By default, nsjail rules truncate outputDir and baseDir before running commands, similar to Sbox
+// rules which always run commands in a fresh sandbox. Calling NsjailKeepGendir keeps outputDir and
+// baseDir as-is, leaving previous artifacts. This is useful when the rules support incremental
+// builds.
+func (r *RuleBuilder) NsjailKeepGendir() *RuleBuilder {
+ if !r.nsjail {
+ panic("NsjailKeepGendir() must be called after Nsjail()")
+ }
+ r.nsjailKeepGendir = true
+ return r
+}
+
// SandboxTools enables tool sandboxing for the rule by copying any referenced tools into the
// sandbox.
func (r *RuleBuilder) SandboxTools() *RuleBuilder {
@@ -555,8 +568,17 @@
if r.nsjail {
var nsjailCmd strings.Builder
nsjailPath := r.ctx.Config().PrebuiltBuildTool(r.ctx, "nsjail")
+ if !r.nsjailKeepGendir {
+ nsjailCmd.WriteString("rm -rf ")
+ nsjailCmd.WriteString(r.nsjailBasePath.String())
+ nsjailCmd.WriteRune(' ')
+ nsjailCmd.WriteString(r.outDir.String())
+ nsjailCmd.WriteString(" && ")
+ }
nsjailCmd.WriteString("mkdir -p ")
nsjailCmd.WriteString(r.nsjailBasePath.String())
+ nsjailCmd.WriteRune(' ')
+ nsjailCmd.WriteString(r.outDir.String())
nsjailCmd.WriteString(" && ")
nsjailCmd.WriteString(nsjailPath.String())
nsjailCmd.WriteRune(' ')
@@ -853,6 +875,18 @@
pool = localPool
}
+ // If the command length is getting close to linux's maximum, dump it to a file, which allows
+ // for longer commands.
+ if len(commandString) > 100000 {
+ hasher := sha256.New()
+ hasher.Write([]byte(output.String()))
+ script := PathForOutput(r.ctx, "rule_builder_scripts", fmt.Sprintf("%x.sh", hasher.Sum(nil)))
+ commandString = "set -eu\n\n" + commandString + "\n"
+ WriteExecutableFileRuleVerbatim(r.ctx, script, commandString)
+ inputs = append(inputs, script)
+ commandString = script.String()
+ }
+
commandString = proptools.NinjaEscape(commandString)
args_vars := make([]string, len(r.args))
diff --git a/android/testing.go b/android/testing.go
index f243e81..765839f 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -190,6 +190,26 @@
})
}
+// PrepareForNativeBridgeEnabled sets configuration with targets including:
+// - X86_64 (primary)
+// - X86 (secondary)
+// - Arm64 on X86_64 (native bridge)
+// - Arm on X86 (native bridge)
+var PrepareForNativeBridgeEnabled = FixtureModifyConfig(
+ func(config Config) {
+ config.Targets[Android] = []Target{
+ {Os: Android, Arch: Arch{ArchType: X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}},
+ NativeBridge: NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
+ {Os: Android, Arch: Arch{ArchType: X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}},
+ NativeBridge: NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
+ {Os: Android, Arch: Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}},
+ NativeBridge: NativeBridgeEnabled, NativeBridgeHostArchName: "x86_64", NativeBridgeRelativePath: "arm64"},
+ {Os: Android, Arch: Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}},
+ NativeBridge: NativeBridgeEnabled, NativeBridgeHostArchName: "x86", NativeBridgeRelativePath: "arm"},
+ }
+ },
+)
+
func NewTestArchContext(config Config) *TestContext {
ctx := NewTestContext(config)
ctx.preDeps = append(ctx.preDeps, registerArchMutator)
diff --git a/android/variable.go b/android/variable.go
index 25d99da..baa2646 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -351,6 +351,8 @@
OemPath *string `json:",omitempty"`
UserdataPath *string `json:",omitempty"`
BuildingUserdataImage *bool `json:",omitempty"`
+ RecoveryPath *string `json:",omitempty"`
+ BuildingRecoveryImage *bool `json:",omitempty"`
ClangTidy *bool `json:",omitempty"`
TidyChecks *string `json:",omitempty"`
@@ -665,6 +667,10 @@
VendorRamdiskKernelBlocklistFile string `json:",omitempty"`
VendorRamdiskKernelLoadModules []string `json:",omitempty"`
VendorRamdiskKernelOptionsFile string `json:",omitempty"`
+
+ ProductFsverityGenerateMetadata bool `json:",omitempty"`
+
+ TargetScreenDensity string `json:",omitempty"`
}
func boolPtr(v bool) *bool {
diff --git a/apex/apex.go b/apex/apex.go
index 72a0455..f934134 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1850,7 +1850,7 @@
// as the apex.
func (a *apexBundle) enforcePartitionTagOnApexSystemServerJar(ctx android.ModuleContext) {
global := dexpreopt.GetGlobalConfig(ctx)
- ctx.VisitDirectDepsWithTag(sscpfTag, func(child android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(sscpfTag, func(child android.ModuleProxy) {
info, ok := android.OtherModuleProvider(ctx, child, java.LibraryNameToPartitionInfoProvider)
if !ok {
ctx.ModuleErrorf("Could not find partition info of apex system server jars.")
@@ -2309,7 +2309,7 @@
// Apexes built from source retrieve this information by visiting `bootclasspath_fragments`
// Used by dex_bootjars to generate the boot image
func (a *apexBundle) provideApexExportsInfo(ctx android.ModuleContext) {
- ctx.VisitDirectDepsWithTag(bcpfTag, func(child android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(bcpfTag, func(child android.ModuleProxy) {
if info, ok := android.OtherModuleProvider(ctx, child, java.BootclasspathFragmentApexContentInfoProvider); ok {
exports := android.ApexExportsInfo{
ApexName: a.ApexVariationName(),
@@ -2340,7 +2340,7 @@
}
if a.Updatable() {
// checking direct deps is sufficient since apex->apk is a direct edge, even when inherited via apex_defaults
- mctx.VisitDirectDeps(func(module android.Module) {
+ mctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
if appInfo, ok := android.OtherModuleProvider(mctx, module, java.AppInfoProvider); ok {
// ignore android_test_app
if !appInfo.TestHelperApp && !appInfo.Updatable {
@@ -2647,16 +2647,12 @@
func (a *apexBundle) checkJavaStableSdkVersion(ctx android.ModuleContext) {
// Visit direct deps only. As long as we guarantee top-level deps are using stable SDKs,
// java's checkLinkType guarantees correct usage for transitive deps
- ctx.VisitDirectDeps(func(module android.Module) {
+ ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
tag := ctx.OtherModuleDependencyTag(module)
switch tag {
case javaLibTag, androidAppTag:
- if m, ok := module.(interface {
- CheckStableSdkVersion(ctx android.BaseModuleContext) error
- }); ok {
- if err := m.CheckStableSdkVersion(ctx); err != nil {
- ctx.ModuleErrorf("cannot depend on \"%v\": %v", ctx.OtherModuleName(module), err)
- }
+ if err := java.CheckStableSdkVersion(ctx, module); err != nil {
+ ctx.ModuleErrorf("cannot depend on \"%v\": %v", ctx.OtherModuleName(module), err)
}
}
})
@@ -2889,7 +2885,7 @@
}
var appEmbeddedJNILibs android.Paths
- ctx.VisitDirectDeps(func(dep android.Module) {
+ ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
tag := ctx.OtherModuleDependencyTag(dep)
if !checkApexTag(tag) {
return
diff --git a/apex/apex_test.go b/apex/apex_test.go
index ed6284d..282cd1d 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -84,26 +84,6 @@
return files.AddToFixture()
}
-// withNativeBridgeTargets sets configuration with targets including:
-// - X86_64 (primary)
-// - X86 (secondary)
-// - Arm64 on X86_64 (native bridge)
-// - Arm on X86 (native bridge)
-var withNativeBridgeEnabled = android.FixtureModifyConfig(
- func(config android.Config) {
- config.Targets[android.Android] = []android.Target{
- {Os: android.Android, Arch: android.Arch{ArchType: android.X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}},
- NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
- {Os: android.Android, Arch: android.Arch{ArchType: android.X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}},
- NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
- {Os: android.Android, Arch: android.Arch{ArchType: android.Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}},
- NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "x86_64", NativeBridgeRelativePath: "arm64"},
- {Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}},
- NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "x86", NativeBridgeRelativePath: "arm"},
- }
- },
-)
-
func withManifestPackageNameOverrides(specs []string) android.FixturePreparer {
return android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.ManifestPackageNameOverrides = specs
@@ -3198,7 +3178,7 @@
},
},
}
- `, withNativeBridgeEnabled)
+ `, android.PrepareForNativeBridgeEnabled)
ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
"bin/foo/bar/mybin",
"bin/foo/bar/mybin64",
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index b0b5da9..2bcbde1 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -81,6 +81,10 @@
ctx.RegisterModuleType("prebuilt_tvservice", PrebuiltTvServiceFactory)
ctx.RegisterModuleType("prebuilt_optee", PrebuiltOpteeFactory)
ctx.RegisterModuleType("prebuilt_tvconfig", PrebuiltTvConfigFactory)
+ ctx.RegisterModuleType("prebuilt_vendor", PrebuiltVendorFactory)
+ ctx.RegisterModuleType("prebuilt_sbin", PrebuiltSbinFactory)
+ ctx.RegisterModuleType("prebuilt_system", PrebuiltSystemFactory)
+ ctx.RegisterModuleType("prebuilt_first_stage_ramdisk", PrebuiltFirstStageRamdiskFactory)
ctx.RegisterModuleType("prebuilt_defaults", defaultsFactory)
@@ -573,6 +577,7 @@
p.installDirBase = dirBase
p.AddProperties(&p.properties)
p.AddProperties(&p.subdirProperties)
+ p.AddProperties(&p.rootProperties)
}
func InitPrebuiltRootModule(p *PrebuiltEtc) {
@@ -972,3 +977,43 @@
android.InitDefaultableModule(module)
return module
}
+
+// prebuilt_vendor installs files in <partition>/vendor directory.
+func PrebuiltVendorFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "vendor")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+ return module
+}
+
+// prebuilt_sbin installs files in <partition>/sbin directory.
+func PrebuiltSbinFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "sbin")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+ return module
+}
+
+// prebuilt_system installs files in <partition>/system directory.
+func PrebuiltSystemFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "system")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+ return module
+}
+
+// prebuilt_first_stage_ramdisk installs files in <partition>/first_stage_ramdisk directory.
+func PrebuiltFirstStageRamdiskFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "first_stage_ramdisk")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+ return module
+}
diff --git a/filesystem/aconfig_files.go b/filesystem/aconfig_files.go
index 7de404f..c80ae03 100644
--- a/filesystem/aconfig_files.go
+++ b/filesystem/aconfig_files.go
@@ -16,7 +16,6 @@
import (
"android/soong/android"
- "strings"
"github.com/google/blueprint/proptools"
)
@@ -26,57 +25,34 @@
return
}
- aconfigFlagsBuilderPath := android.PathForModuleOut(ctx, "aconfig_flags_builder.sh")
- aconfigToolPath := ctx.Config().HostToolPath(ctx, "aconfig")
- cmd := builder.Command().Tool(aconfigFlagsBuilderPath).Implicit(aconfigToolPath)
-
- var caches []string
+ var caches []android.Path
for _, ps := range specs {
- cmd.Implicits(ps.GetAconfigPaths())
- caches = append(caches, ps.GetAconfigPaths().Strings()...)
+ caches = append(caches, ps.GetAconfigPaths()...)
}
- caches = android.SortedUniqueStrings(caches)
-
- var sbCaches strings.Builder
- for _, cache := range caches {
- sbCaches.WriteString(" --cache ")
- sbCaches.WriteString(cache)
- sbCaches.WriteString(" \\\n")
- }
- sbCaches.WriteRune('\n')
-
- var sb strings.Builder
- sb.WriteString("set -e\n")
+ caches = android.SortedUniquePaths(caches)
installAconfigFlagsPath := dir.Join(ctx, "etc", "aconfig_flags.pb")
- sb.WriteString(aconfigToolPath.String())
- sb.WriteString(" dump-cache --dedup --format protobuf --out ")
- sb.WriteString(installAconfigFlagsPath.String())
- sb.WriteString(" --filter container:")
- sb.WriteString(f.PartitionType())
- sb.WriteString(" \\\n")
- sb.WriteString(sbCaches.String())
- cmd.ImplicitOutput(installAconfigFlagsPath)
+ cmd := builder.Command().
+ BuiltTool("aconfig").
+ Text(" dump-cache --dedup --format protobuf --out").
+ Output(installAconfigFlagsPath).
+ Textf("--filter container:%s", f.PartitionType())
+ for _, cache := range caches {
+ cmd.FlagWithInput("--cache ", cache)
+ }
f.appendToEntry(ctx, installAconfigFlagsPath)
installAconfigStorageDir := dir.Join(ctx, "etc", "aconfig")
- sb.WriteString("mkdir -p ")
- sb.WriteString(installAconfigStorageDir.String())
- sb.WriteRune('\n')
+ builder.Command().Text("mkdir -p").Text(installAconfigStorageDir.String())
generatePartitionAconfigStorageFile := func(fileType, fileName string) {
outputPath := installAconfigStorageDir.Join(ctx, fileName)
- sb.WriteString(aconfigToolPath.String())
- sb.WriteString(" create-storage --container ")
- sb.WriteString(f.PartitionType())
- sb.WriteString(" --file ")
- sb.WriteString(fileType)
- sb.WriteString(" --out ")
- sb.WriteString(outputPath.String())
- sb.WriteString(" --cache ")
- sb.WriteString(installAconfigFlagsPath.String())
- sb.WriteRune('\n')
- cmd.ImplicitOutput(outputPath)
+ builder.Command().
+ BuiltTool("aconfig").
+ FlagWithArg("create-storage --container ", f.PartitionType()).
+ FlagWithArg("--file ", fileType).
+ FlagWithOutput("--out ", outputPath).
+ FlagWithArg("--cache ", installAconfigFlagsPath.String())
f.appendToEntry(ctx, outputPath)
}
@@ -86,6 +62,4 @@
generatePartitionAconfigStorageFile("flag_val", "flag.val")
generatePartitionAconfigStorageFile("flag_info", "flag.info")
}
-
- android.WriteExecutableFileRuleVerbatim(ctx, aconfigFlagsBuilderPath, sb.String())
}
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 5b217ae..fbc8089 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -25,6 +25,7 @@
"android/soong/android"
"android/soong/cc"
+ "android/soong/java"
"android/soong/linkerconfig"
"github.com/google/blueprint"
@@ -33,6 +34,7 @@
func init() {
registerBuildComponents(android.InitRegistrationContext)
+ registerMutators(android.InitRegistrationContext)
}
func registerBuildComponents(ctx android.RegistrationContext) {
@@ -45,6 +47,12 @@
ctx.RegisterModuleType("avb_gen_vbmeta_image_defaults", avbGenVbmetaImageDefaultsFactory)
}
+func registerMutators(ctx android.RegistrationContext) {
+ ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("add_autogenerated_rro_deps", addAutogeneratedRroDeps)
+ })
+}
+
type filesystem struct {
android.ModuleBase
android.PackagingBase
@@ -170,6 +178,14 @@
// Path to the dev nodes description file. This is only needed for building the ramdisk
// partition and should not be explicitly specified.
Dev_nodes_description_file *string `android:"path" blueprint:"mutated"`
+
+ // Additional dependencies used for building android products
+ Android_filesystem_deps AndroidFilesystemDeps
+}
+
+type AndroidFilesystemDeps struct {
+ System *string
+ System_ext *string
}
// Additional properties required to generate erofs FS partitions.
@@ -235,6 +251,12 @@
depTag
}
+type interPartitionDepTag struct {
+ blueprint.BaseDependencyTag
+}
+
+var interPartitionDependencyTag = interPartitionDepTag{}
+
var _ android.ExcludeFromVisibilityEnforcementTag = (*depTagWithVisibilityEnforcementBypass)(nil)
func (t depTagWithVisibilityEnforcementBypass) ExcludeFromVisibilityEnforcement() {}
@@ -257,6 +279,12 @@
} else {
f.AddDeps(ctx, dependencyTag)
}
+ if f.properties.Android_filesystem_deps.System != nil {
+ ctx.AddDependency(ctx.Module(), interPartitionDependencyTag, proptools.String(f.properties.Android_filesystem_deps.System))
+ }
+ if f.properties.Android_filesystem_deps.System_ext != nil {
+ ctx.AddDependency(ctx.Module(), interPartitionDependencyTag, proptools.String(f.properties.Android_filesystem_deps.System_ext))
+ }
}
type fsType int
@@ -649,11 +677,10 @@
switch fst {
case erofsType:
// Add erofs properties
- if compressor := f.properties.Erofs.Compressor; compressor != nil {
- addStr("erofs_default_compressor", proptools.String(compressor))
- }
- if compressHints := f.properties.Erofs.Compress_hints; compressHints != nil {
- addPath("erofs_default_compress_hints", android.PathForModuleSrc(ctx, *compressHints))
+ addStr("erofs_default_compressor", proptools.StringDefault(f.properties.Erofs.Compressor, "lz4hc,9"))
+ if f.properties.Erofs.Compress_hints != nil {
+ src := android.PathForModuleSrc(ctx, *f.properties.Erofs.Compress_hints)
+ addPath("erofs_default_compress_hints", src)
}
if proptools.BoolDefault(f.properties.Erofs.Sparse, true) {
// https://source.corp.google.com/h/googleplex-android/platform/build/+/88b1c67239ca545b11580237242774b411f2fed9:core/Makefile;l=2292;bpv=1;bpt=0;drc=ea8f34bc1d6e63656b4ec32f2391e9d54b3ebb6b
@@ -762,6 +789,7 @@
"system_dlkm",
"ramdisk",
"vendor_ramdisk",
+ "recovery",
}
func (f *filesystem) addMakeBuiltFiles(ctx android.ModuleContext, builder *android.RuleBuilder, rootDir android.Path) {
@@ -1004,3 +1032,30 @@
image, maxSize)
cmd.Implicit(image)
}
+
+// addAutogeneratedRroDeps walks the transitive closure of vendor and product partitions.
+// It visits apps installed in system and system_ext partitions, and adds the autogenerated
+// RRO modules to its own deps.
+func addAutogeneratedRroDeps(ctx android.BottomUpMutatorContext) {
+ f, ok := ctx.Module().(*filesystem)
+ if !ok {
+ return
+ }
+ thisPartition := f.PartitionType()
+ if thisPartition != "vendor" && thisPartition != "product" {
+ return
+ }
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ depTag := ctx.OtherModuleDependencyTag(child)
+ if parent.Name() == f.Name() && depTag != interPartitionDependencyTag {
+ return false // This is a module listed in deps of vendor/product filesystem
+ }
+ if vendorOverlay := java.AutogeneratedRroModuleName(ctx, child.Name(), "vendor"); ctx.OtherModuleExists(vendorOverlay) && thisPartition == "vendor" {
+ ctx.AddFarVariationDependencies(nil, dependencyTagWithVisibilityEnforcementBypass, vendorOverlay)
+ }
+ if productOverlay := java.AutogeneratedRroModuleName(ctx, child.Name(), "product"); ctx.OtherModuleExists(productOverlay) && thisPartition == "product" {
+ ctx.AddFarVariationDependencies(nil, dependencyTagWithVisibilityEnforcementBypass, productOverlay)
+ }
+ return true
+ })
+}
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index 746e4de..72a5211 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -16,6 +16,7 @@
import (
"os"
+ "strings"
"testing"
"android/soong/android"
@@ -182,10 +183,14 @@
module := result.ModuleForTests("myfilesystem", "android_common")
output := module.Output("out/soong/.intermediates/myfilesystem/android_common/root/system/etc/linker.config.pb")
+ fullCommand := output.RuleParams.Command
+ startIndex := strings.Index(fullCommand, "conv_linker_config")
+ linkerConfigCommand := fullCommand[startIndex:]
+
android.AssertStringDoesContain(t, "linker.config.pb should have libfoo",
- output.RuleParams.Command, "libfoo.so")
+ linkerConfigCommand, "libfoo.so")
android.AssertStringDoesNotContain(t, "linker.config.pb should not have libbar",
- output.RuleParams.Command, "libbar.so")
+ linkerConfigCommand, "libbar.so")
}
func registerComponent(ctx android.RegistrationContext) {
diff --git a/filesystem/fsverity_metadata.go b/filesystem/fsverity_metadata.go
index 3119f2f..ef46067 100644
--- a/filesystem/fsverity_metadata.go
+++ b/filesystem/fsverity_metadata.go
@@ -66,62 +66,44 @@
return
}
- fsverityBuilderPath := android.PathForModuleOut(ctx, "fsverity_builder.sh")
- metadataGeneratorPath := ctx.Config().HostToolPath(ctx, "fsverity_metadata_generator")
fsverityPath := ctx.Config().HostToolPath(ctx, "fsverity")
- cmd := builder.Command().Tool(fsverityBuilderPath)
-
// STEP 1: generate .fsv_meta
var sb strings.Builder
sb.WriteString("set -e\n")
- cmd.Implicit(metadataGeneratorPath).Implicit(fsverityPath)
for _, spec := range matchedSpecs {
// srcPath is copied by CopySpecsToDir()
srcPath := rebasedDir.Join(ctx, spec.RelPathInPackage())
destPath := rebasedDir.Join(ctx, spec.RelPathInPackage()+".fsv_meta")
- sb.WriteString(metadataGeneratorPath.String())
- sb.WriteString(" --fsverity-path ")
- sb.WriteString(fsverityPath.String())
- sb.WriteString(" --signature none --hash-alg sha256 --output ")
- sb.WriteString(destPath.String())
- sb.WriteRune(' ')
- sb.WriteString(srcPath.String())
- sb.WriteRune('\n')
+ builder.Command().
+ BuiltTool("fsverity_metadata_generator").
+ FlagWithInput("--fsverity-path ", fsverityPath).
+ FlagWithArg("--signature ", "none").
+ FlagWithArg("--hash-alg ", "sha256").
+ FlagWithArg("--output ", destPath.String()).
+ Text(srcPath.String())
f.appendToEntry(ctx, destPath)
}
// STEP 2: generate signed BuildManifest.apk
// STEP 2-1: generate build_manifest.pb
- assetsPath := android.PathForModuleOut(ctx, "fsverity_manifest/assets")
- manifestPbPath := assetsPath.Join(ctx, "build_manifest.pb")
- manifestGeneratorPath := ctx.Config().HostToolPath(ctx, "fsverity_manifest_generator")
- cmd.Implicit(manifestGeneratorPath)
- sb.WriteString("rm -rf ")
- sb.WriteString(assetsPath.String())
- sb.WriteString(" && mkdir -p ")
- sb.WriteString(assetsPath.String())
- sb.WriteRune('\n')
- sb.WriteString(manifestGeneratorPath.String())
- sb.WriteString(" --fsverity-path ")
- sb.WriteString(fsverityPath.String())
- sb.WriteString(" --base-dir ")
- sb.WriteString(rootDir.String())
- sb.WriteString(" --output ")
- sb.WriteString(manifestPbPath.String())
- sb.WriteRune(' ')
- f.appendToEntry(ctx, manifestPbPath)
-
manifestGeneratorListPath := android.PathForModuleOut(ctx, "fsverity_manifest.list")
f.writeManifestGeneratorListFile(ctx, manifestGeneratorListPath, matchedSpecs, rebasedDir)
- sb.WriteRune('@')
- sb.WriteString(manifestGeneratorListPath.String())
- sb.WriteRune('\n')
- cmd.Implicit(manifestGeneratorListPath)
+ assetsPath := android.PathForModuleOut(ctx, "fsverity_manifest/assets")
+ manifestPbPath := assetsPath.Join(ctx, "build_manifest.pb")
+ builder.Command().Text("rm -rf " + assetsPath.String())
+ builder.Command().Text("mkdir -p " + assetsPath.String())
+ builder.Command().
+ BuiltTool("fsverity_manifest_generator").
+ FlagWithInput("--fsverity-path ", fsverityPath).
+ FlagWithArg("--base-dir ", rootDir.String()).
+ FlagWithArg("--output ", manifestPbPath.String()).
+ FlagWithInput("@", manifestGeneratorListPath)
+
+ f.appendToEntry(ctx, manifestPbPath)
f.appendToEntry(ctx, manifestGeneratorListPath)
// STEP 2-2: generate BuildManifest.apk (unsigned)
- aapt2Path := ctx.Config().HostToolPath(ctx, "aapt2")
apkNameSuffix := ""
if f.PartitionType() == "system_ext" {
//https://source.corp.google.com/h/googleplex-android/platform/build/+/e392d2b486c2d4187b20a72b1c67cc737ecbcca5:core/Makefile;l=3410;drc=ea8f34bc1d6e63656b4ec32f2391e9d54b3ebb6b;bpv=1;bpt=0
@@ -131,55 +113,38 @@
idsigPath := rebasedDir.Join(ctx, "etc", "security", "fsverity", fmt.Sprintf("BuildManifest%s.apk.idsig", apkNameSuffix))
manifestTemplatePath := android.PathForSource(ctx, "system/security/fsverity/AndroidManifest.xml")
libs := android.PathsForModuleSrc(ctx, f.properties.Fsverity.Libs)
- cmd.Implicit(aapt2Path)
- cmd.Implicit(manifestTemplatePath)
- cmd.Implicits(libs)
- cmd.ImplicitOutput(apkPath)
- sb.WriteString(aapt2Path.String())
- sb.WriteString(" link -o ")
- sb.WriteString(apkPath.String())
- sb.WriteString(" -A ")
- sb.WriteString(assetsPath.String())
- for _, lib := range libs {
- sb.WriteString(" -I ")
- sb.WriteString(lib.String())
- }
minSdkVersion := ctx.Config().PlatformSdkCodename()
if minSdkVersion == "REL" {
minSdkVersion = ctx.Config().PlatformSdkVersion().String()
}
- sb.WriteString(" --min-sdk-version ")
- sb.WriteString(minSdkVersion)
- sb.WriteString(" --version-code ")
- sb.WriteString(ctx.Config().PlatformSdkVersion().String())
- sb.WriteString(" --version-name ")
- sb.WriteString(ctx.Config().AppsDefaultVersionName())
- sb.WriteString(" --manifest ")
- sb.WriteString(manifestTemplatePath.String())
- sb.WriteString(" --rename-manifest-package com.android.security.fsverity_metadata.")
- sb.WriteString(f.partitionName())
- sb.WriteRune('\n')
+
+ unsignedApkCommand := builder.Command().
+ BuiltTool("aapt2").
+ Text("link").
+ FlagWithOutput("-o ", apkPath).
+ FlagWithArg("-A ", assetsPath.String())
+ for _, lib := range libs {
+ unsignedApkCommand.FlagWithInput("-I ", lib)
+ }
+ unsignedApkCommand.
+ FlagWithArg("--min-sdk-version ", minSdkVersion).
+ FlagWithArg("--version-code ", ctx.Config().PlatformSdkVersion().String()).
+ FlagWithArg("--version-name ", ctx.Config().AppsDefaultVersionName()).
+ FlagWithInput("--manifest ", manifestTemplatePath).
+ Text(" --rename-manifest-package com.android.security.fsverity_metadata." + f.partitionName())
f.appendToEntry(ctx, apkPath)
// STEP 2-3: sign BuildManifest.apk
- apksignerPath := ctx.Config().HostToolPath(ctx, "apksigner")
pemPath, keyPath := ctx.Config().DefaultAppCertificate(ctx)
- cmd.Implicit(apksignerPath)
- cmd.Implicit(pemPath)
- cmd.Implicit(keyPath)
- cmd.ImplicitOutput(idsigPath)
- sb.WriteString(apksignerPath.String())
- sb.WriteString(" sign --in ")
- sb.WriteString(apkPath.String())
- sb.WriteString(" --cert ")
- sb.WriteString(pemPath.String())
- sb.WriteString(" --key ")
- sb.WriteString(keyPath.String())
- sb.WriteRune('\n')
+ builder.Command().
+ BuiltTool("apksigner").
+ Text("sign").
+ FlagWithArg("--in ", apkPath.String()).
+ FlagWithInput("--cert ", pemPath).
+ FlagWithInput("--key ", keyPath).
+ ImplicitOutput(idsigPath)
f.appendToEntry(ctx, idsigPath)
-
- android.WriteExecutableFileRuleVerbatim(ctx, fsverityBuilderPath, sb.String())
}
diff --git a/fsgen/Android.bp b/fsgen/Android.bp
index a022581..e8065f3 100644
--- a/fsgen/Android.bp
+++ b/fsgen/Android.bp
@@ -17,6 +17,7 @@
"filesystem_creator.go",
"fsgen_mutators.go",
"prebuilt_etc_modules_gen.go",
+ "util.go",
"vbmeta_partitions.go",
],
testSrcs: [
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index 8325b1e..745aeaa 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -69,6 +69,7 @@
avbpubkeyGenerated := createAvbpubkeyModule(ctx)
createFsGenState(ctx, generatedPrebuiltEtcModuleNames, avbpubkeyGenerated)
module.createAvbKeyFilegroups(ctx)
+ module.createMiscFilegroups(ctx)
module.createInternalModules(ctx)
})
@@ -108,6 +109,9 @@
if buildingVendorBootImage(partitionVars) {
generatedPartitions = append(generatedPartitions, "vendor_ramdisk")
}
+ if ctx.DeviceConfig().BuildingRecoveryImage() && ctx.DeviceConfig().RecoveryPath() == "recovery" {
+ generatedPartitions = append(generatedPartitions, "recovery")
+ }
return generatedPartitions
}
@@ -205,23 +209,25 @@
ctx.CreateModule(filesystem.AndroidDeviceFactory, baseProps, partitionProps)
}
-func partitionSpecificFsProps(fsProps *filesystem.FilesystemProperties, partitionVars android.PartitionVariables, partitionType string) {
+func partitionSpecificFsProps(ctx android.EarlyModuleContext, fsProps *filesystem.FilesystemProperties, partitionVars android.PartitionVariables, partitionType string) {
switch partitionType {
case "system":
fsProps.Build_logtags = proptools.BoolPtr(true)
// https://source.corp.google.com/h/googleplex-android/platform/build//639d79f5012a6542ab1f733b0697db45761ab0f3:core/packaging/flags.mk;l=21;drc=5ba8a8b77507f93aa48cc61c5ba3f31a4d0cbf37;bpv=1;bpt=0
fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
// Identical to that of the aosp_shared_system_image
- fsProps.Fsverity.Inputs = []string{
- "etc/boot-image.prof",
- "etc/dirty-image-objects",
- "etc/preloaded-classes",
- "etc/classpaths/*.pb",
- "framework/*",
- "framework/*/*", // framework/{arch}
- "framework/oat/*/*", // framework/oat/{arch}
+ if partitionVars.ProductFsverityGenerateMetadata {
+ fsProps.Fsverity.Inputs = []string{
+ "etc/boot-image.prof",
+ "etc/dirty-image-objects",
+ "etc/preloaded-classes",
+ "etc/classpaths/*.pb",
+ "framework/*",
+ "framework/*/*", // framework/{arch}
+ "framework/oat/*/*", // framework/oat/{arch}
+ }
+ fsProps.Fsverity.Libs = []string{":framework-res{.export-package.apk}"}
}
- fsProps.Fsverity.Libs = []string{":framework-res{.export-package.apk}"}
// Most of the symlinks and directories listed here originate from create_root_structure.mk,
// but the handwritten generic system image also recreates them:
// https://cs.android.com/android/platform/superproject/main/+/main:build/make/target/product/generic/Android.bp;l=33;drc=db08311f1b6ef6cb0a4fbcc6263b89849360ce04
@@ -348,14 +354,20 @@
"product",
})
case "system_ext":
- fsProps.Fsverity.Inputs = []string{
- "framework/*",
- "framework/*/*", // framework/{arch}
- "framework/oat/*/*", // framework/oat/{arch}
+ if partitionVars.ProductFsverityGenerateMetadata {
+ fsProps.Fsverity.Inputs = []string{
+ "framework/*",
+ "framework/*/*", // framework/{arch}
+ "framework/oat/*/*", // framework/oat/{arch}
+ }
+ fsProps.Fsverity.Libs = []string{":framework-res{.export-package.apk}"}
}
- fsProps.Fsverity.Libs = []string{":framework-res{.export-package.apk}"}
case "product":
fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
+ fsProps.Android_filesystem_deps.System = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system"))
+ if ctx.DeviceConfig().SystemExtPath() == "system_ext" {
+ fsProps.Android_filesystem_deps.System_ext = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext"))
+ }
case "vendor":
fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
fsProps.Symlinks = []filesystem.SymlinkDefinition{
@@ -368,6 +380,10 @@
Name: proptools.StringPtr("vendor/lib/modules"),
},
}
+ fsProps.Android_filesystem_deps.System = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system"))
+ if ctx.DeviceConfig().SystemExtPath() == "system_ext" {
+ fsProps.Android_filesystem_deps.System_ext = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext"))
+ }
case "odm":
fsProps.Symlinks = []filesystem.SymlinkDefinition{
filesystem.SymlinkDefinition{
@@ -399,6 +415,22 @@
"first_stage_ramdisk/sys",
})
}
+ case "recovery":
+ // Following https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2826;drc=ad7cfb56010cb22c3aa0e70cf71c804352553526
+ fsProps.Dirs = android.NewSimpleConfigurable([]string{
+ "sdcard",
+ "tmp",
+ })
+ fsProps.Symlinks = []filesystem.SymlinkDefinition{
+ {
+ Target: proptools.StringPtr("/system/bin/init"),
+ Name: proptools.StringPtr("init"),
+ },
+ {
+ Target: proptools.StringPtr("prop.default"),
+ Name: proptools.StringPtr("default.prop"),
+ },
+ }
}
}
@@ -491,6 +523,29 @@
}
}
+// Creates filegroups for miscellaneous other files
+func (f *filesystemCreator) createMiscFilegroups(ctx android.LoadHookContext) {
+ partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
+
+ if partitionVars.BoardErofsCompressorHints != "" {
+ dir := filepath.Dir(partitionVars.BoardErofsCompressorHints)
+ base := filepath.Base(partitionVars.BoardErofsCompressorHints)
+ ctx.CreateModuleInDirectory(
+ android.FileGroupFactory,
+ dir,
+ &struct {
+ Name *string
+ Srcs []string
+ Visibility []string
+ }{
+ Name: proptools.StringPtr("soong_generated_board_erofs_compress_hints_filegroup"),
+ Srcs: []string{base},
+ Visibility: []string{"//visibility:public"},
+ },
+ )
+ }
+}
+
// createPrebuiltKernelModules creates `prebuilt_kernel_modules`. These modules will be added to deps of the
// autogenerated *_dlkm filsystem modules. Each _dlkm partition should have a single prebuilt_kernel_modules dependency.
// This ensures that the depmod artifacts (modules.* installed in /lib/modules/) are generated with a complete view.
@@ -690,6 +745,15 @@
return nil, false
}
+ if *fsProps.Type == "erofs" {
+ if partitionVars.BoardErofsCompressor != "" {
+ fsProps.Erofs.Compressor = proptools.StringPtr(partitionVars.BoardErofsCompressor)
+ }
+ if partitionVars.BoardErofsCompressorHints != "" {
+ fsProps.Erofs.Compress_hints = proptools.StringPtr(":soong_generated_board_erofs_compress_hints_filegroup")
+ }
+ }
+
// Don't build this module on checkbuilds, the soong-built partitions are still in-progress
// and sometimes don't build.
fsProps.Unchecked_module = proptools.BoolPtr(true)
@@ -711,7 +775,7 @@
fsProps.Is_auto_generated = proptools.BoolPtr(true)
- partitionSpecificFsProps(fsProps, partitionVars, partitionType)
+ partitionSpecificFsProps(ctx, fsProps, partitionVars, partitionType)
// system_image properties that are not set:
// - filesystemProperties.Avb_hash_algorithm
diff --git a/fsgen/filesystem_creator_test.go b/fsgen/filesystem_creator_test.go
index fe4a403..5657608 100644
--- a/fsgen/filesystem_creator_test.go
+++ b/fsgen/filesystem_creator_test.go
@@ -168,13 +168,8 @@
BoardFileSystemType: "ext4",
},
}
- config.Targets[android.Android] = []android.Target{
- {Os: android.Android, Arch: android.Arch{ArchType: android.X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}}, NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: "", HostCross: false},
- {Os: android.Android, Arch: android.Arch{ArchType: android.X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: "", HostCross: false},
- {Os: android.Android, Arch: android.Arch{ArchType: android.Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "x86_64", NativeBridgeRelativePath: "arm64", HostCross: false},
- {Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "x86", NativeBridgeRelativePath: "arm", HostCross: false},
- }
}),
+ android.PrepareForNativeBridgeEnabled,
android.FixtureMergeMockFs(android.MockFS{
"external/avb/test/data/testkey_rsa4096.pem": nil,
"build/soong/fsgen/Android.bp": []byte(`
diff --git a/fsgen/fsgen_mutators.go b/fsgen/fsgen_mutators.go
index 0cc643e..f0a54db 100644
--- a/fsgen/fsgen_mutators.go
+++ b/fsgen/fsgen_mutators.go
@@ -150,6 +150,7 @@
},
"ramdisk": {},
"vendor_ramdisk": {},
+ "recovery": {},
},
fsDepsMutex: sync.Mutex{},
moduleToInstallationProps: map[string]installationProperties{},
@@ -161,6 +162,9 @@
(*fsGenState.fsDeps["product"])["system_other_avbpubkey"] = defaultDepCandidateProps(ctx.Config())
}
+ // Add common resources `prebuilt_res` module as dep of recovery partition
+ (*fsGenState.fsDeps["recovery"])[fmt.Sprintf("recovery-resources-common-%s", getDpi(ctx))] = defaultDepCandidateProps(ctx.Config())
+
return &fsGenState
}).(*FsGenState)
}
diff --git a/fsgen/prebuilt_etc_modules_gen.go b/fsgen/prebuilt_etc_modules_gen.go
index efbc462..e028b1d 100644
--- a/fsgen/prebuilt_etc_modules_gen.go
+++ b/fsgen/prebuilt_etc_modules_gen.go
@@ -36,6 +36,7 @@
system_ext map[string][]srcBaseFileInstallBaseFileTuple
product map[string][]srcBaseFileInstallBaseFileTuple
vendor map[string][]srcBaseFileInstallBaseFileTuple
+ recovery map[string][]srcBaseFileInstallBaseFileTuple
}
func newPrebuiltSrcGroupByInstallPartition() *prebuiltSrcGroupByInstallPartition {
@@ -44,6 +45,7 @@
system_ext: map[string][]srcBaseFileInstallBaseFileTuple{},
product: map[string][]srcBaseFileInstallBaseFileTuple{},
vendor: map[string][]srcBaseFileInstallBaseFileTuple{},
+ recovery: map[string][]srcBaseFileInstallBaseFileTuple{},
}
}
@@ -73,6 +75,8 @@
srcMap = srcGroup.product
case "vendor":
srcMap = srcGroup.vendor
+ case "recovery":
+ srcMap = srcGroup.recovery
}
if srcMap != nil {
srcMap[relativeInstallDir] = append(srcMap[relativeInstallDir], srcBaseFileInstallBaseFileTuple{
@@ -128,6 +132,7 @@
// System is intentionally added at the last to consider the scenarios where
// non-system partitions are installed as part of the system partition
partitionToInstallPathList := []partitionToInstallPath{
+ {name: "recovery", installPath: "recovery/root"},
{name: "vendor", installPath: ctx.DeviceConfig().VendorPath()},
{name: "product", installPath: ctx.DeviceConfig().ProductPath()},
{name: "system_ext", installPath: ctx.DeviceConfig().SystemExtPath()},
@@ -155,6 +160,8 @@
Soc_specific *bool
Product_specific *bool
System_ext_specific *bool
+ Recovery *bool
+ Ramdisk *bool
Srcs []string
Dsts []string
@@ -174,42 +181,52 @@
Relative_install_path *string
}
+// Split install_in_root to a separate struct as it is part of rootProperties instead of
+// properties
+type prebuiltInstallInRootProperties struct {
+ Install_in_root *bool
+}
+
var (
etcInstallPathToFactoryList = map[string]android.ModuleFactory{
- "": etc.PrebuiltRootFactory,
- "avb": etc.PrebuiltAvbFactory,
- "bin": etc.PrebuiltBinaryFactory,
- "bt_firmware": etc.PrebuiltBtFirmwareFactory,
- "cacerts": etc.PrebuiltEtcCaCertsFactory,
- "dsp": etc.PrebuiltDSPFactory,
- "etc": etc.PrebuiltEtcFactory,
- "etc/dsp": etc.PrebuiltDSPFactory,
- "etc/firmware": etc.PrebuiltFirmwareFactory,
- "firmware": etc.PrebuiltFirmwareFactory,
- "fonts": etc.PrebuiltFontFactory,
- "framework": etc.PrebuiltFrameworkFactory,
- "lib": etc.PrebuiltRenderScriptBitcodeFactory,
- "lib64": etc.PrebuiltRenderScriptBitcodeFactory,
- "lib/rfsa": etc.PrebuiltRFSAFactory,
- "media": etc.PrebuiltMediaFactory,
- "odm": etc.PrebuiltOdmFactory,
- "optee": etc.PrebuiltOpteeFactory,
- "overlay": etc.PrebuiltOverlayFactory,
- "priv-app": etc.PrebuiltPrivAppFactory,
- "res": etc.PrebuiltResFactory,
- "rfs": etc.PrebuiltRfsFactory,
- "tts": etc.PrebuiltVoicepackFactory,
- "tvconfig": etc.PrebuiltTvConfigFactory,
- "tvservice": etc.PrebuiltTvServiceFactory,
- "usr/share": etc.PrebuiltUserShareFactory,
- "usr/hyphen-data": etc.PrebuiltUserHyphenDataFactory,
- "usr/keylayout": etc.PrebuiltUserKeyLayoutFactory,
- "usr/keychars": etc.PrebuiltUserKeyCharsFactory,
- "usr/srec": etc.PrebuiltUserSrecFactory,
- "usr/idc": etc.PrebuiltUserIdcFactory,
- "vendor_dlkm": etc.PrebuiltVendorDlkmFactory,
- "wallpaper": etc.PrebuiltWallpaperFactory,
- "wlc_upt": etc.PrebuiltWlcUptFactory,
+ "": etc.PrebuiltRootFactory,
+ "avb": etc.PrebuiltAvbFactory,
+ "bin": etc.PrebuiltBinaryFactory,
+ "bt_firmware": etc.PrebuiltBtFirmwareFactory,
+ "cacerts": etc.PrebuiltEtcCaCertsFactory,
+ "dsp": etc.PrebuiltDSPFactory,
+ "etc": etc.PrebuiltEtcFactory,
+ "etc/dsp": etc.PrebuiltDSPFactory,
+ "etc/firmware": etc.PrebuiltFirmwareFactory,
+ "firmware": etc.PrebuiltFirmwareFactory,
+ "first_stage_ramdisk": etc.PrebuiltFirstStageRamdiskFactory,
+ "fonts": etc.PrebuiltFontFactory,
+ "framework": etc.PrebuiltFrameworkFactory,
+ "lib": etc.PrebuiltRenderScriptBitcodeFactory,
+ "lib64": etc.PrebuiltRenderScriptBitcodeFactory,
+ "lib/rfsa": etc.PrebuiltRFSAFactory,
+ "media": etc.PrebuiltMediaFactory,
+ "odm": etc.PrebuiltOdmFactory,
+ "optee": etc.PrebuiltOpteeFactory,
+ "overlay": etc.PrebuiltOverlayFactory,
+ "priv-app": etc.PrebuiltPrivAppFactory,
+ "sbin": etc.PrebuiltSbinFactory,
+ "system": etc.PrebuiltSystemFactory,
+ "res": etc.PrebuiltResFactory,
+ "rfs": etc.PrebuiltRfsFactory,
+ "tts": etc.PrebuiltVoicepackFactory,
+ "tvconfig": etc.PrebuiltTvConfigFactory,
+ "tvservice": etc.PrebuiltTvServiceFactory,
+ "usr/share": etc.PrebuiltUserShareFactory,
+ "usr/hyphen-data": etc.PrebuiltUserHyphenDataFactory,
+ "usr/keylayout": etc.PrebuiltUserKeyLayoutFactory,
+ "usr/keychars": etc.PrebuiltUserKeyCharsFactory,
+ "usr/srec": etc.PrebuiltUserSrecFactory,
+ "usr/idc": etc.PrebuiltUserIdcFactory,
+ "vendor": etc.PrebuiltVendorFactory,
+ "vendor_dlkm": etc.PrebuiltVendorDlkmFactory,
+ "wallpaper": etc.PrebuiltWallpaperFactory,
+ "wlc_upt": etc.PrebuiltWlcUptFactory,
}
)
@@ -242,7 +259,7 @@
return ret, maxLen
}
-func prebuiltEtcModuleProps(moduleName, partition string) prebuiltModuleProperties {
+func prebuiltEtcModuleProps(ctx android.LoadHookContext, moduleName, partition, destDir string) prebuiltModuleProperties {
moduleProps := prebuiltModuleProperties{}
moduleProps.Name = proptools.StringPtr(moduleName)
@@ -254,6 +271,13 @@
moduleProps.Product_specific = proptools.BoolPtr(true)
case "vendor":
moduleProps.Soc_specific = proptools.BoolPtr(true)
+ case "recovery":
+ // To match the logic in modulePartition() in android/paths.go
+ if ctx.DeviceConfig().BoardUsesRecoveryAsBoot() && strings.HasPrefix(destDir, "first_stage_ramdisk") {
+ moduleProps.Ramdisk = proptools.BoolPtr(true)
+ } else {
+ moduleProps.Recovery = proptools.BoolPtr(true)
+ }
}
moduleProps.No_full_install = proptools.BoolPtr(true)
@@ -287,7 +311,7 @@
}
moduleName := generatedPrebuiltEtcModuleName(partition, srcDir, destDir, fileIndex)
- moduleProps := prebuiltEtcModuleProps(moduleName, partition)
+ moduleProps := prebuiltEtcModuleProps(ctx, moduleName, partition, destDir)
modulePropsPtr := &moduleProps
propsList := []interface{}{modulePropsPtr}
@@ -301,6 +325,16 @@
installBaseFiles = append(installBaseFiles, tuple.installBaseFile)
}
+ // Recovery partition-installed modules are installed to `recovery/root/system` by
+ // default (See modulePartition() in android/paths.go). If the destination file
+ // directory is not `recovery/root/system/...`, it should set install_in_root to true
+ // to prevent being installed in `recovery/root/system`.
+ if partition == "recovery" && !strings.HasPrefix(destDir, "system") {
+ propsList = append(propsList, &prebuiltInstallInRootProperties{
+ Install_in_root: proptools.BoolPtr(true),
+ })
+ }
+
// Set appropriate srcs, dsts, and releative_install_path based on
// the source and install file names
if allCopyFileNamesUnchanged {
@@ -346,6 +380,7 @@
ret = append(ret, createPrebuiltEtcModulesForPartition(ctx, "system_ext", srcDir, groupedSource.system_ext)...)
ret = append(ret, createPrebuiltEtcModulesForPartition(ctx, "product", srcDir, groupedSource.product)...)
ret = append(ret, createPrebuiltEtcModulesForPartition(ctx, "vendor", srcDir, groupedSource.vendor)...)
+ ret = append(ret, createPrebuiltEtcModulesForPartition(ctx, "recovery", srcDir, groupedSource.recovery)...)
}
return ret
diff --git a/fsgen/util.go b/fsgen/util.go
new file mode 100644
index 0000000..9ab3ad8
--- /dev/null
+++ b/fsgen/util.go
@@ -0,0 +1,60 @@
+// 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.
+
+package fsgen
+
+import (
+ "android/soong/android"
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+// Returns the appropriate dpi for recovery common resources selection. Replicates the logic in
+// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2536;drc=a6af369e71ded123734523ea640b97b70a557cb9
+func getDpi(ctx android.LoadHookContext) string {
+ recoveryDensity := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.TargetScreenDensity
+ if len(recoveryDensity) == 0 {
+ aaptPreferredConfig := ctx.Config().ProductAAPTPreferredConfig()
+ if len(aaptPreferredConfig) > 0 {
+ recoveryDensity = aaptPreferredConfig
+ } else {
+ recoveryDensity = "mdpi"
+ }
+ }
+ if !android.InList(recoveryDensity, []string{"xxxhdpi", "xxhdpi", "xhdpi", "hdpi", "mdpi"}) {
+ recoveryDensity = strings.TrimSuffix(recoveryDensity, "dpi")
+ dpiInt, err := strconv.ParseInt(recoveryDensity, 10, 64)
+ if err != nil {
+ panic(fmt.Sprintf("Error in parsing recoveryDensity: %s", err.Error()))
+ }
+ if dpiInt >= 560 {
+ recoveryDensity = "xxxhdpi"
+ } else if dpiInt >= 400 {
+ recoveryDensity = "xxhdpi"
+ } else if dpiInt >= 280 {
+ recoveryDensity = "xhdpi"
+ } else if dpiInt >= 200 {
+ recoveryDensity = "hdpi"
+ } else {
+ recoveryDensity = "mdpi"
+ }
+ }
+
+ if p := android.ExistentPathForSource(ctx, fmt.Sprintf("bootable/recovery/res-%s", recoveryDensity)); !p.Valid() {
+ recoveryDensity = "xhdpi"
+ }
+
+ return recoveryDensity
+}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 9d2dbc7..ac62b8d 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -230,8 +230,9 @@
shards int
// For nsjail tasks
- useNsjail bool
- dirSrcs android.DirectoryPaths
+ useNsjail bool
+ dirSrcs android.DirectoryPaths
+ keepGendir bool
}
func (g *Module) GeneratedSourceFiles() android.Paths {
@@ -487,6 +488,9 @@
name := "generator"
if task.useNsjail {
rule = android.NewRuleBuilder(pctx, ctx).Nsjail(task.genDir, android.PathForModuleOut(ctx, "nsjail_build_sandbox"))
+ if task.keepGendir {
+ rule.NsjailKeepGendir()
+ }
} else {
manifestName := "genrule.sbox.textproto"
if task.shards > 0 {
@@ -897,17 +901,24 @@
return nil
}
+ keepGendir := Bool(properties.Keep_gendir)
+ if keepGendir && !useNsjail {
+ ctx.PropertyErrorf("keep_gendir", "can't use keep_gendir if use_nsjail is false")
+ return nil
+ }
+
outs := make(android.WritablePaths, len(properties.Out))
for i, out := range properties.Out {
outs[i] = android.PathForModuleGen(ctx, out)
}
return []generateTask{{
- in: srcFiles,
- out: outs,
- genDir: android.PathForModuleGen(ctx),
- cmd: rawCommand,
- useNsjail: useNsjail,
- dirSrcs: dirSrcs,
+ in: srcFiles,
+ out: outs,
+ genDir: android.PathForModuleGen(ctx),
+ cmd: rawCommand,
+ useNsjail: useNsjail,
+ dirSrcs: dirSrcs,
+ keepGendir: keepGendir,
}}
}
@@ -928,6 +939,10 @@
// dir_srcs is limited only to Trusty build.
Dir_srcs []string `android:"path"`
+ // If set to true, $(genDir) is not truncated. Useful when this genrule can be incrementally
+ // built. Can be set only when use_nsjail is true.
+ Keep_gendir *bool
+
// names of the output files that will be generated
Out []string `android:"arch_variant"`
}
diff --git a/java/aar.go b/java/aar.go
index e0e642e..1e5c95a 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -588,14 +588,16 @@
}
}
- for _, dir := range overlayDirs {
- compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files,
- compileFlags, a.filterProduct(), opts.aconfigTextFiles).Paths()...)
- }
-
var compiledRro, compiledRroOverlay android.Paths
if opts.rroDirs != nil {
compiledRro, compiledRroOverlay = a.compileResInDir(ctx, *opts.rroDirs, compileFlags, opts.aconfigTextFiles)
+ } else {
+ // RRO enforcement is done based on module name. Compile the overlayDirs only if rroDirs is nil.
+ // This ensures that the autogenerated RROs do not compile the overlay dirs twice.
+ for _, dir := range overlayDirs {
+ compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files,
+ compileFlags, a.filterProduct(), opts.aconfigTextFiles).Paths()...)
+ }
}
var splitPackages android.WritablePaths
diff --git a/java/androidmk.go b/java/androidmk.go
index 2ad30b1..b6bab53 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -307,15 +307,11 @@
Disabled: true,
}}
}
- var required []string
- if proptools.Bool(app.appProperties.Generate_product_characteristics_rro) {
- required = []string{app.productCharacteristicsRROPackageName()}
- }
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "APPS",
OutputFile: android.OptionalPathForPath(app.outputFile),
Include: "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
- Required: required,
+ Required: app.requiredModuleNames,
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
// App module names can be overridden.
@@ -350,31 +346,6 @@
entries.SetBoolIfTrue("LOCAL_NO_STANDARD_LIBRARIES", true)
}
- filterRRO := func(filter overlayType) android.Paths {
- var paths android.Paths
- seen := make(map[android.Path]bool)
- for _, d := range app.rroDirsDepSet.ToList() {
- if d.overlayType == filter {
- if seen[d.path] {
- continue
- }
- seen[d.path] = true
- paths = append(paths, d.path)
- }
- }
- // Reverse the order, Soong stores rroDirs in aapt2 order (low to high priority), but Make
- // expects it in LOCAL_RESOURCE_DIRS order (high to low priority).
- return android.ReversePaths(paths)
- }
- deviceRRODirs := filterRRO(device)
- if len(deviceRRODirs) > 0 {
- entries.AddStrings("LOCAL_SOONG_DEVICE_RRO_DIRS", deviceRRODirs.Strings()...)
- }
- productRRODirs := filterRRO(product)
- if len(productRRODirs) > 0 {
- entries.AddStrings("LOCAL_SOONG_PRODUCT_RRO_DIRS", productRRODirs.Strings()...)
- }
-
entries.SetBoolIfTrue("LOCAL_EXPORT_PACKAGE_RESOURCES", Bool(app.appProperties.Export_package_resources))
entries.SetPath("LOCAL_FULL_MANIFEST_FILE", app.manifestPath)
@@ -437,7 +408,7 @@
Include: "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- entries.SetString("LOCAL_CERTIFICATE", "presigned") // The apk will be signed by soong
+ entries.SetString("LOCAL_CERTIFICATE", "PRESIGNED") // The apk will be signed by soong
},
},
}}
diff --git a/java/app.go b/java/app.go
index 832a083..8739d1c 100644
--- a/java/app.go
+++ b/java/app.go
@@ -223,6 +223,8 @@
javaApiUsedByOutputFile android.ModuleOutPath
privAppAllowlist android.OptionalPath
+
+ requiredModuleNames []string
}
func (a *AndroidApp) IsInstallable() bool {
@@ -421,6 +423,24 @@
TestHelperApp: false,
EmbeddedJNILibs: embeddedJniLibs,
})
+
+ a.requiredModuleNames = a.getRequiredModuleNames(ctx)
+}
+
+func (a *AndroidApp) getRequiredModuleNames(ctx android.ModuleContext) []string {
+ var required []string
+ if proptools.Bool(a.appProperties.Generate_product_characteristics_rro) {
+ required = []string{a.productCharacteristicsRROPackageName()}
+ }
+ // Install the vendor overlay variant if this app is installed.
+ if len(filterRRO(a.rroDirsDepSet, device)) > 0 {
+ required = append(required, AutogeneratedRroModuleName(ctx, ctx.Module().Name(), "vendor"))
+ }
+ // Install the product overlay variant if this app is installed.
+ if len(filterRRO(a.rroDirsDepSet, product)) > 0 {
+ required = append(required, AutogeneratedRroModuleName(ctx, ctx.Module().Name(), "product"))
+ }
+ return required
}
func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) {
@@ -1083,10 +1103,11 @@
}
jniLib, prebuiltJniPackages := collectJniDeps(ctx, shouldCollectRecursiveNativeDeps,
checkNativeSdkVersion, func(parent, child android.Module) bool {
+ apkInApex := ctx.Module().(android.ApexModule).NotInPlatform()
childLinkable, _ := child.(cc.LinkableInterface)
parentLinkable, _ := parent.(cc.LinkableInterface)
useStubsOfDep := childLinkable.IsStubs()
- if parent.(android.ApexModule).NotInPlatform() && parentLinkable != nil {
+ if apkInApex && parentLinkable != nil {
// APK-in-APEX
// If the parent is a linkable interface, use stubs if the dependency edge crosses an apex boundary.
useStubsOfDep = useStubsOfDep || (childLinkable.HasStubsVariants() && cc.ShouldUseStubForApex(ctx, parent, child))
@@ -1387,11 +1408,82 @@
}
}
ctx.CreateModule(RuntimeResourceOverlayFactory, &rroProperties)
+
+ })
+
+ module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
+ createInternalRuntimeOverlays(ctx, module.ModuleBase)
})
return module
}
+func AutogeneratedRroModuleName(ctx android.EarlyModuleContext, moduleName, partition string) string {
+ return fmt.Sprintf("%s__%s__auto_generated_rro_%s", moduleName, ctx.Config().DeviceProduct(), partition)
+}
+
+type createModuleContext interface {
+ android.EarlyModuleContext
+ CreateModule(android.ModuleFactory, ...interface{}) android.Module
+}
+
+func createInternalRuntimeOverlays(ctx createModuleContext, a android.ModuleBase) {
+ if !ctx.Config().HasDeviceProduct() {
+ return
+ }
+ // vendor
+ vendorOverlayProps := struct {
+ Name *string
+ Base *string
+ Vendor *bool
+ Product_specific *bool
+ System_ext_specific *bool
+ Manifest *string
+ Sdk_version *string
+ Compile_multilib *string
+ Enabled proptools.Configurable[bool]
+ }{
+ Name: proptools.StringPtr(AutogeneratedRroModuleName(ctx, a.Name(), "vendor")),
+ Base: proptools.StringPtr(a.Name()),
+ Vendor: proptools.BoolPtr(true),
+ Product_specific: proptools.BoolPtr(false),
+ System_ext_specific: proptools.BoolPtr(false),
+ Manifest: proptools.StringPtr(":" + a.Name() + "{.manifest.xml}"),
+ Sdk_version: proptools.StringPtr("current"),
+ Compile_multilib: proptools.StringPtr("first"),
+ Enabled: a.EnabledProperty().Clone(),
+ }
+ ctx.CreateModule(AutogenRuntimeResourceOverlayFactory, &vendorOverlayProps)
+
+ // product
+ productOverlayProps := struct {
+ Name *string
+ Base *string
+ Vendor *bool
+ Proprietary *bool
+ Soc_specific *bool
+ Product_specific *bool
+ System_ext_specific *bool
+ Manifest *string
+ Sdk_version *string
+ Compile_multilib *string
+ Enabled proptools.Configurable[bool]
+ }{
+ Name: proptools.StringPtr(AutogeneratedRroModuleName(ctx, a.Name(), "product")),
+ Base: proptools.StringPtr(a.Name()),
+ Vendor: proptools.BoolPtr(false),
+ Proprietary: proptools.BoolPtr(false),
+ Soc_specific: proptools.BoolPtr(false),
+ Product_specific: proptools.BoolPtr(true),
+ System_ext_specific: proptools.BoolPtr(false),
+ Manifest: proptools.StringPtr(":" + a.Name() + "{.manifest.xml}"),
+ Sdk_version: proptools.StringPtr("current"),
+ Compile_multilib: proptools.StringPtr("first"),
+ Enabled: a.EnabledProperty().Clone(),
+ }
+ ctx.CreateModule(AutogenRuntimeResourceOverlayFactory, &productOverlayProps)
+}
+
// A dictionary of values to be overridden in the manifest.
type Manifest_values struct {
// Overrides the value of package_name in the manifest
@@ -1702,6 +1794,10 @@
android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibCommon)
android.InitOverrideModule(m)
+ android.AddLoadHook(m, func(ctx android.LoadHookContext) {
+ createInternalRuntimeOverlays(ctx, m.ModuleBase)
+ })
+
return m
}
diff --git a/java/app_test.go b/java/app_test.go
index 3d83ea1..61b718d 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -4727,3 +4727,74 @@
"out/soong/.intermediates/foo/android_common/aapt2/res/values_strings.(test.package.flag1).arsc.flat",
)
}
+
+func TestAutogeneratedStaticRro(t *testing.T) {
+ t.Parallel()
+ bp := `
+android_app {
+ name: "foo",
+ srcs: ["foo.java"],
+ platform_apis: true,
+}
+override_android_app {
+ name: "override_foo",
+ base: "foo",
+}
+`
+ testCases := []struct {
+ desc string
+ preparer android.FixturePreparer
+ overlayApkExpected bool
+ }{
+ {
+ desc: "No DEVICE_PACKAGE_OVERLAYS, no overlay .apk file",
+ overlayApkExpected: false,
+ },
+ {
+ desc: "DEVICE_PACKAGE_OVERLAYS exists, but the directory is empty",
+ overlayApkExpected: false,
+ preparer: android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.DeviceResourceOverlays = []string{"device/company/test_product"}
+ }),
+ },
+ {
+ desc: "DEVICE_PACKAGE_OVERLAYS exists, directory is non-empty, but does not contain a matching resource dir",
+ overlayApkExpected: false,
+ preparer: android.GroupFixturePreparers(
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.DeviceResourceOverlays = []string{"device/company/test_product"}
+ }),
+ android.MockFS{
+ "res/foo.xml": nil,
+ "device/company/test_product/different_res/foo.xml": nil, // different dir
+ }.AddToFixture(),
+ ),
+ },
+ {
+ desc: "DEVICE_PACKAGE_OVERLAYS and the directory contain a matching resource dir",
+ overlayApkExpected: true,
+ preparer: android.GroupFixturePreparers(
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.DeviceResourceOverlays = []string{"device/company/test_product"}
+ }),
+ android.MockFS{
+ "res/foo.xml": nil,
+ "device/company/test_product/res/foo.xml": nil,
+ }.AddToFixture(),
+ ),
+ },
+ }
+ for _, tc := range testCases {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.EnforceRROTargets = []string{"*"}
+ }),
+ android.OptionalFixturePreparer(tc.preparer),
+ ).RunTestWithBp(t, bp)
+ vendorOverlayApk := result.ModuleForTests("foo__test_product__auto_generated_rro_vendor", "android_arm64_armv8-a").MaybeOutput("foo__test_product__auto_generated_rro_vendor.apk")
+ android.AssertBoolEquals(t, tc.desc, tc.overlayApkExpected, vendorOverlayApk.Rule != nil)
+ overrideVendorOverlayApk := result.ModuleForTests("override_foo__test_product__auto_generated_rro_vendor", "android_arm64_armv8-a").MaybeOutput("override_foo__test_product__auto_generated_rro_vendor.apk")
+ android.AssertBoolEquals(t, tc.desc, tc.overlayApkExpected, overrideVendorOverlayApk.Rule != nil)
+ }
+}
diff --git a/java/base.go b/java/base.go
index 3bf2e23..c0ac4ab 100644
--- a/java/base.go
+++ b/java/base.go
@@ -612,21 +612,24 @@
return proptools.Bool(j.properties.Is_stubs_module)
}
-func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error {
- sdkVersion := j.SdkVersion(ctx)
- if sdkVersion.Stable() {
- return nil
- }
- if sdkVersion.Kind == android.SdkCorePlatform {
- if useLegacyCorePlatformApi(ctx, j.BaseModuleName()) {
- return fmt.Errorf("non stable SDK %v - uses legacy core platform", sdkVersion)
- } else {
- // Treat stable core platform as stable.
+func CheckStableSdkVersion(ctx android.BaseModuleContext, module android.ModuleProxy) error {
+ if info, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
+ if info.SdkVersion.Stable() {
return nil
}
- } else {
- return fmt.Errorf("non stable SDK %v", sdkVersion)
+ if info.SdkVersion.Kind == android.SdkCorePlatform {
+ if useLegacyCorePlatformApi(ctx, android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey).BaseModuleName) {
+ return fmt.Errorf("non stable SDK %v - uses legacy core platform", info.SdkVersion)
+ } else {
+ // Treat stable core platform as stable.
+ return nil
+ }
+ } else {
+ return fmt.Errorf("non stable SDK %v", info.SdkVersion)
+ }
}
+
+ return nil
}
// checkSdkVersions enforces restrictions around SDK dependencies.
@@ -1300,6 +1303,7 @@
ExportedPluginDisableTurbine: j.exportedDisableTurbine,
StubsLinkType: j.stubsLinkType,
AconfigIntermediateCacheOutputPaths: deps.aconfigProtoFiles,
+ SdkVersion: j.SdkVersion(ctx),
})
j.outputFile = j.headerJarFile
@@ -1929,6 +1933,7 @@
JacocoReportClassesFile: j.jacocoReportClassesFile,
StubsLinkType: j.stubsLinkType,
AconfigIntermediateCacheOutputPaths: j.aconfigCacheFiles,
+ SdkVersion: j.SdkVersion(ctx),
})
// Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
diff --git a/java/java.go b/java/java.go
index 260d336..ee112c1 100644
--- a/java/java.go
+++ b/java/java.go
@@ -326,6 +326,8 @@
// AconfigIntermediateCacheOutputPaths is a path to the cache files collected from the
// java_aconfig_library modules that are statically linked to this module.
AconfigIntermediateCacheOutputPaths android.Paths
+
+ SdkVersion android.SdkSpec
}
var JavaInfoProvider = blueprint.NewProvider[*JavaInfo]()
diff --git a/java/rro_test.go b/java/rro_test.go
index 4d79130..4d58bb4 100644
--- a/java/rro_test.go
+++ b/java/rro_test.go
@@ -255,103 +255,6 @@
}
}
-func TestEnforceRRO_propagatesToDependencies(t *testing.T) {
- testCases := []struct {
- name string
- enforceRROTargets []string
- rroDirs map[string][]string
- }{
- {
- name: "no RRO",
- enforceRROTargets: nil,
- rroDirs: map[string][]string{
- "foo": nil,
- "bar": nil,
- },
- },
- {
- name: "enforce RRO on all",
- enforceRROTargets: []string{"*"},
- rroDirs: map[string][]string{
- "foo": {"product/vendor/blah/overlay/lib2/res"},
- "bar": {"product/vendor/blah/overlay/lib2/res"},
- },
- },
- {
- name: "enforce RRO on foo",
- enforceRROTargets: []string{"foo"},
- rroDirs: map[string][]string{
- "foo": {"product/vendor/blah/overlay/lib2/res"},
- "bar": nil,
- },
- },
- }
-
- productResourceOverlays := []string{
- "product/vendor/blah/overlay",
- }
-
- fs := android.MockFS{
- "lib2/res/values/strings.xml": nil,
- "product/vendor/blah/overlay/lib2/res/values/strings.xml": nil,
- }
-
- bp := `
- android_app {
- name: "foo",
- sdk_version: "current",
- resource_dirs: [],
- static_libs: ["lib"],
- }
-
- android_app {
- name: "bar",
- sdk_version: "current",
- resource_dirs: [],
- static_libs: ["lib"],
- }
-
- android_library {
- name: "lib",
- sdk_version: "current",
- resource_dirs: [],
- static_libs: ["lib2"],
- }
-
- android_library {
- name: "lib2",
- sdk_version: "current",
- resource_dirs: ["lib2/res"],
- }
- `
-
- for _, testCase := range testCases {
- t.Run(testCase.name, func(t *testing.T) {
- result := android.GroupFixturePreparers(
- PrepareForTestWithJavaDefaultModules,
- fs.AddToFixture(),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.ProductResourceOverlays = productResourceOverlays
- if testCase.enforceRROTargets != nil {
- variables.EnforceRROTargets = testCase.enforceRROTargets
- }
- }),
- ).RunTestWithBp(t, bp)
-
- modules := []string{"foo", "bar"}
- for _, moduleName := range modules {
- module := result.ModuleForTests(moduleName, "android_common")
- mkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, module.Module())[0]
- actualRRODirs := mkEntries.EntryMap["LOCAL_SOONG_PRODUCT_RRO_DIRS"]
- if !reflect.DeepEqual(actualRRODirs, testCase.rroDirs[moduleName]) {
- t.Errorf("exected %s LOCAL_SOONG_PRODUCT_RRO_DIRS entry: %v\ngot:%q",
- moduleName, testCase.rroDirs[moduleName], actualRRODirs)
- }
- }
- })
- }
-}
-
func TestRuntimeResourceOverlayPartition(t *testing.T) {
bp := `
runtime_resource_overlay {