Build system_other image in soong-only builds

This just builds an empty system_other image for now, the dexpreopt
files will be added in a followup change.

Bug: 390269431
Test: m --soong-only
Change-Id: Ic4a9bcb8b7ba1eb4444b3339d6c0b0cdfd485714
diff --git a/filesystem/super_image.go b/filesystem/super_image.go
index 4419a2f..5332462 100644
--- a/filesystem/super_image.go
+++ b/filesystem/super_image.go
@@ -18,6 +18,7 @@
 	"fmt"
 	"path/filepath"
 	"regexp"
+	"slices"
 	"strconv"
 	"strings"
 
@@ -55,6 +56,9 @@
 	Sparse *bool
 	// information about how partitions within the super partition are grouped together
 	Partition_groups []PartitionGroupsInfo
+	// Name of the system_other partition filesystem module. This module will be installed to
+	// the "b" slot of the system partition in a/b partition builds.
+	System_other_partition *string
 	// whether dynamic partitions is used
 	Use_dynamic_partitions *bool
 	Virtual_ab             struct {
@@ -127,6 +131,12 @@
 
 var subImageDepTag superImageDepTagType
 
+type systemOtherDepTagType struct {
+	blueprint.BaseDependencyTag
+}
+
+var systemOtherDepTag systemOtherDepTagType
+
 func (s *superImage) DepsMutator(ctx android.BottomUpMutatorContext) {
 	addDependencyIfDefined := func(dep *string) {
 		if dep != nil {
@@ -143,6 +153,9 @@
 	addDependencyIfDefined(s.partitionProps.Vendor_dlkm_partition)
 	addDependencyIfDefined(s.partitionProps.Odm_partition)
 	addDependencyIfDefined(s.partitionProps.Odm_dlkm_partition)
+	if s.properties.System_other_partition != nil {
+		ctx.AddDependency(ctx.Module(), systemOtherDepTag, *s.properties.System_other_partition)
+	}
 }
 
 func (s *superImage) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -299,6 +312,20 @@
 		}
 	}
 
+	if s.properties.System_other_partition != nil {
+		if !slices.Contains(partitionList, "system") {
+			ctx.PropertyErrorf("system_other_partition", "Must have a system partition to use a system_other partition")
+		}
+		systemOther := ctx.GetDirectDepProxyWithTag(*s.properties.System_other_partition, systemOtherDepTag)
+		systemOtherFiles := android.OutputFilesForModule(ctx, systemOther, "")
+		if len(systemOtherFiles) != 1 {
+			ctx.PropertyErrorf("system_other_partition", "Expected 1 output file from module %q", *&s.properties.System_other_partition)
+		} else {
+			addStr("system_other_image", systemOtherFiles[0].String())
+			deps = append(deps, systemOtherFiles[0])
+		}
+	}
+
 	// Delay the error message until execution time because on aosp-main-future-without-vendor,
 	// BUILDING_VENDOR_IMAGE is false so we don't get the vendor image, but it's still listed in
 	// BOARD_GOOGLE_DYNAMIC_PARTITIONS_PARTITION_LIST.