Generate sdk_repo notice files from license metadata

Use the new license metadata files to generate the notice files
for sdk_repo modules.

Bug: 207445310
Test: m sdk_repo_build_tools
Change-Id: I8079061fbdf7417c94eebbb1b31486d3f506f931
diff --git a/android/license_metadata.go b/android/license_metadata.go
index 544295c..6a5b0da 100644
--- a/android/license_metadata.go
+++ b/android/license_metadata.go
@@ -34,7 +34,7 @@
 	}, "args")
 )
 
-func buildLicenseMetadata(ctx ModuleContext) {
+func buildLicenseMetadata(ctx ModuleContext, licenseMetadataFile WritablePath) {
 	base := ctx.Module().base()
 
 	if !base.Enabled() {
@@ -118,8 +118,10 @@
 		JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_text.Strings()), "-n "))
 
 	if isContainer {
+		transitiveDeps := newPathsDepSet(nil, allDepMetadataDepSets).ToList()
 		args = append(args,
-			JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(newPathsDepSet(nil, allDepMetadataDepSets).ToList().Strings()), "-d "))
+			JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(transitiveDeps.Strings()), "-d "))
+		orderOnlyDeps = append(orderOnlyDeps, transitiveDeps...)
 	} else {
 		args = append(args,
 			JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepMetadataArgs), "-d "))
@@ -149,8 +151,6 @@
 		args = append(args, "--is_container")
 	}
 
-	licenseMetadataFile := PathForModuleOut(ctx, "meta_lic")
-
 	ctx.Build(pctx, BuildParams{
 		Rule:        licenseMetadataRule,
 		Output:      licenseMetadataFile,
diff --git a/android/module.go b/android/module.go
index 2d0813c..0e69f27 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1321,6 +1321,9 @@
 	// set of dependency module:location mappings used to populate the license metadata for
 	// apex containers.
 	licenseInstallMap []string
+
+	// The path to the generated license metadata file for the module.
+	licenseMetadataFile WritablePath
 }
 
 // A struct containing all relevant information about a Bazel target converted via bp2build.
@@ -2076,6 +2079,8 @@
 		variables:         make(map[string]string),
 	}
 
+	m.licenseMetadataFile = PathForModuleOut(ctx, "meta_lic")
+
 	dependencyInstallFiles, dependencyPackagingSpecs := m.computeInstallDeps(ctx)
 	// set m.installFilesDepSet to only the transitive dependencies to be used as the dependencies
 	// of installed files of this module.  It will be replaced by a depset including the installed
@@ -2207,7 +2212,7 @@
 	m.installFilesDepSet = newInstallPathsDepSet(m.installFiles, dependencyInstallFiles)
 	m.packagingSpecsDepSet = newPackagingSpecsDepSet(m.packagingSpecs, dependencyPackagingSpecs)
 
-	buildLicenseMetadata(ctx)
+	buildLicenseMetadata(ctx, m.licenseMetadataFile)
 
 	m.buildParams = ctx.buildParams
 	m.ruleParams = ctx.ruleParams
diff --git a/android/notices.go b/android/notices.go
index d8cfaf2..194a734 100644
--- a/android/notices.go
+++ b/android/notices.go
@@ -16,6 +16,7 @@
 
 import (
 	"path/filepath"
+	"strings"
 
 	"github.com/google/blueprint"
 )
@@ -101,55 +102,15 @@
 	}
 }
 
