diff options
| -rw-r--r-- | android/paths.go | 16 | ||||
| -rw-r--r-- | etc/prebuilt_etc.go | 6 | ||||
| -rw-r--r-- | fsgen/filesystem_creator_test.go | 127 | ||||
| -rw-r--r-- | fsgen/prebuilt_etc_modules_gen.go | 12 |
4 files changed, 155 insertions, 6 deletions
diff --git a/android/paths.go b/android/paths.go index 3f67c55b2..8f066cc08 100644 --- a/android/paths.go +++ b/android/paths.go @@ -2613,3 +2613,19 @@ func IsThirdPartyPath(path string) bool { } 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 47b391caa..943ec817d 100644 --- a/etc/prebuilt_etc.go +++ b/etc/prebuilt_etc.go @@ -88,7 +88,7 @@ func RegisterPrebuiltEtcBuildComponents(ctx android.RegistrationContext) { 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 @@ type PrebuiltEtc struct { 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 @@ func DefaultsFactory(props ...interface{}) android.Module { module.AddProperties(props...) module.AddProperties( - &prebuiltEtcProperties{}, + &PrebuiltEtcProperties{}, &prebuiltSubdirProperties{}, ) diff --git a/fsgen/filesystem_creator_test.go b/fsgen/filesystem_creator_test.go index 199eaad11..6111a4117 100644 --- a/fsgen/filesystem_creator_test.go +++ b/fsgen/filesystem_creator_test.go @@ -16,6 +16,7 @@ package fsgen import ( "android/soong/android" + "android/soong/etc" "android/soong/filesystem" "android/soong/java" "testing" @@ -253,3 +254,129 @@ java_library { _, 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 983dcfbcf..97d5482cb 100644 --- a/fsgen/prebuilt_etc_modules_gen.go +++ b/fsgen/prebuilt_etc_modules_gen.go @@ -100,10 +100,15 @@ func uniqueExistingProductCopyFileMap(ctx android.LoadHookContext) map[string][] 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 @@ func createPrebuiltEtcModulesInDirectory(ctx android.LoadHookContext, partition, 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]) } |