Merge "Do not read 'vendor_available: false'"
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/androidmk.go b/android/androidmk.go
index 73f60d0..5856851 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -28,6 +28,7 @@
 	"io/ioutil"
 	"os"
 	"path/filepath"
+	"reflect"
 	"sort"
 	"strings"
 
@@ -434,6 +435,17 @@
 	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 @@
 	// 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 @@
 		}
 	}()
 
+	// 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 @@
 	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 @@
 	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 @@
 	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 @@
 		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 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{
diff --git a/apex/Android.bp b/apex/Android.bp
index 9e8c30d..e3a547c 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -7,6 +7,7 @@
         "soong-android",
         "soong-bpf",
         "soong-cc",
+        "soong-filesystem",
         "soong-java",
         "soong-python",
         "soong-rust",
diff --git a/apex/androidmk.go b/apex/androidmk.go
index e7f8b7f..0b114f8 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -63,6 +63,16 @@
 	}
 }
 
+// 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 @@
 
 		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 @@
 	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 @@
 	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 @@
 				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 @@
 				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/apex/apex.go b/apex/apex.go
index 2182069..a18e34b 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -30,6 +30,7 @@
 	"android/soong/bpf"
 	"android/soong/cc"
 	prebuilt_etc "android/soong/etc"
+	"android/soong/filesystem"
 	"android/soong/java"
 	"android/soong/python"
 	"android/soong/rust"
@@ -96,6 +97,9 @@
 	// List of BPF programs inside this APEX bundle.
 	Bpfs []string
 
+	// List of filesystem images that are embedded inside this APEX bundle.
+	Filesystems []string
+
 	// Name of the apex_key module that provides the private key to sign this APEX bundle.
 	Key *string
 
@@ -530,6 +534,7 @@
 	bpfTag         = dependencyTag{name: "bpf", payload: true}
 	certificateTag = dependencyTag{name: "certificate"}
 	executableTag  = dependencyTag{name: "executable", payload: true}
+	fsTag          = dependencyTag{name: "filesystem", payload: true}
 	javaLibTag     = dependencyTag{name: "javaLib", payload: true}
 	jniLibTag      = dependencyTag{name: "jniLib", payload: true}
 	keyTag         = dependencyTag{name: "key"}
@@ -709,6 +714,7 @@
 	commonVariation := ctx.Config().AndroidCommonTarget.Variations()
 	ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
 	ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.properties.Bpfs...)
+	ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
 
 	// With EMMA_INSTRUMENT_FRAMEWORK=true the ART boot image includes jacoco library.
 	if a.artApex && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
@@ -1481,6 +1487,11 @@
 	return newApexFile(ctx, builtFile, builtFile.Base(), dirInApex, etc, bpfProgram)
 }
 
+func apexFileForFilesystem(ctx android.BaseModuleContext, buildFile android.Path, fs filesystem.Filesystem) apexFile {
+	dirInApex := filepath.Join("etc", "fs")
+	return newApexFile(ctx, buildFile, buildFile.Base(), dirInApex, etc, fs)
+}
+
 // WalyPayloadDeps visits dependencies that contributes to the payload of this APEX. For each of the
 // visited module, the `do` callback is executed. Returning true in the callback continues the visit
 // to the child modules. Returning false makes the visit to continue in the sibling or the parent
@@ -1655,6 +1666,12 @@
 				} else {
 					ctx.PropertyErrorf("bpfs", "%q is not a bpf module", depName)
 				}
+			case fsTag:
+				if fs, ok := child.(filesystem.Filesystem); ok {
+					filesInfo = append(filesInfo, apexFileForFilesystem(ctx, fs.OutputPath(), fs))
+				} else {
+					ctx.PropertyErrorf("filesystems", "%q is not a filesystem module", depName)
+				}
 			case prebuiltTag:
 				if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
 					filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 9d43348..fc74672 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -250,7 +250,7 @@
 
 	ctx.RegisterModuleType("cc_test", cc.TestFactory)
 	ctx.RegisterModuleType("vndk_prebuilt_shared", cc.VndkPrebuiltSharedFactory)
