Add gen_notice module.

Refactor notices to support notices for multiple modules.

Enforce visibility and handle missing dependencies.

Test: m cts dist reportmissinglicenses

Test: m droid dist

Bug: 213388645
Bug: 240342946

Change-Id: Id6a81987f087419ad37d0cce57a71e8a7c4cd6e0
Merged-in: Id6a81987f087419ad37d0cce57a71e8a7c4cd6e0
Merged-in: I07963c83eaddfe363a04871e813b56fe7f1465ad
Merged-in: Ib2f8d0ad46ffe795d392166a74a7c6309b1246e2
Merged-in: I1d630c3d14d27b7605ab13d204d34b6851a24d33
diff --git a/android/Android.bp b/android/Android.bp
index d583703..65332b2 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -49,6 +49,7 @@
         "expand.go",
         "filegroup.go",
         "fixture.go",
+        "gen_notice.go",
         "hooks.go",
         "image.go",
         "license.go",
@@ -106,6 +107,7 @@
         "deptag_test.go",
         "expand_test.go",
         "fixture_test.go",
+        "gen_notice_test.go",
         "license_kind_test.go",
         "license_test.go",
         "licenses_test.go",
diff --git a/android/gen_notice.go b/android/gen_notice.go
new file mode 100644
index 0000000..e2b839f
--- /dev/null
+++ b/android/gen_notice.go
@@ -0,0 +1,212 @@
+// 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 (
+	"fmt"
+	"strings"
+
+	"github.com/google/blueprint/proptools"
+)
+
+func init() {
+	RegisterGenNoticeBuildComponents(InitRegistrationContext)
+}
+
+// Register the gen_notice module type.
+func RegisterGenNoticeBuildComponents(ctx RegistrationContext) {
+	ctx.RegisterSingletonType("gen_notice_build_rules", GenNoticeBuildRulesFactory)
+	ctx.RegisterModuleType("gen_notice", GenNoticeFactory)
+}
+
+type genNoticeBuildRules struct{}
+
+func (s *genNoticeBuildRules) GenerateBuildActions(ctx SingletonContext) {
+	ctx.VisitAllModules(func(m Module) {
+		gm, ok := m.(*genNoticeModule)
+		if !ok {
+			return
+		}
+		if len(gm.missing) > 0 {
+			missingReferencesRule(ctx, gm)
+			return
+		}
+		out := BuildNoticeTextOutputFromLicenseMetadata
+		if proptools.Bool(gm.properties.Xml) {
+			out = BuildNoticeXmlOutputFromLicenseMetadata
+		} else if proptools.Bool(gm.properties.Html) {
+			out = BuildNoticeHtmlOutputFromLicenseMetadata
+		}
+		defaultName := ""
+		if len(gm.properties.For) > 0 {
+			defaultName = gm.properties.For[0]
+		}
+
+		modules := make([]Module, 0)
+		for _, name := range gm.properties.For {
+			mods := ctx.ModuleVariantsFromName(gm, name)
+			for _, mod := range mods {
+				if mod == nil {
+					continue
+				}
+				modules = append(modules, mod)
+			}
+		}
+		if ctx.Failed() {
+			return
+		}
+		out(ctx, gm.output, ctx.ModuleName(gm),
+			proptools.StringDefault(gm.properties.ArtifactName, defaultName),
+			[]string{
+				ctx.Config().OutDir() + "/",
+				ctx.Config().SoongOutDir() + "/",
+			}, modules...)
+	})
+}
+
+func GenNoticeBuildRulesFactory() Singleton {
+	return &genNoticeBuildRules{}
+}
+
+type genNoticeProperties struct {
+	// For specifies the modules for which to generate a notice file.
+	For []string
+	// ArtifactName specifies the internal name to use for the notice file.
+	// It appears in the "used by:" list for targets whose entire name is stripped by --strip_prefix.
+	ArtifactName *string
+	// Stem specifies the base name of the output file.
+	Stem *string `android:"arch_variant"`
+	// Html indicates an html-format file is needed. The default is text. Can be Html or Xml but not both.
+	Html *bool
+	// Xml indicates an xml-format file is needed. The default is text. Can be Html or Xml but not both.
+	Xml *bool
+	// Gzipped indicates the output file must be compressed with gzip. Will append .gz to suffix if not there.
+	Gzipped *bool
+	// Suffix specifies the file extension to use. Defaults to .html for html, .xml for xml, or no extension for text.
+	Suffix *string
+	// Visibility specifies where this license can be used
+	Visibility []string
+}
+
+type genNoticeModule struct {
+	ModuleBase
+	DefaultableModuleBase
+
+	properties genNoticeProperties
+
+	output  OutputPath
+	missing []string
+}
+
+func (m *genNoticeModule) DepsMutator(ctx BottomUpMutatorContext) {
+	if proptools.Bool(m.properties.Html) && proptools.Bool(m.properties.Xml) {
+		ctx.ModuleErrorf("can be html or xml but not both")
+	}
+	if !ctx.Config().AllowMissingDependencies() {
+		var missing []string
+		// Verify the modules for which to generate notices exist.
+		for _, otherMod := range m.properties.For {
+			if !ctx.OtherModuleExists(otherMod) {
+				missing = append(missing, otherMod)
+			}
+		}
+		if len(missing) == 1 {
+			ctx.PropertyErrorf("for", "no %q module exists", missing[0])
+		} else if len(missing) > 1 {
+			ctx.PropertyErrorf("for", "modules \"%s\" do not exist", strings.Join(missing, "\", \""))
+		}
+	}
+}
+
+func (m *genNoticeModule) getStem() string {
+	stem := m.base().BaseModuleName()
+	if m.properties.Stem != nil {
+		stem = proptools.String(m.properties.Stem)
+	}
+	return stem
+}
+
+func (m *genNoticeModule) getSuffix() string {
+	suffix := ""
+	if m.properties.Suffix == nil {
+		if proptools.Bool(m.properties.Html) {
+			suffix = ".html"
+		} else if proptools.Bool(m.properties.Xml) {
+			suffix = ".xml"
+		}
+	} else {
+		suffix = proptools.String(m.properties.Suffix)
+	}
+	if proptools.Bool(m.properties.Gzipped) && !strings.HasSuffix(suffix, ".gz") {
+		suffix += ".gz"
+	}
+	return suffix
+}
+
+func (m *genNoticeModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+	if ctx.Config().AllowMissingDependencies() {
+		// Verify the modules for which to generate notices exist.
+		for _, otherMod := range m.properties.For {
+			if !ctx.OtherModuleExists(otherMod) {
+				m.missing = append(m.missing, otherMod)
+			}
+		}
+		m.missing = append(m.missing, ctx.GetMissingDependencies()...)
+		m.missing = FirstUniqueStrings(m.missing)
+	}
+	out := m.getStem() + m.getSuffix()
+	m.output = PathForModuleOut(ctx, out).OutputPath
+}
+
+func GenNoticeFactory() Module {
+	module := &genNoticeModule{}
+
+	base := module.base()
+	module.AddProperties(&base.nameProperties, &module.properties)
+
+	// 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
+}
+
+var _ OutputFileProducer = (*genNoticeModule)(nil)
+
+// Implements OutputFileProducer
+func (m *genNoticeModule) OutputFiles(tag string) (Paths, error) {
+	if tag == "" {
+		return Paths{m.output}, nil
+	}
+	return nil, fmt.Errorf("unrecognized tag %q", tag)
+}
+
+// missingReferencesRule emits an ErrorRule for missing module references.
+func missingReferencesRule(ctx BuilderContext, m *genNoticeModule) {
+	if len(m.missing) < 1 {
+		panic(fmt.Errorf("missing references rule requested with no missing references"))
+	}
+
+	ctx.Build(pctx, BuildParams{
+		Rule:        ErrorRule,
+		Output:      m.output,
+		Description: "notice for " + proptools.StringDefault(m.properties.ArtifactName, "container"),
+		Args: map[string]string{
+			"error": m.Name() + " references missing module(s): " + strings.Join(m.missing, ", "),
+		},
+	})
+}
diff --git a/android/gen_notice_test.go b/android/gen_notice_test.go
new file mode 100644
index 0000000..4ad2ecf
--- /dev/null
+++ b/android/gen_notice_test.go
@@ -0,0 +1,164 @@
+package android
+
+import (
+	"testing"
+
+	"github.com/google/blueprint"
+)
+
+var genNoticeTests = []struct {
+	name           string
+	fs             MockFS
+	expectedErrors []string
+}{
+	{
+		name: "gen_notice must not accept licenses property",
+		fs: map[string][]byte{
+			"top/Android.bp": []byte(`
+				gen_notice {
+					name: "top_license",
+					licenses: ["other_license"],
+				}`),
+		},
+		expectedErrors: []string{
+			`unrecognized property "licenses"`,
+		},
+	},
+	{
+		name: "bad gen_notice",
+		fs: map[string][]byte{
+			"top/Android.bp": []byte(`
+				gen_notice {
+					name: "top_notice",
+					for: ["top_rule"],
+				}`),
+			"other/Android.bp": []byte(`
+				mock_genrule {
+					name: "other_rule",
+					dep: ["top_notice"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "top_notice": for: no "top_rule" module exists`,
+		},
+	},
+	{
+		name: "doubly bad gen_notice",
+		fs: map[string][]byte{
+			"top/Android.bp": []byte(`
+				gen_notice {
+					name: "top_notice",
+					for: ["top_rule", "other_rule"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "top_notice": for: modules "top_rule", "other_rule" do not exist`,
+		},
+	},
+	{
+		name: "good gen_notice",
+		fs: map[string][]byte{
+			"top/Android.bp": []byte(`
+				gen_notice {
+					name: "top_notice",
+					for: ["top_rule"],
+				}
+
+				mock_genrule {
+					name: "top_rule",
+					dep: ["top_notice"],
+				}`),
+			"other/Android.bp": []byte(`
+				mock_genrule {
+					name: "other_rule",
+					dep: ["top_notice"],
+				}`),
+		},
+	},
+	{
+		name: "multiple license kinds",
+		fs: map[string][]byte{
+			"top/Android.bp": []byte(`
+				gen_notice {
+					name: "top_notice",
+					for: ["top_rule"],
+				}
+
+				gen_notice {
+					name: "top_html_notice",
+					html: true,
+					for: ["top_rule"],
+				}
+
+				gen_notice {
+					name: "top_xml_notice",
+					xml: true,
+					for: ["top_notice"],
+				}
+
+				mock_genrule {
+					name: "top_rule",
+					dep: [
+						"top_notice",
+						"top_html_notice",
+						"top_xml_notice",
+					],
+				}`),
+			"other/Android.bp": []byte(`
+				mock_genrule {
+					name: "other_rule",
+					dep: ["top_xml_notice"],
+				}`),
+		},
+	},
+}
+
+func TestGenNotice(t *testing.T) {
+	for _, test := range genNoticeTests {
+		t.Run(test.name, func(t *testing.T) {
+			GroupFixturePreparers(
+				PrepareForTestWithGenNotice,
+				FixtureRegisterWithContext(func(ctx RegistrationContext) {
+					ctx.RegisterModuleType("mock_genrule", newMockGenruleModule)
+				}),
+				test.fs.AddToFixture(),
+			).
+				ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
+				RunTest(t)
+		})
+	}
+}
+
+type mockGenruleProperties struct {
+	Dep []string
+}
+
+type mockGenruleModule struct {
+	ModuleBase
+	DefaultableModuleBase
+
+	properties mockGenruleProperties
+}
+
+func newMockGenruleModule() Module {
+	m := &mockGenruleModule{}
+	m.AddProperties(&m.properties)
+	InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon)
+	InitDefaultableModule(m)
+	return m
+}
+
+type genruleDepTag struct {
+	blueprint.BaseDependencyTag
+}
+
+func (j *mockGenruleModule) DepsMutator(ctx BottomUpMutatorContext) {
+	m, ok := ctx.Module().(Module)
+	if !ok {
+		return
+	}
+	ctx.AddDependency(m, genruleDepTag{}, j.properties.Dep...)
+}
+
+func (p *mockGenruleModule) GenerateAndroidBuildActions(ModuleContext) {
+}
diff --git a/android/licenses.go b/android/licenses.go
index bd14b26..81c557e 100644
--- a/android/licenses.go
+++ b/android/licenses.go
@@ -303,6 +303,7 @@
 	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.genNoticeModule": // contains license texts as data
 	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
diff --git a/android/singleton.go b/android/singleton.go
index 7ff96c9..7c6cf4f 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -29,6 +29,10 @@
 	ModuleType(module blueprint.Module) string
 	BlueprintFile(module blueprint.Module) string
 
+	// ModuleVariantsFromName returns the list of module variants named `name` in the same namespace as `referer` enforcing visibility rules.
+	// Allows generating build actions for `referer` based on the metadata for `name` deferred until the singleton context.
+	ModuleVariantsFromName(referer Module, name string) []Module
+
 	// ModuleProvider returns the value, if any, for the provider for a module.  If the value for the
 	// provider was not set it returns the zero value of the type of the provider, which means the
 	// return value can always be type-asserted to the type of the provider.  The return value should
@@ -251,3 +255,30 @@
 func (s *singletonContextAdaptor) FinalModule(module Module) Module {
 	return s.SingletonContext.FinalModule(module).(Module)
 }
+
+func (s *singletonContextAdaptor) ModuleVariantsFromName(referer Module, name string) []Module {
+	// get qualified module name for visibility enforcement
+	qualified := createQualifiedModuleName(s.ModuleName(referer), s.ModuleDir(referer))
+
+	modules := s.SingletonContext.ModuleVariantsFromName(referer, name)
+	result := make([]Module, 0, len(modules))
+	for _, m := range modules {
+		if module, ok := m.(Module); ok {
+			// enforce visibility
+			depName := s.ModuleName(module)
+			depDir := s.ModuleDir(module)
+			depQualified := qualifiedModuleName{depDir, depName}
+			// Targets are always visible to other targets in their own package.
+			if depQualified.pkg != qualified.pkg {
+				rule := effectiveVisibilityRules(s.Config(), depQualified)
+				if !rule.matches(qualified) {
+					s.ModuleErrorf(referer, "module %q references %q which is not visible to this module\nYou may need to add %q to its visibility",
+						referer.Name(), depQualified, "//"+s.ModuleDir(referer))
+					continue
+				}
+			}
+			result = append(result, module)
+		}
+	}
+	return result
+}
diff --git a/android/testing.go b/android/testing.go
index ac02db9..85bdca4 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -83,6 +83,8 @@
 	FixtureRegisterWithContext(registerLicenseMutators),
 )
 
