Merge changes Idda28cf7,I15782670 into main

* changes:
  Panic prebuilt etc module gen test if module isn't PrebuiltEtc
  fsgen: Use prebuilt_{root,any} in case install_in_root is set
diff --git a/fsgen/filesystem_creator_test.go b/fsgen/filesystem_creator_test.go
index 651d2d1..2c4d3c8 100644
--- a/fsgen/filesystem_creator_test.go
+++ b/fsgen/filesystem_creator_test.go
@@ -289,6 +289,10 @@
 				"device/sample/etc/apns-full-conf.xml:product/etc/apns-conf-2.xml",
 				"device/sample/etc/apns-full-conf.xml:system/foo/file.txt",
 				"device/sample/etc/apns-full-conf.xml:system/foo/apns-full-conf.xml",
+				"device/sample/firmware/firmware.bin:recovery/root/firmware.bin",
+				"device/sample/firmware/firmware.bin:recovery/root/firmware-2.bin",
+				"device/sample/firmware/firmware.bin:recovery/root/lib/firmware/firmware.bin",
+				"device/sample/firmware/firmware.bin:recovery/root/lib/firmware/firmware-2.bin",
 			}
 			config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.PartitionQualifiedVariables =
 				map[string]android.PartitionQualifiedVariablesType{
@@ -309,6 +313,7 @@
 			"frameworks/base/data/keyboards/Vendor_0079_Product_0011.kl": nil,
 			"frameworks/base/data/keyboards/Vendor_0079_Product_18d4.kl": nil,
 			"device/sample/etc/apns-full-conf.xml":                       nil,
+			"device/sample/firmware/firmware.bin":                        nil,
 		}),
 	).RunTest(t)
 
@@ -324,7 +329,7 @@
 
 	// check generated prebuilt_* module type install path and install partition
 	generatedModule := result.ModuleForTests(t, "system-frameworks_base_config-etc-0", "android_arm64_armv8-a").Module()
-	etcModule, _ := generatedModule.(*etc.PrebuiltEtc)
+	etcModule := generatedModule.(*etc.PrebuiltEtc)
 	android.AssertStringEquals(
 		t,
 		"module expected to have etc install path",
@@ -342,7 +347,7 @@
 
 	// check generated prebuilt_* module specifies correct relative_install_path property
 	generatedModule = result.ModuleForTests(t, "system-frameworks_base_data_keyboards-usr_keylayout_subdir-0", "android_arm64_armv8-a").Module()
-	etcModule, _ = generatedModule.(*etc.PrebuiltEtc)
+	etcModule = generatedModule.(*etc.PrebuiltEtc)
 	android.AssertStringEquals(
 		t,
 		"module expected to set correct relative_install_path properties",
@@ -490,7 +495,7 @@
 	)
 
 	// check generated prebuilt_* module specifies correct install path and relative install path
-	etcModule, _ = generatedModule1.(*etc.PrebuiltEtc)
+	etcModule = generatedModule1.(*etc.PrebuiltEtc)
 	android.AssertStringEquals(
 		t,
 		"module expected to have . install path",
@@ -520,4 +525,138 @@
 			return ""
 		}),
 	)
