Merge "Always allow mixing old and new SDK version formats" into main
diff --git a/android/licenses.go b/android/licenses.go
index 32d12c8..55f46ae 100644
--- a/android/licenses.go
+++ b/android/licenses.go
@@ -351,9 +351,7 @@
 	ctx.Strict("HTMLNOTICE", ctx.Config().HostToolPath(ctx, "htmlnotice").String())
 	ctx.Strict("XMLNOTICE", ctx.Config().HostToolPath(ctx, "xmlnotice").String())
 	ctx.Strict("TEXTNOTICE", ctx.Config().HostToolPath(ctx, "textnotice").String())
-	ctx.Strict("COMPLIANCENOTICE_BOM", ctx.Config().HostToolPath(ctx, "compliancenotice_bom").String())
 	ctx.Strict("COMPLIANCENOTICE_SHIPPEDLIBS", ctx.Config().HostToolPath(ctx, "compliancenotice_shippedlibs").String())
 	ctx.Strict("COMPLIANCE_LISTSHARE", ctx.Config().HostToolPath(ctx, "compliance_listshare").String())
 	ctx.Strict("COMPLIANCE_CHECKSHARE", ctx.Config().HostToolPath(ctx, "compliance_checkshare").String())
-	ctx.Strict("COMPLIANCE_SBOM", ctx.Config().HostToolPath(ctx, "compliance_sbom").String())
 }
diff --git a/android/neverallow.go b/android/neverallow.go
index 14dc6d2..8995a0f 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -304,6 +304,8 @@
 			// Trusty vm target names
 			Without("name", "trusty_test_vm_arm64.bin").
 			Without("name", "trusty_test_vm_x86_64.elf").
+			Without("name", "trusty_test_vm_os_arm64.bin").
+			Without("name", "trusty_test_vm_os_x86_64.elf").
 			Without("name", "trusty_security_vm_arm64.bin").
 			Without("name", "trusty_security_vm_x86_64.elf").
 			Without("name", "trusty_widevine_vm_arm64.bin").
@@ -317,6 +319,8 @@
 			// Trusty vm target names
 			Without("name", "trusty_test_vm_arm64.bin").
 			Without("name", "trusty_test_vm_x86_64.elf").
+			Without("name", "trusty_test_vm_os_arm64.bin").
+			Without("name", "trusty_test_vm_os_x86_64.elf").
 			Without("name", "trusty_security_vm_arm64.bin").
 			Without("name", "trusty_security_vm_x86_64.elf").
 			Without("name", "trusty_widevine_vm_arm64.bin").
diff --git a/android/variable.go b/android/variable.go
index a655717..bccf12f 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -668,6 +668,7 @@
 	AbOtaPartitions                   []string                                 `json:",omitempty"`
 	AbOtaKeys                         []string                                 `json:",omitempty"`
 	AbOtaPostInstallConfig            []string                                 `json:",omitempty"`
+	BoardSuperImageInUpdatePackage    bool                                     `json:",omitempty"`
 
 	// Avb (android verified boot) stuff
 	BoardAvbEnable          bool                                `json:",omitempty"`
@@ -716,6 +717,8 @@
 	ProductFsCompression string `json:",omitempty"`
 
 	ReleaseToolsExtensionDir string `json:",omitempty"`
+
+	BoardFastbootInfoFile string `json:",omitempty"`
 }
 
 func boolPtr(v bool) *bool {
diff --git a/apex/apex.go b/apex/apex.go
index f700768..196f389 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -18,6 +18,7 @@
 
 import (
 	"fmt"
+	"path"
 	"path/filepath"
 	"regexp"
 	"slices"
@@ -2258,6 +2259,7 @@
 	a.enforcePartitionTagOnApexSystemServerJar(ctx)
 
 	a.verifyNativeImplementationLibs(ctx)
+	a.enforceNoVintfInUpdatable(ctx)
 
 	android.SetProvider(ctx, android.ApexBundleDepsDataProvider, android.ApexBundleDepsData{
 		FlatListPath: a.FlatListPath(),
@@ -2918,3 +2920,16 @@
 		}
 	}
 }
+
+// TODO(b/399527905) libvintf is not forward compatible.
+func (a *apexBundle) enforceNoVintfInUpdatable(ctx android.ModuleContext) {
+	if !a.Updatable() {
+		return
+	}
+	for _, fi := range a.filesInfo {
+		if match, _ := path.Match("etc/vintf/*", fi.path()); match {
+			ctx.ModuleErrorf("VINTF fragment (%s) is not supported in updatable APEX.", fi.path())
+			break
+		}
+	}
+}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 9eaf814..a0a42a1 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -12216,3 +12216,30 @@
 	// Ensure that vintf fragment file is being installed
 	ensureContains(t, cmd, "/etc/vintf/my_vintf_fragment.xml ")
 }