+var PrepareForTestWithGenNotice = FixtureRegisterWithContext(RegisterGenNoticeBuildComponents)
+
 func registerLicenseMutators(ctx RegistrationContext) {
 	ctx.PreArchMutators(RegisterLicensesPackageMapper)
 	ctx.PreArchMutators(RegisterLicensesPropertyGatherer)
diff --git a/android/visibility.go b/android/visibility.go
index 5d1be6b..b209599 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -234,7 +234,7 @@
 
 // Checks the per-module visibility rule lists before defaults expansion.
 func visibilityRuleChecker(ctx BottomUpMutatorContext) {
-	qualified := createQualifiedModuleName(ctx)
+	qualified := createQualifiedModuleName(ctx.ModuleName(), ctx.ModuleDir())
 	if m, ok := ctx.Module().(Module); ok {
 		visibilityProperties := m.visibilityProperties()
 		for _, p := range visibilityProperties {
@@ -435,7 +435,7 @@
 		return
 	}
 
-	qualified := createQualifiedModuleName(ctx)
+	qualified := createQualifiedModuleName(ctx.ModuleName(), ctx.ModuleDir())
 
 	// Visit all the dependencies making sure that this module has access to them all.
 	ctx.VisitDirectDeps(func(dep Module) {
@@ -486,9 +486,7 @@
 	return rule
 }
 
-func createQualifiedModuleName(ctx BaseModuleContext) qualifiedModuleName {
-	moduleName := ctx.ModuleName()
-	dir := ctx.ModuleDir()
+func createQualifiedModuleName(moduleName, dir string) qualifiedModuleName {
 	qualified := qualifiedModuleName{dir, moduleName}
 	return qualified
 }
diff --git a/android/visibility_test.go b/android/visibility_test.go
index 714c92a..a66f0b6 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -135,7 +135,49 @@
 					name: "libexample",
 					visibility: ["//visibility:public"],
 				}
-	
+
+				mock_library {
+					name: "libsamepackage",
+					deps: ["libexample"],
+				}
+
+				gen_notice {
+					name: "libexample-notice",
+					for: ["libexample"],
+				}`),
+			"top/nested/Android.bp": []byte(`
+				mock_library {
+					name: "libnested",
+					deps: ["libexample"],
+				}
+
+				gen_notice {
+					name: "nested-notice",
+					for: ["libexample"],
+				}`),
+			"other/Android.bp": []byte(`
+				mock_library {
+					name: "libother",
+					deps: ["libexample"],
+				}
+
+				gen_notice {
+					name: "other-notice",
+					for: ["libexample"],
+				}`),
+		},
+	},
+	{
+		// Verify that //visibility:private allows the module to be referenced from the current
+		// directory only.
+		name: "//visibility:private",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_library {
+					name: "libexample",
+					visibility: ["//visibility:private"],
+				}
+
 				mock_library {
 					name: "libsamepackage",
 					deps: ["libexample"],
@@ -151,18 +193,61 @@
 					deps: ["libexample"],
 				}`),
 		},
+		expectedErrors: []string{
+			`module "libnested" variant "android_common": depends on //top:libexample which is not` +
+				` visible to this module`,
+			`module "libother" variant "android_common": depends on //top:libexample which is not` +
+				` visible to this module`,
+		},
 	},
 	{
 		// Verify that //visibility:private allows the module to be referenced from the current
 		// directory only.
-		name: "//visibility:private",
+		name: "//visibility:private (notices)",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
 				mock_library {
 					name: "libexample",
 					visibility: ["//visibility:private"],
 				}
-	
+
+				mock_library {
+					name: "libsamepackage",
+					deps: ["libexample"],
+				}
+
+				gen_notice {
+					name: "libexample-notice",
+					for: ["libexample"],
+				}`),
+			"top/nested/Android.bp": []byte(`
+				gen_notice {
+					name: "nested-notice",
+					for: ["libexample"],
+				}`),
+			"other/Android.bp": []byte(`
+				gen_notice {
+					name: "other-notice",
+					for: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "nested-notice" references "//top:libexample" which is not visible to this` +
+				` module\nYou may need to add "//top/nested" to its visibility`,
+			`module "other-notice" references "//top:libexample" which is not visible to this module\n` +
+				`You may need to add "//other" to its visibility`,
+		},
+	},
+	{
+		// Verify that :__pkg__ allows the module to be referenced from the current directory only.
+		name: ":__pkg__",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_library {
+					name: "libexample",
+					visibility: [":__pkg__"],
+				}
+
 				mock_library {
 					name: "libsamepackage",
 					deps: ["libexample"],
@@ -187,34 +272,32 @@
 	},
 	{
 		// Verify that :__pkg__ allows the module to be referenced from the current directory only.
-		name: ":__pkg__",
+		name: ":__pkg__ (notices)",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
 				mock_library {
 					name: "libexample",
 					visibility: [":__pkg__"],
 				}
-	
-				mock_library {
-					name: "libsamepackage",
-					deps: ["libexample"],
+
+				gen_notice {
+					name: "libexample-notice",
+					for: ["libexample"],
 				}`),
 			"top/nested/Android.bp": []byte(`
-				mock_library {
-					name: "libnested",
-					deps: ["libexample"],
+				gen_notice {
+					name: "nested-notice",
+					for: ["libexample"],
 				}`),
 			"other/Android.bp": []byte(`
-				mock_library {
-					name: "libother",
-					deps: ["libexample"],
+				gen_notice {
+					name: "other-notice",
+					for: ["libexample"],
 				}`),
 		},
 		expectedErrors: []string{
-			`module "libnested" variant "android_common": depends on //top:libexample which is not` +
-				` visible to this module`,
-			`module "libother" variant "android_common": depends on //top:libexample which is not` +
-				` visible to this module`,
+			`module "nested-notice" references "//top:libexample" which is not visible to this module`,
+			`module "other-notice" references "//top:libexample" which is not visible to this module`,
 		},
 	},
 	{
@@ -227,7 +310,7 @@
 					name: "libexample",
 					visibility: ["//top/nested"],
 				}
