diff options
Diffstat (limited to 'android')
| -rw-r--r-- | android/Android.bp | 3 | ||||
| -rw-r--r-- | android/android_info.go | 91 | ||||
| -rw-r--r-- | android/apex.go | 2 | ||||
| -rw-r--r-- | android/apex_contributions.go | 12 | ||||
| -rw-r--r-- | android/base_module_context.go | 20 | ||||
| -rw-r--r-- | android/build_prop.go | 33 | ||||
| -rw-r--r-- | android/build_prop_test.go | 41 | ||||
| -rw-r--r-- | android/config.go | 87 | ||||
| -rw-r--r-- | android/config_test.go | 45 | ||||
| -rw-r--r-- | android/dirgroup.go | 3 | ||||
| -rw-r--r-- | android/filegroup_test.go | 46 | ||||
| -rw-r--r-- | android/init.go | 1 | ||||
| -rw-r--r-- | android/module.go | 31 | ||||
| -rw-r--r-- | android/module_context.go | 49 | ||||
| -rw-r--r-- | android/module_proxy.go | 16 | ||||
| -rw-r--r-- | android/mutator.go | 26 | ||||
| -rw-r--r-- | android/neverallow.go | 44 | ||||
| -rw-r--r-- | android/neverallow_test.go | 28 | ||||
| -rw-r--r-- | android/packaging.go | 216 | ||||
| -rw-r--r-- | android/path_properties.go | 23 | ||||
| -rw-r--r-- | android/paths.go | 72 | ||||
| -rw-r--r-- | android/paths_test.go | 6 | ||||
| -rw-r--r-- | android/prebuilt.go | 2 | ||||
| -rw-r--r-- | android/register.go | 1 | ||||
| -rw-r--r-- | android/rule_builder.go | 60 | ||||
| -rw-r--r-- | android/singleton.go | 29 | ||||
| -rw-r--r-- | android/util.go | 10 | ||||
| -rw-r--r-- | android/variable.go | 39 | ||||
| -rw-r--r-- | android/vintf_data.go | 171 |
29 files changed, 992 insertions, 215 deletions
diff --git a/android/Android.bp b/android/Android.bp index 1ed2dbaa1..a9a3564ab 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -31,6 +31,7 @@ bootstrap_go_package { srcs: [ "aconfig_providers.go", "all_teams.go", + "android_info.go", "androidmk.go", "apex.go", "apex_contributions.go", @@ -111,6 +112,7 @@ bootstrap_go_package { "util.go", "variable.go", "vintf_fragment.go", + "vintf_data.go", "visibility.go", ], testSrcs: [ @@ -120,6 +122,7 @@ bootstrap_go_package { "apex_test.go", "arch_test.go", "blueprint_e2e_test.go", + "build_prop_test.go", "config_test.go", "configured_jars_test.go", "csuite_config_test.go", diff --git a/android/android_info.go b/android/android_info.go new file mode 100644 index 000000000..a8d3d4e2c --- /dev/null +++ b/android/android_info.go @@ -0,0 +1,91 @@ +// Copyright 2024 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import ( + "github.com/google/blueprint" + "github.com/google/blueprint/proptools" +) + +var ( + mergeAndRemoveComments = pctx.AndroidStaticRule("merge_and_remove_comments", + blueprint.RuleParams{ + Command: "cat $in | grep -v '#' > $out", + }, + ) + androidInfoTxtToProp = pctx.AndroidStaticRule("android_info_txt_to_prop", + blueprint.RuleParams{ + Command: "grep 'require version-' $in | sed -e 's/require version-/ro.build.expect./g' > $out", + }, + ) +) + +type androidInfoProperties struct { + // Name of output file. Defaults to module name + Stem *string + + // Paths of board-info.txt files. + Board_info_files []string `android:"path"` + + // Name of bootloader board. If board_info_files is empty, `board={bootloader_board_name}` will + // be printed to output. Ignored if board_info_files is not empty. + Bootloader_board_name *string +} + +type androidInfoModule struct { + ModuleBase + + properties androidInfoProperties +} + +func (p *androidInfoModule) GenerateAndroidBuildActions(ctx ModuleContext) { + if len(p.properties.Board_info_files) > 0 && p.properties.Bootloader_board_name != nil { + ctx.ModuleErrorf("Either Board_info_files or Bootloader_board_name should be set. Please remove one of them\n") + return + } + androidInfoTxtName := proptools.StringDefault(p.properties.Stem, ctx.ModuleName()+".txt") + androidInfoTxt := PathForModuleOut(ctx, androidInfoTxtName) + androidInfoProp := androidInfoTxt.ReplaceExtension(ctx, "prop") + + if boardInfoFiles := PathsForModuleSrc(ctx, p.properties.Board_info_files); len(boardInfoFiles) > 0 { + ctx.Build(pctx, BuildParams{ + Rule: mergeAndRemoveComments, + Inputs: boardInfoFiles, + Output: androidInfoTxt, + }) + } else if bootloaderBoardName := proptools.String(p.properties.Bootloader_board_name); bootloaderBoardName != "" { + WriteFileRule(ctx, androidInfoTxt, "board="+bootloaderBoardName) + } else { + WriteFileRule(ctx, androidInfoTxt, "") + } + + // Create android_info.prop + ctx.Build(pctx, BuildParams{ + Rule: androidInfoTxtToProp, + Input: androidInfoTxt, + Output: androidInfoProp, + }) + + ctx.SetOutputFiles(Paths{androidInfoProp}, "") +} + +// android_info module generate a file named android-info.txt that contains various information +// about the device we're building for. This file is typically packaged up with everything else. +func AndroidInfoFactory() Module { + module := &androidInfoModule{} + module.AddProperties(&module.properties) + InitAndroidModule(module) + return module +} diff --git a/android/apex.go b/android/apex.go index 79ab13caf..e73b3e662 100644 --- a/android/apex.go +++ b/android/apex.go @@ -833,7 +833,7 @@ func UpdateDirectlyInAnyApex(mctx BottomUpMutatorContext, am ApexModule) { // If this is the FinalModule (last visited module) copy // AnyVariantDirectlyInAnyApex to all the other variants - if am == mctx.FinalModule().(ApexModule) { + if mctx.IsFinalModule(am) { mctx.VisitAllModuleVariants(func(variant Module) { variant.(ApexModule).apexModuleBase().ApexProperties.AnyVariantDirectlyInAnyApex = base.ApexProperties.AnyVariantDirectlyInAnyApex diff --git a/android/apex_contributions.go b/android/apex_contributions.go index 4cd8dda93..ce3427840 100644 --- a/android/apex_contributions.go +++ b/android/apex_contributions.go @@ -26,7 +26,7 @@ func init() { func RegisterApexContributionsBuildComponents(ctx RegistrationContext) { ctx.RegisterModuleType("apex_contributions", apexContributionsFactory) ctx.RegisterModuleType("apex_contributions_defaults", apexContributionsDefaultsFactory) - ctx.RegisterSingletonModuleType("all_apex_contributions", allApexContributionsFactory) + ctx.RegisterModuleType("all_apex_contributions", allApexContributionsFactory) } type apexContributions struct { @@ -87,10 +87,10 @@ func apexContributionsDefaultsFactory() Module { // Based on product_config, it will create a dependency on the selected // apex_contributions per mainline module type allApexContributions struct { - SingletonModuleBase + ModuleBase } -func allApexContributionsFactory() SingletonModule { +func allApexContributionsFactory() Module { module := &allApexContributions{} InitAndroidModule(module) return module @@ -191,7 +191,7 @@ func (p *PrebuiltSelectionInfoMap) GetSelectedModulesForApiDomain(apiDomain stri // This module type does not have any build actions. func (a *allApexContributions) GenerateAndroidBuildActions(ctx ModuleContext) { -} - -func (a *allApexContributions) GenerateSingletonBuildActions(ctx SingletonContext) { + if ctx.ModuleName() != "all_apex_contributions" { + ctx.ModuleErrorf("There can only be 1 all_apex_contributions module in build/soong") + } } diff --git a/android/base_module_context.go b/android/base_module_context.go index 7fa58766f..060fae5bc 100644 --- a/android/base_module_context.go +++ b/android/base_module_context.go @@ -88,6 +88,10 @@ type BaseModuleContext interface { // This method shouldn't be used directly, prefer the type-safe android.OtherModuleProvider instead. otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) + // OtherModuleIsAutoGenerated returns true if the module is auto generated by another module + // instead of being defined in Android.bp file. + OtherModuleIsAutoGenerated(m blueprint.Module) bool + // Provider returns the value for a provider for the current module. If the value is // not set it returns nil and false. It panics if called before the appropriate // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep @@ -194,9 +198,15 @@ type BaseModuleContext interface { // singleton actions that are only done once for all variants of a module. FinalModule() Module + // IsFinalModule returns if the current module is the last variant. Variants of a module are always visited in + // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all + // variants using VisitAllModuleVariants if the current module is the last one. This can be used to perform + // singleton actions that are only done once for all variants of a module. + IsFinalModule(module Module) bool + // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read - // from all variants if the current module == FinalModule(). Otherwise, care must be taken to not access any + // from all variants if the current module is the last one. Otherwise, care must be taken to not access any // data modified by the current mutator. VisitAllModuleVariants(visit func(Module)) @@ -276,6 +286,10 @@ func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blu return b.bp.OtherModuleProvider(m, provider) } +func (b *baseModuleContext) OtherModuleIsAutoGenerated(m blueprint.Module) bool { + return b.bp.OtherModuleIsAutoGenerated(m) +} + func (b *baseModuleContext) provider(provider blueprint.AnyProviderKey) (any, bool) { return b.bp.Provider(provider) } @@ -584,6 +598,10 @@ func (b *baseModuleContext) FinalModule() Module { return b.bp.FinalModule().(Module) } +func (b *baseModuleContext) IsFinalModule(module Module) bool { + return b.bp.IsFinalModule(module) +} + // IsMetaDependencyTag returns true for cross-cutting metadata dependencies. func IsMetaDependencyTag(tag blueprint.DependencyTag) bool { if tag == licenseKindTag { diff --git a/android/build_prop.go b/android/build_prop.go index 7c3c50645..838947045 100644 --- a/android/build_prop.go +++ b/android/build_prop.go @@ -19,8 +19,12 @@ import ( ) func init() { - ctx := InitRegistrationContext + registerBuildPropComponents(InitRegistrationContext) +} + +func registerBuildPropComponents(ctx RegistrationContext) { ctx.RegisterModuleType("build_prop", BuildPropFactory) + ctx.RegisterModuleType("android_info", AndroidInfoFactory) } type buildPropProperties struct { @@ -38,6 +42,10 @@ type buildPropProperties struct { // Path to a JSON file containing product configs. Product_config *string `android:"path"` + // Path to android-info.txt file containing board specific info. + // This is empty for build.prop of all partitions except vendor. + Android_info *string `android:"path"` + // Optional subdirectory under which this file is installed into Relative_install_path *string } @@ -66,7 +74,10 @@ func (p *buildPropModule) propFiles(ctx ModuleContext) Paths { } else if partition == "odm" { return ctx.Config().OdmPropFiles(ctx) } else if partition == "vendor" { - // TODO (b/375500423): Add android-info.txt to prop files + if p.properties.Android_info != nil { + androidInfo := PathForModuleSrc(ctx, proptools.String(p.properties.Android_info)) + return append(ctx.Config().VendorPropFiles(ctx), androidInfo) + } return ctx.Config().VendorPropFiles(ctx) } return nil @@ -98,6 +109,12 @@ func (p *buildPropModule) partition(config DeviceConfig) string { return "product" } else if p.SystemExtSpecific() { return "system_ext" + } else if p.InstallInSystemDlkm() { + return "system_dlkm" + } else if p.InstallInVendorDlkm() { + return "vendor_dlkm" + } else if p.InstallInOdmDlkm() { + return "odm_dlkm" } return "system" } @@ -108,16 +125,18 @@ var validPartitions = []string{ "product", "odm", "vendor", + "system_dlkm", + "vendor_dlkm", + "odm_dlkm", } func (p *buildPropModule) GenerateAndroidBuildActions(ctx ModuleContext) { - p.outputFilePath = PathForModuleOut(ctx, "build.prop").OutputPath - if !ctx.Config().KatiEnabled() { - WriteFileRule(ctx, p.outputFilePath, "# no build.prop if kati is disabled") - ctx.SetOutputFiles(Paths{p.outputFilePath}, "") - return + if !p.SocSpecific() && p.properties.Android_info != nil { + ctx.ModuleErrorf("Android_info cannot be set if build.prop is not installed in vendor partition") } + p.outputFilePath = PathForModuleOut(ctx, "build.prop").OutputPath + partition := p.partition(ctx.DeviceConfig()) if !InList(partition, validPartitions) { ctx.PropertyErrorf("partition", "unsupported partition %q: only %q are supported", partition, validPartitions) diff --git a/android/build_prop_test.go b/android/build_prop_test.go new file mode 100644 index 000000000..e75975a0a --- /dev/null +++ b/android/build_prop_test.go @@ -0,0 +1,41 @@ +// Copyright 2024 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import ( + "testing" +) + +func TestPropFileInputs(t *testing.T) { + bp := ` +build_prop { + name: "vendor-build.prop", + stem: "build.prop", + vendor: true, + android_info: ":board-info", + //product_config: ":product_config", +} +android_info { + name: "board-info", + stem: "android-info.txt", +} +` + + res := GroupFixturePreparers( + FixtureRegisterWithContext(registerBuildPropComponents), + ).RunTestWithBp(t, bp) + buildPropCmd := res.ModuleForTests("vendor-build.prop", "").Rule("vendor-build.prop_.vendor-build.prop").RuleParams.Command + AssertStringDoesContain(t, "Could not find android-info in prop files of vendor build.prop", buildPropCmd, "--prop-files=out/soong/.intermediates/board-info/android-info.prop") +} diff --git a/android/config.go b/android/config.go index feed22f6a..d9db64ef6 100644 --- a/android/config.go +++ b/android/config.go @@ -413,18 +413,21 @@ type jsonConfigurable interface { // To add a new feature to the list, add the field in the struct // `partialCompileFlags` above, and then add the name of the field in the // switch statement below. -func (c *config) parsePartialCompileFlags() (partialCompileFlags, error) { - defaultFlags := partialCompileFlags{ - // Set any opt-out flags here. Opt-in flags are off by default. - enabled: false, +var defaultPartialCompileFlags = partialCompileFlags{ + // Set any opt-out flags here. Opt-in flags are off by default. + enabled: false, +} + +func (c *config) parsePartialCompileFlags(isEngBuild bool) (partialCompileFlags, error) { + if !isEngBuild { + return partialCompileFlags{}, nil } value := c.Getenv("SOONG_PARTIAL_COMPILE") - if value == "" { - return defaultFlags, nil + return defaultPartialCompileFlags, nil } - ret := defaultFlags + ret := defaultPartialCompileFlags tokens := strings.Split(strings.ToLower(value), ",") makeVal := func(state string, defaultValue bool) bool { switch state { @@ -455,17 +458,17 @@ func (c *config) parsePartialCompileFlags() (partialCompileFlags, error) { } switch tok { case "true": - ret = defaultFlags + ret = defaultPartialCompileFlags ret.enabled = true case "false": // Set everything to false. ret = partialCompileFlags{} case "enabled": - ret.enabled = makeVal(state, defaultFlags.enabled) + ret.enabled = makeVal(state, defaultPartialCompileFlags.enabled) case "use_d8": - ret.use_d8 = makeVal(state, defaultFlags.use_d8) + ret.use_d8 = makeVal(state, defaultPartialCompileFlags.use_d8) default: - return partialCompileFlags{}, fmt.Errorf("Unknown SOONG_PARTIAL_COMPILE value: %v", value) + return partialCompileFlags{}, fmt.Errorf("Unknown SOONG_PARTIAL_COMPILE value: %v", tok) } } return ret, nil @@ -616,6 +619,8 @@ func NewConfig(cmdArgs CmdArgs, availableEnv map[string]string) (Config, error) buildFromSourceStub: cmdArgs.BuildFromSourceStub, } + variant, ok := os.LookupEnv("TARGET_BUILD_VARIANT") + isEngBuild := !ok || variant == "eng" config.deviceConfig = &deviceConfig{ config: config, @@ -657,7 +662,7 @@ func NewConfig(cmdArgs CmdArgs, availableEnv map[string]string) (Config, error) return Config{}, err } - config.partialCompileFlags, err = config.parsePartialCompileFlags() + config.partialCompileFlags, err = config.parsePartialCompileFlags(isEngBuild) if err != nil { return Config{}, err } @@ -862,7 +867,7 @@ func (c *config) IsEnvFalse(key string) bool { } func (c *config) TargetsJava21() bool { - return c.IsEnvTrue("EXPERIMENTAL_TARGET_JAVA_VERSION_21") + return c.productVariables.GetBuildFlagBool("RELEASE_TARGET_JAVA_21") } // EnvDeps returns the environment variables this build depends on. The first @@ -1517,6 +1522,13 @@ func (c *deviceConfig) VendorPath() string { return "vendor" } +func (c *deviceConfig) VendorDlkmPath() string { + if c.config.productVariables.VendorDlkmPath != nil { + return *c.config.productVariables.VendorDlkmPath + } + return "vendor_dlkm" +} + func (c *deviceConfig) BuildingVendorImage() bool { return proptools.Bool(c.config.productVariables.BuildingVendorImage) } @@ -1544,6 +1556,17 @@ func (c *deviceConfig) OdmPath() string { return "odm" } +func (c *deviceConfig) BuildingOdmImage() bool { + return proptools.Bool(c.config.productVariables.BuildingOdmImage) +} + +func (c *deviceConfig) OdmDlkmPath() string { + if c.config.productVariables.OdmDlkmPath != nil { + return *c.config.productVariables.OdmDlkmPath + } + return "odm_dlkm" +} + func (c *deviceConfig) ProductPath() string { if c.config.productVariables.ProductPath != nil { return *c.config.productVariables.ProductPath @@ -1562,6 +1585,20 @@ func (c *deviceConfig) SystemExtPath() string { return "system_ext" } +func (c *deviceConfig) SystemDlkmPath() string { + if c.config.productVariables.SystemDlkmPath != nil { + return *c.config.productVariables.SystemDlkmPath + } + return "system_dlkm" +} + +func (c *deviceConfig) OemPath() string { + if c.config.productVariables.OemPath != nil { + return *c.config.productVariables.OemPath + } + return "oem" +} + func (c *deviceConfig) BtConfigIncludeDir() string { return String(c.config.productVariables.BtConfigIncludeDir) } @@ -2229,3 +2266,27 @@ func (c *config) BoardAvbSystemAddHashtreeFooterArgs() []string { func (c Config) InstallApexSystemServerDexpreoptSamePartition() bool { return c.config.productVariables.GetBuildFlagBool("RELEASE_INSTALL_APEX_SYSTEMSERVER_DEXPREOPT_SAME_PARTITION") } + +func (c *config) DeviceMatrixFile() []string { + return c.productVariables.DeviceMatrixFile +} + +func (c *config) ProductManifestFiles() []string { + return c.productVariables.ProductManifestFiles +} + +func (c *config) SystemManifestFile() []string { + return c.productVariables.SystemManifestFile +} + +func (c *config) SystemExtManifestFiles() []string { + return c.productVariables.SystemExtManifestFiles +} + +func (c *config) DeviceManifestFiles() []string { + return c.productVariables.DeviceManifestFiles +} + +func (c *config) OdmManifestFiles() []string { + return c.productVariables.OdmManifestFiles +} diff --git a/android/config_test.go b/android/config_test.go index 773216844..adb5ffac5 100644 --- a/android/config_test.go +++ b/android/config_test.go @@ -212,3 +212,48 @@ func TestConfiguredJarList(t *testing.T) { assertStringEquals(t, "apex1:jarA", list5.String()) }) } + +func (p partialCompileFlags) updateEnabled(value bool) partialCompileFlags { + p.enabled = value + return p +} + +func (p partialCompileFlags) updateUseD8(value bool) partialCompileFlags { + p.use_d8 = value + return p +} + +func TestPartialCompile(t *testing.T) { + mockConfig := func(value string) *config { + c := &config{ + env: map[string]string{ + "SOONG_PARTIAL_COMPILE": value, + }, + } + return c + } + tests := []struct { + value string + isEngBuild bool + expected partialCompileFlags + }{ + {"", true, defaultPartialCompileFlags}, + {"false", true, partialCompileFlags{}}, + {"true", true, defaultPartialCompileFlags.updateEnabled(true)}, + {"true", false, partialCompileFlags{}}, + {"true,use_d8", true, defaultPartialCompileFlags.updateEnabled(true).updateUseD8(true)}, + {"true,-use_d8", true, defaultPartialCompileFlags.updateEnabled(true).updateUseD8(false)}, + {"use_d8,false", true, partialCompileFlags{}}, + {"false,+use_d8", true, partialCompileFlags{}.updateUseD8(true)}, + } + + for _, test := range tests { + t.Run(test.value, func(t *testing.T) { + config := mockConfig(test.value) + flags, _ := config.parsePartialCompileFlags(test.isEngBuild) + if flags != test.expected { + t.Errorf("expected %v found %v", test.expected, flags) + } + }) + } +} diff --git a/android/dirgroup.go b/android/dirgroup.go index 20c4d13a6..62fbaa5c8 100644 --- a/android/dirgroup.go +++ b/android/dirgroup.go @@ -39,8 +39,7 @@ type dirGroup struct { } type DirInfo struct { - // TODO(b/358302178): Use DirectoryPaths instead of Paths - Dirs Paths + Dirs DirectoryPaths } var DirProvider = blueprint.NewProvider[DirInfo]() diff --git a/android/filegroup_test.go b/android/filegroup_test.go index 14e9368ca..670037d56 100644 --- a/android/filegroup_test.go +++ b/android/filegroup_test.go @@ -1,55 +1,9 @@ package android import ( - "path/filepath" "testing" ) -func TestFileGroupWithPathProp(t *testing.T) { - // TODO(b/247782695), TODO(b/242847534) Fix mixed builds for filegroups - t.Skip("Re-enable once filegroups are corrected for mixed builds") - outBaseDir := "outputbase" - pathPrefix := outBaseDir + "/execroot/__main__" - expectedOutputfile := filepath.Join(pathPrefix, "a/b/c/d/test.aidl") - - testCases := []struct { - bp string - rel string - }{ - { - bp: ` - filegroup { - name: "baz", - srcs: ["a/b/c/d/test.aidl"], - path: "a/b", - bazel_module: { label: "//:baz" }, - } -`, - rel: "c/d/test.aidl", - }, - { - bp: ` - filegroup { - name: "baz", - srcs: ["a/b/c/d/test.aidl"], - bazel_module: { label: "//:baz" }, - } -`, - rel: "a/b/c/d/test.aidl", - }, - } - - for _, testCase := range testCases { - result := GroupFixturePreparers( - PrepareForTestWithFilegroup, - ).RunTestWithBp(t, testCase.bp) - - fg := result.Module("baz", "").(*fileGroup) - AssertStringEquals(t, "src relativeRoot", testCase.rel, fg.srcs[0].Rel()) - AssertStringEquals(t, "src full path", expectedOutputfile, fg.srcs[0].String()) - } -} - func TestFilegroupDefaults(t *testing.T) { bp := FixtureAddTextFile("p/Android.bp", ` filegroup_defaults { diff --git a/android/init.go b/android/init.go index 1ace34494..d3a13d0ed 100644 --- a/android/init.go +++ b/android/init.go @@ -20,6 +20,7 @@ func init() { gob.Register(extraFilesZip{}) gob.Register(InstallPath{}) gob.Register(ModuleGenPath{}) + gob.Register(ModuleObjPath{}) gob.Register(ModuleOutPath{}) gob.Register(OutputPath{}) gob.Register(PhonyPath{}) diff --git a/android/module.go b/android/module.go index 114843056..58ae885c8 100644 --- a/android/module.go +++ b/android/module.go @@ -81,10 +81,14 @@ type Module interface { InstallInProduct() bool InstallInVendor() bool InstallInSystemExt() bool + InstallInSystemDlkm() bool + InstallInVendorDlkm() bool + InstallInOdmDlkm() bool InstallForceOS() (*OsType, *ArchType) PartitionTag(DeviceConfig) string HideFromMake() IsHideFromMake() bool + SkipInstall() IsSkipInstall() bool MakeUninstallable() ReplacedByPrebuilt() @@ -385,6 +389,15 @@ type commonProperties struct { // Whether this module is installed to debug ramdisk Debug_ramdisk *bool + // Install to partition system_dlkm when set to true. + System_dlkm_specific *bool + + // Install to partition vendor_dlkm when set to true. + Vendor_dlkm_specific *bool + + // Install to partition odm_dlkm when set to true. + Odm_dlkm_specific *bool + // Whether this module is built for non-native architectures (also known as native bridge binary) Native_bridge_supported *bool `android:"arch_variant"` @@ -1421,6 +1434,7 @@ func (m *ModuleBase) IsSkipInstall() bool { func (m *ModuleBase) MakeUninstallable() { m.commonProperties.UninstallableApexPlatformVariant = true m.HideFromMake() + m.SkipInstall() } func (m *ModuleBase) ReplacedByPrebuilt() { @@ -1533,6 +1547,18 @@ func (m *ModuleBase) InstallInRoot() bool { return false } +func (m *ModuleBase) InstallInSystemDlkm() bool { + return Bool(m.commonProperties.System_dlkm_specific) +} + +func (m *ModuleBase) InstallInVendorDlkm() bool { + return Bool(m.commonProperties.Vendor_dlkm_specific) +} + +func (m *ModuleBase) InstallInOdmDlkm() bool { + return Bool(m.commonProperties.Odm_dlkm_specific) +} + func (m *ModuleBase) InstallForceOS() (*OsType, *ArchType) { return nil, nil } @@ -1820,6 +1846,8 @@ type CommonPropertiesProviderData struct { Enabled bool // Whether the module has been replaced by a prebuilt ReplacedByPrebuilt bool + // The Target of artifacts that this module variant is responsible for creating. + CompileTarget Target } var CommonPropertiesProviderKey = blueprint.NewProvider[CommonPropertiesProviderData]() @@ -2008,7 +2036,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) ctx.GetMissingDependencies() } - if m == ctx.FinalModule().(Module).base() { + if ctx.IsFinalModule(m.module) { m.generateModuleTarget(ctx) if ctx.Failed() { return @@ -2084,6 +2112,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) commonData := CommonPropertiesProviderData{ ReplacedByPrebuilt: m.commonProperties.ReplacedByPrebuilt, + CompileTarget: m.commonProperties.CompileTarget, } if m.commonProperties.ForcedDisabled { commonData.Enabled = false diff --git a/android/module_context.go b/android/module_context.go index 9fa3a6211..41cb0ccb2 100644 --- a/android/module_context.go +++ b/android/module_context.go @@ -19,6 +19,7 @@ import ( "github.com/google/blueprint/depset" "path" "path/filepath" + "slices" "strings" "github.com/google/blueprint" @@ -195,6 +196,9 @@ type ModuleContext interface { InstallInOdm() bool InstallInProduct() bool InstallInVendor() bool + InstallInSystemDlkm() bool + InstallInVendorDlkm() bool + InstallInOdmDlkm() bool InstallForceOS() (*OsType, *ArchType) RequiredModuleNames(ctx ConfigurableEvaluatorContext) []string @@ -492,15 +496,23 @@ func (m *moduleContext) InstallInVendor() bool { return m.module.InstallInVendor() } +func (m *moduleContext) InstallInSystemDlkm() bool { + return m.module.InstallInSystemDlkm() +} + +func (m *moduleContext) InstallInVendorDlkm() bool { + return m.module.InstallInVendorDlkm() +} + +func (m *moduleContext) InstallInOdmDlkm() bool { + return m.module.InstallInOdmDlkm() +} + func (m *moduleContext) skipInstall() bool { if m.module.base().commonProperties.SkipInstall { return true } - if m.module.base().commonProperties.HideFromMake { - return true - } - // We'll need a solution for choosing which of modules with the same name in different // namespaces to install. For now, reuse the list of namespaces exported to Make as the // list of namespaces to install in a Soong-only build. @@ -519,6 +531,10 @@ func (m *moduleContext) requiresFullInstall() bool { return false } + if m.module.base().commonProperties.HideFromMake { + return false + } + if proptools.Bool(m.module.base().commonProperties.No_full_install) { return false } @@ -562,9 +578,22 @@ func (m *moduleContext) setAconfigPaths(paths Paths) { m.aconfigFilePaths = paths } +func (m *moduleContext) getOwnerAndOverrides() (string, []string) { + owner := m.ModuleName() + overrides := slices.Clone(m.Module().base().commonProperties.Overrides) + if b, ok := m.Module().(OverridableModule); ok { + if b.GetOverriddenBy() != "" { + // overriding variant of base module + overrides = append(overrides, m.ModuleName()) // com.android.foo + owner = m.Module().Name() // com.company.android.foo + } + } + return owner, overrides +} + func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool) PackagingSpec { licenseFiles := m.Module().EffectiveLicenseFiles() - overrides := CopyOf(m.Module().base().commonProperties.Overrides) + owner, overrides := m.getOwnerAndOverrides() spec := PackagingSpec{ relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()), srcPath: srcPath, @@ -576,7 +605,7 @@ func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, e aconfigPaths: m.getAconfigPaths(), archType: m.target.Arch.ArchType, overrides: &overrides, - owner: m.ModuleName(), + owner: owner, } m.packagingSpecs = append(m.packagingSpecs, spec) return spec @@ -695,7 +724,7 @@ func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, src m.installFiles = append(m.installFiles, fullInstallPath) } - overrides := CopyOf(m.Module().base().commonProperties.Overrides) + owner, overrides := m.getOwnerAndOverrides() m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{ relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()), srcPath: nil, @@ -706,7 +735,7 @@ func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, src aconfigPaths: m.getAconfigPaths(), archType: m.target.Arch.ArchType, overrides: &overrides, - owner: m.ModuleName(), + owner: owner, }) return fullInstallPath @@ -742,7 +771,7 @@ func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name str m.installFiles = append(m.installFiles, fullInstallPath) } - overrides := CopyOf(m.Module().base().commonProperties.Overrides) + owner, overrides := m.getOwnerAndOverrides() m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{ relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()), srcPath: nil, @@ -753,7 +782,7 @@ func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name str aconfigPaths: m.getAconfigPaths(), archType: m.target.Arch.ArchType, overrides: &overrides, - owner: m.ModuleName(), + owner: owner, }) return fullInstallPath diff --git a/android/module_proxy.go b/android/module_proxy.go index 2a650729f..1f9679926 100644 --- a/android/module_proxy.go +++ b/android/module_proxy.go @@ -106,6 +106,18 @@ func (m ModuleProxy) InstallInSystemExt() bool { panic("method is not implemented on ModuleProxy") } +func (m ModuleProxy) InstallInSystemDlkm() bool { + panic("method is not implemented on ModuleProxy") +} + +func (m ModuleProxy) InstallInVendorDlkm() bool { + panic("method is not implemented on ModuleProxy") +} + +func (m ModuleProxy) InstallInOdmDlkm() bool { + panic("method is not implemented on ModuleProxy") +} + func (m ModuleProxy) InstallForceOS() (*OsType, *ArchType) { panic("method is not implemented on ModuleProxy") } @@ -122,6 +134,10 @@ func (m ModuleProxy) IsHideFromMake() bool { panic("method is not implemented on ModuleProxy") } +func (m ModuleProxy) SkipInstall() { + panic("method is not implemented on ModuleProxy") +} + func (m ModuleProxy) IsSkipInstall() bool { panic("method is not implemented on ModuleProxy") } diff --git a/android/mutator.go b/android/mutator.go index 4ddc606b1..fdd16a889 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -70,7 +70,7 @@ type RegisterMutatorsContext interface { TopDown(name string, m TopDownMutator) MutatorHandle BottomUp(name string, m BottomUpMutator) MutatorHandle BottomUpBlueprint(name string, m blueprint.BottomUpMutator) MutatorHandle - Transition(name string, m TransitionMutator) + Transition(name string, m TransitionMutator) TransitionMutatorHandle } type RegisterMutatorFunc func(RegisterMutatorsContext) @@ -579,7 +579,7 @@ func (a *androidTransitionMutator) Mutate(ctx blueprint.BottomUpMutatorContext, } } -func (x *registerMutatorsContext) Transition(name string, m TransitionMutator) { +func (x *registerMutatorsContext) Transition(name string, m TransitionMutator) TransitionMutatorHandle { atm := &androidTransitionMutator{ finalPhase: x.finalPhase, mutator: m, @@ -587,8 +587,10 @@ func (x *registerMutatorsContext) Transition(name string, m TransitionMutator) { } mutator := &mutator{ name: name, - transitionMutator: atm} + transitionMutator: atm, + } x.mutators = append(x.mutators, mutator) + return mutator } func (x *registerMutatorsContext) mutatorName(name string) string { @@ -625,7 +627,10 @@ func (mutator *mutator) register(ctx *Context) { } else if mutator.topDownMutator != nil { handle = blueprintCtx.RegisterTopDownMutator(mutator.name, mutator.topDownMutator) } else if mutator.transitionMutator != nil { - blueprintCtx.RegisterTransitionMutator(mutator.name, mutator.transitionMutator) + handle := blueprintCtx.RegisterTransitionMutator(mutator.name, mutator.transitionMutator) + if mutator.neverFar { + handle.NeverFar() + } } // Forward booleans set on the MutatorHandle to the blueprint.MutatorHandle. @@ -681,6 +686,14 @@ type MutatorHandle interface { MutatesGlobalState() MutatorHandle } +type TransitionMutatorHandle interface { + // NeverFar causes the variations created by this mutator to never be ignored when adding + // far variation dependencies. Normally, far variation dependencies ignore all the variants + // of the source module, and only use the variants explicitly requested by the + // AddFarVariationDependencies call. + NeverFar() MutatorHandle +} + func (mutator *mutator) Parallel() MutatorHandle { return mutator } @@ -715,6 +728,11 @@ func (mutator *mutator) MutatesGlobalState() MutatorHandle { return mutator } +func (mutator *mutator) NeverFar() MutatorHandle { + mutator.neverFar = true + return mutator +} + func RegisterComponentsMutator(ctx RegisterMutatorsContext) { ctx.BottomUp("component-deps", componentDepsMutator) } diff --git a/android/neverallow.go b/android/neverallow.go index 44ac2cd6c..6176a996a 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -63,6 +63,7 @@ func init() { AddNeverAllowRules(createLimitDirgroupRule()...) AddNeverAllowRules(createFilesystemIsAutoGeneratedRule()) AddNeverAllowRules(createKotlinPluginRule()...) + AddNeverAllowRules(createPrebuiltEtcBpDefineRule()) } // Add a NeverAllow rule to the set of rules to apply. @@ -321,6 +322,27 @@ func createKotlinPluginRule() []Rule { } } +// These module types are introduced to convert PRODUCT_COPY_FILES to Soong, +// and is only intended to be used by filesystem_creator. +func createPrebuiltEtcBpDefineRule() Rule { + return NeverAllow(). + ModuleType( + "prebuilt_usr_srec", + "prebuilt_priv_app", + "prebuilt_rfs", + "prebuilt_framework", + "prebuilt_res", + "prebuilt_wlc_upt", + "prebuilt_odm", + "prebuilt_vendor_dlkm", + "prebuilt_bt_firmware", + "prebuilt_tvservice", + "prebuilt_optee", + ). + DefinedInBpFile(). + Because("module type not allowed to be defined in bp file") +} + func neverallowMutator(ctx BottomUpMutatorContext) { m, ok := ctx.Module().(Module) if !ok { @@ -354,6 +376,10 @@ func neverallowMutator(ctx BottomUpMutatorContext) { continue } + if !n.appliesToBpDefinedModule(ctx) { + continue + } + ctx.ModuleErrorf("violates " + n.String()) } } @@ -477,6 +503,8 @@ type Rule interface { WithoutMatcher(properties string, matcher ValueMatcher) Rule + DefinedInBpFile() Rule + Because(reason string) Rule } @@ -498,6 +526,8 @@ type rule struct { unlessProps ruleProperties onlyBootclasspathJar bool + + definedInBp bool } // Create a new NeverAllow rule. @@ -571,6 +601,13 @@ func (r *rule) WithoutMatcher(properties string, matcher ValueMatcher) Rule { return r } +// DefinedInBpFile specifies that this rule applies to modules that are defined +// in bp files, and does not apply to modules that are auto generated by other modules. +func (r *rule) DefinedInBpFile() Rule { + r.definedInBp = true + return r +} + func selectMatcher(expected string) ValueMatcher { if expected == "*" { return anyMatcherInstance @@ -665,6 +702,13 @@ func (r *rule) appliesToProperties(ctx BottomUpMutatorContext, properties []inte return includeProps && !excludeProps } +func (r *rule) appliesToBpDefinedModule(ctx BottomUpMutatorContext) bool { + if !r.definedInBp { + return true + } + return !ctx.OtherModuleIsAutoGenerated(ctx.Module()) == r.definedInBp +} + func StartsWith(prefix string) ValueMatcher { return &startsWithMatcher{prefix} } diff --git a/android/neverallow_test.go b/android/neverallow_test.go index caec8c7d9..c74d5ff58 100644 --- a/android/neverallow_test.go +++ b/android/neverallow_test.go @@ -374,6 +374,20 @@ var neverallowTests = []struct { `is_auto_generated property is only allowed for filesystem modules in build/soong/fsgen directory`, }, }, + // Test for the rule restricting use of prebuilt_* module + { + name: `"prebuilt_usr_srec" defined in Android.bp file`, + fs: map[string][]byte{ + "a/b/Android.bp": []byte(` + prebuilt_usr_srec { + name: "foo", + } + `), + }, + expectedErrors: []string{ + `module type not allowed to be defined in bp file`, + }, + }, } var prepareForNeverAllowTest = GroupFixturePreparers( @@ -383,6 +397,7 @@ var prepareForNeverAllowTest = GroupFixturePreparers( ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule) ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule) ctx.RegisterModuleType("filesystem", newMockFilesystemModule) + ctx.RegisterModuleType("prebuilt_usr_srec", newMockPrebuiltUsrSrecModule) }), ) @@ -482,3 +497,16 @@ func newMockJavaLibraryModule() Module { func (p *mockJavaLibraryModule) GenerateAndroidBuildActions(ModuleContext) { } + +type mockPrebuiltUsrSrecModule struct { + ModuleBase +} + +func (p *mockPrebuiltUsrSrecModule) GenerateAndroidBuildActions(ModuleContext) { +} + +func newMockPrebuiltUsrSrecModule() Module { + m := &mockPrebuiltUsrSrecModule{} + InitAndroidModule(m) + return m +} diff --git a/android/packaging.go b/android/packaging.go index acafcd4f2..98c85fa0c 100644 --- a/android/packaging.go +++ b/android/packaging.go @@ -207,38 +207,49 @@ type PackagingBase struct { // If this is set to true by a module type inheriting PackagingBase, the deps property // collects the first target only even with compile_multilib: true. DepsCollectFirstTargetOnly bool + + // If this is set to try by a module type inheriting PackagingBase, the module type is + // allowed to utilize High_priority_deps. + AllowHighPriorityDeps bool } -type depsProperty struct { +type DepsProperty struct { + // Deps that have higher priority in packaging when there is a packaging conflict. + // For example, if multiple files are being installed to same filepath, the install file + // of the module listed in this property will have a higher priority over those in other + // deps properties. + High_priority_deps []string `android:"arch_variant"` + // Modules to include in this package Deps proptools.Configurable[[]string] `android:"arch_variant"` } type packagingMultilibProperties struct { - First depsProperty `android:"arch_variant"` - Common depsProperty `android:"arch_variant"` - Lib32 depsProperty `android:"arch_variant"` - Lib64 depsProperty `android:"arch_variant"` - Both depsProperty `android:"arch_variant"` - Prefer32 depsProperty `android:"arch_variant"` + First DepsProperty `android:"arch_variant"` + Common DepsProperty `android:"arch_variant"` + Lib32 DepsProperty `android:"arch_variant"` + Lib64 DepsProperty `android:"arch_variant"` + Both DepsProperty `android:"arch_variant"` + Prefer32 DepsProperty `android:"arch_variant"` } type packagingArchProperties struct { - Arm64 depsProperty - Arm depsProperty - X86_64 depsProperty - X86 depsProperty + Arm64 DepsProperty + Arm DepsProperty + X86_64 DepsProperty + X86 DepsProperty } type PackagingProperties struct { - Deps proptools.Configurable[[]string] `android:"arch_variant"` - Multilib packagingMultilibProperties `android:"arch_variant"` + DepsProperty + + Multilib packagingMultilibProperties `android:"arch_variant"` Arch packagingArchProperties } func InitPackageModule(p PackageModule) { base := p.packagingBase() - p.AddProperties(&base.properties) + p.AddProperties(&base.properties, &base.properties.DepsProperty) } func (p *PackagingBase) packagingBase() *PackagingBase { @@ -249,55 +260,72 @@ func (p *PackagingBase) packagingBase() *PackagingBase { // the current archicture when this module is not configured for multi target. When configured for // multi target, deps is selected for each of the targets and is NOT selected for the current // architecture which would be Common. -func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) []string { - get := func(prop proptools.Configurable[[]string]) []string { - return prop.GetOrDefault(ctx, nil) +// It returns two lists, the normal and high priority deps, respectively. +func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) ([]string, []string) { + var normalDeps []string + var highPriorityDeps []string + + get := func(prop DepsProperty) { + normalDeps = append(normalDeps, prop.Deps.GetOrDefault(ctx, nil)...) + highPriorityDeps = append(highPriorityDeps, prop.High_priority_deps...) + } + has := func(prop DepsProperty) bool { + return len(prop.Deps.GetOrDefault(ctx, nil)) > 0 || len(prop.High_priority_deps) > 0 } - var ret []string if arch == ctx.Target().Arch.ArchType && len(ctx.MultiTargets()) == 0 { - ret = append(ret, get(p.properties.Deps)...) + get(p.properties.DepsProperty) } else if arch.Multilib == "lib32" { - ret = append(ret, get(p.properties.Multilib.Lib32.Deps)...) + get(p.properties.Multilib.Lib32) // multilib.prefer32.deps are added for lib32 only when they support 32-bit arch - for _, dep := range get(p.properties.Multilib.Prefer32.Deps) { + for _, dep := range p.properties.Multilib.Prefer32.Deps.GetOrDefault(ctx, nil) { + if checkIfOtherModuleSupportsLib32(ctx, dep) { + normalDeps = append(normalDeps, dep) + } + } + for _, dep := range p.properties.Multilib.Prefer32.High_priority_deps { if checkIfOtherModuleSupportsLib32(ctx, dep) { - ret = append(ret, dep) + highPriorityDeps = append(highPriorityDeps, dep) } } } else if arch.Multilib == "lib64" { - ret = append(ret, get(p.properties.Multilib.Lib64.Deps)...) + get(p.properties.Multilib.Lib64) // multilib.prefer32.deps are added for lib64 only when they don't support 32-bit arch - for _, dep := range get(p.properties.Multilib.Prefer32.Deps) { + for _, dep := range p.properties.Multilib.Prefer32.Deps.GetOrDefault(ctx, nil) { if !checkIfOtherModuleSupportsLib32(ctx, dep) { - ret = append(ret, dep) + normalDeps = append(normalDeps, dep) + } + } + for _, dep := range p.properties.Multilib.Prefer32.High_priority_deps { + if !checkIfOtherModuleSupportsLib32(ctx, dep) { + highPriorityDeps = append(highPriorityDeps, dep) } } } else if arch == Common { - ret = append(ret, get(p.properties.Multilib.Common.Deps)...) + get(p.properties.Multilib.Common) } if p.DepsCollectFirstTargetOnly { - if len(get(p.properties.Multilib.First.Deps)) > 0 { + if has(p.properties.Multilib.First) { ctx.PropertyErrorf("multilib.first.deps", "not supported. use \"deps\" instead") } for i, t := range ctx.MultiTargets() { if t.Arch.ArchType == arch { - ret = append(ret, get(p.properties.Multilib.Both.Deps)...) + get(p.properties.Multilib.Both) if i == 0 { - ret = append(ret, get(p.properties.Deps)...) + get(p.properties.DepsProperty) } } } } else { - if len(get(p.properties.Multilib.Both.Deps)) > 0 { + if has(p.properties.Multilib.Both) { ctx.PropertyErrorf("multilib.both.deps", "not supported. use \"deps\" instead") } for i, t := range ctx.MultiTargets() { if t.Arch.ArchType == arch { - ret = append(ret, get(p.properties.Deps)...) + get(p.properties.DepsProperty) if i == 0 { - ret = append(ret, get(p.properties.Multilib.First.Deps)...) + get(p.properties.Multilib.First) } } } @@ -306,17 +334,21 @@ func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) []s if ctx.Arch().ArchType == Common { switch arch { case Arm64: - ret = append(ret, get(p.properties.Arch.Arm64.Deps)...) + get(p.properties.Arch.Arm64) case Arm: - ret = append(ret, get(p.properties.Arch.Arm.Deps)...) + get(p.properties.Arch.Arm) case X86_64: - ret = append(ret, get(p.properties.Arch.X86_64.Deps)...) + get(p.properties.Arch.X86_64) case X86: - ret = append(ret, get(p.properties.Arch.X86.Deps)...) + get(p.properties.Arch.X86) } } - return FirstUniqueStrings(ret) + if len(highPriorityDeps) > 0 && !p.AllowHighPriorityDeps { + ctx.ModuleErrorf("Usage of high_priority_deps is not allowed for %s module type", ctx.ModuleType()) + } + + return FirstUniqueStrings(normalDeps), FirstUniqueStrings(highPriorityDeps) } func getSupportedTargets(ctx BaseModuleContext) []Target { @@ -360,6 +392,8 @@ type PackagingItem interface { IsPackagingItem() bool } +var _ PackagingItem = (*PackagingItemAlwaysDepTag)(nil) + // DepTag provides default implementation of PackagingItem interface. // PackagingBase-derived modules can define their own dependency tag by embedding this, which // can be passed to AddDeps() or AddDependencies(). @@ -371,31 +405,52 @@ func (PackagingItemAlwaysDepTag) IsPackagingItem() bool { return true } +// highPriorityDepTag provides default implementation of HighPriorityPackagingItem interface. +type highPriorityDepTag struct { + blueprint.DependencyTag +} + // See PackageModule.AddDeps func (p *PackagingBase) AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag) { + addDep := func(t Target, dep string, highPriority bool) { + if p.IgnoreMissingDependencies && !ctx.OtherModuleExists(dep) { + return + } + targetVariation := t.Variations() + sharedVariation := blueprint.Variation{ + Mutator: "link", + Variation: "shared", + } + // If a shared variation exists, use that. Static variants do not provide any standalone files + // for packaging. + if ctx.OtherModuleFarDependencyVariantExists([]blueprint.Variation{sharedVariation}, dep) { + targetVariation = append(targetVariation, sharedVariation) + } + depTagToUse := depTag + if highPriority { + depTagToUse = highPriorityDepTag{depTag} + } + + ctx.AddFarVariationDependencies(targetVariation, depTagToUse, dep) + } for _, t := range getSupportedTargets(ctx) { - for _, dep := range p.getDepsForArch(ctx, t.Arch.ArchType) { - if p.IgnoreMissingDependencies && !ctx.OtherModuleExists(dep) { - continue - } - targetVariation := t.Variations() - sharedVariation := blueprint.Variation{ - Mutator: "link", - Variation: "shared", - } - // If a shared variation exists, use that. Static variants do not provide any standalone files - // for packaging. - if ctx.OtherModuleFarDependencyVariantExists([]blueprint.Variation{sharedVariation}, dep) { - targetVariation = append(targetVariation, sharedVariation) - } - ctx.AddFarVariationDependencies(targetVariation, depTag, dep) + normalDeps, highPriorityDeps := p.getDepsForArch(ctx, t.Arch.ArchType) + for _, dep := range normalDeps { + addDep(t, dep, false) + } + for _, dep := range highPriorityDeps { + addDep(t, dep, true) } } } func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec { - // all packaging specs gathered from the dep. - var all []PackagingSpec + // packaging specs gathered from the dep that are not high priorities. + var regularPriorities []PackagingSpec + + // all packaging specs gathered from the high priority deps. + var highPriorities []PackagingSpec + // Name of the dependency which requested the packaging spec. // If this dep is overridden, the packaging spec will not be installed via this dependency chain. // (the packaging spec might still be installed if there are some other deps which depend on it). @@ -420,7 +475,8 @@ func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter } ctx.VisitDirectDeps(func(child Module) { - if pi, ok := ctx.OtherModuleDependencyTag(child).(PackagingItem); !ok || !pi.IsPackagingItem() { + depTag := ctx.OtherModuleDependencyTag(child) + if pi, ok := depTag.(PackagingItem); !ok || !pi.IsPackagingItem() { return } for _, ps := range OtherModuleProviderOrDefault( @@ -434,7 +490,13 @@ func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter continue } } - all = append(all, ps) + + if _, ok := depTag.(highPriorityDepTag); ok { + highPriorities = append(highPriorities, ps) + } else { + regularPriorities = append(regularPriorities, ps) + } + depNames = append(depNames, child.Name()) if ps.overrides != nil { overridden = append(overridden, *ps.overrides...) @@ -442,21 +504,26 @@ func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter } }) - // all minus packaging specs that are overridden - var filtered []PackagingSpec - for index, ps := range all { - if ps.owner != "" && InList(ps.owner, overridden) { - continue - } - // The dependency which requested this packaging spec has been overridden. - if InList(depNames[index], overridden) { - continue + filterOverridden := func(input []PackagingSpec) []PackagingSpec { + // input minus packaging specs that are overridden + var filtered []PackagingSpec + for index, ps := range input { + if ps.owner != "" && InList(ps.owner, overridden) { + continue + } + // The dependency which requested this packaging spec has been overridden. + if InList(depNames[index], overridden) { + continue + } + filtered = append(filtered, ps) } - filtered = append(filtered, ps) + return filtered } + filteredRegularPriority := filterOverridden(regularPriorities) + m := make(map[string]PackagingSpec) - for _, ps := range filtered { + for _, ps := range filteredRegularPriority { dstPath := ps.relPathInPackage if existingPs, ok := m[dstPath]; ok { if !existingPs.Equals(&ps) { @@ -466,6 +533,21 @@ func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter } m[dstPath] = ps } + + filteredHighPriority := filterOverridden(highPriorities) + highPriorityPs := make(map[string]PackagingSpec) + for _, ps := range filteredHighPriority { + dstPath := ps.relPathInPackage + if existingPs, ok := highPriorityPs[dstPath]; ok { + if !existingPs.Equals(&ps) { + ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps) + } + continue + } + highPriorityPs[dstPath] = ps + m[dstPath] = ps + } + return m } diff --git a/android/path_properties.go b/android/path_properties.go index f3c62ea43..55a4dc066 100644 --- a/android/path_properties.go +++ b/android/path_properties.go @@ -52,16 +52,12 @@ func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) { var pathProperties []string var pathDeviceFirstProperties []string var pathDeviceFirstPrefer32Properties []string - var pathDeviceFirstVendorProperties []string - var pathDeviceFirstVendorSharedProperties []string var pathDeviceCommonProperties []string var pathCommonOsProperties []string for _, ps := range props { pathProperties = append(pathProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path")...) pathDeviceFirstProperties = append(pathDeviceFirstProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_first")...) pathDeviceFirstPrefer32Properties = append(pathDeviceFirstPrefer32Properties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_first_prefer32")...) - pathDeviceFirstVendorProperties = append(pathDeviceFirstVendorProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_first_vendor")...) - pathDeviceFirstVendorSharedProperties = append(pathDeviceFirstVendorSharedProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_first_vendor_shared")...) pathDeviceCommonProperties = append(pathDeviceCommonProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_common")...) pathCommonOsProperties = append(pathCommonOsProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_common_os")...) } @@ -70,8 +66,6 @@ func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) { pathProperties = FirstUniqueStrings(pathProperties) pathDeviceFirstProperties = FirstUniqueStrings(pathDeviceFirstProperties) pathDeviceFirstPrefer32Properties = FirstUniqueStrings(pathDeviceFirstPrefer32Properties) - pathDeviceFirstVendorProperties = FirstUniqueStrings(pathDeviceFirstVendorProperties) - pathDeviceFirstVendorSharedProperties = FirstUniqueStrings(pathDeviceFirstVendorSharedProperties) pathDeviceCommonProperties = FirstUniqueStrings(pathDeviceCommonProperties) pathCommonOsProperties = FirstUniqueStrings(pathCommonOsProperties) @@ -108,23 +102,6 @@ func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) { } } } - // path_device_first_vendor is path_device_first + vendor variation - deviceFirstVendorVariations := ctx.Config().AndroidFirstDeviceTarget.Variations() - deviceFirstVendorVariations = append(deviceFirstVendorVariations, - blueprint.Variation{Mutator: "image", Variation: "vendor"}) - for _, s := range pathDeviceFirstVendorProperties { - if m, t := SrcIsModuleWithTag(s); m != "" { - ctx.AddVariationDependencies(deviceFirstVendorVariations, sourceOrOutputDepTag(m, t), m) - } - } - // path_device_first_vendor_shared is path_device_first_vendor + shared linkage variation - deviceFirstVendorSharedVariations := append(deviceFirstVendorVariations, - blueprint.Variation{Mutator: "link", Variation: "shared"}) - for _, s := range pathDeviceFirstVendorSharedProperties { - if m, t := SrcIsModuleWithTag(s); m != "" { - ctx.AddVariationDependencies(deviceFirstVendorSharedVariations, sourceOrOutputDepTag(m, t), m) - } - } // properties tagged "path_device_common" get the device common variant for _, s := range pathDeviceCommonProperties { if m, t := SrcIsModuleWithTag(s); m != "" { diff --git a/android/paths.go b/android/paths.go index bf2c3a097..9cb872d6f 100644 --- a/android/paths.go +++ b/android/paths.go @@ -117,6 +117,9 @@ type ModuleInstallPathContext interface { InstallInOdm() bool InstallInProduct() bool InstallInVendor() bool + InstallInSystemDlkm() bool + InstallInVendorDlkm() bool + InstallInOdmDlkm() bool InstallForceOS() (*OsType, *ArchType) } @@ -170,6 +173,18 @@ func (ctx *baseModuleContextToModuleInstallPathContext) InstallInVendor() bool { return ctx.Module().InstallInVendor() } +func (ctx *baseModuleContextToModuleInstallPathContext) InstallInSystemDlkm() bool { + return ctx.Module().InstallInSystemDlkm() +} + +func (ctx *baseModuleContextToModuleInstallPathContext) InstallInVendorDlkm() bool { + return ctx.Module().InstallInVendorDlkm() +} + +func (ctx *baseModuleContextToModuleInstallPathContext) InstallInOdmDlkm() bool { + return ctx.Module().InstallInOdmDlkm() +} + func (ctx *baseModuleContextToModuleInstallPathContext) InstallForceOS() (*OsType, *ArchType) { return ctx.Module().InstallForceOS() } @@ -551,15 +566,35 @@ func PathsRelativeToModuleSourceDir(input SourceInput) Paths { return ret } +type directoryPath struct { + basePath +} + +func (d *directoryPath) String() string { + return d.basePath.String() +} + +func (d *directoryPath) base() basePath { + return d.basePath +} + +// DirectoryPath represents a source path for directories. Incompatible with Path by design. +type DirectoryPath interface { + String() string + base() basePath +} + +var _ DirectoryPath = (*directoryPath)(nil) + +type DirectoryPaths []DirectoryPath + // DirectoryPathsForModuleSrcExcludes returns a Paths{} containing the resolved references in // directory paths. Elements of paths are resolved as: // - filepath, relative to local module directory, resolves as a filepath relative to the local // source directory // - other modules using the ":name" syntax. These modules must implement DirProvider. -// -// TODO(b/358302178): Implement DirectoryPath and change the return type. -func DirectoryPathsForModuleSrc(ctx ModuleMissingDepsPathContext, paths []string) Paths { - var ret Paths +func DirectoryPathsForModuleSrc(ctx ModuleMissingDepsPathContext, paths []string) DirectoryPaths { + var ret DirectoryPaths for _, path := range paths { if m, t := SrcIsModuleWithTag(path); m != "" { @@ -588,12 +623,12 @@ func DirectoryPathsForModuleSrc(ctx ModuleMissingDepsPathContext, paths []string } else if !isDir { ReportPathErrorf(ctx, "module directory path %q is not a directory", p) } else { - ret = append(ret, p) + ret = append(ret, &directoryPath{basePath{path: p.path, rel: p.rel}}) } } } - seen := make(map[Path]bool, len(ret)) + seen := make(map[DirectoryPath]bool, len(ret)) for _, path := range ret { if seen[path] { ReportPathErrorf(ctx, "duplicated path %q", path) @@ -2057,6 +2092,10 @@ func PathForMainlineSdksInstall(ctx PathContext, paths ...string) InstallPath { return base.Join(ctx, paths...) } +func PathForSuiteInstall(ctx PathContext, suite string, pathComponents ...string) InstallPath { + return pathForPartitionInstallDir(ctx, "test_suites", "test_suites", false).Join(ctx, suite).Join(ctx, pathComponents...) +} + func InstallPathToOnDevicePath(ctx PathContext, path InstallPath) string { rel := Rel(ctx, strings.TrimSuffix(path.PartitionDir(), path.partition), path.String()) return "/" + rel @@ -2111,6 +2150,12 @@ func modulePartition(ctx ModuleInstallPathContext, device bool) string { partition = ctx.DeviceConfig().SystemExtPath() } else if ctx.InstallInRoot() { partition = "root" + } else if ctx.InstallInSystemDlkm() { + partition = ctx.DeviceConfig().SystemDlkmPath() + } else if ctx.InstallInVendorDlkm() { + partition = ctx.DeviceConfig().VendorDlkmPath() + } else if ctx.InstallInOdmDlkm() { + partition = ctx.DeviceConfig().OdmDlkmPath() } else { partition = "system" } @@ -2314,6 +2359,9 @@ type testModuleInstallPathContext struct { inOdm bool inProduct bool inVendor bool + inSystemDlkm bool + inVendorDlkm bool + inOdmDlkm bool forceOS *OsType forceArch *ArchType } @@ -2368,6 +2416,18 @@ func (m testModuleInstallPathContext) InstallInVendor() bool { return m.inVendor } +func (m testModuleInstallPathContext) InstallInSystemDlkm() bool { + return m.inSystemDlkm +} + +func (m testModuleInstallPathContext) InstallInVendorDlkm() bool { + return m.inVendorDlkm +} + +func (m testModuleInstallPathContext) InstallInOdmDlkm() bool { + return m.inOdmDlkm +} + func (m testModuleInstallPathContext) InstallForceOS() (*OsType, *ArchType) { return m.forceOS, m.forceArch } diff --git a/android/paths_test.go b/android/paths_test.go index 941f0ca78..5e618f914 100644 --- a/android/paths_test.go +++ b/android/paths_test.go @@ -1592,6 +1592,12 @@ func TestPathRelativeToTop(t *testing.T) { }) } +func TestDirectoryPathIsIncompatibleWithPath(t *testing.T) { + d := (DirectoryPath)(&directoryPath{}) + _, ok := d.(Path) + AssertBoolEquals(t, "directoryPath shouldn't implement Path", ok, false) +} + func ExampleOutputPath_ReplaceExtension() { ctx := &configErrorWrapper{ config: TestConfig("out", nil, "", nil), diff --git a/android/prebuilt.go b/android/prebuilt.go index 5d75b62fe..51e72af9a 100644 --- a/android/prebuilt.go +++ b/android/prebuilt.go @@ -569,6 +569,7 @@ func hideUnflaggedModules(ctx BottomUpMutatorContext, psi PrebuiltSelectionInfoM for _, moduleInFamily := range allModulesInFamily { if moduleInFamily.Name() != selectedModuleInFamily.Name() { moduleInFamily.HideFromMake() + moduleInFamily.SkipInstall() // If this is a prebuilt module, unset properties.UsePrebuilt // properties.UsePrebuilt might evaluate to true via soong config var fallback mechanism // Set it to false explicitly so that the following mutator does not replace rdeps to this unselected prebuilt @@ -639,6 +640,7 @@ func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) { } } else { m.HideFromMake() + m.SkipInstall() } } } diff --git a/android/register.go b/android/register.go index bb1ead73c..8d2f19e73 100644 --- a/android/register.go +++ b/android/register.go @@ -98,6 +98,7 @@ type mutator struct { usesCreateModule bool mutatesDependencies bool mutatesGlobalState bool + neverFar bool } var _ sortableComponent = &mutator{} diff --git a/android/rule_builder.go b/android/rule_builder.go index 56de9cd00..403c18418 100644 --- a/android/rule_builder.go +++ b/android/rule_builder.go @@ -575,25 +575,28 @@ func (r *RuleBuilder) build(name string, desc string, ninjaEscapeCommandString b nsjailCmd.WriteString(r.outDir.String()) nsjailCmd.WriteString(":nsjail_build_sandbox/out") - for _, input := range inputs { + addBindMount := func(src, dst string) { nsjailCmd.WriteString(" -R $PWD/") - nsjailCmd.WriteString(input.String()) + nsjailCmd.WriteString(src) nsjailCmd.WriteString(":nsjail_build_sandbox/") - nsjailCmd.WriteString(r.nsjailPathForInputRel(input)) + nsjailCmd.WriteString(dst) + } + + for _, input := range inputs { + addBindMount(input.String(), r.nsjailPathForInputRel(input)) } for _, tool := range tools { - nsjailCmd.WriteString(" -R $PWD/") - nsjailCmd.WriteString(tool.String()) - nsjailCmd.WriteString(":nsjail_build_sandbox/") - nsjailCmd.WriteString(nsjailPathForToolRel(r.ctx, tool)) + addBindMount(tool.String(), nsjailPathForToolRel(r.ctx, tool)) } inputs = append(inputs, tools...) for _, c := range r.commands { + for _, directory := range c.implicitDirectories { + addBindMount(directory.String(), directory.String()) + // TODO(b/375551969): Add implicitDirectories to BuildParams, rather than relying on implicits + inputs = append(inputs, SourcePath{basePath: directory.base()}) + } for _, tool := range c.packagedTools { - nsjailCmd.WriteString(" -R $PWD/") - nsjailCmd.WriteString(tool.srcPath.String()) - nsjailCmd.WriteString(":nsjail_build_sandbox/") - nsjailCmd.WriteString(nsjailPathForPackagedToolRel(tool)) + addBindMount(tool.srcPath.String(), nsjailPathForPackagedToolRel(tool)) inputs = append(inputs, tool.srcPath) } } @@ -917,16 +920,17 @@ func (r *RuleBuilder) build(name string, desc string, ninjaEscapeCommandString b type RuleBuilderCommand struct { rule *RuleBuilder - buf strings.Builder - inputs Paths - implicits Paths - orderOnlys Paths - validations Paths - outputs WritablePaths - depFiles WritablePaths - tools Paths - packagedTools []PackagingSpec - rspFiles []rspFileAndPaths + buf strings.Builder + inputs Paths + implicits Paths + orderOnlys Paths + validations Paths + outputs WritablePaths + depFiles WritablePaths + tools Paths + packagedTools []PackagingSpec + rspFiles []rspFileAndPaths + implicitDirectories DirectoryPaths } type rspFileAndPaths struct { @@ -951,6 +955,10 @@ func (c *RuleBuilderCommand) addImplicit(path Path) { c.implicits = append(c.implicits, path) } +func (c *RuleBuilderCommand) addImplicitDirectory(path DirectoryPath) { + c.implicitDirectories = append(c.implicitDirectories, path) +} + func (c *RuleBuilderCommand) addOrderOnly(path Path) { checkPathNotNil(path) c.orderOnlys = append(c.orderOnlys, path) @@ -1313,6 +1321,16 @@ func (c *RuleBuilderCommand) Implicits(paths Paths) *RuleBuilderCommand { return c } +// ImplicitDirectory adds the specified input directory to the dependencies without modifying the +// command line. Added directories will be bind-mounted for the nsjail. +func (c *RuleBuilderCommand) ImplicitDirectory(path DirectoryPath) *RuleBuilderCommand { + if !c.rule.nsjail { + panic("ImplicitDirectory() must be called after Nsjail()") + } + c.addImplicitDirectory(path) + return c +} + // GetImplicits returns the command's implicit inputs. func (c *RuleBuilderCommand) GetImplicits() Paths { return c.implicits diff --git a/android/singleton.go b/android/singleton.go index 913bf6a56..0754b0ccb 100644 --- a/android/singleton.go +++ b/android/singleton.go @@ -64,6 +64,7 @@ type SingletonContext interface { VisitAllModulesBlueprint(visit func(blueprint.Module)) VisitAllModules(visit func(Module)) + VisitAllModuleProxies(visit func(proxy ModuleProxy)) VisitAllModulesIf(pred func(Module) bool, visit func(Module)) VisitDirectDeps(module Module, visit func(Module)) @@ -77,8 +78,10 @@ type SingletonContext interface { VisitAllModuleVariants(module Module, visit func(Module)) + VisitAllModuleVariantProxies(module Module, visit func(proxy ModuleProxy)) + PrimaryModule(module Module) Module - FinalModule(module Module) Module + IsFinalModule(module Module) bool AddNinjaFileDeps(deps ...string) @@ -193,7 +196,7 @@ func (s *singletonContextAdaptor) Eval(pctx PackageContext, ninjaStr string) (st } // visitAdaptor wraps a visit function that takes an android.Module parameter into -// a function that takes an blueprint.Module parameter and only calls the visit function if the +// a function that takes a blueprint.Module parameter and only calls the visit function if the // blueprint.Module is an android.Module. func visitAdaptor(visit func(Module)) func(blueprint.Module) { return func(module blueprint.Module) { @@ -203,6 +206,16 @@ func visitAdaptor(visit func(Module)) func(blueprint.Module) { } } +// visitProxyAdaptor wraps a visit function that takes an android.ModuleProxy parameter into +// a function that takes a blueprint.ModuleProxy parameter. +func visitProxyAdaptor(visit func(proxy ModuleProxy)) func(proxy blueprint.ModuleProxy) { + return func(module blueprint.ModuleProxy) { + visit(ModuleProxy{ + module: module, + }) + } +} + // predAdaptor wraps a pred function that takes an android.Module parameter // into a function that takes an blueprint.Module parameter and only calls the visit function if the // blueprint.Module is an android.Module, otherwise returns false. @@ -224,6 +237,10 @@ func (s *singletonContextAdaptor) VisitAllModules(visit func(Module)) { s.SingletonContext.VisitAllModules(visitAdaptor(visit)) } +func (s *singletonContextAdaptor) VisitAllModuleProxies(visit func(proxy ModuleProxy)) { + s.SingletonContext.VisitAllModuleProxies(visitProxyAdaptor(visit)) +} + func (s *singletonContextAdaptor) VisitAllModulesIf(pred func(Module) bool, visit func(Module)) { s.SingletonContext.VisitAllModulesIf(predAdaptor(pred), visitAdaptor(visit)) } @@ -248,12 +265,16 @@ func (s *singletonContextAdaptor) VisitAllModuleVariants(module Module, visit fu s.SingletonContext.VisitAllModuleVariants(module, visitAdaptor(visit)) } +func (s *singletonContextAdaptor) VisitAllModuleVariantProxies(module Module, visit func(proxy ModuleProxy)) { + s.SingletonContext.VisitAllModuleVariantProxies(module, visitProxyAdaptor(visit)) +} + func (s *singletonContextAdaptor) PrimaryModule(module Module) Module { return s.SingletonContext.PrimaryModule(module).(Module) } -func (s *singletonContextAdaptor) FinalModule(module Module) Module { - return s.SingletonContext.FinalModule(module).(Module) +func (s *singletonContextAdaptor) IsFinalModule(module Module) bool { + return s.SingletonContext.IsFinalModule(module) } func (s *singletonContextAdaptor) ModuleVariantsFromName(referer Module, name string) []Module { diff --git a/android/util.go b/android/util.go index 2d269b724..3fc4608e0 100644 --- a/android/util.go +++ b/android/util.go @@ -660,3 +660,13 @@ func (m *SyncMap[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) { v, loaded := m.Map.LoadOrStore(key, value) return v.(V), loaded } + +// AppendIfNotZero append the given value to the slice if it is not the zero value +// for its type. +func AppendIfNotZero[T comparable](slice []T, value T) []T { + var zeroValue T // Get the zero value of the type T + if value != zeroValue { + return append(slice, value) + } + return slice +} diff --git a/android/variable.go b/android/variable.go index 6693d9197..f82c9cae8 100644 --- a/android/variable.go +++ b/android/variable.go @@ -339,11 +339,16 @@ type ProductVariables struct { HWASanExcludePaths []string `json:",omitempty"` VendorPath *string `json:",omitempty"` + VendorDlkmPath *string `json:",omitempty"` BuildingVendorImage *bool `json:",omitempty"` OdmPath *string `json:",omitempty"` + BuildingOdmImage *bool `json:",omitempty"` + OdmDlkmPath *string `json:",omitempty"` ProductPath *string `json:",omitempty"` BuildingProductImage *bool `json:",omitempty"` SystemExtPath *string `json:",omitempty"` + SystemDlkmPath *string `json:",omitempty"` + OemPath *string `json:",omitempty"` ClangTidy *bool `json:",omitempty"` TidyChecks *string `json:",omitempty"` @@ -535,6 +540,13 @@ type ProductVariables struct { ExtraAllowedDepsTxt *string `json:",omitempty"` AdbKeys *string `json:",omitempty"` + + DeviceMatrixFile []string `json:",omitempty"` + ProductManifestFiles []string `json:",omitempty"` + SystemManifestFile []string `json:",omitempty"` + SystemExtManifestFiles []string `json:",omitempty"` + DeviceManifestFiles []string `json:",omitempty"` + OdmManifestFiles []string `json:",omitempty"` } type PartitionQualifiedVariablesType struct { @@ -565,6 +577,14 @@ type PartitionQualifiedVariablesType struct { BoardAvbRollbackIndexLocation string `json:",omitempty"` } +type ChainedAvbPartitionProps struct { + Partitions []string `json:",omitempty"` + Key string `json:",omitempty"` + Algorithm string `json:",omitempty"` + RollbackIndex string `json:",omitempty"` + RollbackIndexLocation string `json:",omitempty"` +} + type PartitionVariables struct { ProductDirectory string `json:",omitempty"` PartitionQualifiedVariables map[string]PartitionQualifiedVariablesType @@ -589,12 +609,25 @@ type PartitionVariables struct { ProductUseDynamicPartitionSize bool `json:",omitempty"` CopyImagesForTargetFilesZip bool `json:",omitempty"` - BoardAvbEnable bool `json:",omitempty"` + BoardAvbEnable bool `json:",omitempty"` + BoardAvbAlgorithm string `json:",omitempty"` + BoardAvbKeyPath string `json:",omitempty"` + BoardAvbRollbackIndex string `json:",omitempty"` + BuildingVbmetaImage bool `json:",omitempty"` + ChainedVbmetaPartitions map[string]ChainedAvbPartitionProps `json:",omitempty"` - ProductPackages []string `json:",omitempty"` - ProductPackagesDebug []string `json:",omitempty"` + ProductPackages []string `json:",omitempty"` + ProductPackagesDebug []string `json:",omitempty"` + VendorLinkerConfigSrcs []string `json:",omitempty"` + ProductLinkerConfigSrcs []string `json:",omitempty"` + + BoardInfoFiles []string `json:",omitempty"` + BootLoaderBoardName string `json:",omitempty"` ProductCopyFiles map[string]string `json:",omitempty"` + + BuildingSystemDlkmImage bool `json:",omitempty"` + SystemKernelModules []string `json:",omitempty"` } func boolPtr(v bool) *bool { diff --git a/android/vintf_data.go b/android/vintf_data.go new file mode 100644 index 000000000..7823397e0 --- /dev/null +++ b/android/vintf_data.go @@ -0,0 +1,171 @@ +// Copyright 2024 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import ( + "fmt" + "strings" + + "github.com/google/blueprint/proptools" +) + +const ( + deviceCmType = "device_cm" + systemManifestType = "system_manifest" + productManifestType = "product_manifest" + systemExtManifestType = "system_ext_manifest" + vendorManifestType = "vendor_manifest" + odmManifestType = "odm_manifest" + + defaultDcm = "system/libhidl/vintfdata/device_compatibility_matrix.default.xml" + defaultSystemManifest = "system/libhidl/vintfdata/manifest.xml" + defaultSystemExtManifest = "system/libhidl/vintfdata/system_ext_manifest.default.xml" +) + +type vintfDataProperties struct { + // Optional name for the installed file. If unspecified it will be manifest.xml by default. + Filename *string + + // Type of the vintf data type, the allowed type are device_compatibility_matrix, system_manifest, + // product_manifest, and system_ext_manifest. + Type *string +} + +type vintfDataRule struct { + ModuleBase + + properties vintfDataProperties + + installDirPath InstallPath + outputFilePath OutputPath + noAction bool +} + +func init() { + registerVintfDataComponents(InitRegistrationContext) +} + +func registerVintfDataComponents(ctx RegistrationContext) { + ctx.RegisterModuleType("vintf_data", vintfDataFactory) +} + +// vintf_fragment module processes vintf fragment file and installs under etc/vintf/manifest. +func vintfDataFactory() Module { + m := &vintfDataRule{} + m.AddProperties( + &m.properties, + ) + InitAndroidArchModule(m, DeviceSupported, MultilibFirst) + + return m +} + +func (m *vintfDataRule) GenerateAndroidBuildActions(ctx ModuleContext) { + builder := NewRuleBuilder(pctx, ctx) + gensrc := PathForModuleOut(ctx, "manifest.xml") + assembleVintfEnvs := []string{} + inputPaths := make(Paths, 0) + + switch proptools.String(m.properties.Type) { + case deviceCmType: + assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("BOARD_SYSTEMSDK_VERSIONS=\"%s\"", strings.Join(ctx.DeviceConfig().SystemSdkVersions(), " "))) + + deviceMatrixs := PathsForSource(ctx, ctx.Config().DeviceMatrixFile()) + if len(deviceMatrixs) > 0 { + inputPaths = append(inputPaths, deviceMatrixs...) + } else { + inputPaths = append(inputPaths, PathForSource(ctx, defaultDcm)) + } + case systemManifestType: + assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("PLATFORM_SYSTEMSDK_VERSIONS=\"%s\"", strings.Join(ctx.DeviceConfig().PlatformSystemSdkVersions(), " "))) + + inputPaths = append(inputPaths, PathForSource(ctx, defaultSystemManifest)) + systemManifestFiles := PathsForSource(ctx, ctx.Config().SystemManifestFile()) + if len(systemManifestFiles) > 0 { + inputPaths = append(inputPaths, systemManifestFiles...) + } + case productManifestType: + productManifestFiles := PathsForSource(ctx, ctx.Config().ProductManifestFiles()) + // Only need to generate the manifest if PRODUCT_MANIFEST_FILES not defined. + if len(productManifestFiles) == 0 { + m.noAction = true + return + } + + inputPaths = append(inputPaths, productManifestFiles...) + case systemExtManifestType: + assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("PROVIDED_VNDK_VERSIONS=\"%s\"", strings.Join(ctx.DeviceConfig().ExtraVndkVersions(), " "))) + + inputPaths = append(inputPaths, PathForSource(ctx, defaultSystemExtManifest)) + systemExtManifestFiles := PathsForSource(ctx, ctx.Config().SystemExtManifestFiles()) + if len(systemExtManifestFiles) > 0 { + inputPaths = append(inputPaths, systemExtManifestFiles...) + } + case vendorManifestType: + assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("BOARD_SEPOLICY_VERS=\"%s\"", ctx.DeviceConfig().BoardSepolicyVers())) + assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("PRODUCT_ENFORCE_VINTF_MANIFEST=%t", *ctx.Config().productVariables.Enforce_vintf_manifest)) + deviceManifestFiles := PathsForSource(ctx, ctx.Config().DeviceManifestFiles()) + // Only need to generate the manifest if DEVICE_MANIFEST_FILE is defined. + if len(deviceManifestFiles) == 0 { + m.noAction = true + return + } + + inputPaths = append(inputPaths, deviceManifestFiles...) + case odmManifestType: + assembleVintfEnvs = append(assembleVintfEnvs, "VINTF_IGNORE_TARGET_FCM_VERSION=true") + odmManifestFiles := PathsForSource(ctx, ctx.Config().OdmManifestFiles()) + // Only need to generate the manifest if ODM_MANIFEST_FILES is defined. + if len(odmManifestFiles) == 0 { + m.noAction = true + return + } + + inputPaths = append(inputPaths, odmManifestFiles...) + default: + panic(fmt.Errorf("For %s: The attribute 'type' value only allowed device_cm, system_manifest, product_manifest, system_ext_manifest!", ctx.Module().Name())) + } + + // Process vintf fragment source file with assemble_vintf tool + builder.Command(). + Flags(assembleVintfEnvs). + BuiltTool("assemble_vintf"). + FlagWithArg("-i ", strings.Join(inputPaths.Strings(), ":")). + FlagWithOutput("-o ", gensrc) + + builder.Build("assemble_vintf", "Process vintf data "+gensrc.String()) + + m.installDirPath = PathForModuleInstall(ctx, "etc", "vintf") + m.outputFilePath = gensrc.OutputPath + + installFileName := "manifest.xml" + if filename := proptools.String(m.properties.Filename); filename != "" { + installFileName = filename + } + + ctx.InstallFile(m.installDirPath, installFileName, gensrc) +} + +// Make this module visible to AndroidMK so it can be referenced from modules defined from Android.mk files +func (m *vintfDataRule) AndroidMkEntries() []AndroidMkEntries { + if m.noAction { + return []AndroidMkEntries{} + } + + return []AndroidMkEntries{{ + Class: "ETC", + OutputFile: OptionalPathForPath(m.outputFilePath), + }} +} |