+
+func TestNoVintfFragmentInUpdatableApex(t *testing.T) {
+	t.Parallel()
+	testApexError(t, `VINTF fragment .* is not supported in updatable APEX`, apex_default_bp+`
+		apex {
+			name: "myapex",
+			manifest: ":myapex.manifest",
+			key: "myapex.key",
+			binaries: [ "mybin" ],
+			updatable: true,
+			min_sdk_version: "29",
+		}
+
+		cc_binary {
+			name: "mybin",
+			srcs: ["mybin.cpp"],
+			vintf_fragment_modules: ["my_vintf_fragment.xml"],
+			apex_available: [ "myapex" ],
+			min_sdk_version: "29",
+		}
+
+		vintf_fragment {
+			name: "my_vintf_fragment.xml",
+			src: "my_vintf_fragment.xml",
+		}
+	`)
+}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index b704ef4..db99a53 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -79,7 +79,7 @@
 
 	minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined",
 		"-fno-sanitize-recover=integer,undefined"}
-	memtagStackCommonFlags = []string{"-Xclang -target-feature -Xclang +mte"}
+	memtagStackCommonFlags = []string{"-march=armv8-a+memtag"}
 	memtagStackLlvmFlags   = []string{"-dom-tree-reachability-max-bbs-to-explore=128"}
 
 	hostOnlySanitizeFlags   = []string{"-fno-sanitize-recover=all"}
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 655ee9b..f3c2b2c 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -717,17 +717,8 @@
 	} else if global.EnableUffdGc == "false" {
 		android.WriteFileRuleVerbatim(ctx, uffdGcFlag, "")
 	} else if global.EnableUffdGc == "default" {
-		// Generated by `build/make/core/Makefile`.
+		// Generated by build/make/core/Makefile, or the android_device module in soong-only builds.
 		kernelVersionFile := android.PathForOutput(ctx, "dexpreopt/kernel_version_for_uffd_gc.txt")
-		if !ctx.Config().KatiEnabled() {
-			// In soong-only mode, we need to generate the kernel_version_for_uffd_gc.txt with kernel version
-			kernelVersion := android.String(ctx.Config().ProductVariables().BoardKernelVersion)
-			if kernelVersion == "" {
-				// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=5382;drc=66783fca85911af9da48d9b4f35a61b3873023e9
-				panic("BOARD_KERNEL_VERSION is not set. Build team will convert more stuff from Make to Soong to support this scenario.")
-			}
-			android.WriteFileRule(ctx, kernelVersionFile, kernelVersion)
-		}
 
 		// Determine the UFFD GC flag by the kernel version file.
 		rule := android.NewRuleBuilder(pctx, ctx)
diff --git a/filesystem/android_device.go b/filesystem/android_device.go
index a2fa0f0..005dc34 100644
--- a/filesystem/android_device.go
+++ b/filesystem/android_device.go
@@ -87,6 +87,14 @@
 
 	Ramdisk_node_list      *string `android:"path"`
 	Releasetools_extension *string `android:"path"`
+	FastbootInfo           *string `android:"path"`
+
+	// The kernel version in the build. Will be verified against the actual kernel.
+	// If not provided, will attempt to extract it from the loose kernel or the kernel inside
+	// the boot image. The version is later used to decide whether or not to enable uffd_gc
+	// when dexpreopting apps. So setting this doesn't really do anything except enforce that the
+	// actual kernel version is as specified here.
+	Kernel_version *string
 }
 
 type androidDevice struct {
@@ -101,6 +109,8 @@
 	proguardDictZip     android.Path
 	proguardDictMapping android.Path
 	proguardUsageZip    android.Path
+	kernelConfig        android.Path
+	kernelVersion       android.Path
 }
 
 func AndroidDeviceFactory() android.Module {
@@ -175,6 +185,7 @@
 
 	allInstalledModules := a.allInstalledModules(ctx)
 
+	a.kernelConfig, a.kernelVersion = a.extractKernelVersionAndConfigs(ctx)
 	a.buildTargetFilesZip(ctx, allInstalledModules)
 	a.buildProguardZips(ctx, allInstalledModules)
 
@@ -621,6 +632,31 @@
 	}
 	installedApexKeys = android.SortedUniquePaths(installedApexKeys) // Sort by keypath to match make
 	builder.Command().Text("cat").Inputs(installedApexKeys).Textf(" >> %s/META/apexkeys.txt", targetFilesDir.String())
