Merge "Don't assume host arch is always x86"
diff --git a/android/arch.go b/android/arch.go
index 9a54614..66edf7e 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -551,6 +551,15 @@
 	}
 }()
 
+var BuildArch = func() ArchType {
+	switch runtime.GOARCH {
+	case "amd64":
+		return X86_64
+	default:
+		panic(fmt.Sprintf("unsupported Arch: %s", runtime.GOARCH))
+	}
+}()
+
 var (
 	OsTypeList      []OsType
 	commonTargetMap = make(map[string]Target)
diff --git a/android/module.go b/android/module.go
index 3374e1d..046c0a0 100644
--- a/android/module.go
+++ b/android/module.go
@@ -198,7 +198,7 @@
 	InstallInRecovery() bool
 	InstallInRoot() bool
 	InstallBypassMake() bool
-	InstallForceOS() *OsType
+	InstallForceOS() (*OsType, *ArchType)
 
 	RequiredModuleNames() []string
 	HostRequiredModuleNames() []string
@@ -254,7 +254,7 @@
 	InstallInRecovery() bool
 	InstallInRoot() bool
 	InstallBypassMake() bool
-	InstallForceOS() *OsType
+	InstallForceOS() (*OsType, *ArchType)
 	SkipInstall()
 	IsSkipInstall() bool
 	MakeUninstallable()
@@ -1120,8 +1120,8 @@
 	return false
 }
 
