Add Singleton class to collect and validate test spec metadata.

Bug: 296873595
Test: Manual testing (Will add unit test case in the next change.)
Change-Id: Ic4177c5f76602088d52a31ca8d9fbaa703855837
diff --git a/testing/Android.bp b/testing/Android.bp
index 26a7d93..85e6a8b 100644
--- a/testing/Android.bp
+++ b/testing/Android.bp
@@ -12,6 +12,7 @@
 
     ],
     srcs: [
+        "all_test_specs.go",
         "test_spec.go",
         "init.go",
     ],
diff --git a/testing/all_test_specs.go b/testing/all_test_specs.go
new file mode 100644
index 0000000..2ecf15f
--- /dev/null
+++ b/testing/all_test_specs.go
@@ -0,0 +1,45 @@
+package testing
+
+import (
+	"android/soong/android"
+)
+
+const ownershipDirectory = "ownership"
+const fileContainingFilePaths = "all_test_spec_paths.rsp"
+const allTestSpecsFile = "all_test_specs.pb"
+
+func AllTestSpecsFactory() android.Singleton {
+	return &allTestSpecsSingleton{}
+}
+
+type allTestSpecsSingleton struct {
+	// Path where the collected metadata is stored after successful validation.
+	outputPath android.OutputPath
+}
+
+func (this *allTestSpecsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+	var intermediateMetadataPaths android.Paths
+
+	ctx.VisitAllModules(func(module android.Module) {
+		if !ctx.ModuleHasProvider(module, testSpecProviderKey) {
+			return
+		}
+		intermediateMetadataPaths = append(intermediateMetadataPaths, ctx.ModuleProvider(module, testSpecProviderKey).(testSpecProviderData).IntermediatePath)
+	})
+
+	rspFile := android.PathForOutput(ctx, fileContainingFilePaths)
+	this.outputPath = android.PathForOutput(ctx, ownershipDirectory, allTestSpecsFile)
+
+	rule := android.NewRuleBuilder(pctx, ctx)
+	cmd := rule.Command().
+		BuiltTool("metadata").
+		FlagWithArg("-rule ", "test_spec").
+		FlagWithRspFileInputList("-inputFile ", rspFile, intermediateMetadataPaths)
+	cmd.FlagWithOutput("-outputFile ", this.outputPath)
+	rule.Build("all_test_specs_rule", "Generate all test specifications")
+	ctx.Phony("all_test_specs", this.outputPath)
+}
+
+func (this *allTestSpecsSingleton) MakeVars(ctx android.MakeVarsContext) {
+	ctx.DistForGoal("test_specs", this.outputPath)
+}
diff --git a/testing/init.go b/testing/init.go
index 8820a60..206b430 100644
--- a/testing/init.go
+++ b/testing/init.go
@@ -18,10 +18,16 @@
 	"android/soong/android"
 )
 
+var (
+	pctx = android.NewPackageContext("android/soong/testing")
+)
+
 func init() {
 	RegisterBuildComponents(android.InitRegistrationContext)
+	pctx.HostBinToolVariable("metadata", "metadata")
 }
 
 func RegisterBuildComponents(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("test_spec", TestSpecFactory)
+	ctx.RegisterParallelSingletonType("all_test_specs", AllTestSpecsFactory)
 }