+	// Copy fastboot-info.txt
+	if fastbootInfo := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.FastbootInfo)); fastbootInfo != nil {
+		// TODO (b/399788523): Autogenerate fastboot-info.txt if there is no source fastboot-info.txt
+		// https://cs.android.com/android/_/android/platform/build/+/80b9546f8f69e78b8fe1870e0e745d70fc18dfcd:core/Makefile;l=5831-5893;drc=077490384423dff9eac954da5c001c6f0be3fa6e;bpv=0;bpt=0
+		builder.Command().Textf("cp").Input(fastbootInfo).Textf(" %s/META/fastboot-info.txt", targetFilesDir.String())
+	}
+
+	// kernel_configs.txt and kernel_version.txt
+	if a.kernelConfig != nil {
+		builder.Command().Textf("cp").Input(a.kernelConfig).Textf(" %s/META/", targetFilesDir.String())
+	}
+	if a.kernelVersion != nil {
+		builder.Command().Textf("cp").Input(a.kernelVersion).Textf(" %s/META/", targetFilesDir.String())
+	}
+
+	if a.partitionProps.Super_partition_name != nil {
+		superPartition := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
+		if info, ok := android.OtherModuleProvider(ctx, superPartition, SuperImageProvider); ok {
+			// dynamic_partitions_info.txt
+			// TODO (b/390192334): Add `building_super_empty_partition=true`
+			builder.Command().Text("cp").Input(info.DynamicPartitionsInfo).Textf(" %s/META/", targetFilesDir.String())
+		} else {
+			ctx.ModuleErrorf("Super partition %s does set SuperImageProvider\n", superPartition.Name())
+		}
+	}
 
 }
 
@@ -680,3 +716,72 @@
 		}
 	}
 }
