Merge "Allow overrides for RBE_log_dir"
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/apex.go b/android/apex.go
index f857ec6..3cc663b 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -24,29 +24,36 @@
 	"github.com/google/blueprint"
 )
 
-const (
-	SdkVersion_Android10 = 29
+var (
+	SdkVersion_Android10 = uncheckedFinalApiLevel(29)
 )
 
 type ApexInfo struct {
 	// Name of the apex variation that this module is mutated into
 	ApexVariationName string
 
-	MinSdkVersion int
-	Updatable     bool
-	RequiredSdks  SdkRefs
+	// Serialized ApiLevel. Use via MinSdkVersion() method. Cannot be stored in
+	// its struct form because this is cloned into properties structs, and
+	// ApiLevel has private members.
+	MinSdkVersionStr string
+	Updatable        bool
+	RequiredSdks     SdkRefs
 
 	InApexes []string
 }
 
-func (i ApexInfo) mergedName() string {
-	name := "apex" + strconv.Itoa(i.MinSdkVersion)
+func (i ApexInfo) mergedName(ctx EarlyModuleContext) string {
+	name := "apex" + strconv.Itoa(i.MinSdkVersion(ctx).FinalOrFutureInt())
 	for _, sdk := range i.RequiredSdks {
 		name += "_" + sdk.Name + "_" + sdk.Version
 	}
 	return name
 }
 
+func (this *ApexInfo) MinSdkVersion(ctx EarlyModuleContext) ApiLevel {
+	return ApiLevelOrPanic(ctx, this.MinSdkVersionStr)
+}
+
 // Extracted from ApexModule to make it easier to define custom subsets of the
 // ApexModule interface and improve code navigation within the IDE.
 type DepIsInSameApex interface {
@@ -141,7 +148,7 @@
 
 	// Returns nil if this module supports sdkVersion
 	// Otherwise, returns error with reason
-	ShouldSupportSdkVersion(ctx BaseModuleContext, sdkVersion int) error
+	ShouldSupportSdkVersion(ctx BaseModuleContext, sdkVersion ApiLevel) error
 
 	// Returns true if this module needs a unique variation per apex, for example if
 	// use_apex_name_macro is set.
@@ -347,18 +354,18 @@
 // mergeApexVariations deduplicates APEX variations that would build identically into a common
 // variation.  It returns the reduced list of variations and a list of aliases from the original
 // variation names to the new variation names.
-func mergeApexVariations(apexVariations []ApexInfo) (merged []ApexInfo, aliases [][2]string) {
+func mergeApexVariations(ctx EarlyModuleContext, apexVariations []ApexInfo) (merged []ApexInfo, aliases [][2]string) {
 	sort.Sort(byApexName(apexVariations))
 	seen := make(map[string]int)
 	for _, apexInfo := range apexVariations {
 		apexName := apexInfo.ApexVariationName
-		mergedName := apexInfo.mergedName()
+		mergedName := apexInfo.mergedName(ctx)
 		if index, exists := seen[mergedName]; exists {
 			merged[index].InApexes = append(merged[index].InApexes, apexName)
 			merged[index].Updatable = merged[index].Updatable || apexInfo.Updatable
 		} else {
 			seen[mergedName] = len(merged)
-			apexInfo.ApexVariationName = apexInfo.mergedName()
+			apexInfo.ApexVariationName = apexInfo.mergedName(ctx)
 			apexInfo.InApexes = CopyOf(apexInfo.InApexes)
 			merged = append(merged, apexInfo)
 		}
@@ -374,7 +381,7 @@
 		var apexVariations []ApexInfo
 		var aliases [][2]string
 		if !mctx.Module().(ApexModule).UniqueApexVariations() && !m.ApexProperties.UniqueApexVariationsForDeps {
-			apexVariations, aliases = mergeApexVariations(m.apexVariations)
+			apexVariations, aliases = mergeApexVariations(mctx, m.apexVariations)
 		} else {
 			apexVariations = m.apexVariations
 		}
@@ -603,7 +610,13 @@
 }
 
 // TODO(b/158059172): remove minSdkVersion allowlist
-var minSdkVersionAllowlist = map[string]int{
+var minSdkVersionAllowlist = func(apiMap map[string]int) map[string]ApiLevel {
+	list := make(map[string]ApiLevel, len(apiMap))
+	for name, finalApiInt := range apiMap {
+		list[name] = uncheckedFinalApiLevel(finalApiInt)
+	}
+	return list
+}(map[string]int{
 	"adbd":                  30,
 	"android.net.ipsec.ike": 30,
 	"androidx-constraintlayout_constraintlayout-solver": 30,
@@ -672,7 +685,7 @@
 	"statsd":                                            30,
 	"tensorflow_headers":                                30,
 	"xz-java":                                           29,
-}
+})
 
 // Function called while walking an APEX's payload dependencies.
 //
@@ -686,7 +699,7 @@
 }
 
 // CheckMinSdkVersion checks if every dependency of an updatable module sets min_sdk_version accordingly
-func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion int) {
+func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion ApiLevel) {
 	// do not enforce min_sdk_version for host
 	if ctx.Host() {
 		return
@@ -699,7 +712,7 @@
 
 	// do not enforce deps.min_sdk_version if APEX/APK doesn't set min_sdk_version or
 	// min_sdk_version is not finalized (e.g. current or codenames)
-	if minSdkVersion == FutureApiLevel {
+	if minSdkVersion.IsCurrent() {
 		return
 	}
 
@@ -714,7 +727,7 @@
 		}
 		if err := to.ShouldSupportSdkVersion(ctx, minSdkVersion); err != nil {
 			toName := ctx.OtherModuleName(to)
-			if ver, ok := minSdkVersionAllowlist[toName]; !ok || ver > minSdkVersion {
+			if ver, ok := minSdkVersionAllowlist[toName]; !ok || ver.GreaterThan(minSdkVersion) {
 				ctx.OtherModuleErrorf(to, "should support min_sdk_version(%v) for %q: %v. Dependency path: %s",
 					minSdkVersion, ctx.ModuleName(), err.Error(), ctx.GetPathString(false))
 				return false
diff --git a/android/api_levels.go b/android/api_levels.go
index ddcdbb7..9768340 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -49,6 +49,14 @@
 	isPreview bool
 }
 
+func (this ApiLevel) FinalOrFutureInt() int {
+	if this.IsPreview() {
+		return FutureApiLevelInt
+	} else {
+		return this.number
+	}
+}
+
 // Returns the canonical name for this API level. For a finalized API level
 // this will be the API number as a string. For a preview API level this
 // will be the codename, or "current".
@@ -119,13 +127,6 @@
 	}
 }
 
-// TODO: Merge with FutureApiLevel
-var CurrentApiLevel = ApiLevel{
-	value:     "current",
-	number:    10000,
-	isPreview: true,
-}
-
 var NoneApiLevel = ApiLevel{
 	value: "(no version)",
 	// Not 0 because we don't want this to compare equal with the first preview.
@@ -180,7 +181,7 @@
 	}
 
 	if raw == "current" {
-		return CurrentApiLevel, nil
+		return FutureApiLevel, nil
 	}
 
 	for _, preview := range ctx.Config().PreviewApiLevels() {
@@ -261,8 +262,19 @@
 			"R":     30,
 		}
 
+		// TODO: Differentiate "current" and "future".
+		// The code base calls it FutureApiLevel, but the spelling is "current",
+		// and these are really two different things. When defining APIs it
+		// means the API has not yet been added to a specific release. When
+		// choosing an API level to build for it means that the future API level
+		// should be used, except in the case where the build is finalized in
+		// which case the platform version should be used. This is *weird*,
+		// because in the circumstance where API foo was added in R and bar was
+		// added in S, both of these are usable when building for "current" when
+		// neither R nor S are final, but the S APIs stop being available in a
+		// final R build.
 		if Bool(config.productVariables.Platform_sdk_final) {
-			apiLevelsMap["current"] = config.PlatformSdkVersionInt()
+			apiLevelsMap["current"] = config.PlatformSdkVersion().FinalOrFutureInt()
 		}
 
 		return apiLevelsMap
@@ -300,24 +312,6 @@
 	}).(map[string]int)
 }
 
-// Converts an API level string into its numeric form.
-// * Codenames are decoded.
-// * Numeric API levels are simply converted.
-// * "current" is mapped to FutureApiLevel(10000)
-// * "minimum" is NDK specific and not handled with this. (refer normalizeNdkApiLevel in cc.go)
-func ApiStrToNum(ctx BaseModuleContext, apiLevel string) (int, error) {
-	if apiLevel == "current" {
-		return FutureApiLevel, nil
-	}
-	if num, ok := getApiLevelsMap(ctx.Config())[apiLevel]; ok {
-		return num, nil
-	}
-	if num, err := strconv.Atoi(apiLevel); err == nil {
-		return num, nil
-	}
-	return 0, fmt.Errorf("SDK version should be one of \"current\", <number> or <codename>: %q", apiLevel)
-}
-
 func (a *apiLevelsSingleton) GenerateBuildActions(ctx SingletonContext) {
 	apiLevelsMap := getApiLevelsMap(ctx.Config())
 	apiLevelsJson := GetApiLevelsJson(ctx)
diff --git a/android/arch.go b/android/arch.go
index 4141138..f4b0d66 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -78,13 +78,22 @@
     },
     target: {
         android: {
-            // Device variants
+            // Device variants (implies Bionic)
         },
         host: {
             // Host variants
         },
+        bionic: {
+            // Bionic (device and host) variants
+        },
+        linux_bionic: {
+            // Bionic host variants
+        },
+        linux: {
+            // Bionic (device and host) and Linux glibc variants
+        },
         linux_glibc: {
-            // Linux host variants
+            // Linux host variants (using non-Bionic libc)
         },
         darwin: {
             // Darwin host variants
@@ -95,6 +104,9 @@
         not_windows: {
             // Non-windows host variants
         },
+        android_arm: {
+            // Any <os>_<arch> combination restricts to that os and arch
+        },
     },
 }
 */
@@ -578,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)
 
@@ -609,7 +621,6 @@
 	Generic OsClass = iota
 	Device
 	Host
-	HostCross
 )
 
 func (class OsClass) String() string {
@@ -620,8 +631,6 @@
 		return "device"
 	case Host:
 		return "host"
-	case HostCross:
-		return "host cross"
 	default:
 		panic(fmt.Errorf("unknown class %d", class))
 	}
