1// Copyright 2020 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package android
16
17import (
18	"reflect"
19	"sync"
20
21	"github.com/google/blueprint"
22)
23
24// Adds cross-cutting licenses dependency to propagate license metadata through the build system.
25//
26// Stage 1 - bottom-up records package-level default_applicable_licenses property mapped by package name.
27// Stage 2 - bottom-up converts licenses property or package default_applicable_licenses to dependencies.
28// Stage 3 - bottom-up type-checks every added applicable license dependency and license_kind dependency.
29// Stage 4 - GenerateBuildActions calculates properties for the union of license kinds, conditions and texts.
30
31type licensesDependencyTag struct {
32	blueprint.BaseDependencyTag
33}
34
35func (l licensesDependencyTag) SdkMemberType(Module) SdkMemberType {
36	// Add the supplied module to the sdk as a license module.
37	return LicenseModuleSdkMemberType
38}
39
40func (l licensesDependencyTag) ExportMember() bool {
41	// The license module will only every be referenced from within the sdk. This will ensure that it
42	// gets a unique name and so avoid clashing with the original license module.
43	return false
44}
45
46var (
47	licensesTag = licensesDependencyTag{}
48
49	// License modules, i.e. modules depended upon via a licensesTag, must be automatically added to
50	// any sdk/module_exports to which their referencing module is a member.
51	_ SdkMemberTypeDependencyTag = licensesTag
52)
53
54// Describes the property provided by a module to reference applicable licenses.
55type applicableLicensesProperty interface {
56	// The name of the property. e.g. default_applicable_licenses or licenses
57	getName() string
58	// The values assigned to the property. (Must reference license modules.)
59	getStrings() []string
60}
61
62type applicableLicensesPropertyImpl struct {
63	name             string
64	licensesProperty *[]string
65}
66
67func newApplicableLicensesProperty(name string, licensesProperty *[]string) applicableLicensesProperty {
68	return applicableLicensesPropertyImpl{
69		name:             name,
70		licensesProperty: licensesProperty,
71	}
72}
73
74func (p applicableLicensesPropertyImpl) getName() string {
75	return p.name
76}
77
78func (p applicableLicensesPropertyImpl) getStrings() []string {
79	return *p.licensesProperty
80}
81
82// Set the primary applicable licenses property for a module.
83func setPrimaryLicensesProperty(module Module, name string, licensesProperty *[]string) {
84	module.base().primaryLicensesProperty = newApplicableLicensesProperty(name, licensesProperty)
85}
86
87// Storage blob for a package's default_applicable_licenses mapped by package directory.
88type licensesContainer struct {
89	licenses []string
90}
91
92func (r licensesContainer) getLicenses() []string {
93	return r.licenses
94}
95
96var packageDefaultLicensesMap = NewOnceKey("packageDefaultLicensesMap")
97
98// The map from package dir name to default applicable licenses as a licensesContainer.
99func moduleToPackageDefaultLicensesMap(config Config) *sync.Map {
100	return config.Once(packageDefaultLicensesMap, func() interface{} {
101		return &sync.Map{}
102	}).(*sync.Map)
103}
104
105// Registers the function that maps each package to its default_applicable_licenses.
106//
107// This goes before defaults expansion so the defaults can pick up the package default.
108func RegisterLicensesPackageMapper(ctx RegisterMutatorsContext) {
109	ctx.BottomUp("licensesPackageMapper", licensesPackageMapper).Parallel()
110}
111
112// Registers the function that gathers the license dependencies for each module.
113//
114// This goes after defaults expansion so that it can pick up default licenses and before visibility enforcement.
115func RegisterLicensesPropertyGatherer(ctx RegisterMutatorsContext) {
116	ctx.BottomUp("licensesPropertyGatherer", licensesPropertyGatherer).Parallel()
117}
118
119// Registers the function that verifies the licenses and license_kinds dependency types for each module.
120func RegisterLicensesDependencyChecker(ctx RegisterMutatorsContext) {
121	ctx.BottomUp("licensesPropertyChecker", licensesDependencyChecker).Parallel()
122}
123
124// Maps each package to its default applicable licenses.
125func licensesPackageMapper(ctx BottomUpMutatorContext) {
126	p, ok := ctx.Module().(*packageModule)
127	if !ok {
128		return
129	}
130
131	licenses := getLicenses(ctx, p)
132
133	dir := ctx.ModuleDir()
134	c := makeLicensesContainer(licenses)
135	moduleToPackageDefaultLicensesMap(ctx.Config()).Store(dir, c)
136}
137
138// Copies the default_applicable_licenses property values for mapping by package directory.
139func makeLicensesContainer(propVals []string) licensesContainer {
140	licenses := make([]string, 0, len(propVals))
141	licenses = append(licenses, propVals...)
142
143	return licensesContainer{licenses}
144}
145
146// Gathers the applicable licenses into dependency references after defaults expansion.
147func licensesPropertyGatherer(ctx BottomUpMutatorContext) {
148	m, ok := ctx.Module().(Module)
149	if !ok {
150		return
151	}
152
153	if exemptFromRequiredApplicableLicensesProperty(m) {
154		return
155	}
156
157	licenses := getLicenses(ctx, m)
158	ctx.AddVariationDependencies(nil, licensesTag, licenses...)
159}
160
161// Verifies the license and license_kind dependencies are each the correct kind of module.
162func licensesDependencyChecker(ctx BottomUpMutatorContext) {
163	m, ok := ctx.Module().(Module)
164	if !ok {
165		return
166	}
167
168	// license modules have no licenses, but license_kinds must refer to license_kind modules
169	if _, ok := m.(*licenseModule); ok {
170		for _, module := range ctx.GetDirectDepsWithTag(licenseKindTag) {
171			if _, ok := module.(*licenseKindModule); !ok {
172				ctx.ModuleErrorf("license_kinds property %q is not a license_kind module", ctx.OtherModuleName(module))
173			}
174		}
175		return
176	}
177
178	if exemptFromRequiredApplicableLicensesProperty(m) {
179		return
180	}
181
182	for _, module := range ctx.GetDirectDepsWithTag(licensesTag) {
183		if _, ok := module.(*licenseModule); !ok {
184			propertyName := "licenses"
185			primaryProperty := m.base().primaryLicensesProperty
186			if primaryProperty != nil {
187				propertyName = primaryProperty.getName()
188			}
189			ctx.ModuleErrorf("%s property %q is not a license module", propertyName, ctx.OtherModuleName(module))
190		}
191	}
192}
193
194// Flattens license and license_kind dependencies into calculated properties.
195//
196// Re-validates applicable licenses properties refer only to license modules and license_kinds properties refer
197// only to license_kind modules.
198func licensesPropertyFlattener(ctx ModuleContext) {
199	m, ok := ctx.Module().(Module)
200	if !ok {
201		return
202	}
203
204	if exemptFromRequiredApplicableLicensesProperty(m) {
205		return
206	}
207
208	var licenses []string
209	for _, module := range ctx.GetDirectDepsWithTag(licensesTag) {
210		if l, ok := module.(*licenseModule); ok {
211			licenses = append(licenses, ctx.OtherModuleName(module))
212			if m.base().commonProperties.Effective_package_name == nil && l.properties.Package_name != nil {
213				m.base().commonProperties.Effective_package_name = l.properties.Package_name
214			}
215			mergeStringProps(&m.base().commonProperties.Effective_licenses, module.base().commonProperties.Effective_licenses...)
216			mergePathProps(&m.base().commonProperties.Effective_license_text, module.base().commonProperties.Effective_license_text...)
217			mergeStringProps(&m.base().commonProperties.Effective_license_kinds, module.base().commonProperties.Effective_license_kinds...)
218			mergeStringProps(&m.base().commonProperties.Effective_license_conditions, module.base().commonProperties.Effective_license_conditions...)
219		} else {
220			propertyName := "licenses"
221			primaryProperty := m.base().primaryLicensesProperty
222			if primaryProperty != nil {
223				propertyName = primaryProperty.getName()
224			}
225			ctx.ModuleErrorf("%s property %q is not a license module", propertyName, ctx.OtherModuleName(module))
226		}
227	}
228
229	// Make the license information available for other modules.
230	licenseInfo := LicenseInfo{
231		Licenses: licenses,
232	}
233	ctx.SetProvider(LicenseInfoProvider, licenseInfo)
234}
235
236// Update a property string array with a distinct union of its values and a list of new values.
237func mergeStringProps(prop *[]string, values ...string) {
238	*prop = append(*prop, values...)
239	*prop = SortedUniqueStrings(*prop)
240}
241
242// Update a property Path array with a distinct union of its values and a list of new values.
243func mergePathProps(prop *Paths, values ...Path) {
244	*prop = append(*prop, values...)
245	*prop = SortedUniquePaths(*prop)
246}
247
248// Get the licenses property falling back to the package default.
249func getLicenses(ctx BaseModuleContext, module Module) []string {
250	if exemptFromRequiredApplicableLicensesProperty(module) {
251		return nil
252	}
253
254	primaryProperty := module.base().primaryLicensesProperty
255	if primaryProperty == nil {
256		if ctx.Config().IsEnvTrue("ANDROID_REQUIRE_LICENSES") {
257			ctx.ModuleErrorf("module type %q must have an applicable licenses property", ctx.OtherModuleType(module))
258		}
259		return nil
260	}
261
262	licenses := primaryProperty.getStrings()
263	if len(licenses) > 0 {
264		s := make(map[string]bool)
265		for _, l := range licenses {
266			if _, ok := s[l]; ok {
267				ctx.ModuleErrorf("duplicate %q %s", l, primaryProperty.getName())
268			}
269			s[l] = true
270		}
271		return licenses
272	}
273
274	dir := ctx.OtherModuleDir(module)
275
276	moduleToApplicableLicenses := moduleToPackageDefaultLicensesMap(ctx.Config())
277	value, ok := moduleToApplicableLicenses.Load(dir)
278	var c licensesContainer
279	if ok {
280		c = value.(licensesContainer)
281	} else {
282		c = licensesContainer{}
283	}
284	return c.getLicenses()
285}
286
287// Returns whether a module is an allowed list of modules that do not have or need applicable licenses.
288func exemptFromRequiredApplicableLicensesProperty(module Module) bool {
289	switch reflect.TypeOf(module).String() {
290	case "*android.licenseModule": // is a license, doesn't need one
291	case "*android.licenseKindModule": // is a license, doesn't need one
292	case "*android.NamespaceModule": // just partitions things, doesn't add anything
293	case "*android.soongConfigModuleTypeModule": // creates aliases for modules with licenses
294	case "*android.soongConfigModuleTypeImport": // creates aliases for modules with licenses
295	case "*android.soongConfigStringVariableDummyModule": // used for creating aliases
296	case "*android.SoongConfigBoolVariableDummyModule": // used for creating aliases
297	default:
298		return false
299	}
300	return true
301}
302
303// LicenseInfo contains information about licenses for a specific module.
304type LicenseInfo struct {
305	// The list of license modules this depends upon, either explicitly or through default package
306	// configuration.
307	Licenses []string
308}
309
310var LicenseInfoProvider = blueprint.NewProvider(LicenseInfo{})
311