| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 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 |  | 
| Joe Onorato | 981c926 | 2023-06-21 15:16:23 -0700 | [diff] [blame] | 15 | package aconfig | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 16 |  | 
|  | 17 | import ( | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 18 | "fmt" | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 19 | "strings" | 
| Vinh Tran | 457ddef | 2023-08-02 13:50:26 -0400 | [diff] [blame] | 20 |  | 
| Yu Liu | 2cc802a | 2023-09-05 17:19:45 -0700 | [diff] [blame] | 21 | "android/soong/android" | 
| Jihoon Kang | cca3e0c | 2023-11-29 19:35:29 +0000 | [diff] [blame] | 22 |  | 
| Vinh Tran | 457ddef | 2023-08-02 13:50:26 -0400 | [diff] [blame] | 23 | "github.com/google/blueprint" | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 24 | ) | 
|  | 25 |  | 
| Joe Onorato | 981c926 | 2023-06-21 15:16:23 -0700 | [diff] [blame] | 26 | type DeclarationsModule struct { | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 27 | android.ModuleBase | 
|  | 28 | android.DefaultableModuleBase | 
|  | 29 |  | 
| Joe Onorato | 981c926 | 2023-06-21 15:16:23 -0700 | [diff] [blame] | 30 | // Properties for "aconfig_declarations" | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 31 | properties struct { | 
|  | 32 | // aconfig files, relative to this Android.bp file | 
|  | 33 | Srcs []string `android:"path"` | 
|  | 34 |  | 
| Joe Onorato | 81b25ed | 2023-06-21 13:49:37 -0700 | [diff] [blame] | 35 | // Release config flag package | 
|  | 36 | Package string | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 37 |  | 
| Joe Onorato | 981c926 | 2023-06-21 15:16:23 -0700 | [diff] [blame] | 38 | // Values from TARGET_RELEASE / RELEASE_ACONFIG_VALUE_SETS | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 39 | Values []string `blueprint:"mutated"` | 
| Yu Liu | eae7b36 | 2023-11-16 17:05:47 -0800 | [diff] [blame] | 40 |  | 
|  | 41 | // Container(system/vendor/apex) that this module belongs to | 
|  | 42 | Container string | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 43 | } | 
|  | 44 |  | 
|  | 45 | intermediatePath android.WritablePath | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 46 | } | 
|  | 47 |  | 
| Joe Onorato | 981c926 | 2023-06-21 15:16:23 -0700 | [diff] [blame] | 48 | func DeclarationsFactory() android.Module { | 
|  | 49 | module := &DeclarationsModule{} | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 50 |  | 
|  | 51 | android.InitAndroidModule(module) | 
|  | 52 | android.InitDefaultableModule(module) | 
|  | 53 | module.AddProperties(&module.properties) | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 54 |  | 
|  | 55 | return module | 
|  | 56 | } | 
|  | 57 |  | 
|  | 58 | type implicitValuesTagType struct { | 
|  | 59 | blueprint.BaseDependencyTag | 
|  | 60 | } | 
|  | 61 |  | 
|  | 62 | var implicitValuesTag = implicitValuesTagType{} | 
|  | 63 |  | 
| Joe Onorato | 981c926 | 2023-06-21 15:16:23 -0700 | [diff] [blame] | 64 | func (module *DeclarationsModule) DepsMutator(ctx android.BottomUpMutatorContext) { | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 65 | // Validate Properties | 
|  | 66 | if len(module.properties.Srcs) == 0 { | 
|  | 67 | ctx.PropertyErrorf("srcs", "missing source files") | 
|  | 68 | return | 
|  | 69 | } | 
| Joe Onorato | 81b25ed | 2023-06-21 13:49:37 -0700 | [diff] [blame] | 70 | if len(module.properties.Package) == 0 { | 
|  | 71 | ctx.PropertyErrorf("package", "missing package property") | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 72 | } | 
| Yu Liu | eae7b36 | 2023-11-16 17:05:47 -0800 | [diff] [blame] | 73 | // TODO(b/311155208): Add mandatory check for container after all pre-existing | 
|  | 74 | // ones are changed. | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 75 |  | 
| Joe Onorato | 981c926 | 2023-06-21 15:16:23 -0700 | [diff] [blame] | 76 | // Add a dependency on the aconfig_value_sets defined in | 
|  | 77 | // RELEASE_ACONFIG_VALUE_SETS, and add any aconfig_values that | 
| Joe Onorato | 81b25ed | 2023-06-21 13:49:37 -0700 | [diff] [blame] | 78 | // match our package. | 
| Joe Onorato | 981c926 | 2023-06-21 15:16:23 -0700 | [diff] [blame] | 79 | valuesFromConfig := ctx.Config().ReleaseAconfigValueSets() | 
| Yu Liu | eebb259 | 2023-10-12 20:31:27 -0700 | [diff] [blame] | 80 | if len(valuesFromConfig) > 0 { | 
|  | 81 | ctx.AddDependency(ctx.Module(), implicitValuesTag, valuesFromConfig...) | 
| Yu Liu | 2cc802a | 2023-09-05 17:19:45 -0700 | [diff] [blame] | 82 | } | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 83 | } | 
|  | 84 |  | 
| Joe Onorato | 981c926 | 2023-06-21 15:16:23 -0700 | [diff] [blame] | 85 | func (module *DeclarationsModule) OutputFiles(tag string) (android.Paths, error) { | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 86 | switch tag { | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 87 | case "": | 
|  | 88 | // The default output of this module is the intermediates format, which is | 
|  | 89 | // not installable and in a private format that no other rules can handle | 
|  | 90 | // correctly. | 
|  | 91 | return []android.Path{module.intermediatePath}, nil | 
|  | 92 | default: | 
| Joe Onorato | 981c926 | 2023-06-21 15:16:23 -0700 | [diff] [blame] | 93 | return nil, fmt.Errorf("unsupported aconfig_declarations module reference tag %q", tag) | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 94 | } | 
|  | 95 | } | 
|  | 96 |  | 
|  | 97 | func joinAndPrefix(prefix string, values []string) string { | 
|  | 98 | var sb strings.Builder | 
|  | 99 | for _, v := range values { | 
|  | 100 | sb.WriteString(prefix) | 
|  | 101 | sb.WriteString(v) | 
|  | 102 | } | 
|  | 103 | return sb.String() | 
|  | 104 | } | 
|  | 105 |  | 
| Zhi Dou | 3f65a41 | 2023-08-10 21:47:40 +0000 | [diff] [blame] | 106 | func optionalVariable(prefix string, value string) string { | 
|  | 107 | var sb strings.Builder | 
|  | 108 | if value != "" { | 
|  | 109 | sb.WriteString(prefix) | 
|  | 110 | sb.WriteString(value) | 
|  | 111 | } | 
|  | 112 | return sb.String() | 
|  | 113 | } | 
|  | 114 |  | 
| Joe Onorato | 981c926 | 2023-06-21 15:16:23 -0700 | [diff] [blame] | 115 | // Provider published by aconfig_value_set | 
| Yu Liu | eae7b36 | 2023-11-16 17:05:47 -0800 | [diff] [blame] | 116 | type DeclarationsProviderData struct { | 
| Jihoon Kang | cca3e0c | 2023-11-29 19:35:29 +0000 | [diff] [blame] | 117 | Package                     string | 
|  | 118 | Container                   string | 
|  | 119 | IntermediateCacheOutputPath android.WritablePath | 
|  | 120 | IntermediateDumpOutputPath  android.WritablePath | 
| Joe Onorato | 175073c | 2023-06-01 14:42:59 -0700 | [diff] [blame] | 121 | } | 
|  | 122 |  | 
| Colin Cross | bc7d76c | 2023-12-12 16:39:03 -0800 | [diff] [blame] | 123 | var DeclarationsProviderKey = blueprint.NewProvider[DeclarationsProviderData]() | 
| Yu Liu | eae7b36 | 2023-11-16 17:05:47 -0800 | [diff] [blame] | 124 |  | 
|  | 125 | // This is used to collect the aconfig declarations info on the transitive closure, | 
|  | 126 | // the data is keyed on the container. | 
|  | 127 | type TransitiveDeclarationsInfo struct { | 
| Colin Cross | d788b3e | 2023-11-28 13:14:56 -0800 | [diff] [blame] | 128 | AconfigFiles map[string]android.Paths | 
| Yu Liu | eae7b36 | 2023-11-16 17:05:47 -0800 | [diff] [blame] | 129 | } | 
|  | 130 |  | 
| Colin Cross | bc7d76c | 2023-12-12 16:39:03 -0800 | [diff] [blame] | 131 | var TransitiveDeclarationsInfoProvider = blueprint.NewProvider[TransitiveDeclarationsInfo]() | 
| Joe Onorato | 175073c | 2023-06-01 14:42:59 -0700 | [diff] [blame] | 132 |  | 
| Joe Onorato | 981c926 | 2023-06-21 15:16:23 -0700 | [diff] [blame] | 133 | func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { | 
|  | 134 | // Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag | 
| Joe Onorato | 4551ea1 | 2023-08-19 19:02:15 -0700 | [diff] [blame] | 135 | valuesFiles := make([]android.Path, 0) | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 136 | ctx.VisitDirectDeps(func(dep android.Module) { | 
| Colin Cross | 313aa54 | 2023-12-13 13:47:44 -0800 | [diff] [blame] | 137 | if depData, ok := android.OtherModuleProvider(ctx, dep, valueSetProviderKey); ok { | 
|  | 138 | paths, ok := depData.AvailablePackages[module.properties.Package] | 
|  | 139 | if ok { | 
|  | 140 | valuesFiles = append(valuesFiles, paths...) | 
|  | 141 | for _, path := range paths { | 
|  | 142 | module.properties.Values = append(module.properties.Values, path.String()) | 
|  | 143 | } | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 144 | } | 
|  | 145 | } | 
|  | 146 | }) | 
|  | 147 |  | 
|  | 148 | // Intermediate format | 
| Joe Onorato | 4551ea1 | 2023-08-19 19:02:15 -0700 | [diff] [blame] | 149 | declarationFiles := android.PathsForModuleSrc(ctx, module.properties.Srcs) | 
| Jihoon Kang | cca3e0c | 2023-11-29 19:35:29 +0000 | [diff] [blame] | 150 | intermediateCacheFilePath := android.PathForModuleOut(ctx, "intermediate.pb") | 
| Zhi Dou | 3f65a41 | 2023-08-10 21:47:40 +0000 | [diff] [blame] | 151 | defaultPermission := ctx.Config().ReleaseAconfigFlagDefaultPermission() | 
| Joe Onorato | 4551ea1 | 2023-08-19 19:02:15 -0700 | [diff] [blame] | 152 | inputFiles := make([]android.Path, len(declarationFiles)) | 
|  | 153 | copy(inputFiles, declarationFiles) | 
|  | 154 | inputFiles = append(inputFiles, valuesFiles...) | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 155 | ctx.Build(pctx, android.BuildParams{ | 
|  | 156 | Rule:        aconfigRule, | 
| Jihoon Kang | cca3e0c | 2023-11-29 19:35:29 +0000 | [diff] [blame] | 157 | Output:      intermediateCacheFilePath, | 
| Joe Onorato | 4551ea1 | 2023-08-19 19:02:15 -0700 | [diff] [blame] | 158 | Inputs:      inputFiles, | 
| Joe Onorato | 981c926 | 2023-06-21 15:16:23 -0700 | [diff] [blame] | 159 | Description: "aconfig_declarations", | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 160 | Args: map[string]string{ | 
| Zhi Dou | 3f65a41 | 2023-08-10 21:47:40 +0000 | [diff] [blame] | 161 | "release_version":    ctx.Config().ReleaseVersion(), | 
|  | 162 | "package":            module.properties.Package, | 
| Joe Onorato | 4551ea1 | 2023-08-19 19:02:15 -0700 | [diff] [blame] | 163 | "declarations":       android.JoinPathsWithPrefix(declarationFiles, "--declarations "), | 
| Zhi Dou | 3f65a41 | 2023-08-10 21:47:40 +0000 | [diff] [blame] | 164 | "values":             joinAndPrefix(" --values ", module.properties.Values), | 
|  | 165 | "default-permission": optionalVariable(" --default-permission ", defaultPermission), | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 166 | }, | 
|  | 167 | }) | 
|  | 168 |  | 
| Jihoon Kang | cca3e0c | 2023-11-29 19:35:29 +0000 | [diff] [blame] | 169 | intermediateDumpFilePath := android.PathForModuleOut(ctx, "intermediate.txt") | 
|  | 170 | ctx.Build(pctx, android.BuildParams{ | 
|  | 171 | Rule:        aconfigTextRule, | 
|  | 172 | Output:      intermediateDumpFilePath, | 
|  | 173 | Inputs:      android.Paths{intermediateCacheFilePath}, | 
|  | 174 | Description: "aconfig_text", | 
|  | 175 | }) | 
|  | 176 |  | 
| Colin Cross | 4021302 | 2023-12-13 15:19:49 -0800 | [diff] [blame] | 177 | android.SetProvider(ctx, DeclarationsProviderKey, DeclarationsProviderData{ | 
| Jihoon Kang | cca3e0c | 2023-11-29 19:35:29 +0000 | [diff] [blame] | 178 | Package:                     module.properties.Package, | 
|  | 179 | Container:                   module.properties.Container, | 
|  | 180 | IntermediateCacheOutputPath: intermediateCacheFilePath, | 
|  | 181 | IntermediateDumpOutputPath:  intermediateDumpFilePath, | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 182 | }) | 
|  | 183 |  | 
| Joe Onorato | fee845a | 2023-05-09 08:14:14 -0700 | [diff] [blame] | 184 | } | 
| Colin Cross | d788b3e | 2023-11-28 13:14:56 -0800 | [diff] [blame] | 185 | func CollectDependencyAconfigFiles(ctx android.ModuleContext, mergedAconfigFiles *map[string]android.Paths) { | 
|  | 186 | if *mergedAconfigFiles == nil { | 
|  | 187 | *mergedAconfigFiles = make(map[string]android.Paths) | 
| Yu Liu | eae7b36 | 2023-11-16 17:05:47 -0800 | [diff] [blame] | 188 | } | 
|  | 189 | ctx.VisitDirectDeps(func(module android.Module) { | 
| Colin Cross | 313aa54 | 2023-12-13 13:47:44 -0800 | [diff] [blame] | 190 | if dep, _ := android.OtherModuleProvider(ctx, module, DeclarationsProviderKey); dep.IntermediateCacheOutputPath != nil { | 
| Jihoon Kang | cca3e0c | 2023-11-29 19:35:29 +0000 | [diff] [blame] | 191 | (*mergedAconfigFiles)[dep.Container] = append((*mergedAconfigFiles)[dep.Container], dep.IntermediateCacheOutputPath) | 
| Yu Liu | eae7b36 | 2023-11-16 17:05:47 -0800 | [diff] [blame] | 192 | return | 
|  | 193 | } | 
| Colin Cross | 313aa54 | 2023-12-13 13:47:44 -0800 | [diff] [blame] | 194 | if dep, _ := android.OtherModuleProvider(ctx, module, TransitiveDeclarationsInfoProvider); len(dep.AconfigFiles) > 0 { | 
| Colin Cross | d788b3e | 2023-11-28 13:14:56 -0800 | [diff] [blame] | 195 | for container, v := range dep.AconfigFiles { | 
|  | 196 | (*mergedAconfigFiles)[container] = append((*mergedAconfigFiles)[container], v...) | 
|  | 197 | } | 
| Yu Liu | eae7b36 | 2023-11-16 17:05:47 -0800 | [diff] [blame] | 198 | } | 
|  | 199 | }) | 
|  | 200 |  | 
| Colin Cross | d788b3e | 2023-11-28 13:14:56 -0800 | [diff] [blame] | 201 | for container, aconfigFiles := range *mergedAconfigFiles { | 
|  | 202 | (*mergedAconfigFiles)[container] = mergeAconfigFiles(ctx, aconfigFiles) | 
|  | 203 | } | 
|  | 204 |  | 
| Colin Cross | 4021302 | 2023-12-13 15:19:49 -0800 | [diff] [blame] | 205 | android.SetProvider(ctx, TransitiveDeclarationsInfoProvider, TransitiveDeclarationsInfo{ | 
| Colin Cross | d788b3e | 2023-11-28 13:14:56 -0800 | [diff] [blame] | 206 | AconfigFiles: *mergedAconfigFiles, | 
| Yu Liu | eae7b36 | 2023-11-16 17:05:47 -0800 | [diff] [blame] | 207 | }) | 
|  | 208 | } | 
|  | 209 |  | 
| Colin Cross | d788b3e | 2023-11-28 13:14:56 -0800 | [diff] [blame] | 210 | func mergeAconfigFiles(ctx android.ModuleContext, inputs android.Paths) android.Paths { | 
| Yu Liu | cec0e41 | 2023-11-30 16:45:50 -0800 | [diff] [blame] | 211 | inputs = android.LastUniquePaths(inputs) | 
| Colin Cross | d788b3e | 2023-11-28 13:14:56 -0800 | [diff] [blame] | 212 | if len(inputs) == 1 { | 
|  | 213 | return android.Paths{inputs[0]} | 
| Yu Liu | eae7b36 | 2023-11-16 17:05:47 -0800 | [diff] [blame] | 214 | } | 
| Colin Cross | d788b3e | 2023-11-28 13:14:56 -0800 | [diff] [blame] | 215 |  | 
|  | 216 | output := android.PathForModuleOut(ctx, "aconfig_merged.pb") | 
|  | 217 |  | 
|  | 218 | ctx.Build(pctx, android.BuildParams{ | 
|  | 219 | Rule:        mergeAconfigFilesRule, | 
|  | 220 | Description: "merge aconfig files", | 
|  | 221 | Inputs:      inputs, | 
|  | 222 | Output:      output, | 
|  | 223 | Args: map[string]string{ | 
|  | 224 | "flags": android.JoinWithPrefix(inputs.Strings(), "--cache "), | 
|  | 225 | }, | 
|  | 226 | }) | 
|  | 227 |  | 
|  | 228 | return android.Paths{output} | 
| Yu Liu | eae7b36 | 2023-11-16 17:05:47 -0800 | [diff] [blame] | 229 | } | 
| Yu Liu | 6dc93f9 | 2023-12-14 01:19:35 +0000 | [diff] [blame] | 230 |  | 
|  | 231 | func SetAconfigFileMkEntries(m *android.ModuleBase, entries *android.AndroidMkEntries, aconfigFiles map[string]android.Paths) { | 
| Yu Liu | 22e32f1 | 2023-12-18 14:44:34 -0800 | [diff] [blame] | 232 | // TODO(b/311155208): The default container here should be system. | 
|  | 233 | container := "" | 
|  | 234 |  | 
|  | 235 | if m.SocSpecific() { | 
|  | 236 | container = "vendor" | 
|  | 237 | } else if m.ProductSpecific() { | 
|  | 238 | container = "product" | 
|  | 239 | } else if m.SystemExtSpecific() { | 
|  | 240 | container = "system_ext" | 
| Yu Liu | 6dc93f9 | 2023-12-14 01:19:35 +0000 | [diff] [blame] | 241 | } | 
| Yu Liu | 22e32f1 | 2023-12-18 14:44:34 -0800 | [diff] [blame] | 242 |  | 
|  | 243 | entries.SetPaths("LOCAL_ACONFIG_FILES", aconfigFiles[container]) | 
| Yu Liu | 6dc93f9 | 2023-12-14 01:19:35 +0000 | [diff] [blame] | 244 | } |