@@ -681,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 {
@@ -739,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 {
@@ -913,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)
@@ -964,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 == "" {
@@ -1240,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)
@@ -1280,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)
@@ -1508,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,
@@ -1515,6 +1548,7 @@
 				NativeBridge:             nativeBridgeEnabled,
 				NativeBridgeHostArchName: nativeBridgeHostArchNameStr,
 				NativeBridgeRelativePath: nativeBridgeRelativePathStr,
+				HostCross:                hostCross,
 			})
 	}
 
@@ -1531,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)
@@ -1771,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 1c06e8c..8df65f7 100644
--- a/android/config.go
+++ b/android/config.go
@@ -21,7 +21,6 @@
 	"os"
 	"path/filepath"
 	"runtime"
-	"strconv"
 	"strings"
 	"sync"
 
@@ -37,7 +36,13 @@
 var String = proptools.String
 var StringDefault = proptools.StringDefault
 
-const FutureApiLevel = 10000
+const FutureApiLevelInt = 10000
+
+var FutureApiLevel = ApiLevel{
+	value:     "current",
+	number:    FutureApiLevelInt,
+	isPreview: true,
+}
 
 // The configuration file name
 const configFileName = "soong.config"
@@ -46,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() {
@@ -222,15 +228,17 @@
 
 	config := &config{
 		productVariables: productVariables{
-			DeviceName:                  stringPtr("test_device"),
-			Platform_sdk_version:        intPtr(30),
-			DeviceSystemSdkVersions:     []string{"14", "15"},
-			Platform_systemsdk_versions: []string{"29", "30"},
-			AAPTConfig:                  []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
-			AAPTPreferredConfig:         stringPtr("xhdpi"),
-			AAPTCharacteristics:         stringPtr("nosdcard"),
-			AAPTPrebuiltDPI:             []string{"xhdpi", "xxhdpi"},
-			UncompressPrivAppDex:        boolPtr(true),
+			DeviceName:                        stringPtr("test_device"),
+			Platform_sdk_version:              intPtr(30),
+			Platform_sdk_codename:             stringPtr("S"),
+			Platform_version_active_codenames: []string{"S"},
+			DeviceSystemSdkVersions:           []string{"14", "15"},
+			Platform_systemsdk_versions:       []string{"29", "30"},
+			AAPTConfig:                        []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
+			AAPTPreferredConfig:               stringPtr("xhdpi"),
+			AAPTCharacteristics:               stringPtr("nosdcard"),
+			AAPTPrebuiltDPI:                   []string{"xhdpi", "xxhdpi"},
+			UncompressPrivAppDex:              boolPtr(true),
 		},
 
 		buildDir:     buildDir,
@@ -260,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
@@ -275,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},
 		},
 	}
 
@@ -292,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},
 		},
 	}
 
@@ -614,12 +622,8 @@
 	return String(c.productVariables.Platform_version_name)
 }
 
