Refactor install paths

Explicitly allow installation into the data partition instead of using
"../data" for tests. At the same time, pipe through the information
required for vendor modules.

Change-Id: I6baf9d828c285e1080e43074beef8aebdbb38875
diff --git a/cc/cc.go b/cc/cc.go
index c532e50..183c6d6 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1359,7 +1359,7 @@
 		installDir = "lib64"
 	}
 
-	ctx.InstallFile(filepath.Join(installDir, c.Properties.Relative_install_path), c.out)
+	ctx.InstallFile(common.PathForModuleInstall(ctx, installDir, c.Properties.Relative_install_path), c.out)
 }
 
 func (c *CCLibrary) installModule(ctx common.AndroidModuleContext, flags CCFlags) {
@@ -1611,7 +1611,7 @@
 }
 
 func (c *CCBinary) installModule(ctx common.AndroidModuleContext, flags CCFlags) {
-	c.installFile = ctx.InstallFile(filepath.Join("bin", c.Properties.Relative_install_path), c.out)
+	c.installFile = ctx.InstallFile(common.PathForModuleInstall(ctx, "bin", c.Properties.Relative_install_path), c.out)
 }
 
 func (c *CCBinary) HostToolPath() common.OptionalPath {
@@ -1678,9 +1678,17 @@
 	return depNames
 }
 
+func (c *CCTest) InstallInData() bool {
+	return true
+}
+
 func (c *CCTest) installModule(ctx common.AndroidModuleContext, flags CCFlags) {
 	if ctx.Device() {
-		ctx.InstallFile("../data/nativetest"+ctx.Arch().ArchType.Multilib[3:]+"/"+ctx.ModuleName(), c.out)
+		installDir := "nativetest"
+		if flags.Toolchain.Is64Bit() {
+			installDir = "nativetest64"
+		}
+		ctx.InstallFile(common.PathForModuleInstall(ctx, installDir, ctx.ModuleName()), c.out)
 	} else {
 		c.CCBinary.installModule(ctx, flags)
 	}
@@ -1708,9 +1716,17 @@
 	return depNames
 }
 
+func (c *CCBenchmark) InstallInData() bool {
+	return true
+}
+
 func (c *CCBenchmark) installModule(ctx common.AndroidModuleContext, flags CCFlags) {
 	if ctx.Device() {
-		ctx.InstallFile("../data/nativetest"+ctx.Arch().ArchType.Multilib[3:]+"/"+ctx.ModuleName(), c.out)
+		installDir := "nativetest"
+		if flags.Toolchain.Is64Bit() {
+			installDir = "nativetest64"
+		}
+		ctx.InstallFile(common.PathForModuleInstall(ctx, installDir, ctx.ModuleName()), c.out)
 	} else {
 		c.CCBinary.installModule(ctx, flags)
 	}
diff --git a/common/module.go b/common/module.go
index a2b2efa..0f6ecb5 100644
--- a/common/module.go
+++ b/common/module.go
@@ -56,6 +56,8 @@
 	Darwin() bool
 	Debug() bool
 	AConfig() Config
+	Proprietary() bool
+	InstallInData() bool
 }
 
 type AndroidBaseContext interface {
@@ -74,8 +76,8 @@
 	ExpandSources(srcFiles, excludes []string) Paths
 	Glob(outDir, globPattern string, excludes []string) Paths
 
-	InstallFile(installPath string, srcPath Path, deps ...Path) Path
-	InstallFileName(installPath, name string, srcPath Path, deps ...Path) Path
+	InstallFile(installPath OutputPath, srcPath Path, deps ...Path) Path
+	InstallFileName(installPath OutputPath, name string, srcPath Path, deps ...Path) Path
 	CheckbuildFile(srcPath Path)
 }
 
@@ -87,6 +89,7 @@
 	base() *AndroidModuleBase
 	Enabled() bool
 	HostOrDevice() HostOrDevice
+	InstallInData() bool
 }
 
 type commonProperties struct {
@@ -103,6 +106,9 @@
 	// platform
 	Compile_multilib string
 
+	// whether this is a proprietary vendor module, and should be installed into /vendor
+	Proprietary bool
+
 	// Set by HostOrDeviceMutator
 	CompileHostOrDevice HostOrDevice `blueprint:"mutated"`
 
@@ -294,6 +300,10 @@
 	return p.noAddressSanitizer
 }
 
