Allow building userdata partition in Soong

The soong vs make generated userdata images are still not bit identical,
but this change resolves execution time failure from build_image when
building userdata.img.

Implementation details:
- Introduce partition_size property to filesystem module
- Specify the correct mount point for userdata partition

Test: m out/soong/.intermediates/build/soong/fsgen/aosp_cf_x86_64_phone_generated_userdata_image/android_common/userdata.img
Bug: 388920173
Change-Id: I2c0945ce70d74c632ba241c8a93c60763cfe87e7
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 993c46e..a315160 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -218,6 +218,10 @@
 
 	// Name of the output. Default is $(module_name).img
 	Stem *string
+
+	// 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
 }
 
 type AndroidFilesystemDeps struct {
@@ -672,6 +676,10 @@
 		copyImageFileToProductOut(ctx, builder, f.partitionName(), output)
 	}
 
+	if f.properties.Partition_size != nil {
+		assertMaxImageSize(builder, output, *f.properties.Partition_size, false)
+	}
+
 	// rootDir is not deleted. Might be useful for quick inspection.
 	builder.Build("build_filesystem_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName()))
 
@@ -809,6 +817,10 @@
 	}
 	f.checkFsTypePropertyError(ctx, fst, fsTypeStr(fst))
 
+	if f.properties.Partition_size != nil {
+		addStr("partition_size", strconv.FormatInt(*f.properties.Partition_size, 10))
+	}
+
 	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 9d61a60..8dfbd64 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -374,8 +374,14 @@
 		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")
+		if vars, ok := partitionVars.PartitionQualifiedVariables["userdata"]; ok {
+			parsed, err := strconv.ParseInt(vars.BoardPartitionSize, 10, 64)
+			if err != nil {
+				panic(fmt.Sprintf("Partition size must be an int, got %s", vars.BoardPartitionSize))
+			}
+			fsProps.Partition_size = &parsed
+		}
 	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{
@@ -822,7 +828,13 @@
 
 	fsProps.Is_auto_generated = proptools.BoolPtr(true)
 	if partitionType != "system" {
-		fsProps.Mount_point = proptools.StringPtr(partitionType)
+		mountPoint := proptools.StringPtr(partitionType)
+		// https://cs.android.com/android/platform/superproject/main/+/main:build/make/tools/releasetools/build_image.py;l=1012;drc=3f576a753594bad3fc838ccb8b1b72f7efac1d50
+		if partitionType == "userdata" {
+			mountPoint = proptools.StringPtr("data")
+		}
+		fsProps.Mount_point = mountPoint
+
 	}
 
 	partitionSpecificFsProps(ctx, fsProps, partitionVars, partitionType)