Merge "Modify apex_available to Bluetooth apex" into main
diff --git a/Android.bp b/Android.bp
index 47a195c..98552a7 100644
--- a/Android.bp
+++ b/Android.bp
@@ -256,5 +256,8 @@
 
 all_apex_certs {
     name: "all_apex_certs",
-    visibility: ["//cts/tests/tests/security"],
+    visibility: [
+        "//cts/tests/tests/security",
+        "//cts/hostsidetests/appsecurity",
+    ],
 }
diff --git a/android/android_info.go b/android/android_info.go
index f2cbc65..225c8f0 100644
--- a/android/android_info.go
+++ b/android/android_info.go
@@ -81,6 +81,7 @@
 	})
 
 	ctx.SetOutputFiles(Paths{androidInfoProp}, "")
+	ctx.SetOutputFiles(Paths{androidInfoTxt}, ".txt")
 
 	builder := NewRuleBuilder(pctx, ctx)
 	builder.Command().Text("touch").Output(timestamp)
diff --git a/android/androidmk.go b/android/androidmk.go
index 9e721e1..87a93e3 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -746,22 +746,31 @@
 	distMkFile := absolutePath(filepath.Join(ctx.Config().katiPackageMkDir(), "dist.mk"))
 
 	var goalOutputPairs []string
-	var buf strings.Builder
-	buf.WriteString("DIST_SRC_DST_PAIRS := $(sort")
+	var srcDstPairs []string
 	for _, contributions := range allDistContributions {
 		for _, copiesForGoal := range contributions.copiesForGoals {
 			goals := strings.Fields(copiesForGoal.goals)
 			for _, copy := range copiesForGoal.copies {
 				for _, goal := range goals {
-					goalOutputPairs = append(goalOutputPairs, fmt.Sprintf("%s:%s", goal, copy.dest))
+					goalOutputPairs = append(goalOutputPairs, fmt.Sprintf(" %s:%s", goal, copy.dest))
 				}
-				buf.WriteString(fmt.Sprintf(" %s:%s", copy.from.String(), copy.dest))
+				srcDstPairs = append(srcDstPairs, fmt.Sprintf(" %s:%s", copy.from.String(), copy.dest))
 			}
 		}
 	}
-	buf.WriteString(")\nDIST_GOAL_OUTPUT_PAIRS := $(sort ")
-	buf.WriteString(strings.Join(goalOutputPairs, " "))
-	buf.WriteString(")\n")
+	// There are duplicates in the lists that we need to remove
+	goalOutputPairs = SortedUniqueStrings(goalOutputPairs)
+	srcDstPairs = SortedUniqueStrings(srcDstPairs)
+	var buf strings.Builder
+	buf.WriteString("DIST_SRC_DST_PAIRS :=")
+	for _, srcDstPair := range srcDstPairs {
+		buf.WriteString(srcDstPair)
+	}
+	buf.WriteString("\nDIST_GOAL_OUTPUT_PAIRS :=")
+	for _, goalOutputPair := range goalOutputPairs {
+		buf.WriteString(goalOutputPair)
+	}
+	buf.WriteString("\n")
 
 	writeValueIfChanged(ctx, distMkFile, buf.String())
 }
