Merge "Revert^2: "Remove implict jni.h include path""
diff --git a/sh/Android.bp b/sh/Android.bp
index 0b04e7d..0f40c5f 100644
--- a/sh/Android.bp
+++ b/sh/Android.bp
@@ -5,6 +5,7 @@
         "blueprint",
         "soong",
         "soong-android",
+        "soong-tradefed",
     ],
     srcs: [
         "sh_binary.go",
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 2dcd716..9276a62 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -22,6 +22,7 @@
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
+	"android/soong/tradefed"
 )
 
 // sh_binary is for shell scripts (and batch files) that are installed as
@@ -74,6 +75,19 @@
 	// list of files or filegroup modules that provide data that should be installed alongside
 	// the test.
 	Data []string `android:"path,arch_variant"`
+
+	// Add RootTargetPreparer to auto generated test config. This guarantees the test to run
+	// with root permission.
+	Require_root *bool
+
+	// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
+	// should be installed with the module.
+	Test_config_template *string `android:"path,arch_variant"`
+
+	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
+	// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
+	// explicitly.
+	Auto_gen_config *bool
 }
 
 type ShBinary struct {
@@ -93,7 +107,8 @@
 
 	testProperties TestProperties
 
-	data android.Paths
+	data       android.Paths
+	testConfig android.Path
 }
 
 func (s *ShBinary) HostToolPath() android.OptionalPath {
@@ -190,6 +205,16 @@
 	s.installedFile = ctx.InstallExecutable(installDir, s.outputFilePath.Base(), s.outputFilePath)
 
 	s.data = android.PathsForModuleSrc(ctx, s.testProperties.Data)
+
+	var configs []tradefed.Config
+	if Bool(s.testProperties.Require_root) {
+		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
+	} else {
+		options := []tradefed.Option{{Name: "force-root", Value: "false"}}
+		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options})
+	}
+	s.testConfig = tradefed.AutoGenShellTestConfig(ctx, s.testProperties.Test_config,
+		s.testProperties.Test_config_template, s.testProperties.Test_suites, configs, s.testProperties.Auto_gen_config, s.outputFilePath.Base())
 }
 
 func (s *ShTest) InstallInData() bool {
@@ -206,7 +231,13 @@
 				s.customAndroidMkEntries(entries)
 
 				entries.AddStrings("LOCAL_COMPATIBILITY_SUITE", s.testProperties.Test_suites...)
-				entries.SetString("LOCAL_TEST_CONFIG", proptools.String(s.testProperties.Test_config))
+				if s.testProperties.Test_config != nil {
+					entries.SetString("LOCAL_TEST_CONFIG", proptools.String(s.testProperties.Test_config))
+				} else {
+					if s.testConfig != nil {
+						entries.SetString("LOCAL_FULL_TEST_CONFIG", s.testConfig.String())
+					}
+				}
 				for _, d := range s.data {
 					rel := d.Rel()
 					path := d.String()
@@ -265,3 +296,5 @@
 	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
 	return module
 }
+
+var Bool = proptools.Bool
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index be44cac..2829146 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -40,9 +40,9 @@
 }
 
 var autogenTestConfig = pctx.StaticRule("autogenTestConfig", blueprint.RuleParams{
-	Command:     "sed 's&{MODULE}&${name}&g;s&{EXTRA_CONFIGS}&'${extraConfigs}'&g' $template > $out",
+	Command:     "sed 's&{MODULE}&${name}&g;s&{EXTRA_CONFIGS}&'${extraConfigs}'&g;s&{OUTPUT_FILENAME}&'${outputFileName}'&g' $template > $out",
 	CommandDeps: []string{"$template"},
-}, "name", "template", "extraConfigs")
+}, "name", "template", "extraConfigs", "outputFileName")
 
 func testConfigPath(ctx android.ModuleContext, prop *string, testSuites []string, autoGenConfig *bool, testConfigTemplateProp *string) (path android.Path, autogenPath android.WritablePath) {
 	p := getTestConfig(ctx, prop)
@@ -108,10 +108,14 @@
 }
 
 func autogenTemplate(ctx android.ModuleContext, output android.WritablePath, template string, configs []Config) {
-	autogenTemplateWithName(ctx, ctx.ModuleName(), output, template, configs)
+	autogenTemplateWithNameAndOutputFile(ctx, ctx.ModuleName(), output, template, configs, "")
 }
 
 func autogenTemplateWithName(ctx android.ModuleContext, name string, output android.WritablePath, template string, configs []Config) {
+	autogenTemplateWithNameAndOutputFile(ctx, ctx.ModuleName(), output, template, configs, "")
+}
+
+func autogenTemplateWithNameAndOutputFile(ctx android.ModuleContext, name string, output android.WritablePath, template string, configs []Config, outputFileName string) {
 	var configStrings []string
 	for _, config := range configs {
 		configStrings = append(configStrings, config.Config())
@@ -124,9 +128,10 @@
 		Description: "test config",
 		Output:      output,
 		Args: map[string]string{
-			"name":         name,
-			"template":     template,
-			"extraConfigs": extraConfigs,
+			"name":           name,
+			"template":       template,
+			"extraConfigs":   extraConfigs,
+			"outputFileName": outputFileName,
 		},
 	})
 }