-func (c *config) PlatformSdkVersionInt() int {
-	return *c.productVariables.Platform_sdk_version
-}
-
-func (c *config) PlatformSdkVersion() string {
-	return strconv.Itoa(c.PlatformSdkVersionInt())
+func (c *config) PlatformSdkVersion() ApiLevel {
+	return uncheckedFinalApiLevel(*c.productVariables.Platform_sdk_version)
 }
 
 func (c *config) PlatformSdkCodename() string {
@@ -648,7 +652,7 @@
 
 func (c *config) FinalApiLevels() []ApiLevel {
 	var levels []ApiLevel
-	for i := 1; i <= c.PlatformSdkVersionInt(); i++ {
+	for i := 1; i <= c.PlatformSdkVersion().FinalOrFutureInt(); i++ {
 		levels = append(levels, uncheckedFinalApiLevel(i))
 	}
 	return levels
@@ -672,19 +676,18 @@
 	return append(levels, c.PreviewApiLevels()...)
 }
 
-func (c *config) DefaultAppTargetSdkInt() int {
-	if Bool(c.productVariables.Platform_sdk_final) {
-		return c.PlatformSdkVersionInt()
-	} else {
-		return FutureApiLevel
-	}
-}
-
-func (c *config) DefaultAppTargetSdk() string {
+func (c *config) DefaultAppTargetSdk(ctx EarlyModuleContext) ApiLevel {
 	if Bool(c.productVariables.Platform_sdk_final) {
 		return c.PlatformSdkVersion()
 	} else {
-		return c.PlatformSdkCodename()
+		codename := c.PlatformSdkCodename()
+		if codename == "" {
+			return NoneApiLevel
+		}
+		if codename == "REL" {
+			panic("Platform_sdk_codename should not be REL when Platform_sdk_final is true")
+		}
+		return ApiLevelOrPanic(ctx, codename)
 	}
 }
 
diff --git a/android/module.go b/android/module.go
index 5bc7a17..f5adc54 100644
--- a/android/module.go
+++ b/android/module.go
@@ -176,6 +176,31 @@
 	// It is intended for use inside the visit functions of Visit* and WalkDeps.
 	OtherModuleType(m blueprint.Module) string
 
+	// OtherModuleProvider returns the value for a provider for the given module.  If the value is
+	// not set it returns the zero value of the type of the provider, so the return value can always
+	// be type asserted to the type of the provider.  The value returned may be a deep copy of the
+	// value originally passed to SetProvider.
+	OtherModuleProvider(m blueprint.Module, provider blueprint.ProviderKey) interface{}
+
+	// OtherModuleHasProvider returns true if the provider for the given module has been set.
+	OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool
+
+	// Provider returns the value for a provider for the current module.  If the value is
+	// not set it returns the zero value of the type of the provider, so the return value can always
+	// be type asserted to the type of the provider.  It panics if called before the appropriate
+	// mutator or GenerateBuildActions pass for the provider.  The value returned may be a deep
+	// copy of the value originally passed to SetProvider.
+	Provider(provider blueprint.ProviderKey) interface{}
+
+	// HasProvider returns true if the provider for the current module has been set.
+	HasProvider(provider blueprint.ProviderKey) bool
+
+	// SetProvider sets the value for a provider for the current module.  It panics if not called
+	// during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
+	// is not of the appropriate type, or if the value has already been set.  The value should not
+	// be modified after being passed to SetProvider.
+	SetProvider(provider blueprint.ProviderKey, value interface{})
+
 	GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
 
 	// GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
@@ -245,6 +270,24 @@
 	// and returns a top-down dependency path from a start module to current child module.
 	GetWalkPath() []Module
 
+	// PrimaryModule returns the first variant of the current module.  Variants of a module are always visited in
+	// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
+	// Module returned by PrimaryModule without data races.  This can be used to perform singleton actions that are
+	// only done once for all variants of a module.
+	PrimaryModule() Module
+
+	// FinalModule returns the last variant of the current module.  Variants of a module are always visited in
+	// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
+	// variants using VisitAllModuleVariants if the current module == FinalModule().  This can be used to perform
+	// singleton actions that are only done once for all variants of a module.
+	FinalModule() Module
+
+	// VisitAllModuleVariants calls visit for each variant of the current module.  Variants of a module are always
+	// visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
+	// from all variants if the current module == FinalModule().  Otherwise, care must be taken to not access any
+	// data modified by the current mutator.
+	VisitAllModuleVariants(visit func(Module))
+
 	// GetTagPath is supposed to be called in visit function passed in WalkDeps()
 	// and returns a top-down dependency tags path from a start module to current child module.
 	// It has one less entry than GetWalkPath() as it contains the dependency tags that
@@ -324,24 +367,6 @@
 	// additional dependencies.
 	Phony(phony string, deps ...Path)
 
-	// PrimaryModule returns the first variant of the current module.  Variants of a module are always visited in
-	// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
-	// Module returned by PrimaryModule without data races.  This can be used to perform singleton actions that are
-	// only done once for all variants of a module.
-	PrimaryModule() Module
-
-	// FinalModule returns the last variant of the current module.  Variants of a module are always visited in
-	// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
-	// variants using VisitAllModuleVariants if the current module == FinalModule().  This can be used to perform
-	// singleton actions that are only done once for all variants of a module.
-	FinalModule() Module
-
-	// VisitAllModuleVariants calls visit for each variant of the current module.  Variants of a module are always
-	// visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
-	// from all variants if the current module == FinalModule().  Otherwise, care must be taken to not access any
-	// data modified by the current mutator.
-	VisitAllModuleVariants(visit func(Module))
-
 	// GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods,
 	// but do not exist.
 	GetMissingDependencies() []string
@@ -541,7 +566,7 @@
 	// control whether this module compiles for 32-bit, 64-bit, or both.  Possible values
 	// are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
 	// architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
-	// platform
+	// platform).
 	Compile_multilib *string `android:"arch_variant"`
 
 	Target struct {
@@ -923,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) {}
@@ -950,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
 }
 
@@ -1046,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 {
@@ -1066,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
 	}
 }
 
@@ -1681,6 +1706,21 @@
 func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
 	return b.bp.OtherModuleType(m)
 }
+func (b *baseModuleContext) OtherModuleProvider(m blueprint.Module, provider blueprint.ProviderKey) interface{} {
+	return b.bp.OtherModuleProvider(m, provider)
+}
+func (b *baseModuleContext) OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool {
+	return b.bp.OtherModuleHasProvider(m, provider)
+}
+func (b *baseModuleContext) Provider(provider blueprint.ProviderKey) interface{} {
+	return b.bp.Provider(provider)
+}
+func (b *baseModuleContext) HasProvider(provider blueprint.ProviderKey) bool {
+	return b.bp.HasProvider(provider)
+}
+func (b *baseModuleContext) SetProvider(provider blueprint.ProviderKey, value interface{}) {
+	b.bp.SetProvider(provider, value)
+}
 
 func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
 	return b.bp.GetDirectDepWithTag(name, tag)
@@ -2001,6 +2041,20 @@
 	return b.tagPath
 }
 
