Add android_sdk_repo_host to build platform-tools&build-tools

The Android SDK has been built with Make up until now, monolithically,
then split up into several sdk-repo zip files for different purposes.
The Mac and Windows SDKs really only need to contain the platform-tools
and build-tools pieces, but due to this monolithic sdk zip, we had to
build the whole SDK first.

This adds an `android_sdk_repo_host` module that can build these
platform-tools and build-tools zips.

Bug: 187222815
Change-Id: I55809e1d7447dd65e22461f921b2b8abb6d5f822
diff --git a/android/notices.go b/android/notices.go
index 07cf3e4..d8cfaf2 100644
--- a/android/notices.go
+++ b/android/notices.go
@@ -100,3 +100,56 @@
 		HtmlGzOutput: OptionalPathForPath(htmlGzOutput),
 	}
 }
+
+// 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),
+	}
+}