+
+func (a *androidDevice) getKernel(ctx android.ModuleContext) android.Path {
+	if a.partitionProps.Boot_partition_name != nil {
+		bootImg := ctx.GetDirectDepProxyWithTag(proptools.String(a.partitionProps.Boot_partition_name), filesystemDepTag)
+		bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider)
+		return bootImgInfo.Kernel
+	}
+	return nil
+}
+
+// Gets the kernel version and configs from the actual kernel file itself. Roughly equivalent to
+// this make code: https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=5443;drc=c0b66fc59de069e06ce0ffd703d4d21613be30c6
+// However, it is a simplified version of that make code. Differences include:
+//   - Not handling BOARD_KERNEL_CONFIG_FILE because BOARD_KERNEL_CONFIG_FILE was never used.
+//   - Not unpacking the bootimage, as we should be able to just always export the kernel directly
+//     in the BootimgInfo. We don't currently support prebuilt boot images, but even if we add that
+//     in the future, it can be done in a prebuilt_bootimage module type that still exports the same
+//     BootimgInfo.
+//   - We don't print a warning and output '<unknown-kernel>' to kernel_version_for_uffd_gc.txt
+//     because we expect the kernel to always be present. If it's not, we will get an error that
+//     kernel_version_for_uffd_gc.txt doesn't exist. This may require later tweaking to the
+//     dexpreopt rules so that they don't attempt to access that file in builds that don't have
+//     a kernel.
+func (a *androidDevice) extractKernelVersionAndConfigs(ctx android.ModuleContext) (android.Path, android.Path) {
+	kernel := a.getKernel(ctx)
+	// If there's no kernel, don't create kernel version / kernel config files. Reverse dependencies
+	// on those files have to account for this, for example by disabling dexpreopt in unbundled
+	// builds.
+	if kernel == nil {
+		return nil, nil
+	}
+
+	lz4tool := ctx.Config().HostToolPath(ctx, "lz4")
+
+	extractedVersionFile := android.PathForModuleOut(ctx, "kernel_version.txt")
+	extractedConfigsFile := android.PathForModuleOut(ctx, "kernel_configs.txt")
+	builder := android.NewRuleBuilder(pctx, ctx)
+	builder.Command().BuiltTool("extract_kernel").
+		Flag("--tools lz4:"+lz4tool.String()).Implicit(lz4tool).
+		FlagWithInput("--input ", kernel).
+		FlagWithOutput("--output-release ", extractedVersionFile).
+		FlagWithOutput("--output-configs ", extractedConfigsFile)
+
+	if specifiedVersion := proptools.String(a.deviceProps.Kernel_version); specifiedVersion != "" {
+		specifiedVersionFile := android.PathForModuleOut(ctx, "specified_kernel_version.txt")
+		android.WriteFileRuleVerbatim(ctx, specifiedVersionFile, specifiedVersion)
+		builder.Command().Text("diff -q").
+			Input(specifiedVersionFile).
+			Input(extractedVersionFile).
+			Textf(`|| (echo "Specified kernel version '$(cat %s)' does not match actual kernel version '$(cat %s)'"; exit 1)`, specifiedVersionFile, extractedVersionFile)
+	}
+
+	builder.Build("extract_kernel_info", "Extract kernel version and configs")
+
+	if proptools.Bool(a.deviceProps.Main_device) && !ctx.Config().KatiEnabled() {
+		if ctx.Config().EnableUffdGc() == "default" {
+			kernelVersionFile := android.PathForOutput(ctx, "dexpreopt/kernel_version_for_uffd_gc.txt")
+			ctx.Build(pctx, android.BuildParams{
+				Rule:   android.CpIfChanged,
+				Input:  extractedVersionFile,
+				Output: kernelVersionFile,
+			})
+		}
+
+		ctx.DistForGoal("droid_targets", extractedVersionFile)
+	}
+
+	return extractedVersionFile, extractedConfigsFile
+}
diff --git a/filesystem/super_image.go b/filesystem/super_image.go
index 58c938a..5e62fa7 100644
--- a/filesystem/super_image.go
+++ b/filesystem/super_image.go
@@ -78,6 +78,8 @@
 		// specified we default to COW version 2 in update_engine for backwards compatibility
 		Cow_version *int64
 	}
+	// Whether the super image will be disted in the update package
+	Super_image_in_update_package *bool
 }
 
 type PartitionGroupsInfo struct {
@@ -114,6 +116,8 @@
 	// Mapping from the sub-partition type to its re-exported FileSystemInfo providers from the
 	// sub-partitions.
 	SubImageInfo map[string]FilesystemInfo
+
+	DynamicPartitionsInfo android.Path
 }
 
 var SuperImageProvider = blueprint.NewProvider[SuperImageInfo]()
@@ -173,8 +177,9 @@
 		Output(output)
 	builder.Build("build_super_image", fmt.Sprintf("Creating super image %s", s.BaseModuleName()))
 	android.SetProvider(ctx, SuperImageProvider, SuperImageInfo{
-		SuperImage:   output,
-		SubImageInfo: subImageInfos,
+		SuperImage:            output,
+		SubImageInfo:          subImageInfos,
+		DynamicPartitionsInfo: s.generateDynamicPartitionsInfo(ctx),
 	})
 	ctx.SetOutputFiles([]android.Path{output}, "")
 	ctx.CheckbuildFile(output)
