diff --git a/android/Android.bp b/android/Android.bp index f8c1d5567..69aa03738 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -30,6 +30,9 @@ bootstrap_go_package { "filegroup.go", "hooks.go", "image.go", + "license.go", + "license_kind.go", + "licenses.go", "makefile_goal.go", "makevars.go", "metrics.go", @@ -77,6 +80,9 @@ bootstrap_go_package { "depset_test.go", "deptag_test.go", "expand_test.go", + "license_kind_test.go", + "license_test.go", + "licenses_test.go", "module_test.go", "mutator_test.go", "namespace_test.go", diff --git a/android/androidmk.go b/android/androidmk.go index 73f60d0c0..585685149 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -28,6 +28,7 @@ import ( "io/ioutil" "os" "path/filepath" + "reflect" "sort" "strings" @@ -434,6 +435,17 @@ func (a *AndroidMkEntries) GetDistForGoals(mod blueprint.Module) []string { return generateDistContributionsForMake(distContributions) } +// Write the license variables to Make for AndroidMkData.Custom(..) methods that do not call WriteAndroidMkData(..) +// It's required to propagate the license metadata even for module types that have non-standard interfaces to Make. +func (a *AndroidMkEntries) WriteLicenseVariables(w io.Writer) { + fmt.Fprintln(w, "LOCAL_LICENSE_KINDS :=", strings.Join(a.EntryMap["LOCAL_LICENSE_KINDS"], " ")) + fmt.Fprintln(w, "LOCAL_LICENSE_CONDITIONS :=", strings.Join(a.EntryMap["LOCAL_LICENSE_CONDITIONS"], " ")) + fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", strings.Join(a.EntryMap["LOCAL_NOTICE_FILE"], " ")) + if pn, ok := a.EntryMap["LOCAL_LICENSE_PACKAGE_NAME"]; ok { + fmt.Fprintln(w, "LOCAL_LICENSE_PACKAGE_NAME :=", strings.Join(pn, " ")) + } +} + // fillInEntries goes through the common variable processing and calls the extra data funcs to // generate and fill in AndroidMkEntries's in-struct data, ready to be flushed to a file. func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod blueprint.Module) { @@ -460,6 +472,13 @@ func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod bluep // Collect make variable assignment entries. a.SetString("LOCAL_PATH", filepath.Dir(bpPath)) a.SetString("LOCAL_MODULE", name+a.SubName) + a.AddStrings("LOCAL_LICENSE_KINDS", amod.commonProperties.Effective_license_kinds...) + a.AddStrings("LOCAL_LICENSE_CONDITIONS", amod.commonProperties.Effective_license_conditions...) + a.AddStrings("LOCAL_NOTICE_FILE", amod.commonProperties.Effective_license_text...) + // TODO(b/151177513): Does this code need to set LOCAL_MODULE_IS_CONTAINER ? + if amod.commonProperties.Effective_package_name != nil { + a.SetString("LOCAL_LICENSE_PACKAGE_NAME", *amod.commonProperties.Effective_package_name) + } a.SetString("LOCAL_MODULE_CLASS", a.Class) a.SetString("LOCAL_PREBUILT_MODULE_FILE", a.OutputFile.String()) a.AddStrings("LOCAL_REQUIRED_MODULES", a.Required...) @@ -682,6 +701,7 @@ func translateAndroidMkModule(ctx SingletonContext, w io.Writer, mod blueprint.M } }() + // Additional cases here require review for correct license propagation to make. switch x := mod.(type) { case AndroidMkDataProvider: return translateAndroidModule(ctx, w, mod, x) @@ -690,6 +710,7 @@ func translateAndroidMkModule(ctx SingletonContext, w io.Writer, mod blueprint.M case AndroidMkEntriesProvider: return translateAndroidMkEntriesModule(ctx, w, mod, x) default: + // Not exported to make so no make variables to set. return nil } } @@ -703,6 +724,10 @@ func translateGoBinaryModule(ctx SingletonContext, w io.Writer, mod blueprint.Mo fmt.Fprintln(w, ".PHONY:", name) fmt.Fprintln(w, name+":", goBinary.InstallPath()) fmt.Fprintln(w, "") + // Assuming no rules in make include go binaries in distributables. + // If the assumption is wrong, make will fail to build without the necessary .meta_lic and .meta_module files. + // In that case, add the targets and rules here to build a .meta_lic file for `name` and a .meta_module for + // `goBinary.InstallPath()` pointing to the `name`.meta_lic file. return nil } @@ -768,6 +793,25 @@ func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Mod blueprintDir := filepath.Dir(ctx.BlueprintFile(mod)) if data.Custom != nil { + // List of module types allowed to use .Custom(...) + // Additions to the list require careful review for proper license handling. + switch reflect.TypeOf(mod).String() { // ctx.ModuleType(mod) doesn't work: aidl_interface creates phony without type + case "*aidl.aidlApi": // writes non-custom before adding .phony + case "*aidl.aidlMapping": // writes non-custom before adding .phony + case "*android.customModule": // appears in tests only + case "*apex.apexBundle": // license properties written + case "*bpf.bpf": // license properties written (both for module and objs) + case "*genrule.Module": // writes non-custom before adding .phony + case "*java.SystemModules": // doesn't go through base_rules + case "*java.systemModulesImport": // doesn't go through base_rules + case "*phony.phony": // license properties written + case "*selinux.selinuxContextsModule": // license properties written + case "*sysprop.syspropLibrary": // license properties written + default: + if ctx.Config().IsEnvTrue("ANDROID_REQUIRE_LICENSES") { + return fmt.Errorf("custom make rules not allowed for %q (%q) module %q", ctx.ModuleType(mod), reflect.TypeOf(mod), ctx.ModuleName(mod)) + } + } data.Custom(w, name, prefix, blueprintDir, data) } else { WriteAndroidMkData(w, data) @@ -804,6 +848,7 @@ func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, mod blue return nil } + // Any new or special cases here need review to verify correct propagation of license information. for _, entries := range provider.AndroidMkEntries() { entries.fillInEntries(ctx.Config(), ctx.BlueprintFile(mod), mod) entries.write(w) diff --git a/android/defaults.go b/android/defaults.go index 44753ce22..aacfbacc6 100644 --- a/android/defaults.go +++ b/android/defaults.go @@ -204,6 +204,9 @@ func InitDefaultsModule(module DefaultsModule) { // its checking phase and parsing phase so add it to the list as a normal property. AddVisibilityProperty(module, "visibility", &commonProperties.Visibility) + // The applicable licenses property for defaults is 'licenses'. + setPrimaryLicensesProperty(module, "licenses", &commonProperties.Licenses) + base.module = module } diff --git a/android/license.go b/android/license.go new file mode 100644 index 000000000..b140b55b1 --- /dev/null +++ b/android/license.go @@ -0,0 +1,82 @@ +// Copyright 2020 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import ( + "github.com/google/blueprint" +) + +type licenseKindDependencyTag struct { + blueprint.BaseDependencyTag +} + +var ( + licenseKindTag = licenseKindDependencyTag{} +) + +func init() { + RegisterLicenseBuildComponents(InitRegistrationContext) +} + +// Register the license module type. +func RegisterLicenseBuildComponents(ctx RegistrationContext) { + ctx.RegisterModuleType("license", LicenseFactory) +} + +type licenseProperties struct { + // Specifies the kinds of license that apply. + License_kinds []string + // Specifies a short copyright notice to use for the license. + Copyright_notice *string + // Specifies the path or label for the text of the license. + License_text []string `android:"path"` + // Specifies the package name to which the license applies. + Package_name *string + // Specifies where this license can be used + Visibility []string +} + +type licenseModule struct { + ModuleBase + DefaultableModuleBase + + properties licenseProperties +} + +func (m *licenseModule) DepsMutator(ctx BottomUpMutatorContext) { + ctx.AddVariationDependencies(nil, licenseKindTag, m.properties.License_kinds...) +} + +func (m *licenseModule) GenerateAndroidBuildActions(ctx ModuleContext) { + // Nothing to do. +} + +func LicenseFactory() Module { + module := &licenseModule{} + + base := module.base() + module.AddProperties(&base.nameProperties, &module.properties) + + base.generalProperties = module.GetProperties() + base.customizableProperties = module.GetProperties() + + // The visibility property needs to be checked and parsed by the visibility module. + setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility) + + initAndroidModuleBase(module) + InitDefaultableModule(module) + + return module +} diff --git a/android/license_kind.go b/android/license_kind.go new file mode 100644 index 000000000..ddecd775f --- /dev/null +++ b/android/license_kind.go @@ -0,0 +1,66 @@ +// Copyright 2020 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +func init() { + RegisterLicenseKindBuildComponents(InitRegistrationContext) +} + +// Register the license_kind module type. +func RegisterLicenseKindBuildComponents(ctx RegistrationContext) { + ctx.RegisterModuleType("license_kind", LicenseKindFactory) +} + +type licenseKindProperties struct { + // Specifies the conditions for all licenses of the kind. + Conditions []string + // Specifies the url to the canonical license definition. + Url string + // Specifies where this license can be used + Visibility []string +} + +type licenseKindModule struct { + ModuleBase + DefaultableModuleBase + + properties licenseKindProperties +} + +func (m *licenseKindModule) DepsMutator(ctx BottomUpMutatorContext) { + // Nothing to do. +} + +func (m *licenseKindModule) GenerateAndroidBuildActions(ModuleContext) { + // Nothing to do. +} + +func LicenseKindFactory() Module { + module := &licenseKindModule{} + + base := module.base() + module.AddProperties(&base.nameProperties, &module.properties) + + base.generalProperties = module.GetProperties() + base.customizableProperties = module.GetProperties() + + // The visibility property needs to be checked and parsed by the visibility module. + setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility) + + initAndroidModuleBase(module) + InitDefaultableModule(module) + + return module +} diff --git a/android/license_kind_test.go b/android/license_kind_test.go new file mode 100644 index 000000000..767b64e82 --- /dev/null +++ b/android/license_kind_test.go @@ -0,0 +1,174 @@ +package android + +import ( + "testing" + + "github.com/google/blueprint" +) + +var licenseKindTests = []struct { + name string + fs map[string][]byte + expectedErrors []string +}{ + { + name: "license_kind must not accept licenses property", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + license_kind { + name: "top_license", + licenses: ["other_license"], + }`), + }, + expectedErrors: []string{ + `top/Blueprints:4:14: unrecognized property "licenses"`, + }, + }, + { + name: "bad license_kind", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + license_kind { + name: "top_notice", + conditions: ["notice"], + }`), + "other/Blueprints": []byte(` + mock_license { + name: "other_notice", + license_kinds: ["notice"], + }`), + }, + expectedErrors: []string{ + `other/Blueprints:2:5: "other_notice" depends on undefined module "notice"`, + }, + }, + { + name: "good license kind", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + license_kind { + name: "top_by_exception_only", + conditions: ["by_exception_only"], + } + + mock_license { + name: "top_proprietary", + license_kinds: ["top_by_exception_only"], + }`), + "other/Blueprints": []byte(` + mock_license { + name: "other_proprietary", + license_kinds: ["top_proprietary"], + }`), + }, + }, + { + name: "multiple license kinds", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + license_kind { + name: "top_notice", + conditions: ["notice"], + } + + license_kind { + name: "top_by_exception_only", + conditions: ["by_exception_only"], + } + + mock_license { + name: "top_allowed_as_notice", + license_kinds: ["top_notice"], + } + + mock_license { + name: "top_proprietary", + license_kinds: ["top_by_exception_only"], + }`), + "other/Blueprints": []byte(` + mock_license { + name: "other_rule", + license_kinds: ["top_by_exception_only"], + }`), + }, + }, +} + +func TestLicenseKind(t *testing.T) { + for _, test := range licenseKindTests { + t.Run(test.name, func(t *testing.T) { + _, errs := testLicenseKind(test.fs) + + expectedErrors := test.expectedErrors + if expectedErrors == nil { + FailIfErrored(t, errs) + } else { + for _, expectedError := range expectedErrors { + FailIfNoMatchingErrors(t, expectedError, errs) + } + if len(errs) > len(expectedErrors) { + t.Errorf("additional errors found, expected %d, found %d", len(expectedErrors), len(errs)) + for i, expectedError := range expectedErrors { + t.Errorf("expectedErrors[%d] = %s", i, expectedError) + } + for i, err := range errs { + t.Errorf("errs[%d] = %s", i, err) + } + } + } + }) + } +} + +func testLicenseKind(fs map[string][]byte) (*TestContext, []error) { + + // Create a new config per test as license_kind information is stored in the config. + config := TestArchConfig(buildDir, nil, "", fs) + + ctx := NewTestArchContext(config) + RegisterLicenseKindBuildComponents(ctx) + ctx.RegisterModuleType("mock_license", newMockLicenseModule) + ctx.Register() + + _, errs := ctx.ParseBlueprintsFiles(".") + if len(errs) > 0 { + return ctx, errs + } + + _, errs = ctx.PrepareBuildActions(config) + return ctx, errs +} + +type mockLicenseProperties struct { + License_kinds []string +} + +type mockLicenseModule struct { + ModuleBase + DefaultableModuleBase + + properties mockLicenseProperties +} + +func newMockLicenseModule() Module { + m := &mockLicenseModule{} + m.AddProperties(&m.properties) + InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon) + InitDefaultableModule(m) + return m +} + +type licensekindTag struct { + blueprint.BaseDependencyTag +} + +func (j *mockLicenseModule) DepsMutator(ctx BottomUpMutatorContext) { + m, ok := ctx.Module().(Module) + if !ok { + return + } + ctx.AddDependency(m, licensekindTag{}, j.properties.License_kinds...) +} + +func (p *mockLicenseModule) GenerateAndroidBuildActions(ModuleContext) { +} diff --git a/android/license_test.go b/android/license_test.go new file mode 100644 index 000000000..552bbaee0 --- /dev/null +++ b/android/license_test.go @@ -0,0 +1,233 @@ +package android + +import ( + "testing" +) + +var licenseTests = []struct { + name string + fs map[string][]byte + expectedErrors []string +}{ + { + name: "license must not accept licenses property", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + license { + name: "top_license", + visibility: ["//visibility:private"], + licenses: ["other_license"], + }`), + }, + expectedErrors: []string{ + `top/Blueprints:5:14: unrecognized property "licenses"`, + }, + }, + { + name: "private license", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + license_kind { + name: "top_notice", + conditions: ["notice"], + visibility: ["//visibility:private"], + } + + license { + name: "top_allowed_as_notice", + license_kinds: ["top_notice"], + visibility: ["//visibility:private"], + }`), + "other/Blueprints": []byte(` + rule { + name: "arule", + licenses: ["top_allowed_as_notice"], + }`), + "yetmore/Blueprints": []byte(` + package { + default_applicable_licenses: ["top_allowed_as_notice"], + }`), + }, + expectedErrors: []string{ + `other/Blueprints:2:5: module "arule": depends on //top:top_allowed_as_notice `+ + `which is not visible to this module`, + `yetmore/Blueprints:2:5: module "//yetmore": depends on //top:top_allowed_as_notice `+ + `which is not visible to this module`, + }, + }, + { + name: "must reference license_kind module", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + rule { + name: "top_by_exception_only", + } + + license { + name: "top_proprietary", + license_kinds: ["top_by_exception_only"], + visibility: ["//visibility:public"], + }`), + }, + expectedErrors: []string{ + `top/Blueprints:6:5: module "top_proprietary": license_kinds property `+ + `"top_by_exception_only" is not a license_kind module`, + }, + }, + { + name: "license_kind module must exist", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + license { + name: "top_notice_allowed", + license_kinds: ["top_notice"], + visibility: ["//visibility:public"], + }`), + }, + expectedErrors: []string{ + `top/Blueprints:2:5: "top_notice_allowed" depends on undefined module "top_notice"`, + }, + }, + { + name: "public license", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + license_kind { + name: "top_by_exception_only", + conditions: ["by_exception_only"], + visibility: ["//visibility:private"], + } + + license { + name: "top_proprietary", + license_kinds: ["top_by_exception_only"], + visibility: ["//visibility:public"], + }`), + "other/Blueprints": []byte(` + rule { + name: "arule", + licenses: ["top_proprietary"], + }`), + "yetmore/Blueprints": []byte(` + package { + default_applicable_licenses: ["top_proprietary"], + }`), + }, + }, + { + name: "multiple licenses", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + package { + default_applicable_licenses: ["top_proprietary"], + } + + license_kind { + name: "top_notice", + conditions: ["notice"], + } + + license_kind { + name: "top_by_exception_only", + conditions: ["by_exception_only"], + visibility: ["//visibility:public"], + } + + license { + name: "top_allowed_as_notice", + license_kinds: ["top_notice"], + } + + license { + name: "top_proprietary", + license_kinds: ["top_by_exception_only"], + visibility: ["//visibility:public"], + } + rule { + name: "myrule", + licenses: ["top_allowed_as_notice", "top_proprietary"] + }`), + "other/Blueprints": []byte(` + rule { + name: "arule", + licenses: ["top_proprietary"], + }`), + "yetmore/Blueprints": []byte(` + package { + default_applicable_licenses: ["top_proprietary"], + }`), + }, + }, +} + +func TestLicense(t *testing.T) { + for _, test := range licenseTests { + t.Run(test.name, func(t *testing.T) { + _, errs := testLicense(test.fs) + + expectedErrors := test.expectedErrors + if expectedErrors == nil { + FailIfErrored(t, errs) + } else { + for _, expectedError := range expectedErrors { + FailIfNoMatchingErrors(t, expectedError, errs) + } + if len(errs) > len(expectedErrors) { + t.Errorf("additional errors found, expected %d, found %d", len(expectedErrors), len(errs)) + for i, expectedError := range expectedErrors { + t.Errorf("expectedErrors[%d] = %s", i, expectedError) + } + for i, err := range errs { + t.Errorf("errs[%d] = %s", i, err) + } + } + } + }) + } +} + +func testLicense(fs map[string][]byte) (*TestContext, []error) { + + // Create a new config per test as visibility information is stored in the config. + env := make(map[string]string) + env["ANDROID_REQUIRE_LICENSES"] = "1" + config := TestArchConfig(buildDir, env, "", fs) + + ctx := NewTestArchContext(config) + RegisterPackageBuildComponents(ctx) + registerTestPrebuiltBuildComponents(ctx) + RegisterLicenseKindBuildComponents(ctx) + RegisterLicenseBuildComponents(ctx) + ctx.RegisterModuleType("rule", newMockRuleModule) + ctx.PreArchMutators(RegisterVisibilityRuleChecker) + ctx.PreArchMutators(RegisterLicensesPackageMapper) + ctx.PreArchMutators(RegisterDefaultsPreArchMutators) + ctx.PreArchMutators(RegisterLicensesPropertyGatherer) + ctx.PreArchMutators(RegisterVisibilityRuleGatherer) + ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer) + ctx.PostDepsMutators(RegisterLicensesDependencyChecker) + ctx.Register() + + _, errs := ctx.ParseBlueprintsFiles(".") + if len(errs) > 0 { + return ctx, errs + } + + _, errs = ctx.PrepareBuildActions(config) + return ctx, errs +} + +type mockRuleModule struct { + ModuleBase + DefaultableModuleBase +} + +func newMockRuleModule() Module { + m := &mockRuleModule{} + InitAndroidModule(m) + InitDefaultableModule(m) + return m +} + +func (p *mockRuleModule) GenerateAndroidBuildActions(ModuleContext) { +} diff --git a/android/licenses.go b/android/licenses.go new file mode 100644 index 000000000..100042911 --- /dev/null +++ b/android/licenses.go @@ -0,0 +1,295 @@ +// Copyright 2020 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import ( + "reflect" + "sync" + + "github.com/google/blueprint" +) + +// Adds cross-cutting licenses dependency to propagate license metadata through the build system. +// +// Stage 1 - bottom-up records package-level default_applicable_licenses property mapped by package name. +// Stage 2 - bottom-up converts licenses property or package default_applicable_licenses to dependencies. +// Stage 3 - bottom-up type-checks every added applicable license dependency and license_kind dependency. +// Stage 4 - GenerateBuildActions calculates properties for the union of license kinds, conditions and texts. + +type licensesDependencyTag struct { + blueprint.BaseDependencyTag +} + +var ( + licensesTag = licensesDependencyTag{} +) + +// Describes the property provided by a module to reference applicable licenses. +type applicableLicensesProperty interface { + // The name of the property. e.g. default_applicable_licenses or licenses + getName() string + // The values assigned to the property. (Must reference license modules.) + getStrings() []string +} + +type applicableLicensesPropertyImpl struct { + name string + licensesProperty *[]string +} + +func newApplicableLicensesProperty(name string, licensesProperty *[]string) applicableLicensesProperty { + return applicableLicensesPropertyImpl{ + name: name, + licensesProperty: licensesProperty, + } +} + +func (p applicableLicensesPropertyImpl) getName() string { + return p.name +} + +func (p applicableLicensesPropertyImpl) getStrings() []string { + return *p.licensesProperty +} + +// Set the primary applicable licenses property for a module. +func setPrimaryLicensesProperty(module Module, name string, licensesProperty *[]string) { + module.base().primaryLicensesProperty = newApplicableLicensesProperty(name, licensesProperty) +} + +// Storage blob for a package's default_applicable_licenses mapped by package directory. +type licensesContainer struct { + licenses []string +} + +func (r licensesContainer) getLicenses() []string { + return r.licenses +} + +var packageDefaultLicensesMap = NewOnceKey("packageDefaultLicensesMap") + +// The map from package dir name to default applicable licenses as a licensesContainer. +func moduleToPackageDefaultLicensesMap(config Config) *sync.Map { + return config.Once(packageDefaultLicensesMap, func() interface{} { + return &sync.Map{} + }).(*sync.Map) +} + +// Registers the function that maps each package to its default_applicable_licenses. +// +// This goes before defaults expansion so the defaults can pick up the package default. +func RegisterLicensesPackageMapper(ctx RegisterMutatorsContext) { + ctx.BottomUp("licensesPackageMapper", licensesPackageMapper).Parallel() +} + +// Registers the function that gathers the license dependencies for each module. +// +// This goes after defaults expansion so that it can pick up default licenses and before visibility enforcement. +func RegisterLicensesPropertyGatherer(ctx RegisterMutatorsContext) { + ctx.BottomUp("licensesPropertyGatherer", licensesPropertyGatherer).Parallel() +} + +// Registers the function that verifies the licenses and license_kinds dependency types for each module. +func RegisterLicensesDependencyChecker(ctx RegisterMutatorsContext) { + ctx.BottomUp("licensesPropertyChecker", licensesDependencyChecker).Parallel() +} + +// Maps each package to its default applicable licenses. +func licensesPackageMapper(ctx BottomUpMutatorContext) { + p, ok := ctx.Module().(*packageModule) + if !ok { + return + } + + licenses := getLicenses(ctx, p) + + dir := ctx.ModuleDir() + c := makeLicensesContainer(licenses) + moduleToPackageDefaultLicensesMap(ctx.Config()).Store(dir, c) +} + +// Copies the default_applicable_licenses property values for mapping by package directory. +func makeLicensesContainer(propVals []string) licensesContainer { + licenses := make([]string, 0, len(propVals)) + licenses = append(licenses, propVals...) + + return licensesContainer{licenses} +} + +// Gathers the applicable licenses into dependency references after defaults expansion. +func licensesPropertyGatherer(ctx BottomUpMutatorContext) { + m, ok := ctx.Module().(Module) + if !ok { + return + } + + if exemptFromRequiredApplicableLicensesProperty(m) { + return + } + + licenses := getLicenses(ctx, m) + + ctx.AddVariationDependencies(nil, licensesTag, licenses...) +} + +// Verifies the license and license_kind dependencies are each the correct kind of module. +func licensesDependencyChecker(ctx BottomUpMutatorContext) { + m, ok := ctx.Module().(Module) + if !ok { + return + } + + // license modules have no licenses, but license_kinds must refer to license_kind modules + if _, ok := m.(*licenseModule); ok { + for _, module := range ctx.GetDirectDepsWithTag(licenseKindTag) { + if _, ok := module.(*licenseKindModule); !ok { + ctx.ModuleErrorf("license_kinds property %q is not a license_kind module", ctx.OtherModuleName(module)) + } + } + return + } + + if exemptFromRequiredApplicableLicensesProperty(m) { + return + } + + for _, module := range ctx.GetDirectDepsWithTag(licensesTag) { + if _, ok := module.(*licenseModule); !ok { + propertyName := "licenses" + primaryProperty := m.base().primaryLicensesProperty + if primaryProperty != nil { + propertyName = primaryProperty.getName() + } + ctx.ModuleErrorf("%s property %q is not a license module", propertyName, ctx.OtherModuleName(module)) + } + } +} + +// Flattens license and license_kind dependencies into calculated properties. +// +// Re-validates applicable licenses properties refer only to license modules and license_kinds properties refer +// only to license_kind modules. +func licensesPropertyFlattener(ctx ModuleContext) { + m, ok := ctx.Module().(Module) + if !ok { + return + } + + // license modules have no licenses, but license_kinds must refer to license_kind modules + if l, ok := m.(*licenseModule); ok { + mergeProps(&m.base().commonProperties.Effective_licenses, ctx.ModuleName()) + mergeProps(&m.base().commonProperties.Effective_license_text, PathsForModuleSrc(ctx, l.properties.License_text).Strings()...) + for _, module := range ctx.GetDirectDepsWithTag(licenseKindTag) { + if lk, ok := module.(*licenseKindModule); ok { + mergeProps(&m.base().commonProperties.Effective_license_conditions, lk.properties.Conditions...) + mergeProps(&m.base().commonProperties.Effective_license_kinds, ctx.OtherModuleName(module)) + } else { + ctx.ModuleErrorf("license_kinds property %q is not a license_kind module", ctx.OtherModuleName(module)) + } + } + return + } + + if exemptFromRequiredApplicableLicensesProperty(m) { + return + } + + for _, module := range ctx.GetDirectDepsWithTag(licensesTag) { + if l, ok := module.(*licenseModule); ok { + if m.base().commonProperties.Effective_package_name == nil && l.properties.Package_name != nil { + m.base().commonProperties.Effective_package_name = l.properties.Package_name + } + mergeProps(&m.base().commonProperties.Effective_licenses, module.base().commonProperties.Effective_licenses...) + mergeProps(&m.base().commonProperties.Effective_license_text, module.base().commonProperties.Effective_license_text...) + mergeProps(&m.base().commonProperties.Effective_license_kinds, module.base().commonProperties.Effective_license_kinds...) + mergeProps(&m.base().commonProperties.Effective_license_conditions, module.base().commonProperties.Effective_license_conditions...) + } else { + propertyName := "licenses" + primaryProperty := m.base().primaryLicensesProperty + if primaryProperty != nil { + propertyName = primaryProperty.getName() + } + ctx.ModuleErrorf("%s property %q is not a license module", propertyName, ctx.OtherModuleName(module)) + } + } +} + +// Update a property string array with a distinct union of its values and a list of new values. +func mergeProps(prop *[]string, values ...string) { + s := make(map[string]bool) + for _, v := range *prop { + s[v] = true + } + for _, v := range values { + s[v] = true + } + *prop = []string{} + *prop = append(*prop, SortedStringKeys(s)...) +} + +// Get the licenses property falling back to the package default. +func getLicenses(ctx BaseModuleContext, module Module) []string { + if exemptFromRequiredApplicableLicensesProperty(module) { + return nil + } + + primaryProperty := module.base().primaryLicensesProperty + if primaryProperty == nil { + if ctx.Config().IsEnvTrue("ANDROID_REQUIRE_LICENSES") { + ctx.ModuleErrorf("module type %q must have an applicable licenses property", ctx.OtherModuleType(module)) + } + return nil + } + + licenses := primaryProperty.getStrings() + if len(licenses) > 0 { + s := make(map[string]bool) + for _, l := range licenses { + if _, ok := s[l]; ok { + ctx.ModuleErrorf("duplicate %q %s", l, primaryProperty.getName()) + } + s[l] = true + } + return licenses + } + + dir := ctx.OtherModuleDir(module) + + moduleToApplicableLicenses := moduleToPackageDefaultLicensesMap(ctx.Config()) + value, ok := moduleToApplicableLicenses.Load(dir) + var c licensesContainer + if ok { + c = value.(licensesContainer) + } else { + c = licensesContainer{} + } + return c.getLicenses() +} + +// Returns whether a module is an allowed list of modules that do not have or need applicable licenses. +func exemptFromRequiredApplicableLicensesProperty(module Module) bool { + switch reflect.TypeOf(module).String() { + case "*android.licenseModule": // is a license, doesn't need one + case "*android.licenseKindModule": // is a license, doesn't need one + case "*android.NamespaceModule": // just partitions things, doesn't add anything + case "*android.soongConfigModuleTypeModule": // creates aliases for modules with licenses + case "*android.soongConfigModuleTypeImport": // creates aliases for modules with licenses + case "*android.soongConfigStringVariableDummyModule": // used for creating aliases + case "*android.SoongConfigBoolVariableDummyModule": // used for creating aliases + default: + return false + } + return true +} diff --git a/android/licenses_test.go b/android/licenses_test.go new file mode 100644 index 000000000..b94add7cf --- /dev/null +++ b/android/licenses_test.go @@ -0,0 +1,863 @@ +package android + +import ( + "testing" + + "github.com/google/blueprint" +) + +var licensesTests = []struct { + name string + fs map[string][]byte + expectedErrors []string + effectiveLicenses map[string][]string + effectiveInheritedLicenses map[string][]string + effectivePackage map[string]string + effectiveNotices map[string][]string + effectiveKinds map[string][]string + effectiveConditions map[string][]string +}{ + { + name: "invalid module type without licenses property", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + mock_bad_module { + name: "libexample", + }`), + }, + expectedErrors: []string{`module type "mock_bad_module" must have an applicable licenses property`}, + }, + { + name: "license must exist", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + mock_library { + name: "libexample", + licenses: ["notice"], + }`), + }, + expectedErrors: []string{`"libexample" depends on undefined module "notice"`}, + }, + { + name: "all good", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + license_kind { + name: "notice", + conditions: ["shownotice"], + } + + license { + name: "top_Apache2", + license_kinds: ["notice"], + package_name: "topDog", + license_text: ["LICENSE", "NOTICE"], + } + + mock_library { + name: "libexample1", + licenses: ["top_Apache2"], + }`), + "top/nested/Blueprints": []byte(` + mock_library { + name: "libnested", + licenses: ["top_Apache2"], + }`), + "other/Blueprints": []byte(` + mock_library { + name: "libother", + licenses: ["top_Apache2"], + }`), + }, + effectiveLicenses: map[string][]string{ + "libexample1": []string{"top_Apache2"}, + "libnested": []string{"top_Apache2"}, + "libother": []string{"top_Apache2"}, + }, + effectiveKinds: map[string][]string{ + "libexample1": []string{"notice"}, + "libnested": []string{"notice"}, + "libother": []string{"notice"}, + }, + effectivePackage: map[string]string{ + "libexample1": "topDog", + "libnested": "topDog", + "libother": "topDog", + }, + effectiveConditions: map[string][]string{ + "libexample1": []string{"shownotice"}, + "libnested": []string{"shownotice"}, + "libother": []string{"shownotice"}, + }, + effectiveNotices: map[string][]string{ + "libexample1": []string{"top/LICENSE", "top/NOTICE"}, + "libnested": []string{"top/LICENSE", "top/NOTICE"}, + "libother": []string{"top/LICENSE", "top/NOTICE"}, + }, + }, + + // Defaults propagation tests + { + // Check that licenses is the union of the defaults modules. + name: "defaults union, basic", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + license_kind { + name: "top_notice", + conditions: ["notice"], + } + + license { + name: "top_other", + license_kinds: ["top_notice"], + } + + mock_defaults { + name: "libexample_defaults", + licenses: ["top_other"], + } + mock_library { + name: "libexample", + licenses: ["nested_other"], + defaults: ["libexample_defaults"], + } + mock_library { + name: "libsamepackage", + deps: ["libexample"], + }`), + "top/nested/Blueprints": []byte(` + license_kind { + name: "nested_notice", + conditions: ["notice"], + } + + license { + name: "nested_other", + license_kinds: ["nested_notice"], + } + + mock_library { + name: "libnested", + deps: ["libexample"], + }`), + "other/Blueprints": []byte(` + mock_library { + name: "libother", + deps: ["libexample"], + }`), + }, + effectiveLicenses: map[string][]string{ + "libexample": []string{"nested_other", "top_other"}, + "libsamepackage": []string{}, + "libnested": []string{}, + "libother": []string{}, + }, + effectiveInheritedLicenses: map[string][]string{ + "libexample": []string{"nested_other", "top_other"}, + "libsamepackage": []string{"nested_other", "top_other"}, + "libnested": []string{"nested_other", "top_other"}, + "libother": []string{"nested_other", "top_other"}, + }, + effectiveKinds: map[string][]string{ + "libexample": []string{"nested_notice", "top_notice"}, + "libsamepackage": []string{}, + "libnested": []string{}, + "libother": []string{}, + }, + effectiveConditions: map[string][]string{ + "libexample": []string{"notice"}, + "libsamepackage": []string{}, + "libnested": []string{}, + "libother": []string{}, + }, + }, + { + name: "defaults union, multiple defaults", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + license { + name: "top", + } + mock_defaults { + name: "libexample_defaults_1", + licenses: ["other"], + } + mock_defaults { + name: "libexample_defaults_2", + licenses: ["top_nested"], + } + mock_library { + name: "libexample", + defaults: ["libexample_defaults_1", "libexample_defaults_2"], + } + mock_library { + name: "libsamepackage", + deps: ["libexample"], + }`), + "top/nested/Blueprints": []byte(` + license { + name: "top_nested", + license_text: ["LICENSE.txt"], + } + mock_library { + name: "libnested", + deps: ["libexample"], + }`), + "other/Blueprints": []byte(` + license { + name: "other", + } + mock_library { + name: "libother", + deps: ["libexample"], + }`), + "outsider/Blueprints": []byte(` + mock_library { + name: "liboutsider", + deps: ["libexample"], + }`), + }, + effectiveLicenses: map[string][]string{ + "libexample": []string{"other", "top_nested"}, + "libsamepackage": []string{}, + "libnested": []string{}, + "libother": []string{}, + "liboutsider": []string{}, + }, + effectiveInheritedLicenses: map[string][]string{ + "libexample": []string{"other", "top_nested"}, + "libsamepackage": []string{"other", "top_nested"}, + "libnested": []string{"other", "top_nested"}, + "libother": []string{"other", "top_nested"}, + "liboutsider": []string{"other", "top_nested"}, + }, + effectiveKinds: map[string][]string{ + "libexample": []string{}, + "libsamepackage": []string{}, + "libnested": []string{}, + "libother": []string{}, + "liboutsider": []string{}, + }, + effectiveNotices: map[string][]string{ + "libexample": []string{"top/nested/LICENSE.txt"}, + "libsamepackage": []string{}, + "libnested": []string{}, + "libother": []string{}, + "liboutsider": []string{}, + }, + }, + + // Defaults module's defaults_licenses tests + { + name: "defaults_licenses invalid", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + mock_defaults { + name: "top_defaults", + licenses: ["notice"], + }`), + }, + expectedErrors: []string{`"top_defaults" depends on undefined module "notice"`}, + }, + { + name: "defaults_licenses overrides package default", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + package { + default_applicable_licenses: ["by_exception_only"], + } + license { + name: "by_exception_only", + } + license { + name: "notice", + } + mock_defaults { + name: "top_defaults", + licenses: ["notice"], + } + mock_library { + name: "libexample", + } + mock_library { + name: "libdefaults", + defaults: ["top_defaults"], + }`), + }, + effectiveLicenses: map[string][]string{ + "libexample": []string{"by_exception_only"}, + "libdefaults": []string{"notice"}, + }, + effectiveInheritedLicenses: map[string][]string{ + "libexample": []string{"by_exception_only"}, + "libdefaults": []string{"notice"}, + }, + }, + + // Package default_applicable_licenses tests + { + name: "package default_applicable_licenses must exist", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + package { + default_applicable_licenses: ["notice"], + }`), + }, + expectedErrors: []string{`"//top" depends on undefined module "notice"`}, + }, + { + // This test relies on the default licenses being legacy_public. + name: "package default_applicable_licenses property used when no licenses specified", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + package { + default_applicable_licenses: ["top_notice"], + } + + license { + name: "top_notice", + } + mock_library { + name: "libexample", + }`), + "outsider/Blueprints": []byte(` + mock_library { + name: "liboutsider", + deps: ["libexample"], + }`), + }, + effectiveLicenses: map[string][]string{ + "libexample": []string{"top_notice"}, + "liboutsider": []string{}, + }, + effectiveInheritedLicenses: map[string][]string{ + "libexample": []string{"top_notice"}, + "liboutsider": []string{"top_notice"}, + }, + }, + { + name: "package default_applicable_licenses not inherited to subpackages", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + package { + default_applicable_licenses: ["top_notice"], + } + license { + name: "top_notice", + } + mock_library { + name: "libexample", + }`), + "top/nested/Blueprints": []byte(` + package { + default_applicable_licenses: ["outsider"], + } + + mock_library { + name: "libnested", + }`), + "top/other/Blueprints": []byte(` + mock_library { + name: "libother", + }`), + "outsider/Blueprints": []byte(` + license { + name: "outsider", + } + mock_library { + name: "liboutsider", + deps: ["libexample", "libother", "libnested"], + }`), + }, + effectiveLicenses: map[string][]string{ + "libexample": []string{"top_notice"}, + "libnested": []string{"outsider"}, + "libother": []string{}, + "liboutsider": []string{}, + }, + effectiveInheritedLicenses: map[string][]string{ + "libexample": []string{"top_notice"}, + "libnested": []string{"outsider"}, + "libother": []string{}, + "liboutsider": []string{"top_notice", "outsider"}, + }, + }, + { + name: "verify that prebuilt dependencies are included", + fs: map[string][]byte{ + "prebuilts/Blueprints": []byte(` + license { + name: "prebuilt" + } + prebuilt { + name: "module", + licenses: ["prebuilt"], + }`), + "top/sources/source_file": nil, + "top/sources/Blueprints": []byte(` + license { + name: "top_sources" + } + source { + name: "module", + licenses: ["top_sources"], + }`), + "top/other/source_file": nil, + "top/other/Blueprints": []byte(` + source { + name: "other", + deps: [":module"], + }`), + }, + effectiveLicenses: map[string][]string{ + "other": []string{}, + }, + effectiveInheritedLicenses: map[string][]string{ + "other": []string{"prebuilt", "top_sources"}, + }, + }, + { + name: "verify that prebuilt dependencies are ignored for licenses reasons (preferred)", + fs: map[string][]byte{ + "prebuilts/Blueprints": []byte(` + license { + name: "prebuilt" + } + prebuilt { + name: "module", + licenses: ["prebuilt"], + prefer: true, + }`), + "top/sources/source_file": nil, + "top/sources/Blueprints": []byte(` + license { + name: "top_sources" + } + source { + name: "module", + licenses: ["top_sources"], + }`), + "top/other/source_file": nil, + "top/other/Blueprints": []byte(` + source { + name: "other", + deps: [":module"], + }`), + }, + effectiveLicenses: map[string][]string{ + "other": []string{}, + }, + effectiveInheritedLicenses: map[string][]string{ + "module": []string{"prebuilt", "top_sources"}, + "other": []string{"prebuilt", "top_sources"}, + }, + }, +} + +func TestLicenses(t *testing.T) { + for _, test := range licensesTests { + t.Run(test.name, func(t *testing.T) { + ctx, errs := testLicenses(buildDir, test.fs) + + CheckErrorsAgainstExpectations(t, errs, test.expectedErrors) + + if test.effectiveLicenses != nil { + checkEffectiveLicenses(t, ctx, test.effectiveLicenses) + } + + if test.effectivePackage != nil { + checkEffectivePackage(t, ctx, test.effectivePackage) + } + + if test.effectiveNotices != nil { + checkEffectiveNotices(t, ctx, test.effectiveNotices) + } + + if test.effectiveKinds != nil { + checkEffectiveKinds(t, ctx, test.effectiveKinds) + } + + if test.effectiveConditions != nil { + checkEffectiveConditions(t, ctx, test.effectiveConditions) + } + + if test.effectiveInheritedLicenses != nil { + checkEffectiveInheritedLicenses(t, ctx, test.effectiveInheritedLicenses) + } + }) + } +} + +func checkEffectiveLicenses(t *testing.T, ctx *TestContext, effectiveLicenses map[string][]string) { + actualLicenses := make(map[string][]string) + ctx.Context.Context.VisitAllModules(func(m blueprint.Module) { + if _, ok := m.(*licenseModule); ok { + return + } + if _, ok := m.(*licenseKindModule); ok { + return + } + if _, ok := m.(*packageModule); ok { + return + } + module, ok := m.(Module) + if !ok { + t.Errorf("%q not a module", m.Name()) + return + } + base := module.base() + if base == nil { + return + } + actualLicenses[m.Name()] = base.commonProperties.Effective_licenses + }) + + for moduleName, expectedLicenses := range effectiveLicenses { + licenses, ok := actualLicenses[moduleName] + if !ok { + licenses = []string{} + } + if !compareUnorderedStringArrays(expectedLicenses, licenses) { + t.Errorf("effective licenses mismatch for module %q: expected %q, found %q", moduleName, expectedLicenses, licenses) + } + } +} + +func checkEffectiveInheritedLicenses(t *testing.T, ctx *TestContext, effectiveInheritedLicenses map[string][]string) { + actualLicenses := make(map[string][]string) + ctx.Context.Context.VisitAllModules(func(m blueprint.Module) { + if _, ok := m.(*licenseModule); ok { + return + } + if _, ok := m.(*licenseKindModule); ok { + return + } + if _, ok := m.(*packageModule); ok { + return + } + module, ok := m.(Module) + if !ok { + t.Errorf("%q not a module", m.Name()) + return + } + base := module.base() + if base == nil { + return + } + inherited := make(map[string]bool) + for _, l := range base.commonProperties.Effective_licenses { + inherited[l] = true + } + ctx.Context.Context.VisitDepsDepthFirst(m, func(c blueprint.Module) { + if _, ok := c.(*licenseModule); ok { + return + } + if _, ok := c.(*licenseKindModule); ok { + return + } + if _, ok := c.(*packageModule); ok { + return + } + cmodule, ok := c.(Module) + if !ok { + t.Errorf("%q not a module", c.Name()) + return + } + cbase := cmodule.base() + if cbase == nil { + return + } + for _, l := range cbase.commonProperties.Effective_licenses { + inherited[l] = true + } + }) + actualLicenses[m.Name()] = []string{} + for l := range inherited { + actualLicenses[m.Name()] = append(actualLicenses[m.Name()], l) + } + }) + + for moduleName, expectedInheritedLicenses := range effectiveInheritedLicenses { + licenses, ok := actualLicenses[moduleName] + if !ok { + licenses = []string{} + } + if !compareUnorderedStringArrays(expectedInheritedLicenses, licenses) { + t.Errorf("effective inherited licenses mismatch for module %q: expected %q, found %q", moduleName, expectedInheritedLicenses, licenses) + } + } +} + +func checkEffectivePackage(t *testing.T, ctx *TestContext, effectivePackage map[string]string) { + actualPackage := make(map[string]string) + ctx.Context.Context.VisitAllModules(func(m blueprint.Module) { + if _, ok := m.(*licenseModule); ok { + return + } + if _, ok := m.(*licenseKindModule); ok { + return + } + if _, ok := m.(*packageModule); ok { + return + } + module, ok := m.(Module) + if !ok { + t.Errorf("%q not a module", m.Name()) + return + } + base := module.base() + if base == nil { + return + } + + if base.commonProperties.Effective_package_name == nil { + actualPackage[m.Name()] = "" + } else { + actualPackage[m.Name()] = *base.commonProperties.Effective_package_name + } + }) + + for moduleName, expectedPackage := range effectivePackage { + packageName, ok := actualPackage[moduleName] + if !ok { + packageName = "" + } + if expectedPackage != packageName { + t.Errorf("effective package mismatch for module %q: expected %q, found %q", moduleName, expectedPackage, packageName) + } + } +} + +func checkEffectiveNotices(t *testing.T, ctx *TestContext, effectiveNotices map[string][]string) { + actualNotices := make(map[string][]string) + ctx.Context.Context.VisitAllModules(func(m blueprint.Module) { + if _, ok := m.(*licenseModule); ok { + return + } + if _, ok := m.(*licenseKindModule); ok { + return + } + if _, ok := m.(*packageModule); ok { + return + } + module, ok := m.(Module) + if !ok { + t.Errorf("%q not a module", m.Name()) + return + } + base := module.base() + if base == nil { + return + } + actualNotices[m.Name()] = base.commonProperties.Effective_license_text + }) + + for moduleName, expectedNotices := range effectiveNotices { + notices, ok := actualNotices[moduleName] + if !ok { + notices = []string{} + } + if !compareUnorderedStringArrays(expectedNotices, notices) { + t.Errorf("effective notice files mismatch for module %q: expected %q, found %q", moduleName, expectedNotices, notices) + } + } +} + +func checkEffectiveKinds(t *testing.T, ctx *TestContext, effectiveKinds map[string][]string) { + actualKinds := make(map[string][]string) + ctx.Context.Context.VisitAllModules(func(m blueprint.Module) { + if _, ok := m.(*licenseModule); ok { + return + } + if _, ok := m.(*licenseKindModule); ok { + return + } + if _, ok := m.(*packageModule); ok { + return + } + module, ok := m.(Module) + if !ok { + t.Errorf("%q not a module", m.Name()) + return + } + base := module.base() + if base == nil { + return + } + actualKinds[m.Name()] = base.commonProperties.Effective_license_kinds + }) + + for moduleName, expectedKinds := range effectiveKinds { + kinds, ok := actualKinds[moduleName] + if !ok { + kinds = []string{} + } + if !compareUnorderedStringArrays(expectedKinds, kinds) { + t.Errorf("effective license kinds mismatch for module %q: expected %q, found %q", moduleName, expectedKinds, kinds) + } + } +} + +func checkEffectiveConditions(t *testing.T, ctx *TestContext, effectiveConditions map[string][]string) { + actualConditions := make(map[string][]string) + ctx.Context.Context.VisitAllModules(func(m blueprint.Module) { + if _, ok := m.(*licenseModule); ok { + return + } + if _, ok := m.(*licenseKindModule); ok { + return + } + if _, ok := m.(*packageModule); ok { + return + } + module, ok := m.(Module) + if !ok { + t.Errorf("%q not a module", m.Name()) + return + } + base := module.base() + if base == nil { + return + } + actualConditions[m.Name()] = base.commonProperties.Effective_license_conditions + }) + + for moduleName, expectedConditions := range effectiveConditions { + conditions, ok := actualConditions[moduleName] + if !ok { + conditions = []string{} + } + if !compareUnorderedStringArrays(expectedConditions, conditions) { + t.Errorf("effective license conditions mismatch for module %q: expected %q, found %q", moduleName, expectedConditions, conditions) + } + } +} + +func compareUnorderedStringArrays(expected, actual []string) bool { + if len(expected) != len(actual) { + return false + } + s := make(map[string]int) + for _, v := range expected { + s[v] += 1 + } + for _, v := range actual { + c, ok := s[v] + if !ok { + return false + } + if c < 1 { + return false + } + s[v] -= 1 + } + return true +} + +func testLicenses(buildDir string, fs map[string][]byte) (*TestContext, []error) { + + // Create a new config per test as licenses information is stored in the config. + env := make(map[string]string) + env["ANDROID_REQUIRE_LICENSES"] = "1" + config := TestArchConfig(buildDir, env, "", fs) + + ctx := NewTestArchContext(config) + ctx.RegisterModuleType("mock_bad_module", newMockLicensesBadModule) + ctx.RegisterModuleType("mock_library", newMockLicensesLibraryModule) + ctx.RegisterModuleType("mock_defaults", defaultsLicensesFactory) + + // Order of the following method calls is significant. + RegisterPackageBuildComponents(ctx) + registerTestPrebuiltBuildComponents(ctx) + RegisterLicenseKindBuildComponents(ctx) + RegisterLicenseBuildComponents(ctx) + ctx.PreArchMutators(RegisterVisibilityRuleChecker) + ctx.PreArchMutators(RegisterLicensesPackageMapper) + ctx.PreArchMutators(RegisterDefaultsPreArchMutators) + ctx.PreArchMutators(RegisterLicensesPropertyGatherer) + ctx.PreArchMutators(RegisterVisibilityRuleGatherer) + ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer) + ctx.PostDepsMutators(RegisterLicensesDependencyChecker) + ctx.Register() + + _, errs := ctx.ParseBlueprintsFiles(".") + if len(errs) > 0 { + return ctx, errs + } + + _, errs = ctx.PrepareBuildActions(config) + return ctx, errs +} + +type mockLicensesBadProperties struct { + Visibility []string +} + +type mockLicensesBadModule struct { + ModuleBase + DefaultableModuleBase + properties mockLicensesBadProperties +} + +func newMockLicensesBadModule() Module { + m := &mockLicensesBadModule{} + + base := m.base() + m.AddProperties(&base.nameProperties, &m.properties) + + base.generalProperties = m.GetProperties() + base.customizableProperties = m.GetProperties() + + // The default_visibility property needs to be checked and parsed by the visibility module during + // its checking and parsing phases so make it the primary visibility property. + setPrimaryVisibilityProperty(m, "visibility", &m.properties.Visibility) + + initAndroidModuleBase(m) + InitDefaultableModule(m) + + return m +} + +func (m *mockLicensesBadModule) GenerateAndroidBuildActions(ModuleContext) { +} + +type mockLicensesLibraryProperties struct { + Deps []string +} + +type mockLicensesLibraryModule struct { + ModuleBase + DefaultableModuleBase + properties mockLicensesLibraryProperties +} + +func newMockLicensesLibraryModule() Module { + m := &mockLicensesLibraryModule{} + m.AddProperties(&m.properties) + InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon) + InitDefaultableModule(m) + return m +} + +type dependencyLicensesTag struct { + blueprint.BaseDependencyTag + name string +} + +func (j *mockLicensesLibraryModule) DepsMutator(ctx BottomUpMutatorContext) { + ctx.AddVariationDependencies(nil, dependencyLicensesTag{name: "mockdeps"}, j.properties.Deps...) +} + +func (p *mockLicensesLibraryModule) GenerateAndroidBuildActions(ModuleContext) { +} + +type mockLicensesDefaults struct { + ModuleBase + DefaultsModuleBase +} + +func defaultsLicensesFactory() Module { + m := &mockLicensesDefaults{} + InitDefaultsModule(m) + return m +} diff --git a/android/module.go b/android/module.go index cfb32c126..b0ad89bb2 100644 --- a/android/module.go +++ b/android/module.go @@ -619,6 +619,20 @@ type commonProperties struct { // more details. Visibility []string + // Describes the licenses applicable to this module. Must reference license modules. + Licenses []string + + // Flattened from direct license dependencies. Equal to Licenses unless particular module adds more. + Effective_licenses []string `blueprint:"mutated"` + // Override of module name when reporting licenses + Effective_package_name *string `blueprint:"mutated"` + // Notice files + Effective_license_text []string `blueprint:"mutated"` + // License names + Effective_license_kinds []string `blueprint:"mutated"` + // License conditions + Effective_license_conditions []string `blueprint:"mutated"` + // control whether this module compiles for 32-bit, 64-bit, or both. Possible values // are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both // architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit @@ -940,6 +954,10 @@ func InitAndroidModule(m Module) { // The default_visibility property needs to be checked and parsed by the visibility module during // its checking and parsing phases so make it the primary visibility property. setPrimaryVisibilityProperty(m, "visibility", &base.commonProperties.Visibility) + + // The default_applicable_licenses property needs to be checked and parsed by the licenses module during + // its checking and parsing phases so make it the primary licenses property. + setPrimaryLicensesProperty(m, "licenses", &base.commonProperties.Licenses) } // InitAndroidArchModule initializes the Module as an Android module that is architecture-specific. @@ -1057,6 +1075,9 @@ type ModuleBase struct { // The primary visibility property, may be nil, that controls access to the module. primaryVisibilityProperty visibilityProperty + // The primary licenses property, may be nil, records license metadata for the module. + primaryLicensesProperty applicableLicensesProperty + noAddressSanitizer bool installFiles InstallPaths installFilesDepSet *installPathsDepSet @@ -1732,6 +1753,11 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) } } + licensesPropertyFlattener(ctx) + if ctx.Failed() { + return + } + m.module.GenerateAndroidBuildActions(ctx) if ctx.Failed() { return diff --git a/android/mutator.go b/android/mutator.go index 31edea331..72c68b2a4 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -115,6 +115,11 @@ var preArch = []RegisterMutatorFunc{ // RegisterVisibilityRuleChecker, + // Record the default_applicable_licenses for each package. + // + // This must run before the defaults so that defaults modules can pick up the package default. + RegisterLicensesPackageMapper, + // Apply properties from defaults modules to the referencing modules. // // Any mutators that are added before this will not see any modules created by @@ -141,6 +146,12 @@ var preArch = []RegisterMutatorFunc{ // prebuilt. RegisterPrebuiltsPreArchMutators, + // Gather the licenses properties for all modules for use during expansion and enforcement. + // + // This must come after the defaults mutators to ensure that any licenses supplied + // in a defaults module has been successfully applied before the rules are gathered. + RegisterLicensesPropertyGatherer, + // Gather the visibility rules for all modules for us during visibility enforcement. // // This must come after the defaults mutators to ensure that any visibility supplied @@ -162,6 +173,7 @@ var postDeps = []RegisterMutatorFunc{ registerPathDepsMutator, RegisterPrebuiltsPostDepsMutators, RegisterVisibilityRuleEnforcer, + RegisterLicensesDependencyChecker, RegisterNeverallowMutator, RegisterOverridePostDepsMutators, } diff --git a/android/package.go b/android/package.go index 182b3ed6e..7012fc7d8 100644 --- a/android/package.go +++ b/android/package.go @@ -31,6 +31,8 @@ func RegisterPackageBuildComponents(ctx RegistrationContext) { type packageProperties struct { // Specifies the default visibility for all modules defined in this package. Default_visibility []string + // Specifies the default license terms for all modules defined in this package. + Default_applicable_licenses []string } type packageModule struct { @@ -68,5 +70,9 @@ func PackageFactory() Module { // its checking and parsing phases so make it the primary visibility property. setPrimaryVisibilityProperty(module, "default_visibility", &module.properties.Default_visibility) + // The default_applicable_licenses property needs to be checked and parsed by the licenses module during + // its checking and parsing phases so make it the primary licenses property. + setPrimaryLicensesProperty(module, "default_applicable_licenses", &module.properties.Default_applicable_licenses) + return module } diff --git a/android/package_test.go b/android/package_test.go index ade95d42d..99be13ffa 100644 --- a/android/package_test.go +++ b/android/package_test.go @@ -17,9 +17,11 @@ var packageTests = []struct { package { name: "package", visibility: ["//visibility:private"], + licenses: ["license"], }`), }, expectedErrors: []string{ + `top/Blueprints:5:14: unrecognized property "licenses"`, `top/Blueprints:3:10: unrecognized property "name"`, `top/Blueprints:4:16: unrecognized property "visibility"`, }, @@ -44,9 +46,10 @@ var packageTests = []struct { "top/Blueprints": []byte(` package { default_visibility: ["//visibility:private"], + default_applicable_licenses: ["license"], } - package { + package { }`), }, expectedErrors: []string{ diff --git a/apex/androidmk.go b/apex/androidmk.go index e7f8b7ff1..0b114f83b 100644 --- a/apex/androidmk.go +++ b/apex/androidmk.go @@ -63,6 +63,16 @@ func (class apexFileClass) nameInMake() string { } } +// Return the full module name for a dependency module, which appends the apex module name unless re-using a system lib. +func (a *apexBundle) fullModuleName(apexBundleName string, fi *apexFile) string { + linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform() + + if linkToSystemLib { + return fi.androidMkModuleName + } + return fi.androidMkModuleName + "." + apexBundleName + a.suffix +} + func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, moduleDir string, apexAndroidMkData android.AndroidMkData) []string { @@ -114,12 +124,7 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform() - var moduleName string - if linkToSystemLib { - moduleName = fi.androidMkModuleName - } else { - moduleName = fi.androidMkModuleName + "." + apexBundleName + a.suffix - } + moduleName := a.fullModuleName(apexBundleName, &fi) if !android.InList(moduleName, moduleNames) { moduleNames = append(moduleNames, moduleName) @@ -311,14 +316,16 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo return moduleNames } -func (a *apexBundle) writeRequiredModules(w io.Writer) { +func (a *apexBundle) writeRequiredModules(w io.Writer, apexBundleName string) { var required []string var targetRequired []string var hostRequired []string + installMapSet := make(map[string]bool) // set of dependency module:location mappings for _, fi := range a.filesInfo { required = append(required, fi.requiredModuleNames...) targetRequired = append(targetRequired, fi.targetRequiredModuleNames...) hostRequired = append(hostRequired, fi.hostRequiredModuleNames...) + installMapSet[a.fullModuleName(apexBundleName, &fi)+":"+fi.installDir+"/"+fi.builtFile.Base()] = true } if len(required) > 0 { @@ -330,6 +337,11 @@ func (a *apexBundle) writeRequiredModules(w io.Writer) { if len(hostRequired) > 0 { fmt.Fprintln(w, "LOCAL_HOST_REQUIRED_MODULES +=", strings.Join(hostRequired, " ")) } + if len(installMapSet) > 0 { + var installs []string + installs = append(installs, android.SortedStringKeys(installMapSet)...) + fmt.Fprintln(w, "LOCAL_LICENSE_INSTALL_MAP +=", strings.Join(installs, " ")) + } } func (a *apexBundle) androidMkForType() android.AndroidMkData { @@ -347,16 +359,18 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData { fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)") fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir) fmt.Fprintln(w, "LOCAL_MODULE :=", name+a.suffix) + data.Entries.WriteLicenseVariables(w) if len(moduleNames) > 0 { fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(moduleNames, " ")) } - a.writeRequiredModules(w) + a.writeRequiredModules(w, name) fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)") } else { fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)") fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir) fmt.Fprintln(w, "LOCAL_MODULE :=", name+a.suffix) + data.Entries.WriteLicenseVariables(w) fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") // do we need a new class? fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFile.String()) fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", a.installDir.ToMakePath().String()) @@ -389,7 +403,7 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData { if len(a.requiredDeps) > 0 { fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(a.requiredDeps, " ")) } - a.writeRequiredModules(w) + a.writeRequiredModules(w, name) var postInstallCommands []string if a.prebuiltFileToDelete != "" { postInstallCommands = append(postInstallCommands, "rm -rf "+ diff --git a/bpf/bpf.go b/bpf/bpf.go index 297e13a4f..8142f10a5 100644 --- a/bpf/bpf.go +++ b/bpf/bpf.go @@ -120,6 +120,7 @@ func (bpf *bpf) AndroidMk() android.AndroidMkData { names = append(names, objName) fmt.Fprintln(w, "include $(CLEAR_VARS)") fmt.Fprintln(w, "LOCAL_MODULE := ", objName) + data.Entries.WriteLicenseVariables(w) fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", obj.String()) fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", obj.Base()) fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") @@ -129,6 +130,7 @@ func (bpf *bpf) AndroidMk() android.AndroidMkData { } fmt.Fprintln(w, "include $(CLEAR_VARS)") fmt.Fprintln(w, "LOCAL_MODULE := ", name) + data.Entries.WriteLicenseVariables(w) fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(names, " ")) fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)") }, diff --git a/java/system_modules.go b/java/system_modules.go index 7394fd547..5cc546d2e 100644 --- a/java/system_modules.go +++ b/java/system_modules.go @@ -192,6 +192,7 @@ func (system *SystemModules) AndroidMk() android.AndroidMkData { fmt.Fprintln(w, name+":", "$("+makevar+")") fmt.Fprintln(w, ".PHONY:", name) + // TODO(b/151177513): Licenses: Doesn't go through base_rules. May have to generate meta_lic and meta_module here. }, } } diff --git a/licenses/Android.bp b/licenses/Android.bp new file mode 100644 index 000000000..217792f23 --- /dev/null +++ b/licenses/Android.bp @@ -0,0 +1,1082 @@ +// +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_visibility: ["//visibility:public"], + default_applicable_licenses: ["Android-Apache-2.0"], +} + +license { + name: "Android-Apache-2.0", + license_kinds: ["SPDX-license-identifier-Apache-2.0"], + copyright_notice: "Copyright (C) The Android Open Source Project", + license_text: ["LICENSE"], +} + +license_kind { + name: "SPDX-license-identifier-AFL-1.1", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/AFL-1.1.html", +} + +license_kind { + name: "SPDX-license-identifier-AFL-1.2", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/AFL-1.2.html", +} + +license_kind { + name: "SPDX-license-identifier-AFL-2.0", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/AFL-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-AFL-2.1", + conditions: ["notice"], + url: "https://spdx.org/licenses/AFL-2.1.html", +} + +license_kind { + name: "SPDX-license-identifier-AFL-3.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/AFL-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-AGPL", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/AGPL.html", +} + +license_kind { + name: "SPDX-license-identifier-AGPL-1.0", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/AGPL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-AGPL-1.0-only", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/AGPL-1.0-only.html", +} + +license_kind { + name: "SPDX-license-identifier-AGPL-1.0-or-later", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/AGPL-1.0-or-later.html", +} + +license_kind { + name: "SPDX-license-identifier-AGPL-3.0", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/AGPL-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-AGPL-3.0-only", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/AGPL-3.0-only.html", +} + +license_kind { + name: "SPDX-license-identifier-AGPL-3.0-or-later", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/AGPL-3.0-or-later.html", +} + +license_kind { + name: "SPDX-license-identifier-Apache", + conditions: ["notice"], +} + +license_kind { + name: "SPDX-license-identifier-Apache-1.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/Apache-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-Apache-1.1", + conditions: ["notice"], + url: "https://spdx.org/licenses/Apache-1.1.html", +} + +license_kind { + name: "SPDX-license-identifier-Apache-2.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/Apache-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-Artistic", + conditions: ["notice"], +} + +license_kind { + name: "SPDX-license-identifier-Artistic-1.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/Artistic-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-Artistic-1.0-Perl", + conditions: ["notice"], + url: "https://spdx.org/licenses/Artistic-1.0-Perl.html", +} + +license_kind { + name: "SPDX-license-identifier-Artistic-1.0-cl8", + conditions: ["notice"], + url: "https://spdx.org/licenses/Artistic-1.0-cl8.html", +} + +license_kind { + name: "SPDX-license-identifier-Artistic-2.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/Artistic-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD", + conditions: ["notice"], +} + +license_kind { + name: "SPDX-license-identifier-BSD-1-Clause", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-1-Clause.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-2-Clause", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-2-Clause.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-2-Clause-FreeBSD", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-2-Clause-FreeBSD.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-2-Clause-NetBSD", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-2-Clause-NetBSD.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-2-Clause-Patent", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-2-Clause-Patent.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-3-Clause", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-3-Clause.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-3-Clause-Attribution", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-3-Clause-Attribution.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-3-Clause-Clear", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-3-Clause-Clear.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-3-Clause-LBNL", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-3-Clause-LBNL.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-3-Clause-No-Nuclear-License", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-3-Clause-No-Nuclear-License-2014", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License-2014.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-3-Clause-No-Nuclear-Warranty", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-Warranty.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-3-Clause-Open-MPI", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-3-Clause-Open-MPI.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-4-Clause", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-4-Clause.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-4-Clause-UC", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-4-Clause-UC.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-Protection", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-Protection.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-Source-Code", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-Source-Code.html", +} + +license_kind { + name: "SPDX-license-identifier-BSL-1.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-Beerware", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/Beerware.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY", + conditions: ["notice"], +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-1.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/CC-BY-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-2.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/CC-BY-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-2.5", + conditions: ["notice"], + url: "https://spdx.org/licenses/CC-BY-2.5.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-3.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/CC-BY-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-4.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/CC-BY-4.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC", + conditions: ["by_exception_only", "not_allowed"], +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-1.0", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/CC-BY-NC-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-2.0", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/CC-BY-NC-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-2.5", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/CC-BY-NC-2.5.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-3.0", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/CC-BY-NC-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-4.0", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/CC-BY-NC-4.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-ND-1.0", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/CC-BY-NC-ND-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-ND-2.0", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/CC-BY-NC-ND-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-ND-2.5", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/CC-BY-NC-ND-2.5.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-ND-3.0", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/CC-BY-NC-ND-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-ND-4.0", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/CC-BY-NC-ND-4.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-SA-1.0", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/CC-BY-NC-SA-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-SA-2.0", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/CC-BY-NC-SA-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-SA-2.5", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/CC-BY-NC-SA-2.5.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-SA-3.0", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/CC-BY-NC-SA-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-SA-4.0", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/CC-BY-NC-SA-4.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-ND", + conditions: ["restricted"], +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-ND-1.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-ND-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-ND-2.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-ND-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-ND-2.5", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-ND-2.5.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-ND-3.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-ND-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-ND-4.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-ND-4.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-SA", + conditions: ["restricted"], +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-SA-1.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-SA-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-SA-2.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-SA-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-SA-2.5", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-SA-2.5.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-SA-3.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-SA-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-SA-4.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-SA-4.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-SA-ND", + conditions: ["restricted"], +} + +license_kind { + name: "SPDX-license-identifier-CC0-1.0", + conditions: ["unencumbered"], + url: "https://spdx.org/licenses/CC0-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CPAL-1.0", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/CPAL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CPL-1.0", + conditions: ["reciprocal"], + url: "https://spdx.org/licenses/CPL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-EPL", + conditions: ["reciprocal"], +} + +license_kind { + name: "SPDX-license-identifier-EPL-1.0", + conditions: ["reciprocal"], + url: "https://spdx.org/licenses/EPL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-EPL-2.0", + conditions: ["reciprocal"], + url: "https://spdx.org/licenses/EPL-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-EUPL", + conditions: ["by_exception_only", "not_allowed"], +} + +license_kind { + name: "SPDX-license-identifier-EUPL-1.0", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/EUPL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-EUPL-1.1", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/EUPL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-EUPL-1.2", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/EUPL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-FTL", + conditions: ["notice"], + url: "https://spdx.org/licenses/FTL.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL", + conditions: ["restricted"], +} + +license_kind { + name: "SPDX-license-identifier-GPL-1.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-1.0+", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-1.0+.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-1.0-only", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-1.0-only.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-1.0-or-later", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-1.0-or-later.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-2.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-2.0+", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-2.0+.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-2.0-only", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-2.0-only.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-2.0-or-later", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-2.0-or-later.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-2.0-with-GCC-exception", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-2.0-with-GCC-exception.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-2.0-with-autoconf-exception", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-2.0-with-autoconf-exception.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-2.0-with-bison-exception", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-2.0-with-bison-exception.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-2.0-with-classpath-exception", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-2.0-with-classpath-exception.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-2.0-with-font-exception", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-2.0-with-font-exception.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-3.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-3.0+", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-3.0+.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-3.0-only", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-3.0-only.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-3.0-or-later", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-3.0-or-later.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-3.0-with-GCC-exception", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-3.0-with-GCC-exception.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-3.0-with-autoconf-exception", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-3.0-with-autoconf-exception.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-with-classpath-exception", + conditions: ["restricted"], +} + +license_kind { + name: "SPDX-license-identifier-HPND", + conditions: ["notice"], + url: "https://spdx.org/licenses/HPND.html", +} + +license_kind { + name: "SPDX-license-identifier-ICU", + conditions: ["notice"], + url: "https://spdx.org/licenses/ICU.html", +} + +license_kind { + name: "SPDX-license-identifier-ISC", + conditions: ["notice"], + url: "https://spdx.org/licenses/ISC.html", +} + +license_kind { + name: "SPDX-license-identifier-JSON", + conditions: ["notice"], + url: "https://spdx.org/licenses/JSON.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL", + conditions: ["restricted"], +} + +license_kind { + name: "SPDX-license-identifier-LGPL-2.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-2.0+", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-2.0+.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-2.0-only", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-2.0-only.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-2.0-or-later", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-2.0-or-later.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-2.1", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-2.1.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-2.1+", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-2.1+.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-2.1-only", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-2.1-only.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-2.1-or-later", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-2.1-or-later.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-3.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-3.0+", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-3.0+.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-3.0-only", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-3.0-only.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-3.0-or-later", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-3.0-or-later.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPLLR", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPLLR.html", +} + +license_kind { + name: "SPDX-license-identifier-LPL-1.02", + conditions: ["notice"], + url: "https://spdx.org/licenses/LPL-1.02.html", +} + +license_kind { + name: "SPDX-license-identifier-MIT", + conditions: ["notice"], +} + +license_kind { + name: "SPDX-license-identifier-MIT-0", + conditions: ["notice"], + url: "https://spdx.org/licenses/MIT-0.html", +} + +license_kind { + name: "SPDX-license-identifier-MIT-CMU", + conditions: ["notice"], + url: "https://spdx.org/licenses/MIT-CMU.html", +} + +license_kind { + name: "SPDX-license-identifier-MIT-advertising", + conditions: ["notice"], + url: "https://spdx.org/licenses/MIT-advertising.html", +} + +license_kind { + name: "SPDX-license-identifier-MIT-enna", + conditions: ["notice"], + url: "https://spdx.org/licenses/MIT-enna.html", +} + +license_kind { + name: "SPDX-license-identifier-MIT-feh", + conditions: ["notice"], + url: "https://spdx.org/licenses/MIT-feh.html", +} + +license_kind { + name: "SPDX-license-identifier-MITNFA", + conditions: ["notice"], + url: "https://spdx.org/licenses/MITNFA.html", +} + +license_kind { + name: "SPDX-license-identifier-MPL", + conditions: ["reciprocal"], +} + +license_kind { + name: "SPDX-license-identifier-MPL-1.0", + conditions: ["reciprocal"], + url: "https://spdx.org/licenses/MPL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-MPL-1.1", + conditions: ["reciprocal"], + url: "https://spdx.org/licenses/MPL-1.1.html", +} + +license_kind { + name: "SPDX-license-identifier-MPL-2.0", + conditions: ["reciprocal"], + url: "https://spdx.org/licenses/MPL-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-MPL-2.0-no-copyleft-exception", + conditions: ["reciprocal"], + url: "https://spdx.org/licenses/MPL-2.0-no-copyleft-exception.html", +} + +license_kind { + name: "SPDX-license-identifier-MS-PL", + conditions: ["notice"], + url: "https://spdx.org/licenses/MS-PL.html", +} + +license_kind { + name: "SPDX-license-identifier-NCSA", + conditions: ["notice"], + url: "https://spdx.org/licenses/NCSA.html", +} + +license_kind { + name: "SPDX-license-identifier-OFL", + conditions: ["by_exception_only"], +} + +license_kind { + name: "SPDX-license-identifier-OFL-1.0", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/OFL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-OFL-1.0-RFN", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/OFL-1.0-RFN.html", +} + +license_kind { + name: "SPDX-license-identifier-OFL-1.0-no-RFN", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/OFL-1.0-no-RFN.html", +} + +license_kind { + name: "SPDX-license-identifier-OFL-1.1", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/OFL-1.1.html", +} + +license_kind { + name: "SPDX-license-identifier-OFL-1.1-RFN", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/OFL-1.1-RFN.html", +} + +license_kind { + name: "SPDX-license-identifier-OFL-1.1-no-RFN", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/OFL-1.1-no-RFN.html", +} + +license_kind { + name: "SPDX-license-identifier-OpenSSL", + conditions: ["notice"], + url: "https://spdx.org/licenses/OpenSSL.html", +} + +license_kind { + name: "SPDX-license-identifier-PSF-2.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/PSF-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-SISSL", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/SISSL.html", +} + +license_kind { + name: "SPDX-license-identifier-SISSL-1.2", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/SISSL-1.2.html", +} + +license_kind { + name: "SPDX-license-identifier-SPL-1.0", + conditions: ["by_exception_only", "reciprocal"], + url: "https://spdx.org/licenses/SPL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-SSPL", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/SSPL.html", +} + +license_kind { + name: "SPDX-license-identifier-UPL-1.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/UPL-1.-.html", +} + +license_kind { + name: "SPDX-license-identifier-Unicode-DFS", + conditions: ["notice"], +} + +license_kind { + name: "SPDX-license-identifier-Unicode-DFS-2015", + conditions: ["notice"], + url: "https://spdx.org/licenses/Unicode-DFS-2015.html", +} + +license_kind { + name: "SPDX-license-identifier-Unicode-DFS-2016", + conditions: ["notice"], + url: "https://spdx.org/licenses/Unicode-DFS-2016.html", +} + +license_kind { + name: "SPDX-license-identifier-Unlicense", + conditions: ["unencumbered"], + url: "https://spdx.org/licenses/Unlicense.html", +} + +license_kind { + name: "SPDX-license-identifier-W3C", + conditions: ["notice"], + url: "https://spdx.org/licenses/W3C.html", +} + +license_kind { + name: "SPDX-license-identifier-W3C-19980720", + conditions: ["notice"], + url: "https://spdx.org/licenses/W3C-19980720.html", +} + +license_kind { + name: "SPDX-license-identifier-W3C-20150513", + conditions: ["notice"], + url: "https://spdx.org/licenses/W3C-20150513.html", +} + +license_kind { + name: "SPDX-license-identifier-WTFPL", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/WTFPL.html", +} + +license_kind { + name: "SPDX-license-identifier-Watcom-1.0", + conditions: ["by_exception_only", "not_allowed"], + url: "https://spdx.org/licenses/Watcom-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-Xnet", + conditions: ["notice"], + url: "https://spdx.org/licenses/Xnet.html", +} + +license_kind { + name: "SPDX-license-identifier-ZPL", + conditions: ["notice"], +} + +license_kind { + name: "SPDX-license-identifier-ZPL-1.1", + conditions: ["notice"], + url: "https://spdx.org/licenses/ZPL-1.1.html", +} + +license_kind { + name: "SPDX-license-identifier-ZPL-2.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/ZPL-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-ZPL-2.1", + conditions: ["notice"], + url: "https://spdx.org/licenses/ZPL-2.1.html", +} + +license_kind { + name: "SPDX-license-identifier-Zend-2.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/Zend-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-Zlib", + conditions: ["notice"], + url: "https://spdx.org/licenses/Zlib.html", +} + +license_kind { + name: "SPDX-license-identifier-libtiff", + conditions: ["notice"], + url: "https://spdx.org/licenses/libtiff.html", +} + + +// Legacy license kinds -- do not add new references -- use an spdx kind instead. +license_kind { + name: "legacy_unknown", + conditions: ["by_exception_only"], +} + +license_kind { + name: "legacy_unencumbered", + conditions: ["unencumbered"], +} + +license_kind { + name: "legacy_notice", + conditions: ["notice"], +} + +license_kind { + name: "legacy_reciprocal", + conditions: ["reciprocal"], +} + +license_kind { + name: "legacy_restricted", + conditions: ["restricted"], +} + +license_kind { + name: "legacy_by_exception_only", + conditions: ["by_exception_only"], +} + +license_kind { + name: "legacy_not_allowed", + conditions: ["by_exception_only", "not_allowed"], +} + +license_kind { + name: "legacy_proprietary", + conditions: ["by_exception_only", "not_allowed", "proprietary"], +} diff --git a/licenses/LICENSE b/licenses/LICENSE new file mode 100644 index 000000000..dae04065f --- /dev/null +++ b/licenses/LICENSE @@ -0,0 +1,214 @@ + + Copyright (c) The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/phony/phony.go b/phony/phony.go index cb60b9f9e..a31d402af 100644 --- a/phony/phony.go +++ b/phony/phony.go @@ -52,6 +52,7 @@ func (p *phony) AndroidMk() android.AndroidMkData { fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)") fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir) fmt.Fprintln(w, "LOCAL_MODULE :=", name) + data.Entries.WriteLicenseVariables(w) if p.Host() { fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true") } diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go index 42caff2c0..38306adfc 100644 --- a/sysprop/sysprop_library.go +++ b/sysprop/sysprop_library.go @@ -307,6 +307,7 @@ func (m *syspropLibrary) AndroidMk() android.AndroidMkData { // Actual implementation libraries are created on LoadHookMutator fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)") fmt.Fprintf(w, "LOCAL_MODULE := %s\n", m.Name()) + data.Entries.WriteLicenseVariables(w) fmt.Fprintf(w, "LOCAL_MODULE_CLASS := FAKE\n") fmt.Fprintf(w, "LOCAL_MODULE_TAGS := optional\n") fmt.Fprintf(w, "include $(BUILD_SYSTEM)/base_rules.mk\n\n")