+func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
+	b.bp.VisitAllModuleVariants(func(module blueprint.Module) {
+		visit(module.(Module))
+	})
+}
+
+func (b *baseModuleContext) PrimaryModule() Module {
+	return b.bp.PrimaryModule().(Module)
+}
+
+func (b *baseModuleContext) FinalModule() Module {
+	return b.bp.FinalModule().(Module)
+}
+
 // A regexp for removing boilerplate from BaseDependencyTag from the string representation of
 // a dependency tag.
 var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`)
@@ -2036,20 +2090,6 @@
 	return sb.String()
 }
 
-func (m *moduleContext) VisitAllModuleVariants(visit func(Module)) {
-	m.bp.VisitAllModuleVariants(func(module blueprint.Module) {
-		visit(module.(Module))
-	})
-}
-
-func (m *moduleContext) PrimaryModule() Module {
-	return m.bp.PrimaryModule().(Module)
-}
-
-func (m *moduleContext) FinalModule() Module {
-	return m.bp.FinalModule().(Module)
-}
-
 func (m *moduleContext) ModuleSubDir() string {
 	return m.bp.ModuleSubDir()
 }
@@ -2075,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 {
@@ -2535,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/mutator.go b/android/mutator.go
index 5acd992..7a10477 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -315,6 +315,14 @@
 	// be used to add dependencies on the toVariationName variant using the fromVariationName
 	// variant.
 	CreateAliasVariation(fromVariationName, toVariationName string)
+
+	// SetVariationProvider sets the value for a provider for the given newly created variant of
+	// the current module, i.e. one of the Modules returned by CreateVariations..  It panics if
+	// not called during the appropriate mutator or GenerateBuildActions pass for the provider,
+	// if the value is not of the appropriate type, or if the module is not a newly created
+	// variant of the current module.  The value should not be modified after being passed to
+	// SetVariationProvider.
+	SetVariationProvider(module blueprint.Module, provider blueprint.ProviderKey, value interface{})
 }
 
 type bottomUpMutatorContext struct {
@@ -550,3 +558,7 @@
 func (b *bottomUpMutatorContext) CreateAliasVariation(fromVariationName, toVariationName string) {
 	b.bp.CreateAliasVariation(fromVariationName, toVariationName)
 }
+
+func (b *bottomUpMutatorContext) SetVariationProvider(module blueprint.Module, provider blueprint.ProviderKey, value interface{}) {
+	b.bp.SetVariationProvider(module, provider, value)
+}
diff --git a/android/prebuilt_build_tool.go b/android/prebuilt_build_tool.go
index 1dcf199..e2555e4 100644
--- a/android/prebuilt_build_tool.go
+++ b/android/prebuilt_build_tool.go
@@ -14,6 +14,8 @@
 
 package android
 
+import "path/filepath"
+
 func init() {
 	RegisterModuleType("prebuilt_build_tool", prebuiltBuildToolFactory)
 }
@@ -58,13 +60,18 @@
 	installedPath := PathForModuleOut(ctx, t.ModuleBase.Name())
 	deps := PathsForModuleSrc(ctx, t.properties.Deps)
 
+	var fromPath = sourcePath.String()
+	if !filepath.IsAbs(fromPath) {
+		fromPath = "$$PWD/" + fromPath
+	}
+
 	ctx.Build(pctx, BuildParams{
 		Rule:      Symlink,
 		Output:    installedPath,
 		Input:     sourcePath,
 		Implicits: deps,
 		Args: map[string]string{
-			"fromPath": "$$PWD/" + sourcePath.String(),
+			"fromPath": fromPath,
 		},
 	})
 
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/android/singleton.go b/android/singleton.go
index 2c51c6c..9832378 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -29,6 +29,16 @@
 	ModuleType(module blueprint.Module) string
 	BlueprintFile(module blueprint.Module) string
 
+	// ModuleProvider returns the value, if any, for the provider for a module.  If the value for the
+	// provider was not set it returns the zero value of the type of the provider, which means the
+	// return value can always be type-asserted to the type of the provider.  The return value should
+	// always be considered read-only.  It panics if called before the appropriate mutator or
+	// GenerateBuildActions pass for the provider on the module.
+	ModuleProvider(module blueprint.Module, provider blueprint.ProviderKey) interface{}
+
+	// ModuleHasProvider returns true if the provider for the given module has been set.
+	ModuleHasProvider(module blueprint.Module, provider blueprint.ProviderKey) bool
+
 	ModuleErrorf(module blueprint.Module, format string, args ...interface{})
 	Errorf(format string, args ...interface{})
 	Failed() bool
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/apex/apex.go b/apex/apex.go
index 8e35e07..e8294a8 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -795,7 +795,7 @@
 	}
 	apexInfo := android.ApexInfo{
 		ApexVariationName: mctx.ModuleName(),
-		MinSdkVersion:     a.minSdkVersion(mctx),
+		MinSdkVersionStr:  a.minSdkVersion(mctx).String(),
 		RequiredSdks:      a.RequiredSdks(),
 		Updatable:         a.Updatable(),
 		InApexes:          []string{mctx.ModuleName()},
@@ -1952,27 +1952,21 @@
 	})
 }
 
-func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) int {
+func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) android.ApiLevel {
 	ver := proptools.String(a.properties.Min_sdk_version)
 	if ver == "" {
 		return android.FutureApiLevel
 	}
-	// Treat the current codenames as "current", which means future API version (10000)
-	// Otherwise, ApiStrToNum converts codename(non-finalized) to a value from [9000...]
-	// and would fail to build against "current".
-	if android.InList(ver, ctx.Config().PlatformVersionActiveCodenames()) {
-		return android.FutureApiLevel
-	}
-	// In "REL" branch, "current" is mapped to finalized sdk version
-	if ctx.Config().PlatformSdkCodename() == "REL" && ver == "current" {
-		return ctx.Config().PlatformSdkVersionInt()
-	}
-	// Finalized codenames are OKAY and will be converted to int
-	intVer, err := android.ApiStrToNum(ctx, ver)
+	apiLevel, err := android.ApiLevelFromUser(ctx, ver)
 	if err != nil {
 		ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
+		return android.NoneApiLevel
 	}
-	return intVer
+	if apiLevel.IsPreview() {
+		// All codenames should build against "current".
+		return android.FutureApiLevel
+	}
+	return apiLevel
 }
 
 func (a *apexBundle) Updatable() bool {
@@ -2046,7 +2040,9 @@
 	if proptools.Bool(a.properties.Use_vendor) && ctx.DeviceConfig().VndkVersion() == "" {
 		return
 	}
-	android.CheckMinSdkVersion(a, ctx, a.minSdkVersion(ctx))
+	// apexBundle::minSdkVersion reports its own errors.
+	minSdkVersion := a.minSdkVersion(ctx)
+	android.CheckMinSdkVersion(a, ctx, minSdkVersion)
 }
 
 // Ensures that a lib providing stub isn't statically linked
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 5c49667..02689a0 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -207,7 +207,7 @@
 	config.TestProductVariables.CertificateOverrides = []string{"myapex_keytest:myapex.certificate.override"}
 	config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("Q")
 	config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(false)
-	config.TestProductVariables.Platform_version_active_codenames = []string{"R"}
+	config.TestProductVariables.Platform_version_active_codenames = []string{"Q"}
 	config.TestProductVariables.Platform_vndk_version = proptools.StringPtr("VER")
 
 	for _, handler := range handlers {
@@ -1425,13 +1425,7 @@
 		ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
 		ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
 	}
-	// 9000 is quite a magic number.
-	// Finalized SDK codenames are mapped as P(28), Q(29), ...
-	// And, codenames which are not finalized yet(active_codenames + future_codenames) are numbered from 9000, 9001, ...
-	// to distinguish them from finalized and future_api(10000)
-	// In this test, "R" is assumed not finalized yet( listed in Platform_version_active_codenames) and translated into 9000
-	// (refer android/api_levels.go)
-	expectLink("libx", "shared_apex10000", "libz", "shared_9000")
+	expectLink("libx", "shared_apex10000", "libz", "shared_R")
 	expectNoLink("libx", "shared_apex10000", "libz", "shared_29")
 	expectNoLink("libx", "shared_apex10000", "libz", "shared")
 }
@@ -6130,7 +6124,7 @@
 			name: "mylib",
 			srcs: ["mylib.cpp"],
 			stubs: {
-				versions: ["10000"],
+				versions: ["current"],
 			},
 			apex_available: ["myapex"],
 		}
@@ -6140,7 +6134,7 @@
 			prefer: false,
 			srcs: ["prebuilt.so"],
 			stubs: {
-				versions: ["10000"],
+				versions: ["current"],
 			},
 			apex_available: ["myapex"],
 		}
diff --git a/apex/builder.go b/apex/builder.go
index c5680ad..b0f0c82 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -21,7 +21,6 @@
 	"path/filepath"
 	"runtime"
 	"sort"
-	"strconv"
 	"strings"
 
 	"android/soong/android"
@@ -214,7 +213,8 @@
 		},
 	})
 
-	if a.minSdkVersion(ctx) == android.SdkVersion_Android10 {
+	minSdkVersion := a.minSdkVersion(ctx)
+	if minSdkVersion.EqualTo(android.SdkVersion_Android10) {
 		// b/143654022 Q apexd can't understand newly added keys in apex_manifest.json
 		// prepare stripped-down version so that APEX modules built from R+ can be installed to Q
 		a.manifestJsonOut = android.PathForModuleOut(ctx, "apex_manifest.json")
@@ -426,7 +426,8 @@
 	var emitCommands []string
 	imageContentFile := android.PathForModuleOut(ctx, "content.txt")
 	emitCommands = append(emitCommands, "echo ./apex_manifest.pb >> "+imageContentFile.String())
-	if a.minSdkVersion(ctx) == android.SdkVersion_Android10 {
+	minSdkVersion := a.minSdkVersion(ctx)
+	if minSdkVersion.EqualTo(android.SdkVersion_Android10) {
 		emitCommands = append(emitCommands, "echo ./apex_manifest.json >> "+imageContentFile.String())
 	}
 	for _, fi := range a.filesInfo {
@@ -532,12 +533,13 @@
 			optFlags = append(optFlags, "--android_manifest "+androidManifestFile.String())
 		}
 
-		targetSdkVersion := ctx.Config().DefaultAppTargetSdk()
+		targetSdkVersion := ctx.Config().DefaultAppTargetSdk(ctx).String()
 		// TODO(b/157078772): propagate min_sdk_version to apexer.
-		minSdkVersion := ctx.Config().DefaultAppTargetSdk()
+		minSdkVersion := ctx.Config().DefaultAppTargetSdk(ctx).String()
 
-		if a.minSdkVersion(ctx) == android.SdkVersion_Android10 {
-			minSdkVersion = strconv.Itoa(a.minSdkVersion(ctx))
+		moduleMinSdkVersion := a.minSdkVersion(ctx)
+		if moduleMinSdkVersion.EqualTo(android.SdkVersion_Android10) {
+			minSdkVersion = moduleMinSdkVersion.String()
 		}
 
 		if java.UseApiFingerprint(ctx) {
@@ -566,7 +568,7 @@
 			ctx.PropertyErrorf("test_only_no_hashtree", "not available")
 			return
 		}
-		if a.minSdkVersion(ctx) > android.SdkVersion_Android10 || a.testOnlyShouldSkipHashtreeGeneration() {
+		if moduleMinSdkVersion.GreaterThan(android.SdkVersion_Android10) || a.testOnlyShouldSkipHashtreeGeneration() {
 			// Apexes which are supposed to be installed in builtin dirs(/system, etc)
 			// don't need hashtree for activation. Therefore, by removing hashtree from
 			// apex bundle (filesystem image in it, to be specific), we can save storage.
@@ -583,7 +585,7 @@
 			optFlags = append(optFlags, "--do_not_check_keyname")
 		}
 
-		if a.minSdkVersion(ctx) == android.SdkVersion_Android10 {
+		if moduleMinSdkVersion == android.SdkVersion_Android10 {
 			implicitInputs = append(implicitInputs, a.manifestJsonOut)
 			optFlags = append(optFlags, "--manifest_json "+a.manifestJsonOut.String())
 		}
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 37457e9..9f6c8ad 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -326,7 +326,7 @@
 			Args: map[string]string{
 				"abis":              strings.Join(java.SupportedAbis(ctx), ","),
 				"allow-prereleased": strconv.FormatBool(proptools.Bool(a.properties.Prerelease)),
-				"sdk-version":       ctx.Config().PlatformSdkVersion(),
+				"sdk-version":       ctx.Config().PlatformSdkVersion().String(),
 			},
 		})
 
diff --git a/apex/vndk.go b/apex/vndk.go
index 5cc0e2a..93265c4 100644
--- a/apex/vndk.go
+++ b/apex/vndk.go
@@ -16,7 +16,6 @@
 
 import (
 	"path/filepath"
-	"strconv"
 	"strings"
 	"sync"
 
@@ -124,10 +123,10 @@
 	// Since prebuilt vndk libs still depend on system/lib/vndk path
 	if strings.HasPrefix(name, vndkApexNamePrefix) {
 		vndkVersion := strings.TrimPrefix(name, vndkApexNamePrefix)
-		if numVer, err := strconv.Atoi(vndkVersion); err != nil {
+		if ver, err := android.ApiLevelFromUser(ctx, vndkVersion); err != nil {
 			ctx.ModuleErrorf("apex_vndk should be named as %v<ver:number>: %s", vndkApexNamePrefix, name)
 			return
-		} else if numVer > android.SdkVersion_Android10 {
+		} else if ver.GreaterThan(android.SdkVersion_Android10) {
 			return
 		}
 		// the name of vndk apex is formatted "com.android.vndk.v" + version
diff --git a/cc/cc.go b/cc/cc.go
index 6584380..e71f859 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -354,7 +354,7 @@
 	useClangLld(actx ModuleContext) bool
 	isForPlatform() bool
 	apexVariationName() string
-	apexSdkVersion() int
+	apexSdkVersion() android.ApiLevel
 	hasStubsVariants() bool
 	isStubs() bool
 	bootstrap() bool
@@ -615,7 +615,7 @@
 	kytheFiles android.Paths
 
 	// For apex variants, this is set as apex.min_sdk_version
-	apexSdkVersion int
+	apexSdkVersion android.ApiLevel
 }
 
 func (c *Module) Toc() android.OptionalPath {
@@ -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)
@@ -1328,7 +1328,7 @@
 	return ctx.mod.ApexVariationName()
 }
 
-func (ctx *moduleContextImpl) apexSdkVersion() int {
+func (ctx *moduleContextImpl) apexSdkVersion() android.ApiLevel {
 	return ctx.mod.apexSdkVersion
 }
 
@@ -2317,7 +2317,7 @@
 	// For the dependency from platform to apex, use the latest stubs
 	c.apexSdkVersion = android.FutureApiLevel
 	if !c.IsForPlatform() {
-		c.apexSdkVersion = c.ApexProperties.Info.MinSdkVersion
+		c.apexSdkVersion = c.ApexProperties.Info.MinSdkVersion(ctx)
 	}
 
 	if android.InList("hwaddress", ctx.Config().SanitizeDevice()) {
@@ -2421,7 +2421,7 @@
 
 		if libDepTag, ok := depTag.(libraryDependencyTag); ok {
 			// Only use static unwinder for legacy (min_sdk_version = 29) apexes (b/144430859)
-			if libDepTag.staticUnwinder && c.apexSdkVersion > android.SdkVersion_Android10 {
+			if libDepTag.staticUnwinder && c.apexSdkVersion.GreaterThan(android.SdkVersion_Android10) {
 				return
 			}
 
@@ -2465,7 +2465,7 @@
 
 				// when to use (unspecified) stubs, check min_sdk_version and choose the right one
 				if useThisDep && depIsStubs && !libDepTag.explicitlyVersioned {
-					versionToUse, err := c.ChooseSdkVersion(ccDep.StubsVersions(), c.apexSdkVersion)
+					versionToUse, err := c.ChooseSdkVersion(ccDep.StubsVersions(), c.apexSdkVersion.FinalOrFutureInt())
 					if err != nil {
 						ctx.OtherModuleErrorf(dep, err.Error())
 						return
@@ -2488,7 +2488,7 @@
 						// if this is for use_vendor apex && dep has stubsVersions
 						// apply the same rule of apex sdk enforcement to choose right version
 						var err error
-						versionToUse, err = c.ChooseSdkVersion(versions, c.apexSdkVersion)
+						versionToUse, err = c.ChooseSdkVersion(versions, c.apexSdkVersion.FinalOrFutureInt())
 						if err != nil {
 							ctx.OtherModuleErrorf(dep, err.Error())
 							return
@@ -3012,21 +3012,8 @@
 	return true
 }
 
-// b/154667674: refactor this to handle "current" in a consistent way
-func decodeSdkVersionString(ctx android.BaseModuleContext, versionString string) (int, error) {
-	if versionString == "" {
-		return 0, fmt.Errorf("not specified")
-	}
-	if versionString == "current" {
-		if ctx.Config().PlatformSdkCodename() == "REL" {
-			return ctx.Config().PlatformSdkVersionInt(), nil
-		}
-		return android.FutureApiLevel, nil
-	}
-	return android.ApiStrToNum(ctx, versionString)
-}
-
-func (c *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+func (c *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
+	sdkVersion android.ApiLevel) error {
 	// We ignore libclang_rt.* prebuilt libs since they declare sdk_version: 14(b/121358700)
 	if strings.HasPrefix(ctx.OtherModuleName(c), "libclang_rt") {
 		return nil
@@ -3050,11 +3037,17 @@
 		// non-SDK variant resets sdk_version, which works too.
 		minSdkVersion = c.SdkVersion()
 	}
-	ver, err := decodeSdkVersionString(ctx, minSdkVersion)
+	if minSdkVersion == "" {
+		return fmt.Errorf("neither min_sdk_version nor sdk_version specificed")
+	}
+	// Not using nativeApiLevelFromUser because the context here is not
+	// necessarily a native context.
+	ver, err := android.ApiLevelFromUser(ctx, minSdkVersion)
 	if err != nil {
 		return err
 	}
-	if ver > sdkVersion {
+
+	if ver.GreaterThan(sdkVersion) {
 		return fmt.Errorf("newer SDK(%v)", ver)
 	}
 	return nil
diff --git a/cc/compiler.go b/cc/compiler.go
index f745820..bb5c7bf 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -354,7 +354,9 @@
 			flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX_NAME__='\""+ctx.apexVariationName()+"\"'")
 		}
 		if ctx.Device() {
-			flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_SDK_VERSION__="+strconv.Itoa(ctx.apexSdkVersion()))
+			flags.Global.CommonFlags = append(flags.Global.CommonFlags,
+				fmt.Sprintf("-D__ANDROID_SDK_VERSION__=%d",
+					ctx.apexSdkVersion().FinalOrFutureInt()))
 		}
 	}
 
@@ -390,7 +392,7 @@
 	if ctx.Os().Class == android.Device {
 		version := ctx.sdkVersion()
 		if version == "" || version == "current" {
-			target += strconv.Itoa(android.FutureApiLevel)
+			target += strconv.Itoa(android.FutureApiLevelInt)
 		} else {
 			target += version
 		}
diff --git a/cc/library.go b/cc/library.go
index 7b09b11..8048f00 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -19,8 +19,6 @@
 	"io"
 	"path/filepath"
 	"regexp"
-	"sort"
-	"strconv"
 	"strings"
 	"sync"
 
@@ -1520,20 +1518,18 @@
 }
 
 func normalizeVersions(ctx android.BaseModuleContext, versions []string) {
-	numVersions := make([]int, len(versions))
+	var previous android.ApiLevel
 	for i, v := range versions {
-		numVer, err := android.ApiStrToNum(ctx, v)
+		ver, err := android.ApiLevelFromUser(ctx, v)
 		if err != nil {
 			ctx.PropertyErrorf("versions", "%s", err.Error())
 			return
 		}
-		numVersions[i] = numVer
-	}
-	if !sort.IsSorted(sort.IntSlice(numVersions)) {
-		ctx.PropertyErrorf("versions", "not sorted: %v", versions)
-	}
-	for i, v := range numVersions {
-		versions[i] = strconv.Itoa(v)
+		if i > 0 && ver.LessThanOrEqualTo(previous) {
+			ctx.PropertyErrorf("versions", "not sorted: %v", versions)
+		}
+		versions[i] = ver.String()
+		previous = ver
 	}
 }
 
diff --git a/cc/library_test.go b/cc/library_test.go
index cb16725..49838b4 100644
--- a/cc/library_test.go
+++ b/cc/library_test.go
@@ -195,7 +195,7 @@
 			name: "libfoo",
 			srcs: ["foo.c"],
 			stubs: {
-				versions: ["29", "R", "10000"],
+				versions: ["29", "R", "current"],
 			},
 		}
 	`
