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	"sync"
19
20	"github.com/google/blueprint"
21	"github.com/google/blueprint/proptools"
22
23	"android/soong/android"
24)
25
26var (
27	currentTxtRule = pctx.StaticRule("currentTxtRule", blueprint.RuleParams{
28		Command:     "cp -f ${in} ${output}",
29		Description: "copy current.txt: ${in} => ${output}",
30	}, "output")
31)
32
33func init() {
34	android.RegisterModuleType("hidl_package_root", hidlPackageRootFactory)
35}
36
37type hidlPackageRoot struct {
38	android.ModuleBase
39
40	properties struct {
41		// Path to the package root from android build root. It is recommended not to set this and
42		// use the current path. This will be deprecated in the future.
43		Path *string
44
45		// True to require a current.txt API file here.
46		//
47		// When false, it uses the file only when it exists.
48		Use_current *bool
49
50		// True to require all things referenced by this package root to be frozen.
51		Require_frozen *bool
52	}
53
54	currentPath android.OptionalPath
55	genOutputs  android.Paths
56}
57
58var _ android.SourceFileProducer = (*hidlPackageRoot)(nil)
59
60func (r *hidlPackageRoot) getFullPackageRoot() string {
61	return "-r" + r.Name() + ":" + *r.properties.Path
62}
63
64func (r *hidlPackageRoot) getCurrentPath() android.OptionalPath {
65	return r.currentPath
66}
67
68func (r *hidlPackageRoot) requireFrozen() bool {
69	return proptools.BoolDefault(r.properties.Require_frozen, false)
70}
71
72func (r *hidlPackageRoot) generateCurrentFile(ctx android.ModuleContext) {
73	if !r.currentPath.Valid() {
74		return
75	}
76
77	output := android.PathForModuleGen(ctx, r.Name()+".txt")
78	r.genOutputs = append(r.genOutputs, output)
79
80	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
81		Rule:   currentTxtRule,
82		Input:  r.currentPath.Path(),
83		Output: output,
84		Args: map[string]string{
85			"output": output.String(),
86		},
87	})
88}
89
90func (r *hidlPackageRoot) Srcs() android.Paths {
91	return r.genOutputs
92}
93
94func (r *hidlPackageRoot) GenerateAndroidBuildActions(ctx android.ModuleContext) {
95	if r.properties.Path == nil {
96		r.properties.Path = proptools.StringPtr(ctx.ModuleDir())
97	}
98
99	if proptools.BoolDefault(r.properties.Use_current, false) {
100		if *r.properties.Path != ctx.ModuleDir() {
101			ctx.PropertyErrorf("path", "Cannot use unrelated path with use_current. "+
102				"Presumably this hidl_package_root should be at %s. Otherwise, current.txt "+
103				"could be located at %s, but use_current must be removed. path is by default "+
104				"the path of hidl_package_root.", *r.properties.Path, ctx.ModuleDir())
105			return
106		}
107
108		r.currentPath = android.OptionalPathForPath(android.PathForModuleSrc(ctx, "current.txt"))
109	} else {
110		r.currentPath = android.ExistentPathForSource(ctx, ctx.ModuleDir(), "current.txt")
111	}
112
113	r.generateCurrentFile(ctx)
114}
115
116func (r *hidlPackageRoot) DepsMutator(ctx android.BottomUpMutatorContext) {
117}
118
119var packageRootsMutex sync.Mutex
120var packageRoots []*hidlPackageRoot
121
122func hidlPackageRootFactory() android.Module {
123	r := &hidlPackageRoot{}
124	r.AddProperties(&r.properties)
125	android.InitAndroidModule(r)
126
127	packageRootsMutex.Lock()
128	packageRoots = append(packageRoots, r)
129	packageRootsMutex.Unlock()
130
131	return r
132}
133
134func lookupPackageRoot(name string) *hidlPackageRoot {
135	for _, i := range packageRoots {
136		if i.ModuleBase.Name() == name {
137			return i
138		}
139	}
140	return nil
141}
142