@@ -791,10 +800,20 @@
 			continue
 		}
 		if info, ok := OtherModuleProvider(ctx, mod, AndroidMkInfoProvider); ok {
+			// Deep copy the provider info since we need to modify the info later
+			info := deepCopyAndroidMkProviderInfo(info)
+			info.PrimaryInfo.fillInEntries(ctx, mod)
+			if info.PrimaryInfo.disabled() {
+				continue
+			}
 			if contribution := info.PrimaryInfo.getDistContributions(ctx, mod); contribution != nil {
 				allDistContributions = append(allDistContributions, *contribution)
 			}
 			for _, ei := range info.ExtraInfo {
+				ei.fillInEntries(ctx, mod)
+				if ei.disabled() {
+					continue
+				}
 				if contribution := ei.getDistContributions(ctx, mod); contribution != nil {
 					allDistContributions = append(allDistContributions, *contribution)
 				}
@@ -809,6 +828,9 @@
 				}
 
 				data.fillInData(ctx, mod)
+				if data.Entries.disabled() {
+					continue
+				}
 				if contribution := data.Entries.getDistContributions(mod); contribution != nil {
 					allDistContributions = append(allDistContributions, *contribution)
 				}
@@ -816,6 +838,9 @@
 				entriesList := x.AndroidMkEntries()
 				for _, entries := range entriesList {
 					entries.fillInEntries(ctx, mod)
+					if entries.disabled() {
+						continue
+					}
 					if contribution := entries.getDistContributions(mod); contribution != nil {
 						allDistContributions = append(allDistContributions, *contribution)
 					}
diff --git a/android/neverallow.go b/android/neverallow.go
index d211784..e12e8b7 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -230,7 +230,7 @@
 func createUncompressDexRules() []Rule {
 	return []Rule{
 		NeverAllow().
-			NotIn("art").
+			NotIn("art", "cts/hostsidetests/compilation").
 			WithMatcher("uncompress_dex", isSetMatcherInstance).
 			Because("uncompress_dex is only allowed for certain jars for test in art."),
 	}
diff --git a/android/variable.go b/android/variable.go
index 6e46e9d..4b61827 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -697,6 +697,8 @@
 	TargetScreenDensity string `json:",omitempty"`
 
 	PrivateRecoveryUiProperties map[string]string `json:",omitempty"`
+
+	PrebuiltBootloader string `json:",omitempty"`
 }
 
 func boolPtr(v bool) *bool {
diff --git a/apex/key.go b/apex/key.go
index 9fa9d1e..1622c65 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -182,6 +182,7 @@
 }
 
 func (_ *allApexCerts) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	var avbpubkeys android.Paths
 	var certificatesPem android.Paths
 	ctx.VisitDirectDeps(func(m android.Module) {
 		if apex, ok := m.(*apexBundle); ok {
@@ -194,9 +195,12 @@
 				}
 			}
 			certificatesPem = append(certificatesPem, pem)
+			// avbpubkey for signing the apex payload
+			avbpubkeys = append(avbpubkeys, apex.publicKeyFile)
 		}
 	})
 	certificatesPem = android.SortedUniquePaths(certificatesPem) // For hermiticity
+	avbpubkeys = android.SortedUniquePaths(avbpubkeys)           // For hermiticity
 	var certificatesDer android.Paths
 	for index, certificatePem := range certificatesPem {
 		certificateDer := android.PathForModuleOut(ctx, fmt.Sprintf("x509.%v.der", index))
@@ -209,6 +213,7 @@
 	}
 	ctx.SetOutputFiles(certificatesPem, ".pem")
 	ctx.SetOutputFiles(certificatesDer, ".der")
+	ctx.SetOutputFiles(avbpubkeys, ".avbpubkey")
 }
 
 func (_ *allApexCerts) GenerateSingletonBuildActions(ctx android.SingletonContext) {
diff --git a/cc/library.go b/cc/library.go
index 5c2cb5d..8262d8b 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1387,6 +1387,11 @@
 		extraFlags = append(extraFlags,
 			"-allow-unreferenced-changes",
 			"-allow-unreferenced-elf-symbol-changes")
+		// The functions in standard libraries are not always declared in the headers.
+		// Allow them to be added or removed without changing the symbols.
+		if isBionic(ctx.ModuleName()) {
+			extraFlags = append(extraFlags, "-allow-adding-removing-referenced-apis")
+		}
 	}
 	if isLlndk {
 		extraFlags = append(extraFlags, "-consider-opaque-types-different")
diff --git a/filesystem/android_device.go b/filesystem/android_device.go
index 5c3842a..83d56c6 100644
--- a/filesystem/android_device.go
+++ b/filesystem/android_device.go
@@ -16,6 +16,7 @@
 
 import (
 	"strings"
+	"sync/atomic"
 
 	"android/soong/android"
 
@@ -54,19 +55,33 @@
 	Odm_dlkm_partition_name *string
 }
 
+type DeviceProperties struct {
+	// Path to the prebuilt bootloader that would be copied to PRODUCT_OUT
+	Bootloader *string `android:"path"`
+	// Path to android-info.txt file containing board specific info.
+	Android_info *string `android:"path"`
+}
+
 type androidDevice struct {
 	android.ModuleBase
 
 	partitionProps PartitionNameProperties
+
+	deviceProps DeviceProperties
+
+	// copyToProductOutTimestamp for copying necessary files to PRODUCT_OUT
+	copyToProductOutTimestamp android.WritablePath
 }
 
 func AndroidDeviceFactory() android.Module {
 	module := &androidDevice{}
-	module.AddProperties(&module.partitionProps)
+	module.AddProperties(&module.partitionProps, &module.deviceProps)
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibFirst)
 	return module
 }
 