@@ -204,7 +204,7 @@
 	ctx := testCcWithConfig(t, config)
 
 	variants := ctx.ModuleVariantsForTests("libfoo")
-	for _, expectedVer := range []string{"29", "9000", "10000"} {
+	for _, expectedVer := range []string{"29", "R", "current"} {
 		expectedVariant := "android_arm_armv7-a-neon_shared_" + expectedVer
 		if !inList(expectedVariant, variants) {
 			t.Errorf("missing expected variant: %q", expectedVariant)
@@ -218,7 +218,7 @@
 			name: "libfoo",
 			srcs: ["foo.c"],
 			stubs: {
-				versions: ["29", "10000", "R"],
+				versions: ["29", "current", "R"],
 			},
 		}
 	`
@@ -233,10 +233,10 @@
 			name: "libfoo",
 			srcs: ["foo.c"],
 			stubs: {
-				versions: ["29", "10000", "X"],
+				versions: ["29", "current", "X"],
 			},
 		}
 	`
 
-	testCcError(t, `"libfoo" .*: versions: SDK version should be`, bp)
+	testCcError(t, `"libfoo" .*: versions: "X" could not be parsed as an integer and is not a recognized codename`, bp)
 }
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 4c6d98c..5682d1c 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -118,8 +118,8 @@
 			versionStrs = append(versionStrs, version.String())
 		}
 	}