-	ctx.RegisterModuleType("vndk_libraries_txt", cc.VndkLibrariesTxtFactory)
+	cc.RegisterVndkLibraryTxtTypes(ctx)
 	prebuilt_etc.RegisterPrebuiltEtcBuildComponents(ctx)
 	ctx.RegisterModuleType("platform_compat_config", java.PlatformCompatConfigFactory)
 	ctx.RegisterModuleType("sh_binary", sh.ShBinaryFactory)
@@ -3219,7 +3219,7 @@
 		if v == "current" {
 			for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate", "vndkproduct"} {
 				result += `
-					vndk_libraries_txt {
+					` + txt + `_libraries_txt {
 						name: "` + txt + `.libraries.txt",
 					}
 				`
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 297e13a..8142f10 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -120,6 +120,7 @@
 				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 @@
 			}
 			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/cc/cc_test.go b/cc/cc_test.go
index 09b728e..3502d5f 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -415,23 +415,24 @@
 			},
 		}
 
-		vndk_libraries_txt {
+		llndk_libraries_txt {
 			name: "llndk.libraries.txt",
 		}
-		vndk_libraries_txt {
+		vndkcore_libraries_txt {
 			name: "vndkcore.libraries.txt",
 		}
-		vndk_libraries_txt {
+		vndksp_libraries_txt {
 			name: "vndksp.libraries.txt",
 		}
-		vndk_libraries_txt {
+		vndkprivate_libraries_txt {
 			name: "vndkprivate.libraries.txt",
 		}
-		vndk_libraries_txt {
+		vndkproduct_libraries_txt {
 			name: "vndkproduct.libraries.txt",
 		}
-		vndk_libraries_txt {
+		vndkcorevariant_libraries_txt {
 			name: "vndkcorevariant.libraries.txt",
+			insert_vndk_version: false,
 		}
 	`
 
@@ -543,7 +544,7 @@
 			}
 		}
 
-		vndk_libraries_txt {
+		vndkcore_libraries_txt {
 			name: "vndkcore.libraries.txt",
 		}
 	`)
@@ -553,8 +554,9 @@
 
 func TestVndkLibrariesTxtAndroidMk(t *testing.T) {
 	bp := `
-		vndk_libraries_txt {
+		llndk_libraries_txt {
 			name: "llndk.libraries.txt",
+			insert_vndk_version: true,
 		}`
 	config := TestConfig(buildDir, android.Android, nil, bp, nil)
 	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
@@ -600,8 +602,9 @@
 			nocrt: true,
 		}
 
-		vndk_libraries_txt {
+		vndkcorevariant_libraries_txt {
 			name: "vndkcorevariant.libraries.txt",
+			insert_vndk_version: false,
 		}
 	`
 
@@ -1243,6 +1246,15 @@
 			t.Errorf("%q expected but not found", jsonFile)
 		}
 	}
+
+	// fake snapshot should have all outputs in the normal snapshot.
+	fakeSnapshotSingleton := ctx.SingletonForTests("vendor-fake-snapshot")
+	for _, output := range snapshotSingleton.AllOutputs() {
+		fakeOutput := strings.Replace(output, "/vendor-snapshot/", "/fake/vendor-snapshot/", 1)
+		if fakeSnapshotSingleton.MaybeOutput(fakeOutput).Rule == nil {
+			t.Errorf("%q expected but not found", fakeOutput)
+		}
+	}
 }
 
 func TestVendorSnapshotUse(t *testing.T) {
@@ -1674,6 +1686,8 @@
 		`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
 		`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
 		`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
+		`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
+		`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
 	})
 }
 
@@ -1717,6 +1731,10 @@
 		`module "libinclude\{.+,image:,arch:arm_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
 		`module "libinclude\{.+,image:vendor.+,arch:arm64_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
 		`module "libinclude\{.+,image:vendor.+,arch:arm_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
+		`module "libinclude\{.+,image:,arch:arm64_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
+		`module "libinclude\{.+,image:,arch:arm_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
+		`module "libinclude\{.+,image:vendor.+,arch:arm64_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
+		`module "libinclude\{.+,image:vendor.+,arch:arm_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
 	})
 }
 
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index 8c5d1a4..e3f3a4d 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -94,6 +94,8 @@
 	android.RegisterModuleType("vendor_snapshot_header", VendorSnapshotHeaderFactory)
 	android.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory)
 	android.RegisterModuleType("vendor_snapshot_object", VendorSnapshotObjectFactory)
+
+	android.RegisterSingletonType("vendor-fake-snapshot", VendorFakeSnapshotSingleton)
 }
 
 func (vendorSnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) bool {
diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go
index 77d82f1..3e6444b 100644
--- a/cc/snapshot_utils.go
+++ b/cc/snapshot_utils.go
@@ -77,9 +77,12 @@
 	}
 	if _, _, ok := isVndkSnapshotAware(ctx.DeviceConfig(), m, apexInfo); ok {
 		return ctx.Config().VndkSnapshotBuildArtifacts()
-	} else if isVendorSnapshotAware(m, isVendorProprietaryPath(ctx.ModuleDir()), apexInfo) ||
-		isRecoverySnapshotAware(m, isRecoveryProprietaryPath(ctx.ModuleDir()), apexInfo) {
-		return true
+	}
+
+	for _, image := range []snapshotImage{vendorSnapshotImageSingleton, recoverySnapshotImageSingleton} {
+		if isSnapshotAware(m, image.isProprietaryPath(ctx.ModuleDir()), apexInfo, image) {
+			return true
+		}
 	}
 	return false
 }
diff --git a/cc/testing.go b/cc/testing.go
index a69e03e..8d92ea2 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -568,15 +568,16 @@
 	ctx.RegisterModuleType("vendor_public_library", vendorPublicLibraryFactory)
 	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
 	ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
-	ctx.RegisterModuleType("vndk_libraries_txt", VndkLibrariesTxtFactory)
 	ctx.RegisterModuleType("vendor_snapshot_shared", VendorSnapshotSharedFactory)
 	ctx.RegisterModuleType("vendor_snapshot_static", VendorSnapshotStaticFactory)
 	ctx.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory)
+	RegisterVndkLibraryTxtTypes(ctx)
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
 	android.RegisterPrebuiltMutators(ctx)
 	RegisterRequiredBuildComponentsForTest(ctx)
 	ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
 	ctx.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
+	ctx.RegisterSingletonType("vendor-fake-snapshot", VendorFakeSnapshotSingleton)
 	ctx.RegisterSingletonType("recovery-snapshot", RecoverySnapshotSingleton)
 
 	return ctx
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 417516b..622ebec 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -34,6 +34,16 @@
 	android.OptionalPath{},
 	true,
 	vendorSnapshotImageSingleton,
+	false, /* fake */
+}
+
+var vendorFakeSnapshotSingleton = snapshotSingleton{
+	"vendor",
+	"SOONG_VENDOR_FAKE_SNAPSHOT_ZIP",
+	android.OptionalPath{},
+	true,
+	vendorSnapshotImageSingleton,
+	true, /* fake */
 }
 
 var recoverySnapshotSingleton = snapshotSingleton{
@@ -42,12 +52,17 @@
 	android.OptionalPath{},
 	false,
 	recoverySnapshotImageSingleton,
+	false, /* fake */
 }
 
 func VendorSnapshotSingleton() android.Singleton {
 	return &vendorSnapshotSingleton
 }
 
+func VendorFakeSnapshotSingleton() android.Singleton {
+	return &vendorFakeSnapshotSingleton
+}
+
 func RecoverySnapshotSingleton() android.Singleton {
 	return &recoverySnapshotSingleton
 }
@@ -70,6 +85,11 @@
 	// associated with this snapshot (e.g., specific to the vendor image,
 	// recovery image, etc.).
 	image snapshotImage
+
+	// Whether this singleton is for fake snapshot or not.
+	// Fake snapshot is a snapshot whose prebuilt binaries and headers are empty.
+	// It is much faster to generate, and can be used to inspect dependencies.
+	fake bool
 }
 
 var (
@@ -177,25 +197,6 @@
 	return false
 }
 
-// Determine if a module is going to be included in vendor snapshot or not.
-//
-// Targets of vendor snapshot are "vendor: true" or "vendor_available: true" modules in
-// AOSP. They are not guaranteed to be compatible with older vendor images. (e.g. might
-// depend on newer VNDK) So they are captured as vendor snapshot To build older vendor
-// image and newer system image altogether.
-func isVendorSnapshotAware(m *Module, inVendorProprietaryPath bool, apexInfo android.ApexInfo) bool {
-	return isSnapshotAware(m, inVendorProprietaryPath, apexInfo, vendorSnapshotImageSingleton)
-}
-
-// Determine if a module is going to be included in recovery snapshot or not.
-//
-// Targets of recovery snapshot are "recovery: true" or "recovery_available: true"
-// modules in AOSP. They are not guaranteed to be compatible with older recovery images.
-// So they are captured as recovery snapshot To build older recovery image.
-func isRecoverySnapshotAware(m *Module, inRecoveryProprietaryPath bool, apexInfo android.ApexInfo) bool {
-	return isSnapshotAware(m, inRecoveryProprietaryPath, apexInfo, recoverySnapshotImageSingleton)
-}
-
 // Determines if the module is a candidate for snapshot.
 func isSnapshotAware(m *Module, inProprietaryPath bool, apexInfo android.ApexInfo, image snapshotImage) bool {
 	if !m.Enabled() || m.Properties.HideFromMake {
@@ -351,6 +352,11 @@
 	*/
 
 	snapshotDir := c.name + "-snapshot"
+	if c.fake {
+		// If this is a fake snapshot singleton, place all files under fake/ subdirectory to avoid
+		// collision with real snapshot files
+		snapshotDir = filepath.Join("fake", snapshotDir)
+	}
 	snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
 
 	includeDir := filepath.Join(snapshotArchDir, "include")
@@ -362,6 +368,15 @@
 
 	var headers android.Paths
 
+	copyFile := copyFileRule
+	if c.fake {
+		// All prebuilt binaries and headers are installed by copyFile function. This makes a fake
+		// snapshot just touch prebuilts and headers, rather than installing real files.
+		copyFile = func(ctx android.SingletonContext, path android.Path, out string) android.OutputPath {
+			return writeStringToFileRule(ctx, "", out)
+		}
+	}
+
 	// installSnapshot function copies prebuilt file (.so, .a, or executable) and json flag file.
 	// For executables, init_rc and vintf_fragments files are also copied.
 	installSnapshot := func(m *Module) android.Paths {
@@ -400,7 +415,7 @@
 			out := filepath.Join(configsDir, path.Base())
 			if !installedConfigs[out] {
 				installedConfigs[out] = true
-				ret = append(ret, copyFileRule(ctx, path, out))
+				ret = append(ret, copyFile(ctx, path, out))
 			}
 		}
 
@@ -451,7 +466,7 @@
 					prop.ModuleName += ".cfi"
 				}
 				snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, stem)
-				ret = append(ret, copyFileRule(ctx, libPath, snapshotLibOut))
+				ret = append(ret, copyFile(ctx, libPath, snapshotLibOut))
 			} else {
 				stem = ctx.ModuleName(m)
 			}
@@ -465,7 +480,7 @@
 			// install bin
 			binPath := m.outputFile.Path()
 			snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base())
-			ret = append(ret, copyFileRule(ctx, binPath, snapshotBinOut))
+			ret = append(ret, copyFile(ctx, binPath, snapshotBinOut))
 			propOut = snapshotBinOut + ".json"
 		} else if m.object() {
 			// object files aren't installed to the device, so their names can conflict.
@@ -473,7 +488,7 @@
 			objPath := m.outputFile.Path()
 			snapshotObjOut := filepath.Join(snapshotArchDir, targetArch, "object",
 				ctx.ModuleName(m)+filepath.Ext(objPath.Base()))
-			ret = append(ret, copyFileRule(ctx, objPath, snapshotObjOut))
+			ret = append(ret, copyFile(ctx, objPath, snapshotObjOut))
 			propOut = snapshotObjOut + ".json"
 		} else {
 			ctx.Errorf("unknown module %q in vendor snapshot", m.String())
@@ -538,16 +553,14 @@
 			// skip already copied notice file
 			if !installedNotices[noticeOut] {
 				installedNotices[noticeOut] = true
-				snapshotOutputs = append(snapshotOutputs, combineNoticesRule(
-					ctx, m.NoticeFiles(), noticeOut))
+				snapshotOutputs = append(snapshotOutputs, combineNoticesRule(ctx, m.NoticeFiles(), noticeOut))
 			}
 		}
 	})
 
 	// install all headers after removing duplicates
 	for _, header := range android.FirstUniquePaths(headers) {
-		snapshotOutputs = append(snapshotOutputs, copyFileRule(
-			ctx, header, filepath.Join(includeDir, header.String())))
+		snapshotOutputs = append(snapshotOutputs, copyFile(ctx, header, filepath.Join(includeDir, header.String())))
 	}
 
 	// All artifacts are ready. Sort them to normalize ninja and then zip.
diff --git a/cc/vndk.go b/cc/vndk.go
index cb29d12..c1264f7 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -449,15 +449,32 @@
 }
 
 func init() {
-	android.RegisterModuleType("vndk_libraries_txt", VndkLibrariesTxtFactory)
+	RegisterVndkLibraryTxtTypes(android.InitRegistrationContext)
 	android.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
 }
 
+func RegisterVndkLibraryTxtTypes(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("llndk_libraries_txt", VndkLibrariesTxtFactory(libclangRTRemover(llndkLibraries)))
+	ctx.RegisterModuleType("vndksp_libraries_txt", VndkLibrariesTxtFactory(vndkSpLibraries))
+	ctx.RegisterModuleType("vndkcore_libraries_txt", VndkLibrariesTxtFactory(vndkCoreLibraries))
+	ctx.RegisterModuleType("vndkprivate_libraries_txt", VndkLibrariesTxtFactory(vndkPrivateLibraries))
+	ctx.RegisterModuleType("vndkproduct_libraries_txt", VndkLibrariesTxtFactory(vndkProductLibraries))
+	ctx.RegisterModuleType("vndkcorevariant_libraries_txt", VndkLibrariesTxtFactory(vndkUsingCoreVariantLibraries))
+}
+
 type vndkLibrariesTxt struct {
 	android.ModuleBase
+
+	lister     func(android.Config) map[string]string
+	properties VndkLibrariesTxtProperties
+
 	outputFile android.OutputPath
 }
 
+type VndkLibrariesTxtProperties struct {
+	Insert_vndk_version *bool
+}
+
 var _ etc.PrebuiltEtcModule = &vndkLibrariesTxt{}
 var _ android.OutputFileProducer = &vndkLibrariesTxt{}
 
@@ -471,10 +488,15 @@
 // A module behaves like a prebuilt_etc but its content is generated by soong.
 // By being a soong module, these files can be referenced by other soong modules.
 // For example, apex_vndk can depend on these files as prebuilt.
-func VndkLibrariesTxtFactory() android.Module {
-	m := &vndkLibrariesTxt{}
-	android.InitAndroidModule(m)
-	return m
+func VndkLibrariesTxtFactory(lister func(android.Config) map[string]string) android.ModuleFactory {
+	return func() android.Module {
+		m := &vndkLibrariesTxt{
+			lister: lister,
+		}
+		m.AddProperties(&m.properties)
+		android.InitAndroidModule(m)
+		return m
+	}
 }
 
 func insertVndkVersion(filename string, vndkVersion string) string {
@@ -484,33 +506,25 @@
 	return filename
 }
 
-func (txt *vndkLibrariesTxt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	var list []string
-	switch txt.Name() {
-	case llndkLibrariesTxt:
-		for _, filename := range android.SortedStringMapValues(llndkLibraries(ctx.Config())) {
-			if strings.HasPrefix(filename, "libclang_rt.hwasan-") {
+func libclangRTRemover(lister func(android.Config) map[string]string) func(android.Config) map[string]string {
+	return func(config android.Config) map[string]string {
+		libs := lister(config)
+		filteredLibs := make(map[string]string, len(libs))
+		for lib, v := range libs {
+			if strings.HasPrefix(lib, "libclang_rt.hwasan-") {
 				continue
 			}
-			list = append(list, filename)
+			filteredLibs[lib] = v
 		}
-	case vndkCoreLibrariesTxt:
-		list = android.SortedStringMapValues(vndkCoreLibraries(ctx.Config()))
-	case vndkSpLibrariesTxt:
-		list = android.SortedStringMapValues(vndkSpLibraries(ctx.Config()))
-	case vndkPrivateLibrariesTxt:
-		list = android.SortedStringMapValues(vndkPrivateLibraries(ctx.Config()))
-	case vndkProductLibrariesTxt:
-		list = android.SortedStringMapValues(vndkProductLibraries(ctx.Config()))
-	case vndkUsingCoreVariantLibrariesTxt:
-		list = android.SortedStringMapValues(vndkUsingCoreVariantLibraries(ctx.Config()))
-	default:
-		ctx.ModuleErrorf("name(%s) is unknown.", txt.Name())
-		return
+		return filteredLibs
 	}
+}
+
+func (txt *vndkLibrariesTxt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	list := android.SortedStringMapValues(txt.lister(ctx.Config()))
 
 	var filename string
-	if txt.Name() != vndkUsingCoreVariantLibrariesTxt {
+	if BoolDefault(txt.properties.Insert_vndk_version, true) {
 		filename = insertVndkVersion(txt.Name(), ctx.DeviceConfig().PlatformVndkVersion())
 	} else {
 		filename = txt.Name()
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index c6181bc..2b3fbae 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -46,7 +46,10 @@
 	return module
 }
 
-var dependencyTag = struct{ blueprint.BaseDependencyTag }{}
+var dependencyTag = struct {
+	blueprint.BaseDependencyTag
+	android.InstallAlwaysNeededDependencyTag
+}{}
 
 func (f *filesystem) DepsMutator(ctx android.BottomUpMutatorContext) {
 	f.AddDeps(ctx, dependencyTag)
@@ -80,7 +83,7 @@
 		Text(">").Output(propFile).
 		Implicit(mkuserimg)
 
-	f.output = android.PathForModuleOut(ctx, "filesystem.img").OutputPath
+	f.output = android.PathForModuleOut(ctx, f.installFileName()).OutputPath
 	builder.Command().BuiltTool("build_image").
 		Text(rootDir.String()). // input directory
 		Input(propFile).
@@ -109,3 +112,16 @@
 		},
 	}}
 }
+
+// Filesystem is the public interface for the filesystem struct. Currently, it's only for the apex
+// package to have access to the output file.
+type Filesystem interface {
+	android.Module
+	OutputPath() android.Path
+}
+
+var _ Filesystem = (*filesystem)(nil)
+
+func (f *filesystem) OutputPath() android.Path {
+	return f.output
+}
diff --git a/java/system_modules.go b/java/system_modules.go
index 7394fd5..5cc546d 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -192,6 +192,7 @@
 
 			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 0000000..217792f
--- /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 0000000..dae0406
--- /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 cb60b9f..a31d402 100644
--- a/phony/phony.go
+++ b/phony/phony.go
@@ -52,6 +52,7 @@
 			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/rust/config/global.go b/rust/config/global.go
index 22d9567..b7fff4a 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -44,6 +44,7 @@
 	GlobalRustFlags = []string{
 		"--remap-path-prefix $$(pwd)=",
 		"-C codegen-units=1",
+		"-C debuginfo=2",
 		"-C opt-level=3",
 		"-C relocation-model=pic",
 	}
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 42caff2..38306ad 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -307,6 +307,7 @@
 			// 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")