+var numAutogeneratedAndroidDevicesOnceKey android.OnceKey = android.NewOnceKey("num_auto_generated_anroid_devices")
+
 type partitionDepTagType struct {
 	blueprint.BaseDependencyTag
 }
@@ -98,6 +113,24 @@
 	}
 }
 
+func (a *androidDevice) copyToProductOut(ctx android.ModuleContext, builder *android.RuleBuilder, src android.Path, dest string) {
+	destPath := android.PathForModuleInPartitionInstall(ctx, "").Join(ctx, dest)
+	builder.Command().Text("rsync").Flag("-a").Flag("--checksum").Input(src).Text(destPath.String())
+}
+
+func (a *androidDevice) copyFilesToProductOut(ctx android.ModuleContext) {
+	a.copyToProductOutTimestamp = android.PathForModuleOut(ctx, "timestamp")
+	builder := android.NewRuleBuilder(pctx, ctx)
+	builder.Command().Text("touch").Output(a.copyToProductOutTimestamp)
+
+	// List all individual files to be copied to PRODUCT_OUT here
+	if a.deviceProps.Bootloader != nil {
+		a.copyToProductOut(ctx, builder, android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Bootloader)), "bootloader")
+	}
+
+	builder.Build("copy_to_product_out", "Copy files to PRODUCT_OUT")
+}
+
 func (a *androidDevice) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	a.buildTargetFilesZip(ctx)
 	var deps []android.Path
@@ -111,14 +144,37 @@
 		}
 		deps = append(deps, imageOutput.DefaultOutputFiles[0])
 	})
-	out := android.PathForModuleOut(ctx, "out")
+
+	a.copyFilesToProductOut(ctx)
+
+	allImagesStamp := android.PathForModuleOut(ctx, "all_images_stamp")
 	ctx.Build(pctx, android.BuildParams{
-		Rule:      android.Touch,
-		Output:    out,
-		Implicits: deps,
+		Rule:       android.Touch,
+		Output:     allImagesStamp,
+		Implicits:  deps,
+		Validation: a.copyToProductOutTimestamp,
 	})
-	ctx.SetOutputFiles(android.Paths{out}, "")
-	ctx.CheckbuildFile(out)
+	ctx.SetOutputFiles(android.Paths{allImagesStamp}, "")
+	ctx.CheckbuildFile(allImagesStamp)
+
+	if ctx.OtherModuleIsAutoGenerated(ctx.Module()) {
+		numAutogeneratedAndroidDevices := ctx.Config().Once(numAutogeneratedAndroidDevicesOnceKey, func() interface{} {
+			return &atomic.Int32{}
+		}).(*atomic.Int32)
+		total := numAutogeneratedAndroidDevices.Add(1)
+		if total > 1 {
+			// There should only be 1 autogenerated android_device module. That one will be
+			// made the default thing to build in soong-only builds.
+			ctx.ModuleErrorf("There cannot be more than 1 autogenerated android_device module")
+		}
+	}
+
+	if !ctx.Config().KatiEnabled() && ctx.OtherModuleIsAutoGenerated(ctx.Module()) {
+		// In soong-only builds, build this module by default.
+		// This is the analogue to this make code:
+		// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/main.mk;l=1396;drc=6595459cdd8164a6008335f6372c9f97b9094060
+		ctx.Phony("droidcore-unbundled", allImagesStamp)
+	}
 }
 
 type targetFilesZipCopy struct {
@@ -168,18 +224,44 @@
 			Textf("-rd %s/. %s/%s", rootDirString, targetFilesDir, subdir).
 			Implicit(fsInfo.Output) // so that the staging dir is built
 
+		if subdir == "SYSTEM" {
+			// Create the ROOT partition in target_files.zip
+			builder.Command().Textf("rsync --links --exclude=system/* %s/ -r %s/ROOT", fsInfo.RootDir, targetFilesDir.String())
+		}
 	}
