1*333d2b36SAndroid Build Coastguard Worker// Copyright 2023 Google Inc. All rights reserved. 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage aconfig 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "android/soong/android" 19*333d2b36SAndroid Build Coastguard Worker "path/filepath" 20*333d2b36SAndroid Build Coastguard Worker "slices" 21*333d2b36SAndroid Build Coastguard Worker "strconv" 22*333d2b36SAndroid Build Coastguard Worker "strings" 23*333d2b36SAndroid Build Coastguard Worker 24*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint" 25*333d2b36SAndroid Build Coastguard Worker) 26*333d2b36SAndroid Build Coastguard Worker 27*333d2b36SAndroid Build Coastguard Workertype AconfigReleaseConfigValue struct { 28*333d2b36SAndroid Build Coastguard Worker ReleaseConfig string 29*333d2b36SAndroid Build Coastguard Worker Values []string `blueprint:"mutated"` 30*333d2b36SAndroid Build Coastguard Worker} 31*333d2b36SAndroid Build Coastguard Worker 32*333d2b36SAndroid Build Coastguard Workertype DeclarationsModule struct { 33*333d2b36SAndroid Build Coastguard Worker android.ModuleBase 34*333d2b36SAndroid Build Coastguard Worker android.DefaultableModuleBase 35*333d2b36SAndroid Build Coastguard Worker blueprint.IncrementalModule 36*333d2b36SAndroid Build Coastguard Worker 37*333d2b36SAndroid Build Coastguard Worker // Properties for "aconfig_declarations" 38*333d2b36SAndroid Build Coastguard Worker properties struct { 39*333d2b36SAndroid Build Coastguard Worker // aconfig files, relative to this Android.bp file 40*333d2b36SAndroid Build Coastguard Worker Srcs []string `android:"path"` 41*333d2b36SAndroid Build Coastguard Worker 42*333d2b36SAndroid Build Coastguard Worker // Release config flag package 43*333d2b36SAndroid Build Coastguard Worker Package string 44*333d2b36SAndroid Build Coastguard Worker 45*333d2b36SAndroid Build Coastguard Worker // Values for release configs / RELEASE_ACONFIG_VALUE_SETS 46*333d2b36SAndroid Build Coastguard Worker // The current release config is `ReleaseConfig: ""`, others 47*333d2b36SAndroid Build Coastguard Worker // are from RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS. 48*333d2b36SAndroid Build Coastguard Worker ReleaseConfigValues []AconfigReleaseConfigValue 49*333d2b36SAndroid Build Coastguard Worker 50*333d2b36SAndroid Build Coastguard Worker // Container(system/vendor/apex) that this module belongs to 51*333d2b36SAndroid Build Coastguard Worker Container string 52*333d2b36SAndroid Build Coastguard Worker 53*333d2b36SAndroid Build Coastguard Worker // The flags will only be repackaged if this prop is true. 54*333d2b36SAndroid Build Coastguard Worker Exportable bool 55*333d2b36SAndroid Build Coastguard Worker } 56*333d2b36SAndroid Build Coastguard Worker} 57*333d2b36SAndroid Build Coastguard Worker 58*333d2b36SAndroid Build Coastguard Workerfunc DeclarationsFactory() android.Module { 59*333d2b36SAndroid Build Coastguard Worker module := &DeclarationsModule{} 60*333d2b36SAndroid Build Coastguard Worker 61*333d2b36SAndroid Build Coastguard Worker android.InitAndroidModule(module) 62*333d2b36SAndroid Build Coastguard Worker android.InitDefaultableModule(module) 63*333d2b36SAndroid Build Coastguard Worker module.AddProperties(&module.properties) 64*333d2b36SAndroid Build Coastguard Worker 65*333d2b36SAndroid Build Coastguard Worker return module 66*333d2b36SAndroid Build Coastguard Worker} 67*333d2b36SAndroid Build Coastguard Worker 68*333d2b36SAndroid Build Coastguard Workertype implicitValuesTagType struct { 69*333d2b36SAndroid Build Coastguard Worker blueprint.BaseDependencyTag 70*333d2b36SAndroid Build Coastguard Worker 71*333d2b36SAndroid Build Coastguard Worker // The release config name for these values. 72*333d2b36SAndroid Build Coastguard Worker // Empty string for the actual current release config. 73*333d2b36SAndroid Build Coastguard Worker ReleaseConfig string 74*333d2b36SAndroid Build Coastguard Worker} 75*333d2b36SAndroid Build Coastguard Worker 76*333d2b36SAndroid Build Coastguard Workervar implicitValuesTag = implicitValuesTagType{} 77*333d2b36SAndroid Build Coastguard Worker 78*333d2b36SAndroid Build Coastguard Workerfunc (module *DeclarationsModule) DepsMutator(ctx android.BottomUpMutatorContext) { 79*333d2b36SAndroid Build Coastguard Worker // Validate Properties 80*333d2b36SAndroid Build Coastguard Worker if len(module.properties.Srcs) == 0 { 81*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("srcs", "missing source files") 82*333d2b36SAndroid Build Coastguard Worker return 83*333d2b36SAndroid Build Coastguard Worker } 84*333d2b36SAndroid Build Coastguard Worker if len(module.properties.Package) == 0 { 85*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("package", "missing package property") 86*333d2b36SAndroid Build Coastguard Worker } 87*333d2b36SAndroid Build Coastguard Worker if len(module.properties.Container) == 0 { 88*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("container", "missing container property") 89*333d2b36SAndroid Build Coastguard Worker } 90*333d2b36SAndroid Build Coastguard Worker 91*333d2b36SAndroid Build Coastguard Worker // treating system_ext as system partition as we are combining them as one container 92*333d2b36SAndroid Build Coastguard Worker // TODO remove this logic once we start enforcing that system_ext cannot be specified as 93*333d2b36SAndroid Build Coastguard Worker // container in the container field. 94*333d2b36SAndroid Build Coastguard Worker if module.properties.Container == "system_ext" { 95*333d2b36SAndroid Build Coastguard Worker module.properties.Container = "system" 96*333d2b36SAndroid Build Coastguard Worker } 97*333d2b36SAndroid Build Coastguard Worker 98*333d2b36SAndroid Build Coastguard Worker // Add a dependency on the aconfig_value_sets defined in 99*333d2b36SAndroid Build Coastguard Worker // RELEASE_ACONFIG_VALUE_SETS, and add any aconfig_values that 100*333d2b36SAndroid Build Coastguard Worker // match our package. 101*333d2b36SAndroid Build Coastguard Worker valuesFromConfig := ctx.Config().ReleaseAconfigValueSets() 102*333d2b36SAndroid Build Coastguard Worker if len(valuesFromConfig) > 0 { 103*333d2b36SAndroid Build Coastguard Worker ctx.AddDependency(ctx.Module(), implicitValuesTag, valuesFromConfig...) 104*333d2b36SAndroid Build Coastguard Worker } 105*333d2b36SAndroid Build Coastguard Worker for rcName, valueSets := range ctx.Config().ReleaseAconfigExtraReleaseConfigsValueSets() { 106*333d2b36SAndroid Build Coastguard Worker if len(valueSets) > 0 { 107*333d2b36SAndroid Build Coastguard Worker ctx.AddDependency(ctx.Module(), implicitValuesTagType{ReleaseConfig: rcName}, valueSets...) 108*333d2b36SAndroid Build Coastguard Worker } 109*333d2b36SAndroid Build Coastguard Worker } 110*333d2b36SAndroid Build Coastguard Worker} 111*333d2b36SAndroid Build Coastguard Worker 112*333d2b36SAndroid Build Coastguard Workerfunc joinAndPrefix(prefix string, values []string) string { 113*333d2b36SAndroid Build Coastguard Worker var sb strings.Builder 114*333d2b36SAndroid Build Coastguard Worker for _, v := range values { 115*333d2b36SAndroid Build Coastguard Worker sb.WriteString(prefix) 116*333d2b36SAndroid Build Coastguard Worker sb.WriteString(v) 117*333d2b36SAndroid Build Coastguard Worker } 118*333d2b36SAndroid Build Coastguard Worker return sb.String() 119*333d2b36SAndroid Build Coastguard Worker} 120*333d2b36SAndroid Build Coastguard Worker 121*333d2b36SAndroid Build Coastguard Workerfunc optionalVariable(prefix string, value string) string { 122*333d2b36SAndroid Build Coastguard Worker var sb strings.Builder 123*333d2b36SAndroid Build Coastguard Worker if value != "" { 124*333d2b36SAndroid Build Coastguard Worker sb.WriteString(prefix) 125*333d2b36SAndroid Build Coastguard Worker sb.WriteString(value) 126*333d2b36SAndroid Build Coastguard Worker } 127*333d2b36SAndroid Build Coastguard Worker return sb.String() 128*333d2b36SAndroid Build Coastguard Worker} 129*333d2b36SAndroid Build Coastguard Worker 130*333d2b36SAndroid Build Coastguard Worker// Assemble the actual filename. 131*333d2b36SAndroid Build Coastguard Worker// If `rcName` is not empty, then insert "-{rcName}" into the path before the 132*333d2b36SAndroid Build Coastguard Worker// file extension. 133*333d2b36SAndroid Build Coastguard Workerfunc assembleFileName(rcName, path string) string { 134*333d2b36SAndroid Build Coastguard Worker if rcName == "" { 135*333d2b36SAndroid Build Coastguard Worker return path 136*333d2b36SAndroid Build Coastguard Worker } 137*333d2b36SAndroid Build Coastguard Worker dir, file := filepath.Split(path) 138*333d2b36SAndroid Build Coastguard Worker rcName = "-" + rcName 139*333d2b36SAndroid Build Coastguard Worker ext := filepath.Ext(file) 140*333d2b36SAndroid Build Coastguard Worker base := file[:len(file)-len(ext)] 141*333d2b36SAndroid Build Coastguard Worker return dir + base + rcName + ext 142*333d2b36SAndroid Build Coastguard Worker} 143*333d2b36SAndroid Build Coastguard Worker 144*333d2b36SAndroid Build Coastguard Workerfunc (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 145*333d2b36SAndroid Build Coastguard Worker // Determine which release configs we are processing. 146*333d2b36SAndroid Build Coastguard Worker // 147*333d2b36SAndroid Build Coastguard Worker // We always process the current release config (empty string). 148*333d2b36SAndroid Build Coastguard Worker // We may have been told to also create artifacts for some others. 149*333d2b36SAndroid Build Coastguard Worker configs := append([]string{""}, ctx.Config().ReleaseAconfigExtraReleaseConfigs()...) 150*333d2b36SAndroid Build Coastguard Worker slices.Sort(configs) 151*333d2b36SAndroid Build Coastguard Worker 152*333d2b36SAndroid Build Coastguard Worker values := make(map[string][]string) 153*333d2b36SAndroid Build Coastguard Worker valuesFiles := make(map[string][]android.Path, 0) 154*333d2b36SAndroid Build Coastguard Worker providerData := android.AconfigReleaseDeclarationsProviderData{} 155*333d2b36SAndroid Build Coastguard Worker ctx.VisitDirectDeps(func(dep android.Module) { 156*333d2b36SAndroid Build Coastguard Worker if depData, ok := android.OtherModuleProvider(ctx, dep, valueSetProviderKey); ok { 157*333d2b36SAndroid Build Coastguard Worker depTag := ctx.OtherModuleDependencyTag(dep) 158*333d2b36SAndroid Build Coastguard Worker for _, config := range configs { 159*333d2b36SAndroid Build Coastguard Worker tag := implicitValuesTagType{ReleaseConfig: config} 160*333d2b36SAndroid Build Coastguard Worker if depTag == tag { 161*333d2b36SAndroid Build Coastguard Worker paths, ok := depData.AvailablePackages[module.properties.Package] 162*333d2b36SAndroid Build Coastguard Worker if ok { 163*333d2b36SAndroid Build Coastguard Worker valuesFiles[config] = append(valuesFiles[config], paths...) 164*333d2b36SAndroid Build Coastguard Worker for _, path := range paths { 165*333d2b36SAndroid Build Coastguard Worker values[config] = append(values[config], path.String()) 166*333d2b36SAndroid Build Coastguard Worker } 167*333d2b36SAndroid Build Coastguard Worker } 168*333d2b36SAndroid Build Coastguard Worker } 169*333d2b36SAndroid Build Coastguard Worker } 170*333d2b36SAndroid Build Coastguard Worker } 171*333d2b36SAndroid Build Coastguard Worker }) 172*333d2b36SAndroid Build Coastguard Worker for _, config := range configs { 173*333d2b36SAndroid Build Coastguard Worker module.properties.ReleaseConfigValues = append(module.properties.ReleaseConfigValues, AconfigReleaseConfigValue{ 174*333d2b36SAndroid Build Coastguard Worker ReleaseConfig: config, 175*333d2b36SAndroid Build Coastguard Worker Values: values[config], 176*333d2b36SAndroid Build Coastguard Worker }) 177*333d2b36SAndroid Build Coastguard Worker 178*333d2b36SAndroid Build Coastguard Worker // Intermediate format 179*333d2b36SAndroid Build Coastguard Worker declarationFiles := android.PathsForModuleSrc(ctx, module.properties.Srcs) 180*333d2b36SAndroid Build Coastguard Worker intermediateCacheFilePath := android.PathForModuleOut(ctx, assembleFileName(config, "intermediate.pb")) 181*333d2b36SAndroid Build Coastguard Worker var defaultPermission string 182*333d2b36SAndroid Build Coastguard Worker defaultPermission = ctx.Config().ReleaseAconfigFlagDefaultPermission() 183*333d2b36SAndroid Build Coastguard Worker if config != "" { 184*333d2b36SAndroid Build Coastguard Worker if confPerm, ok := ctx.Config().GetBuildFlag("RELEASE_ACONFIG_FLAG_DEFAULT_PERMISSION_" + config); ok { 185*333d2b36SAndroid Build Coastguard Worker defaultPermission = confPerm 186*333d2b36SAndroid Build Coastguard Worker } 187*333d2b36SAndroid Build Coastguard Worker } 188*333d2b36SAndroid Build Coastguard Worker var allowReadWrite bool 189*333d2b36SAndroid Build Coastguard Worker if requireAllReadOnly, ok := ctx.Config().GetBuildFlag("RELEASE_ACONFIG_REQUIRE_ALL_READ_ONLY"); ok { 190*333d2b36SAndroid Build Coastguard Worker // The build flag (RELEASE_ACONFIG_REQUIRE_ALL_READ_ONLY) is the negation of the aconfig flag 191*333d2b36SAndroid Build Coastguard Worker // (allow-read-write) for historical reasons. 192*333d2b36SAndroid Build Coastguard Worker // Bool build flags are always "" for false, and generally "true" for true. 193*333d2b36SAndroid Build Coastguard Worker allowReadWrite = requireAllReadOnly == "" 194*333d2b36SAndroid Build Coastguard Worker } 195*333d2b36SAndroid Build Coastguard Worker inputFiles := make([]android.Path, len(declarationFiles)) 196*333d2b36SAndroid Build Coastguard Worker copy(inputFiles, declarationFiles) 197*333d2b36SAndroid Build Coastguard Worker inputFiles = append(inputFiles, valuesFiles[config]...) 198*333d2b36SAndroid Build Coastguard Worker args := map[string]string{ 199*333d2b36SAndroid Build Coastguard Worker "release_version": ctx.Config().ReleaseVersion(), 200*333d2b36SAndroid Build Coastguard Worker "package": module.properties.Package, 201*333d2b36SAndroid Build Coastguard Worker "declarations": android.JoinPathsWithPrefix(declarationFiles, "--declarations "), 202*333d2b36SAndroid Build Coastguard Worker "values": joinAndPrefix(" --values ", values[config]), 203*333d2b36SAndroid Build Coastguard Worker "default-permission": optionalVariable(" --default-permission ", defaultPermission), 204*333d2b36SAndroid Build Coastguard Worker "allow-read-write": optionalVariable(" --allow-read-write ", strconv.FormatBool(allowReadWrite)), 205*333d2b36SAndroid Build Coastguard Worker } 206*333d2b36SAndroid Build Coastguard Worker if len(module.properties.Container) > 0 { 207*333d2b36SAndroid Build Coastguard Worker args["container"] = "--container " + module.properties.Container 208*333d2b36SAndroid Build Coastguard Worker } 209*333d2b36SAndroid Build Coastguard Worker ctx.Build(pctx, android.BuildParams{ 210*333d2b36SAndroid Build Coastguard Worker Rule: aconfigRule, 211*333d2b36SAndroid Build Coastguard Worker Output: intermediateCacheFilePath, 212*333d2b36SAndroid Build Coastguard Worker Inputs: inputFiles, 213*333d2b36SAndroid Build Coastguard Worker Description: "aconfig_declarations", 214*333d2b36SAndroid Build Coastguard Worker Args: args, 215*333d2b36SAndroid Build Coastguard Worker }) 216*333d2b36SAndroid Build Coastguard Worker 217*333d2b36SAndroid Build Coastguard Worker intermediateDumpFilePath := android.PathForModuleOut(ctx, assembleFileName(config, "intermediate.txt")) 218*333d2b36SAndroid Build Coastguard Worker ctx.Build(pctx, android.BuildParams{ 219*333d2b36SAndroid Build Coastguard Worker Rule: aconfigTextRule, 220*333d2b36SAndroid Build Coastguard Worker Output: intermediateDumpFilePath, 221*333d2b36SAndroid Build Coastguard Worker Inputs: android.Paths{intermediateCacheFilePath}, 222*333d2b36SAndroid Build Coastguard Worker Description: "aconfig_text", 223*333d2b36SAndroid Build Coastguard Worker }) 224*333d2b36SAndroid Build Coastguard Worker 225*333d2b36SAndroid Build Coastguard Worker providerData[config] = android.AconfigDeclarationsProviderData{ 226*333d2b36SAndroid Build Coastguard Worker Package: module.properties.Package, 227*333d2b36SAndroid Build Coastguard Worker Container: module.properties.Container, 228*333d2b36SAndroid Build Coastguard Worker Exportable: module.properties.Exportable, 229*333d2b36SAndroid Build Coastguard Worker IntermediateCacheOutputPath: intermediateCacheFilePath, 230*333d2b36SAndroid Build Coastguard Worker IntermediateDumpOutputPath: intermediateDumpFilePath, 231*333d2b36SAndroid Build Coastguard Worker } 232*333d2b36SAndroid Build Coastguard Worker } 233*333d2b36SAndroid Build Coastguard Worker android.SetProvider(ctx, android.AconfigDeclarationsProviderKey, providerData[""]) 234*333d2b36SAndroid Build Coastguard Worker android.SetProvider(ctx, android.AconfigReleaseDeclarationsProviderKey, providerData) 235*333d2b36SAndroid Build Coastguard Worker} 236*333d2b36SAndroid Build Coastguard Worker 237*333d2b36SAndroid Build Coastguard Workervar _ blueprint.Incremental = &DeclarationsModule{} 238