Merge changes Ia60fadb8,I13310d60 into main

* changes:
  Add a partial IMAGES/ subdir for target_files.zip
  Add a Stem property to filesystem
diff --git a/filesystem/android_device.go b/filesystem/android_device.go
index 83d56c6..555eddc 100644
--- a/filesystem/android_device.go
+++ b/filesystem/android_device.go
@@ -208,6 +208,9 @@
 		toCopy = append(toCopy, targetFilesZipCopy{a.partitionProps.Recovery_partition_name, "VENDOR_BOOT/RAMDISK"})
 	}
 
+	// Create an IMAGES/ subdirectory
+	builder.Command().Textf("mkdir -p %s/IMAGES/", targetFilesDir.String())
+
 	for _, zipCopy := range toCopy {
 		if zipCopy.srcModule == nil {
 			continue
@@ -228,6 +231,7 @@
 			// Create the ROOT partition in target_files.zip
 			builder.Command().Textf("rsync --links --exclude=system/* %s/ -r %s/ROOT", fsInfo.RootDir, targetFilesDir.String())
 		}
+		builder.Command().Textf("cp %s %s/IMAGES/", fsInfo.Output, targetFilesDir.String())
 	}
 	// Copy cmdline, kernel etc. files of boot images
 	if a.partitionProps.Vendor_boot_partition_name != nil {
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 1861d8e..993c46e 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -215,6 +215,9 @@
 
 	// Additional dependencies used for building android products
 	Android_filesystem_deps AndroidFilesystemDeps
+
+	// Name of the output. Default is $(module_name).img
+	Stem *string
 }
 
 type AndroidFilesystemDeps struct {
@@ -392,7 +395,7 @@
 }
 
 func (f *filesystem) installFileName() string {
-	return f.BaseModuleName() + ".img"
+	return proptools.StringDefault(f.properties.Stem, f.BaseModuleName()+".img")
 }
 
 func (f *filesystem) partitionName() string {
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index 590d33a..a070e01 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -321,6 +321,7 @@
 		if ctx.DeviceConfig().SystemExtPath() == "system_ext" {
 			fsProps.Import_aconfig_flags_from = []string{generatedModuleNameForPartition(ctx.Config(), "system_ext")}
 		}
+		fsProps.Stem = proptools.StringPtr("system.img")
 	case "system_ext":
 		if partitionVars.ProductFsverityGenerateMetadata {
 			fsProps.Fsverity.Inputs = []string{
@@ -331,6 +332,7 @@
 			fsProps.Fsverity.Libs = []string{":framework-res{.export-package.apk}"}
 		}
 		fsProps.Security_patch = proptools.StringPtr(ctx.Config().PlatformSecurityPatch())
+		fsProps.Stem = proptools.StringPtr("system_ext.img")
 	case "product":
 		fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
 		fsProps.Android_filesystem_deps.System = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system"))
@@ -338,6 +340,7 @@
 			fsProps.Android_filesystem_deps.System_ext = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext"))
 		}
 		fsProps.Security_patch = proptools.StringPtr(ctx.Config().PlatformSecurityPatch())
+		fsProps.Stem = proptools.StringPtr("product.img")
 	case "vendor":
 		fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
 		fsProps.Symlinks = []filesystem.SymlinkDefinition{
@@ -355,6 +358,7 @@
 			fsProps.Android_filesystem_deps.System_ext = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext"))
 		}
 		fsProps.Security_patch = proptools.StringPtr(partitionVars.VendorSecurityPatch)
+		fsProps.Stem = proptools.StringPtr("vendor.img")
 	case "odm":
 		fsProps.Symlinks = []filesystem.SymlinkDefinition{
 			filesystem.SymlinkDefinition{
@@ -363,8 +367,10 @@
 			},
 		}
 		fsProps.Security_patch = proptools.StringPtr(partitionVars.OdmSecurityPatch)
+		fsProps.Stem = proptools.StringPtr("odm.img")
 	case "userdata":
 		fsProps.Base_dir = proptools.StringPtr("data")
+		fsProps.Stem = proptools.StringPtr("userdata.img")
 	case "ramdisk":
 		// Following the logic in https://cs.android.com/android/platform/superproject/main/+/c3c5063df32748a8806ce5da5dd0db158eab9ad9:build/make/core/Makefile;l=1307
 		fsProps.Dirs = android.NewSimpleConfigurable([]string{
@@ -387,6 +393,7 @@
 				"first_stage_ramdisk/sys",
 			})
 		}
+		fsProps.Stem = proptools.StringPtr("ramdisk.img")
 	case "recovery":
 		dirs := append(commonPartitionDirs, []string{
 			"sdcard",
@@ -402,16 +409,21 @@
 			Target: proptools.StringPtr("prop.default"),
 			Name:   proptools.StringPtr("default.prop"),
 		}), "root")
+		fsProps.Stem = proptools.StringPtr("recovery.img")
 	case "system_dlkm":
 		fsProps.Security_patch = proptools.StringPtr(partitionVars.SystemDlkmSecurityPatch)
+		fsProps.Stem = proptools.StringPtr("system_dlkm.img")
 	case "vendor_dlkm":
 		fsProps.Security_patch = proptools.StringPtr(partitionVars.VendorDlkmSecurityPatch)
+		fsProps.Stem = proptools.StringPtr("vendor_dlkm.img")
 	case "odm_dlkm":
 		fsProps.Security_patch = proptools.StringPtr(partitionVars.OdmDlkmSecurityPatch)
+		fsProps.Stem = proptools.StringPtr("odm_dlkm.img")
 	case "vendor_ramdisk":
 		if android.InList("recovery", generatedPartitions(ctx)) {
 			fsProps.Include_files_of = []string{generatedModuleNameForPartition(ctx.Config(), "recovery")}
 		}
+		fsProps.Stem = proptools.StringPtr("vendor_ramdisk.img")
 	}
 }