Add ability to force compile as 64 bit.

When trying to build a single 64 bit and 32 bit image, there are
a few executables that are prefer32. When set, this will force all
of those targets to be compiled as 64 bit.

Bug: 229787331

Test: With this option, drmserver/mediaserver are built as 64 bit.
Test: Without this option, drmserver/mediaserver are built as 32 bit.
Change-Id: I1c3dbe229f9b612ff76b857ca7163b14e7dc92c5
Merged-In: I1c3dbe229f9b612ff76b857ca7163b14e7dc92c5
diff --git a/android/arch.go b/android/arch.go
index cbf77c7..3587b46 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -655,7 +655,8 @@
 	prefer32 := os == Windows
 
 	// Determine the multilib selection for this module.
-	multilib, extraMultilib := decodeMultilib(base, os)
+	force_first_on_device := mctx.Config().ForceMultilibFirstOnDevice()
+	multilib, extraMultilib := decodeMultilib(base, os, force_first_on_device)
 
 	// Convert the multilib selection into a list of Targets.
 	targets, err := decodeMultilibTargets(multilib, osTargets, prefer32)
@@ -730,7 +731,7 @@
 // multilib from the factory's call to InitAndroidArchModule if none was set.  For modules that
 // called InitAndroidMultiTargetsArchModule it always returns "common" for multilib, and returns
 // the actual multilib in extraMultilib.
-func decodeMultilib(base *ModuleBase, os OsType) (multilib, extraMultilib string) {
+func decodeMultilib(base *ModuleBase, os OsType, force_first_on_device bool) (multilib, extraMultilib string) {
 	// First check the "android.compile_multilib" or "host.compile_multilib" properties.
 	switch os.Class {
 	case Device:
@@ -749,6 +750,13 @@
 		multilib = base.commonProperties.Default_multilib
 	}
 
+	// If a device is configured with multiple targets, this option
+	// force all device targets that prefer32 to be compiled only as
+	// the first target.
+	if force_first_on_device && os.Class == Device && (multilib == "prefer32" || multilib == "first_prefer32") {
+		multilib = "first"
+	}
+
 	if base.commonProperties.UseTargetVariants {
 		// Darwin has the concept of "universal binaries" which is implemented in Soong by
 		// building both x86_64 and arm64 variants, and having select module types know how to
diff --git a/android/config.go b/android/config.go
index ba95c5a..3c99659 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1701,6 +1701,10 @@
 	return c.config.productVariables.GenerateAidlNdkPlatformBackend
 }
 
+func (c *config) ForceMultilibFirstOnDevice() bool {
+	return c.productVariables.ForceMultilibFirstOnDevice
+}
+
 // The ConfiguredJarList struct provides methods for handling a list of (apex, jar) pairs.
 // Such lists are used in the build system for things like bootclasspath jars or system server jars.
 // The apex part is either an apex name, or a special names "platform" or "system_ext". Jar is a
diff --git a/android/variable.go b/android/variable.go
index 373891a..4420684 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -443,6 +443,8 @@
 	SepolicyFreezeTestExtraPrebuiltDirs []string `json:",omitempty"`
 
 	GenerateAidlNdkPlatformBackend bool `json:",omitempty"`
+
+	ForceMultilibFirstOnDevice bool `json:",omitempty"`
 }
 
 func boolPtr(v bool) *bool {