-	
+
 				mock_library {
 					name: "libsamepackage",
 					deps: ["libexample"],
@@ -256,6 +339,42 @@
 		},
 	},
 	{
+		// Verify that //top/nested allows the module to be referenced from the current directory and
+		// the top/nested directory only, not a subdirectory of top/nested and not peak directory.
+		name: "//top/nested (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_library {
+					name: "libexample",
+					visibility: ["//top/nested"],
+				}
+
+				gen_notice {
+					name: "libexample-notice",
+					for: ["libexample"],
+				}`),
+			"top/nested/Android.bp": []byte(`
+				gen_notice {
+					name: "nested-notice",
+					for: ["libexample"],
+				}`),
+			"top/nested/again/Android.bp": []byte(`
+				gen_notice {
+					name: "nestedagain-notice",
+					for: ["libexample"],
+				}`),
+			"peak/Android.bp": []byte(`
+				gen_notice {
+					name: "other-notice",
+					for: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "other-notice" references "//top:libexample" which is not visible to this module`,
+			`module "nestedagain-notice" references "//top:libexample" which is not visible to this module`,
+		},
+	},
+	{
 		// Verify that :__subpackages__ allows the module to be referenced from the current directory
 		// and sub directories but nowhere else.
 		name: ":__subpackages__",
@@ -265,7 +384,7 @@
 					name: "libexample",
 					visibility: [":__subpackages__"],
 				}
-	
+
 				mock_library {
 					name: "libsamepackage",
 					deps: ["libexample"],
@@ -287,6 +406,36 @@
 		},
 	},
 	{
+		// Verify that :__subpackages__ allows the module to be referenced from the current directory
+		// and sub directories but nowhere else.
+		name: ":__subpackages__ (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_library {
+					name: "libexample",
+					visibility: [":__subpackages__"],
+				}
+
+				gen_notice {
+					name: "libexample-notice",
+					for: ["libexample"],
+				}`),
+			"top/nested/Android.bp": []byte(`
+				gen_notice {
+					name: "nested-notice",
+					for: ["libexample"],
+				}`),
+			"peak/other/Android.bp": []byte(`
+				gen_notice {
+					name: "other-notice",
+					for: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "other-notice" references "//top:libexample" which is not visible to this module`,
+		},
+	},
+	{
 		// Verify that //top/nested:__subpackages__ allows the module to be referenced from the current
 		// directory and sub directories but nowhere else.
 		name: "//top/nested:__subpackages__",
@@ -296,7 +445,7 @@
 					name: "libexample",
 					visibility: ["//top/nested:__subpackages__", "//other"],
 				}