-	// Copy cmdline files of boot images
+	// Copy cmdline, kernel etc. files of boot images
 	if a.partitionProps.Vendor_boot_partition_name != nil {
 		bootImg := ctx.GetDirectDepWithTag(proptools.String(a.partitionProps.Vendor_boot_partition_name), filesystemDepTag)
 		bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider)
-		builder.Command().Textf("echo %s > %s/%s/cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir, "VENDOR_BOOT")
-		builder.Command().Textf("echo %s > %s/%s/vendor_cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir, "VENDOR_BOOT")
+		builder.Command().Textf("echo %s > %s/VENDOR_BOOT/cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir)
+		builder.Command().Textf("echo %s > %s/VENDOR_BOOT/vendor_cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir)
+		if bootImgInfo.Dtb != nil {
+			builder.Command().Textf("cp %s %s/VENDOR_BOOT/dtb", bootImgInfo.Dtb, targetFilesDir)
+		}
+		if bootImgInfo.Bootconfig != nil {
+			builder.Command().Textf("cp %s %s/VENDOR_BOOT/vendor_bootconfig", bootImgInfo.Bootconfig, targetFilesDir)
+		}
 	}
 	if a.partitionProps.Boot_partition_name != nil {
 		bootImg := ctx.GetDirectDepWithTag(proptools.String(a.partitionProps.Boot_partition_name), filesystemDepTag)
 		bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider)
-		builder.Command().Textf("echo %s > %s/%s/cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir, "BOOT")
+		builder.Command().Textf("echo %s > %s/BOOT/cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir)
+		if bootImgInfo.Dtb != nil {
+			builder.Command().Textf("cp %s %s/BOOT/dtb", bootImgInfo.Dtb, targetFilesDir)
+		}
+		if bootImgInfo.Kernel != nil {
+			builder.Command().Textf("cp %s %s/BOOT/kernel", bootImgInfo.Kernel, targetFilesDir)
+			// Even though kernel is not used to build vendor_boot, copy the kernel to VENDOR_BOOT to match the behavior of make packaging.
+			builder.Command().Textf("cp %s %s/VENDOR_BOOT/kernel", bootImgInfo.Kernel, targetFilesDir)
+		}
+		if bootImgInfo.Bootconfig != nil {
+			builder.Command().Textf("cp %s %s/BOOT/bootconfig", bootImgInfo.Bootconfig, targetFilesDir)
+		}
+	}
+
+	if a.deviceProps.Android_info != nil {
+		builder.Command().Textf("mkdir -p %s/OTA", targetFilesDir)
+		builder.Command().Textf("cp %s %s/OTA/android-info.txt", android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Android_info)), targetFilesDir)
 	}
 
 	builder.Command().
diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go
index 00398b2..0a3a177 100644
--- a/filesystem/bootimg.go
+++ b/filesystem/bootimg.go
@@ -197,12 +197,8 @@
 		ctx.PropertyErrorf("kernel_prebuilt", "boot partition must have kernel")
 		return
 	}
-	var kernel android.Path
-	if kernelProp != "" {
-		kernel = android.PathForModuleSrc(ctx, kernelProp)
-	}
 
-	unsignedOutput := b.buildBootImage(ctx, kernel)
+	unsignedOutput := b.buildBootImage(ctx, b.getKernelPath(ctx))
 
 	output := unsignedOutput
 	if proptools.Bool(b.properties.Use_avb) {
@@ -213,7 +209,7 @@
 		case "default":
 			output = b.signImage(ctx, unsignedOutput)
 		case "make_legacy":
-			output = b.addAvbFooter(ctx, unsignedOutput, kernel)
+			output = b.addAvbFooter(ctx, unsignedOutput, b.getKernelPath(ctx))
 		default:
 			ctx.PropertyErrorf("avb_mode", `Unknown value for avb_mode, expected "default" or "make_legacy", got: %q`, *b.properties.Avb_mode)
 		}
@@ -235,14 +231,47 @@
 
 	// Set BootimgInfo for building target_files.zip
 	android.SetProvider(ctx, BootimgInfoProvider, BootimgInfo{
-		Cmdline: b.properties.Cmdline,
+		Cmdline:    b.properties.Cmdline,
+		Kernel:     b.getKernelPath(ctx),
+		Dtb:        b.getDtbPath(ctx),
+		Bootconfig: b.getBootconfigPath(ctx),
 	})
 }
 
 var BootimgInfoProvider = blueprint.NewProvider[BootimgInfo]()
 
 type BootimgInfo struct {
-	Cmdline []string
+	Cmdline    []string
+	Kernel     android.Path
+	Dtb        android.Path
+	Bootconfig android.Path
+}
+
+func (b *bootimg) getKernelPath(ctx android.ModuleContext) android.Path {
+	var kernelPath android.Path
+	kernelName := proptools.String(b.properties.Kernel_prebuilt)
+	if kernelName != "" {
+		kernelPath = android.PathForModuleSrc(ctx, kernelName)
+	}
+	return kernelPath
+}
+
+func (b *bootimg) getDtbPath(ctx android.ModuleContext) android.Path {
+	var dtbPath android.Path
+	dtbName := proptools.String(b.properties.Dtb_prebuilt)
+	if dtbName != "" {
+		dtbPath = android.PathForModuleSrc(ctx, dtbName)
+	}
+	return dtbPath
+}
+
+func (b *bootimg) getBootconfigPath(ctx android.ModuleContext) android.Path {
+	var bootconfigPath android.Path
+	bootconfigName := proptools.String(b.properties.Bootconfig)
+	if bootconfigName != "" {
+		bootconfigPath = android.PathForModuleSrc(ctx, bootconfigName)
+	}
+	return bootconfigPath
 }
 
 func (b *bootimg) buildBootImage(ctx android.ModuleContext, kernel android.Path) android.Path {
@@ -261,10 +290,8 @@
 		cmd.FlagWithArg("--os_patch_level ", ctx.Config().PlatformSecurityPatch())
 	}
 