-	versions = append(versions, android.CurrentApiLevel)
-	versionStrs = append(versionStrs, android.CurrentApiLevel.String())
+	versions = append(versions, android.FutureApiLevel)
+	versionStrs = append(versionStrs, android.FutureApiLevel.String())
 
 	modules := ctx.CreateVariations(versionStrs...)
 	for i, module := range modules {
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 1ee096e..9d1b016 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -16,6 +16,7 @@
 
 import (
 	"android/soong/android"
+	"path/filepath"
 )
 
 func init() {
@@ -360,13 +361,18 @@
 			sharedLibPaths = append(sharedLibPaths, deps.SharedLibs...)
 			sharedLibPaths = append(sharedLibPaths, deps.LateSharedLibs...)
 
+			var fromPath = in.String()
+			if !filepath.IsAbs(fromPath) {
+				fromPath = "$$PWD/" + fromPath
+			}
+
 			ctx.Build(pctx, android.BuildParams{
 				Rule:      android.Symlink,
 				Output:    outputFile,
 				Input:     in,
 				Implicits: sharedLibPaths,
 				Args: map[string]string{
-					"fromPath": "$$PWD/" + in.String(),
+					"fromPath": fromPath,
 				},
 			})
 
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 1cec289..4a2f810 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -555,7 +555,8 @@
 	}
 }
 