+
+	generatedModule0 = result.ModuleForTests(t, "recovery-device_sample_firmware-0", "android_recovery_arm64_armv8-a").Module()
+	generatedModule1 = result.ModuleForTests(t, "recovery-device_sample_firmware-1", "android_recovery_common").Module()
+
+	// check generated prebuilt_* module specifies correct install path and relative install path
+	etcModule = generatedModule0.(*etc.PrebuiltEtc)
+	android.AssertStringEquals(
+		t,
+		"module expected to have . install path",
+		".",
+		etcModule.BaseDir(),
+	)
+	android.AssertStringEquals(
+		t,
+		"module expected to set empty relative_install_path properties",
+		"",
+		etcModule.SubDir(),
+	)
+
+	// check that generated prebuilt_* module don't set dsts
+	eval = generatedModule0.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
+	android.AssertStringEquals(
+		t,
+		"module expected to not set dsts property",
+		"",
+		getModuleProp(generatedModule0, func(actual interface{}) string {
+			if p, ok := actual.(*etc.PrebuiltDstsProperties); ok {
+				dsts := p.Dsts.GetOrDefault(eval, nil)
+				if len(dsts) != 0 {
+					return dsts[0]
+				}
+			}
+			return ""
+		}),
+	)
+
+	// check generated prebuilt_* module specifies correct install path and relative install path
+	etcModule = generatedModule1.(*etc.PrebuiltEtc)
+	android.AssertStringEquals(
+		t,
+		"module expected to have . install path",
+		".",
+		etcModule.BaseDir(),
+	)
+	android.AssertStringEquals(
+		t,
+		"module expected to set empty relative_install_path properties",
+		"",
+		etcModule.SubDir(),
+	)
+
+	// check that generated prebuilt_* module sets correct dsts
+	eval = generatedModule1.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
+	android.AssertStringEquals(
+		t,
+		"module expected to set correct dsts property",
+		"firmware-2.bin",
+		getModuleProp(generatedModule1, func(actual interface{}) string {
+			if p, ok := actual.(*etc.PrebuiltDstsProperties); ok {
+				dsts := p.Dsts.GetOrDefault(eval, nil)
+				if len(dsts) == 1 {
+					return dsts[0]
+				}
+			}
+			return ""
+		}),
+	)
+
+	generatedModule0 = result.ModuleForTests(t, "recovery-device_sample_firmware-lib_firmware-0", "android_recovery_common").Module()
+	generatedModule1 = result.ModuleForTests(t, "recovery-device_sample_firmware-lib_firmware-1", "android_recovery_common").Module()
+
+	// check generated prebuilt_* module specifies correct install path and relative install path
+	etcModule = generatedModule0.(*etc.PrebuiltEtc)
+	android.AssertStringEquals(
+		t,
+		"module expected to have . install path",
+		".",
+		etcModule.BaseDir(),
+	)
+	android.AssertStringEquals(
+		t,
+		"module expected to set correct relative_install_path properties",
+		"lib/firmware",
+		etcModule.SubDir(),
+	)
+
+	// check that generated prebuilt_* module sets correct srcs
+	eval = generatedModule0.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
+	android.AssertStringEquals(
+		t,
+		"module expected to not set dsts property",
+		"",
+		getModuleProp(generatedModule0, func(actual interface{}) string {
+			if p, ok := actual.(*etc.PrebuiltDstsProperties); ok {
+				dsts := p.Dsts.GetOrDefault(eval, nil)
+				if len(dsts) != 0 {
+					return dsts[0]
+				}
+			}
+			return ""
+		}),
+	)
+
+	// check generated prebuilt_* module specifies correct install path and relative install path
+	etcModule = generatedModule1.(*etc.PrebuiltEtc)
+	android.AssertStringEquals(
+		t,
+		"module expected to have . install path",
+		".",
+		etcModule.BaseDir(),
+	)
+	android.AssertStringEquals(
+		t,
+		"module expected to set empty relative_install_path properties",
+		"",
+		etcModule.SubDir(),
+	)
+
+	// check that generated prebuilt_* module sets correct srcs
+	eval = generatedModule1.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
+	android.AssertStringEquals(
+		t,
+		"module expected to set correct dsts property",
+		"lib/firmware/firmware-2.bin",
+		getModuleProp(generatedModule1, func(actual interface{}) string {
+			if p, ok := actual.(*etc.PrebuiltDstsProperties); ok {
+				dsts := p.Dsts.GetOrDefault(eval, nil)
+				if len(dsts) == 1 {
+					return dsts[0]
+				}
+			}
+			return ""
+		}),
+	)
 }
diff --git a/fsgen/prebuilt_etc_modules_gen.go b/fsgen/prebuilt_etc_modules_gen.go
index e9dabe4..c0f114c 100644
--- a/fsgen/prebuilt_etc_modules_gen.go
+++ b/fsgen/prebuilt_etc_modules_gen.go
@@ -337,6 +337,10 @@
 			propsList = append(propsList, &prebuiltInstallInRootProperties{
 				Install_in_root: proptools.BoolPtr(true),
 			})
+			// Discard any previously picked module and force it to prebuilt_{root,any} as
+			// they are the only modules allowed to specify the `install_in_root` property.
+			etcInstallPathKey = ""
+			relDestDirFromInstallDirBase = destDir
 		}
 
 		// Set appropriate srcs, dsts, and releative_install_path based on