Add support for the remote execution of metalava actions.

Test: built aosp crosshatch userdebug with RBE_METALAVA=1
Change-Id: I3d42d75b4522f99ff95ce8c997ead782e4322f6e
diff --git a/remoteexec/remoteexec.go b/remoteexec/remoteexec.go
index 860db55..99e29dc 100644
--- a/remoteexec/remoteexec.go
+++ b/remoteexec/remoteexec.go
@@ -82,17 +82,31 @@
 
 func init() {
 	pctx.VariableFunc("Wrapper", func(ctx android.PackageVarContext) string {
-		if override := ctx.Config().Getenv("RBE_WRAPPER"); override != "" {
-			return override
-		}
-		return DefaultWrapperPath
+		return wrapper(ctx.Config())
 	})
 }
 
-// Generate the remote execution wrapper template to be added as a prefix to the rule's command.
-func (r *REParams) Template() string {
-	template := "${remoteexec.Wrapper}"
+func wrapper(cfg android.Config) string {
+	if override := cfg.Getenv("RBE_WRAPPER"); override != "" {
+		return override
+	}
+	return DefaultWrapperPath
+}
 
+// Template generates the remote execution wrapper template to be added as a prefix to the rule's
+// command.
+func (r *REParams) Template() string {
+	return "${remoteexec.Wrapper}" + r.wrapperArgs()
+}
+
+// NoVarTemplate generate the remote execution wrapper template without variables, to be used in
+// RuleBuilder.
+func (r *REParams) NoVarTemplate(cfg android.Config) string {
+	return wrapper(cfg) + r.wrapperArgs()
+}
+
+func (r *REParams) wrapperArgs() string {
+	args := ""
 	var kvs []string
 	labels := r.Labels
 	if len(labels) == 0 {
@@ -102,7 +116,7 @@
 		kvs = append(kvs, k+"="+v)
 	}
 	sort.Strings(kvs)
-	template += " --labels=" + strings.Join(kvs, ",")
+	args += " --labels=" + strings.Join(kvs, ",")
 
 	var platform []string
 	for k, v := range r.Platform {
@@ -116,32 +130,32 @@
 	}
 	if platform != nil {
 		sort.Strings(platform)
-		template += " --platform=\"" + strings.Join(platform, ",") + "\""
+		args += " --platform=\"" + strings.Join(platform, ",") + "\""
 	}
 
 	strategy := r.ExecStrategy
 	if strategy == "" {
 		strategy = defaultExecStrategy
 	}
-	template += " --exec_strategy=" + strategy
+	args += " --exec_strategy=" + strategy
 
 	if len(r.Inputs) > 0 {
-		template += " --inputs=" + strings.Join(r.Inputs, ",")
+		args += " --inputs=" + strings.Join(r.Inputs, ",")
 	}
 
 	if r.RSPFile != "" {
-		template += " --input_list_paths=" + r.RSPFile
+		args += " --input_list_paths=" + r.RSPFile
 	}
 
 	if len(r.OutputFiles) > 0 {
-		template += " --output_files=" + strings.Join(r.OutputFiles, ",")
+		args += " --output_files=" + strings.Join(r.OutputFiles, ",")
 	}
 
 	if len(r.ToolchainInputs) > 0 {
-		template += " --toolchain_inputs=" + strings.Join(r.ToolchainInputs, ",")
+		args += " --toolchain_inputs=" + strings.Join(r.ToolchainInputs, ",")
 	}
 
-	return template + " -- "
+	return args + " -- "
 }
 
 // StaticRules returns a pair of rules based on the given RuleParams, where the first rule is a
diff --git a/remoteexec/remoteexec_test.go b/remoteexec/remoteexec_test.go
index 30e891c..56985d3 100644
--- a/remoteexec/remoteexec_test.go
+++ b/remoteexec/remoteexec_test.go
@@ -17,6 +17,8 @@
 import (
 	"fmt"
 	"testing"
+
+	"android/soong/android"
 )
 
 func TestTemplate(t *testing.T) {
@@ -64,6 +66,22 @@
 	}
 }
 
+func TestNoVarTemplate(t *testing.T) {
+	params := &REParams{
+		Labels:      map[string]string{"type": "compile", "lang": "cpp", "compiler": "clang"},
+		Inputs:      []string{"$in"},
+		OutputFiles: []string{"$out"},
+		Platform: map[string]string{
+			ContainerImageKey: DefaultImage,
+			PoolKey:           "default",
+		},
+	}
+	want := fmt.Sprintf("prebuilts/remoteexecution-client/live/rewrapper --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=local --inputs=$in --output_files=$out -- ", DefaultImage)
+	if got := params.NoVarTemplate(android.NullConfig("")); got != want {
+		t.Errorf("NoVarTemplate() returned\n%s\nwant\n%s", got, want)
+	}
+}
+
 func TestTemplateDeterminism(t *testing.T) {
 	r := &REParams{
 		Labels:      map[string]string{"type": "compile", "lang": "cpp", "compiler": "clang"},