-	dtbName := proptools.String(b.properties.Dtb_prebuilt)
-	if dtbName != "" {
-		dtb := android.PathForModuleSrc(ctx, dtbName)
-		cmd.FlagWithInput("--dtb ", dtb)
+	if b.getDtbPath(ctx) != nil {
+		cmd.FlagWithInput("--dtb ", b.getDtbPath(ctx))
 	}
 
 	cmdline := strings.Join(b.properties.Cmdline, " ")
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 64b7931..b112568 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -459,6 +459,7 @@
 		FileListFile: fileListFile,
 		RootDir:      rootDir,
 	})
+
 	f.fileListFile = fileListFile
 
 	if proptools.Bool(f.properties.Unchecked_module) {
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index 41faf94..590d33a 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -128,6 +128,8 @@
 			f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, partitionType)
 		}
 	}
+	// Create android_info.prop
+	f.createAndroidInfo(ctx)
 
 	partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
 	dtbImg := createDtbImgFilegroup(ctx)
@@ -161,7 +163,7 @@
 
 	if buildingSuperImage(partitionVars) {
 		createSuperImage(ctx, finalSoongGeneratedPartitions, partitionVars)
-		f.properties.Super_image = ":" + generatedModuleName(ctx.Config(), "super")
+		f.properties.Super_image = ":" + generatedModuleNameForPartition(ctx.Config(), "super")
 	}
 
 	ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions = finalSoongGeneratedPartitions
