Merge "Convert buildApexDependencyInfo to use ModuleProxy." into main
diff --git a/android/variable.go b/android/variable.go
index baa2646..19f63e3 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -581,6 +581,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"`
@@ -634,6 +639,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/cc/fuzz.go b/cc/fuzz.go
index 8a974c0..26ac7d1 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -350,6 +350,8 @@
 	fuzzPackagedModule.Corpus = append(fuzzPackagedModule.Corpus, android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Device_common_corpus)...)
 
 	fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Data)
+	fuzzPackagedModule.Data = append(fuzzPackagedModule.Data, android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Device_common_data)...)
+	fuzzPackagedModule.Data = append(fuzzPackagedModule.Data, android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Device_first_data)...)
 
 	if fuzzPackagedModule.FuzzProperties.Dictionary != nil {
 		fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *fuzzPackagedModule.FuzzProperties.Dictionary)
diff --git a/cc/test.go b/cc/test.go
index ae73886..abec19a 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -83,14 +83,14 @@
 	// the test
 	Data []string `android:"path,arch_variant"`
 
-	// Same as data, but adds depedencies on modules using the device's os variant, and common
+	// Same as data, but adds dependencies on modules using the device's os variant, and common
 	// architecture's variant. Can be useful to add device-built apps to the data of a host
 	// test.
 	Device_common_data []string `android:"path_device_common"`
 
-	// Same as data, but adds depedencies on modules using the device's os variant, and the device's
-	// first architecture's variant. Can be useful to add device-built apps to the data of a host
-	// test.
+	// Same as data, but adds dependencies on modules using the device's os variant, and the
+	// device's first architecture's variant. Can be useful to add device-built apps to the data
+	// of a host test.
 	Device_first_data []string `android:"path_device_first"`
 
 	// list of shared library modules that should be installed alongside the test
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..b9cb076 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
 
@@ -121,9 +130,13 @@
 	// checks, and will be used in the future for API surface checks.
 	Partition_type *string
 
-	// file_contexts file to make image. Currently, only ext4 is supported.
+	// file_contexts file to make image. Currently, only ext4 is supported. These file contexts
+	// will be compiled with sefcontext_compile
 	File_contexts *string `android:"path"`
 
+	// The selinux file contexts, after having already run them through sefcontext_compile
+	Precompiled_file_contexts *string `android:"path"`
+
 	// Base directory relative to root, to which deps are installed, e.g. "system". Default is "."
 	// (root).
 	Base_dir *string
@@ -444,7 +457,7 @@
 }
 
 func (f *filesystem) appendToEntry(ctx android.ModuleContext, installedFile android.Path) {
-	partitionBaseDir := android.PathForModuleOut(ctx, "root", f.partitionName()).String() + "/"
+	partitionBaseDir := android.PathForModuleOut(ctx, "root", proptools.String(f.properties.Base_dir)).String() + "/"
 
 	relPath, inTargetPartition := strings.CutPrefix(installedFile.String(), partitionBaseDir)
 	if inTargetPartition {
@@ -563,11 +576,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 +657,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,15 +676,22 @@
 			}
 			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())
 	}
 
