Merge "Make sure dist files have license metadata."
diff --git a/android/Android.bp b/android/Android.bp
index 8eb55d2..65332b2 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -107,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_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/cc/builder.go b/cc/builder.go
index 107cd58..468452d 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -957,9 +957,10 @@
 	return outputFile
 }
 
-// sourceAbiDiff registers a build statement to compare linked sAbi dump files (.ldump).
+// sourceAbiDiff registers a build statement to compare linked sAbi dump files (.lsdump).
 func sourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceDump android.Path,
-	baseName, exportedHeaderFlags string, checkAllApis, isLlndk, isNdk, isVndkExt bool) android.OptionalPath {
+	baseName, exportedHeaderFlags string, diffFlags []string,
+	checkAllApis, isLlndk, isNdk, isVndkExt bool) android.OptionalPath {
 
 	outputFile := android.PathForModuleOut(ctx, baseName+".abidiff")
 	libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
@@ -990,6 +991,8 @@
 	if isVndkExt {
 		extraFlags = append(extraFlags, "-allow-extensions")
 	}
+	// TODO(b/232891473): Simplify the above logic with diffFlags.
+	extraFlags = append(extraFlags, diffFlags...)
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        sAbiDiff,
diff --git a/cc/library.go b/cc/library.go
index a43f5b4..0fa01d7 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -110,6 +110,9 @@
 		// Run checks on all APIs (in addition to the ones referred by
 		// one of exported ELF symbols.)
 		Check_all_apis *bool
+
+		// Extra flags passed to header-abi-diff
+		Diff_flags []string
 	}
 
 	// Inject boringssl hash into the shared library.  This is only intended for use by external/boringssl.
@@ -1634,6 +1637,7 @@
 		if refAbiDumpFile != nil {
 			library.sAbiDiff = sourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
 				refAbiDumpFile, fileName, exportedHeaderFlags,
+				library.Properties.Header_abi_checker.Diff_flags,
 				Bool(library.Properties.Header_abi_checker.Check_all_apis),
 				ctx.IsLlndk(), ctx.isNdk(ctx.Config()), ctx.IsVndkExt())
 		}
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index b1e119f..bd5a1bd 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -166,8 +166,7 @@
 	touch(shared.JoinPath(topDir, queryviewMarker))
 }
 
-func writeMetrics(configuration android.Config, eventHandler metrics.EventHandler) {
-	metricsDir := configuration.Getenv("LOG_DIR")
+func writeMetrics(configuration android.Config, eventHandler metrics.EventHandler, metricsDir string) {
 	if len(metricsDir) < 1 {
 		fmt.Fprintf(os.Stderr, "\nMissing required env var for generating soong metrics: LOG_DIR\n")
 		os.Exit(1)
@@ -221,7 +220,7 @@
 // doChosenActivity runs Soong for a specific activity, like bp2build, queryview
 // or the actual Soong build for the build.ninja file. Returns the top level
 // output file of the specific activity.
-func doChosenActivity(configuration android.Config, extraNinjaDeps []string) string {
+func doChosenActivity(configuration android.Config, extraNinjaDeps []string, logDir string) string {
 	mixedModeBuild := configuration.BazelContext.BazelEnabled()
 	generateBazelWorkspace := bp2buildMarker != ""
 	generateQueryView := bazelQueryViewDir != ""
@@ -285,7 +284,7 @@
 		}
 	}
 
-	writeMetrics(configuration, *ctx.EventHandler)
+	writeMetrics(configuration, *ctx.EventHandler, logDir)
 	return cmdlineArgs.OutFile
 }
 
@@ -341,7 +340,11 @@
 		extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.SoongOutDir(), "always_rerun_for_delve"))
 	}
 
-	finalOutputFile := doChosenActivity(configuration, extraNinjaDeps)
+	// Bypass configuration.Getenv, as LOG_DIR does not need to be dependency tracked. By definition, it will
+	// change between every CI build, so tracking it would require re-running Soong for every build.
+	logDir := availableEnv["LOG_DIR"]
+
+	finalOutputFile := doChosenActivity(configuration, extraNinjaDeps, logDir)
 
 	writeUsedEnvironmentFile(configuration, finalOutputFile)
 }
diff --git a/rust/config/global.go b/rust/config/global.go
index d11665c..554cfe2 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
 var pctx = android.NewPackageContext("android/soong/rust/config")
 
 var (
-	RustDefaultVersion = "1.60.0"
+	RustDefaultVersion = "1.61.0"
 	RustDefaultBase    = "prebuilts/rust/"
 	DefaultEdition     = "2021"
 	Stdlibs            = []string{