sh_binary can be included in APEX

Bug: 123891899
Test: m (apex_test amended)

Change-Id: Idebe577b20019fe9cd0fb6617f3b8c52a5b87714
diff --git a/apex/apex.go b/apex/apex.go
index ad1b57c..3584896 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -274,6 +274,7 @@
 	etc apexFileClass = iota
 	nativeSharedLib
 	nativeExecutable
+	shBinary
 	javaSharedLib
 )
 
@@ -333,7 +334,7 @@
 		return "ETC"
 	case nativeSharedLib:
 		return "SHARED_LIBRARIES"
-	case nativeExecutable:
+	case nativeExecutable, shBinary:
 		return "EXECUTABLES"
 	case javaSharedLib:
 		return "JAVA_LIBRARIES"
@@ -570,6 +571,12 @@
 	return
 }
 
+func getCopyManifestForShBinary(sh *android.ShBinary) (fileToCopy android.Path, dirInApex string) {
+	dirInApex = filepath.Join("bin", sh.SubDir())
+	fileToCopy = sh.OutputFile()
+	return
+}
+
 func getCopyManifestForJavaLibrary(java *java.Library) (fileToCopy android.Path, dirInApex string) {
 	dirInApex = "javalib"
 	fileToCopy = java.DexJarFile()
@@ -626,8 +633,11 @@
 					fileToCopy, dirInApex := getCopyManifestForExecutable(cc)
 					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeExecutable, cc, cc.Symlinks()})
 					return true
+				} else if sh, ok := child.(*android.ShBinary); ok {
+					fileToCopy, dirInApex := getCopyManifestForShBinary(sh)
+					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, shBinary, sh, nil})
 				} else {
-					ctx.PropertyErrorf("binaries", "%q is not a cc_binary module", depName)
+					ctx.PropertyErrorf("binaries", "%q is neithher cc_binary nor sh_binary", depName)
 				}
 			case javaLibTag:
 				if java, ok := child.(*java.Library); ok {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 1315c25..56ddd5f 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -47,6 +47,7 @@
 	ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(cc.LlndkLibraryFactory))
 	ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
 	ctx.RegisterModuleType("prebuilt_etc", android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory))
+	ctx.RegisterModuleType("sh_binary", android.ModuleFactoryAdaptor(android.ShBinaryFactory))
 	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.BottomUp("image", cc.ImageMutator).Parallel()
 		ctx.BottomUp("link", cc.LinkageMutator).Parallel()
@@ -975,3 +976,31 @@
 	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_core_shared")
 	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_core_shared")
 }
+
+func TestApexWithShBinary(t *testing.T) {
+	ctx := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			binaries: ["myscript"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		sh_binary {
+			name: "myscript",
+			src: "mylib.cpp",
+			filename: "myscript.sh",
+			sub_dir: "script",
+		}
+	`)
+
+	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+	copyCmds := apexRule.Args["copy_commands"]
+
+	ensureContains(t, copyCmds, "image.apex/bin/script/myscript.sh")
+}