Modify the installation rules of sh binary based on the image variants

This change modifes the build rules of sh binary module type so that:
- The installation paths respects the image variations and the
  *_available properties.
- The androidmk entries have subnames so that the names of the different
  variants do not collide.

Test: Patch ag/27004177 and run m nothing
Bug: 336582138
Change-Id: Id85c428980ab459bff8d84098bd6c501a12231ed
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 3a4adc6..3f82560 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -99,6 +99,12 @@
 
 	// Make this module available when building for recovery.
 	Recovery_available *bool
+
+	// The name of the image this module is built for
+	ImageVariation string `blueprint:"mutated"`
+
+	// Suffix for the name of Android.mk entries generated by this module
+	SubName string `blueprint:"mutated"`
 }
 
 type TestProperties struct {
@@ -207,15 +213,15 @@
 func (s *ShBinary) ImageMutatorBegin(ctx android.BaseModuleContext) {}
 
 func (s *ShBinary) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
-	return !s.ModuleBase.InstallInRecovery() && !s.ModuleBase.InstallInRamdisk()
+	return !s.InstallInRecovery() && !s.InstallInRamdisk() && !s.InstallInVendorRamdisk() && !s.ModuleBase.InstallInVendor()
 }
 
 func (s *ShBinary) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
-	return proptools.Bool(s.properties.Ramdisk_available) || s.ModuleBase.InstallInRamdisk()
+	return proptools.Bool(s.properties.Ramdisk_available) || s.InstallInRamdisk()
 }
 
 func (s *ShBinary) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
-	return proptools.Bool(s.properties.Vendor_ramdisk_available) || s.ModuleBase.InstallInVendorRamdisk()
+	return proptools.Bool(s.properties.Vendor_ramdisk_available) || s.InstallInVendorRamdisk()
 }
 
 func (s *ShBinary) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
@@ -223,14 +229,45 @@
 }
 
 func (s *ShBinary) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
-	return proptools.Bool(s.properties.Recovery_available) || s.ModuleBase.InstallInRecovery()
+	return proptools.Bool(s.properties.Recovery_available) || s.InstallInRecovery()
 }
 
 func (s *ShBinary) ExtraImageVariations(ctx android.BaseModuleContext) []string {
-	return nil
+	extraVariations := []string{}
+	if s.InstallInProduct() {
+		extraVariations = append(extraVariations, cc.ProductVariation)
+	}
+	if s.InstallInVendor() {
+		extraVariations = append(extraVariations, cc.VendorVariation)
+	}
+	return extraVariations
 }
 
 func (s *ShBinary) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
+	if m, ok := module.(*ShBinary); ok {
+		m.properties.ImageVariation = variation
+	}
+}
+
+// Overrides ModuleBase.InstallInRamdisk() so that the install rule respects
+// Ramdisk_available property for ramdisk variant
+func (s *ShBinary) InstallInRamdisk() bool {
+	return s.ModuleBase.InstallInRamdisk() ||
+		(proptools.Bool(s.properties.Ramdisk_available) && s.properties.ImageVariation == android.RamdiskVariation)
+}
+
+// Overrides ModuleBase.InstallInVendorRamdisk() so that the install rule respects
+// Vendor_ramdisk_available property for vendor ramdisk variant
+func (s *ShBinary) InstallInVendorRamdisk() bool {
+	return s.ModuleBase.InstallInVendorRamdisk() ||
+		(proptools.Bool(s.properties.Vendor_ramdisk_available) && s.properties.ImageVariation == android.VendorRamdiskVariation)
+}
+
+// Overrides ModuleBase.InstallInRecovery() so that the install rule respects
+// Recovery_available property for recovery variant
+func (s *ShBinary) InstallInRecovery() bool {
+	return s.ModuleBase.InstallInRecovery() ||
+		(proptools.Bool(s.properties.Recovery_available) && s.properties.ImageVariation == android.RecoveryVariation)
 }
 
 func (s *ShBinary) generateAndroidBuildActions(ctx android.ModuleContext) {
@@ -260,11 +297,24 @@
 		Output: s.outputFilePath,
 		Input:  s.sourceFilePath,
 	})
+
+	s.properties.SubName = s.GetSubname(ctx)
+
 	android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: []string{s.sourceFilePath.String()}})
 
 	ctx.SetOutputFiles(android.Paths{s.outputFilePath}, "")
 }
 
+func (s *ShBinary) GetSubname(ctx android.ModuleContext) string {
+	ret := ""
+	if s.properties.ImageVariation != "" {
+		if s.properties.ImageVariation != cc.VendorVariation {
+			ret = "." + s.properties.ImageVariation
+		}
+	}
+	return ret
+}
+
 func (s *ShBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	s.generateAndroidBuildActions(ctx)
 	installDir := android.PathForModuleInstall(ctx, "bin", proptools.String(s.properties.Sub_dir))
@@ -278,7 +328,7 @@
 }
 
 func (s *ShBinary) AndroidMkEntries() []android.AndroidMkEntries {
-	return []android.AndroidMkEntries{android.AndroidMkEntries{
+	return []android.AndroidMkEntries{{
 		Class:      "EXECUTABLES",
 		OutputFile: android.OptionalPathForPath(s.outputFilePath),
 		Include:    "$(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk",
@@ -289,6 +339,7 @@
 				entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !s.Installable())
 			},
 		},
+		SubName: s.properties.SubName,
 	}}
 }