@@ -186,6 +191,7 @@
 
 func (s *superImage) buildMiscInfo(ctx android.ModuleContext) (android.Path, android.Paths, map[string]FilesystemInfo) {
 	var miscInfoString strings.Builder
+	partitionList := s.dumpDynamicPartitionInfo(ctx, &miscInfoString)
 	addStr := func(name string, value string) {
 		miscInfoString.WriteString(name)
 		miscInfoString.WriteRune('=')
@@ -193,71 +199,6 @@
 		miscInfoString.WriteRune('\n')
 	}
 
-	addStr("build_super_partition", "true")
-	addStr("use_dynamic_partitions", strconv.FormatBool(proptools.Bool(s.properties.Use_dynamic_partitions)))
-	if proptools.Bool(s.properties.Retrofit) {
-		addStr("dynamic_partition_retrofit", "true")
-	}
-	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_partition_size", strconv.Itoa(proptools.Int(s.properties.Size)))
-	// TODO: In make, there's more complicated logic than just this surrounding super_*_device_size
-	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, " "))
-	}
-	initialPartitionListLen := len(partitionList)
-	partitionList = android.SortedUniqueStrings(partitionList)
-	if len(partitionList) != initialPartitionListLen {
-		ctx.ModuleErrorf("Duplicate partitions found in the partition_groups property")
-	}
-	addStr("super_partition_groups", strings.Join(groups, " "))
-	addStr("dynamic_partition_list", strings.Join(partitionList, " "))
-
-	addStr("ab_update", strconv.FormatBool(proptools.Bool(s.properties.Ab_update)))
-
-	if proptools.Bool(s.properties.Virtual_ab.Enable) {
-		addStr("virtual_ab", "true")
-		if proptools.Bool(s.properties.Virtual_ab.Retrofit) {
-			addStr("virtual_ab_retrofit", "true")
-		}
-		addStr("virtual_ab_compression", strconv.FormatBool(proptools.Bool(s.properties.Virtual_ab.Compression)))
-		if s.properties.Virtual_ab.Compression_method != nil {
-			matched, _ := regexp.MatchString("^[a-zA-Z0-9_-]+$", *s.properties.Virtual_ab.Compression_method)
-			if !matched {
-				ctx.PropertyErrorf("virtual_ab.compression_method", "compression_method cannot have special characters")
-			}
-			addStr("virtual_ab_compression_method", *s.properties.Virtual_ab.Compression_method)
-		}
-		if s.properties.Virtual_ab.Compression_factor != nil {
-			addStr("virtual_ab_compression_factor", strconv.FormatInt(*s.properties.Virtual_ab.Compression_factor, 10))
-		}
-		if s.properties.Virtual_ab.Cow_version != nil {
-			addStr("virtual_ab_cow_version", strconv.FormatInt(*s.properties.Virtual_ab.Cow_version, 10))
-		}
-
-	} else {
-		if s.properties.Virtual_ab.Retrofit != nil {
-			ctx.PropertyErrorf("virtual_ab.retrofit", "This property cannot be set when virtual_ab is disabled")
-		}
-		if s.properties.Virtual_ab.Compression != nil {
-			ctx.PropertyErrorf("virtual_ab.compression", "This property cannot be set when virtual_ab is disabled")
-		}
-		if s.properties.Virtual_ab.Compression_method != nil {
-			ctx.PropertyErrorf("virtual_ab.compression_method", "This property cannot be set when virtual_ab is disabled")
-		}
-		if s.properties.Virtual_ab.Compression_factor != nil {
-			ctx.PropertyErrorf("virtual_ab.compression_factor", "This property cannot be set when virtual_ab is disabled")
-		}
-	}
-
 	subImageInfo := make(map[string]FilesystemInfo)
 	var deps android.Paths
 
@@ -346,3 +287,90 @@
 	android.WriteFileRule(ctx, miscInfo, miscInfoString.String(), missingPartitionErrorMessageFile)
 	return miscInfo, deps, subImageInfo
 }
