APEX respects relative_install_path

relative_install_path for cc_library is respected by APEX.

relative_install_path for cc_binary is not yet respected because doing
it will break the path to the dynamic linker in the runtime APEX.
That change should be done along with changes in init, bionic, etc.

Bug: 123721777
Test: m (apex_test.go amended)
Change-Id: I855f8eda0d4255d563861ac96d0d3e2c669e9a2a
diff --git a/apex/apex.go b/apex/apex.go
index f6daf9b..eb791d9 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -540,6 +540,7 @@
 	case "lib64":
 		dirInApex = "lib64"
 	}
+	dirInApex = filepath.Join(dirInApex, cc.RelativeInstallPath())
 	if !cc.Arch().Native {
 		dirInApex = filepath.Join(dirInApex, cc.Arch().ArchType.String())
 	}
@@ -564,6 +565,8 @@
 }
 
 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"
 	fileToCopy = cc.OutputFile().Path()
 	return
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 9d33060..1315c25 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -615,7 +615,10 @@
 		apex {
 			name: "myapex",
 			key: "myapex.key",
+			native_shared_libs: ["mylib"],
+			binaries: ["mybin"],
 			prebuilts: ["myetc"],
+			compile_multilib: "both",
 		}
 
 		apex_key {
@@ -629,15 +632,43 @@
 			src: "myprebuilt",
 			sub_dir: "foo/bar",
 		}
+
+		cc_library {
+			name: "mylib",
+			srcs: ["mylib.cpp"],
+			relative_install_path: "foo/bar",
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		cc_binary {
+			name: "mybin",
+			srcs: ["mylib.cpp"],
+			relative_install_path: "foo/bar",
+			system_shared_libs: [],
+			static_executable: true,
+			stl: "none",
+		}
 	`)
 
 	generateFsRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("generateFsConfig")
 	dirs := strings.Split(generateFsRule.Args["exec_paths"], " ")
 
-	// Ensure that etc, etc/foo, and etc/foo/bar are all listed
+	// Ensure that the subdirectories are all listed
 	ensureListContains(t, dirs, "etc")
 	ensureListContains(t, dirs, "etc/foo")
 	ensureListContains(t, dirs, "etc/foo/bar")
+	ensureListContains(t, dirs, "lib64")
+	ensureListContains(t, dirs, "lib64/foo")
+	ensureListContains(t, dirs, "lib64/foo/bar")
+	ensureListContains(t, dirs, "lib")
+	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")
 }
 
 func TestUseVendor(t *testing.T) {
diff --git a/cc/cc.go b/cc/cc.go
index 5a2f0ae..02f36d5 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -315,6 +315,7 @@
 	inData() bool
 	inSanitizerDir() bool
 	hostToolPath() android.OptionalPath
+	relativeInstallPath() string
 }
 
 type dependencyTag struct {
@@ -413,6 +414,13 @@
 	return nil
 }
 
+func (c *Module) RelativeInstallPath() string {
+	if c.installer != nil {
+		return c.installer.relativeInstallPath()
+	}
+	return ""
+}
+
 func (c *Module) Init() android.Module {
 	c.AddProperties(&c.Properties, &c.VendorProperties)
 	if c.compiler != nil {
diff --git a/cc/installer.go b/cc/installer.go
index 33f29f2..bd8f9e7 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -73,7 +73,7 @@
 		dir = filepath.Join(dir, "vendor")
 	}
 	return android.PathForModuleInstall(ctx, dir, installer.subDir,
-		String(installer.Properties.Relative_install_path), installer.relative)
+		installer.relativeInstallPath(), installer.relative)
 }
 
 func (installer *baseInstaller) install(ctx ModuleContext, file android.Path) {
@@ -91,3 +91,7 @@
 func (installer *baseInstaller) hostToolPath() android.OptionalPath {
 	return android.OptionalPath{}
 }
+
+func (installer *baseInstaller) relativeInstallPath() string {
+	return String(installer.Properties.Relative_install_path)
+}