Introduce prebuilt_any module type

prebuilt_any is a "wildcard" module type that allows installing the
files in any subdirectories within the partition. This module is only
used for converting the PRODUCT_COPY_FILES in fsgen, and should not be
written in the bp files.

Test: m nothing --no-skip-soong-tests
Bug: 375053752
Change-Id: Ic0839b0dbbfa6b012c6b920eecf4ebc6fed8d51f
diff --git a/android/neverallow.go b/android/neverallow.go
index fdcbe1c..3136a15 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -250,6 +250,7 @@
 			NotModuleType("prebuilt_system").
 			NotModuleType("prebuilt_first_stage_ramdisk").
 			NotModuleType("prebuilt_res").
+			NotModuleType("prebuilt_any").
 			Because("install_in_root is only for init_first_stage or librecovery_ui_ext."),
 	}
 }
@@ -341,6 +342,7 @@
 func createPrebuiltEtcBpDefineRule() Rule {
 	return NeverAllow().
 		ModuleType(
+			"prebuilt_any",
 			"prebuilt_usr_srec",
 			"prebuilt_priv_app",
 			"prebuilt_rfs",
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 2bcbde1..e6d50cc 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -85,6 +85,7 @@
 	ctx.RegisterModuleType("prebuilt_sbin", PrebuiltSbinFactory)
 	ctx.RegisterModuleType("prebuilt_system", PrebuiltSystemFactory)
 	ctx.RegisterModuleType("prebuilt_first_stage_ramdisk", PrebuiltFirstStageRamdiskFactory)
+	ctx.RegisterModuleType("prebuilt_any", PrebuiltAnyFactory)
 
 	ctx.RegisterModuleType("prebuilt_defaults", defaultsFactory)
 
@@ -632,6 +633,20 @@
 	return module
 }
 
+// prebuilt_any is a special module where the module can define the subdirectory that the files
+// are installed to. This is only used for converting the PRODUCT_COPY_FILES entries to Soong
+// modules, and should never be defined in the bp files. If none of the existing prebuilt_*
+// modules allow installing the file at the desired location, introduce a new prebuilt_* module
+// type instead.
+func PrebuiltAnyFactory() android.Module {
+	module := &PrebuiltEtc{}
+	InitPrebuiltEtcModule(module, ".")
+	// This module is device-only
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+	android.InitDefaultableModule(module)
+	return module
+}
+
 // prebuilt_etc_host is for a host prebuilt artifact that is installed in
 // <partition>/etc/<sub_dir> directory.
 func PrebuiltEtcCaCertsFactory() android.Module {
diff --git a/fsgen/filesystem_creator_test.go b/fsgen/filesystem_creator_test.go
index 5657608..b47b21e 100644
--- a/fsgen/filesystem_creator_test.go
+++ b/fsgen/filesystem_creator_test.go
@@ -271,6 +271,8 @@
 				"some/non/existing/file.txt:system/etc/file.txt",
 				"device/sample/etc/apns-full-conf.xml:product/etc/apns-conf.xml:google",
 				"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",
 			}
 			config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.PartitionQualifiedVariables =
 				map[string]android.PartitionQualifiedVariablesType{
diff --git a/fsgen/prebuilt_etc_modules_gen.go b/fsgen/prebuilt_etc_modules_gen.go
index e028b1d..0adf7a1 100644
--- a/fsgen/prebuilt_etc_modules_gen.go
+++ b/fsgen/prebuilt_etc_modules_gen.go
@@ -299,6 +299,7 @@
 			etcInstallPathKey = etcInstallPath
 		}
 	}
+	moduleFactory := etcInstallPathToFactoryList[etcInstallPathKey]
 	relDestDirFromInstallDirBase, _ := filepath.Rel(etcInstallPathKey, destDir)
 
 	for fileIndex := range maxLen {
@@ -348,6 +349,11 @@
 				})
 			}
 		} else {
+			// If dsts property has to be set and the selected module type is prebuilt_root,
+			// use prebuilt_any instead.
+			if etcInstallPathKey == "" {
+				moduleFactory = etc.PrebuiltAnyFactory
+			}
 			modulePropsPtr.Srcs = srcBaseFiles
 			dsts := []string{}
 			for _, installBaseFile := range installBaseFiles {
@@ -356,7 +362,7 @@
 			modulePropsPtr.Dsts = dsts
 		}
 
-		ctx.CreateModuleInDirectory(etcInstallPathToFactoryList[etcInstallPathKey], srcDir, propsList...)
+		ctx.CreateModuleInDirectory(moduleFactory, srcDir, propsList...)
 		moduleNames = append(moduleNames, moduleName)
 	}