+
+func (s *superImage) dumpDynamicPartitionInfo(ctx android.ModuleContext, sb *strings.Builder) []string {
+	addStr := func(name string, value string) {
+		sb.WriteString(name)
+		sb.WriteRune('=')
+		sb.WriteString(value)
+		sb.WriteRune('\n')
+	}
+
+	addStr("build_super_partition", "true")
+	addStr("use_dynamic_partitions", strconv.FormatBool(proptools.Bool(s.properties.Use_dynamic_partitions)))
+	if proptools.Bool(s.properties.Retrofit) {
+		addStr("dynamic_partition_retrofit", "true")
+	}
+	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, " "))
+	}
+	if proptools.Bool(s.properties.Super_image_in_update_package) {
+		addStr("super_image_in_update_package", "true")
+	}
+	addStr("super_partition_size", strconv.Itoa(proptools.Int(s.properties.Size)))
+	// TODO: In make, there's more complicated logic than just this surrounding super_*_device_size
+	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, " "))
+	}
+	initialPartitionListLen := len(partitionList)
+	partitionList = android.SortedUniqueStrings(partitionList)
+	if len(partitionList) != initialPartitionListLen {
+		ctx.ModuleErrorf("Duplicate partitions found in the partition_groups property")
+	}
+	addStr("super_partition_groups", strings.Join(groups, " "))
+	addStr("dynamic_partition_list", strings.Join(partitionList, " "))
+
+	addStr("ab_update", strconv.FormatBool(proptools.Bool(s.properties.Ab_update)))
+
+	if proptools.Bool(s.properties.Virtual_ab.Enable) {
+		addStr("virtual_ab", "true")
+		if proptools.Bool(s.properties.Virtual_ab.Retrofit) {
+			addStr("virtual_ab_retrofit", "true")
+		}
+		addStr("virtual_ab_compression", strconv.FormatBool(proptools.Bool(s.properties.Virtual_ab.Compression)))
+		if s.properties.Virtual_ab.Compression_method != nil {
+			matched, _ := regexp.MatchString("^[a-zA-Z0-9_-]+$", *s.properties.Virtual_ab.Compression_method)
+			if !matched {
+				ctx.PropertyErrorf("virtual_ab.compression_method", "compression_method cannot have special characters")
+			}
+			addStr("virtual_ab_compression_method", *s.properties.Virtual_ab.Compression_method)
+		}
+		if s.properties.Virtual_ab.Compression_factor != nil {
+			addStr("virtual_ab_compression_factor", strconv.FormatInt(*s.properties.Virtual_ab.Compression_factor, 10))
+		}
+		if s.properties.Virtual_ab.Cow_version != nil {
+			addStr("virtual_ab_cow_version", strconv.FormatInt(*s.properties.Virtual_ab.Cow_version, 10))
+		}
+
+	} else {
+		if s.properties.Virtual_ab.Retrofit != nil {
+			ctx.PropertyErrorf("virtual_ab.retrofit", "This property cannot be set when virtual_ab is disabled")
+		}
+		if s.properties.Virtual_ab.Compression != nil {
+			ctx.PropertyErrorf("virtual_ab.compression", "This property cannot be set when virtual_ab is disabled")
+		}
+		if s.properties.Virtual_ab.Compression_method != nil {
+			ctx.PropertyErrorf("virtual_ab.compression_method", "This property cannot be set when virtual_ab is disabled")
+		}
+		if s.properties.Virtual_ab.Compression_factor != nil {
+			ctx.PropertyErrorf("virtual_ab.compression_factor", "This property cannot be set when virtual_ab is disabled")
+		}
+	}
+
+	return partitionList
+}
+
+func (s *superImage) generateDynamicPartitionsInfo(ctx android.ModuleContext) android.Path {
+	var contents strings.Builder
+	s.dumpDynamicPartitionInfo(ctx, &contents)
+	dynamicPartitionsInfo := android.PathForModuleOut(ctx, "dynamic_partitions_info.txt")
+	android.WriteFileRule(ctx, dynamicPartitionsInfo, contents.String())
+	return dynamicPartitionsInfo
+}
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index 3d83706..9378822 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -340,6 +340,26 @@
 	return releaseToolsFilegroupName, true
 }
 
+func (f *filesystemCreator) createFastbootInfoFilegroup(ctx android.LoadHookContext) (string, bool) {
+	fastbootInfoFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BoardFastbootInfoFile
+	if fastbootInfoFile == "" {
+		return "", false
+	}
+
+	fastbootInfoFilegroupName := generatedModuleName(ctx.Config(), "fastboot")
+	filegroupProps := &struct {
+		Name       *string
+		Srcs       []string
+		Visibility []string
+	}{
+		Name:       proptools.StringPtr(fastbootInfoFilegroupName),
+		Srcs:       []string{fastbootInfoFile},
+		Visibility: []string{"//visibility:public"},
+	}
+	ctx.CreateModuleInDirectory(android.FileGroupFactory, ".", filegroupProps)
+	return fastbootInfoFilegroupName, true
+}
+
 func (f *filesystemCreator) createDeviceModule(
 	ctx android.LoadHookContext,
 	partitions allGeneratedPartitionData,
@@ -405,6 +425,7 @@
 		Ab_ota_postinstall_config: ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaPostInstallConfig,
 		Ramdisk_node_list:         proptools.StringPtr(":ramdisk_node_list"),
 		Android_info:              proptools.StringPtr(":" + generatedModuleName(ctx.Config(), "android_info.prop{.txt}")),
+		Kernel_version:            ctx.Config().ProductVariables().BoardKernelVersion,
 	}
 
 	if bootloader, ok := f.createBootloaderFilegroup(ctx); ok {
@@ -413,6 +434,9 @@
 	if releaseTools, ok := f.createReleaseToolsFilegroup(ctx); ok {
 		deviceProps.Releasetools_extension = proptools.StringPtr(":" + releaseTools)
 	}
+	if fastbootInfo, ok := f.createFastbootInfoFilegroup(ctx); ok {
+		deviceProps.FastbootInfo = proptools.StringPtr(":" + fastbootInfo)
+	}
 
 	ctx.CreateModule(filesystem.AndroidDeviceFactory, baseProps, partitionProps, deviceProps)
 }
