• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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