• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2017 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 hidl
16
17import (
18	"fmt"
19	"sort"
20	"strings"
21	"sync"
22
23	"github.com/google/blueprint"
24	"github.com/google/blueprint/proptools"
25
26	"android/soong/android"
27	"android/soong/cc"
28	"android/soong/genrule"
29	"android/soong/java"
30)
31
32var (
33	hidlInterfaceSuffix       = "_interface"
34	hidlMetadataSingletonName = "hidl_metadata_json"
35
36	pctx = android.NewPackageContext("android/hidl")
37
38	hidl             = pctx.HostBinToolVariable("hidl", "hidl-gen")
39	vtsc             = pctx.HostBinToolVariable("vtsc", "vtsc")
40	hidlLint         = pctx.HostBinToolVariable("lint", "hidl-lint")
41	soong_zip        = pctx.HostBinToolVariable("soong_zip", "soong_zip")
42	intermediatesDir = pctx.IntermediatesPathVariable("intermediatesDir", "")
43
44	hidlRule = pctx.StaticRule("hidlRule", blueprint.RuleParams{
45		Depfile:     "${depfile}",
46		Deps:        blueprint.DepsGCC,
47		Command:     "rm -rf ${genDir} && ${hidl} -R -p . -d ${depfile} -o ${genDir} -L ${language} ${roots} ${fqName}",
48		CommandDeps: []string{"${hidl}"},
49		Description: "HIDL ${language}: ${in} => ${out}",
50	}, "depfile", "fqName", "genDir", "language", "roots")
51
52	hidlSrcJarRule = pctx.StaticRule("hidlSrcJarRule", blueprint.RuleParams{
53		Depfile: "${depfile}",
54		Deps:    blueprint.DepsGCC,
55		Command: "rm -rf ${genDir} && " +
56			"${hidl} -R -p . -d ${depfile} -o ${genDir}/srcs -L ${language} ${roots} ${fqName} && " +
57			"${soong_zip} -o ${genDir}/srcs.srcjar -C ${genDir}/srcs -D ${genDir}/srcs",
58		CommandDeps: []string{"${hidl}", "${soong_zip}"},
59		Description: "HIDL ${language}: ${in} => srcs.srcjar",
60	}, "depfile", "fqName", "genDir", "language", "roots")
61
62	vtsRule = pctx.StaticRule("vtsRule", blueprint.RuleParams{
63		Command:     "rm -rf ${genDir} && ${vtsc} -m${mode} -t${type} ${inputDir}/${packagePath} ${genDir}/${packagePath}",
64		CommandDeps: []string{"${vtsc}"},
65		Description: "VTS ${mode} ${type}: ${in} => ${out}",
66	}, "mode", "type", "inputDir", "genDir", "packagePath")
67
68	lintRule = pctx.StaticRule("lintRule", blueprint.RuleParams{
69		Command:     "rm -f ${output} && touch ${output} && ${lint} -j -e -R -p . ${roots} ${fqName} > ${output}",
70		CommandDeps: []string{"${lint}"},
71		Description: "hidl-lint ${fqName}: ${out}",
72	}, "output", "roots", "fqName")
73
74	zipLintRule = pctx.StaticRule("zipLintRule", blueprint.RuleParams{
75		Command:     "rm -f ${output} && ${soong_zip} -o ${output} -C ${intermediatesDir} ${files}",
76		CommandDeps: []string{"${soong_zip}"},
77		Description: "Zipping hidl-lints into ${output}",
78	}, "output", "files")
79
80	inheritanceHierarchyRule = pctx.StaticRule("inheritanceHierarchyRule", blueprint.RuleParams{
81		Command:     "rm -f ${out} && ${hidl} -L inheritance-hierarchy ${roots} ${fqInterface} > ${out}",
82		CommandDeps: []string{"${hidl}"},
83		Description: "HIDL inheritance hierarchy: ${fqInterface} => ${out}",
84	}, "roots", "fqInterface")
85
86	joinJsonObjectsToArrayRule = pctx.StaticRule("joinJsonObjectsToArrayRule", blueprint.RuleParams{
87		Rspfile:        "$out.rsp",
88		RspfileContent: "$files",
89		Command: "rm -rf ${out} && " +
90			// Start the output array with an opening bracket.
91			"echo '[' >> ${out} && " +
92			// Append each input file and a comma to the output.
93			"for file in $$(cat ${out}.rsp); do " +
94			"cat $$file >> ${out}; echo ',' >> ${out}; " +
95			"done && " +
96			// Remove the last comma, replacing it with the closing bracket.
97			"sed -i '$$d' ${out} && echo ']' >> ${out}",
98		Description: "Joining JSON objects into array ${out}",
99	}, "files")
100)
101
102func init() {
103	android.RegisterModuleType("hidl_interface", hidlInterfaceFactory)
104	android.RegisterSingletonType("all_hidl_lints", allHidlLintsFactory)
105	android.RegisterMakeVarsProvider(pctx, makeVarsProvider)
106	android.RegisterModuleType("hidl_interfaces_metadata", hidlInterfacesMetadataSingletonFactory)
107	pctx.Import("android/soong/android")
108}
109
110func hidlInterfacesMetadataSingletonFactory() android.Module {
111	i := &hidlInterfacesMetadataSingleton{}
112	android.InitAndroidModule(i)
113	return i
114}
115
116type hidlInterfacesMetadataSingleton struct {
117	android.ModuleBase
118
119	inheritanceHierarchyPath android.OutputPath
120}
121
122var _ android.OutputFileProducer = (*hidlInterfacesMetadataSingleton)(nil)
123
124func (m *hidlInterfacesMetadataSingleton) GenerateAndroidBuildActions(ctx android.ModuleContext) {
125	if m.Name() != hidlMetadataSingletonName {
126		ctx.PropertyErrorf("name", "must be %s", hidlMetadataSingletonName)
127		return
128	}
129
130	var inheritanceHierarchyOutputs android.Paths
131	ctx.VisitDirectDeps(func(m android.Module) {
132		if !m.ExportedToMake() {
133			return
134		}
135		if t, ok := m.(*hidlGenRule); ok {
136			if t.properties.Language == "inheritance-hierarchy" {
137				inheritanceHierarchyOutputs = append(inheritanceHierarchyOutputs, t.genOutputs.Paths()...)
138			}
139		}
140	})
141
142	m.inheritanceHierarchyPath = android.PathForIntermediates(ctx, "hidl_inheritance_hierarchy.json")
143
144	ctx.Build(pctx, android.BuildParams{
145		Rule:   joinJsonObjectsToArrayRule,
146		Inputs: inheritanceHierarchyOutputs,
147		Output: m.inheritanceHierarchyPath,
148		Args: map[string]string{
149			"files": strings.Join(inheritanceHierarchyOutputs.Strings(), " "),
150		},
151	})
152}
153
154func (m *hidlInterfacesMetadataSingleton) OutputFiles(tag string) (android.Paths, error) {
155	if tag != "" {
156		return nil, fmt.Errorf("unsupported tag %q", tag)
157	}
158
159	return android.Paths{m.inheritanceHierarchyPath}, nil
160}
161
162func allHidlLintsFactory() android.Singleton {
163	return &allHidlLintsSingleton{}
164}
165
166type allHidlLintsSingleton struct {
167	outPath string
168}
169
170func (m *allHidlLintsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
171	var hidlLintOutputs android.Paths
172	ctx.VisitAllModules(func(m android.Module) {
173		if t, ok := m.(*hidlGenRule); ok {
174			if t.properties.Language == "lint" {
175				if len(t.genOutputs) == 1 {
176					hidlLintOutputs = append(hidlLintOutputs, t.genOutputs[0])
177				} else {
178					panic("-hidl-lint target was not configured correctly")
179				}
180			}
181		}
182	})
183
184	outPath := android.PathForIntermediates(ctx, "hidl-lint.zip")
185	m.outPath = outPath.String()
186
187	ctx.Build(pctx, android.BuildParams{
188		Rule:   zipLintRule,
189		Inputs: hidlLintOutputs,
190		Output: outPath,
191		Args: map[string]string{
192			"output": outPath.String(),
193			"files":  strings.Join(wrap("-f ", hidlLintOutputs.Strings(), ""), " "),
194		},
195	})
196}
197
198func (m *allHidlLintsSingleton) MakeVars(ctx android.MakeVarsContext) {
199	ctx.Strict("ALL_HIDL_LINTS_ZIP", m.outPath)
200}
201
202type hidlGenProperties struct {
203	Language       string
204	FqName         string
205	Root           string
206	Interfaces     []string
207	Inputs         []string
208	Outputs        []string
209	Apex_available []string
210}
211
212type hidlGenRule struct {
213	android.ModuleBase
214
215	properties hidlGenProperties
216
217	genOutputDir android.Path
218	genInputs    android.Paths
219	genOutputs   android.WritablePaths
220}
221
222var _ android.SourceFileProducer = (*hidlGenRule)(nil)
223var _ genrule.SourceFileGenerator = (*hidlGenRule)(nil)
224
225func (g *hidlGenRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
226	g.genOutputDir = android.PathForModuleGen(ctx)
227
228	for _, input := range g.properties.Inputs {
229		g.genInputs = append(g.genInputs, android.PathForModuleSrc(ctx, input))
230	}
231
232	var interfaces []string
233	for _, src := range g.properties.Inputs {
234		if strings.HasSuffix(src, ".hal") && strings.HasPrefix(src, "I") {
235			interfaces = append(interfaces, strings.TrimSuffix(src, ".hal"))
236		}
237	}
238
239	switch g.properties.Language {
240	case "lint":
241		g.genOutputs = append(g.genOutputs, android.PathForModuleGen(ctx, "lint.json"))
242	case "inheritance-hierarchy":
243		for _, intf := range interfaces {
244			g.genOutputs = append(g.genOutputs, android.PathForModuleGen(ctx, intf+"_inheritance_hierarchy.json"))
245		}
246	default:
247		for _, output := range g.properties.Outputs {
248			g.genOutputs = append(g.genOutputs, android.PathForModuleGen(ctx, output))
249		}
250	}
251
252	if g.properties.Language == "vts" && isVtsSpecPackage(ctx.ModuleName()) {
253		vtsList := vtsList(ctx.AConfig())
254		vtsListMutex.Lock()
255		*vtsList = append(*vtsList, g.genOutputs.Paths()...)
256		vtsListMutex.Unlock()
257	}
258
259	var fullRootOptions []string
260	var currentPath android.OptionalPath
261	ctx.VisitDirectDeps(func(dep android.Module) {
262		switch t := dep.(type) {
263		case *hidlInterface:
264			fullRootOptions = append(fullRootOptions, t.properties.Full_root_option)
265		case *hidlPackageRoot:
266			if currentPath.Valid() {
267				panic(fmt.Sprintf("Expecting only one path, but found %v %v", currentPath, t.getCurrentPath()))
268			}
269
270			currentPath = t.getCurrentPath()
271		default:
272			panic(fmt.Sprintf("Unrecognized hidlGenProperties dependency: %T", t))
273		}
274	})
275
276	fullRootOptions = android.FirstUniqueStrings(fullRootOptions)
277
278	inputs := g.genInputs
279	if currentPath.Valid() {
280		inputs = append(inputs, currentPath.Path())
281	}
282
283	rule := hidlRule
284	if g.properties.Language == "java" {
285		rule = hidlSrcJarRule
286	}
287
288	if g.properties.Language == "lint" {
289		ctx.Build(pctx, android.BuildParams{
290			Rule:   lintRule,
291			Inputs: inputs,
292			Output: g.genOutputs[0],
293			Args: map[string]string{
294				"output": g.genOutputs[0].String(),
295				"fqName": g.properties.FqName,
296				"roots":  strings.Join(fullRootOptions, " "),
297			},
298		})
299
300		return
301	}
302
303	if g.properties.Language == "inheritance-hierarchy" {
304		for i, intf := range interfaces {
305			ctx.Build(pctx, android.BuildParams{
306				Rule:   inheritanceHierarchyRule,
307				Inputs: inputs,
308				Output: g.genOutputs[i],
309				Args: map[string]string{
310					"fqInterface": g.properties.FqName + "::" + intf,
311					"roots":       strings.Join(fullRootOptions, " "),
312				},
313			})
314		}
315
316		return
317	}
318
319	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
320		Rule:            rule,
321		Inputs:          inputs,
322		Output:          g.genOutputs[0],
323		ImplicitOutputs: g.genOutputs[1:],
324		Args: map[string]string{
325			"depfile":  g.genOutputs[0].String() + ".d",
326			"genDir":   g.genOutputDir.String(),
327			"fqName":   g.properties.FqName,
328			"language": g.properties.Language,
329			"roots":    strings.Join(fullRootOptions, " "),
330		},
331	})
332}
333
334func (g *hidlGenRule) GeneratedSourceFiles() android.Paths {
335	return g.genOutputs.Paths()
336}
337
338func (g *hidlGenRule) Srcs() android.Paths {
339	return g.genOutputs.Paths()
340}
341
342func (g *hidlGenRule) GeneratedDeps() android.Paths {
343	return g.genOutputs.Paths()
344}
345
346func (g *hidlGenRule) GeneratedHeaderDirs() android.Paths {
347	return android.Paths{g.genOutputDir}
348}
349
350func (g *hidlGenRule) DepsMutator(ctx android.BottomUpMutatorContext) {
351	ctx.AddDependency(ctx.Module(), nil, g.properties.FqName+hidlInterfaceSuffix)
352	ctx.AddDependency(ctx.Module(), nil, wrap("", g.properties.Interfaces, hidlInterfaceSuffix)...)
353	ctx.AddDependency(ctx.Module(), nil, g.properties.Root)
354
355	ctx.AddReverseDependency(ctx.Module(), nil, hidlMetadataSingletonName)
356}
357
358func hidlGenFactory() android.Module {
359	g := &hidlGenRule{}
360	g.AddProperties(&g.properties)
361	android.InitAndroidModule(g)
362	return g
363}
364
365type vtscProperties struct {
366	Mode        string
367	Type        string
368	SpecName    string // e.g. foo-vts.spec
369	Outputs     []string
370	PackagePath string // e.g. android/hardware/foo/1.0/
371}
372
373type vtscRule struct {
374	android.ModuleBase
375
376	properties vtscProperties
377
378	genOutputDir android.Path
379	genInputDir  android.Path
380	genInputs    android.Paths
381	genOutputs   android.WritablePaths
382}
383
384var _ android.SourceFileProducer = (*vtscRule)(nil)
385var _ genrule.SourceFileGenerator = (*vtscRule)(nil)
386
387func (g *vtscRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
388	g.genOutputDir = android.PathForModuleGen(ctx)
389
390	ctx.VisitDirectDeps(func(dep android.Module) {
391		if specs, ok := dep.(*hidlGenRule); ok {
392			g.genInputDir = specs.genOutputDir
393			g.genInputs = specs.genOutputs.Paths()
394		}
395	})
396
397	for _, output := range g.properties.Outputs {
398		g.genOutputs = append(g.genOutputs, android.PathForModuleGen(ctx, output))
399	}
400
401	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
402		Rule:    vtsRule,
403		Inputs:  g.genInputs,
404		Outputs: g.genOutputs,
405		Args: map[string]string{
406			"mode":        g.properties.Mode,
407			"type":        g.properties.Type,
408			"inputDir":    g.genInputDir.String(),
409			"genDir":      g.genOutputDir.String(),
410			"packagePath": g.properties.PackagePath,
411		},
412	})
413}
414
415func (g *vtscRule) GeneratedSourceFiles() android.Paths {
416	return g.genOutputs.Paths()
417}
418
419func (g *vtscRule) Srcs() android.Paths {
420	return g.genOutputs.Paths()
421}
422
423func (g *vtscRule) GeneratedDeps() android.Paths {
424	return g.genOutputs.Paths()
425}
426
427func (g *vtscRule) GeneratedHeaderDirs() android.Paths {
428	return android.Paths{g.genOutputDir}
429}
430
431func (g *vtscRule) DepsMutator(ctx android.BottomUpMutatorContext) {
432	ctx.AddDependency(ctx.Module(), nil, g.properties.SpecName)
433}
434
435func vtscFactory() android.Module {
436	g := &vtscRule{}
437	g.AddProperties(&g.properties)
438	android.InitAndroidModule(g)
439	return g
440}
441
442type hidlInterfaceProperties struct {
443	// Vndk properties for interface library only.
444	cc.VndkProperties
445
446	// List of .hal files which compose this interface.
447	Srcs []string
448
449	// List of hal interface packages that this library depends on.
450	Interfaces []string
451
452	// Package root for this package, must be a prefix of name
453	Root string
454
455	// Unused/deprecated: List of non-TypeDef types declared in types.hal.
456	Types []string
457
458	// Whether to generate the Java library stubs.
459	// Default: true
460	Gen_java *bool
461
462	// Whether to generate a Java library containing constants
463	// expressed by @export annotations in the hal files.
464	Gen_java_constants bool
465
466	// Whether to generate VTS-related testing libraries.
467	Gen_vts *bool
468
469	// example: -randroid.hardware:hardware/interfaces
470	Full_root_option string `blueprint:"mutated"`
471
472	// Whether this interface library should be installed on product partition.
473	// TODO(b/150902910): remove, since this should be an inherited property.
474	Product_specific *bool
475
476	// List of APEX modules this interface can be used in.
477	//
478	// WARNING: HIDL is not fully supported in APEX since VINTF currently doesn't
479	// read files from APEXes (b/130058564).
480	//
481	// "//apex_available:anyapex" is a pseudo APEX name that matches to any APEX.
482	// "//apex_available:platform" refers to non-APEX partitions like "system.img"
483	//
484	// Note, this only applies to C++ libs, Java libs, and Java constant libs. It
485	// does  not apply to VTS targets/adapter targets/fuzzers since these components
486	// should not be shipped on device.
487	Apex_available []string
488}
489
490type hidlInterface struct {
491	android.ModuleBase
492
493	properties hidlInterfaceProperties
494}
495
496func processSources(mctx android.LoadHookContext, srcs []string) ([]string, []string, bool) {
497	var interfaces []string
498	var types []string // hidl-gen only supports types.hal, but don't assume that here
499
500	hasError := false
501
502	for _, v := range srcs {
503		if !strings.HasSuffix(v, ".hal") {
504			mctx.PropertyErrorf("srcs", "Source must be a .hal file: "+v)
505			hasError = true
506			continue
507		}
508
509		name := strings.TrimSuffix(v, ".hal")
510
511		if strings.HasPrefix(name, "I") {
512			baseName := strings.TrimPrefix(name, "I")
513			interfaces = append(interfaces, baseName)
514		} else {
515			types = append(types, name)
516		}
517	}
518
519	return interfaces, types, !hasError
520}
521
522func processDependencies(mctx android.LoadHookContext, interfaces []string) ([]string, []string, bool) {
523	var dependencies []string
524	var javaDependencies []string
525
526	hasError := false
527
528	for _, v := range interfaces {
529		name, err := parseFqName(v)
530		if err != nil {
531			mctx.PropertyErrorf("interfaces", err.Error())
532			hasError = true
533			continue
534		}
535		dependencies = append(dependencies, name.string())
536		javaDependencies = append(javaDependencies, name.javaName())
537	}
538
539	return dependencies, javaDependencies, !hasError
540}
541
542func removeCoreDependencies(mctx android.LoadHookContext, dependencies []string) []string {
543	var ret []string
544
545	for _, i := range dependencies {
546		if !isCorePackage(i) {
547			ret = append(ret, i)
548		}
549	}
550
551	return ret
552}
553
554func hidlInterfaceMutator(mctx android.LoadHookContext, i *hidlInterface) {
555	name, err := parseFqName(i.ModuleBase.Name())
556	if err != nil {
557		mctx.PropertyErrorf("name", err.Error())
558	}
559
560	if !name.inPackage(i.properties.Root) {
561		mctx.PropertyErrorf("root", i.properties.Root+" must be a prefix of  "+name.string()+".")
562	}
563	if lookupPackageRoot(i.properties.Root) == nil {
564		mctx.PropertyErrorf("interfaces", `Cannot find package root specification for package `+
565			`root '%s' needed for module '%s'. Either this is a mispelling of the package `+
566			`root, or a new hidl_package_root module needs to be added. For example, you can `+
567			`fix this error by adding the following to <some path>/Android.bp:
568
569hidl_package_root {
570name: "%s",
571// if you want to require <some path>/current.txt for interface versioning
572use_current: true,
573}
574
575This corresponds to the "-r%s:<some path>" option that would be passed into hidl-gen.`,
576			i.properties.Root, name, i.properties.Root, i.properties.Root)
577	}
578
579	interfaces, types, _ := processSources(mctx, i.properties.Srcs)
580
581	if len(interfaces) == 0 && len(types) == 0 {
582		mctx.PropertyErrorf("srcs", "No sources provided.")
583	}
584
585	dependencies, javaDependencies, _ := processDependencies(mctx, i.properties.Interfaces)
586	cppDependencies := removeCoreDependencies(mctx, dependencies)
587
588	if mctx.Failed() {
589		return
590	}
591
592	shouldGenerateLibrary := !isCorePackage(name.string())
593	// explicitly true if not specified to give early warning to devs
594	shouldGenerateJava := proptools.BoolDefault(i.properties.Gen_java, true)
595	shouldGenerateJavaConstants := i.properties.Gen_java_constants
596	shouldGenerateVts := shouldGenerateLibrary && proptools.BoolDefault(i.properties.Gen_vts, true)
597
598	// TODO(b/150902910): re-enable VTS builds for product things
599	shouldGenerateVts = shouldGenerateVts && !proptools.Bool(i.properties.Product_specific)
600
601	var libraryIfExists []string
602	if shouldGenerateLibrary {
603		libraryIfExists = []string{name.string()}
604	}
605
606	// TODO(b/69002743): remove filegroups
607	mctx.CreateModule(android.FileGroupFactory, &fileGroupProperties{
608		Name: proptools.StringPtr(name.fileGroupName()),
609		Srcs: i.properties.Srcs,
610	})
611
612	mctx.CreateModule(hidlGenFactory, &nameProperties{
613		Name: proptools.StringPtr(name.sourcesName()),
614	}, &hidlGenProperties{
615		Language:   "c++-sources",
616		FqName:     name.string(),
617		Root:       i.properties.Root,
618		Interfaces: i.properties.Interfaces,
619		Inputs:     i.properties.Srcs,
620		Outputs:    concat(wrap(name.dir(), interfaces, "All.cpp"), wrap(name.dir(), types, ".cpp")),
621	})
622	mctx.CreateModule(hidlGenFactory, &nameProperties{
623		Name: proptools.StringPtr(name.headersName()),
624	}, &hidlGenProperties{
625		Language:   "c++-headers",
626		FqName:     name.string(),
627		Root:       i.properties.Root,
628		Interfaces: i.properties.Interfaces,
629		Inputs:     i.properties.Srcs,
630		Outputs: concat(wrap(name.dir()+"I", interfaces, ".h"),
631			wrap(name.dir()+"Bs", interfaces, ".h"),
632			wrap(name.dir()+"BnHw", interfaces, ".h"),
633			wrap(name.dir()+"BpHw", interfaces, ".h"),
634			wrap(name.dir()+"IHw", interfaces, ".h"),
635			wrap(name.dir(), types, ".h"),
636			wrap(name.dir()+"hw", types, ".h")),
637	})
638
639	if shouldGenerateLibrary {
640		mctx.CreateModule(cc.LibraryFactory, &ccProperties{
641			Name:               proptools.StringPtr(name.string()),
642			Host_supported:     proptools.BoolPtr(true),
643			Recovery_available: proptools.BoolPtr(true),
644			Vendor_available:   proptools.BoolPtr(true),
645			Double_loadable:    proptools.BoolPtr(isDoubleLoadable(name.string())),
646			Defaults:           []string{"hidl-module-defaults"},
647			Generated_sources:  []string{name.sourcesName()},
648			Generated_headers:  []string{name.headersName()},
649			Shared_libs: concat(cppDependencies, []string{
650				"libhidlbase",
651				"liblog",
652				"libutils",
653				"libcutils",
654			}),
655			Export_shared_lib_headers: concat(cppDependencies, []string{
656				"libhidlbase",
657				"libutils",
658			}),
659			Export_generated_headers: []string{name.headersName()},
660			Apex_available:           i.properties.Apex_available,
661			Min_sdk_version:          getMinSdkVersion(name.string()),
662		}, &i.properties.VndkProperties)
663	}
664
665	if shouldGenerateJava {
666		mctx.CreateModule(hidlGenFactory, &nameProperties{
667			Name: proptools.StringPtr(name.javaSourcesName()),
668		}, &hidlGenProperties{
669			Language:   "java",
670			FqName:     name.string(),
671			Root:       i.properties.Root,
672			Interfaces: i.properties.Interfaces,
673			Inputs:     i.properties.Srcs,
674			Outputs:    []string{"srcs.srcjar"},
675		})
676
677		commonJavaProperties := javaProperties{
678			Defaults:    []string{"hidl-java-module-defaults"},
679			Installable: proptools.BoolPtr(true),
680			Srcs:        []string{":" + name.javaSourcesName()},
681
682			// This should ideally be system_current, but android.hidl.base-V1.0-java is used
683			// to build framework, which is used to build system_current.  Use core_current
684			// plus hwbinder.stubs, which together form a subset of system_current that does
685			// not depend on framework.
686			Sdk_version:    proptools.StringPtr("core_current"),
687			Libs:           []string{"hwbinder.stubs"},
688			Apex_available: i.properties.Apex_available,
689		}
690
691		mctx.CreateModule(java.LibraryFactory, &javaProperties{
692			Name:        proptools.StringPtr(name.javaName()),
693			Static_libs: javaDependencies,
694		}, &commonJavaProperties)
695		mctx.CreateModule(java.LibraryFactory, &javaProperties{
696			Name: proptools.StringPtr(name.javaSharedName()),
697			Libs: javaDependencies,
698		}, &commonJavaProperties)
699	}
700
701	if shouldGenerateJavaConstants {
702		mctx.CreateModule(hidlGenFactory, &nameProperties{
703			Name: proptools.StringPtr(name.javaConstantsSourcesName()),
704		}, &hidlGenProperties{
705			Language:   "java-constants",
706			FqName:     name.string(),
707			Root:       i.properties.Root,
708			Interfaces: i.properties.Interfaces,
709			Inputs:     i.properties.Srcs,
710			Outputs:    []string{name.sanitizedDir() + "Constants.java"},
711		})
712		mctx.CreateModule(java.LibraryFactory, &javaProperties{
713			Name:           proptools.StringPtr(name.javaConstantsName()),
714			Defaults:       []string{"hidl-java-module-defaults"},
715			Sdk_version:    proptools.StringPtr("core_current"),
716			Srcs:           []string{":" + name.javaConstantsSourcesName()},
717			Apex_available: i.properties.Apex_available,
718		})
719	}
720
721	mctx.CreateModule(hidlGenFactory, &nameProperties{
722		Name: proptools.StringPtr(name.adapterHelperSourcesName()),
723	}, &hidlGenProperties{
724		Language:   "c++-adapter-sources",
725		FqName:     name.string(),
726		Root:       i.properties.Root,
727		Interfaces: i.properties.Interfaces,
728		Inputs:     i.properties.Srcs,
729		Outputs:    wrap(name.dir()+"A", concat(interfaces, types), ".cpp"),
730	})
731	mctx.CreateModule(hidlGenFactory, &nameProperties{
732		Name: proptools.StringPtr(name.adapterHelperHeadersName()),
733	}, &hidlGenProperties{
734		Language:   "c++-adapter-headers",
735		FqName:     name.string(),
736		Root:       i.properties.Root,
737		Interfaces: i.properties.Interfaces,
738		Inputs:     i.properties.Srcs,
739		Outputs:    wrap(name.dir()+"A", concat(interfaces, types), ".h"),
740	})
741
742	mctx.CreateModule(cc.LibraryFactory, &ccProperties{
743		Name:              proptools.StringPtr(name.adapterHelperName()),
744		Vendor_available:  proptools.BoolPtr(true),
745		Defaults:          []string{"hidl-module-defaults"},
746		Generated_sources: []string{name.adapterHelperSourcesName()},
747		Generated_headers: []string{name.adapterHelperHeadersName()},
748		Shared_libs: []string{
749			"libbase",
750			"libcutils",
751			"libhidlbase",
752			"liblog",
753			"libutils",
754		},
755		Static_libs: concat([]string{
756			"libhidladapter",
757		}, wrap("", dependencies, "-adapter-helper"), cppDependencies, libraryIfExists),
758		Export_shared_lib_headers: []string{
759			"libhidlbase",
760		},
761		Export_static_lib_headers: concat([]string{
762			"libhidladapter",
763		}, wrap("", dependencies, "-adapter-helper"), cppDependencies, libraryIfExists),
764		Export_generated_headers: []string{name.adapterHelperHeadersName()},
765		Group_static_libs:        proptools.BoolPtr(true),
766	})
767	mctx.CreateModule(hidlGenFactory, &nameProperties{
768		Name: proptools.StringPtr(name.adapterSourcesName()),
769	}, &hidlGenProperties{
770		Language:   "c++-adapter-main",
771		FqName:     name.string(),
772		Root:       i.properties.Root,
773		Interfaces: i.properties.Interfaces,
774		Inputs:     i.properties.Srcs,
775		Outputs:    []string{"main.cpp"},
776	})
777	mctx.CreateModule(cc.TestFactory, &ccProperties{
778		Name:              proptools.StringPtr(name.adapterName()),
779		Generated_sources: []string{name.adapterSourcesName()},
780		Shared_libs: []string{
781			"libbase",
782			"libcutils",
783			"libhidlbase",
784			"liblog",
785			"libutils",
786		},
787		Static_libs: concat([]string{
788			"libhidladapter",
789			name.adapterHelperName(),
790		}, wrap("", dependencies, "-adapter-helper"), cppDependencies, libraryIfExists),
791		Group_static_libs: proptools.BoolPtr(true),
792	})
793
794	if shouldGenerateVts {
795		vtsSpecs := concat(wrap(name.dir(), interfaces, ".vts"), wrap(name.dir(), types, ".vts"))
796
797		mctx.CreateModule(hidlGenFactory, &nameProperties{
798			Name: proptools.StringPtr(name.vtsSpecName()),
799		}, &hidlGenProperties{
800			Language:   "vts",
801			FqName:     name.string(),
802			Root:       i.properties.Root,
803			Interfaces: i.properties.Interfaces,
804			Inputs:     i.properties.Srcs,
805			Outputs:    vtsSpecs,
806		})
807
808		mctx.CreateModule(vtscFactory, &nameProperties{
809			Name: proptools.StringPtr(name.vtsDriverSourcesName()),
810		}, &vtscProperties{
811			Mode:        "DRIVER",
812			Type:        "SOURCE",
813			SpecName:    name.vtsSpecName(),
814			Outputs:     wrap("", vtsSpecs, ".cpp"),
815			PackagePath: name.dir(),
816		})
817		mctx.CreateModule(vtscFactory, &nameProperties{
818			Name: proptools.StringPtr(name.vtsDriverHeadersName()),
819		}, &vtscProperties{
820			Mode:        "DRIVER",
821			Type:        "HEADER",
822			SpecName:    name.vtsSpecName(),
823			Outputs:     wrap("", vtsSpecs, ".h"),
824			PackagePath: name.dir(),
825		})
826		mctx.CreateModule(cc.LibraryFactory, &ccProperties{
827			Name:                      proptools.StringPtr(name.vtsDriverName()),
828			Defaults:                  []string{"VtsHalDriverDefaults"},
829			Generated_sources:         []string{name.vtsDriverSourcesName()},
830			Generated_headers:         []string{name.vtsDriverHeadersName()},
831			Export_generated_headers:  []string{name.vtsDriverHeadersName()},
832			Shared_libs:               wrap("", cppDependencies, "-vts.driver"),
833			Export_shared_lib_headers: wrap("", cppDependencies, "-vts.driver"),
834			Static_libs:               concat(cppDependencies, libraryIfExists),
835
836			// TODO(b/126244142)
837			Cflags: []string{"-Wno-unused-variable"},
838		})
839
840		mctx.CreateModule(vtscFactory, &nameProperties{
841			Name: proptools.StringPtr(name.vtsProfilerSourcesName()),
842		}, &vtscProperties{
843			Mode:        "PROFILER",
844			Type:        "SOURCE",
845			SpecName:    name.vtsSpecName(),
846			Outputs:     wrap("", vtsSpecs, ".cpp"),
847			PackagePath: name.dir(),
848		})
849		mctx.CreateModule(vtscFactory, &nameProperties{
850			Name: proptools.StringPtr(name.vtsProfilerHeadersName()),
851		}, &vtscProperties{
852			Mode:        "PROFILER",
853			Type:        "HEADER",
854			SpecName:    name.vtsSpecName(),
855			Outputs:     wrap("", vtsSpecs, ".h"),
856			PackagePath: name.dir(),
857		})
858		mctx.CreateModule(cc.LibraryFactory, &ccProperties{
859			Name:                      proptools.StringPtr(name.vtsProfilerName()),
860			Defaults:                  []string{"VtsHalProfilerDefaults"},
861			Generated_sources:         []string{name.vtsProfilerSourcesName()},
862			Generated_headers:         []string{name.vtsProfilerHeadersName()},
863			Export_generated_headers:  []string{name.vtsProfilerHeadersName()},
864			Shared_libs:               wrap("", cppDependencies, "-vts.profiler"),
865			Export_shared_lib_headers: wrap("", cppDependencies, "-vts.profiler"),
866			Static_libs:               concat(cppDependencies, libraryIfExists),
867
868			// TODO(b/126244142)
869			Cflags: []string{"-Wno-unused-variable"},
870		})
871
872		specDependencies := append(cppDependencies, name.string())
873		mctx.CreateModule(cc.FuzzFactory, &ccProperties{
874			Name:        proptools.StringPtr(name.vtsFuzzerName()),
875			Defaults:    []string{"vts_proto_fuzzer_default"},
876			Shared_libs: []string{name.vtsDriverName()},
877			Cflags: []string{
878				"-DSTATIC_TARGET_FQ_NAME=" + name.string(),
879				"-DSTATIC_SPEC_DATA=" + strings.Join(specDependencies, ":"),
880			},
881		}, &fuzzProperties{
882			Data: wrap(":", specDependencies, "-vts.spec"),
883			Fuzz_config: &fuzzConfig{
884				Fuzz_on_haiku_device: proptools.BoolPtr(isFuzzerEnabled(name.vtsFuzzerName())),
885			},
886		})
887	}
888
889	mctx.CreateModule(hidlGenFactory, &nameProperties{
890		Name: proptools.StringPtr(name.lintName()),
891	}, &hidlGenProperties{
892		Language:   "lint",
893		FqName:     name.string(),
894		Root:       i.properties.Root,
895		Interfaces: i.properties.Interfaces,
896		Inputs:     i.properties.Srcs,
897	})
898
899	mctx.CreateModule(hidlGenFactory, &nameProperties{
900		Name: proptools.StringPtr(name.inheritanceHierarchyName()),
901	}, &hidlGenProperties{
902		Language:   "inheritance-hierarchy",
903		FqName:     name.string(),
904		Root:       i.properties.Root,
905		Interfaces: i.properties.Interfaces,
906		Inputs:     i.properties.Srcs,
907	})
908}
909
910func (h *hidlInterface) Name() string {
911	return h.ModuleBase.Name() + hidlInterfaceSuffix
912}
913func (h *hidlInterface) GenerateAndroidBuildActions(ctx android.ModuleContext) {
914	visited := false
915	ctx.VisitDirectDeps(func(dep android.Module) {
916		if visited {
917			panic("internal error, multiple dependencies found but only one added")
918		}
919		visited = true
920		h.properties.Full_root_option = dep.(*hidlPackageRoot).getFullPackageRoot()
921	})
922	if !visited {
923		panic("internal error, no dependencies found but dependency added")
924	}
925
926}
927func (h *hidlInterface) DepsMutator(ctx android.BottomUpMutatorContext) {
928	ctx.AddDependency(ctx.Module(), nil, h.properties.Root)
929}
930
931func hidlInterfaceFactory() android.Module {
932	i := &hidlInterface{}
933	i.AddProperties(&i.properties)
934	android.InitAndroidModule(i)
935	android.AddLoadHook(i, func(ctx android.LoadHookContext) { hidlInterfaceMutator(ctx, i) })
936
937	return i
938}
939
940var minSdkVersion = map[string]string{
941	"android.hardware.audio.common@5.0":         "30",
942	"android.hardware.bluetooth.a2dp@1.0":       "30",
943	"android.hardware.bluetooth.audio@2.0":      "30",
944	"android.hardware.bluetooth@1.0":            "30",
945	"android.hardware.bluetooth@1.1":            "30",
946	"android.hardware.cas.native@1.0":           "29",
947	"android.hardware.cas@1.0":                  "29",
948	"android.hardware.graphics.allocator@2.0":   "29",
949	"android.hardware.graphics.allocator@3.0":   "29",
950	"android.hardware.graphics.allocator@4.0":   "29",
951	"android.hardware.graphics.bufferqueue@1.0": "29",
952	"android.hardware.graphics.bufferqueue@2.0": "29",
953	"android.hardware.graphics.common@1.0":      "29",
954	"android.hardware.graphics.common@1.1":      "29",
955	"android.hardware.graphics.common@1.2":      "29",
956	"android.hardware.graphics.mapper@2.0":      "29",
957	"android.hardware.graphics.mapper@2.1":      "29",
958	"android.hardware.graphics.mapper@3.0":      "29",
959	"android.hardware.graphics.mapper@4.0":      "29",
960	"android.hardware.media.bufferpool@2.0":     "29",
961	"android.hardware.media.c2@1.0":             "29",
962	"android.hardware.media.c2@1.1":             "29",
963	"android.hardware.media.omx@1.0":            "29",
964	"android.hardware.media@1.0":                "29",
965	"android.hardware.neuralnetworks@1.0":       "30",
966	"android.hardware.neuralnetworks@1.1":       "30",
967	"android.hardware.neuralnetworks@1.2":       "30",
968	"android.hardware.neuralnetworks@1.3":       "30",
969	"android.hidl.allocator@1.0":                "29",
970	"android.hidl.memory.token@1.0":             "29",
971	"android.hidl.memory@1.0":                   "29",
972	"android.hidl.safe_union@1.0":               "29",
973	"android.hidl.token@1.0":                    "29",
974}
975
976func getMinSdkVersion(name string) *string {
977	if ver, ok := minSdkVersion[name]; ok {
978		return proptools.StringPtr(ver)
979	}
980	return nil
981}
982
983var doubleLoadablePackageNames = []string{
984	"android.frameworks.bufferhub@1.0",
985	"android.hardware.cas@1.0",
986	"android.hardware.cas.native@1.0",
987	"android.hardware.configstore@",
988	"android.hardware.drm@",
989	"android.hardware.graphics.allocator@",
990	"android.hardware.graphics.bufferqueue@",
991	"android.hardware.media@",
992	"android.hardware.media.bufferpool@",
993	"android.hardware.media.c2@",
994	"android.hardware.media.omx@",
995	"android.hardware.memtrack@1.0",
996	"android.hardware.neuralnetworks@",
997	"android.hidl.allocator@",
998	"android.hidl.token@",
999	"android.system.suspend@1.0",
1000}
1001
1002func isDoubleLoadable(name string) bool {
1003	for _, pkgname := range doubleLoadablePackageNames {
1004		if strings.HasPrefix(name, pkgname) {
1005			return true
1006		}
1007	}
1008	return false
1009}
1010
1011// packages in libhidlbase
1012var coreDependencyPackageNames = []string{
1013	"android.hidl.base@",
1014	"android.hidl.manager@",
1015}
1016
1017func isCorePackage(name string) bool {
1018	for _, pkgname := range coreDependencyPackageNames {
1019		if strings.HasPrefix(name, pkgname) {
1020			return true
1021		}
1022	}
1023	return false
1024}
1025
1026var fuzzerPackageNameBlacklist = []string{
1027	"android.hardware.keymaster@", // to avoid deleteAllKeys()
1028}
1029
1030func isFuzzerEnabled(name string) bool {
1031	for _, pkgname := range fuzzerPackageNameBlacklist {
1032		if strings.HasPrefix(name, pkgname) {
1033			return false
1034		}
1035	}
1036	return true
1037}
1038
1039// TODO(b/126383715): centralize this logic/support filtering in core VTS build
1040var coreVtsSpecs = []string{
1041	"android.frameworks.",
1042	"android.hardware.",
1043	"android.hidl.",
1044	"android.system.",
1045}
1046
1047func isVtsSpecPackage(name string) bool {
1048	for _, pkgname := range coreVtsSpecs {
1049		if strings.HasPrefix(name, pkgname) {
1050			return true
1051		}
1052	}
1053	return false
1054}
1055
1056var vtsListKey = android.NewOnceKey("vtsList")
1057
1058func vtsList(config android.Config) *android.Paths {
1059	return config.Once(vtsListKey, func() interface{} {
1060		return &android.Paths{}
1061	}).(*android.Paths)
1062}
1063
1064var vtsListMutex sync.Mutex
1065
1066func makeVarsProvider(ctx android.MakeVarsContext) {
1067	vtsList := vtsList(ctx.Config()).Strings()
1068	sort.Strings(vtsList)
1069
1070	ctx.Strict("VTS_SPEC_FILE_LIST", strings.Join(vtsList, " "))
1071}
1072