Revert^2 "Add ability to declare licenses in soong."

df98d3e4a546a3a3e5e6aba5ca6151d00547ef20

Change-Id: Ie7e1695ecb8cd943124426a0cad2c0d1db2b46ed
diff --git a/android/Android.bp b/android/Android.bp
index f8c1d55..69aa037 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -30,6 +30,9 @@
         "filegroup.go",
         "hooks.go",
         "image.go",
+        "license.go",
+        "license_kind.go",
+        "licenses.go",
         "makefile_goal.go",
         "makevars.go",
         "metrics.go",
@@ -77,6 +80,9 @@
         "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/defaults.go b/android/defaults.go
index 44753ce..aacfbac 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -204,6 +204,9 @@
 	// 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 0000000..b140b55
--- /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 0000000..ddecd77
--- /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 0000000..767b64e
--- /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 0000000..552bbae
--- /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 0000000..1000429
--- /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 0000000..b94add7
--- /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 cfb32c1..b0ad89b 100644
--- a/android/module.go
+++ b/android/module.go
@@ -619,6 +619,20 @@
 	// 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 @@
 	// 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 @@
 	// 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 @@
 			}
 		}
 
+		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 31edea3..72c68b2 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -115,6 +115,11 @@
 	//
 	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 @@
 	// 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 @@
 	registerPathDepsMutator,
 	RegisterPrebuiltsPostDepsMutators,
 	RegisterVisibilityRuleEnforcer,
+	RegisterLicensesDependencyChecker,
 	RegisterNeverallowMutator,
 	RegisterOverridePostDepsMutators,
 }
diff --git a/android/package.go b/android/package.go
index 182b3ed..7012fc7 100644
--- a/android/package.go
+++ b/android/package.go
@@ -31,6 +31,8 @@
 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 @@
 	// 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 ade95d4..99be13f 100644
--- a/android/package_test.go
+++ b/android/package_test.go
@@ -17,9 +17,11 @@
 				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 @@
 			"top/Blueprints": []byte(`
 				package {
 					default_visibility: ["//visibility:private"],
+					default_applicable_licenses: ["license"],
 				}
 
-        package {
+			        package {
 				}`),
 		},
 		expectedErrors: []string{