@@ -180,15 +182,37 @@
 	return generatedModuleName(cfg, fmt.Sprintf("%s_image", partitionType))
 }
 
+func (f *filesystemCreator) createBootloaderFilegroup(ctx android.LoadHookContext) (string, bool) {
+	bootloaderPath := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.PrebuiltBootloader
+	if len(bootloaderPath) == 0 {
+		return "", false
+	}
+
+	bootloaderFilegroupName := generatedModuleName(ctx.Config(), "bootloader")
+	filegroupProps := &struct {
+		Name       *string
+		Srcs       []string
+		Visibility []string
+	}{
+		Name:       proptools.StringPtr(bootloaderFilegroupName),
+		Srcs:       []string{bootloaderPath},
+		Visibility: []string{"//visibility:public"},
+	}
+	ctx.CreateModuleInDirectory(android.FileGroupFactory, ".", filegroupProps)
+	return bootloaderFilegroupName, true
+}
+
 func (f *filesystemCreator) createDeviceModule(
 	ctx android.LoadHookContext,
 	generatedPartitionTypes []string,
 	vbmetaPartitions []string,
 ) {
 	baseProps := &struct {
-		Name *string
+		Name         *string
+		Android_info *string
 	}{
-		Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "device")),
+		Name:         proptools.StringPtr(generatedModuleName(ctx.Config(), "device")),
+		Android_info: proptools.StringPtr(":" + generatedModuleName(ctx.Config(), "android_info.prop{.txt}")),
 	}
 
 	// Currently, only the system and system_ext partition module is created.
@@ -234,7 +258,12 @@
 	}
 	partitionProps.Vbmeta_partitions = vbmetaPartitions
 
-	ctx.CreateModule(filesystem.AndroidDeviceFactory, baseProps, partitionProps)
+	deviceProps := &filesystem.DeviceProperties{}
+	if bootloader, ok := f.createBootloaderFilegroup(ctx); ok {
+		deviceProps.Bootloader = proptools.StringPtr(":" + bootloader)
+	}
+
+	ctx.CreateModule(filesystem.AndroidDeviceFactory, baseProps, partitionProps, deviceProps)
 }
 
 func partitionSpecificFsProps(ctx android.EarlyModuleContext, fsProps *filesystem.FilesystemProperties, partitionVars android.PartitionVariables, partitionType string) {
@@ -575,8 +604,8 @@
 	(*fsGenState.fsDeps[partitionType])[name] = defaultDepCandidateProps(ctx.Config())
 }
 