-	if proptools.String(f.properties.File_contexts) != "" {
+	if f.properties.File_contexts != nil && f.properties.Precompiled_file_contexts != nil {
+		ctx.ModuleErrorf("file_contexts and precompiled_file_contexts cannot both be set")
+	} else if f.properties.File_contexts != nil {
 		addPath("selinux_fc", f.buildFileContexts(ctx))
+	} else if f.properties.Precompiled_file_contexts != nil {
+		src := android.PathForModuleSrc(ctx, *f.properties.Precompiled_file_contexts)
+		if src != nil {
+			addPath("selinux_fc", src)
+		}
 	}
 	if timestamp := proptools.String(f.properties.Fake_timestamp); timestamp != "" {
 		addStr("timestamp", timestamp)
@@ -694,8 +729,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 +1023,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..0ed3870 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -244,7 +244,7 @@
 	`)
 
 	module := result.ModuleForTests("myfilesystem", "android_common").Module().(*systemImage)
-	android.AssertDeepEquals(t, "entries should have foo only", []string{"components/foo"}, module.entries)
+	android.AssertDeepEquals(t, "entries should have foo and not bar", []string{"components/foo", "etc/linker.config.pb"}, module.entries)
 }
 
 func TestAvbGenVbmetaImage(t *testing.T) {
@@ -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..0f8f614
--- /dev/null
+++ b/filesystem/super_image.go
@@ -0,0 +1,236 @@
+// 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))
+	if len(s.properties.Block_devices) > 0 {
+		addStr("super_block_devices", strings.Join(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..1378513 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)
 }
@@ -321,7 +328,22 @@
 				Target: proptools.StringPtr("/data/cache"),
 				Name:   proptools.StringPtr("cache"),
 			},
+			// For Treble Generic System Image (GSI), system-as-root GSI needs to work on
+			// both devices with and without /odm_dlkm partition. Those symlinks are for
+			// devices without /odm_dlkm partition. For devices with /odm_dlkm
+			// partition, mount odm_dlkm.img under /odm_dlkm will hide those symlinks.
+			// Note that /odm_dlkm/lib is omitted because odm DLKMs should be accessed
+			// via /odm/lib/modules directly. All of this also applies to the vendor_dlkm symlink
+			filesystem.SymlinkDefinition{
+				Target: proptools.StringPtr("/odm/odm_dlkm/etc"),
+				Name:   proptools.StringPtr("odm_dlkm/etc"),
+			},
+			filesystem.SymlinkDefinition{
+				Target: proptools.StringPtr("/vendor/vendor_dlkm/etc"),
+				Name:   proptools.StringPtr("vendor_dlkm/etc"),
+			},
 		}
+		fsProps.Base_dir = proptools.StringPtr("system")
 		fsProps.Dirs = proptools.NewSimpleConfigurable([]string{
 			// From generic_rootdirs in build/make/target/product/generic/Android.bp
 			"acct",
@@ -373,11 +395,11 @@
 		fsProps.Symlinks = []filesystem.SymlinkDefinition{
 			filesystem.SymlinkDefinition{
 				Target: proptools.StringPtr("/odm"),
-				Name:   proptools.StringPtr("vendor/odm"),
+				Name:   proptools.StringPtr("odm"),
 			},
 			filesystem.SymlinkDefinition{
 				Target: proptools.StringPtr("/vendor_dlkm/lib/modules"),
-				Name:   proptools.StringPtr("vendor/lib/modules"),
+				Name:   proptools.StringPtr("lib/modules"),
 			},
 		}
 		fsProps.Android_filesystem_deps.System = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system"))
@@ -388,7 +410,7 @@
 		fsProps.Symlinks = []filesystem.SymlinkDefinition{
 			filesystem.SymlinkDefinition{
 				Target: proptools.StringPtr("/odm_dlkm/lib/modules"),
-				Name:   proptools.StringPtr("odm/lib/modules"),
+				Name:   proptools.StringPtr("lib/modules"),
 			},
 		}
 	case "userdata":
@@ -431,6 +453,7 @@
 				Name:   proptools.StringPtr("default.prop"),
 			},
 		}
+		fsProps.Base_dir = proptools.StringPtr("recovery")
 	}
 }
 
@@ -766,29 +789,21 @@
 	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)
 
-	if !strings.Contains(partitionType, "ramdisk") {
-		fsProps.Base_dir = proptools.StringPtr(partitionType)
+	switch partitionType {
+	// The partitions that support file_contexts came from here:
+	// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2270;drc=ad7cfb56010cb22c3aa0e70cf71c804352553526
+	case "system", "userdata", "cache", "vendor", "product", "system_ext", "odm", "vendor_dlkm", "odm_dlkm", "system_dlkm", "oem":
+		fsProps.Precompiled_file_contexts = proptools.StringPtr(":file_contexts_bin_gen")
 	}
 
 	fsProps.Is_auto_generated = proptools.BoolPtr(true)
 
 	partitionSpecificFsProps(ctx, fsProps, partitionVars, partitionType)
 
-	// system_image properties that are not set:
-	// - filesystemProperties.Avb_hash_algorithm
-	// - filesystemProperties.File_contexts
-	// - filesystemProperties.Dirs
-	// - filesystemProperties.Symlinks
-	// - filesystemProperties.Fake_timestamp
-	// - filesystemProperties.Uuid
-	// - filesystemProperties.Mount_point
-	// - filesystemProperties.Include_make_built_files
-	// - filesystemProperties.Build_logtags
-	// - systemImageProperties.Linker_config_src
-
 	return fsProps, true
 }
 
@@ -799,6 +814,7 @@
 	avbAlgorithm     *string
 	avbRollbackIndex *int64
 	avbMode          *string
+	avbHashAlgorithm *string
 }
 
 func getAvbInfo(config android.Config, partitionType string) avbInfo {
@@ -808,10 +824,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 +853,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 +1011,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..8ee3bf2
--- /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:          partitionVars.BoardSuperPartitionBlockDevices,
+		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/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index aa393a2..3fd79a7 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -419,6 +419,14 @@
 	// Optional list of data files to be installed to the fuzz target's output
 	// directory. Directory structure relative to the module is preserved.
 	Data []string `android:"path"`
+	// Same as data, but adds dependencies on modules using the device's os variant, and common
+	// architecture's variant. Can be useful to add device-built apps to the data of a host
+	// test.
+	Device_common_data []string `android:"path_device_common"`
+	// Same as data, but adds dependencies on modules using the device's os variant, and the
+	// device's first architecture's variant. Can be useful to add device-built apps to the data
+	// of a host test.
+	Device_first_data []string `android:"path_device_first"`
 	// Optional dictionary to be installed to the fuzz target's output directory.
 	Dictionary *string `android:"path"`
 	// Define the fuzzing frameworks this fuzz target can be built for. If
diff --git a/java/aar.go b/java/aar.go
index 1e5c95a..b668766 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -257,7 +257,7 @@
 }
 
 func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext android.SdkContext,
-	manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths,
+	manifestPath android.Path, doNotIncludeAssetDirImplicitly bool) (compileFlags, linkFlags []string, linkDeps android.Paths,
 	resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) {
 
 	hasVersionCode := android.PrefixInList(a.aaptProperties.Aaptflags, "--version-code")
@@ -274,7 +274,12 @@
 		Paths:       a.aaptProperties.Assets,
 		IncludeDirs: false,
 	})
-	assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets")
+	var assetDirs android.Paths
+	if doNotIncludeAssetDirImplicitly {
+		assetDirs = android.PathsForModuleSrc(ctx, a.aaptProperties.Asset_dirs)
+	} else {
+		assetDirs = android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets")
+	}
 	resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs.GetOrDefault(ctx, nil), "res")
 	resourceZips := android.PathsForModuleSrc(ctx, a.aaptProperties.Resource_zips)
 
@@ -494,7 +499,8 @@
 		a.mergedManifestFile = manifestPath
 	}
 
-	compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resZips := a.aapt2Flags(ctx, opts.sdkContext, manifestPath)
+	// do not include assets in autogenerated RRO.
+	compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resZips := a.aapt2Flags(ctx, opts.sdkContext, manifestPath, opts.rroDirs != nil)
 
 	a.rroDirsDepSet = depset.NewBuilder[rroDir](depset.TOPOLOGICAL).
 		Direct(rroDirs...).
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/java/base.go b/java/base.go
index c0ac4ab..f26404b 100644
--- a/java/base.go
+++ b/java/base.go
@@ -60,6 +60,9 @@
 	// This is most useful in the arch/multilib variants to remove non-common files
 	Exclude_srcs []string `android:"path,arch_variant"`
 
+	// list of Kotlin source files that should excluded from the list of common_srcs.
+	Exclude_common_srcs []string `android:"path,arch_variant"`
+
 	// list of directories containing Java resources
 	Java_resource_dirs []string `android:"arch_variant"`
 
@@ -922,7 +925,7 @@
 
 	if j.useCompose(ctx) {
 		ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), kotlinPluginTag,
-			"androidx.compose.compiler_compiler-hosted-plugin")
+			"kotlin-compose-compiler-plugin")
 	}
 }
 
@@ -1182,7 +1185,7 @@
 		flags = protoFlags(ctx, &j.properties, &j.protoProperties, flags)
 	}
 
-	kotlinCommonSrcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Common_srcs, nil)
+	kotlinCommonSrcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Common_srcs, j.properties.Exclude_common_srcs)
 	if len(kotlinCommonSrcFiles.FilterOutByExt(".kt")) > 0 {
 		ctx.PropertyErrorf("common_srcs", "common_srcs must be .kt files")
 	}
diff --git a/java/config/kotlin.go b/java/config/kotlin.go
index 302d021..bf4c886 100644
--- a/java/config/kotlin.go
+++ b/java/config/kotlin.go
@@ -49,7 +49,7 @@
 		"-J--add-opens=java.base/java.util=ALL-UNNAMED", // https://youtrack.jetbrains.com/issue/KT-43704
 	}, " "))
 
-	pctx.StaticVariable("KotlincGlobalFlags", strings.Join([]string{}, " "))
+	pctx.StaticVariable("KotlincGlobalFlags", strings.Join([]string{"-language-version 1.9"}, " "))
 	// Use KotlincKytheGlobalFlags to prevent kotlinc version skew issues between android and
 	// g3 kythe indexers.
 	// This is necessary because there might be instances of kotlin code in android
diff --git a/java/core-libraries/jarjar-strip-annotations-rules.txt b/java/core-libraries/jarjar-strip-annotations-rules.txt
index a1c261b..c74eaca 100644
--- a/java/core-libraries/jarjar-strip-annotations-rules.txt
+++ b/java/core-libraries/jarjar-strip-annotations-rules.txt
@@ -2,3 +2,4 @@
 strip-annotation android.annotation.Nullable
 strip-annotation androidx.annotation.RecentlyNonNull
 strip-annotation androidx.annotation.RecentlyNullable
+strip-annotation android.annotation.FlaggedApi
diff --git a/java/fuzz.go b/java/fuzz.go
index 90f09a8..dba8815 100644
--- a/java/fuzz.go
+++ b/java/fuzz.go
@@ -107,23 +107,7 @@
 }
 
 func (j *JavaFuzzTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	if j.fuzzPackagedModule.FuzzProperties.Corpus != nil {
-		j.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Corpus)
-	}
-	if j.fuzzPackagedModule.FuzzProperties.Device_common_corpus != nil {
-		j.fuzzPackagedModule.Corpus = append(j.fuzzPackagedModule.Corpus, android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Device_common_corpus)...)
-	}
-	if j.fuzzPackagedModule.FuzzProperties.Data != nil {
-		j.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Data)
-	}
-	if j.fuzzPackagedModule.FuzzProperties.Dictionary != nil {
-		j.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *j.fuzzPackagedModule.FuzzProperties.Dictionary)
-	}
-	if j.fuzzPackagedModule.FuzzProperties.Fuzz_config != nil {
-		configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
-		android.WriteFileRule(ctx, configPath, j.fuzzPackagedModule.FuzzProperties.Fuzz_config.String())
-		j.fuzzPackagedModule.Config = configPath
-	}
+	j.fuzzPackagedModule = cc.PackageFuzzModule(ctx, j.fuzzPackagedModule, pctx)
 
 	_, sharedDeps := cc.CollectAllSharedDependencies(ctx)
 	for _, dep := range sharedDeps {
diff --git a/java/kotlin_test.go b/java/kotlin_test.go
index 45eac01..ad8734d 100644
--- a/java/kotlin_test.go
+++ b/java/kotlin_test.go
@@ -501,7 +501,7 @@
 		}
 
 		kotlin_plugin {
-			name: "androidx.compose.compiler_compiler-hosted-plugin",
+			name: "kotlin-compose-compiler-plugin",
 		}
 
 		java_library {
@@ -523,7 +523,7 @@
 
 	buildOS := result.Config.BuildOS.String()
 
-	composeCompiler := result.ModuleForTests("androidx.compose.compiler_compiler-hosted-plugin", buildOS+"_common").Rule("combineJar").Output
+	composeCompiler := result.ModuleForTests("kotlin-compose-compiler-plugin", buildOS+"_common").Rule("combineJar").Output
 	withCompose := result.ModuleForTests("withcompose", "android_common")
 	noCompose := result.ModuleForTests("nocompose", "android_common")
 
diff --git a/root.bp b/root.bp
index 7e0c1ed..ee208a0 100644
--- a/root.bp
+++ b/root.bp
@@ -2,3 +2,12 @@
 // 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 = [
+    "-Xep:IdentifierName:OFF",
+]
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/gen_build_prop.py b/scripts/gen_build_prop.py
index 5f52d6f..47bbf59 100644
--- a/scripts/gen_build_prop.py
+++ b/scripts/gen_build_prop.py
@@ -450,7 +450,7 @@
   props.append(f"ro.vendor.build.security_patch={config['VendorSecurityPatch']}")
   props.append(f"ro.product.board={config['BootloaderBoardName']}")
   props.append(f"ro.board.platform={config['BoardPlatform']}")
-  props.append(f"ro.hwui.use_vulkan={'true' if config['UsesVulkan'] else 'false'}")
+  props.append(f"ro.hwui.use_vulkan={config['UsesVulkan']}")
 
   if config["ScreenDensity"]:
     props.append(f"ro.sf.lcd_density={config['ScreenDensity']}")
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()