1// Copyright 2023 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package aconfig 16 17import ( 18 "android/soong/android" 19 "fmt" 20 "strings" 21 22 "github.com/google/blueprint" 23) 24 25// Properties for "aconfig_value_set" 26type ValueSetModule struct { 27 android.ModuleBase 28 android.DefaultableModuleBase 29 30 properties struct { 31 // aconfig_values modules 32 Values []string 33 34 // Paths to the Android.bp files where the aconfig_values modules are defined. 35 Srcs []string 36 } 37} 38 39func ValueSetFactory() android.Module { 40 module := &ValueSetModule{} 41 42 android.InitAndroidModule(module) 43 android.InitDefaultableModule(module) 44 module.AddProperties(&module.properties) 45 46 return module 47} 48 49// Dependency tag for values property 50type valueSetType struct { 51 blueprint.BaseDependencyTag 52} 53 54var valueSetTag = valueSetType{} 55 56// Provider published by aconfig_value_set 57type valueSetProviderData struct { 58 // The package of each of the 59 // (map of package --> aconfig_module) 60 AvailablePackages map[string]android.Paths 61} 62 63var valueSetProviderKey = blueprint.NewProvider[valueSetProviderData]() 64 65func (module *ValueSetModule) FindAconfigValuesFromSrc(ctx android.BottomUpMutatorContext) map[string]android.Path { 66 moduleDir := ctx.ModuleDir() 67 srcs := android.PathsForModuleSrcExcludes(ctx, module.properties.Srcs, []string{ctx.BlueprintsFile()}) 68 69 aconfigValuesPrefix := strings.Replace(module.Name(), "aconfig_value_set", "aconfig-values", 1) 70 moduleNamesSrcMap := make(map[string]android.Path) 71 for _, src := range srcs { 72 subDir := strings.TrimPrefix(src.String(), moduleDir+"/") 73 packageName, _, found := strings.Cut(subDir, "/") 74 if found { 75 moduleName := fmt.Sprintf("%s-%s-all", aconfigValuesPrefix, packageName) 76 moduleNamesSrcMap[moduleName] = src 77 } 78 } 79 return moduleNamesSrcMap 80} 81 82func (module *ValueSetModule) DepsMutator(ctx android.BottomUpMutatorContext) { 83 84 // TODO: b/366285733 - Replace the file path based solution with more robust solution. 85 aconfigValuesMap := module.FindAconfigValuesFromSrc(ctx) 86 for _, moduleName := range android.SortedKeys(aconfigValuesMap) { 87 if ctx.OtherModuleExists(moduleName) { 88 ctx.AddDependency(ctx.Module(), valueSetTag, moduleName) 89 } else { 90 ctx.ModuleErrorf("module %q not found. Rename the aconfig_values module defined in %q to %q", moduleName, aconfigValuesMap[moduleName], moduleName) 91 } 92 } 93 94 deps := ctx.AddDependency(ctx.Module(), valueSetTag, module.properties.Values...) 95 for _, dep := range deps { 96 _, ok := dep.(*ValuesModule) 97 if !ok { 98 ctx.PropertyErrorf("values", "values must be a aconfig_values module") 99 return 100 } 101 } 102} 103 104func (module *ValueSetModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 105 // Accumulate the packages of the values modules listed, and set that as an 106 // valueSetProviderKey provider that aconfig modules can read and use 107 // to append values to their aconfig actions. 108 packages := make(map[string]android.Paths) 109 ctx.VisitDirectDeps(func(dep android.Module) { 110 if depData, ok := android.OtherModuleProvider(ctx, dep, valuesProviderKey); ok { 111 srcs := make([]android.Path, len(depData.Values)) 112 copy(srcs, depData.Values) 113 packages[depData.Package] = srcs 114 } 115 116 }) 117 android.SetProvider(ctx, valueSetProviderKey, valueSetProviderData{ 118 AvailablePackages: packages, 119 }) 120} 121