+func (p *AndroidModuleBase) InstallInData() bool {
+	return false
+}
+
 func (a *AndroidModuleBase) generateModuleTarget(ctx blueprint.ModuleContext) {
 	if a != ctx.FinalModule().(AndroidModule).base() {
 		return
@@ -352,10 +362,12 @@
 
 func (a *AndroidModuleBase) androidBaseContextFactory(ctx blueprint.BaseModuleContext) androidBaseContextImpl {
 	return androidBaseContextImpl{
-		arch:   a.commonProperties.CompileArch,
-		hod:    a.commonProperties.CompileHostOrDevice,
-		ht:     a.commonProperties.CompileHostType,
-		config: ctx.Config().(Config),
+		arch:          a.commonProperties.CompileArch,
+		hod:           a.commonProperties.CompileHostOrDevice,
+		ht:            a.commonProperties.CompileHostType,
+		proprietary:   a.commonProperties.Proprietary,
+		config:        ctx.Config().(Config),
+		installInData: a.module.InstallInData(),
 	}
 }
 
@@ -387,11 +399,13 @@
 }
 
 type androidBaseContextImpl struct {
-	arch   Arch
-	hod    HostOrDevice
-	ht     HostType
-	debug  bool
-	config Config
+	arch          Arch
+	hod           HostOrDevice
+	ht            HostType
+	debug         bool
+	config        Config
+	proprietary   bool
+	installInData bool
 }
 
 type androidModuleContext struct {
@@ -492,10 +506,18 @@
 	return a.config
 }
 
-func (a *androidModuleContext) InstallFileName(installPath, name string, srcPath Path,
+func (a *androidBaseContextImpl) Proprietary() bool {
+	return a.proprietary
+}
+
+func (a *androidBaseContextImpl) InstallInData() bool {
+	return a.installInData
+}
+
+func (a *androidModuleContext) InstallFileName(installPath OutputPath, name string, srcPath Path,
 	deps ...Path) Path {
 
-	fullInstallPath := PathForModuleInstall(a, installPath, name)
+	fullInstallPath := installPath.Join(a, name)
 
 	deps = append(deps, a.installDeps...)
 
@@ -512,7 +534,7 @@
 	return fullInstallPath
 }
 
-func (a *androidModuleContext) InstallFile(installPath string, srcPath Path, deps ...Path) Path {
+func (a *androidModuleContext) InstallFile(installPath OutputPath, srcPath Path, deps ...Path) Path {
 	return a.InstallFileName(installPath, filepath.Base(srcPath.String()), srcPath, deps...)
 }
 
diff --git a/common/paths.go b/common/paths.go
index e0d4914..2bbb72c 100644
--- a/common/paths.go
+++ b/common/paths.go
@@ -601,10 +601,20 @@
 func PathForModuleInstall(ctx AndroidModuleContext, paths ...string) OutputPath {
 	var outPaths []string
 	if ctx.Device() {
-		outPaths = []string{"target", "product", ctx.AConfig().DeviceName(), "system"}
+		partition := "system"
+		if ctx.Proprietary() {
+			partition = "vendor"
+		}
+		if ctx.InstallInData() {
+			partition = "data"
+		}
+		outPaths = []string{"target", "product", ctx.AConfig().DeviceName(), partition}
 	} else {
 		outPaths = []string{"host", ctx.HostType().String() + "-x86"}
 	}
+	if ctx.Debug() {
+		outPaths = append([]string{"debug"}, outPaths...)
+	}
 	outPaths = append(outPaths, paths...)
 	return PathForOutput(ctx, outPaths...)
 }
diff --git a/java/app.go b/java/app.go
index f0eb3c8..3d16281 100644
--- a/java/app.go
+++ b/java/app.go
@@ -152,7 +152,7 @@
 	}
 
 	a.outputFile = CreateAppPackage(ctx, aaptPackageFlags, a.outputFile, certificates)
-	ctx.InstallFileName("app", ctx.ModuleName()+".apk", a.outputFile)
+	ctx.InstallFileName(common.PathForModuleInstall(ctx, "app"), ctx.ModuleName()+".apk", a.outputFile)
 }
 
 var aaptIgnoreFilenames = []string{
diff --git a/java/java.go b/java/java.go
index 839fb01..db1ae05 100644
--- a/java/java.go
+++ b/java/java.go
@@ -442,7 +442,7 @@
 func (j *JavaLibrary) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
 	j.javaBase.GenerateJavaBuildActions(ctx)
 
-	j.installFile = ctx.InstallFileName("framework", ctx.ModuleName()+".jar", j.outputFile)
+	j.installFile = ctx.InstallFileName(common.PathForModuleInstall(ctx, "framework"), ctx.ModuleName()+".jar", j.outputFile)
 }
 
 func JavaLibraryFactory() (blueprint.Module, []interface{}) {
@@ -479,7 +479,7 @@
 
 	// Depend on the installed jar (j.installFile) so that the wrapper doesn't get executed by
 	// another build rule before the jar has been installed.
-	ctx.InstallFile("bin", common.PathForModuleSrc(ctx, j.binaryProperties.Wrapper),
+	ctx.InstallFile(common.PathForModuleInstall(ctx, "bin"), common.PathForModuleSrc(ctx, j.binaryProperties.Wrapper),
 		j.installFile)
 }
 
@@ -526,7 +526,7 @@
 	j.classpathFile = prebuilt
 	j.classJarSpecs = []jarSpec{classJarSpec}
 	j.resourceJarSpecs = []jarSpec{resourceJarSpec}
-	ctx.InstallFileName("framework", ctx.ModuleName()+".jar", j.classpathFile)
+	ctx.InstallFileName(common.PathForModuleInstall(ctx, "framework"), ctx.ModuleName()+".jar", j.classpathFile)
 }
 
 var _ JavaDependency = (*JavaPrebuilt)(nil)