-func (g *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+func (g *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
+	sdkVersion android.ApiLevel) error {
 	// Because generated outputs are checked by client modules(e.g. cc_library, ...)
 	// we can safely ignore the check here.
 	return nil
diff --git a/java/aar.go b/java/aar.go
index 667dd9d..9cab0bd 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -189,7 +189,7 @@
 
 	// Version code
 	if !hasVersionCode {
-		linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion())
+		linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion().String())
 	}
 
 	if !hasVersionName {
@@ -774,7 +774,8 @@
 	return a.depIsInSameApex(ctx, dep)
 }
 
-func (g *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+func (g *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
+	sdkVersion android.ApiLevel) error {
 	return nil
 }
 
diff --git a/java/app.go b/java/app.go
index ae7373f..13d08b9 100755
--- a/java/app.go
+++ b/java/app.go
@@ -157,7 +157,7 @@
 				"abis":              strings.Join(SupportedAbis(ctx), ","),
 				"allow-prereleased": strconv.FormatBool(proptools.Bool(as.properties.Prerelease)),
 				"screen-densities":  screenDensities,
-				"sdk-version":       ctx.Config().PlatformSdkVersion(),
+				"sdk-version":       ctx.Config().PlatformSdkVersion().String(),
 				"stem":              as.BaseModuleName(),
 				"apkcerts":          as.apkcertsFile.String(),
 				"partition":         as.PartitionTag(ctx.DeviceConfig()),
@@ -436,7 +436,7 @@
 
 		if minSdkVersion, err := a.minSdkVersion().effectiveVersion(ctx); err == nil {
 			a.checkJniLibsSdkVersion(ctx, minSdkVersion)
-			android.CheckMinSdkVersion(a, ctx, int(minSdkVersion))
+			android.CheckMinSdkVersion(a, ctx, minSdkVersion.ApiLevel(ctx))
 		} else {
 			ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
 		}
@@ -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
 		}
 
@@ -1637,7 +1637,8 @@
 	return sdkSpecFrom("")
 }
 