-func (m *ModuleBase) InstallForceOS() *OsType {
-	return nil
+func (m *ModuleBase) InstallForceOS() (*OsType, *ArchType) {
+	return nil, nil
 }
 
 func (m *ModuleBase) Owner() string {
@@ -2021,7 +2021,7 @@
 	return m.module.InstallBypassMake()
 }
 
-func (m *moduleContext) InstallForceOS() *OsType {
+func (m *moduleContext) InstallForceOS() (*OsType, *ArchType) {
 	return m.module.InstallForceOS()
 }
 
diff --git a/android/paths.go b/android/paths.go
index 6b603ba..3825d45 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -61,7 +61,7 @@
 	InstallInRecovery() bool
 	InstallInRoot() bool
 	InstallBypassMake() bool
-	InstallForceOS() *OsType
+	InstallForceOS() (*OsType, *ArchType)
 }
 
 var _ ModuleInstallPathContext = ModuleContext(nil)
@@ -1278,12 +1278,17 @@
 // module appended with paths...
 func PathForModuleInstall(ctx ModuleInstallPathContext, pathComponents ...string) InstallPath {
 	os := ctx.Os()
-	if forceOS := ctx.InstallForceOS(); forceOS != nil {
+	arch := ctx.Arch().ArchType
+	forceOS, forceArch := ctx.InstallForceOS()
+	if forceOS != nil {
 		os = *forceOS
 	}
+	if forceArch != nil {
+		arch = *forceArch
+	}
 	partition := modulePartition(ctx, os)
 
-	ret := pathForInstall(ctx, os, partition, ctx.Debug(), pathComponents...)
+	ret := pathForInstall(ctx, os, arch, partition, ctx.Debug(), pathComponents...)
 
 	if ctx.InstallBypassMake() && ctx.Config().EmbeddedInMake() {
 		ret = ret.ToMakePath()
@@ -1292,7 +1297,7 @@
 	return ret
 }
 
-func pathForInstall(ctx PathContext, os OsType, partition string, debug bool,
+func pathForInstall(ctx PathContext, os OsType, arch ArchType, partition string, debug bool,
 	pathComponents ...string) InstallPath {
 
 	var outPaths []string
@@ -1300,15 +1305,21 @@
 	if os.Class == Device {
 		outPaths = []string{"target", "product", ctx.Config().DeviceName(), partition}
 	} else {
-		switch os {
-		case Linux:
-			outPaths = []string{"host", "linux-x86", partition}
-		case LinuxBionic:
-			// TODO: should this be a separate top level, or shared with linux-x86?
-			outPaths = []string{"host", "linux_bionic-x86", partition}
-		default:
-			outPaths = []string{"host", os.String() + "-x86", partition}
+		osName := os.String()
+		if os == Linux {
+			// instead of linux_glibc
+			osName = "linux"
 		}
+		// SOONG_HOST_OUT is set to out/host/$(HOST_OS)-$(HOST_PREBUILT_ARCH)
+		// and HOST_PREBUILT_ARCH is forcibly set to x86 even on x86_64 hosts. We don't seem
+		// to have a plan to fix it (see the comment in build/make/core/envsetup.mk).
+		// Let's keep using x86 for the existing cases until we have a need to support
+		// other architectures.
+		archName := arch.String()
+		if os.Class == Host && (arch == X86_64 || arch == Common) {
+			archName = "x86"
+		}
+		outPaths = []string{"host", osName + "-" + archName, partition}
 	}
 	if debug {
 		outPaths = append([]string{"debug"}, outPaths...)
diff --git a/android/paths_test.go b/android/paths_test.go
index a9cd22b..d099f65 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -207,6 +207,7 @@
 	inRecovery     bool
 	inRoot         bool
 	forceOS        *OsType
+	forceArch      *ArchType
 }
 
 func (m moduleInstallPathContextImpl) Config() Config {
@@ -243,8 +244,8 @@
 	return false
 }
 
-func (m moduleInstallPathContextImpl) InstallForceOS() *OsType {
-	return m.forceOS
+func (m moduleInstallPathContextImpl) InstallForceOS() (*OsType, *ArchType) {
+	return m.forceOS, m.forceArch
 }
 
 func pathTestConfig(buildDir string) Config {
@@ -254,8 +255,8 @@
 func TestPathForModuleInstall(t *testing.T) {
 	testConfig := pathTestConfig("")
 
-	hostTarget := Target{Os: Linux}
-	deviceTarget := Target{Os: Android}
+	hostTarget := Target{Os: Linux, Arch: Arch{ArchType: X86}}
+	deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
 
 	testCases := []struct {
 		name string
@@ -635,6 +636,7 @@
 				},
 				inTestcases: true,
 				forceOS:     &Linux,
+				forceArch:   &X86,
 			},
 			in:  []string{"my_test", "my_test_bin"},
 			out: "host/linux-x86/testcases/my_test/my_test_bin",
diff --git a/android/test_suites.go b/android/test_suites.go
index 79d0fbc..34e487e 100644
--- a/android/test_suites.go
+++ b/android/test_suites.go
@@ -60,7 +60,7 @@
 	for _, module := range SortedStringKeys(files) {
 		installedPaths = append(installedPaths, files[module]...)
 	}
-	testCasesDir := pathForInstall(ctx, BuildOs, "testcases", false).ToMakePath()
+	testCasesDir := pathForInstall(ctx, BuildOs, X86, "testcases", false).ToMakePath()
 
 	outputFile := PathForOutput(ctx, "packaging", "robolectric-tests.zip")
 	rule := NewRuleBuilder()
diff --git a/java/robolectric.go b/java/robolectric.go
index 3fe6626..ec112bc 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -326,9 +326,11 @@
 	return module
 }
 
-func (r *robolectricTest) InstallBypassMake() bool         { return true }
-func (r *robolectricTest) InstallInTestcases() bool        { return true }
-func (r *robolectricTest) InstallForceOS() *android.OsType { return &android.BuildOs }
+func (r *robolectricTest) InstallBypassMake() bool  { return true }
+func (r *robolectricTest) InstallInTestcases() bool { return true }
+func (r *robolectricTest) InstallForceOS() (*android.OsType, *android.ArchType) {
+	return &android.BuildOs, &android.BuildArch
+}
 
 func robolectricRuntimesFactory() android.Module {
 	module := &robolectricRuntimes{}
@@ -390,6 +392,8 @@
 	}
 }
 
-func (r *robolectricRuntimes) InstallBypassMake() bool         { return true }
-func (r *robolectricRuntimes) InstallInTestcases() bool        { return true }
-func (r *robolectricRuntimes) InstallForceOS() *android.OsType { return &android.BuildOs }
+func (r *robolectricRuntimes) InstallBypassMake() bool  { return true }
+func (r *robolectricRuntimes) InstallInTestcases() bool { return true }
+func (r *robolectricRuntimes) InstallForceOS() (*android.OsType, *android.ArchType) {
+	return &android.BuildOs, &android.BuildArch
+}