Revert "Build notice files from license metadata."

This reverts commit 43c2dcaef609c4a268bfab6c95ed924af4ead6b1.

Reason for revert: suspect build break

Bug: 227682036

Test: TARGET_BUILD_VARIANT=userdebug UNBUNDLED_BUILD_SDKS_FROM_SOURCE=true vendor/google/build/mainline_modules_bundles.sh -j97


Change-Id: Ibfb8b4fefc264f52f32ba661c269a9cd625d800a
diff --git a/java/androidmk.go b/java/androidmk.go
index 80b828d..b930441 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -409,6 +409,22 @@
 				entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", app.linter.reports)
 			},
 		},
+		ExtraFooters: []android.AndroidMkExtraFootersFunc{
+			func(w io.Writer, name, prefix, moduleDir string) {
+				if app.noticeOutputs.Merged.Valid() {
+					fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n",
+						app.installApkName, app.noticeOutputs.Merged.String(), app.installApkName+"_NOTICE")
+				}
+				if app.noticeOutputs.TxtOutput.Valid() {
+					fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n",
+						app.installApkName, app.noticeOutputs.TxtOutput.String(), app.installApkName+"_NOTICE.txt")
+				}
+				if app.noticeOutputs.HtmlOutput.Valid() {
+					fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n",
+						app.installApkName, app.noticeOutputs.HtmlOutput.String(), app.installApkName+"_NOTICE.html")
+				}
+			},
+		},
 	}}
 }
 
diff --git a/java/app.go b/java/app.go
index 5b1daa4..8728df6 100755
--- a/java/app.go
+++ b/java/app.go
@@ -19,6 +19,7 @@
 
 import (
 	"path/filepath"
+	"sort"
 	"strings"
 
 	"github.com/google/blueprint"
@@ -163,6 +164,8 @@
 
 	additionalAaptFlags []string
 
+	noticeOutputs android.NoticeOutputs
+
 	overriddenManifestPackageName string
 
 	android.ApexBundleDepsInfo
@@ -520,6 +523,53 @@
 	return jniSymbols
 }
 
+func (a *AndroidApp) noticeBuildActions(ctx android.ModuleContext) {
+	// Collect NOTICE files from all dependencies.
+	seenModules := make(map[android.Module]bool)
+	noticePathSet := make(map[android.Path]bool)
+
+	ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
+		// Have we already seen this?
+		if _, ok := seenModules[child]; ok {
+			return false
+		}
+		seenModules[child] = true
+
+		// Skip host modules.
+		if child.Target().Os.Class == android.Host {
+			return false
+		}
+
+		paths := child.(android.Module).NoticeFiles()
+		if len(paths) > 0 {
+			for _, path := range paths {
+				noticePathSet[path] = true
+			}
+		}
+		return true
+	})
+
+	// If the app has one, add it too.
+	if len(a.NoticeFiles()) > 0 {
+		for _, path := range a.NoticeFiles() {
+			noticePathSet[path] = true
+		}
+	}
+
+	if len(noticePathSet) == 0 {
+		return
+	}
+	var noticePaths []android.Path
+	for path := range noticePathSet {
+		noticePaths = append(noticePaths, path)
+	}
+	sort.Slice(noticePaths, func(i, j int) bool {
+		return noticePaths[i].String() < noticePaths[j].String()
+	})
+
+	a.noticeOutputs = android.BuildNoticeOutput(ctx, a.installDir, a.installApkName+".apk", noticePaths)
+}
+
 // Reads and prepends a main cert from the default cert dir if it hasn't been set already, i.e. it
 // isn't a cert module reference. Also checks and enforces system cert restriction if applicable.
 func processMainCert(m android.ModuleBase, certPropValue string, certificates []Certificate, ctx android.ModuleContext) []Certificate {
@@ -586,10 +636,9 @@
 	}
 	a.onDeviceDir = android.InstallPathToOnDevicePath(ctx, a.installDir)
 
-	noticeFile := android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
-	android.BuildNoticeHtmlOutputFromLicenseMetadata(ctx, noticeFile)
+	a.noticeBuildActions(ctx)
 	if Bool(a.appProperties.Embed_notices) || ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") {
-		a.aapt.noticeFile = android.OptionalPathForPath(noticeFile)
+		a.aapt.noticeFile = a.noticeOutputs.HtmlGzOutput
 	}
 
 	a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
diff --git a/java/app_test.go b/java/app_test.go
index 08baf54..16bbec1 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -27,6 +27,7 @@
 	"android/soong/android"
 	"android/soong/cc"
 	"android/soong/dexpreopt"
