Merge "Make ModifyPackagingSpec generic to any filesystem" into main
diff --git a/android/paths.go b/android/paths.go
index 3f67c55..8f066cc 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -2613,3 +2613,19 @@
}
return false
}
+
+// ToRelativeSourcePath converts absolute source path to the path relative to the source root.
+// This throws an error if the input path is outside of the source root and cannot be converted
+// to the relative path.
+// This should be rarely used given that the source path is relative in Soong.
+func ToRelativeSourcePath(ctx PathContext, path string) string {
+ ret := path
+ if filepath.IsAbs(path) {
+ relPath, err := filepath.Rel(absSrcDir, path)
+ if err != nil || strings.HasPrefix(relPath, "..") {
+ ReportPathErrorf(ctx, "%s is outside of the source root", path)
+ }
+ ret = relPath
+ }
+ return ret
+}
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 47b391c..943ec81 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -88,7 +88,7 @@
var PrepareForTestWithPrebuiltEtc = android.FixtureRegisterWithContext(RegisterPrebuiltEtcBuildComponents)
-type prebuiltEtcProperties struct {
+type PrebuiltEtcProperties struct {
// Source file of this prebuilt. Can reference a genrule type module with the ":module" syntax.
// Mutually exclusive with srcs.
Src proptools.Configurable[string] `android:"path,arch_variant,replace_instead_of_append"`
@@ -175,7 +175,7 @@
android.ModuleBase
android.DefaultableModuleBase
- properties prebuiltEtcProperties
+ properties PrebuiltEtcProperties
// rootProperties is used to return the value of the InstallInRoot() method. Currently, only
// prebuilt_avb and prebuilt_root modules use this.
@@ -607,7 +607,7 @@
module.AddProperties(props...)
module.AddProperties(
- &prebuiltEtcProperties{},
+ &PrebuiltEtcProperties{},
&prebuiltSubdirProperties{},
)
diff --git a/fsgen/filesystem_creator_test.go b/fsgen/filesystem_creator_test.go
index 199eaad..6111a41 100644
--- a/fsgen/filesystem_creator_test.go
+++ b/fsgen/filesystem_creator_test.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "android/soong/etc"
"android/soong/filesystem"
"android/soong/java"
"testing"
@@ -253,3 +254,129 @@
_, libFooInDeps := (*resolvedSystemDeps)["libfoo"]
android.AssertBoolEquals(t, "libfoo should not appear in deps because it has been overridden by libbaz. The latter is a required dep of libbar, which is listed in PRODUCT_PACKAGES", false, libFooInDeps)
}
+
+func TestPrebuiltEtcModuleGen(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ android.PrepareForIntegrationTestWithAndroid,
+ android.PrepareForTestWithAndroidBuildComponents,
+ android.PrepareForTestWithAllowMissingDependencies,
+ filesystem.PrepareForTestWithFilesystemBuildComponents,
+ prepareForTestWithFsgenBuildComponents,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.ProductCopyFiles = []string{
+ "frameworks/base/config/preloaded-classes:system/etc/preloaded-classes",
+ "frameworks/base/data/keyboards/Vendor_0079_Product_0011.kl:system/usr/keylayout/subdir/Vendor_0079_Product_0011.kl",
+ "frameworks/base/data/keyboards/Vendor_0079_Product_18d4.kl:system/usr/keylayout/subdir/Vendor_0079_Product_18d4.kl",
+ "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",
+ }
+ config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.PartitionQualifiedVariables =
+ map[string]android.PartitionQualifiedVariablesType{
+ "system": {
+ BoardFileSystemType: "ext4",
+ },
+ }
+ }),
+ android.FixtureMergeMockFs(android.MockFS{
+ "external/avb/test/data/testkey_rsa4096.pem": nil,
+ "build/soong/fsgen/Android.bp": []byte(`
+ soong_filesystem_creator {
+ name: "foo",
+ }
+ `),
+ "frameworks/base/config/preloaded-classes": nil,
+ "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,
+ }),
+ ).RunTest(t)
+
+ checkModuleProp := func(m android.Module, matcher func(actual interface{}) bool) bool {
+ for _, prop := range m.GetProperties() {
+
+ if matcher(prop) {
+ return true
+ }
+ }
+ return false
+ }
+
+ // check generated prebuilt_* module type install path and install partition
+ generatedModule := result.ModuleForTests("system-frameworks_base_config-etc-0", "android_arm64_armv8-a").Module()
+ etcModule, _ := generatedModule.(*etc.PrebuiltEtc)
+ android.AssertStringEquals(
+ t,
+ "module expected to have etc install path",
+ "etc",
+ etcModule.BaseDir(),
+ )
+ android.AssertBoolEquals(
+ t,
+ "module expected to be installed in system partition",
+ true,
+ !generatedModule.InstallInProduct() &&
+ !generatedModule.InstallInVendor() &&
+ !generatedModule.InstallInSystemExt(),
+ )
+
+ // check generated prebuilt_* module specifies correct relative_install_path property
+ generatedModule = result.ModuleForTests("system-frameworks_base_data_keyboards-usr_keylayout_subdir-0", "android_arm64_armv8-a").Module()
+ etcModule, _ = generatedModule.(*etc.PrebuiltEtc)
+ android.AssertStringEquals(
+ t,
+ "module expected to set correct relative_install_path properties",
+ "subdir",
+ etcModule.SubDir(),
+ )
+
+ // check that prebuilt_* module is not generated for non existing source file
+ android.AssertPanicMessageContains(
+ t,
+ "prebuilt_* module not generated for non existing source file",
+ "failed to find module \"system-some_non_existing-etc-0\"",
+ func() { result.ModuleForTests("system-some_non_existing-etc-0", "android_arm64_armv8-a") },
+ )
+
+ // check that duplicate src file can exist in PRODUCT_COPY_FILES and generates separate modules
+ generatedModule0 := result.ModuleForTests("product-device_sample_etc-etc-0", "android_arm64_armv8-a").Module()
+ generatedModule1 := result.ModuleForTests("product-device_sample_etc-etc-1", "android_arm64_armv8-a").Module()
+
+ // check that generated prebuilt_* module sets correct srcs and dsts property
+ eval := generatedModule0.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
+ android.AssertBoolEquals(
+ t,
+ "module expected to set correct srcs and dsts properties",
+ true,
+ checkModuleProp(generatedModule0, func(actual interface{}) bool {
+ if p, ok := actual.(*etc.PrebuiltEtcProperties); ok {
+ srcs := p.Srcs.GetOrDefault(eval, nil)
+ dsts := p.Dsts.GetOrDefault(eval, nil)
+ return len(srcs) == 1 &&
+ srcs[0] == "apns-full-conf.xml" &&
+ len(dsts) == 1 &&
+ dsts[0] == "apns-conf.xml"
+ }
+ return false
+ }),
+ )
+
+ // check that generated prebuilt_* module sets correct srcs and dsts property
+ eval = generatedModule1.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
+ android.AssertBoolEquals(
+ t,
+ "module expected to set correct srcs and dsts properties",
+ true,
+ checkModuleProp(generatedModule1, func(actual interface{}) bool {
+ if p, ok := actual.(*etc.PrebuiltEtcProperties); ok {
+ srcs := p.Srcs.GetOrDefault(eval, nil)
+ dsts := p.Dsts.GetOrDefault(eval, nil)
+ return len(srcs) == 1 &&
+ srcs[0] == "apns-full-conf.xml" &&
+ len(dsts) == 1 &&
+ dsts[0] == "apns-conf-2.xml"
+ }
+ return false
+ }),
+ )
+}
diff --git a/fsgen/prebuilt_etc_modules_gen.go b/fsgen/prebuilt_etc_modules_gen.go
index 983dcfb..97d5482 100644
--- a/fsgen/prebuilt_etc_modules_gen.go
+++ b/fsgen/prebuilt_etc_modules_gen.go
@@ -100,10 +100,15 @@
ctx.ModuleErrorf("PRODUCT_COPY_FILES must follow the format \"src:dest\", got: %s", copyFilePair)
}
src, dest := srcDestList[0], srcDestList[1]
+
+ // Some downstream branches use absolute path as entries in PRODUCT_COPY_FILES.
+ // Convert them to relative path from top and check if they do not escape the tree root.
+ relSrc := android.ToRelativeSourcePath(ctx, src)
+
if _, ok := seen[dest]; !ok {
- if optionalPath := android.ExistentPathForSource(ctx, src); optionalPath.Valid() {
+ if optionalPath := android.ExistentPathForSource(ctx, relSrc); optionalPath.Valid() {
seen[dest] = true
- filtered[src] = append(filtered[src], dest)
+ filtered[relSrc] = append(filtered[relSrc], dest)
}
}
}
@@ -274,7 +279,8 @@
for fileIndex := range maxLen {
srcTuple := []srcBaseFileInstallBaseFileTuple{}
- for _, groupedDestFile := range groupedDestFiles {
+ for _, srcFile := range android.SortedKeys(groupedDestFiles) {
+ groupedDestFile := groupedDestFiles[srcFile]
if len(groupedDestFile) > fileIndex {
srcTuple = append(srcTuple, groupedDestFile[fileIndex])
}