-	
+
 				mock_library {
 					name: "libsamepackage",
 					deps: ["libexample"],
@@ -318,6 +467,36 @@
 		},
 	},
 	{
+		// Verify that //top/nested:__subpackages__ allows the module to be referenced from the current
+		// directory and sub directories but nowhere else.
+		name: "//top/nested:__subpackages__ (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_library {
+					name: "libexample",
+					visibility: ["//top/nested:__subpackages__", "//other"],
+				}
+
+				gen_notice {
+					name: "libexample-notice",
+					for: ["libexample"],
+				}`),
+			"top/nested/Android.bp": []byte(`
+				gen_notice {
+					name: "nested-notice",
+					for: ["libexample"],
+				}`),
+			"top/other/Android.bp": []byte(`
+				gen_notice {
+					name: "other-notice",
+					for: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "other-notice" references "//top:libexample" which is not visible to this module`,
+		},
+	},
+	{
 		// Verify that ["//top/nested", "//peak:__subpackages"] allows the module to be referenced from
 		// the current directory, top/nested and peak and all its subpackages.
 		name: `["//top/nested", "//peak:__subpackages__"]`,
@@ -327,7 +506,7 @@
 					name: "libexample",
 					visibility: ["//top/nested", "//peak:__subpackages__"],
 				}
-	
+
 				mock_library {
 					name: "libsamepackage",
 					deps: ["libexample"],
@@ -345,6 +524,33 @@
 		},
 	},
 	{
+		// Verify that ["//top/nested", "//peak:__subpackages"] allows the module to be referenced from
+		// the current directory, top/nested and peak and all its subpackages.
+		name: `["//top/nested", "//peak:__subpackages__ (notices)"]`,
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_library {
+					name: "libexample",
+					visibility: ["//top/nested", "//peak:__subpackages__"],
+				}
+
+				gen_notice {
+					name: "libexample-notice",
+					for: ["libexample"],
+				}`),
+			"top/nested/Android.bp": []byte(`
+				gen_notice {
+					name: "nested-notice",
+					for: ["libexample"],
+				}`),
+			"peak/other/Android.bp": []byte(`
+				gen_notice {
+					name: "other-notice",
+					for: ["libexample"],
+				}`),
+		},
+	},
+	{
 		// Verify that //vendor... cannot be used outside vendor apart from //vendor:__subpackages__
 		name: `//vendor`,
 		fs: MockFS{
@@ -353,7 +559,7 @@
 					name: "libexample",
 					visibility: ["//vendor:__subpackages__"],
 				}
-	
+
 				mock_library {
 					name: "libsamepackage",
 					visibility: ["//vendor/apps/AcmeSettings"],
@@ -418,6 +624,45 @@
 		},
 	},
 	{
+		// Check that visibility is the union of the defaults modules.
+		name: "defaults union, basic (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//other"],
+				}
+				mock_library {
+					name: "libexample",
+					visibility: ["//top/nested"],
+					defaults: ["libexample_defaults"],
+				}
+
+				gen_notice {
+					name: "libexample-notice",
+					for: ["libexample"],
+				}`),
+			"top/nested/Android.bp": []byte(`
+				gen_notice {
+					name: "nested-notice",
+					for: ["libexample"],
+				}`),
+			"other/Android.bp": []byte(`
+				gen_notice {
+					name: "other-notice",
+					for: ["libexample"],
+				}`),
+			"outsider/Android.bp": []byte(`
+				gen_notice {
+					name: "outsider-notice",
+					for: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "outsider-notice" references "//top:libexample" which is not visible to this module`,
+		},
+	},
+	{
 		name: "defaults union, multiple defaults",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
@@ -459,6 +704,47 @@
 		},
 	},
 	{
+		name: "defaults union, multiple defaults (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_defaults {
+					name: "libexample_defaults_1",
+					visibility: ["//other"],
+				}
+				mock_defaults {
+					name: "libexample_defaults_2",
+					visibility: ["//top/nested"],
+				}
+				mock_library {
+					name: "libexample",
+					defaults: ["libexample_defaults_1", "libexample_defaults_2"],
+				}
+
+				gen_notice {
+					name: "libexample-notice",
+					for: ["libexample"],
+				}`),
+			"top/nested/Android.bp": []byte(`
+				gen_notice {
+					name: "nested-notice",
+					for: ["libexample"],
+				}`),
+			"other/Android.bp": []byte(`
+				gen_notice {
+					name: "other-notice",
+					for: ["libexample"],
+				}`),
+			"outsider/Android.bp": []byte(`
+				gen_notice {
+					name: "outsider-notice",
+					for: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "outsider-notice" references "//top:libexample" which is not visible to this module`,
+		},
+	},
+	{
 		name: "//visibility:public mixed with other in defaults",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
@@ -500,6 +786,29 @@
 		},
 	},
 	{
+		name: "//visibility:public overriding defaults (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//namespace"],
+				}
+				mock_library {
+					name: "libexample",
+					visibility: ["//visibility:public"],
+					defaults: ["libexample_defaults"],
+				}`),
+			"outsider/Android.bp": []byte(`
+				gen_notice {
+					name: "outsider-notice",
+					for: ["libexample"],
+				}`),
+		},
+		effectiveVisibility: map[qualifiedModuleName][]string{
+			qualifiedModuleName{pkg: "top", name: "libexample"}: {"//visibility:public"},
+		},
+	},
+	{
 		name: "//visibility:public mixed with other from different defaults 1",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
@@ -523,6 +832,34 @@
 		},
 	},
 	{
+		name: "//visibility:public mixed with other from different defaults 1",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_defaults {
+					name: "libexample_defaults_1",
+					visibility: ["//namespace"],
+				}
+				mock_defaults {
+					name: "libexample_defaults_2",
+					visibility: ["//visibility:public"],
+				}
+				mock_library {
+					name: "libexample",
+					defaults: ["libexample_defaults_1", "libexample_defaults_2"],
+				}
+
+				gen_notice {
+					name: "libexample-notice",
+					for: ["libexample"],
+				}`),
+			"outsider/Android.bp": []byte(`
+				gen_notice {
+					name: "outsider-notice",
+					for: ["libexample"],
+				}`),
+		},
+	},
+	{
 		name: "//visibility:public mixed with other from different defaults 2",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
@@ -546,6 +883,29 @@
 		},
 	},
 	{
+		name: "//visibility:public mixed with other from different defaults 2 (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_defaults {
+					name: "libexample_defaults_1",
+					visibility: ["//visibility:public"],
+				}
+				mock_defaults {
+					name: "libexample_defaults_2",
+					visibility: ["//namespace"],
+				}
+				mock_library {
+					name: "libexample",
+					defaults: ["libexample_defaults_1", "libexample_defaults_2"],
+				}`),
+			"outsider/Android.bp": []byte(`
+				gen_notice {
+					name: "outsider-notice",
+					for: ["libexample"],
+				}`),
+		},
+	},
+	{
 		name: "//visibility:private in defaults",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
@@ -580,6 +940,39 @@
 		},
 	},
 	{
+		name: "//visibility:private in defaults (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//visibility:private"],
+				}
+				mock_library {
+					name: "libexample",
+					defaults: ["libexample_defaults"],
+				}
+
+				gen_notice {
+					name: "libexample-notice",
+					for: ["libexample"],
+				}`),
+			"top/nested/Android.bp": []byte(`
+				gen_notice {
+					name: "nested-notice",
+					for: ["libexample"],
+				}`),
+			"other/Android.bp": []byte(`
+				gen_notice {
+					name: "other-notice",
+					for: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "nested-notice" references "//top:libexample" which is not visible to this module`,
+			`module "other-notice" references "//top:libexample" which is not visible to this module`,
+		},
+	},
+	{
 		name: "//visibility:private mixed with other in defaults",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
@@ -706,6 +1099,27 @@
 		},
 	},
 	{
+		name: "//visibility:override discards //visibility:private (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//visibility:private"],
+				}
+				mock_library {
+					name: "libexample",
+					// Make this visibility to //other but not //visibility:private
+					visibility: ["//visibility:override", "//other"],
+					defaults: ["libexample_defaults"],
+				}`),
+			"other/Android.bp": []byte(`
+				gen_notice {
+					name: "other-notice",
+					for: ["libexample"],
+				}`),
+		},
+	},
+	{
 		name: "//visibility:override discards //visibility:public",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
@@ -735,6 +1149,35 @@
 		},
 	},
 	{
+		name: "//visibility:override discards //visibility:public (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//visibility:public"],
+				}
+				mock_library {
+					name: "libexample",
+					// Make this visibility to //other but not //visibility:public
+					visibility: ["//visibility:override", "//other"],
+					defaults: ["libexample_defaults"],
+				}`),
+			"other/Android.bp": []byte(`
+				gen_notice {
+					name: "other-notice",
+					for: ["libexample"],
+				}`),
+			"namespace/Android.bp": []byte(`
+				gen_notice {
+					name: "namespace-notice",
+					for: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "namespace-notice" references "//top:libexample" which is not visible to this module\nYou may need to add "//namespace" to its visibility`,
+		},
+	},
+	{
 		name: "//visibility:override discards defaults supplied rules",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
@@ -764,6 +1207,35 @@
 		},
 	},
 	{
+		name: "//visibility:override discards defaults supplied rules (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//namespace"],
+				}
+				mock_library {
+					name: "libexample",
+					// Make this visibility to //other but not //namespace
+					visibility: ["//visibility:override", "//other"],
+					defaults: ["libexample_defaults"],
+				}`),
+			"other/Android.bp": []byte(`
+				gen_notice {
+					name: "other-notice",
+					for: ["libexample"],
+				}`),
+			"namespace/Android.bp": []byte(`
+				gen_notice {
+					name: "namespace-notice",
+					for: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "namespace-notice" references "//top:libexample" which is not visible to this module\nYou may need to add "//namespace" to its visibility`,
+		},
+	},
+	{
 		name: "//visibility:override can override //visibility:public with //visibility:private",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
@@ -787,6 +1259,29 @@
 		},
 	},
 	{
+		name: "//visibility:override can override //visibility:public with //visibility:private (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//visibility:public"],
+				}
+				mock_library {
+					name: "libexample",
+					visibility: ["//visibility:override", "//visibility:private"],
+					defaults: ["libexample_defaults"],
+				}`),
+			"namespace/Android.bp": []byte(`
+				gen_notice {
+					name: "namespace-notice",
+					for: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "namespace-notice" references "//top:libexample" which is not visible to this module`,
+		},
+	},
+	{
 		name: "//visibility:override can override //visibility:private with //visibility:public",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
@@ -807,6 +1302,26 @@
 		},
 	},
 	{
+		name: "//visibility:override can override //visibility:private with //visibility:public (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//visibility:private"],
+				}
+				mock_library {
+					name: "libexample",
+					visibility: ["//visibility:override", "//visibility:public"],
+					defaults: ["libexample_defaults"],
+				}`),
+			"namespace/Android.bp": []byte(`
+				gen_notice {
+					name: "namespace-notice",
+					for: ["libexample"],
+				}`),
+		},
+	},
+	{
 		name: "//visibility:private mixed with itself",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
@@ -834,6 +1349,33 @@
 				` visible to this module`,
 		},
 	},
+	{
+		name: "//visibility:private mixed with itself (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_defaults {
+					name: "libexample_defaults_1",
+					visibility: ["//visibility:private"],
+				}
+				mock_defaults {
+					name: "libexample_defaults_2",
+					visibility: ["//visibility:private"],
+				}
+				mock_library {
+					name: "libexample",
+					visibility: ["//visibility:private"],
+					defaults: ["libexample_defaults_1", "libexample_defaults_2"],
+				}`),
+			"outsider/Android.bp": []byte(`
+				gen_notice {
+					name: "outsider-notice",
+					for: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "outsider-notice" references "//top:libexample" which is not visible to this module`,
+		},
+	},
 
 	// Defaults module's defaults_visibility tests
 	{
@@ -903,6 +1445,28 @@
 		},
 	},
 	{
+		// This test relies on the default visibility being legacy_public.
+		name: "package default_visibility property used when no visibility specified (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				package {
+					default_visibility: ["//visibility:private"],
+				}
+
+				mock_library {
+					name: "libexample",
+				}`),
+			"outsider/Android.bp": []byte(`
+				gen_notice {
+					name: "outsider-notice",
+					for: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "outsider-notice" references "//top:libexample" which is not visible to this module`,
+		},
+	},
+	{
 		name: "package default_visibility public does not override visibility private",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
@@ -926,6 +1490,28 @@
 		},
 	},
 	{
+		name: "package default_visibility public does not override visibility private (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				package {
+					default_visibility: ["//visibility:public"],
+				}
+
+				mock_library {
+					name: "libexample",
+					visibility: ["//visibility:private"],
+				}`),
+			"outsider/Android.bp": []byte(`
+				gen_notice {
+					name: "outsider-notice",
+					for: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "outsider-notice" references "//top:libexample" which is not visible to this module`,
+		},
+	},
+	{
 		name: "package default_visibility private does not override visibility public",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
@@ -945,6 +1531,25 @@
 		},
 	},
 	{
+		name: "package default_visibility private does not override visibility public (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				package {
+					default_visibility: ["//visibility:private"],
+				}
+
+				mock_library {
+					name: "libexample",
+					visibility: ["//visibility:public"],
+				}`),
+			"outsider/Android.bp": []byte(`
+				gen_notice {
+					name: "outsider-notice",
+					for: ["libexample"],
+				}`),
+		},
+	},
+	{
 		name: "package default_visibility :__subpackages__",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
@@ -972,6 +1577,32 @@
 		},
 	},
 	{
+		name: "package default_visibility :__subpackages__ (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				package {
+					default_visibility: [":__subpackages__"],
+				}
+
+				mock_library {
+					name: "libexample",
+				}`),
+			"top/nested/Android.bp": []byte(`
+				gen_notice {
+					name: "nested-notice",
+					for: ["libexample"],
+				}`),
+			"outsider/Android.bp": []byte(`
+				gen_notice {
+					name: "outsider-notice",
+					for: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "outsider-notice" references "//top:libexample" which is not visible to this module`,
+		},
+	},
+	{
 		name: "package default_visibility inherited to subpackages",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
@@ -981,7 +1612,7 @@
 
 				mock_library {
 					name: "libexample",
-          visibility: [":__subpackages__"],
+					visibility: [":__subpackages__"],
 				}`),
 			"top/nested/Android.bp": []byte(`
 				mock_library {
@@ -1000,6 +1631,38 @@
 		},
 	},
 	{
+		name: "package default_visibility inherited to subpackages (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				package {
+					default_visibility: ["//outsider"],
+				}
+
+				mock_library {
+					name: "libexample",
+					visibility: [":__subpackages__"],
+				}`),
+			"top/nested/Android.bp": []byte(`
+				mock_library {
+					name: "libnested",
+					deps: ["libexample"],
+				}
+
+				gen_notice {
+					name: "nested-notice",
+					for: ["libexample"],
+				}`),
+			"outsider/Android.bp": []byte(`
+				gen_notice {
+					name: "outsider-notice",
+					for: ["libexample", "libnested"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "outsider-notice" references "//top:libexample" which is not visible to this module`,
+		},
+	},
+	{
 		name: "package default_visibility inherited to subpackages",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
@@ -1030,6 +1693,41 @@
 		},
 	},
 	{
+		name: "package default_visibility inherited to subpackages (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				package {
+					default_visibility: ["//visibility:private"],
+				}`),
+			"top/nested/Android.bp": []byte(`
+				package {
+					default_visibility: ["//outsider"],
+				}
+
+				mock_library {
+					name: "libnested",
+				}`),
+			"top/other/Android.bp": []byte(`
+				mock_library {
+					name: "libother",
+				}
+
+				gen_notice {
+					name: "other-notice",
+					for: ["libother"],
+				}`),
+			"outsider/Android.bp": []byte(`
+				gen_notice {
+					name: "outsider-notice",
+					for: ["libother", "libnested"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "outsider-notice" references "//top/other:libother" which is not visible to this` +
+				` module\nYou may need to add "//outsider" to its visibility`,
+		},
+	},
+	{
 		name: "verify that prebuilt dependencies are ignored for visibility reasons (not preferred)",
 		fs: MockFS{
 			"prebuilts/Android.bp": []byte(`
@@ -1052,6 +1750,28 @@
 		},
 	},
 	{
+		name: "verify that prebuilt dependencies are ignored for visibility reasons (not preferred) (notices)",
+		fs: MockFS{
+			"prebuilts/Android.bp": []byte(`
+				prebuilt {
+					name: "module",
+					visibility: ["//top/other"],
+				}`),
+			"top/sources/source_file": nil,
+			"top/sources/Android.bp": []byte(`
+				source {
+					name: "module",
+					visibility: ["//top/other"],
+				}`),
+			"top/other/source_file": nil,
+			"top/other/Android.bp": []byte(`
+				gen_notice {
+					name: "other-notice",
+					for: ["module"],
+				}`),
+		},
+	},
+	{
 		name: "verify that prebuilt dependencies are ignored for visibility reasons (preferred)",
 		fs: MockFS{
 			"prebuilts/Android.bp": []byte(`
@@ -1075,6 +1795,29 @@
 		},
 	},
 	{
+		name: "verify that prebuilt dependencies are ignored for visibility reasons (preferred) (notices)",
+		fs: MockFS{
+			"prebuilts/Android.bp": []byte(`
+				prebuilt {
+					name: "module",
+					visibility: ["//top/other"],
+					prefer: true,
+				}`),
+			"top/sources/source_file": nil,
+			"top/sources/Android.bp": []byte(`
+				source {
+					name: "module",
+					visibility: ["//top/other"],
+				}`),
+			"top/other/source_file": nil,
+			"top/other/Android.bp": []byte(`
+				gen_notice {
+					name: "other-notice",
+					for: ["module"],
+				}`),
+		},
+	},
+	{
 		name: "ensure visibility properties are checked for correctness",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
@@ -1137,6 +1880,30 @@
 				}`),
 		},
 	},
+	{
+		name: "automatic visibility inheritance enabled (notices)",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				mock_parent {
+					name: "parent",
+					visibility: ["//top/nested"],
+					child: {
+						name: "libchild",
+						visibility: ["//top/other"],
+					},
+				}`),
+			"top/nested/Android.bp": []byte(`
+				gen_notice {
+					name: "nested-notice",
+					for: ["libchild"],
+				}`),
+			"top/other/Android.bp": []byte(`
+				gen_notice {
+					name: "other-notice",
+					for: ["libchild"],
+				}`),
+		},
+	},
 }
 
 func TestVisibility(t *testing.T) {
@@ -1147,6 +1914,7 @@
 				// registration order.
 				PrepareForTestWithArchMutator,
 				PrepareForTestWithDefaults,
+				PrepareForTestWithGenNotice,
 				PrepareForTestWithOverrides,
 				PrepareForTestWithPackageModule,
 				PrepareForTestWithPrebuilts,
diff --git a/java/app.go b/java/app.go
index 41419ba..94e6fb9 100755
--- a/java/app.go
+++ b/java/app.go
@@ -589,16 +589,6 @@
 
 	a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
 
-	var noticeAssetPath android.WritablePath
-	if Bool(a.appProperties.Embed_notices) || ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") {
-		// The rule to create the notice file can't be generated yet, as the final output path
-		// for the apk isn't known yet.  Add the path where the notice file will be generated to the
-		// aapt rules now before calling aaptBuildActions, the rule to create the notice file will
-		// be generated later.
-		noticeAssetPath = android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
-		a.aapt.noticeFile = android.OptionalPathForPath(noticeAssetPath)
-	}
-
 	// Process all building blocks, from AAPT to certificates.
 	a.aaptBuildActions(ctx)
 
@@ -673,8 +663,7 @@
 		a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile)
 	}
 
-	if a.aapt.noticeFile.Valid() {
-		// Generating the notice file rule has to be here after a.outputFile is known.
+	if Bool(a.appProperties.Embed_notices) || ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") {
 		noticeFile := android.PathForModuleOut(ctx, "NOTICE.html.gz")
 		android.BuildNoticeHtmlOutputFromLicenseMetadata(
 			ctx, noticeFile, "", "",
@@ -683,11 +672,13 @@
 				android.PathForModuleInstall(ctx).String() + "/",
 				a.outputFile.String(),
 			})
+		noticeAssetPath := android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
 		builder := android.NewRuleBuilder(pctx, ctx)
 		builder.Command().Text("cp").
 			Input(noticeFile).
 			Output(noticeAssetPath)
 		builder.Build("notice_dir", "Building notice dir")
+		a.aapt.noticeFile = android.OptionalPathForPath(noticeAssetPath)
 	}
 
 	for _, split := range a.aapt.splits {