Merge "Add type information to symbolfile and ndkstubgen."
diff --git a/android/androidmk.go b/android/androidmk.go
index fafbfd6..e90e5f0 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -304,15 +304,16 @@
 	host := false
 	switch amod.Os().Class {
 	case Host:
-		// Make cannot identify LOCAL_MODULE_HOST_ARCH:= common.
-		if amod.Arch().ArchType != Common {
-			a.SetString("LOCAL_MODULE_HOST_ARCH", archStr)
-		}
-		host = true
-	case HostCross:
-		// Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common.
-		if amod.Arch().ArchType != Common {
-			a.SetString("LOCAL_MODULE_HOST_CROSS_ARCH", archStr)
+		if amod.Target().HostCross {
+			// Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common.
+			if amod.Arch().ArchType != Common {
+				a.SetString("LOCAL_MODULE_HOST_CROSS_ARCH", archStr)
+			}
+		} else {
+			// Make cannot identify LOCAL_MODULE_HOST_ARCH:= common.
+			if amod.Arch().ArchType != Common {
+				a.SetString("LOCAL_MODULE_HOST_ARCH", archStr)
+			}
 		}
 		host = true
 	case Device:
@@ -359,9 +360,11 @@
 	if amod.ArchSpecific() {
 		switch amod.Os().Class {
 		case Host:
-			prefix = "HOST_"
-		case HostCross:
-			prefix = "HOST_CROSS_"
+			if amod.Target().HostCross {
+				prefix = "HOST_CROSS_"
+			} else {
+				prefix = "HOST_"
+			}
 		case Device:
 			prefix = "TARGET_"
 
@@ -563,9 +566,11 @@
 	if amod.ArchSpecific() {
 		switch amod.Os().Class {
 		case Host:
-			prefix = "HOST_"
-		case HostCross:
-			prefix = "HOST_CROSS_"
+			if amod.Target().HostCross {
+				prefix = "HOST_CROSS_"
+			} else {
+				prefix = "HOST_"
+			}
 		case Device:
 			prefix = "TARGET_"
 
diff --git a/android/arch.go b/android/arch.go
index eb3c709..f4b0d66 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -590,7 +590,7 @@
 	Linux       = NewOsType("linux_glibc", Host, false)
 	Darwin      = NewOsType("darwin", Host, false)
 	LinuxBionic = NewOsType("linux_bionic", Host, false)
-	Windows     = NewOsType("windows", HostCross, true)
+	Windows     = NewOsType("windows", Host, true)
 	Android     = NewOsType("android", Device, false)
 	Fuchsia     = NewOsType("fuchsia", Device, false)
 
@@ -621,7 +621,6 @@
 	Generic OsClass = iota
 	Device
 	Host
-	HostCross
 )
 
 func (class OsClass) String() string {
@@ -632,8 +631,6 @@
 		return "device"
 	case Host:
 		return "host"
-	case HostCross:
-		return "host cross"
 	default:
 		panic(fmt.Errorf("unknown class %d", class))
 	}
@@ -693,6 +690,11 @@
 	NativeBridge             NativeBridgeSupport
 	NativeBridgeHostArchName string
 	NativeBridgeRelativePath string
+
+	// HostCross is true when the target cannot run natively on the current build host.
+	// For example, linux_glibc_x86 returns true on a regular x86/i686/Linux machines, but returns false
+	// on Mac (different OS), or on 64-bit only i686/Linux machines (unsupported arch).
+	HostCross bool
 }
 
 func (target Target) String() string {
@@ -751,26 +753,15 @@
 		return
 	}
 
-	osClasses := base.OsClassSupported()
-
 	var moduleOSList []OsType
 
 	for _, os := range OsTypeList {
-		supportedClass := false
-		for _, osClass := range osClasses {
-			if os.Class == osClass {
-				supportedClass = true
+		for _, t := range mctx.Config().Targets[os] {
+			if base.supportsTarget(t, mctx.Config()) {
+				moduleOSList = append(moduleOSList, os)
+				break
 			}
 		}
-		if !supportedClass {
-			continue
-		}
-
-		if len(mctx.Config().Targets[os]) == 0 {
-			continue
-		}
-
-		moduleOSList = append(moduleOSList, os)
 	}
 
 	if len(moduleOSList) == 0 {
@@ -925,7 +916,7 @@
 
 	prefer32 := false
 	if base.prefer32 != nil {
-		prefer32 = base.prefer32(mctx, base, os.Class)
+		prefer32 = base.prefer32(mctx, base, os)
 	}
 
 	multilib, extraMultilib := decodeMultilib(base, os.Class)
@@ -976,7 +967,7 @@
 	switch class {
 	case Device:
 		multilib = String(base.commonProperties.Target.Android.Compile_multilib)
-	case Host, HostCross:
+	case Host:
 		multilib = String(base.commonProperties.Target.Host.Compile_multilib)
 	}
 	if multilib == "" {
@@ -1252,7 +1243,7 @@
 			//         key: value,
 			//     },
 			// },
-			if os.Class == Host || os.Class == HostCross {
+			if os.Class == Host {
 				field := "Host"
 				prefix := "target.host"
 				m.appendProperties(ctx, genProps, targetProp, field, prefix)
@@ -1292,7 +1283,7 @@
 			prefix := "target." + os.Name
 			m.appendProperties(ctx, genProps, targetProp, field, prefix)
 
-			if (os.Class == Host || os.Class == HostCross) && os != Windows {
+			if os.Class == Host && os != Windows {
 				field := "Not_windows"
 				prefix := "target.not_windows"
 				m.appendProperties(ctx, genProps, targetProp, field, prefix)
@@ -1520,6 +1511,36 @@
 			nativeBridgeRelativePathStr = arch.ArchType.String()
 		}
 
+		// A target is considered as HostCross if it's a host target which can't run natively on
+		// the currently configured build machine (either because the OS is different or because of
+		// the unsupported arch)
+		hostCross := false
+		if os.Class == Host {
+			var osSupported bool
+			if os == BuildOs {
+				osSupported = true
+			} else if BuildOs.Linux() && os.Linux() {
+				// LinuxBionic and Linux are compatible
+				osSupported = true
+			} else {
+				osSupported = false
+			}
+
+			var archSupported bool
+			if arch.ArchType == Common {
+				archSupported = true
+			} else if arch.ArchType.Name == *variables.HostArch {
+				archSupported = true
+			} else if variables.HostSecondaryArch != nil && arch.ArchType.Name == *variables.HostSecondaryArch {
+				archSupported = true
+			} else {
+				archSupported = false
+			}
+			if !osSupported || !archSupported {
+				hostCross = true
+			}
+		}
+
 		targets[os] = append(targets[os],
 			Target{
 				Os:                       os,
@@ -1527,6 +1548,7 @@
 				NativeBridge:             nativeBridgeEnabled,
 				NativeBridgeHostArchName: nativeBridgeHostArchNameStr,
 				NativeBridgeRelativePath: nativeBridgeRelativePathStr,
+				HostCross:                hostCross,
 			})
 	}
 
@@ -1543,6 +1565,9 @@
 	if Bool(config.Host_bionic) {
 		addTarget(LinuxBionic, "x86_64", nil, nil, nil, NativeBridgeDisabled, nil, nil)
 	}
+	if Bool(config.Host_bionic_arm64) {
+		addTarget(LinuxBionic, "arm64", nil, nil, nil, NativeBridgeDisabled, nil, nil)
+	}
 
 	if String(variables.CrossHost) != "" {
 		crossHostOs := osByName(*variables.CrossHost)
@@ -1783,13 +1808,22 @@
 }
 
 func firstTarget(targets []Target, filters ...string) []Target {
+	// find the first target from each OS
+	var ret []Target
+	hasHost := false
+	set := make(map[OsType]bool)
+
 	for _, filter := range filters {
 		buildTargets := filterMultilibTargets(targets, filter)
-		if len(buildTargets) > 0 {
-			return buildTargets[:1]
+		for _, t := range buildTargets {
+			if _, found := set[t.Os]; !found {
+				hasHost = hasHost || (t.Os.Class == Host)
+				set[t.Os] = true
+				ret = append(ret, t)
+			}
 		}
 	}
-	return nil
+	return ret
 }
 
 // Use the module multilib setting to select one or more targets from a target list
diff --git a/android/config.go b/android/config.go
index f5deeee..8df65f7 100644
--- a/android/config.go
+++ b/android/config.go
@@ -51,8 +51,9 @@
 // A FileConfigurableOptions contains options which can be configured by the
 // config file. These will be included in the config struct.
 type FileConfigurableOptions struct {
-	Mega_device *bool `json:",omitempty"`
-	Host_bionic *bool `json:",omitempty"`
+	Mega_device       *bool `json:",omitempty"`
+	Host_bionic       *bool `json:",omitempty"`
+	Host_bionic_arm64 *bool `json:",omitempty"`
 }
 
 func (f *FileConfigurableOptions) SetDefaultConfig() {
@@ -267,10 +268,10 @@
 	config := testConfig.config
 
 	config.Targets[Android] = []Target{
-		{Android, Arch{ArchType: X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", ""},
-		{Android, Arch{ArchType: X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", ""},
-		{Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeEnabled, "x86_64", "arm64"},
-		{Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeEnabled, "x86", "arm"},
+		{Android, Arch{ArchType: X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", "", false},
+		{Android, Arch{ArchType: X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", "", false},
+		{Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeEnabled, "x86_64", "arm64", false},
+		{Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeEnabled, "x86", "arm", false},
 	}
 
 	return testConfig
@@ -282,10 +283,10 @@
 
 	config.Targets = map[OsType][]Target{
 		Fuchsia: []Target{
-			{Fuchsia, Arch{ArchType: Arm64, ArchVariant: "", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", ""},
+			{Fuchsia, Arch{ArchType: Arm64, ArchVariant: "", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", "", false},
 		},
 		BuildOs: []Target{
-			{BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", ""},
+			{BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", false},
 		},
 	}
 
@@ -299,12 +300,12 @@
 
 	config.Targets = map[OsType][]Target{
 		Android: []Target{
-			{Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", ""},
-			{Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", ""},
+			{Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", "", false},
+			{Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", "", false},
 		},
 		BuildOs: []Target{
-			{BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", ""},
-			{BuildOs, Arch{ArchType: X86}, NativeBridgeDisabled, "", ""},
+			{BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", false},
+			{BuildOs, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", false},
 		},
 	}
 
diff --git a/android/module.go b/android/module.go
index d3341d2..f5adc54 100644
--- a/android/module.go
+++ b/android/module.go
@@ -948,7 +948,7 @@
 	initRcPaths         Paths
 	vintfFragmentsPaths Paths
 
-	prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool
+	prefer32 func(ctx BaseModuleContext, base *ModuleBase, os OsType) bool
 }
 
 func (m *ModuleBase) ComponentDepsMutator(BottomUpMutatorContext) {}
@@ -975,7 +975,7 @@
 	return m.variables
 }
 
-func (m *ModuleBase) Prefer32(prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool) {
+func (m *ModuleBase) Prefer32(prefer32 func(ctx BaseModuleContext, base *ModuleBase, os OsType) bool) {
 	m.prefer32 = prefer32
 }
 
@@ -1071,7 +1071,7 @@
 }
 
 func (m *ModuleBase) Host() bool {
-	return m.Os().Class == Host || m.Os().Class == HostCross
+	return m.Os().Class == Host
 }
 
 func (m *ModuleBase) Device() bool {
@@ -1091,28 +1091,28 @@
 	return m.commonProperties.CommonOSVariant
 }
 
-func (m *ModuleBase) OsClassSupported() []OsClass {
+func (m *ModuleBase) supportsTarget(target Target, config Config) bool {
 	switch m.commonProperties.HostOrDeviceSupported {
 	case HostSupported:
-		return []OsClass{Host, HostCross}
+		return target.Os.Class == Host
 	case HostSupportedNoCross:
-		return []OsClass{Host}
+		return target.Os.Class == Host && !target.HostCross
 	case DeviceSupported:
-		return []OsClass{Device}
+		return target.Os.Class == Device
 	case HostAndDeviceSupported, HostAndDeviceDefault:
-		var supported []OsClass
+		supported := false
 		if Bool(m.hostAndDeviceProperties.Host_supported) ||
 			(m.commonProperties.HostOrDeviceSupported == HostAndDeviceDefault &&
 				m.hostAndDeviceProperties.Host_supported == nil) {
-			supported = append(supported, Host, HostCross)
+			supported = supported || target.Os.Class == Host
 		}
 		if m.hostAndDeviceProperties.Device_supported == nil ||
 			*m.hostAndDeviceProperties.Device_supported {
-			supported = append(supported, Device)
+			supported = supported || target.Os.Class == Device
 		}
 		return supported
 	default:
-		return nil
+		return false
 	}
 }
 
@@ -2115,7 +2115,7 @@
 }
 
 func (b *baseModuleContext) Host() bool {
-	return b.os.Class == Host || b.os.Class == HostCross
+	return b.os.Class == Host
 }
 
 func (b *baseModuleContext) Device() bool {
@@ -2575,30 +2575,36 @@
 	}
 
 	// Create (host|host-cross|target)-<OS> phony rules to build a reduced checkbuild.
-	osDeps := map[OsType]Paths{}
+	type osAndCross struct {
+		os        OsType
+		hostCross bool
+	}
+	osDeps := map[osAndCross]Paths{}
 	ctx.VisitAllModules(func(module Module) {
 		if module.Enabled() {
-			os := module.Target().Os
-			osDeps[os] = append(osDeps[os], module.base().checkbuildFiles...)
+			key := osAndCross{os: module.Target().Os, hostCross: module.Target().HostCross}
+			osDeps[key] = append(osDeps[key], module.base().checkbuildFiles...)
 		}
 	})
 
 	osClass := make(map[string]Paths)
-	for os, deps := range osDeps {
+	for key, deps := range osDeps {
 		var className string
 
-		switch os.Class {
+		switch key.os.Class {
 		case Host:
-			className = "host"
-		case HostCross:
-			className = "host-cross"
+			if key.hostCross {
+				className = "host-cross"
+			} else {
+				className = "host"
+			}
 		case Device:
 			className = "target"
 		default:
 			continue
 		}
 
-		name := className + "-" + os.Name
+		name := className + "-" + key.os.Name
 		osClass[className] = append(osClass[className], PathForPhony(ctx, name))
 
 		ctx.Phony(name, deps...)
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index 6c3cd9e..854395e 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -285,7 +285,7 @@
 				t.Errorf("windows is assumed to be disabled by default")
 			}
 			config.config.Targets[Windows] = []Target{
-				{Windows, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", ""},
+				{Windows, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", true},
 			}
 
 			ctx := NewTestArchContext()
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 1b53a67..c4fe3a3 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -157,13 +157,14 @@
 			host := false
 			switch fi.module.Target().Os.Class {
 			case android.Host:
-				if fi.module.Target().Arch.ArchType != android.Common {
-					fmt.Fprintln(w, "LOCAL_MODULE_HOST_ARCH :=", archStr)
-				}
-				host = true
-			case android.HostCross:
-				if fi.module.Target().Arch.ArchType != android.Common {
-					fmt.Fprintln(w, "LOCAL_MODULE_HOST_CROSS_ARCH :=", archStr)
+				if fi.module.Target().HostCross {
+					if fi.module.Target().Arch.ArchType != android.Common {
+						fmt.Fprintln(w, "LOCAL_MODULE_HOST_CROSS_ARCH :=", archStr)
+					}
+				} else {
+					if fi.module.Target().Arch.ArchType != android.Common {
+						fmt.Fprintln(w, "LOCAL_MODULE_HOST_ARCH :=", archStr)
+					}
 				}
 				host = true
 			case android.Device:
diff --git a/cc/cc.go b/cc/cc.go
index 9877cc6..e71f859 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -950,9 +950,9 @@
 		c.AddProperties(feature.props()...)
 	}
 
-	c.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
+	c.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, os android.OsType) bool {
 		// Windows builds always prefer 32-bit
-		return class == android.HostCross
+		return os == android.Windows
 	})
 	android.InitAndroidArchModule(c, c.hod, c.multilib)
 	android.InitApexModule(c)
diff --git a/cc/lto.go b/cc/lto.go
index d1903b8..3e1acdf 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -45,6 +45,8 @@
 		Thin  *bool `android:"arch_variant"`
 	} `android:"arch_variant"`
 
+	GlobalThin *bool `blueprint:"mutated"`
+
 	// Dep properties indicate that this module needs to be built with LTO
 	// since it is an object dependency of an LTO module.
 	FullDep bool `blueprint:"mutated"`
@@ -68,6 +70,8 @@
 func (lto *lto) begin(ctx BaseModuleContext) {
 	if ctx.Config().IsEnvTrue("DISABLE_LTO") {
 		lto.Properties.Lto.Never = boolPtr(true)
+	} else if ctx.Config().IsEnvTrue("GLOBAL_THINLTO") {
+		lto.Properties.GlobalThin = boolPtr(true)
 	}
 }
 
@@ -91,7 +95,7 @@
 
 	if lto.LTO() {
 		var ltoFlag string
-		if Bool(lto.Properties.Lto.Thin) {
+		if lto.ThinLTO() {
 			ltoFlag = "-flto=thin -fsplit-lto-unit"
 		} else {
 			ltoFlag = "-flto"
@@ -104,7 +108,7 @@
 			flags.Local.CFlags = append(flags.Local.CFlags, "-fwhole-program-vtables")
 		}
 
-		if ctx.Config().IsEnvTrue("USE_THINLTO_CACHE") && Bool(lto.Properties.Lto.Thin) && lto.useClangLld(ctx) {
+		if lto.ThinLTO() && ctx.Config().IsEnvTrue("USE_THINLTO_CACHE") && lto.useClangLld(ctx) {
 			// Set appropriate ThinLTO cache policy
 			cacheDirFormat := "-Wl,--thinlto-cache-dir="
 			cacheDir := android.PathForOutput(ctx, "thinlto-cache").String()
@@ -133,9 +137,21 @@
 		return false
 	}
 
-	full := Bool(lto.Properties.Lto.Full)
-	thin := Bool(lto.Properties.Lto.Thin)
-	return full || thin
+	return lto.FullLTO() || lto.ThinLTO()
+}
+
+func (lto *lto) FullLTO() bool {
+	return Bool(lto.Properties.Lto.Full)
+}
+
+func (lto *lto) ThinLTO() bool {
+	if Bool(lto.Properties.GlobalThin) {
+		if !lto.Disabled() && !lto.FullLTO() {
+			return true
+		}
+	}
+
+	return Bool(lto.Properties.Lto.Thin)
 }
 
 // Is lto.never explicitly set to true?
@@ -146,8 +162,8 @@
 // Propagate lto requirements down from binaries
 func ltoDepsMutator(mctx android.TopDownMutatorContext) {
 	if m, ok := mctx.Module().(*Module); ok && m.lto.LTO() {
-		full := Bool(m.lto.Properties.Lto.Full)
-		thin := Bool(m.lto.Properties.Lto.Thin)
+		full := m.lto.FullLTO()
+		thin := m.lto.ThinLTO()
 		if full && thin {
 			mctx.PropertyErrorf("LTO", "FullLTO and ThinLTO are mutually exclusive")
 		}
@@ -169,10 +185,10 @@
 
 			if dep, ok := dep.(*Module); ok && dep.lto != nil &&
 				!dep.lto.Disabled() {
-				if full && !Bool(dep.lto.Properties.Lto.Full) {
+				if full && !dep.lto.FullLTO() {
 					dep.lto.Properties.FullDep = true
 				}
-				if thin && !Bool(dep.lto.Properties.Lto.Thin) {
+				if thin && !dep.lto.ThinLTO() {
 					dep.lto.Properties.ThinDep = true
 				}
 			}
@@ -189,19 +205,19 @@
 		// Create variations for LTO types required as static
 		// dependencies
 		variationNames := []string{""}
-		if m.lto.Properties.FullDep && !Bool(m.lto.Properties.Lto.Full) {
+		if m.lto.Properties.FullDep && !m.lto.FullLTO() {
 			variationNames = append(variationNames, "lto-full")
 		}
-		if m.lto.Properties.ThinDep && !Bool(m.lto.Properties.Lto.Thin) {
+		if m.lto.Properties.ThinDep && !m.lto.ThinLTO() {
 			variationNames = append(variationNames, "lto-thin")
 		}
 
 		// Use correct dependencies if LTO property is explicitly set
 		// (mutually exclusive)
-		if Bool(m.lto.Properties.Lto.Full) {
+		if m.lto.FullLTO() {
 			mctx.SetDependencyVariation("lto-full")
 		}
-		if Bool(m.lto.Properties.Lto.Thin) {
+		if m.lto.ThinLTO() {
 			mctx.SetDependencyVariation("lto-thin")
 		}
 
diff --git a/java/app.go b/java/app.go
index 2377c91..13d08b9 100755
--- a/java/app.go
+++ b/java/app.go
@@ -678,7 +678,7 @@
 		seenModules[child] = true
 
 		// Skip host modules.
-		if child.Target().Os.Class == android.Host || child.Target().Os.Class == android.HostCross {
+		if child.Target().Os.Class == android.Host {
 			return false
 		}
 
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 55bc041..8b66dbf 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1412,9 +1412,7 @@
 
 		// TODO(b/154317059): Clean up this whitelist by baselining and/or checking in last-released.
 		if d.Name() != "android.car-system-stubs-docs" &&
-			d.Name() != "android.car-stubs-docs" &&
-			d.Name() != "system-api-stubs-docs" &&
-			d.Name() != "test-api-stubs-docs" {
+			d.Name() != "android.car-stubs-docs" {
 			cmd.Flag("--lints-as-errors")
 			cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
 		}
diff --git a/python/binary.go b/python/binary.go
index 5a74926..1d2400e 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -79,7 +79,7 @@
 }
 
 func PythonBinaryHostFactory() android.Module {
-	module, _ := NewBinary(android.HostSupportedNoCross)
+	module, _ := NewBinary(android.HostSupported)
 
 	return module.Init()
 }
diff --git a/python/library.go b/python/library.go
index 65c1352..0c8d613 100644
--- a/python/library.go
+++ b/python/library.go
@@ -26,7 +26,7 @@
 }
 
 func PythonLibraryHostFactory() android.Module {
-	module := newModule(android.HostSupportedNoCross, android.MultilibFirst)
+	module := newModule(android.HostSupported, android.MultilibFirst)
 
 	return module.Init()
 }
diff --git a/rust/bindgen.go b/rust/bindgen.go
index cafdb8b..d8d126d 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -21,6 +21,7 @@
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
+	cc_config "android/soong/cc/config"
 )
 
 var (
@@ -56,7 +57,11 @@
 var _ SourceProvider = (*bindgenDecorator)(nil)
 
 type BindgenProperties struct {
-	// The wrapper header file
+	// The wrapper header file. By default this is assumed to be a C header unless the extension is ".hh" or ".hpp".
+	// This is used to specify how to interpret the header and determines which '-std' flag to use by default.
+	//
+	// If your C++ header must have some other extension, then the default behavior can be overridden by setting the
+	// cpp_std property.
 	Wrapper_src *string `android:"path,arch_variant"`
 
 	// list of bindgen-specific flags and options
@@ -81,6 +86,22 @@
 	// "my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]"
 	Custom_bindgen string `android:"path"`
 
+	// C standard version to use. Can be a specific version (such as "gnu11"),
+	// "experimental" (which will use draft versions like C1x when available),
+	// or the empty string (which will use the default).
+	//
+	// If this is set, the file extension will be ignored and this will be used as the std version value. Setting this
+	// to "default" will use the build system default version. This cannot be set at the same time as cpp_std.
+	C_std *string
+
+	// C++ standard version to use. Can be a specific version (such as
+	// "gnu++11"), "experimental" (which will use draft versions like C++1z when
+	// available), or the empty string (which will use the default).
+	//
+	// If this is set, the file extension will be ignored and this will be used as the std version value. Setting this
+	// to "default" will use the build system default version. This cannot be set at the same time as c_std.
+	Cpp_std *string
+
 	//TODO(b/161141999) Add support for headers from cc_library_header modules.
 }
 
@@ -90,6 +111,45 @@
 	Properties BindgenProperties
 }
 
+func (b *bindgenDecorator) getStdVersion(ctx ModuleContext, src android.Path) (string, bool) {
+	// Assume headers are C headers
+	isCpp := false
+	stdVersion := ""
+
+	switch src.Ext() {
+	case ".hpp", ".hh":
+		isCpp = true
+	}
+
+	if String(b.Properties.Cpp_std) != "" && String(b.Properties.C_std) != "" {
+		ctx.PropertyErrorf("c_std", "c_std and cpp_std cannot both be defined at the same time.")
+	}
+
+	if String(b.Properties.Cpp_std) != "" {
+		if String(b.Properties.Cpp_std) == "experimental" {
+			stdVersion = cc_config.ExperimentalCppStdVersion
+		} else if String(b.Properties.Cpp_std) == "default" {
+			stdVersion = cc_config.CppStdVersion
+		} else {
+			stdVersion = String(b.Properties.Cpp_std)
+		}
+	} else if b.Properties.C_std != nil {
+		if String(b.Properties.C_std) == "experimental" {
+			stdVersion = cc_config.ExperimentalCStdVersion
+		} else if String(b.Properties.C_std) == "default" {
+			stdVersion = cc_config.CStdVersion
+		} else {
+			stdVersion = String(b.Properties.C_std)
+		}
+	} else if isCpp {
+		stdVersion = cc_config.CppStdVersion
+	} else {
+		stdVersion = cc_config.CStdVersion
+	}
+
+	return stdVersion, isCpp
+}
+
 func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) android.Path {
 	ccToolchain := ctx.RustModule().ccToolchain(ctx)
 
@@ -134,6 +194,17 @@
 		ctx.PropertyErrorf("wrapper_src", "invalid path to wrapper source")
 	}
 
+	// Add C std version flag
+	stdVersion, isCpp := b.getStdVersion(ctx, wrapperFile.Path())
+	cflags = append(cflags, "-std="+stdVersion)
+
+	// Specify the header source language to avoid ambiguity.
+	if isCpp {
+		cflags = append(cflags, "-x c++")
+	} else {
+		cflags = append(cflags, "-x c")
+	}
+
 	outputFile := android.PathForModuleOut(ctx, b.BaseSourceProvider.getStem(ctx)+".rs")
 
 	var cmd, cmdDesc string
@@ -169,7 +240,9 @@
 
 // rust_bindgen generates Rust FFI bindings to C libraries using bindgen given a wrapper header as the primary input.
 // Bindgen has a number of flags to control the generated source, and additional flags can be passed to clang to ensure
-// the header and generated source is appropriately handled.
+// the header and generated source is appropriately handled. It is recommended to add it as a dependency in the
+// rlibs, dylibs or rustlibs property. It may also be added in the srcs property for external crates, using the ":"
+// prefix.
 func RustBindgenFactory() android.Module {
 	module, _ := NewRustBindgen(android.HostAndDeviceSupported)
 	return module.Init()
diff --git a/rust/bindgen_test.go b/rust/bindgen_test.go
index 191da9b..e69bce2 100644
--- a/rust/bindgen_test.go
+++ b/rust/bindgen_test.go
@@ -41,7 +41,7 @@
 			export_include_dirs: ["static_include"],
 		}
 	`)
-	libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a").Output("bindings.rs")
+	libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a_source").Output("bindings.rs")
 	// Ensure that the flags are present and escaped
 	if !strings.Contains(libbindgen.Args["flags"], "'--bindgen-flag.*'") {
 		t.Errorf("missing bindgen flags in rust_bindgen rule: flags %#v", libbindgen.Args["flags"])
@@ -73,7 +73,7 @@
 		}
 	`)
 
-	libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a").Output("bindings.rs")
+	libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a_source").Output("bindings.rs")
 
 	// The rule description should contain the custom binary name rather than bindgen, so checking the description
 	// should be sufficient.
@@ -82,3 +82,47 @@
 			libbindgen.Description)
 	}
 }
+
+func TestRustBindgenStdVersions(t *testing.T) {
+	testRustError(t, "c_std and cpp_std cannot both be defined at the same time.", `
+		rust_bindgen {
+			name: "libbindgen",
+			wrapper_src: "src/any.h",
+			crate_name: "bindgen",
+			stem: "libbindgen",
+			source_stem: "bindings",
+			c_std: "somevalue",
+			cpp_std: "somevalue",
+		}
+	`)
+
+	ctx := testRust(t, `
+		rust_bindgen {
+			name: "libbindgen_cstd",
+			wrapper_src: "src/any.h",
+			crate_name: "bindgen",
+			stem: "libbindgen",
+			source_stem: "bindings",
+			c_std: "foo"
+		}
+		rust_bindgen {
+			name: "libbindgen_cppstd",
+			wrapper_src: "src/any.h",
+			crate_name: "bindgen",
+			stem: "libbindgen",
+			source_stem: "bindings",
+			cpp_std: "foo"
+		}
+	`)
+
+	libbindgen_cstd := ctx.ModuleForTests("libbindgen_cstd", "android_arm64_armv8-a_source").Output("bindings.rs")
+	libbindgen_cppstd := ctx.ModuleForTests("libbindgen_cppstd", "android_arm64_armv8-a_source").Output("bindings.rs")
+
+	if !strings.Contains(libbindgen_cstd.Args["cflags"], "-std=foo") {
+		t.Errorf("c_std value not passed in to rust_bindgen as a clang flag")
+	}
+
+	if !strings.Contains(libbindgen_cppstd.Args["cflags"], "-std=foo") {
+		t.Errorf("cpp_std value not passed in to rust_bindgen as a clang flag")
+	}
+}
diff --git a/rust/config/arm_device.go b/rust/config/arm_device.go
index ac4f1c6..adfe917 100644
--- a/rust/config/arm_device.go
+++ b/rust/config/arm_device.go
@@ -52,7 +52,7 @@
 }
 
 func (t *toolchainArm) RustTriple() string {
-	return "arm-linux-androideabi"
+	return "armv7-linux-androideabi"
 }
 
 func (t *toolchainArm) ToolchainLinkFlags() string {
diff --git a/rust/library.go b/rust/library.go
index 4931f19..2792c5b 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -15,6 +15,7 @@
 package rust
 
 import (
+	"fmt"
 	"regexp"
 	"strings"
 
@@ -77,6 +78,8 @@
 	VariantIsShared bool `blueprint:"mutated"`
 	// This variant is a static library
 	VariantIsStatic bool `blueprint:"mutated"`
+	// This variant is a source provider
+	VariantIsSource bool `blueprint:"mutated"`
 
 	// This variant is disabled and should not be compiled
 	// (used for SourceProvider variants that produce only source)
@@ -103,6 +106,7 @@
 	static() bool
 	shared() bool
 	sysroot() bool
+	source() bool
 
 	// Returns true if the build options for the module have selected a particular build type
 	buildRlib() bool
@@ -115,6 +119,7 @@
 	setDylib()
 	setShared()
 	setStatic()
+	setSource()
 
 	// Set libstd linkage
 	setRlibStd()
@@ -158,6 +163,10 @@
 	return library.static() || library.MutatedProperties.VariantIsStaticStd
 }
 
+func (library *libraryDecorator) source() bool {
+	return library.MutatedProperties.VariantIsSource
+}
+
 func (library *libraryDecorator) buildRlib() bool {
 	return library.MutatedProperties.BuildRlib && BoolDefault(library.Properties.Rlib.Enabled, true)
 }
@@ -210,13 +219,17 @@
 	library.MutatedProperties.VariantIsDylib = false
 }
 
+func (library *libraryDecorator) setSource() {
+	library.MutatedProperties.VariantIsSource = true
+}
+
 func (library *libraryDecorator) autoDep(ctx BaseModuleContext) autoDep {
 	if library.rlib() || library.static() {
 		return rlibAutoDep
 	} else if library.dylib() || library.shared() {
 		return dylibAutoDep
 	} else {
-		panic("autoDep called on library" + ctx.ModuleName() + "that has no enabled variants.")
+		panic(fmt.Errorf("autoDep called on library %q that has no enabled variants.", ctx.ModuleName()))
 	}
 }
 
@@ -518,41 +531,68 @@
 	}
 }
 
+// LibraryMutator mutates the libraries into variants according to the
+// build{Rlib,Dylib} attributes.
 func LibraryMutator(mctx android.BottomUpMutatorContext) {
-	if m, ok := mctx.Module().(*Module); ok && m.compiler != nil {
-		switch library := m.compiler.(type) {
-		case libraryInterface:
-			if library.buildRlib() && library.buildDylib() {
-				variants := []string{"rlib", "dylib"}
-				if m.sourceProvider != nil {
-					variants = append(variants, "")
-				}
-				modules := mctx.CreateLocalVariations(variants...)
+	// Only mutate on Rust libraries.
+	m, ok := mctx.Module().(*Module)
+	if !ok || m.compiler == nil {
+		return
+	}
+	library, ok := m.compiler.(libraryInterface)
+	if !ok {
+		return
+	}
 
-				rlib := modules[0].(*Module)
-				dylib := modules[1].(*Module)
-				rlib.compiler.(libraryInterface).setRlib()
-				dylib.compiler.(libraryInterface).setDylib()
-				if m.sourceProvider != nil {
-					// This library is SourceProvider generated, so the non-library-producing
-					// variant needs to disable it's compiler and skip installation.
-					sourceProvider := modules[2].(*Module)
-					sourceProvider.compiler.SetDisabled()
-				}
-			} else if library.buildRlib() {
-				modules := mctx.CreateLocalVariations("rlib")
-				modules[0].(*Module).compiler.(libraryInterface).setRlib()
-			} else if library.buildDylib() {
-				modules := mctx.CreateLocalVariations("dylib")
-				modules[0].(*Module).compiler.(libraryInterface).setDylib()
-			}
+	var variants []string
+	// The source variant is used for SourceProvider modules. The other variants (i.e. rlib and dylib)
+	// depend on this variant. It must be the first variant to be declared.
+	sourceVariant := false
+	if m.sourceProvider != nil {
+		variants = append(variants, "source")
+		sourceVariant = true
+	}
+	if library.buildRlib() {
+		variants = append(variants, rlibVariation)
+	}
+	if library.buildDylib() {
+		variants = append(variants, dylibVariation)
+	}
 
-			if m.sourceProvider != nil {
-				// Alias the non-library variant to the empty-string variant.
-				mctx.AliasVariation("")
-			}
+	if len(variants) == 0 {
+		return
+	}
+	modules := mctx.CreateLocalVariations(variants...)
+
+	// The order of the variations (modules) matches the variant names provided. Iterate
+	// through the new variation modules and set their mutated properties.
+	for i, v := range modules {
+		switch variants[i] {
+		case rlibVariation:
+			v.(*Module).compiler.(libraryInterface).setRlib()
+		case dylibVariation:
+			v.(*Module).compiler.(libraryInterface).setDylib()
+		case "source":
+			v.(*Module).compiler.(libraryInterface).setSource()
+			// The source variant does not produce any library.
+			// Disable the compilation steps.
+			v.(*Module).compiler.SetDisabled()
 		}
 	}
+
+	// If a source variant is created, add an inter-variant dependency
+	// between the other variants and the source variant.
+	if sourceVariant {
+		sv := modules[0]
+		for _, v := range modules[1:] {
+			if !v.Enabled() {
+				continue
+			}
+			mctx.AddInterVariantDependency(sourceDepTag, v, sv)
+		}
+		// Alias the source variation so it can be named directly in "srcs" properties.
+		mctx.AliasVariation("source")
+	}
 }
 
 func LibstdMutator(mctx android.BottomUpMutatorContext) {
diff --git a/rust/protobuf_test.go b/rust/protobuf_test.go
index a9dbf39..bd11a5a 100644
--- a/rust/protobuf_test.go
+++ b/rust/protobuf_test.go
@@ -29,7 +29,7 @@
 		}
 	`)
 	// Check that there's a rule to generate the expected output
-	_ = ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_dylib").Output("buf.rs")
+	_ = ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_source").Output("buf.rs")
 
 	// Check that libprotobuf is added as a dependency.
 	librust_proto := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_dylib").Module().(*Module)
diff --git a/rust/rust.go b/rust/rust.go
index d22acea..22b81f1 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -87,8 +87,7 @@
 	sourceProvider   SourceProvider
 	subAndroidMkOnce map[SubAndroidMkProvider]bool
 
-	outputFile    android.OptionalPath
-	generatedFile android.OptionalPath
+	outputFile android.OptionalPath
 }
 
 func (mod *Module) OutputFiles(tag string) (android.Paths, error) {
@@ -687,12 +686,20 @@
 		flags, deps = mod.clippy.flags(ctx, flags, deps)
 	}
 
-	// SourceProvider needs to call GenerateSource() before compiler calls compile() so it can provide the source.
-	// TODO(b/162588681) This shouldn't have to run for every variant.
+	// SourceProvider needs to call GenerateSource() before compiler calls
+	// compile() so it can provide the source. A SourceProvider has
+	// multiple variants (e.g. source, rlib, dylib). Only the "source"
+	// variant is responsible for effectively generating the source. The
+	// remaining variants relies on the "source" variant output.
 	if mod.sourceProvider != nil {
-		generatedFile := mod.sourceProvider.GenerateSource(ctx, deps)
-		mod.generatedFile = android.OptionalPathForPath(generatedFile)
-		mod.sourceProvider.setSubName(ctx.ModuleSubDir())
+		if mod.compiler.(libraryInterface).source() {
+			mod.sourceProvider.GenerateSource(ctx, deps)
+			mod.sourceProvider.setSubName(ctx.ModuleSubDir())
+		} else {
+			sourceMod := actx.GetDirectDepWithTag(mod.Name(), sourceDepTag)
+			sourceLib := sourceMod.(*Module).compiler.(*libraryDecorator)
+			mod.sourceProvider.setOutputFile(sourceLib.sourceProvider.Srcs()[0])
+		}
 	}
 
 	if mod.compiler != nil && !mod.compiler.Disabled() {
@@ -743,6 +750,7 @@
 	dylibDepTag         = dependencyTag{name: "dylib", library: true}
 	procMacroDepTag     = dependencyTag{name: "procMacro", proc_macro: true}
 	testPerSrcDepTag    = dependencyTag{name: "rust_unit_tests"}
+	sourceDepTag        = dependencyTag{name: "source"}
 )
 
 type autoDep struct {
@@ -751,8 +759,10 @@
 }
 
 var (
-	rlibAutoDep  = autoDep{variation: "rlib", depTag: rlibDepTag}
-	dylibAutoDep = autoDep{variation: "dylib", depTag: dylibDepTag}
+	rlibVariation  = "rlib"
+	dylibVariation = "dylib"
+	rlibAutoDep    = autoDep{variation: rlibVariation, depTag: rlibDepTag}
+	dylibAutoDep   = autoDep{variation: dylibVariation, depTag: dylibDepTag}
 )
 
 type autoDeppable interface {
@@ -1000,11 +1010,11 @@
 
 	actx.AddVariationDependencies(
 		append(rlibDepVariations, []blueprint.Variation{
-			{Mutator: "rust_libraries", Variation: "rlib"}}...),
+			{Mutator: "rust_libraries", Variation: rlibVariation}}...),
 		rlibDepTag, deps.Rlibs...)
 	actx.AddVariationDependencies(
 		append(commonDepVariations, []blueprint.Variation{
-			{Mutator: "rust_libraries", Variation: "dylib"}}...),
+			{Mutator: "rust_libraries", Variation: dylibVariation}}...),
 		dylibDepTag, deps.Dylibs...)
 
 	if deps.Rustlibs != nil && !mod.compiler.Disabled() {
diff --git a/rust/source_provider.go b/rust/source_provider.go
index 755a369..03adf9e 100644
--- a/rust/source_provider.go
+++ b/rust/source_provider.go
@@ -43,6 +43,7 @@
 	SourceProviderProps() []interface{}
 	SourceProviderDeps(ctx DepsContext, deps Deps) Deps
 	setSubName(subName string)
+	setOutputFile(outputFile android.Path)
 }
 
 func (sp *BaseSourceProvider) Srcs() android.Paths {
@@ -95,3 +96,7 @@
 func (sp *BaseSourceProvider) setSubName(subName string) {
 	sp.subName = subName
 }
+
+func (sp *BaseSourceProvider) setOutputFile(outputFile android.Path) {
+	sp.OutputFile = outputFile
+}
diff --git a/sdk/testing.go b/sdk/testing.go
index b53558d..e57f1f7 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -68,14 +68,14 @@
 	// Add windows as a default disable OS to test behavior when some OS variants
 	// are disabled.
 	config.Targets[android.Windows] = []android.Target{
-		{android.Windows, android.Arch{ArchType: android.X86_64}, android.NativeBridgeDisabled, "", ""},
+		{android.Windows, android.Arch{ArchType: android.X86_64}, android.NativeBridgeDisabled, "", "", true},
 	}
 
 	for _, extraOsType := range extraOsTypes {
 		switch extraOsType {
 		case android.LinuxBionic:
 			config.Targets[android.LinuxBionic] = []android.Target{
-				{android.LinuxBionic, android.Arch{ArchType: android.X86_64}, android.NativeBridgeDisabled, "", ""},
+				{android.LinuxBionic, android.Arch{ArchType: android.X86_64}, android.NativeBridgeDisabled, "", "", false},
 			}
 		}
 	}
@@ -89,7 +89,7 @@
 	android.RegisterAndroidMkBuildComponents(ctx)
 	android.SetInMakeForTests(config)
 	config.Targets[android.CommonOS] = []android.Target{
-		{android.CommonOS, android.Arch{ArchType: android.Common}, android.NativeBridgeDisabled, "", ""},
+		{android.CommonOS, android.Arch{ArchType: android.Common}, android.NativeBridgeDisabled, "", "", true},
 	}
 
 	// from android package
diff --git a/sdk/update.go b/sdk/update.go
index 537ab13..3c4309c 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -371,8 +371,7 @@
 			osPropertySet := targetPropertySet.AddPropertySet(sdkVariant.Target().Os.Name)
 
 			// Enable the variant explicitly when we've disabled it by default on host.
-			if hasHostOsDependentMember &&
-				(osType.Class == android.Host || osType.Class == android.HostCross) {
+			if hasHostOsDependentMember && osType.Class == android.Host {
 				osPropertySet.AddProperty("enabled", true)
 			}
 
@@ -731,7 +730,7 @@
 
 	for _, variant := range member.Variants() {
 		osClass := variant.Target().Os.Class
-		if osClass == android.Host || osClass == android.HostCross {
+		if osClass == android.Host {
 			hostSupported = true
 		} else if osClass == android.Device {
 			deviceSupported = true
@@ -1061,8 +1060,7 @@
 		archPropertySet = targetPropertySet
 
 		// Enable the variant explicitly when we've disabled it by default on host.
-		if ctx.memberType.IsHostOsDependent() &&
-			(osType.Class == android.Host || osType.Class == android.HostCross) {
+		if ctx.memberType.IsHostOsDependent() && osType.Class == android.Host {
 			osPropertySet.AddProperty("enabled", true)
 		}
 
@@ -1086,7 +1084,7 @@
 
 func (osInfo *osTypeSpecificInfo) isHostVariant() bool {
 	osClass := osInfo.osType.Class
-	return osClass == android.Host || osClass == android.HostCross
+	return osClass == android.Host
 }
 
 var _ isHostVariant = (*osTypeSpecificInfo)(nil)
@@ -1323,7 +1321,7 @@
 			}
 		}
 		if s.HostSupported() {
-			if osType.Class == android.Host || osType.Class == android.HostCross {
+			if osType.Class == android.Host {
 				osTypes = append(osTypes, osType)
 			}
 		}
diff --git a/ui/build/config.go b/ui/build/config.go
index 9bd0877..27f3be3 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -851,6 +851,11 @@
 }
 
 func (c *configImpl) logDir() string {
+	for _, f := range []string{"RBE_log_dir", "FLAG_log_dir"} {
+		if v, ok := c.environ.Get(f); ok {
+			return v
+		}
+	}
 	if c.Dist() {
 		return filepath.Join(c.DistDir(), "logs")
 	}