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 "strings" 19 20 "android/soong/android" 21 22 "github.com/google/blueprint" 23) 24 25type DeclarationsModule struct { 26 android.ModuleBase 27 android.DefaultableModuleBase 28 29 // Properties for "aconfig_declarations" 30 properties struct { 31 // aconfig files, relative to this Android.bp file 32 Srcs []string `android:"path"` 33 34 // Release config flag package 35 Package string 36 37 // Values from TARGET_RELEASE / RELEASE_ACONFIG_VALUE_SETS 38 Values []string `blueprint:"mutated"` 39 40 // Container(system/vendor/apex) that this module belongs to 41 Container string 42 43 // The flags will only be repackaged if this prop is true. 44 Exportable bool 45 } 46} 47 48func DeclarationsFactory() android.Module { 49 module := &DeclarationsModule{} 50 51 android.InitAndroidModule(module) 52 android.InitDefaultableModule(module) 53 module.AddProperties(&module.properties) 54 55 return module 56} 57 58type implicitValuesTagType struct { 59 blueprint.BaseDependencyTag 60} 61 62var implicitValuesTag = implicitValuesTagType{} 63 64func (module *DeclarationsModule) DepsMutator(ctx android.BottomUpMutatorContext) { 65 // Validate Properties 66 if len(module.properties.Srcs) == 0 { 67 ctx.PropertyErrorf("srcs", "missing source files") 68 return 69 } 70 if len(module.properties.Package) == 0 { 71 ctx.PropertyErrorf("package", "missing package property") 72 } 73 if len(module.properties.Container) == 0 { 74 ctx.PropertyErrorf("container", "missing container property") 75 } 76 77 // Add a dependency on the aconfig_value_sets defined in 78 // RELEASE_ACONFIG_VALUE_SETS, and add any aconfig_values that 79 // match our package. 80 valuesFromConfig := ctx.Config().ReleaseAconfigValueSets() 81 if len(valuesFromConfig) > 0 { 82 ctx.AddDependency(ctx.Module(), implicitValuesTag, valuesFromConfig...) 83 } 84} 85 86func joinAndPrefix(prefix string, values []string) string { 87 var sb strings.Builder 88 for _, v := range values { 89 sb.WriteString(prefix) 90 sb.WriteString(v) 91 } 92 return sb.String() 93} 94 95func optionalVariable(prefix string, value string) string { 96 var sb strings.Builder 97 if value != "" { 98 sb.WriteString(prefix) 99 sb.WriteString(value) 100 } 101 return sb.String() 102} 103 104func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 105 // Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag 106 valuesFiles := make([]android.Path, 0) 107 ctx.VisitDirectDeps(func(dep android.Module) { 108 if depData, ok := android.OtherModuleProvider(ctx, dep, valueSetProviderKey); ok { 109 paths, ok := depData.AvailablePackages[module.properties.Package] 110 if ok { 111 valuesFiles = append(valuesFiles, paths...) 112 for _, path := range paths { 113 module.properties.Values = append(module.properties.Values, path.String()) 114 } 115 } 116 } 117 }) 118 119 // Intermediate format 120 declarationFiles := android.PathsForModuleSrc(ctx, module.properties.Srcs) 121 intermediateCacheFilePath := android.PathForModuleOut(ctx, "intermediate.pb") 122 defaultPermission := ctx.Config().ReleaseAconfigFlagDefaultPermission() 123 inputFiles := make([]android.Path, len(declarationFiles)) 124 copy(inputFiles, declarationFiles) 125 inputFiles = append(inputFiles, valuesFiles...) 126 args := map[string]string{ 127 "release_version": ctx.Config().ReleaseVersion(), 128 "package": module.properties.Package, 129 "declarations": android.JoinPathsWithPrefix(declarationFiles, "--declarations "), 130 "values": joinAndPrefix(" --values ", module.properties.Values), 131 "default-permission": optionalVariable(" --default-permission ", defaultPermission), 132 } 133 if len(module.properties.Container) > 0 { 134 args["container"] = "--container " + module.properties.Container 135 } 136 ctx.Build(pctx, android.BuildParams{ 137 Rule: aconfigRule, 138 Output: intermediateCacheFilePath, 139 Inputs: inputFiles, 140 Description: "aconfig_declarations", 141 Args: args, 142 }) 143 144 intermediateDumpFilePath := android.PathForModuleOut(ctx, "intermediate.txt") 145 ctx.Build(pctx, android.BuildParams{ 146 Rule: aconfigTextRule, 147 Output: intermediateDumpFilePath, 148 Inputs: android.Paths{intermediateCacheFilePath}, 149 Description: "aconfig_text", 150 }) 151 152 android.SetProvider(ctx, android.AconfigDeclarationsProviderKey, android.AconfigDeclarationsProviderData{ 153 Package: module.properties.Package, 154 Container: module.properties.Container, 155 Exportable: module.properties.Exportable, 156 IntermediateCacheOutputPath: intermediateCacheFilePath, 157 IntermediateDumpOutputPath: intermediateDumpFilePath, 158 }) 159} 160