Snap for 12755599 from 6cba6573f7ff997a14fc05fda064c2855fb3669c to 25Q1-release
Change-Id: I61f5be5bed24a0d343bebea5f473c957dddbc7c6
diff --git a/android/variable.go b/android/variable.go
index 3829f48..e012103 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -582,6 +582,11 @@
BoardAvbRollbackIndexLocation string `json:",omitempty"`
}
+type BoardSuperPartitionGroupProps struct {
+ GroupSize string `json:",omitempty"`
+ PartitionList []string `json:",omitempty"`
+}
+
type ChainedAvbPartitionProps struct {
Partitions []string `json:",omitempty"`
Key string `json:",omitempty"`
@@ -635,6 +640,18 @@
InternalBootconfig []string `json:",omitempty"`
InternalBootconfigFile string `json:",omitempty"`
+ // Super image stuff
+ ProductUseDynamicPartitions bool `json:",omitempty"`
+ ProductRetrofitDynamicPartitions bool `json:",omitempty"`
+ ProductBuildSuperPartition bool `json:",omitempty"`
+ BoardSuperPartitionSize string `json:",omitempty"`
+ BoardSuperPartitionMetadataDevice string `json:",omitempty"`
+ BoardSuperPartitionBlockDevices []string `json:",omitempty"`
+ BoardSuperPartitionGroups map[string]BoardSuperPartitionGroupProps `json:",omitempty"`
+ ProductVirtualAbOta bool `json:",omitempty"`
+ ProductVirtualAbOtaRetrofit bool `json:",omitempty"`
+ AbOtaUpdater bool `json:",omitempty"`
+
// Avb (android verified boot) stuff
BoardAvbEnable bool `json:",omitempty"`
BoardAvbAlgorithm string `json:",omitempty"`
diff --git a/filesystem/Android.bp b/filesystem/Android.bp
index bbb3ea7..127faa7 100644
--- a/filesystem/Android.bp
+++ b/filesystem/Android.bp
@@ -25,6 +25,7 @@
"fsverity_metadata.go",
"logical_partition.go",
"raw_binary.go",
+ "super_image.go",
"system_image.go",
"vbmeta.go",
"testing.go",
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index fbc8089..d49ac1f 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -53,6 +53,12 @@
})
}
+// Remember to add referenced files to implicits!
+var textFileProcessorRule = pctx.AndroidStaticRule("text_file_processing", blueprint.RuleParams{
+ Command: "build/soong/scripts/text_file_processor.py $in $out",
+ CommandDeps: []string{"build/soong/scripts/text_file_processor.py"},
+})
+
type filesystem struct {
android.ModuleBase
android.PackagingBase
@@ -107,6 +113,9 @@
// avbtool. Default used by avbtool is sha1.
Avb_hash_algorithm *string
+ // Whether or not to use forward-error-correction codes when signing with AVB. Defaults to true.
+ Use_fec *bool
+
// The index used to prevent rollback of the image. Only used if use_avb is true.
Rollback_index *int64
@@ -563,11 +572,21 @@
FlagWithArg("--out_system=", rootDir.String()+"/system")
propFile, toolDeps := f.buildPropFile(ctx)
+
+ // Most of the time, if build_image were to call a host tool, it accepts the path to the
+ // host tool in a field in the prop file. However, it doesn't have that option for fec, which
+ // it expects to just be on the PATH. Add fec to the PATH.
+ fec := ctx.Config().HostToolPath(ctx, "fec")
+ pathToolDirs := []string{filepath.Dir(fec.String())}
+
output := android.PathForModuleOut(ctx, f.installFileName())
- builder.Command().BuiltTool("build_image").
+ builder.Command().
+ Textf("PATH=%s:$PATH", strings.Join(pathToolDirs, ":")).
+ BuiltTool("build_image").
Text(rootDir.String()). // input directory
Input(propFile).
Implicits(toolDeps).
+ Implicit(fec).
Output(output).
Text(rootDir.String()) // directory where to find fs_config_files|dirs
@@ -634,10 +653,15 @@
addPath("avb_avbtool", ctx.Config().HostToolPath(ctx, "avbtool"))
algorithm := proptools.StringDefault(f.properties.Avb_algorithm, "SHA256_RSA4096")
addStr("avb_algorithm", algorithm)
- key := android.PathForModuleSrc(ctx, proptools.String(f.properties.Avb_private_key))
- addPath("avb_key_path", key)
+ if f.properties.Avb_private_key != nil {
+ key := android.PathForModuleSrc(ctx, *f.properties.Avb_private_key)
+ addPath("avb_key_path", key)
+ }
addStr("partition_name", f.partitionName())
- avb_add_hashtree_footer_args := "--do_not_generate_fec"
+ avb_add_hashtree_footer_args := ""
+ if !proptools.BoolDefault(f.properties.Use_fec, true) {
+ avb_add_hashtree_footer_args += " --do_not_generate_fec"
+ }
if hashAlgorithm := proptools.String(f.properties.Avb_hash_algorithm); hashAlgorithm != "" {
avb_add_hashtree_footer_args += " --hash_algorithm " + hashAlgorithm
}
@@ -648,9 +672,9 @@
}
avb_add_hashtree_footer_args += " --rollback_index " + strconv.Itoa(rollbackIndex)
}
- securityPatchKey := "com.android.build." + f.partitionName() + ".security_patch"
- securityPatchValue := ctx.Config().PlatformSecurityPatch()
- avb_add_hashtree_footer_args += " --prop " + securityPatchKey + ":" + securityPatchValue
+ avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.os_version:%s", f.partitionName(), ctx.Config().PlatformVersionLastStable())
+ avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.fingerprint:{CONTENTS_OF:%s}", f.partitionName(), ctx.Config().BuildFingerprintFile(ctx))
+ avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.security_patch:%s", f.partitionName(), ctx.Config().PlatformSecurityPatch())
addStr("avb_add_hashtree_footer_args", avb_add_hashtree_footer_args)
addStr("avb_salt", f.salt())
}
@@ -694,8 +718,15 @@
}
f.checkFsTypePropertyError(ctx, fst, fsTypeStr(fst))
+ propFilePreProcessing := android.PathForModuleOut(ctx, "prop_pre_processing")
+ android.WriteFileRuleVerbatim(ctx, propFilePreProcessing, propFileString.String())
propFile := android.PathForModuleOut(ctx, "prop")
- android.WriteFileRuleVerbatim(ctx, propFile, propFileString.String())
+ ctx.Build(pctx, android.BuildParams{
+ Rule: textFileProcessorRule,
+ Input: propFilePreProcessing,
+ Output: propFile,
+ Implicit: ctx.Config().BuildFingerprintFile(ctx),
+ })
return propFile, deps
}
@@ -981,7 +1012,7 @@
ctx.WalkDeps(func(child, parent android.Module) bool {
for _, ps := range android.OtherModuleProviderOrDefault(
ctx, child, android.InstallFilesProvider).PackagingSpecs {
- if _, ok := deps[ps.RelPathInPackage()]; ok {
+ if _, ok := deps[ps.RelPathInPackage()]; ok && ps.Partition() == f.PartitionType() {
modulesInPackageByModule[child] = true
modulesInPackageByName[child.Name()] = true
return true
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index 72a5211..86496eb 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -593,7 +593,7 @@
`)
partition := result.ModuleForTests("erofs_partition", "android_common")
- buildImageConfig := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("prop"))
+ buildImageConfig := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("prop_pre_processing"))
android.AssertStringDoesContain(t, "erofs fs type", buildImageConfig, "fs_type=erofs")
android.AssertStringDoesContain(t, "erofs fs type compress algorithm", buildImageConfig, "erofs_default_compressor=lz4hc,9")
android.AssertStringDoesContain(t, "erofs fs type compress hint", buildImageConfig, "erofs_default_compress_hints=compress_hints.txt")
@@ -609,7 +609,7 @@
`)
partition := result.ModuleForTests("f2fs_partition", "android_common")
- buildImageConfig := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("prop"))
+ buildImageConfig := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("prop_pre_processing"))
android.AssertStringDoesContain(t, "f2fs fs type", buildImageConfig, "fs_type=f2fs")
android.AssertStringDoesContain(t, "f2fs fs type sparse", buildImageConfig, "f2fs_sparse_flag=-S")
}
diff --git a/filesystem/super_image.go b/filesystem/super_image.go
new file mode 100644
index 0000000..1583c0b
--- /dev/null
+++ b/filesystem/super_image.go
@@ -0,0 +1,234 @@
+// 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 filesystem
+
+import (
+ "fmt"
+ "path/filepath"
+ "strconv"
+ "strings"
+
+ "android/soong/android"
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+func init() {
+ android.RegisterModuleType("super_image", SuperImageFactory)
+}
+
+type superImage struct {
+ android.ModuleBase
+
+ properties SuperImageProperties
+ partitionProps SuperImagePartitionNameProperties
+
+ installDir android.InstallPath
+}
+
+type SuperImageProperties struct {
+ // the size of the super partition
+ Size *int64
+ // the block device where metadata for dynamic partitions is stored
+ Metadata_device *string
+ // the super partition block device list
+ Block_devices *string
+ // whether A/B updater is used
+ Ab_update *bool
+ // whether dynamic partitions is enabled on devices that were launched without this support
+ Retrofit *bool
+ // whether virtual A/B seamless update is enabled
+ Virtual_ab *bool
+ // whether retrofitting virtual A/B seamless update is enabled
+ Virtual_ab_retrofit *bool
+ // whether the output is a sparse image
+ Sparse *bool
+ // information about how partitions within the super partition are grouped together
+ Partition_groups []PartitionGroupsInfo
+ // whether dynamic partitions is used
+ Use_dynamic_partitions *bool
+}
+
+type PartitionGroupsInfo struct {
+ Name string
+ GroupSize string
+ PartitionList []string
+}
+
+type SuperImagePartitionNameProperties struct {
+ // Name of the System partition filesystem module
+ System_partition *string
+ // Name of the System_ext partition filesystem module
+ System_ext_partition *string
+ // Name of the System_dlkm partition filesystem module
+ System_dlkm_partition *string
+ // Name of the System_other partition filesystem module
+ System_other_partition *string
+ // Name of the Product partition filesystem module
+ Product_partition *string
+ // Name of the Vendor partition filesystem module
+ Vendor_partition *string
+ // Name of the Vendor_dlkm partition filesystem module
+ Vendor_dlkm_partition *string
+ // Name of the Odm partition filesystem module
+ Odm_partition *string
+ // Name of the Odm_dlkm partition filesystem module
+ Odm_dlkm_partition *string
+}
+
+func SuperImageFactory() android.Module {
+ module := &superImage{}
+ module.AddProperties(&module.properties, &module.partitionProps)
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ return module
+}
+
+type superImageDepTagType struct {
+ blueprint.BaseDependencyTag
+}
+
+var superImageDepTag superImageDepTagType
+
+func (s *superImage) DepsMutator(ctx android.BottomUpMutatorContext) {
+ addDependencyIfDefined := func(dep *string) {
+ if dep != nil {
+ ctx.AddDependency(ctx.Module(), superImageDepTag, proptools.String(dep))
+ }
+ }
+
+ addDependencyIfDefined(s.partitionProps.System_partition)
+ addDependencyIfDefined(s.partitionProps.System_ext_partition)
+ addDependencyIfDefined(s.partitionProps.System_dlkm_partition)
+ addDependencyIfDefined(s.partitionProps.System_other_partition)
+ addDependencyIfDefined(s.partitionProps.Product_partition)
+ addDependencyIfDefined(s.partitionProps.Vendor_partition)
+ addDependencyIfDefined(s.partitionProps.Vendor_dlkm_partition)
+ addDependencyIfDefined(s.partitionProps.Odm_partition)
+ addDependencyIfDefined(s.partitionProps.Odm_dlkm_partition)
+}
+
+func (s *superImage) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ miscInfo, deps := s.buildMiscInfo(ctx)
+ builder := android.NewRuleBuilder(pctx, ctx)
+ output := android.PathForModuleOut(ctx, s.installFileName())
+ lpMake := ctx.Config().HostToolPath(ctx, "lpmake")
+ lpMakeDir := filepath.Dir(lpMake.String())
+ deps = append(deps, lpMake)
+ builder.Command().Textf("PATH=%s:\\$PATH", lpMakeDir).
+ BuiltTool("build_super_image").
+ Text("-v").
+ Input(miscInfo).
+ Implicits(deps).
+ Output(output)
+ builder.Build("build_super_image", fmt.Sprintf("Creating super image %s", s.BaseModuleName()))
+ ctx.SetOutputFiles([]android.Path{output}, "")
+}
+
+func (s *superImage) installFileName() string {
+ return s.BaseModuleName() + ".img"
+}
+
+func (s *superImage) buildMiscInfo(ctx android.ModuleContext) (android.Path, android.Paths) {
+ var miscInfoString strings.Builder
+ addStr := func(name string, value string) {
+ miscInfoString.WriteString(name)
+ miscInfoString.WriteRune('=')
+ miscInfoString.WriteString(value)
+ miscInfoString.WriteRune('\n')
+ }
+
+ addStr("use_dynamic_partitions", strconv.FormatBool(proptools.Bool(s.properties.Use_dynamic_partitions)))
+ addStr("dynamic_partition_retrofit", strconv.FormatBool(proptools.Bool(s.properties.Retrofit)))
+ addStr("lpmake", "lpmake")
+ addStr("super_metadata_device", proptools.String(s.properties.Metadata_device))
+ addStr("super_block_devices", proptools.String(s.properties.Block_devices))
+ addStr("super_super_device_size", strconv.Itoa(proptools.Int(s.properties.Size)))
+ var groups, partitionList []string
+ for _, groupInfo := range s.properties.Partition_groups {
+ groups = append(groups, groupInfo.Name)
+ partitionList = append(partitionList, groupInfo.PartitionList...)
+ addStr("super_"+groupInfo.Name+"_group_size", groupInfo.GroupSize)
+ addStr("super_"+groupInfo.Name+"_partition_list", strings.Join(groupInfo.PartitionList, " "))
+ }
+ addStr("super_partition_groups", strings.Join(groups, " "))
+ addStr("dynamic_partition_list", strings.Join(partitionList, " "))
+
+ addStr("virtual_ab", strconv.FormatBool(proptools.Bool(s.properties.Virtual_ab)))
+ addStr("virtual_ab_retrofit", strconv.FormatBool(proptools.Bool(s.properties.Virtual_ab_retrofit)))
+ addStr("ab_update", strconv.FormatBool(proptools.Bool(s.properties.Ab_update)))
+ addStr("build_non_sparse_super_partition", strconv.FormatBool(!proptools.Bool(s.properties.Sparse)))
+
+ partitionToImagePath := make(map[string]string)
+ nameToPartition := make(map[string]string)
+ var systemOtherPartitionNameNeeded string
+ addEntryToPartitionToName := func(p string, s *string) {
+ if proptools.String(s) != "" {
+ nameToPartition[*s] = p
+ }
+ }
+
+ // Build partitionToImagePath, because system partition may need system_other
+ // partition image path
+ for _, p := range partitionList {
+ if _, ok := nameToPartition[p]; ok {
+ continue
+ }
+ switch p {
+ case "system":
+ addEntryToPartitionToName(p, s.partitionProps.System_partition)
+ systemOtherPartitionNameNeeded = proptools.String(s.partitionProps.System_other_partition)
+ case "system_dlkm":
+ addEntryToPartitionToName(p, s.partitionProps.System_dlkm_partition)
+ case "system_ext":
+ addEntryToPartitionToName(p, s.partitionProps.System_ext_partition)
+ case "product":
+ addEntryToPartitionToName(p, s.partitionProps.Product_partition)
+ case "vendor":
+ addEntryToPartitionToName(p, s.partitionProps.Vendor_partition)
+ case "vendor_dlkm":
+ addEntryToPartitionToName(p, s.partitionProps.Vendor_dlkm_partition)
+ case "odm":
+ addEntryToPartitionToName(p, s.partitionProps.Odm_partition)
+ case "odm_dlkm":
+ addEntryToPartitionToName(p, s.partitionProps.Odm_dlkm_partition)
+ default:
+ ctx.ModuleErrorf("current partition %s not a super image supported partition", p)
+ }
+ }
+
+ var deps android.Paths
+ ctx.VisitDirectDeps(func(m android.Module) {
+ if p, ok := nameToPartition[m.Name()]; ok {
+ if output, ok := android.OtherModuleProvider(ctx, m, android.OutputFilesProvider); ok {
+ partitionToImagePath[p] = output.DefaultOutputFiles[0].String()
+ deps = append(deps, output.DefaultOutputFiles[0])
+ }
+ } else if systemOtherPartitionNameNeeded != "" && m.Name() == systemOtherPartitionNameNeeded {
+ if output, ok := android.OtherModuleProvider(ctx, m, android.OutputFilesProvider); ok {
+ partitionToImagePath["system_other"] = output.DefaultOutputFiles[0].String()
+ // TODO: add system_other to deps after it can be generated
+ // deps = append(deps, output.DefaultOutputFiles[0])
+ }
+ }
+ })
+
+ for _, p := range android.SortedKeys(partitionToImagePath) {
+ addStr(p+"_image", partitionToImagePath[p])
+ }
+
+ miscInfo := android.PathForModuleOut(ctx, "misc_info.txt")
+ android.WriteFileRule(ctx, miscInfo, miscInfoString.String())
+ return miscInfo, deps
+}
diff --git a/fsgen/Android.bp b/fsgen/Android.bp
index e8065f3..365d954 100644
--- a/fsgen/Android.bp
+++ b/fsgen/Android.bp
@@ -17,6 +17,7 @@
"filesystem_creator.go",
"fsgen_mutators.go",
"prebuilt_etc_modules_gen.go",
+ "super_img.go",
"util.go",
"vbmeta_partitions.go",
],
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index 745aeaa..8d355dd 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -18,6 +18,7 @@
"crypto/sha256"
"fmt"
"path/filepath"
+ "slices"
"strconv"
"strings"
@@ -51,6 +52,7 @@
Boot_image string `blueprint:"mutated" android:"path_device_first"`
Vendor_boot_image string `blueprint:"mutated" android:"path_device_first"`
Init_boot_image string `blueprint:"mutated" android:"path_device_first"`
+ Super_image string `blueprint:"mutated" android:"path_device_first"`
}
type filesystemCreator struct {
@@ -157,6 +159,11 @@
f.properties.Vbmeta_partition_names = append(f.properties.Vbmeta_partition_names, x.partitionName)
}
+ if buildingSuperImage(partitionVars) {
+ createSuperImage(ctx, finalSoongGeneratedPartitions, partitionVars)
+ f.properties.Super_image = ":" + generatedModuleName(ctx.Config(), "super")
+ }
+
ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions = finalSoongGeneratedPartitions
f.createDeviceModule(ctx, finalSoongGeneratedPartitions, f.properties.Vbmeta_module_names)
}
@@ -766,6 +773,7 @@
fsProps.Avb_algorithm = avbInfo.avbAlgorithm
// BOARD_AVB_SYSTEM_ROLLBACK_INDEX
fsProps.Rollback_index = avbInfo.avbRollbackIndex
+ fsProps.Avb_hash_algorithm = avbInfo.avbHashAlgorithm
fsProps.Partition_name = proptools.StringPtr(partitionType)
@@ -799,6 +807,7 @@
avbAlgorithm *string
avbRollbackIndex *int64
avbMode *string
+ avbHashAlgorithm *string
}
func getAvbInfo(config android.Config, partitionType string) avbInfo {
@@ -808,10 +817,23 @@
boardAvbEnable := partitionVars.BoardAvbEnable
if boardAvbEnable {
result.avbEnable = proptools.BoolPtr(true)
+ // There are "global" and "specific" copies of a lot of these variables. Sometimes they
+ // choose the specific and then fall back to the global one if it's not set, other times
+ // the global one actually only applies to the vbmeta partition.
+ if partitionType == "vbmeta" {
+ if partitionVars.BoardAvbKeyPath != "" {
+ result.avbKeyPath = proptools.StringPtr(partitionVars.BoardAvbKeyPath)
+ }
+ if partitionVars.BoardAvbRollbackIndex != "" {
+ parsed, err := strconv.ParseInt(partitionVars.BoardAvbRollbackIndex, 10, 64)
+ if err != nil {
+ panic(fmt.Sprintf("Rollback index must be an int, got %s", partitionVars.BoardAvbRollbackIndex))
+ }
+ result.avbRollbackIndex = &parsed
+ }
+ }
if specificPartitionVars.BoardAvbKeyPath != "" {
result.avbKeyPath = proptools.StringPtr(specificPartitionVars.BoardAvbKeyPath)
- } else if partitionVars.BoardAvbKeyPath != "" {
- result.avbKeyPath = proptools.StringPtr(partitionVars.BoardAvbKeyPath)
}
if specificPartitionVars.BoardAvbAlgorithm != "" {
result.avbAlgorithm = proptools.StringPtr(specificPartitionVars.BoardAvbAlgorithm)
@@ -824,13 +846,24 @@
panic(fmt.Sprintf("Rollback index must be an int, got %s", specificPartitionVars.BoardAvbRollbackIndex))
}
result.avbRollbackIndex = &parsed
- } else if partitionVars.BoardAvbRollbackIndex != "" {
- parsed, err := strconv.ParseInt(partitionVars.BoardAvbRollbackIndex, 10, 64)
+ }
+ if specificPartitionVars.BoardAvbRollbackIndex != "" {
+ parsed, err := strconv.ParseInt(specificPartitionVars.BoardAvbRollbackIndex, 10, 64)
if err != nil {
- panic(fmt.Sprintf("Rollback index must be an int, got %s", partitionVars.BoardAvbRollbackIndex))
+ panic(fmt.Sprintf("Rollback index must be an int, got %s", specificPartitionVars.BoardAvbRollbackIndex))
}
result.avbRollbackIndex = &parsed
}
+
+ // Make allows you to pass arbitrary arguments to avbtool via this variable, but in practice
+ // it's only used for --hash_algorithm. The soong module has a dedicated property for the
+ // hashtree algorithm, and doesn't allow custom arguments, so just extract the hashtree
+ // algorithm out of the arbitrary arguments.
+ addHashtreeFooterArgs := strings.Split(specificPartitionVars.BoardAvbAddHashtreeFooterArgs, " ")
+ if i := slices.Index(addHashtreeFooterArgs, "--hash_algorithm"); i >= 0 {
+ result.avbHashAlgorithm = &addHashtreeFooterArgs[i+1]
+ }
+
result.avbMode = proptools.StringPtr("make_legacy")
}
if result.avbKeyPath != nil {
@@ -971,6 +1004,14 @@
diffTestFiles = append(diffTestFiles, diffTestFile)
ctx.Phony("soong_generated_init_boot_filesystem_test", diffTestFile)
}
+ if f.properties.Super_image != "" {
+ diffTestFile := android.PathForModuleOut(ctx, "super_diff_test.txt")
+ soongSuperImg := android.PathForModuleSrc(ctx, f.properties.Super_image)
+ makeSuperImage := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/super.img", ctx.Config().DeviceName()))
+ createDiffTest(ctx, diffTestFile, soongSuperImg, makeSuperImage)
+ diffTestFiles = append(diffTestFiles, diffTestFile)
+ ctx.Phony("soong_generated_super_filesystem_test", diffTestFile)
+ }
ctx.Phony("soong_generated_filesystem_tests", diffTestFiles...)
}
diff --git a/fsgen/super_img.go b/fsgen/super_img.go
new file mode 100644
index 0000000..4569896
--- /dev/null
+++ b/fsgen/super_img.go
@@ -0,0 +1,91 @@
+// 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 (
+ "strconv"
+
+ "android/soong/android"
+ "android/soong/filesystem"
+ "github.com/google/blueprint/proptools"
+)
+
+func buildingSuperImage(partitionVars android.PartitionVariables) bool {
+ return partitionVars.ProductBuildSuperPartition
+}
+
+func createSuperImage(ctx android.LoadHookContext, partitions []string, partitionVars android.PartitionVariables) {
+ baseProps := &struct {
+ Name *string
+ }{
+ Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "super")),
+ }
+
+ superImageProps := &filesystem.SuperImageProperties{
+ Metadata_device: proptools.StringPtr(partitionVars.BoardSuperPartitionMetadataDevice),
+ Block_devices: proptools.StringPtr(partitionVars.BoardSuperPartitionBlockDevices[0]),
+ Ab_update: proptools.BoolPtr(partitionVars.AbOtaUpdater),
+ Retrofit: proptools.BoolPtr(partitionVars.ProductRetrofitDynamicPartitions),
+ Virtual_ab: proptools.BoolPtr(partitionVars.ProductVirtualAbOta),
+ Virtual_ab_retrofit: proptools.BoolPtr(partitionVars.ProductVirtualAbOtaRetrofit),
+ Use_dynamic_partitions: proptools.BoolPtr(partitionVars.ProductUseDynamicPartitions),
+ }
+ size, _ := strconv.ParseInt(partitionVars.BoardSuperPartitionSize, 10, 64)
+ superImageProps.Size = proptools.Int64Ptr(size)
+ sparse := !partitionVars.TargetUserimagesSparseExtDisabled && !partitionVars.TargetUserimagesSparseF2fsDisabled
+ superImageProps.Sparse = proptools.BoolPtr(sparse)
+
+ var partitionGroupsInfo []filesystem.PartitionGroupsInfo
+ for _, groupName := range android.SortedKeys(partitionVars.BoardSuperPartitionGroups) {
+ info := filesystem.PartitionGroupsInfo{
+ Name: groupName,
+ GroupSize: partitionVars.BoardSuperPartitionGroups[groupName].GroupSize,
+ PartitionList: partitionVars.BoardSuperPartitionGroups[groupName].PartitionList,
+ }
+ partitionGroupsInfo = append(partitionGroupsInfo, info)
+ }
+ superImageProps.Partition_groups = partitionGroupsInfo
+
+ partitionNameProps := &filesystem.SuperImagePartitionNameProperties{}
+ if android.InList("system", partitions) {
+ partitionNameProps.System_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system"))
+ }
+ if android.InList("system_ext", partitions) {
+ partitionNameProps.System_ext_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext"))
+ }
+ if android.InList("system_dlkm", partitions) {
+ partitionNameProps.System_dlkm_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_dlkm"))
+ }
+ if android.InList("system_other", partitions) {
+ partitionNameProps.System_other_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_other"))
+ }
+ if android.InList("product", partitions) {
+ partitionNameProps.Product_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "product"))
+ }
+ if android.InList("vendor", partitions) {
+ partitionNameProps.Vendor_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor"))
+ }
+ if android.InList("vendor_dlkm", partitions) {
+ partitionNameProps.Vendor_dlkm_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor_dlkm"))
+ }
+ if android.InList("odm", partitions) {
+ partitionNameProps.Odm_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "odm"))
+ }
+ if android.InList("odm_dlkm", partitions) {
+ partitionNameProps.Odm_dlkm_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "odm_dlkm"))
+ }
+
+ ctx.CreateModule(filesystem.SuperImageFactory, baseProps, superImageProps, partitionNameProps)
+}
diff --git a/java/app.go b/java/app.go
index 8739d1c..bedb45c 100644
--- a/java/app.go
+++ b/java/app.go
@@ -1794,9 +1794,9 @@
android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibCommon)
android.InitOverrideModule(m)
- android.AddLoadHook(m, func(ctx android.LoadHookContext) {
+ android.AddLoadHookWithPriority(m, func(ctx android.LoadHookContext) {
createInternalRuntimeOverlays(ctx, m.ModuleBase)
- })
+ }, 1) // Run after soong config load hoook
return m
}
diff --git a/java/app_test.go b/java/app_test.go
index 61b718d..11556b0 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -4798,3 +4798,76 @@
android.AssertBoolEquals(t, tc.desc, tc.overlayApkExpected, overrideVendorOverlayApk.Rule != nil)
}
}
+
+func TestNoAutogeneratedStaticRroForDisabledOverrideApps(t *testing.T) {
+ t.Parallel()
+ bp := `
+soong_config_module_type {
+ name: "my_custom_override_android_app",
+ module_type: "override_android_app",
+ config_namespace: "my_namespace",
+ value_variables: ["my_app_enabled"],
+ properties: ["enabled"],
+}
+soong_config_bool_variable {
+ name: "my_app_enabled",
+}
+android_app {
+ name: "foo",
+ srcs: ["foo.java"],
+ platform_apis: true,
+}
+my_custom_override_android_app {
+ name: "override_foo",
+ base: "foo",
+ soong_config_variables: {
+ my_app_enabled: {
+ enabled: true,
+ conditions_default: {
+ enabled: false
+ },
+ },
+ }
+}
+`
+ testCases := []struct {
+ desc string
+ preparer android.FixturePreparer
+ overlayApkExpected bool
+ }{
+ {
+ desc: "my_app_enabled is empty",
+ overlayApkExpected: false,
+ },
+ {
+ desc: "my_app_enabled is true",
+ overlayApkExpected: true,
+ preparer: android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.VendorVars = map[string]map[string]string{
+ "my_namespace": {
+ "my_app_enabled": "true",
+ },
+ }
+ }),
+ },
+ }
+ for _, tc := range testCases {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.PrepareForTestWithSoongConfigModuleBuildComponents,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.EnforceRROTargets = []string{"*"}
+ }),
+ 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(),
+ android.OptionalFixturePreparer(tc.preparer),
+ ).RunTestWithBp(t, bp)
+ overrideVendorOverlayApk := result.ModuleForTests("override_foo__test_product__auto_generated_rro_vendor", "android_arm64_armv8-a").Module().(*AutogenRuntimeResourceOverlay)
+ android.AssertBoolEquals(t, tc.desc, tc.overlayApkExpected, overrideVendorOverlayApk.exportPackage != nil)
+ }
+}
diff --git a/root.bp b/root.bp
index 7e0c1ed..8e621c4 100644
--- a/root.bp
+++ b/root.bp
@@ -2,3 +2,10 @@
// subdirs= and optional_subdirs= are obsolete and this file no longer
// needs a list of the top level directories that may contain Android.bp
// files.
+
+// TODO(b/253827323) Remove this. A module in internal builds needs to disable a new check,
+// IdentifierName, when errorprone is updated. In order to avoid having the update errorprone
+// in internal first, and then aosp, create this variable that we can fill out in internal in the
+// same topic as the errorprone update, then move the flag out of the variable after the update,
+// then remove the variable.
+disable_identifiername_for_errorprone_update = []
diff --git a/scripts/build-apex-bundle.py b/scripts/build-apex-bundle.py
index dcdd9ef..277e112 100644
--- a/scripts/build-apex-bundle.py
+++ b/scripts/build-apex-bundle.py
@@ -16,8 +16,6 @@
#
"""A tool to create an APEX bundle out of Soong-built base.zip"""
-from __future__ import print_function
-
import argparse
import sys
import tempfile
diff --git a/scripts/check_boot_jars/check_boot_jars.py b/scripts/check_boot_jars/check_boot_jars.py
index b711f9d..174b96e 100755
--- a/scripts/check_boot_jars/check_boot_jars.py
+++ b/scripts/check_boot_jars/check_boot_jars.py
@@ -4,7 +4,6 @@
Usage: check_boot_jars.py <dexdump_path> <package_allow_list_file> <jar1> \
<jar2> ...
"""
-from __future__ import print_function
import logging
import re
import subprocess
diff --git a/scripts/construct_context.py b/scripts/construct_context.py
index fc3a89e..882c2db 100755
--- a/scripts/construct_context.py
+++ b/scripts/construct_context.py
@@ -16,8 +16,6 @@
#
"""A tool for constructing class loader context."""
-from __future__ import print_function
-
import argparse
import json
import sys
diff --git a/scripts/manifest.py b/scripts/manifest.py
index 32603e8..87f4f0c 100755
--- a/scripts/manifest.py
+++ b/scripts/manifest.py
@@ -16,7 +16,6 @@
#
"""A tool for inserting values from the build system into a manifest or a test config."""
-from __future__ import print_function
from xml.dom import minidom
diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py
index 1e32d1d..175451e 100755
--- a/scripts/manifest_check.py
+++ b/scripts/manifest_check.py
@@ -16,8 +16,6 @@
#
"""A tool for checking that a manifest agrees with the build system."""
-from __future__ import print_function
-
import argparse
import json
import re
diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py
index 9847ad5..ad3b313 100755
--- a/scripts/manifest_fixer.py
+++ b/scripts/manifest_fixer.py
@@ -16,8 +16,6 @@
#
"""A tool for inserting values from the build system into a manifest."""
-from __future__ import print_function
-
import argparse
import sys
from xml.dom import minidom
diff --git a/scripts/modify_permissions_allowlist.py b/scripts/modify_permissions_allowlist.py
index 38ec7ec..4a0ca8f 100755
--- a/scripts/modify_permissions_allowlist.py
+++ b/scripts/modify_permissions_allowlist.py
@@ -16,8 +16,6 @@
#
"""A tool for modifying privileged permission allowlists."""
-from __future__ import print_function
-
import argparse
import sys
from xml.dom import minidom
diff --git a/scripts/modify_permissions_allowlist_test.py b/scripts/modify_permissions_allowlist_test.py
index ee8b12c..577388f 100755
--- a/scripts/modify_permissions_allowlist_test.py
+++ b/scripts/modify_permissions_allowlist_test.py
@@ -16,8 +16,6 @@
#
"""Unit tests for modify_permissions_allowlist.py."""
-from __future__ import print_function
-
import unittest
from xml.dom import minidom
diff --git a/scripts/test_config_fixer.py b/scripts/test_config_fixer.py
index 2876bcb..91a83f2 100644
--- a/scripts/test_config_fixer.py
+++ b/scripts/test_config_fixer.py
@@ -16,8 +16,6 @@
#
"""A tool for modifying values in a test config."""
-from __future__ import print_function
-
import argparse
import json
import sys
diff --git a/scripts/text_file_processor.py b/scripts/text_file_processor.py
new file mode 100755
index 0000000..10186ce
--- /dev/null
+++ b/scripts/text_file_processor.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2024 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the 'License');
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an 'AS IS' BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import argparse
+import re
+
+def main():
+ parser = argparse.ArgumentParser(description='This script looks for '
+ '`{CONTENTS_OF:path/to/file}` markers in the input file and replaces them with the actual '
+ 'contents of that file, with leading/trailing whitespace stripped. The idea is that this '
+ 'script could be extended to support more types of markers in the future.')
+ parser.add_argument('input')
+ parser.add_argument('output')
+ args = parser.parse_args()
+
+ with open(args.input, 'r') as f:
+ contents = f.read()
+
+ i = 0
+ replacedContents = ''
+ for m in re.finditer(r'{CONTENTS_OF:([a-zA-Z0-9 _/.-]+)}', contents):
+ replacedContents += contents[i:m.start()]
+ with open(m.group(1), 'r') as f:
+ replacedContents += f.read().strip()
+ i = m.end()
+ replacedContents += contents[i:]
+
+ with open(args.output, 'w') as f:
+ f.write(replacedContents)
+
+
+if __name__ == '__main__':
+ main()