-// Create a build_prop and android_info module. This will be used to create /vendor/build.prop
-func (f *filesystemCreator) createVendorBuildProp(ctx android.LoadHookContext) {
+// Create an android_info module. This will be used to create /vendor/build.prop
+func (f *filesystemCreator) createAndroidInfo(ctx android.LoadHookContext) {
 	// Create a android_info for vendor
 	// The board info files might be in a directory outside the root soong namespace, so create
 	// the module in "."
@@ -600,7 +629,9 @@
 		androidInfoProps,
 	)
 	androidInfoProp.HideFromMake()
-	// Create a build prop for vendor
+}
+
+func (f *filesystemCreator) createVendorBuildProp(ctx android.LoadHookContext) {
 	vendorBuildProps := &struct {
 		Name           *string
 		Vendor         *bool
@@ -613,7 +644,7 @@
 		Vendor:         proptools.BoolPtr(true),
 		Stem:           proptools.StringPtr("build.prop"),
 		Product_config: proptools.StringPtr(":product_config"),
-		Android_info:   proptools.StringPtr(":" + androidInfoProp.Name()),
+		Android_info:   proptools.StringPtr(":" + generatedModuleName(ctx.Config(), "android_info.prop")),
 		Licenses:       []string{"Android-Apache-2.0"},
 	}
 	vendorBuildProp := ctx.CreateModule(
diff --git a/fsgen/super_img.go b/fsgen/super_img.go
index 8ee3bf2..a36f614 100644
--- a/fsgen/super_img.go
+++ b/fsgen/super_img.go
@@ -19,6 +19,7 @@
 
 	"android/soong/android"
 	"android/soong/filesystem"
+
 	"github.com/google/blueprint/proptools"
 )
 
@@ -30,7 +31,7 @@
 	baseProps := &struct {
 		Name *string
 	}{
-		Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "super")),
+		Name: proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "super")),
 	}
 
 	superImageProps := &filesystem.SuperImageProperties{
diff --git a/java/base.go b/java/base.go
index 1aef37c..a2fc29d 100644
--- a/java/base.go
+++ b/java/base.go
@@ -90,6 +90,10 @@
 	// list of module-specific flags that will be used for kotlinc compiles
 	Kotlincflags []string `android:"arch_variant"`
 
+	// Kotlin language version to target. Currently only 1.9 and 2 are supported.
+	// See kotlinc's `-language-version` flag.
+	Kotlin_lang_version *string
+
 	// list of java libraries that will be in the classpath
 	Libs []string `android:"arch_variant"`
 
@@ -1331,6 +1335,16 @@
 		kotlincFlags := j.properties.Kotlincflags
 		CheckKotlincFlags(ctx, kotlincFlags)
 
+		kotlin_lang_version := proptools.StringDefault(j.properties.Kotlin_lang_version, "1.9")
+		if kotlin_lang_version == "1.9" {
+			kotlincFlags = append(kotlincFlags, "-language-version 1.9")
+		} else if kotlin_lang_version == "2" {
+			kotlincFlags = append(kotlincFlags, "-Xsuppress-version-warnings", "-Xconsistent-data-class-copy-visibility")
+		} else {
+			ctx.PropertyErrorf("kotlin_lang_version", "Must be one of `1.9` or `2`")
+
+		}
+
 		// Workaround for KT-46512
 		kotlincFlags = append(kotlincFlags, "-Xsam-conversions=class")
 
@@ -2059,7 +2073,9 @@
 		} else if strings.HasPrefix(flag, "-Xintellij-plugin-root") {
 			ctx.PropertyErrorf("kotlincflags",
 				"Bad flag: `%s`, only use internal compiler for consistency.", flag)
-		} else if inList(flag, config.KotlincIllegalFlags) {
+		} else if slices.ContainsFunc(config.KotlincIllegalFlags, func(f string) bool {
+			return strings.HasPrefix(flag, f)
+		}) {
 			ctx.PropertyErrorf("kotlincflags", "Flag `%s` already used by build system", flag)
 		} else if flag == "-include-runtime" {
 			ctx.PropertyErrorf("kotlincflags", "Bad flag: `%s`, do not include runtime.", flag)
diff --git a/java/config/kotlin.go b/java/config/kotlin.go
index bf4c886..ffb025d 100644
--- a/java/config/kotlin.go
+++ b/java/config/kotlin.go
@@ -21,6 +21,7 @@
 	KotlincIllegalFlags = []string{
 		"-no-jdk",
 		"-no-stdlib",
+		"-language-version",
 	}
 )
 
@@ -49,12 +50,12 @@
 		"-J--add-opens=java.base/java.util=ALL-UNNAMED", // https://youtrack.jetbrains.com/issue/KT-43704
 	}, " "))
 
-	pctx.StaticVariable("KotlincGlobalFlags", strings.Join([]string{"-language-version 1.9"}, " "))
+	pctx.StaticVariable("KotlincGlobalFlags", strings.Join([]string{}, " "))
 	// 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
 	// platform that are not fully compatible with the kotlinc used in g3 kythe indexers.
 	// e.g. uninitialized variables are a warning in 1.*, but an error in 2.*
 	// https://github.com/JetBrains/kotlin/blob/master/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt#L748
-	pctx.StaticVariable("KotlincKytheGlobalFlags", strings.Join([]string{"-language-version 1.9"}, " "))
+	pctx.StaticVariable("KotlincKytheGlobalFlags", strings.Join([]string{}, " "))
 }