-func (j *AndroidAppImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+func (j *AndroidAppImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
+	sdkVersion android.ApiLevel) error {
 	// Do not check for prebuilts against the min_sdk_version of enclosing APEX
 	return nil
 }
diff --git a/java/app_test.go b/java/app_test.go
index 5367971..4347db8 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1078,6 +1078,7 @@
 		platformSdkFinal      bool
 		expectedMinSdkVersion string
 		platformApis          bool
+		activeCodenames       []string
 	}{
 		{
 			name:                  "current final SDK",
@@ -1094,6 +1095,7 @@
 			platformSdkCodename:   "OMR1",
 			platformSdkFinal:      false,
 			expectedMinSdkVersion: "OMR1",
+			activeCodenames:       []string{"OMR1"},
 		},
 		{
 			name:                  "default final SDK",
@@ -1112,11 +1114,14 @@
 			platformSdkCodename:   "OMR1",
 			platformSdkFinal:      false,
 			expectedMinSdkVersion: "OMR1",
+			activeCodenames:       []string{"OMR1"},
 		},
 		{
 			name:                  "14",
 			sdkVersion:            "14",
 			expectedMinSdkVersion: "14",
+			platformSdkCodename:   "S",
+			activeCodenames:       []string{"S"},
 		},
 	}
 
@@ -1137,6 +1142,7 @@
 				config := testAppConfig(nil, bp, nil)
 				config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt
 				config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename
+				config.TestProductVariables.Platform_version_active_codenames = test.activeCodenames
 				config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal
 				checkSdkVersion(t, config, test.expectedMinSdkVersion)
 
@@ -1179,15 +1185,6 @@
 			platformSdkInt:                        29,
 			platformSdkCodename:                   "Q",
 			platformSdkFinal:                      false,
-			deviceCurrentApiLevelForVendorModules: "current",
-			expectedMinSdkVersion:                 "Q",
-		},
-		{
-			name:                                  "current final SDK",
-			sdkVersion:                            "current",
-			platformSdkInt:                        29,
-			platformSdkCodename:                   "Q",
-			platformSdkFinal:                      false,
 			deviceCurrentApiLevelForVendorModules: "28",
 			expectedMinSdkVersion:                 "28",
 		},
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 85a61dd..55bc041 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1228,7 +1228,7 @@
 
 	cmd.FlagWithOutput("--generate-api-levels ", d.apiVersionsXml)
 	cmd.FlagWithInput("--apply-api-levels ", d.apiVersionsXml)
-	cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion())
+	cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
 	cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
 
 	filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
diff --git a/java/java.go b/java/java.go
index d67e9e0..1d7eaa7 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1658,7 +1658,7 @@
 			if v := sdkSpec.version; v.isNumbered() {
 				return v.String()
 			} else {
-				return ctx.Config().DefaultAppTargetSdk()
+				return ctx.Config().DefaultAppTargetSdk(ctx).String()
 			}
 		}
 
@@ -1876,7 +1876,8 @@
 	return j.depIsInSameApex(ctx, dep)
 }
 
-func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
+	sdkVersion android.ApiLevel) error {
 	sdkSpec := j.minSdkVersion()
 	if !sdkSpec.specified() {
 		return fmt.Errorf("min_sdk_version is not specified")
@@ -1888,7 +1889,7 @@
 	if err != nil {
 		return err
 	}
-	if int(ver) > sdkVersion {
+	if ver.ApiLevel(ctx).GreaterThan(sdkVersion) {
 		return fmt.Errorf("newer SDK(%v)", ver)
 	}
 	return nil
@@ -2753,7 +2754,8 @@
 	return j.depIsInSameApex(ctx, dep)
 }
 
-func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
+	sdkVersion android.ApiLevel) error {
 	// Do not check for prebuilts against the min_sdk_version of enclosing APEX
 	return nil
 }
@@ -2936,7 +2938,8 @@
 	return j.dexJarFile
 }
 
-func (j *DexImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+func (j *DexImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
+	sdkVersion android.ApiLevel) error {
 	// we don't check prebuilt modules for sdk_version
 	return nil
 }
diff --git a/java/sdk.go b/java/sdk.go
index 56fa12b..f599265 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -107,7 +107,7 @@
 
 const (
 	// special version number for a not-yet-frozen SDK
-	sdkVersionCurrent sdkVersion = sdkVersion(android.FutureApiLevel)
+	sdkVersionCurrent sdkVersion = sdkVersion(android.FutureApiLevelInt)
 	// special version number to be used for SDK specs where version number doesn't
 	// make sense, e.g. "none", "", etc.
 	sdkVersionNone sdkVersion = sdkVersion(0)
@@ -133,6 +133,10 @@
 	return "(no version)"
 }
 
+func (v sdkVersion) ApiLevel(ctx android.EarlyModuleContext) android.ApiLevel {
+	return android.ApiLevelOrPanic(ctx, v.String())
+}
+
 // asNumberString directly converts the numeric value of this sdk version as a string.
 // When isNumbered() is true, this method is the same as String(). However, for sdkVersionCurrent
 // and sdkVersionNone, this returns 10000 and 0 while String() returns "current" and "(no version"),
@@ -243,7 +247,7 @@
 	if s.version.isNumbered() {
 		return s.version, nil
 	}
-	return sdkVersion(ctx.Config().DefaultAppTargetSdkInt()), nil
+	return sdkVersion(ctx.Config().DefaultAppTargetSdk(ctx).FinalOrFutureInt()), nil
 }
 
 // effectiveVersionString converts an sdkSpec into the concrete version string that the module
@@ -251,8 +255,8 @@
 // it returns the codename (P, Q, R, etc.)
 func (s sdkSpec) effectiveVersionString(ctx android.EarlyModuleContext) (string, error) {
 	ver, err := s.effectiveVersion(ctx)
-	if err == nil && int(ver) == ctx.Config().DefaultAppTargetSdkInt() {
-		return ctx.Config().DefaultAppTargetSdk(), nil
+	if err == nil && int(ver) == ctx.Config().DefaultAppTargetSdk(ctx).FinalOrFutureInt() {
+		return ctx.Config().DefaultAppTargetSdk(ctx).String(), nil
 	}
 	return ver.String(), err
 }
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 1a5ef54..a7b92b3 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1878,7 +1878,8 @@
 	return false
 }
 
-func (module *SdkLibraryImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+func (module *SdkLibraryImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
+	sdkVersion android.ApiLevel) error {
 	// we don't check prebuilt modules for sdk_version
 	return nil
 }
@@ -2078,7 +2079,8 @@
 	// do nothing
 }
 
-func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
+	sdkVersion android.ApiLevel) error {
 	// sdkLibraryXml doesn't need to be checked separately because java_sdk_library is checked
 	return nil
 }
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/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/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/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 768c8e5..480f9b7 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -310,7 +310,8 @@
 		}}
 }
 
-func (m *syspropLibrary) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+func (m *syspropLibrary) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
+	sdkVersion android.ApiLevel) error {
 	return fmt.Errorf("sysprop_library is not supposed to be part of apex modules")
 }