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