blob: b8f2a14118a1ae49b43b703791e3019ab2b8e88f [file] [log] [blame]
Yifan Hong0cd10dd2018-10-12 13:08:52 -07001// Copyright (C) 2018 The Android Open Source Project
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 vintf
16
17import (
18 "fmt"
19 "io"
20 "strings"
21
22 "github.com/google/blueprint"
23 "github.com/google/blueprint/proptools"
24
25 "android/soong/android"
26 "android/soong/kernel/configs"
Bill Yangb7995ac2024-09-05 09:22:09 +000027 "android/soong/selinux"
Yifan Hong0cd10dd2018-10-12 13:08:52 -070028)
29
30type dependencyTag struct {
31 blueprint.BaseDependencyTag
32 name string
33}
34
35var (
36 pctx = android.NewPackageContext("android/vintf")
37
38 assembleVintfRule = pctx.AndroidStaticRule("assemble_vintf", blueprint.RuleParams{
Bill Yangb7995ac2024-09-05 09:22:09 +000039 Command: `${assembleVintfEnv} ${assembleVintfCmd} -i ${inputs} -o ${out} ${extraArgs}`,
40 CommandDeps: []string{"${assembleVintfCmd}", "${AvbToolCmd}"},
Yifan Hong0cd10dd2018-10-12 13:08:52 -070041 Description: "assemble_vintf -i ${inputs}",
Bill Yangb7995ac2024-09-05 09:22:09 +000042 }, "inputs", "extraArgs", "assembleVintfEnv")
Yifan Hong0cd10dd2018-10-12 13:08:52 -070043
Yifan Hongfca5d952020-04-10 16:42:50 -070044 xmllintXsd = pctx.AndroidStaticRule("xmllint-xsd", blueprint.RuleParams{
Yifan Hong5a6c7b12021-02-24 17:58:17 -080045 Command: `$XmlLintCmd --quiet --schema $xsd $in > /dev/null && touch -a $out`,
Yifan Hongfca5d952020-04-10 16:42:50 -070046 CommandDeps: []string{"$XmlLintCmd"},
47 Restat: true,
48 }, "xsd")
49
50 kernelConfigTag = dependencyTag{name: "kernel-config"}
51 schemaTag = dependencyTag{name: "matrix-schema"}
52 schemaModuleName = "compatibility_matrix_schema"
Yifan Hong0cd10dd2018-10-12 13:08:52 -070053)
54
55const (
Bill Yangb7995ac2024-09-05 09:22:09 +000056 relpath = "vintf"
57 emptyManifest = "hardware/interfaces/compatibility_matrices/manifest.empty.xml"
58 compatibilityEmptyMatrix = "hardware/interfaces/compatibility_matrices/compatibility_matrix.empty.xml"
59 deviceFcmType = "device_fcm"
60 productFcmType = "product_fcm"
Yifan Hong0cd10dd2018-10-12 13:08:52 -070061)
62
63type vintfCompatibilityMatrixProperties struct {
64 // set the name of the output
65 Stem *string
66
67 // list of source compatibility matrix XML files
68 Srcs []string
69
70 // list of kernel_config modules to be combined to final output
71 Kernel_configs []string
Bill Yangb7995ac2024-09-05 09:22:09 +000072
73 // Type of the FCM type, the allowed type are device_fcm and product_fcm and it should only be used under hardware/interfaces/compatibility_matrices
74 Type *string
Yifan Hong0cd10dd2018-10-12 13:08:52 -070075}
76
77type vintfCompatibilityMatrixRule struct {
78 android.ModuleBase
79 properties vintfCompatibilityMatrixProperties
80
Yifan Hongfca5d952020-04-10 16:42:50 -070081 genFile android.WritablePath
82 additionalDependencies android.WritablePaths
Bill Yangb7995ac2024-09-05 09:22:09 +000083 phonyOnly bool
Yifan Hong0cd10dd2018-10-12 13:08:52 -070084}
85
86func init() {
87 pctx.HostBinToolVariable("assembleVintfCmd", "assemble_vintf")
Yifan Hongfca5d952020-04-10 16:42:50 -070088 pctx.HostBinToolVariable("XmlLintCmd", "xmllint")
Bill Yangb7995ac2024-09-05 09:22:09 +000089 pctx.HostBinToolVariable("AvbToolCmd", "avbtool")
Yifan Hong0cd10dd2018-10-12 13:08:52 -070090 android.RegisterModuleType("vintf_compatibility_matrix", vintfCompatibilityMatrixFactory)
91}
92
93func vintfCompatibilityMatrixFactory() android.Module {
94 g := &vintfCompatibilityMatrixRule{}
95 g.AddProperties(&g.properties)
96 android.InitAndroidArchModule(g, android.DeviceSupported, android.MultilibCommon)
97 return g
98}
99
100var _ android.AndroidMkDataProvider = (*vintfCompatibilityMatrixRule)(nil)
101
102func (g *vintfCompatibilityMatrixRule) DepsMutator(ctx android.BottomUpMutatorContext) {
103 android.ExtractSourcesDeps(ctx, g.properties.Srcs)
104 ctx.AddDependency(ctx.Module(), kernelConfigTag, g.properties.Kernel_configs...)
Yifan Hongfca5d952020-04-10 16:42:50 -0700105 ctx.AddDependency(ctx.Module(), schemaTag, schemaModuleName)
106}
107
108func (g *vintfCompatibilityMatrixRule) timestampFilePath(ctx android.ModuleContext, path android.Path) android.WritablePath {
109 return android.GenPathWithExt(ctx, "vintf-xmllint", path, "ts")
110}
111
112func (g *vintfCompatibilityMatrixRule) generateValidateBuildAction(ctx android.ModuleContext, path android.Path, schema android.Path) {
113 timestamp := g.timestampFilePath(ctx, path)
114 ctx.Build(pctx, android.BuildParams{
115 Rule: xmllintXsd,
116 Description: "xmllint-xsd",
117 Input: path,
118 Output: timestamp,
119 Implicit: schema,
120 Args: map[string]string{
121 "xsd": schema.String(),
122 },
123 })
124 g.additionalDependencies = append(g.additionalDependencies, timestamp)
125}
126
127func (g *vintfCompatibilityMatrixRule) getSchema(ctx android.ModuleContext) android.OptionalPath {
128 schemaModule := ctx.GetDirectDepWithTag(schemaModuleName, schemaTag)
129 sfp, ok := schemaModule.(android.SourceFileProducer)
130 if !ok {
131 ctx.ModuleErrorf("Implicit dependency %q has no srcs", ctx.OtherModuleName(schemaModule))
132 return android.OptionalPath{}
133 }
134
135 schemaSrcs := sfp.Srcs()
136 if len(schemaSrcs) != 1 {
137 ctx.PropertyErrorf(`srcs of implicit dependency %q has length %d != 1`, ctx.OtherModuleName(schemaModule), len(schemaSrcs))
138 return android.OptionalPath{}
139 }
140 return android.OptionalPathForPath(schemaSrcs[0])
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700141}
142
143func (g *vintfCompatibilityMatrixRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Bill Yangb7995ac2024-09-05 09:22:09 +0000144 // Types attribute only allow `device_fcm` or `product_fcm` if set and only restricted it being used under
145 // `hardware/interfaces/compatibility_matrices` to prevent accidental external usages.
146 matrixType := proptools.String(g.properties.Type)
147 if matrixType != "" {
148 if matrixType != deviceFcmType && matrixType != productFcmType {
149 panic(fmt.Errorf("The attribute 'type' value must be either 'device_fcm' or 'product_fcm' if set!"))
150 }
151 if !strings.HasPrefix(android.PathForModuleSrc(ctx).String(), "hardware/interfaces/compatibility_matrices") {
152 panic(fmt.Errorf("Attribute type can only be set for module under `hardware/interfaces/compatibility_matrices`!"))
153 }
154 if (len(g.properties.Srcs) + len(g.properties.Kernel_configs)) > 0 {
155 panic(fmt.Errorf("Attribute 'type' and 'srcs' or 'kernel_configs' should not set simultaneously! To update inputs for this rule, edit vintf_compatibility_matrix.go directly."))
156 }
157 }
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700158
159 outputFilename := proptools.String(g.properties.Stem)
160 if outputFilename == "" {
161 outputFilename = g.Name()
162 }
163
Yifan Hongfca5d952020-04-10 16:42:50 -0700164 schema := g.getSchema(ctx)
165 if !schema.Valid() {
166 return
167 }
168
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700169 inputPaths := android.PathsForModuleSrc(ctx, g.properties.Srcs)
Yifan Hongfca5d952020-04-10 16:42:50 -0700170 for _, srcPath := range inputPaths {
171 g.generateValidateBuildAction(ctx, srcPath, schema.Path())
172 }
173
174 // No need to validate matrices from kernel configs because they are generated by
175 // assemble_vintf.
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700176 ctx.VisitDirectDepsWithTag(kernelConfigTag, func(m android.Module) {
177 if k, ok := m.(*configs.KernelConfigRule); ok {
178 inputPaths = append(inputPaths, k.OutputPath())
179 } else {
Steven Moreland3f40b2b2021-05-21 20:25:47 +0000180 ctx.PropertyErrorf("kernel_configs",
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700181 "module %q is not a kernel_config", ctx.OtherModuleName(m))
182 }
183 })
184
Bill Yangb7995ac2024-09-05 09:22:09 +0000185 // For product_compatibility_matrix.xml the source is from the product configuration
186 // DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE.
187 extraArgs := []string{}
188 if matrixType == productFcmType {
189 productMatrixs := android.PathsForSource(ctx, ctx.Config().DeviceProductCompatibilityMatrixFile())
190 if len(productMatrixs) > 0 {
191 inputPaths = append(inputPaths, productMatrixs...)
192 extraArgs = append(extraArgs, "-c", android.PathForSource(ctx, emptyManifest).String())
193 } else {
194 // For product_fcm, if DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE not set, treat it as a phony target without any output generated.
195 g.phonyOnly = true
196 return
197 }
198 }
199
200 // For framework_compatibility_matrix.device.xml the source may come from the product configuration
201 // DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE or use compatibilityEmptyMatrix if not set. We can't
202 // use a phony target because we still need to install framework_compatibility_matrix.device.xml to
203 // include sepolicy versions.
204 frameworkRuleImplicits := []android.Path{}
205
206 if matrixType == deviceFcmType {
207 frameworkMatrixs := android.PathsForSource(ctx, ctx.Config().DeviceFrameworkCompatibilityMatrixFile())
208 if len(frameworkMatrixs) > 0 {
209 inputPaths = append(inputPaths, frameworkMatrixs...)
210
211 // Generate BuildAction for generating the check manifest.
212 emptyManifestPath := android.PathForSource(ctx, emptyManifest)
213 genCheckManifest := android.PathForModuleGen(ctx, "manifest.check.xml")
214 checkManifestInputs := []android.Path{emptyManifestPath}
215 genCheckManifestEnvs := []string{
216 "BOARD_SEPOLICY_VERS=" + ctx.DeviceConfig().BoardSepolicyVers(),
217 "VINTF_IGNORE_TARGET_FCM_VERSION=true",
218 }
219
220 ctx.Build(pctx, android.BuildParams{
221 Rule: assembleVintfRule,
222 Description: "Framework Check Manifest",
223 Implicits: checkManifestInputs,
224 Output: genCheckManifest,
225 Args: map[string]string{
226 "inputs": android.PathForSource(ctx, emptyManifest).String(),
227 "extraArgs": "",
228 "assembleVintfEnv": strings.Join(genCheckManifestEnvs, " "),
229 },
230 })
231
232 frameworkRuleImplicits = append(frameworkRuleImplicits, genCheckManifest)
233 extraArgs = append(extraArgs, "-c", genCheckManifest.String())
234 } else {
235 inputPaths = append(inputPaths, android.PathForSource(ctx, compatibilityEmptyMatrix))
236 }
237 }
238
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700239 g.genFile = android.PathForModuleGen(ctx, outputFilename)
Bill Yangb7995ac2024-09-05 09:22:09 +0000240 frameworkRuleImplicits = append(frameworkRuleImplicits, inputPaths...)
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700241
242 ctx.Build(pctx, android.BuildParams{
243 Rule: assembleVintfRule,
244 Description: "Framework Compatibility Matrix",
Bill Yangb7995ac2024-09-05 09:22:09 +0000245 Implicits: frameworkRuleImplicits,
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700246 Output: g.genFile,
247 Args: map[string]string{
Bill Yangb7995ac2024-09-05 09:22:09 +0000248 "inputs": strings.Join(inputPaths.Strings(), ":"),
249 "extraArgs": strings.Join(extraArgs, " "),
250 "assembleVintfEnv": g.getAssembleVintfEnv(ctx),
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700251 },
252 })
Yifan Hongfca5d952020-04-10 16:42:50 -0700253 g.generateValidateBuildAction(ctx, g.genFile, schema.Path())
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700254
255 ctx.InstallFile(android.PathForModuleInstall(ctx, "etc", relpath), outputFilename, g.genFile)
256}
257
Bill Yangb7995ac2024-09-05 09:22:09 +0000258func (g *vintfCompatibilityMatrixRule) getAssembleVintfEnv(ctx android.ModuleContext) string {
259 if proptools.String(g.properties.Type) == deviceFcmType {
260 assembleVintfEnvs := []string{
261 // POLICYVERS defined in system/sepolicy/build/soong/policy.go
262 fmt.Sprintf("POLICYVERS=%d", selinux.PolicyVers),
263 fmt.Sprintf("PLATFORM_SEPOLICY_VERSION=%s", ctx.DeviceConfig().PlatformSepolicyVersion()),
264 fmt.Sprintf("PLATFORM_SEPOLICY_COMPAT_VERSIONS=\"%s\"", strings.Join(ctx.DeviceConfig().PlatformSepolicyCompatVersions(), " ")),
265 }
266
267 if ctx.Config().BoardAvbEnable() {
268 assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("FRAMEWORK_VBMETA_VERSION=\"$$(${AvbToolCmd} add_hashtree_footer --print_required_libavb_version %s)\"", strings.Join(ctx.Config().BoardAvbSystemAddHashtreeFooterArgs(), " ")))
269 } else {
270 assembleVintfEnvs = append(assembleVintfEnvs, "FRAMEWORK_VBMETA_VERSION=\"0.0\"")
271 }
272
273 return strings.Join(assembleVintfEnvs, " ")
274 }
275
276 return ""
277}
278
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700279func (g *vintfCompatibilityMatrixRule) AndroidMk() android.AndroidMkData {
Bill Yangb7995ac2024-09-05 09:22:09 +0000280 if g.phonyOnly {
281 return android.AndroidMkData{
282 Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
283 fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)", " # vintf.vintf_compatibility_matrix")
284 fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
285 fmt.Fprintln(w, "LOCAL_MODULE :=", name)
286 fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
287 },
288 }
289 }
290
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700291 return android.AndroidMkData{
292 Class: "ETC",
293 OutputFile: android.OptionalPathForPath(g.genFile),
294 Extra: []android.AndroidMkExtraFunc{
295 func(w io.Writer, outputFile android.Path) {
296 fmt.Fprintln(w, "LOCAL_MODULE_RELATIVE_PATH :=", relpath)
297 if proptools.String(g.properties.Stem) != "" {
298 fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", proptools.String(g.properties.Stem))
299 }
Yifan Hongfca5d952020-04-10 16:42:50 -0700300 for _, path := range g.additionalDependencies {
301 fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES +=", path.String())
302 }
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700303 },
304 },
305 }
306}