Merge "Rename test description"
diff --git a/android/sh_binary.go b/android/sh_binary.go
index 52c5a9a..8bb3517 100644
--- a/android/sh_binary.go
+++ b/android/sh_binary.go
@@ -17,6 +17,7 @@
 import (
 	"fmt"
 	"io"
+	"strings"
 )
 
 // sh_binary is for shell scripts (and batch files) that are installed as
@@ -28,6 +29,7 @@
 func init() {
 	RegisterModuleType("sh_binary", ShBinaryFactory)
 	RegisterModuleType("sh_binary_host", ShBinaryHostFactory)
+	RegisterModuleType("sh_test", ShTestFactory)
 }
 
 type shBinaryProperties struct {
@@ -48,6 +50,16 @@
 	Installable *bool
 }
 
+type TestProperties struct {
+	// list of compatibility suites (for example "cts", "vts") that the module should be
+	// installed into.
+	Test_suites []string `android:"arch_variant"`
+
+	// the name of the test configuration (for example "AndroidTest.xml") that should be
+	// installed with the module.
+	Test_config *string `android:"arch_variant"`
+}
+
 type ShBinary struct {
 	ModuleBase
 
@@ -57,6 +69,12 @@
 	outputFilePath OutputPath
 }
 
+type ShTest struct {
+	ShBinary
+
+	testProperties TestProperties
+}
+
 func (s *ShBinary) DepsMutator(ctx BottomUpMutatorContext) {
 	if s.properties.Src == nil {
 		ctx.PropertyErrorf("src", "missing prebuilt source file")
@@ -119,6 +137,16 @@
 	}
 }
 
+func (s *ShTest) AndroidMk() AndroidMkData {
+	data := s.ShBinary.AndroidMk()
+	data.Extra = append(data.Extra, func(w io.Writer, outputFile Path) {
+		fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=",
+			strings.Join(s.testProperties.Test_suites, " "))
+		fmt.Fprintln(w, "LOCAL_TEST_CONFIG :=", String(s.testProperties.Test_config))
+	})
+	return data
+}
+
 func InitShBinaryModule(s *ShBinary) {
 	s.AddProperties(&s.properties)
 }
@@ -140,3 +168,12 @@
 	InitAndroidArchModule(module, HostSupported, MultilibFirst)
 	return module
 }
+
+func ShTestFactory() Module {
+	module := &ShTest{}
+	InitShBinaryModule(&module.ShBinary)
+	module.AddProperties(&module.testProperties)
+
+	InitAndroidArchModule(module, HostAndDeviceSupported, MultilibFirst)
+	return module
+}
diff --git a/apex/apex.go b/apex/apex.go
index 341968b..a70a37b 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -613,9 +613,7 @@
 }
 
 func getCopyManifestForExecutable(cc *cc.Module) (fileToCopy android.Path, dirInApex string) {
-	// TODO(b/123721777) respect relative_install_path also for binaries
-	// dirInApex = filepath.Join("bin", cc.RelativeInstallPath())
-	dirInApex = "bin"
+	dirInApex = filepath.Join("bin", cc.RelativeInstallPath())
 	fileToCopy = cc.OutputFile().Path()
 	return
 }
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 5b767ef..f221cf2 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -696,10 +696,9 @@
 	ensureListContains(t, dirs, "lib/foo")
 	ensureListContains(t, dirs, "lib/foo/bar")
 
-	// TODO(b/123721777) respect relative path for binaries
-	// ensureListContains(t, dirs, "bin")
-	// ensureListContains(t, dirs, "bin/foo")
-	// ensureListContains(t, dirs, "bin/foo/bar")
+	ensureListContains(t, dirs, "bin")
+	ensureListContains(t, dirs, "bin/foo")
+	ensureListContains(t, dirs, "bin/foo/bar")
 }
 
 func TestUseVendor(t *testing.T) {