@@ -150,6 +155,21 @@
 	return path
 }
 
+func AutoGenShellTestConfig(ctx android.ModuleContext, testConfigProp *string,
+	testConfigTemplateProp *string, testSuites []string, config []Config, autoGenConfig *bool, outputFileName string) android.Path {
+	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
+	if autogenPath != nil {
+		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
+		if templatePath.Valid() {
+			autogenTemplateWithNameAndOutputFile(ctx, ctx.ModuleName(), autogenPath, templatePath.String(), config, outputFileName)
+		} else {
+			autogenTemplateWithNameAndOutputFile(ctx, ctx.ModuleName(), autogenPath, "${ShellTestConfigTemplate}", config, outputFileName)
+		}
+		return autogenPath
+	}
+	return path
+}
+
 func AutoGenNativeBenchmarkTestConfig(ctx android.ModuleContext, testConfigProp *string,
 	testConfigTemplateProp *string, testSuites []string, configs []Config, autoGenConfig *bool) android.Path {
 	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
diff --git a/tradefed/config.go b/tradefed/config.go
index a289073..34195c3 100644
--- a/tradefed/config.go
+++ b/tradefed/config.go
@@ -33,6 +33,7 @@
 	pctx.SourcePathVariable("PythonBinaryHostTestConfigTemplate", "build/make/core/python_binary_host_test_config_template.xml")
 	pctx.SourcePathVariable("RustDeviceTestConfigTemplate", "build/make/core/rust_device_test_config_template.xml")
 	pctx.SourcePathVariable("RustHostTestConfigTemplate", "build/make/core/rust_host_test_config_template.xml")
+	pctx.SourcePathVariable("ShellTestConfigTemplate", "build/make/core/shell_test_config_template.xml")
 
 	pctx.SourcePathVariable("EmptyTestConfig", "build/make/core/empty_test_config.xml")
 }
diff --git a/tradefed/makevars.go b/tradefed/makevars.go
index d4cf7a8..f9682e4 100644
--- a/tradefed/makevars.go
+++ b/tradefed/makevars.go
@@ -33,6 +33,7 @@
 	ctx.Strict("PYTHON_BINARY_HOST_TEST_CONFIG_TEMPLATE", "${PythonBinaryHostTestConfigTemplate}")
 	ctx.Strict("RUST_DEVICE_TEST_CONFIG_TEMPLATE", "${RustDeviceTestConfigTemplate}")
 	ctx.Strict("RUST_HOST_TEST_CONFIG_TEMPLATE", "${RustHostTestConfigTemplate}")
+	ctx.Strict("SHELL_TEST_CONFIG_TEMPLATE", "${ShellTestConfigTemplate}")
 
 	ctx.Strict("EMPTY_TEST_CONFIG", "${EmptyTestConfig}")
 }