diff --git a/fsgen/super_img.go b/fsgen/super_img.go
index 569f780..f564636 100644
--- a/fsgen/super_img.go
+++ b/fsgen/super_img.go
@@ -40,11 +40,12 @@
 	}
 
 	superImageProps := &filesystem.SuperImageProperties{
-		Metadata_device:        proptools.StringPtr(partitionVars.BoardSuperPartitionMetadataDevice),
-		Block_devices:          partitionVars.BoardSuperPartitionBlockDevices,
-		Ab_update:              proptools.BoolPtr(partitionVars.AbOtaUpdater),
-		Retrofit:               proptools.BoolPtr(partitionVars.ProductRetrofitDynamicPartitions),
-		Use_dynamic_partitions: proptools.BoolPtr(partitionVars.ProductUseDynamicPartitions),
+		Metadata_device:               proptools.StringPtr(partitionVars.BoardSuperPartitionMetadataDevice),
+		Block_devices:                 partitionVars.BoardSuperPartitionBlockDevices,
+		Ab_update:                     proptools.BoolPtr(partitionVars.AbOtaUpdater),
+		Retrofit:                      proptools.BoolPtr(partitionVars.ProductRetrofitDynamicPartitions),
+		Use_dynamic_partitions:        proptools.BoolPtr(partitionVars.ProductUseDynamicPartitions),
+		Super_image_in_update_package: proptools.BoolPtr(partitionVars.BoardSuperImageInUpdatePackage),
 	}
 	if partitionVars.ProductVirtualAbOta {
 		superImageProps.Virtual_ab.Enable = proptools.BoolPtr(true)
diff --git a/java/aar.go b/java/aar.go
index 0e27cb8..ebada65 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -219,11 +219,7 @@
 func (a *aapt) useResourceProcessorBusyBox(ctx android.BaseModuleContext) bool {
 	return BoolDefault(a.aaptProperties.Use_resource_processor, true) &&
 		// TODO(b/331641946): remove this when ResourceProcessorBusyBox supports generating shared libraries.
-		!slices.Contains(a.aaptProperties.Aaptflags, "--shared-lib") &&
-		// Use the legacy resource processor in kythe builds.
-		// The legacy resource processor creates an R.srcjar, which kythe can use for generating crossrefs.
-		// TODO(b/354854007): Re-enable BusyBox in kythe builds
-		!ctx.Config().EmitXrefRules()
+		!slices.Contains(a.aaptProperties.Aaptflags, "--shared-lib")
 }
 
 func (a *aapt) filterProduct() string {
diff --git a/java/app.go b/java/app.go
index c2aa8a4..fe5eec3 100644
--- a/java/app.go
+++ b/java/app.go
@@ -611,7 +611,7 @@
 	ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
 		tag := ctx.OtherModuleDependencyTag(dep)
 		switch tag {
-		case staticLibTag:
+		case staticLibTag, rroDepTag:
 			if flagPackages, ok := android.OtherModuleProvider(ctx, dep, FlagsPackagesProvider); ok {
 				aconfigTextFilePaths = append(aconfigTextFilePaths, flagPackages.AconfigTextFiles...)
 			}
diff --git a/java/rro.go b/java/rro.go
index f7f85f0..b3d9348 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -406,10 +406,11 @@
 
 	a.aapt.buildActions(ctx,
 		aaptBuildActionOptions{
-			sdkContext:      a,
-			extraLinkFlags:  aaptLinkFlags,
-			rroDirs:         &rroDirs,
-			manifestForAapt: genManifest,
+			sdkContext:       a,
+			extraLinkFlags:   aaptLinkFlags,
+			rroDirs:          &rroDirs,
+			manifestForAapt:  genManifest,
+			aconfigTextFiles: getAconfigFilePaths(ctx),
 		},
 	)