Merge changes from topic "rm-allowed-deps" into main

* changes:
  Resend aosp/3445142
  Resend aosp/3446212
diff --git a/android/base_module_context.go b/android/base_module_context.go
index d8558d0..4b90083 100644
--- a/android/base_module_context.go
+++ b/android/base_module_context.go
@@ -254,6 +254,9 @@
 }
 
 func getWrappedModule(module blueprint.Module) blueprint.Module {
+	if mp, isProxy := module.(*ModuleProxy); isProxy {
+		return mp.module
+	}
 	if mp, isProxy := module.(ModuleProxy); isProxy {
 		return mp.module
 	}
@@ -291,7 +294,7 @@
 }
 
 func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
-	return b.bp.OtherModuleProvider(m, provider)
+	return b.bp.OtherModuleProvider(getWrappedModule(m), provider)
 }
 
 func (b *baseModuleContext) OtherModuleIsAutoGenerated(m blueprint.Module) bool {
diff --git a/android/module.go b/android/module.go
index 9e620fb..2dd2f19 100644
--- a/android/module.go
+++ b/android/module.go
@@ -2494,6 +2494,8 @@
 			return proptools.ConfigurableValueBool(ctx.Config().BuildFromTextStub())
 		case "debuggable":
 			return proptools.ConfigurableValueBool(ctx.Config().Debuggable())
+		case "eng":
+			return proptools.ConfigurableValueBool(ctx.Config().Eng())
 		case "use_debug_art":
 			// TODO(b/234351700): Remove once ART does not have separated debug APEX
 			return proptools.ConfigurableValueBool(ctx.Config().UseDebugArt())
diff --git a/android/variable.go b/android/variable.go
index 1de8796..d5b731a 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -697,6 +697,10 @@
 	PrivateRecoveryUiProperties map[string]string `json:",omitempty"`
 
 	PrebuiltBootloader string `json:",omitempty"`
+
+	ProductFsCasefold    string `json:",omitempty"`
+	ProductQuotaProjid   string `json:",omitempty"`
+	ProductFsCompression string `json:",omitempty"`
 }
 
 func boolPtr(v bool) *bool {
diff --git a/filesystem/android_device.go b/filesystem/android_device.go
index 83cac74..8332bc5 100644
--- a/filesystem/android_device.go
+++ b/filesystem/android_device.go
@@ -145,7 +145,7 @@
 	a.buildTargetFilesZip(ctx)
 	var deps []android.Path
 	if proptools.String(a.partitionProps.Super_partition_name) != "" {
-		superImage := ctx.GetDirectDepWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
+		superImage := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
 		if info, ok := android.OtherModuleProvider(ctx, superImage, SuperImageProvider); ok {
 			assertUnset := func(prop *string, propName string) {
 				if prop != nil && *prop != "" {
@@ -182,7 +182,7 @@
 			ctx.ModuleErrorf("Expected super image dep to provide SuperImageProvider")
 		}
 	}
-	ctx.VisitDirectDepsWithTag(filesystemDepTag, func(m android.Module) {
+	ctx.VisitDirectDepsProxyWithTag(filesystemDepTag, func(m android.ModuleProxy) {
 		imageOutput, ok := android.OtherModuleProvider(ctx, m, android.OutputFilesProvider)
 		if !ok {
 			ctx.ModuleErrorf("Partition module %s doesn't set OutputfilesProvider", m.Name())
@@ -274,7 +274,7 @@
 	}
 	// Get additional filesystems from super_partition dependency
 	if a.partitionProps.Super_partition_name != nil {
-		superPartition := ctx.GetDirectDepWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
+		superPartition := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
 		if info, ok := android.OtherModuleProvider(ctx, superPartition, SuperImageProvider); ok {
 			for _, partition := range android.SortedStringKeys(info.SubImageInfo) {
 				filesystemsToCopy = append(
@@ -305,7 +305,7 @@
 	}
 	// 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)
+		bootImg := ctx.GetDirectDepProxyWithTag(proptools.String(a.partitionProps.Vendor_boot_partition_name), filesystemDepTag)
 		bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider)
 		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)
@@ -317,7 +317,7 @@
 		}
 	}
 	if a.partitionProps.Boot_partition_name != nil {
-		bootImg := ctx.GetDirectDepWithTag(proptools.String(a.partitionProps.Boot_partition_name), filesystemDepTag)
+		bootImg := ctx.GetDirectDepProxyWithTag(proptools.String(a.partitionProps.Boot_partition_name), filesystemDepTag)
 		bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider)
 		builder.Command().Textf("echo %s > %s/BOOT/cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir)
 		if bootImgInfo.Dtb != nil {
@@ -374,10 +374,11 @@
 	})
 
 	if a.partitionProps.Super_partition_name != nil {
-		superPartition := ctx.GetDirectDepWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
+		superPartition := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
 		if info, ok := android.OtherModuleProvider(ctx, superPartition, SuperImageProvider); ok {
-			for _, partition := range android.SortedStringKeys(info.SubImageInfo) {
+			for _, partition := range android.SortedKeys(info.SubImageInfo) {
 				builder.Command().Textf("cp ").Input(info.SubImageInfo[partition].Output).Textf(" %s/IMAGES/", targetFilesDir.String())
+				builder.Command().Textf("cp ").Input(info.SubImageInfo[partition].MapFile).Textf(" %s/IMAGES/", targetFilesDir.String())
 			}
 		} else {
 			ctx.ModuleErrorf("Super partition %s does set SuperImageProvider\n", superPartition.Name())
@@ -386,7 +387,7 @@
 }
 
 func (a *androidDevice) getFilesystemInfo(ctx android.ModuleContext, depName string) FilesystemInfo {
-	fsMod := ctx.GetDirectDepWithTag(depName, filesystemDepTag)
+	fsMod := ctx.GetDirectDepProxyWithTag(depName, filesystemDepTag)
 	fsInfo, ok := android.OtherModuleProvider(ctx, fsMod, FilesystemProvider)
 	if !ok {
 		ctx.ModuleErrorf("Expected dependency %s to be a filesystem", depName)
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index a315160..469fd9e 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -222,6 +222,15 @@
 	// The size of the partition on the device. It will be a build error if this built partition
 	// image exceeds this size.
 	Partition_size *int64
+
+	// Whether to format f2fs and ext4 in a way that supports casefolding
+	Support_casefolding *bool
+
+	// Whether to format f2fs and ext4 in a way that supports project quotas
+	Support_project_quota *bool
+
+	// Whether to enable per-file compression in f2fs
+	Enable_compression *bool
 }
 
 type AndroidFilesystemDeps struct {
@@ -360,6 +369,9 @@
 	// to add a dependency on the Output file, as you cannot add dependencies on directories
 	// in ninja.
 	RootDir android.Path
+	// A text file with block data of the .img file
+	// This is an implicit output of `build_image`
+	MapFile android.Path
 }
 
 var FilesystemProvider = blueprint.NewProvider[FilesystemInfo]()
@@ -447,9 +459,11 @@
 	}
 
 	var rootDir android.OutputPath
+	var mapFile android.Path
 	switch f.fsType(ctx) {
 	case ext4Type, erofsType, f2fsType:
 		f.output, rootDir = f.buildImageUsingBuildImage(ctx)
+		mapFile = f.getMapFile(ctx)
 	case compressedCpioType:
 		f.output, rootDir = f.buildCpioImage(ctx, true)
 	case cpioType:
@@ -469,11 +483,16 @@
 	fileListFile := android.PathForModuleOut(ctx, "fileList")
 	android.WriteFileRule(ctx, fileListFile, f.installedFilesList())
 
-	android.SetProvider(ctx, FilesystemProvider, FilesystemInfo{
+	fsInfo := FilesystemInfo{
 		Output:       f.output,
 		FileListFile: fileListFile,
 		RootDir:      rootDir,
-	})
+	}
+	if mapFile != nil {
+		fsInfo.MapFile = mapFile
+	}
+
+	android.SetProvider(ctx, FilesystemProvider, fsInfo)
 
 	f.fileListFile = fileListFile
 
@@ -482,6 +501,11 @@
 	}
 }
 
+func (f *filesystem) getMapFile(ctx android.ModuleContext) android.WritablePath {
+	// create the filepath by replacing the extension of the corresponding img file
+	return android.PathForModuleOut(ctx, f.installFileName()).ReplaceExtension(ctx, "map")
+}
+
 func (f *filesystem) validateVintfFragments(ctx android.ModuleContext) {
 	visitedModule := map[string]bool{}
 	packagingSpecs := f.gatherFilteredPackagingSpecs(ctx)
@@ -662,6 +686,7 @@
 	pathToolDirs := []string{filepath.Dir(fec.String())}
 
 	output := android.PathForModuleOut(ctx, f.installFileName())
+	builder.Command().Text("touch").Output(f.getMapFile(ctx))
 	builder.Command().
 		Textf("PATH=%s:$PATH", strings.Join(pathToolDirs, ":")).
 		BuiltTool("build_image").
@@ -723,6 +748,7 @@
 		}
 		panic(fmt.Errorf("unsupported fs type %v", t))
 	}
+	addStr("block_list", f.getMapFile(ctx).String()) // This will be an implicit output
 
 	addStr("fs_type", fsTypeStr(f.fsType(ctx)))
 	addStr("mount_point", proptools.StringDefault(f.properties.Mount_point, "/"))
@@ -789,12 +815,11 @@
 		addStr("hash_seed", uuid)
 	}
 
-	// TODO(b/381120092): This should only be added if none of the size-related properties are set,
-	// but currently soong built partitions don't have size properties. Make code:
-	// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2262;drc=39cd33701c9278db0e7e481a090605f428d5b12d
-	// Make uses system_disable_sparse but disable_sparse has the same effect, and we shouldn't need
-	// to qualify it because each partition gets its own property file built.
-	addStr("disable_sparse", "true")
+	// Disable sparse only when partition size is not defined. disable_sparse has the same
+	// effect as <partition name>_disable_sparse.
+	if f.properties.Partition_size == nil {
+		addStr("disable_sparse", "true")
+	}
 
 	fst := f.fsType(ctx)
 	switch fst {
@@ -821,6 +846,18 @@
 		addStr("partition_size", strconv.FormatInt(*f.properties.Partition_size, 10))
 	}
 
+	if proptools.BoolDefault(f.properties.Support_casefolding, false) {
+		addStr("needs_casefold", "1")
+	}
+
+	if proptools.BoolDefault(f.properties.Support_project_quota, false) {
+		addStr("needs_projid", "1")
+	}
+
+	if proptools.BoolDefault(f.properties.Enable_compression, false) {
+		addStr("needs_compress", "1")
+	}
+
 	propFilePreProcessing := android.PathForModuleOut(ctx, "prop_pre_processing")
 	android.WriteFileRuleVerbatim(ctx, propFilePreProcessing, propFileString.String())
 	propFile := android.PathForModuleOut(ctx, "prop")
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index 8dfbd64..9aed460 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -381,7 +381,26 @@
 				panic(fmt.Sprintf("Partition size must be an int, got %s", vars.BoardPartitionSize))
 			}
 			fsProps.Partition_size = &parsed
+			// Disable avb for userdata partition
+			fsProps.Use_avb = nil
 		}
+		// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2265;drc=7f50a123045520f2c5e18e9eb4e83f92244a1459
+		if s, err := strconv.ParseBool(partitionVars.ProductFsCasefold); err == nil {
+			fsProps.Support_casefolding = proptools.BoolPtr(s)
+		} else if len(partitionVars.ProductFsCasefold) > 0 {
+			ctx.ModuleErrorf("Unrecognized PRODUCT_FS_CASEFOLD value %s", partitionVars.ProductFsCasefold)
+		}
+		if s, err := strconv.ParseBool(partitionVars.ProductQuotaProjid); err == nil {
+			fsProps.Support_project_quota = proptools.BoolPtr(s)
+		} else if len(partitionVars.ProductQuotaProjid) > 0 {
+			ctx.ModuleErrorf("Unrecognized PRODUCT_QUOTA_PROJID value %s", partitionVars.ProductQuotaProjid)
+		}
+		if s, err := strconv.ParseBool(partitionVars.ProductFsCompression); err == nil {
+			fsProps.Enable_compression = proptools.BoolPtr(s)
+		} else if len(partitionVars.ProductFsCompression) > 0 {
+			ctx.ModuleErrorf("Unrecognized PRODUCT_FS_COMPRESSION value %s", partitionVars.ProductFsCompression)
+		}
+
 	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{
diff --git a/fsgen/vbmeta_partitions.go b/fsgen/vbmeta_partitions.go
index 11c5759..d146cbb 100644
--- a/fsgen/vbmeta_partitions.go
+++ b/fsgen/vbmeta_partitions.go
@@ -154,8 +154,8 @@
 			// Already handled by a chained vbmeta partition
 			continue
 		}
-		if strings.Contains(partitionType, "ramdisk") || strings.Contains(partitionType, "boot") {
-			// ramdisk is never signed with avb information
+		if strings.Contains(partitionType, "ramdisk") || strings.Contains(partitionType, "boot") || partitionType == "userdata" {
+			// ramdisk and userdata are never signed with avb information
 			// boot partitions just have the avb footer, and don't have a corresponding vbmeta
 			// partition.
 			continue
diff --git a/tests/sbom_test.sh b/tests/sbom_test.sh
index 0471853..2ef9e37 100755
--- a/tests/sbom_test.sh
+++ b/tests/sbom_test.sh
@@ -83,6 +83,12 @@
   dump_erofs=$out_dir/host/linux-x86/bin/dump.erofs
   lz4=$out_dir/host/linux-x86/bin/lz4
 
+  declare -A diff_excludes
+  diff_excludes[system]="\
+    -I /etc/NOTICE.xml.gz \
+    -I /odm_dlkm/etc \
+    -I /vendor_dlkm/etc"
+
   # Example output of dump.erofs is as below, and the data used in the test start
   # at line 11. Column 1 is inode id, column 2 is inode type and column 3 is name.
   # Each line is captured in variable "entry", awk is used to get type and name.
@@ -155,7 +161,11 @@
     sort -n -o "$files_in_soong_spdx_file" "$files_in_soong_spdx_file"
 
     echo ============ Diffing files in $f and SBOM created by Soong
-    diff_files "$file_list_file" "$files_in_soong_spdx_file" "$partition_name" ""
+    exclude=
+    if [ -v 'diff_excludes[$partition_name]' ]; then
+     exclude=${diff_excludes[$partition_name]}
+    fi
+    diff_files "$file_list_file" "$files_in_soong_spdx_file" "$partition_name" "$exclude"
   done
 
   RAMDISK_IMAGES="$product_out/ramdisk.img"
@@ -230,10 +240,10 @@
     exit 1
   fi
 
-  # PRODUCT and 7 prebuilt packages have "PackageLicenseDeclared: NOASSERTION"
+  # PRODUCT and 6 prebuilt packages have "PackageLicenseDeclared: NOASSERTION"
   # All other packages have declared licenses
   num_of_packages_with_noassertion_license=$(grep 'PackageLicenseDeclared: NOASSERTION' $sbom_file | wc -l)
-  if [ $num_of_packages_with_noassertion_license = 15 ]
+  if [ $num_of_packages_with_noassertion_license = 13 ]
   then
     echo "Number of packages with NOASSERTION license is correct."
   else