+	"android/soong/genrule"
 )
 
 // testApp runs tests using the prepareForJavaTest
@@ -2721,6 +2722,116 @@
 	}
 }
 
+func TestEmbedNotice(t *testing.T) {
+	result := android.GroupFixturePreparers(
+		PrepareForTestWithJavaDefaultModules,
+		cc.PrepareForTestWithCcDefaultModules,
+		genrule.PrepareForTestWithGenRuleBuildComponents,
+		android.MockFS{
+			"APP_NOTICE":     nil,
+			"GENRULE_NOTICE": nil,
+			"LIB_NOTICE":     nil,
+			"TOOL_NOTICE":    nil,
+		}.AddToFixture(),
+	).RunTestWithBp(t, `
+		android_app {
+			name: "foo",
+			srcs: ["a.java"],
+			static_libs: ["javalib"],
+			jni_libs: ["libjni"],
+			notice: "APP_NOTICE",
+			embed_notices: true,
+			sdk_version: "current",
+		}
+
+		// No embed_notice flag
+		android_app {
+			name: "bar",
+			srcs: ["a.java"],
+			jni_libs: ["libjni"],
+			notice: "APP_NOTICE",
+			sdk_version: "current",
+		}
+
+		// No NOTICE files
+		android_app {
+			name: "baz",
+			srcs: ["a.java"],
+			embed_notices: true,
+			sdk_version: "current",
+		}
+
+		cc_library {
+			name: "libjni",
+			system_shared_libs: [],
+			stl: "none",
+			notice: "LIB_NOTICE",
+			sdk_version: "current",
+		}
+
+		java_library {
+			name: "javalib",
+			srcs: [
+				":gen",
+			],
+			sdk_version: "current",
+		}
+
+		genrule {
+			name: "gen",
+			tools: ["gentool"],
+			out: ["gen.java"],
+			notice: "GENRULE_NOTICE",
+		}
+
+		java_binary_host {
+			name: "gentool",
+			srcs: ["b.java"],
+			notice: "TOOL_NOTICE",
+		}
+	`)
+
+	// foo has NOTICE files to process, and embed_notices is true.
+	foo := result.ModuleForTests("foo", "android_common")
+	// verify merge notices rule.
+	mergeNotices := foo.Rule("mergeNoticesRule")
+	noticeInputs := mergeNotices.Inputs.Strings()
+	// TOOL_NOTICE should be excluded as it's a host module.
+	if len(mergeNotices.Inputs) != 3 {
+		t.Errorf("number of input notice files: expected = 3, actual = %q", noticeInputs)
+	}
+	if !inList("APP_NOTICE", noticeInputs) {
+		t.Errorf("APP_NOTICE is missing from notice files, %q", noticeInputs)
+	}
+	if !inList("LIB_NOTICE", noticeInputs) {
+		t.Errorf("LIB_NOTICE is missing from notice files, %q", noticeInputs)
+	}
+	if !inList("GENRULE_NOTICE", noticeInputs) {
+		t.Errorf("GENRULE_NOTICE is missing from notice files, %q", noticeInputs)
+	}
+	// aapt2 flags should include -A <NOTICE dir> so that its contents are put in the APK's /assets.
+	res := foo.Output("package-res.apk")
+	aapt2Flags := res.Args["flags"]
+	e := "-A out/soong/.intermediates/foo/android_common/NOTICE"
+	android.AssertStringDoesContain(t, "expected.apkPath", aapt2Flags, e)
+
+	// bar has NOTICE files to process, but embed_notices is not set.
+	bar := result.ModuleForTests("bar", "android_common")
+	res = bar.Output("package-res.apk")
+	aapt2Flags = res.Args["flags"]
+	e = "-A out/soong/.intermediates/bar/android_common/NOTICE"
+	android.AssertStringDoesNotContain(t, "bar shouldn't have the asset dir flag for NOTICE", aapt2Flags, e)
+
+	// baz's embed_notice is true, but it doesn't have any NOTICE files.
+	baz := result.ModuleForTests("baz", "android_common")
+	res = baz.Output("package-res.apk")
+	aapt2Flags = res.Args["flags"]
+	e = "-A out/soong/.intermediates/baz/android_common/NOTICE"
+	if strings.Contains(aapt2Flags, e) {
+		t.Errorf("baz shouldn't have the asset dir flag for NOTICE: %q", e)
+	}
+}
+
 func TestUncompressDex(t *testing.T) {
 	testCases := []struct {
 		name string