-// BuildNotices merges the supplied NOTICE files into a single file that lists notices
-// for every key in noticeMap (which would normally be installed files).
-func BuildNotices(ctx ModuleContext, noticeMap map[string]Paths) NoticeOutputs {
-	// TODO(jungjw): We should just produce a well-formatted NOTICE.html file in a single pass.
-	//
-	// generate-notice-files.py, which processes the merged NOTICE file, has somewhat strict rules
-	// about input NOTICE file paths.
-	// 1. Their relative paths to the src root become their NOTICE index titles. We want to use
-	// on-device paths as titles, and so output the merged NOTICE file the corresponding location.
-	// 2. They must end with .txt extension. Otherwise, they're ignored.
-
-	mergeTool := PathForSource(ctx, "build/soong/scripts/mergenotice.py")
-	generateNoticeTool := PathForSource(ctx, "build/soong/scripts/generate-notice-files.py")
-
-	outputDir := PathForModuleOut(ctx, "notices")
-	builder := NewRuleBuilder(pctx, ctx).
-		Sbox(outputDir, PathForModuleOut(ctx, "notices.sbox.textproto"))
-	for _, installPath := range SortedStringKeys(noticeMap) {
-		noticePath := outputDir.Join(ctx, installPath+".txt")
-		// It would be nice if sbox created directories for temporaries, but until then
-		// this is simple enough.
-		builder.Command().
-			Text("(cd").OutputDir().Text("&&").
-			Text("mkdir -p").Text(filepath.Dir(installPath)).Text(")")
-		builder.Temporary(noticePath)
-		builder.Command().
-			Tool(mergeTool).
-			Flag("--output").Output(noticePath).
-			Inputs(noticeMap[installPath])
-	}
-
-	// Transform the merged NOTICE file into a gzipped HTML file.
-	txtOutput := outputDir.Join(ctx, "NOTICE.txt")
-	htmlOutput := outputDir.Join(ctx, "NOTICE.html")
-	htmlGzOutput := outputDir.Join(ctx, "NOTICE.html.gz")
-	title := "\"Notices for " + ctx.ModuleName() + "\""
-	builder.Command().Tool(generateNoticeTool).
-		FlagWithOutput("--text-output ", txtOutput).
-		FlagWithOutput("--html-output ", htmlOutput).
-		FlagWithArg("-t ", title).
-		Flag("-s").OutputDir()
-	builder.Command().BuiltTool("minigzip").
-		FlagWithInput("-c ", htmlOutput).
-		FlagWithOutput("> ", htmlGzOutput)
-	builder.Build("build_notices", "generate notice output")
-
-	return NoticeOutputs{
-		TxtOutput:    OptionalPathForPath(txtOutput),
-		HtmlOutput:   OptionalPathForPath(htmlOutput),
-		HtmlGzOutput: OptionalPathForPath(htmlGzOutput),
-	}
+// BuildNoticeTextOutputFromLicenseMetadata writes out a notice text file based on the module's
+// generated license metadata file.
+func BuildNoticeTextOutputFromLicenseMetadata(ctx ModuleContext, outputFile WritablePath) {
+	depsFile := outputFile.ReplaceExtension(ctx, strings.TrimPrefix(outputFile.Ext()+".d", "."))
+	rule := NewRuleBuilder(pctx, ctx)
+	rule.Command().
+		BuiltTool("textnotice").
+		FlagWithOutput("-o ", outputFile).
+		FlagWithDepFile("-d ", depsFile).
+		Input(ctx.Module().base().licenseMetadataFile)
+	rule.Build("container_notice", "container notice file")
 }
diff --git a/android_sdk/sdk_repo_host.go b/android_sdk/sdk_repo_host.go
index d64eb7a..f050a2e 100644
--- a/android_sdk/sdk_repo_host.go
+++ b/android_sdk/sdk_repo_host.go
@@ -122,17 +122,10 @@
 
 	s.CopySpecsToDir(ctx, builder, packageSpecs, dir)
 
-	// Collect licenses to write into NOTICE.txt
-	noticeMap := map[string]android.Paths{}
-	for path, pkgSpec := range packageSpecs {
-		licenseFiles := pkgSpec.EffectiveLicenseFiles()
-		if len(licenseFiles) > 0 {
-			noticeMap[path] = pkgSpec.EffectiveLicenseFiles()
-		}
-	}
-	notices := android.BuildNotices(ctx, noticeMap)
+	noticeFile := android.PathForModuleOut(ctx, "NOTICES.txt")
+	android.BuildNoticeTextOutputFromLicenseMetadata(ctx, noticeFile)
 	builder.Command().Text("cp").
-		Input(notices.TxtOutput.Path()).
+		Input(noticeFile).
 		Text(filepath.Join(dir.String(), "NOTICE.txt"))
 
 	// Handle `merge_zips` by extracting their contents into our tmpdir